Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add square wave latency summand #17

Merged
merged 5 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ func parseArgs(args []string) (*lib.SpeedbumpCfg, error) {
sawPeriod = app.Flag("saw-period", "Period of the latency sawtooth wave.").
PlaceHolder("0").
Duration()
squareAmplitude = app.Flag("square-amplitude", "Amplitude of the latency square wave.").
PlaceHolder("0").
Duration()
suqarePeriod = app.Flag("square-period", "Period of the latency square wave.").
PlaceHolder("0").
Duration()
destAddr = app.Arg("destination", "TCP proxy destination in host:post format.").
Required().
String()
Expand All @@ -52,11 +58,13 @@ func parseArgs(args []string) (*lib.SpeedbumpCfg, error) {
BufferSize: int(*bufferSize),
QueueSize: *queueSize,
Latency: &lib.LatencyCfg{
Base: *latency,
SineAmplitude: *sineAmplitude,
SinePeriod: *sinePeriod,
SawAmplitute: *sawAmplitute,
SawPeriod: *sawPeriod,
Base: *latency,
SineAmplitude: *sineAmplitude,
SinePeriod: *sinePeriod,
SawAmplitute: *sawAmplitute,
SawPeriod: *sawPeriod,
SquareAmplitude:*squareAmplitude,
SquarePeriod: *suqarePeriod,
},
LogLevel: *logLevel,
}
Expand Down
4 changes: 4 additions & 0 deletions args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ func TestParseArgsAll(t *testing.T) {
"--latency=100ms",
"--sine-amplitude=50ms",
"--sine-period=1m",
"--square-amplitude=123ms",
"--square-period=3m",
"host:777",
},
)
Expand All @@ -42,4 +44,6 @@ func TestParseArgsAll(t *testing.T) {
assert.Equal(t, time.Minute, cfg.Latency.SinePeriod)
assert.Equal(t, time.Duration(0), cfg.Latency.SawAmplitute)
assert.Equal(t, time.Duration(0), cfg.Latency.SawPeriod)
assert.Equal(t, time.Millisecond*123, cfg.Latency.SquareAmplitude)
assert.Equal(t, time.Minute*3, cfg.Latency.SquarePeriod)
}
18 changes: 13 additions & 5 deletions lib/latency_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ type LatencyGenerator interface {
}

type LatencyCfg struct {
Base time.Duration
SineAmplitude time.Duration
SinePeriod time.Duration
SawAmplitute time.Duration
SawPeriod time.Duration
Base time.Duration
SineAmplitude time.Duration
SinePeriod time.Duration
SawAmplitute time.Duration
SawPeriod time.Duration
SquareAmplitude time.Duration
SquarePeriod time.Duration
}

type latencySummand interface {
Expand All @@ -39,6 +41,12 @@ func newSimpleLatencyGenerator(start time.Time, cfg *LatencyCfg) simpleLatencyGe
cfg.SawPeriod,
})
}
if cfg.SquareAmplitude > 0 && cfg.SquarePeriod > 0 {
summands = append(summands, squareLatencySummand{
cfg.SquareAmplitude,
cfg.SquarePeriod,
})
}
return simpleLatencyGenerator{
start: start,
summands: summands,
Expand Down
15 changes: 14 additions & 1 deletion lib/speedbump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,20 @@ func TestSpeedbumpWithEchoServer(t *testing.T) {
assert.Nil(t, err)

tcpAddr, _ := net.ResolveTCPAddr("tcp", "localhost:8000")
conn, _ := net.DialTCP("tcp", nil, tcpAddr)

var conn *net.TCPConn

// Wait for the speedbump instance to start listening
// since it is started in a separate goroutine, we don't know
// if it has already started listening by this point
for {
conn, err = net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
time.Sleep(10 * time.Millisecond)
} else {
break
}
}
Comment on lines +144 to +156
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test bug was causing the CI pipeline to fail every once in a while. Thanks for fixing it.

On a side note, it shows that the public API could be a bit more intuitive (i.e. Start() that returns immediately after the proxy starts listening). Such changes will likely be introduced in v1 due to their breaking nature.


firstOpStart := time.Now()

Expand Down
17 changes: 17 additions & 0 deletions lib/square.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package lib

import (
"math"
"time"
)

type squareLatencySummand struct {
amplitude time.Duration
period time.Duration
}

func (s squareLatencySummand) getLatency(elapsed time.Duration) time.Duration {
return time.Duration(
(2 * (2 * math.Floor((1 / float64 (s.period)) * float64(elapsed)) - math.Floor(2 * (1 / float64 (s.period)) * float64(elapsed))) + 1) * float64(s.amplitude),
)
kffl marked this conversation as resolved.
Show resolved Hide resolved
}
23 changes: 23 additions & 0 deletions lib/square_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package lib

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestSquareLatencySummand(t *testing.T) {
s := squareLatencySummand{
amplitude: time.Second * 2,
period: time.Minute,
}

assert.Equal(t, s.getLatency(time.Duration(0)), time.Second * 2)
assert.Equal(t, s.getLatency(time.Second * 15), time.Second * 2)
assert.Equal(t, s.getLatency(time.Second * 30), time.Second * -2)
assert.Equal(t, s.getLatency(time.Second * 45), time.Second * -2)
assert.Equal(t, s.getLatency(time.Second * 60), time.Second * 2)
assert.Equal(t, s.getLatency(time.Second * 84), time.Second * 2)
assert.Equal(t, s.getLatency(time.Second * 90), time.Second * -2)
}