From b2a07a3bf33510db4fcbccb21ce311c12bd96bba Mon Sep 17 00:00:00 2001 From: Jason Wilder Date: Wed, 22 Apr 2015 23:50:29 -0600 Subject: [PATCH] Fix error calling MarshalJSON for type *influxdb.Result: json: unsupported value: NaN If the MapMean did not have any values in the iterator, it would return and empty meanMapOutput(). ReduceMean would in turn divider the results by an unitialized float64 producing a NaN. NaN is not serializable to JSON by default. --- influxql/functions.go | 7 +++- influxql/functions_test.go | 67 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 influxql/functions_test.go diff --git a/influxql/functions.go b/influxql/functions.go index 3ae5caba327..eff918534ee 100644 --- a/influxql/functions.go +++ b/influxql/functions.go @@ -213,7 +213,12 @@ func MapMean(itr Iterator) interface{} { out.Count++ out.Mean += (v.(float64) - out.Mean) / float64(out.Count) } - return out + + if out.Count > 0 { + return out + } + + return nil } type meanMapOutput struct { diff --git a/influxql/functions_test.go b/influxql/functions_test.go new file mode 100644 index 00000000000..2dfaa11ffe9 --- /dev/null +++ b/influxql/functions_test.go @@ -0,0 +1,67 @@ +package influxql + +import "testing" + +type point struct { + seriesID uint64 + timestamp int64 + value interface{} +} + +type testIterator struct { + values []point +} + +func (t *testIterator) Next() (seriesID uint64, timestamp int64, value interface{}) { + if len(t.values) > 0 { + v := t.values[0] + t.values = t.values[1:] + return v.seriesID, v.timestamp, v.value + } + return 0, 0, nil +} + +func TestMapMeanNoValues(t *testing.T) { + iter := &testIterator{} + if got := MapMean(iter); got != nil { + t.Errorf("output mismatch: exp nil got %v", got) + } +} + +func TestMapMean(t *testing.T) { + + tests := []struct { + input []point + output *meanMapOutput + }{ + { // Single point + input: []point{ + point{0, 1, 1.0}, + }, + output: &meanMapOutput{1, 1}, + }, + { // Two points + input: []point{ + point{0, 1, 2.0}, + point{0, 2, 8.0}, + }, + output: &meanMapOutput{2, 5.0}, + }, + } + + for _, test := range tests { + iter := &testIterator{ + values: test.input, + } + + got := MapMean(iter) + if got == nil { + t.Fatalf("MapMean(%v): output mismatch: exp %v got %v", test.input, test.output, got) + } + + if got.(*meanMapOutput).Count != test.output.Count || got.(*meanMapOutput).Mean != test.output.Mean { + t.Errorf("output mismatch: exp %v got %v", test.output, got) + } + + } +}