// protobuf of latency summary info. func TestDataCompletenessSummary(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } r := wt.Request{ID: wt.L(), URL: "/data/completeness/summary", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var f mtrpb.DataCompletenessSummaryResult if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if len(f.Result) != 1 { t.Error("expected 1 result.") } d := f.Result[0] if d.SiteID != "TAUP" { t.Errorf("expected TAUP got %s", d.SiteID) } if d.TypeID != "completeness.gnss.1hz" { t.Errorf("expected gnss.1hz got %s", d.TypeID) } if d.Seconds == 0 { t.Error("unexpected zero seconds") } r.URL = "/data/completeness/summary?typeID=completeness.gnss.1hz" if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } f.Reset() if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if len(f.Result) != 1 { t.Errorf("expected 1 result got %d results", len(f.Result)) } }
func TestDataLatencyCsv(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } r := wt.Request{ User: userW, Password: keyW, Method: "PUT", } var err error type latencyTest struct { time time.Time mean, fifty, ninety float32 } utcNow := time.Now().UTC().Truncate(time.Second) t0 := utcNow.Add(time.Second * -10) latencyTestData := []latencyTest{ {time: t0, mean: 20, fifty: 30, ninety: 40}, // Can only have one value due to rate_limit. // TODO: make the rate_limit value configurable so we can test properly //{time: t0.Add(time.Second), mean: 21, fifty:31, ninety: 41}, //{time: t0.Add(time.Second * 2), mean: 22, fifty:32, ninety: 42}, //{time: t0.Add(time.Second * 3), mean: 23, fifty:33, ninety: 43}, } expectedVals := [][]string{ {""}, // header line, ignored in test. {latencyTestData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", latencyTestData[0].mean), fmt.Sprintf("%.2f", latencyTestData[0].fifty), fmt.Sprintf("%.2f", latencyTestData[0].ninety)}, //{latencyTestData[1].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", latencyTestData[1].mean), fmt.Sprintf("%.2f", latencyTestData[1].fifty), fmt.Sprintf("%.2f", latencyTestData[1].ninety)}, //{latencyTestData[2].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", latencyTestData[2].mean), fmt.Sprintf("%.2f", latencyTestData[2].fifty), fmt.Sprintf("%.2f", latencyTestData[2].ninety)}, //{latencyTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", latencyTestData[3].mean), fmt.Sprintf("%.2f", latencyTestData[3].fifty), fmt.Sprintf("%.2f", latencyTestData[3].ninety)}, } // Add metrics for _, lt := range latencyTestData { r.URL = fmt.Sprintf("/data/latency?siteID=TAUP&typeID=latency.strong&time=%s&mean=%d&fifty=%d&ninety=%d", lt.time.Format(time.RFC3339), int(lt.mean), int(lt.fifty), int(lt.ninety)) addData(r, t) } r = wt.Request{ID: wt.L(), URL: "/data/latency?siteID=TAUP&typeID=latency.strong&resolution=full", Method: "GET", Accept: "text/csv"} var b []byte if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedVals, t) // test for invalid siteID condition r = wt.Request{ID: wt.L(), URL: "/data/latency?siteID=NOT_THERE&typeID=latency.strong&resolution=full", Method: "GET", Accept: "text/csv", Status: http.StatusNotFound} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } // Test with a time range start := latencyTestData[0].time.Add(time.Second * -1).UTC().Format(time.RFC3339) end := latencyTestData[0].time.Add(time.Second).UTC().Format(time.RFC3339) r = wt.Request{ID: wt.L(), URL: "/data/latency?siteID=TAUP&typeID=latency.strong&resolution=full&startDate=" + start + "&endDate=" + end, Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedVals, t) }
func TestAppMetricCounterCsv(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } r := wt.Request{ User: userW, Password: keyW, Method: "PUT", } var err error type testPoint struct { typeID int count float64 time time.Time } // Testing the "counter" group utcNow := time.Now().UTC().Truncate(time.Second) t0 := utcNow.Add(time.Second * -10) testCounterData := []testPoint{ {typeID: http.StatusOK, count: 1.0, time: t0}, {typeID: http.StatusBadRequest, count: 2.0, time: t0}, // add a different typeID at the same time as previous typeID {typeID: http.StatusNotFound, count: 1.0, time: t0.Add(time.Second * 2)}, {typeID: http.StatusBadRequest, count: 2.0, time: t0.Add(time.Second * 4)}, {typeID: http.StatusInternalServerError, count: 3.0, time: t0.Add(time.Second * 6)}, } // the expected CSV data, ignoring the header fields on the first line expectedVals := [][]string{ {""}, // header line, ignored in test. Should be time, statusOK, statusBadRequest, StatusNotFound, StatusInternalServerError {testCounterData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", testCounterData[0].count), fmt.Sprintf("%.2f", testCounterData[1].count), "", ""}, {testCounterData[2].time.Format(DYGRAPH_TIME_FORMAT), "", "", fmt.Sprintf("%.2f", testCounterData[2].count), ""}, {testCounterData[3].time.Format(DYGRAPH_TIME_FORMAT), "", fmt.Sprintf("%.2f", testCounterData[3].count), "", ""}, {testCounterData[4].time.Format(DYGRAPH_TIME_FORMAT), "", "", "", fmt.Sprintf("%.2f", testCounterData[4].count)}, } for _, td := range testCounterData { r.URL = fmt.Sprintf("/application/counter?applicationID=test-app&instanceID=test-instance&typeID=%d&count=%d&time=%s", td.typeID, int(td.count), td.time.Format(time.RFC3339)) addData(r, t) } r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=counters&resolution=full", Method: "GET", Accept: "text/csv"} var b []byte if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedVals, t) // test with time range specified expectedSubset := [][]string{ {""}, // header line, ignored in test. Should be time, statusOK, statusBadRequest {testCounterData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", testCounterData[0].count), fmt.Sprintf("%.2f", testCounterData[1].count)}, } // time window so we only get the points at t0. RFC3339 has second precision. start := t0.Add(time.Second * -1).Format(time.RFC3339) end := t0.Add(time.Second).Format(time.RFC3339) r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=counters&resolution=full&startDate=" + start + "&endDate=" + end, Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedSubset, t) }
func TestAppMetricObjectsCsv(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } // Testing the "timers" group, could move to another testing function r := wt.Request{ User: userW, Password: keyW, Method: "PUT", } type objectTest struct { appId, instanceId string typeId int value float64 time time.Time } // handling objects and routines in the same test since it's the same method being exercised utcNow := time.Now().UTC().Truncate(time.Second) t0 := utcNow.Add(time.Second * -10) objTestData := []objectTest{ {appId: "test-app", instanceId: "test-instance", typeId: int(internal.MemHeapObjects), value: 8, time: t0.Add(time.Second)}, {appId: "test-app", instanceId: "test-instance", typeId: int(internal.MemHeapObjects), value: 12, time: t0.Add(time.Second * 2)}, {appId: "test-app", instanceId: "test-instance", typeId: int(internal.Routines), value: 1, time: t0.Add(time.Second * 3)}, {appId: "test-app", instanceId: "test-instance", typeId: int(internal.Routines), value: 3, time: t0.Add(time.Second * 6)}, {appId: "test-app", instanceId: "test-instance", typeId: int(internal.MemSys), value: 10, time: t0.Add(time.Second * 7)}, {appId: "test-app", instanceId: "test-instance", typeId: int(internal.MemHeapAlloc), value: 9, time: t0.Add(time.Second * 8)}, {appId: "test-app", instanceId: "test-instance", typeId: int(internal.MemHeapSys), value: 7, time: t0.Add(time.Second * 9)}, } // the expected CSV data, ignoring the header fields on the first line expectedObjValues := [][]string{ {""}, // header line, ignored in test. {objTestData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", objTestData[0].value)}, {objTestData[1].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", objTestData[1].value)}, } // Add timer values for _, ov := range objTestData { // /application/metric?applicationID=test-app&instanceID=test-instance&typeID=1000&value=10000&time=2015-05-14T21:40:30Z r.URL = fmt.Sprintf("/application/metric?applicationID=%s&instanceID=%s&typeID=%d&value=%d&time=%s", ov.appId, ov.instanceId, ov.typeId, int(ov.value), ov.time.Format(time.RFC3339)) addData(r, t) } r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=objects&resolution=full", Method: "GET", Accept: "text/csv"} var err error var b []byte if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedObjValues, t) // test again for number of goroutines expectedRoutineValues := [][]string{ {""}, // header line, ignored in test. {objTestData[2].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", objTestData[2].value)}, {objTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", objTestData[3].value)}, } r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=routines&resolution=full", Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedRoutineValues, t) // Also test for invalid applicationID, should give a 404 r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=NOT_AN_APP&group=routines&resolution=full", Method: "GET", Accept: "text/csv", Status: http.StatusNotFound} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } // Test again with time range start := objTestData[3].time.Add(time.Second * -1).UTC().Format(time.RFC3339) end := objTestData[3].time.Add(time.Second).UTC().Format(time.RFC3339) r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=routines&resolution=full&startDate=" + start + "&endDate=" + end, Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } expectedRoutineSubset := [][]string{ {""}, // header line, ignored in test. {objTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", objTestData[3].value)}, } compareCsvData(b, expectedRoutineSubset, t) }
func TestAppMetricMemoryCsv(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } // Testing the "timers" group, could move to another testing function r := wt.Request{ User: userW, Password: keyW, Method: "PUT", } type memoryTest struct { appId, instanceId string typeId int value float64 time time.Time } utcNow := time.Now().UTC().Truncate(time.Second) t0 := utcNow.Add(time.Second * -10) memTestData := []memoryTest{ {appId: "test-app", instanceId: "test-instance", typeId: 1000, value: 10, time: t0}, {appId: "test-app", instanceId: "test-instance", typeId: 1000, value: 9, time: t0.Add(time.Second * 2)}, {appId: "test-app", instanceId: "test-instance", typeId: 1000, value: 8, time: t0.Add(time.Second * 4)}, {appId: "test-app", instanceId: "test-instance", typeId: 1000, value: 7, time: t0.Add(time.Second * 6)}, {appId: "test-app", instanceId: "test-instance", typeId: 1000, value: 6, time: t0.Add(time.Second * 8)}, } // the expected CSV data, ignoring the header fields on the first line expectedMemVals := [][]string{ {""}, // header line, ignored in test. {memTestData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", memTestData[0].value)}, {memTestData[1].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", memTestData[1].value)}, {memTestData[2].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", memTestData[2].value)}, {memTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", memTestData[3].value)}, {memTestData[4].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", memTestData[4].value)}, } // Add timer values for _, mt := range memTestData { // /application/metric?applicationID=test-app&instanceID=test-instance&typeID=1000&value=10000&time=2015-05-14T21:40:30Z r.URL = fmt.Sprintf("/application/metric?applicationID=%s&instanceID=%s&typeID=%d&value=%d&time=%s", mt.appId, mt.instanceId, mt.typeId, int(mt.value), mt.time.Format(time.RFC3339)) addData(r, t) } r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=memory&resolution=full", Method: "GET", Accept: "text/csv"} var err error var b []byte if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedMemVals, t) // test with time range start := memTestData[3].time.Add(time.Second * -1).UTC().Format(time.RFC3339) end := memTestData[3].time.Add(time.Second).UTC().Format(time.RFC3339) r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=memory&resolution=full&startDate=" + start + "&endDate=" + end, Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } expectedMemSubset := [][]string{ {""}, // header line, ignored in test. {memTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", memTestData[3].value)}, } compareCsvData(b, expectedMemSubset, t) }
func TestAppMetricTimerCsv(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } // Testing the "timers" group, could move to another testing function r := wt.Request{ User: userW, Password: keyW, Method: "PUT", } type timerTest struct { appId string count float64 average float64 fifty float64 ninety float64 time time.Time } utcNow := time.Now().UTC().Truncate(time.Second) t0 := utcNow.Add(time.Second * -10) timerTestData := []timerTest{ {appId: "func-name", count: 1, average: 30, fifty: 73, ninety: 81, time: t0}, {appId: "func-name2", count: 3, average: 32, fifty: 57, ninety: 59, time: t0}, // same time as above but different appId {appId: "func-name3", count: 6, average: 31, fifty: 76, ninety: 82, time: t0}, {appId: "func-name", count: 4, average: 36, fifty: 73, ninety: 78, time: t0.Add(time.Second * 2)}, {appId: "func-name", count: 2, average: 33, fifty: 76, ninety: 93, time: t0.Add(time.Second * 4)}, {appId: "func-name", count: 9, average: 38, fifty: 73, ninety: 91, time: t0.Add(time.Second * 6)}, } // the expected CSV data, ignoring the header fields on the first line expectedTimerVals := [][]string{ {""}, // header line, ignored in test. Should be: time, func-name, func-name2, func-name3. Only one measurement per metric {timerTestData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[0].ninety), fmt.Sprintf("%.2f", timerTestData[1].ninety), fmt.Sprintf("%.2f", timerTestData[2].ninety)}, {timerTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[3].ninety), "", ""}, {timerTestData[4].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[4].ninety), "", ""}, {timerTestData[5].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[5].ninety), "", ""}, } // Add timer values for _, tv := range timerTestData { r.URL = fmt.Sprintf("/application/timer?applicationID=test-app&instanceID=test-instance&sourceID=%s&count=%d&average=%d&fifty=%d&ninety=%d&time=%s", tv.appId, int(tv.count), int(tv.average), int(tv.fifty), int(tv.ninety), tv.time.Format(time.RFC3339)) addData(r, t) } r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=timers&resolution=full", Method: "GET", Accept: "text/csv"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedTimerVals, t) // same test with time range start := timerTestData[3].time.Add(time.Second * -1).Format(time.RFC3339) end := timerTestData[3].time.Add(time.Second).Format(time.RFC3339) r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=timers&resolution=full&startDate=" + start + "&endDate=" + end, Method: "GET", Accept: "text/csv"} expectedTimerSubset := [][]string{ {""}, // header line, ignored in test. Should be: time, func-name. {timerTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[3].ninety)}, } if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } //fmt.Println(string(b), start, end, "subset time", timerTestData[3].time) compareCsvData(b, expectedTimerSubset, t) // do same test with sourceID specified since it uses another SQL query and outputs different results (average, fifty, ninety for the specified applicationID) r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=timers&sourceID=func-name&resolution=full", Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } expectedTimerSrcVals := [][]string{ {""}, // header line, ignored in test. Should be: time, func-name. {timerTestData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[0].average), fmt.Sprintf("%.2f", timerTestData[0].fifty), fmt.Sprintf("%.2f", timerTestData[0].ninety)}, {timerTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[3].average), fmt.Sprintf("%.2f", timerTestData[3].fifty), fmt.Sprintf("%.2f", timerTestData[3].ninety)}, {timerTestData[4].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[4].average), fmt.Sprintf("%.2f", timerTestData[4].fifty), fmt.Sprintf("%.2f", timerTestData[4].ninety)}, {timerTestData[5].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[5].average), fmt.Sprintf("%.2f", timerTestData[5].fifty), fmt.Sprintf("%.2f", timerTestData[5].ninety)}, } compareCsvData(b, expectedTimerSrcVals, t) // similar test but with a time range r = wt.Request{ID: wt.L(), URL: "/app/metric?applicationID=test-app&group=timers&sourceID=func-name&resolution=full&startDate=" + start + "&endDate=" + end, Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } expectedTimerSrcSubset := [][]string{ {""}, // header line, ignored in test. Should be: time, func-name. {timerTestData[3].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", timerTestData[3].average), fmt.Sprintf("%.2f", timerTestData[3].fifty), fmt.Sprintf("%.2f", timerTestData[3].ninety)}, } compareCsvData(b, expectedTimerSrcSubset, t) }
func TestFieldMetricCsv(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } r := wt.Request{ User: userW, Password: keyW, Method: "PUT", } var err error type testPoint struct { time time.Time value float64 } // Testing the "counter" group utcNow := time.Now().UTC().Truncate(time.Second) t0 := utcNow.Add(time.Second * -10) testData := []testPoint{ {time: t0, value: 10000.0}, // can only use one point due to rate limiting in put method } // the expected CSV data, ignoring the header fields on the first line scale := 0.001 expectedVals := [][]string{ {""}, // header line, ignored in test. Should be time, value {testData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", testData[0].value*scale)}, } for _, td := range testData { r.URL = fmt.Sprintf("/field/metric?deviceID=gps-taupoairport&typeID=voltage&time=%s&value=%d", td.time.Format(time.RFC3339), int(td.value)) addData(r, t) } r = wt.Request{ID: wt.L(), URL: "/field/metric?deviceID=gps-taupoairport&typeID=voltage&resolution=full", Method: "GET", Accept: "text/csv"} var b []byte if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } compareCsvData(b, expectedVals, t) // test for invalid deviceID r = wt.Request{ID: wt.L(), URL: "/field/metric?deviceID=NOT_THERE&typeID=voltage&resolution=full", Method: "GET", Accept: "text/csv", Status: http.StatusNotFound} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } // test with a time range, only one point so not much we can do start := testData[0].time.Add(time.Second * -1).UTC().Format(time.RFC3339) end := testData[0].time.Add(time.Second).UTC().Format(time.RFC3339) r = wt.Request{ID: wt.L(), URL: "/field/metric?deviceID=gps-taupoairport&typeID=voltage&resolution=full&startDate=" + start + "&endDate=" + end, Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } expectedSubset := [][]string{ {""}, // header line, ignored in test. Should be time, value {testData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", testData[0].value*scale)}, } compareCsvData(b, expectedSubset, t) // test multiple typeIDs in a single call (using voltage twice since we only have a single metric), needed for plotting N different series on one graph. r = wt.Request{ID: wt.L(), URL: "/field/metric?deviceID=gps-taupoairport&typeID=voltage&typeID=voltage&resolution=full", Method: "GET", Accept: "text/csv"} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } expectedOutput := [][]string{ {""}, // header line, ignored in test. Should be time, voltage, voltage {testData[0].time.Format(DYGRAPH_TIME_FORMAT), fmt.Sprintf("%.2f", testData[0].value*scale), fmt.Sprintf("%.2f", testData[0].value*scale)}, } compareCsvData(b, expectedOutput, t) // an invalid typeID should get a 404 r = wt.Request{ID: wt.L(), URL: "/field/metric?deviceID=gps-taupoairport&typeID=notAValidTypeID&resolution=full", Method: "GET", Accept: "text/csv", Status: http.StatusNotFound} if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } }
// protobuf of field metric summary info. func TestFieldMetricsSummary(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } r := wt.Request{ID: wt.L(), URL: "/field/metric/summary", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var f mtrpb.FieldMetricSummaryResult if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if len(f.Result) != 1 { t.Error("expected 1 result.") } d := f.Result[0] if d.DeviceID != "gps-taupoairport" { t.Errorf("expected gps-taupoairport got %s", d.DeviceID) } if d.ModelID != "Trimble NetR9" { t.Errorf("expected Trimble NetR9 got %s", d.ModelID) } if d.TypeID != "voltage" { t.Errorf("expected voltage got %s", d.TypeID) } if d.Value != 14100 { t.Errorf("expected 14100 got %d", d.Value) } if d.Seconds == 0 { t.Error("unexpected zero seconds") } if d.Upper != 45000 { t.Errorf("expected 45000 got %d", d.Upper) } if d.Lower != 12000 { t.Errorf("expected 12000 got %d", d.Lower) } if d.Scale != 0.001 { t.Errorf("expected 0.001 got %f", d.Scale) } // should be no errors and empty result for typeID=conn r.URL = "/field/metric/summary?typeID=conn" if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } f.Reset() if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if len(f.Result) != 0 { t.Error("expected 0 results.") } }
// protobuf of latency summary info. func TestDataLatencySummary(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } r := wt.Request{ID: wt.L(), URL: "/data/latency/summary", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var f mtrpb.DataLatencySummaryResult if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if len(f.Result) != 1 { t.Error("expected 1 result.") } d := f.Result[0] if d.SiteID != "TAUP" { t.Errorf("expected TAUP got %s", d.SiteID) } if d.TypeID != "latency.strong" { t.Errorf("expected latency.strong got %s", d.TypeID) } if d.Mean != 10000 { t.Errorf("expected 10000 got %d", d.Mean) } if d.Fifty != 0 { t.Errorf("expected 0 got %d", d.Fifty) } if d.Ninety != 0 { t.Errorf("expected 0 got %d", d.Ninety) } if d.Seconds == 0 { t.Error("unexpected zero seconds") } if d.Upper != 15000 { t.Errorf("expected 15000 got %d", d.Upper) } if d.Lower != 12000 { t.Errorf("expected 12000 got %d", d.Lower) } if d.Scale != 1.0 { t.Errorf("expected 1.0 got %f", d.Scale) } r.URL = "/data/latency/summary?typeID=latency.strong" if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } f.Reset() if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if len(f.Result) != 1 { t.Error("expected 1 result.") } }
/* Adds some plot data. Run just this test: go test -run TestPlotData Then visit http://localhost:8080/field/metric?deviceID=gps-taupoairport&typeID=voltage http://localhost:8080/data/latency?siteID=TAUP&typeID=latency.strong */ func TestPlotData(t *testing.T) { setup(t) defer teardown() // Load test data. if err := routes.DoAllStatusOk(testServer.URL); err != nil { t.Error(err) } r := wt.Request{ User: userW, Password: keyW, Method: "PUT", } var err error // Load some field metrics (every 5 mins) now := time.Now().UTC() v := 14000 for i := -720; i < 0; i += 5 { if i >= -100 { v = int(14000*(1/(float64(i)+101.0))) + 10000 if v > 14000 { v = 14000 } } r.URL = fmt.Sprintf("/field/metric?deviceID=gps-taupoairport&typeID=voltage&time=%s&value=%d", now.Add(time.Duration(i)*time.Minute).Format(time.RFC3339), v) if _, err = r.Do(testServer.URL); err != nil { t.Error(err) } } // Load some latency metrics (every 5 mins) now = time.Now().UTC() v = 14000 for i := -720; i < 0; i += 5 { if i >= -100 { v = int(14000*(1/(float64(i)+101.0))) + 10000 if v > 14000 { v = 14000 } } r.URL = fmt.Sprintf("/data/latency?siteID=TAUP&typeID=latency.strong&time=%s&mean=%d", now.Add(time.Duration(i)*time.Minute).Format(time.RFC3339), v) if _, err = r.Do(testServer.URL); err != nil { t.Error(err) } } // Load some completeness data (every 5 mins) now = time.Now().UTC() v = 300 for i := -720; i < 0; i += 5 { if i >= -100 { v = int(300*(1/(float64(i)+101.0))) + 200 if v > 300 { v = 300 } } r.URL = fmt.Sprintf("/data/completeness?siteID=TAUP&typeID=completeness.gnss.1hz&time=%s&count=%d", now.Add(time.Duration(i)*time.Minute).Format(time.RFC3339), v) if _, err = r.Do(testServer.URL); err != nil { t.Error(err) } } }