diff options
| -rw-r--r-- | lgc/lgc.go | 18 | ||||
| -rw-r--r-- | rpm/rpm.go | 31 | ||||
| -rw-r--r-- | traceable/traceable_test.go | 153 |
3 files changed, 180 insertions, 22 deletions
@@ -279,14 +279,7 @@ func (lgd *LoadGeneratingConnectionDownload) Start( ) } - // Later, when the doDownload function attempts to add a tracer to the http request, - // it will be associated with the context. Multiple tracers associated with the same - // context will make it impossible to disambiguate the events. In other words, if there - // are multiple tracers associated with the same context, *all* the tracers get invoked - // every time that an event happens on a request with any of them! So, we will make a - // unique context so that there is a one-to-one correspondence between tracers and requests. - downloadCtx, _ := context.WithCancel(parentCtx) - go lgd.doDownload(downloadCtx) + go lgd.doDownload(parentCtx) return true } @@ -432,14 +425,7 @@ func (lgu *LoadGeneratingConnectionUpload) Start( fmt.Printf("Started a load-generating upload (id: %v).\n", lgu.clientId) } - // Later, when the doUpload function attempts to add a tracer to the http request, - // it will be associated with the context. Multiple tracers associated with the same - // context will make it impossible to disambiguate the events. In other words, if there - // are multiple tracers associated with the same context, *all* the tracers get invoked - // every time that an event happens on a request with any of them! So, we will make a - // unique context so that there is a one-to-one correspondence between tracers and requests. - uploadCtx, _ := context.WithCancel(parentCtx) - go lgu.doUpload(uploadCtx) + go lgu.doUpload(parentCtx) return true } @@ -53,12 +53,17 @@ type LGDataCollectionResult struct { DataPoints []DataPoint } -func LGProbe(parentProbeCtx context.Context, connection lgc.LoadGeneratingConnection, lgProbeUrl string, result *chan DataPoint, debugging *debug.DebugWithPrefix) error { - probeCtx, _ := context.WithCancel(parentProbeCtx) +func LGProbe( + parentProbeCtx context.Context, + connection lgc.LoadGeneratingConnection, + lgProbeUrl string, + result *chan DataPoint, + debugging *debug.DebugWithPrefix, +) error { probeTracer := NewProbeTracer(connection.Client(), true, debugging) time_before_probe := time.Now() probe_req, err := http.NewRequestWithContext( - httptrace.WithClientTrace(probeCtx, probeTracer.trace), + httptrace.WithClientTrace(parentProbeCtx, probeTracer.trace), "GET", lgProbeUrl, nil, @@ -109,9 +114,16 @@ func LGProbe(parentProbeCtx context.Context, connection lgc.LoadGeneratingConnec *result <- DataPoint{RoundTripCount: 1, Duration: totalDelay} return nil - ///////////// } -func LGProber(proberCtx context.Context, defaultConnection lgc.LoadGeneratingConnection, altConnections *[]lgc.LoadGeneratingConnection, url string, interval time.Duration, debugging *debug.DebugWithPrefix) (points chan DataPoint) { + +func LGProber( + proberCtx context.Context, + defaultConnection lgc.LoadGeneratingConnection, + altConnections *[]lgc.LoadGeneratingConnection, + url string, + interval time.Duration, + debugging *debug.DebugWithPrefix, +) (points chan DataPoint) { points = make(chan DataPoint) go func() { @@ -149,7 +161,14 @@ func LGCollectData( lgProbeConfiguration := lgProbeConfigurationGenerator() - LGProber(lgDataCollectionCtx, lgcs[0], &lgcs, lgProbeConfiguration.URL, time.Duration(100*time.Millisecond), debugging) + LGProber( + lgDataCollectionCtx, + lgcs[0], + &lgcs, + lgProbeConfiguration.URL, + time.Duration(100*time.Millisecond), + debugging, + ) previousFlowIncreaseInterval := uint64(0) previousMovingAverage := float64(0) diff --git a/traceable/traceable_test.go b/traceable/traceable_test.go new file mode 100644 index 0000000..e0fcb04 --- /dev/null +++ b/traceable/traceable_test.go @@ -0,0 +1,153 @@ +package traceable + +import ( + "context" + "crypto/tls" + "io" + "io/ioutil" + "net/http" + "net/http/httptrace" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/network-quality/goresponsiveness/debug" +) + +type CountingTraceable struct { + Counter *uint64 +} + +func (lgd *CountingTraceable) SetDnsStartTimeInfo( + now time.Time, + dnsStartInfo httptrace.DNSStartInfo, +) { + +} + +func (lgd *CountingTraceable) SetDnsDoneTimeInfo( + now time.Time, + dnsDoneInfo httptrace.DNSDoneInfo, +) { + +} + +func (lgd *CountingTraceable) SetConnectStartTime( + now time.Time, +) { + +} + +func (lgd *CountingTraceable) SetConnectDoneTimeError( + now time.Time, + err error, +) { + +} + +func (lgd *CountingTraceable) SetGetConnTime(now time.Time) { +} + +func (lgd *CountingTraceable) SetGotConnTimeInfo( + now time.Time, + gotConnInfo httptrace.GotConnInfo, +) { + atomic.AddUint64(lgd.Counter, 1) +} + +func (lgd *CountingTraceable) SetTLSHandshakeStartTime( + now time.Time, +) { +} + +func (lgd *CountingTraceable) SetTLSHandshakeDoneTimeState( + now time.Time, + connectionState tls.ConnectionState, +) { +} + +func (lgd *CountingTraceable) SetHttpWroteRequestTimeInfo( + now time.Time, + info httptrace.WroteRequestInfo, +) { +} + +func (lgd *CountingTraceable) SetHttpResponseReadyTime( + now time.Time, +) { +} + +// Ensure that two different http client request tracers started with the same context +// do not compose and receive each other's callbacks. +func TestDuplicativeTraceables(t *testing.T) { + + singleCtx, singleCtxCancel_ := context.WithCancel(context.Background()) + defer singleCtxCancel_() + + client := http.Client{} + + counterA := new(uint64) + countingTracerA := CountingTraceable{Counter: counterA} + counterB := new(uint64) + countingTracerB := CountingTraceable{Counter: counterB} + + debugging := debug.NewDebugWithPrefix(debug.Debug, "TestDuplicativeTraceables") + request_a, err := http.NewRequestWithContext( + httptrace.WithClientTrace( + singleCtx, + GenerateHttpTimingTracer(&countingTracerA, debugging.Level), + ), + "GET", + "https://www.google.com/", + nil, + ) + if err != nil { + t.Fatalf("Failed to create request A to GET google.com") + } + request_b, err := http.NewRequestWithContext( + httptrace.WithClientTrace( + singleCtx, + GenerateHttpTimingTracer(&countingTracerB, debugging.Level), + ), + "GET", + "https://www.google.com/", + nil, + ) + if err != nil { + t.Fatalf("Failed to create request B to GET google.com") + } + + requestWg := new(sync.WaitGroup) + + requestWg.Add(2) + go func() { + defer requestWg.Done() + get, err := client.Do(request_a) + if err != nil { + return + } + _, _ = io.Copy(ioutil.Discard, get.Body) + get.Body.Close() + }() + go func() { + defer requestWg.Done() + get, err := client.Do(request_b) + if err != nil { + return + } + _, _ = io.Copy(ioutil.Discard, get.Body) + get.Body.Close() + }() + + requestWg.Wait() + + if !(*counterA == 1 && *counterB == 1) { + t.Fatalf( + "Two separate tracers received overlapping callbacks on each other's http requests: (counterA: %d, counterB: %d)", + *counterA, + *counterB, + ) + } + +} |
