diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | go.mod | 9 | ||||
| -rw-r--r-- | go.sum | 9 | ||||
| -rw-r--r-- | qualityattenuation/qualityattenuation.go | 8 | ||||
| -rw-r--r-- | qualityattenuation/qualityattenuation_test.go | 65 |
5 files changed, 87 insertions, 6 deletions
@@ -6,7 +6,7 @@ all: build test build: go build $(LDFLAGS) networkQuality.go test: - go test ./timeoutat/ ./traceable/ ./ms/ ./utilities/ ./lgc + go test ./timeoutat/ ./traceable/ ./ms/ ./utilities/ ./lgc ./qualityattenuation golines: find . -name '*.go' -exec ~/go/bin/golines -w {} \; clean: @@ -14,4 +14,11 @@ require ( require ( github.com/influxdata/tdigest v0.0.1 -)
\ No newline at end of file + github.com/stretchr/testify v1.8.3 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) @@ -1,6 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY= github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= @@ -13,3 +19,6 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/qualityattenuation/qualityattenuation.go b/qualityattenuation/qualityattenuation.go index 67143a7..9782925 100644 --- a/qualityattenuation/qualityattenuation.go +++ b/qualityattenuation/qualityattenuation.go @@ -70,12 +70,12 @@ func (qa *SimpleQualityAttenuation) GetPercentile(percentile float64) float64 { } func (qa *SimpleQualityAttenuation) GetAverage() float64 { - return qa.Offset_sum/float64(qa.Number_of_samples) + qa.Offset + return qa.Offset_sum/float64(qa.Number_of_samples-qa.Number_of_losses) + qa.Offset } func (qa *SimpleQualityAttenuation) GetVariance() float64 { number_of_latency_samples := float64(qa.Number_of_samples) - float64(qa.Number_of_losses) - return (qa.Offset_sum_of_squares - (qa.Offset_sum * qa.Offset_sum / number_of_latency_samples)) / (number_of_latency_samples - 1) + return (qa.Offset_sum_of_squares - (qa.Offset_sum * qa.Offset_sum / number_of_latency_samples)) / (number_of_latency_samples) } func (qa *SimpleQualityAttenuation) GetStandardDeviation() float64 { @@ -95,11 +95,11 @@ func (qa *SimpleQualityAttenuation) GetMedian() float64 { } func (qa *SimpleQualityAttenuation) GetLossPercentage() float64 { - return float64(qa.Number_of_losses) / float64(qa.Number_of_samples) + return 100 * float64(qa.Number_of_losses) / float64(qa.Number_of_samples) } func (qa *SimpleQualityAttenuation) GetRPM() float64 { - return 60 / qa.GetAverage() + return 60.0 / qa.GetAverage() } func (qa *SimpleQualityAttenuation) GetPDV(percentile float64) float64 { diff --git a/qualityattenuation/qualityattenuation_test.go b/qualityattenuation/qualityattenuation_test.go new file mode 100644 index 0000000..862dc28 --- /dev/null +++ b/qualityattenuation/qualityattenuation_test.go @@ -0,0 +1,65 @@ +package qualityattenuation + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBasicSimpleQualityAttenuation(t *testing.T) { + qa := NewSimpleQualityAttenuation() + qa.AddSample(1.0) + qa.AddSample(2.0) + qa.AddSample(3.0) + assert.Equal(t, qa.Number_of_samples, int64(3)) + assert.Equal(t, qa.Number_of_losses, int64(0)) + assert.InEpsilon(t, 1.0, qa.Minimum_latency, 0.000001) + assert.InEpsilon(t, 3.0, qa.Maximum_latency, 0.000001) + assert.InEpsilon(t, 5.7, qa.Offset_sum, 0.000001) + assert.InEpsilon(t, 12.83, qa.Offset_sum_of_squares, 0.000001) + assert.InEpsilon(t, 1.0, qa.EmpiricalDistribution.Quantile(0.1), 0.000001) + assert.InEpsilon(t, 2.0, qa.EmpiricalDistribution.Quantile(0.5), 0.000001) + assert.InEpsilon(t, 3.0, qa.EmpiricalDistribution.Quantile(0.9), 0.000001) + //Test the get functions + assert.Equal(t, qa.GetNumberOfSamples(), int64(3)) + assert.Equal(t, qa.GetNumberOfLosses(), int64(0)) + assert.InEpsilon(t, 1.0, qa.GetMinimum(), 0.000001) + assert.InEpsilon(t, 3.0, qa.GetMaximum(), 0.000001) + assert.InEpsilon(t, 2.0, qa.GetAverage(), 0.000001) + assert.InEpsilon(t, 1.0, qa.GetVariance(), 0.000001) + assert.InEpsilon(t, 1.0, qa.GetStandardDeviation(), 0.000001) + assert.InEpsilon(t, 2.0, qa.GetMedian(), 0.000001) + assert.InEpsilon(t, 1.0, qa.GetLossPercentage()+1.000000000, 0.000001) + assert.InEpsilon(t, 30, qa.GetRPM(), 0.000001) + assert.InEpsilon(t, 1.0, qa.GetPercentile(10.0), 0.000001) + assert.InEpsilon(t, 2.0, qa.GetPercentile(50.0), 0.000001) + assert.InEpsilon(t, 3.0, qa.GetPercentile(90.0), 0.000001) + assert.InEpsilon(t, 2.0, qa.GetPDV(90), 0.000001) +} + +func TestManySamples(t *testing.T) { + qa := NewSimpleQualityAttenuation() + for i := 1; i < 160000; i++ { + qa.AddSample(float64(i) / 10000.0) //Linear ramp from 0.0001 to 16.0 + } + assert.Equal(t, qa.Number_of_samples, int64(160000-1)) + assert.Equal(t, qa.Number_of_losses, int64(10000-1)) //Samples from 15.0001 to 16.0 are lost + assert.InEpsilon(t, 0.0001, qa.Minimum_latency, 0.000001) + assert.InEpsilon(t, 15.0000, qa.Maximum_latency, 0.000001) + assert.InEpsilon(t, 1110007.5, qa.Offset_sum, 0.000001) + assert.InEpsilon(t, 11026611.00024998, qa.Offset_sum_of_squares, 0.000001) + assert.InEpsilon(t, 1.50005, qa.EmpiricalDistribution.Quantile(0.1), 0.000001) + assert.InEpsilon(t, 7.500049, qa.EmpiricalDistribution.Quantile(0.5), 0.000001) + assert.InEpsilon(t, 13.50005, qa.EmpiricalDistribution.Quantile(0.9), 0.000001) + //Test the get functions + assert.Equal(t, qa.GetNumberOfSamples(), int64(160000-1)) + assert.Equal(t, qa.GetNumberOfLosses(), int64(10000-1)) + assert.InEpsilon(t, 0.0001, qa.GetMinimum(), 0.000001) + assert.InEpsilon(t, 15.0000, qa.GetMaximum(), 0.000001) + assert.InEpsilon(t, 7.500049, qa.GetAverage(), 0.000001) + assert.InEpsilon(t, 18.749750, qa.GetVariance(), 0.001) + assert.InEpsilon(t, 4.330098, qa.GetStandardDeviation(), 0.001) + assert.InEpsilon(t, 7.500049, qa.GetMedian(), 0.000001) + assert.InEpsilon(t, 6.249414, qa.GetLossPercentage(), 0.000001) + assert.InEpsilon(t, 7.999947, qa.GetRPM(), 0.000001) +} |
