// all tags as a protobuf func TestTagAll(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: "/tag", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var tr mtrpb.TagResult if err = proto.Unmarshal(b, &tr); err != nil { t.Error(err) } if len(tr.Result) != 6 { t.Errorf("expected 6 tags got %d", len(tr.Result)) } if tr.Result[0].Tag != "DAGG" { t.Errorf("expected DAGG as the first tag got %s", tr.Result[0].Tag) } }
// protobuf of field metrics and latencies for a single tag. func TestTag(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: "/tag/TAUP", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var tr mtrpb.TagSearchResult if err = proto.Unmarshal(b, &tr); err != nil { t.Error(err) } if tr.FieldMetric == nil { t.Error("Got nil FieldMetric") } if tr.DataLatency == nil { t.Error("Got nil DataLatency") } if tr.FieldState == nil { t.Error("Got nil FieldState") } if tr.DataCompleteness == nil { t.Error("Got nil DataCompleteness") } if tr.FieldMetric[0].DeviceID != "gps-taupoairport" { t.Errorf("expected deviceID gps-taupoairport got %s", tr.FieldMetric[0].DeviceID) } if tr.DataLatency[0].SiteID != "TAUP" { t.Errorf("expected siteID TAUP got %s", tr.DataLatency[0].SiteID) } if tr.FieldState[0].DeviceID != "gps-taupoairport" { t.Errorf("expected deviceID gps-taupoairport got %s", tr.FieldState[0].DeviceID) } if tr.DataCompleteness[0].SiteID != "TAUP" { t.Errorf("expected siteID TAUP got %s", tr.DataCompleteness[0].SiteID) } }
// protobuf of field metric threshold info. func TestFieldMetricsThreshold(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/threshold", 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.FieldMetricThresholdResult if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if f.Result == nil { t.Error("got nil for /field/metric/threshold protobuf") } 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.TypeID != "voltage" { t.Errorf("expected voltage got %s", d.TypeID) } 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) } }
// protobuf of data sites. func TestDataSites(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/site", 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.DataSiteResult if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if f.Result == nil { t.Error("got nil for /data/site protobuf") } if len(f.Result) != 2 { t.Error("expected 2 results.") } var found bool for _, v := range f.Result { if v.SiteID == "TAUP" { found = true if v.Latitude != -38.74270 { t.Errorf("Data site TAUP got expected latitude -38.74270 got %f", v.Latitude) } if v.Longitude != 176.08100 { t.Errorf("Data site TAUP got expected longitude 176.08100 got %f", v.Longitude) } } } if !found { t.Error("Didn't find site TAUP") } }
// protobuf for /field/state endpoint func TestFieldState(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/state", Accept: "application/x-protobuf"} var b []byte var err error // get the protobuf data back if b, err = r.Do(testServer.URL); err != nil { t.Fatal(err) } var dtr mtrpb.FieldStateResult if err = proto.Unmarshal(b, &dtr); err != nil { t.Fatal(err) } if dtr.Result == nil { t.Fatal("got nil for /field/state protobuf") } if len(dtr.Result) != 1 { t.Fatalf("expected 1 result, got %d.", len(dtr.Result)) } res := dtr.Result[0] if res.DeviceID != "gps-taupoairport" { t.Errorf("expected gps-taupoairport got %s", res.DeviceID) } if res.TypeID != "mains" { t.Errorf("expected mains got %s", res.TypeID) } if res.Seconds != 1431639630 { t.Errorf("expected 1431639630 got %d", res.Seconds) } if res.Value != true { t.Errorf("expected true got %s", res.Value) } }
// protobuf of /model/device endpoint func TestFieldDevice(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/device", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var fdr mtrpb.FieldDeviceResult if err = proto.Unmarshal(b, &fdr); err != nil { t.Error(err) } // ftr.Result should be a slice of struct pointers if fdr.Result == nil { t.Error("got nil for /field/device protobuf") } if len(fdr.Result) != 1 { t.Error("expected 1 result.") } d := fdr.Result[0] if d.ModelID != "Trimble NetR9" { t.Errorf("expected Trimble NetR9 got %s", d.ModelID) } if d.DeviceID != "gps-taupoairport" { t.Errorf("expected gps-taupoairport got %s", d.DeviceID) } if d.Latitude != -38.7427 { t.Errorf("expected -38.7427 got %s", d.Latitude) } if d.Longitude != 176.081 { t.Errorf("expected 176.081 got %s", d.Longitude) } }
// protobuf for /field/state/tag endpoint func TestFieldStateTag(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/state/tag", Method: "GET", Accept: "application/x-protobuf"} var b []byte var err error // get the protobuf data back if b, err = r.Do(testServer.URL); err != nil { t.Fatal(err) } var tr mtrpb.FieldStateTagResult if err = proto.Unmarshal(b, &tr); err != nil { t.Fatal(err) } if tr.Result == nil { t.Fatal("got nil for /field/state protobuf") } if len(tr.Result) != 1 { t.Fatalf("expected 1 result, got %d.", len(tr.Result)) } res := tr.Result[0] if res.DeviceID != "gps-taupoairport" { t.Errorf("expected gps-taupoairport got %s", res.DeviceID) } if res.TypeID != "mains" { t.Errorf("expected mains got %s", res.TypeID) } if res.Tag != "TAUP" { t.Errorf("expected TAUP got %s", res.Tag) } }
// protobuf of metric history log info. func TestFieldMetricHistoryLog(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?deviceID=gps-taupoairport&typeID=voltage&resolution=minute", 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.FieldMetricResult if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if f.DeviceID != "gps-taupoairport" { t.Errorf("expected gps-taupoairport got %s", f.DeviceID) } if f.TypeID != "voltage" { t.Errorf("expected voltage got %s", f.TypeID) } if f.Upper != 45000 { t.Errorf("expected 45000 got %d", f.Upper) } if f.Lower != 12000 { t.Errorf("expected 12000 got %d", f.Lower) } if f.Scale != 0.001 { t.Errorf("expected 12000 got %f", f.Scale) } // Not testing number of latency log }
// protobuf of latency history log info. func TestDataLatencyHistoryLog(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?siteID=TAUP&typeID=latency.strong&resolution=minute", 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.DataLatencyResult if err = proto.Unmarshal(b, &f); err != nil { t.Error(err) } if f.SiteID != "TAUP" { t.Errorf("expected TAUP got %s", f.SiteID) } if f.TypeID != "latency.strong" { t.Errorf("expected latency.strong got %s", f.TypeID) } if f.Upper != 15000 { t.Errorf("expected 15000 got %d", f.Upper) } if f.Lower != 12000 { t.Errorf("expected 12000 got %d", f.Lower) } if f.Scale != 1.0 { t.Errorf("expected 1.0 got %f", f.Scale) } // Not testing number of latency log }
func TestQuakesCount(t *testing.T) { setup(t) defer teardown() //1. get all quakes r := wt.Request{ Accept: CONTENT_TYPE_JSON, URL: "/count?bbox=163.60840,-49.18170,182.98828,-32.28713", } b, err := r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } var qc QuakesCount err = json.Unmarshal(b, &qc) if err != nil { log.Fatal(err) } if qc.Count != 3 { t.Errorf("Found wrong number of quakes: %d", qc.Count) } //2. get only one quake r = wt.Request{ Accept: CONTENT_TYPE_JSON, URL: "/count?bbox=163.60840,-49.18170,182.98828,-32.28713&startdate=2010-1-1T00:00:00&enddate=2015-1-1T00:00:00", } b, err = r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } err = json.Unmarshal(b, &qc) if err != nil { t.Error(err) } if qc.Count != 1 { t.Errorf("Found wrong number of quakes: %d", qc.Count) } //3. get 2 quakes r = wt.Request{ Accept: CONTENT_TYPE_JSON, URL: "/count?bbox=163.60840,-49.18170,182.98828,-32.28713&minmag=5", } b, err = r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } err = json.Unmarshal(b, &qc) if err != nil { t.Error(err) } if qc.Count != 2 { t.Errorf("Found wrong number of quakes: %d", qc.Count) } }
func TestQuakesGeoJson(t *testing.T) { setup(t) defer teardown() //1. get all quakes r := wt.Request{URL: "/geojson?limit=100&bbox=163.60840,-49.18170,182.98828,-32.28713", Accept: CONTENT_TYPE_GeoJSON} b, err := r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } var f GeoJsonFeatureCollection err = json.Unmarshal(b, &f) if err != nil { log.Fatal(err) } if len(f.Features) != 3 { t.Errorf("Found wrong number of features: %d", len(f.Features)) } //2. get only one quake r = wt.Request{URL: "/geojson?limit=100&bbox=163.60840,-49.18170,182.98828,-32.28713&startdate=2010-1-1T00:00:00&enddate=2015-1-1T00:00:00", Accept: CONTENT_TYPE_GeoJSON} b, err = r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } err = json.Unmarshal(b, &f) if err != nil { log.Fatal(err) } if len(f.Features) != 1 { t.Errorf("Found wrong number of features: %d", len(f.Features)) } if f.Features[0].Properties.Publicid != "3366146" { t.Errorf("Found wrong publicid: %s", f.Features[0].Properties.Publicid) } }
func TestQuakesGeoJson(t *testing.T) { setup(t) defer teardown() //1. get all quakes cql_filter=BBOX(origin_geom,163.60840,-49.18170,182.98828,-32.28713) r := wt.Request{URL: url_wfs + "&outputFormat=json&cql_filter=BBOX(origin_geom,163.60840,-49.18170,182.98828,-32.28713)", Accept: CONTENT_TYPE_GeoJSON} b, err := r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } var f GeoJsonFeatureCollection err = json.Unmarshal(b, &f) if err != nil { log.Fatal(err) } if len(f.Features) != 3 { t.Errorf("Found wrong number of features: %d", len(f.Features)) } //2. get only one quake r = wt.Request{URL: url_wfs + "&outputFormat=json&cql_filter=BBOX(origin_geom,163.60840,-49.18170,182.98828,-32.28713)+AND+origintime>='2010-01-01'+AND+origintime<'2015-01-01'", Accept: CONTENT_TYPE_GeoJSON} b, err = r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } err = json.Unmarshal(b, &f) if err != nil { log.Fatal(err) } if len(f.Features) != 1 { t.Errorf("Found wrong number of features: %d", len(f.Features)) } if f.Features[0].Properties.Publicid != "3366146" { t.Errorf("Found wrong publicid: %s", f.Features[0].Properties.Publicid) } }
// protobuf of /model/type endpoint func TestFieldType(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/type", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var ftr mtrpb.FieldTypeResult if err = proto.Unmarshal(b, &ftr); err != nil { t.Error(err) } // ftr.Result should be a slice of struct pointers if ftr.Result == nil { t.Error("got nil for /field/type protobuf") } if len(ftr.Result) != 12 { t.Error("expected 12 results.") } if ftr.Result[0].TypeID != "centre" { t.Errorf("expected centre got %s", ftr.Result[0].TypeID) } if ftr.Result[0].Display != "mV" { t.Errorf("expected mV got %s", ftr.Result[0].Display) } }
func TestGeoJSONFormat(t *testing.T) { setup(t) defer teardown() r := wt.Request{ ID: wt.L(), Accept: CONTENT_TYPE_GeoJSON, Content: CONTENT_TYPE_GeoJSON, URL: "/geojson?limit=100&bbox=163.60840,-49.18170,182.98828,-32.28713&startdate=2000-1-1T00:00:00&enddate=2015-1-1T00:00:00", } b, err := r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } body := bytes.NewBuffer(b) res, err := client.Post("http://geojsonlint.com/validate", "application/vnd.geo+json", body) defer res.Body.Close() if err != nil { t.Errorf("Problem contacting geojsonlint for test %s", r.ID) } b, err = ioutil.ReadAll(res.Body) if err != nil { t.Errorf("Problem reading body from geojsonlint for test %s", r.ID) } var v valid err = json.Unmarshal(b, &v) if err != nil { t.Errorf("Problem unmarshalling body from geojsonlint for test %s", r.ID) } if v.Status != "ok" { t.Errorf("invalid geoJSON for test %s" + r.ID) } }
func TestGeoJSONFormat(t *testing.T) { setup(t) defer teardown() r := wt.Request{ ID: wt.L(), Accept: CONTENT_TYPE_GeoJSON, Content: CONTENT_TYPE_GeoJSON, URL: url_wfs + "&outputFormat=json&cql_filter=BBOX(origin_geom,163.60840,-49.18170,182.98828,-32.28713)+AND+origintime>='2000-01-01'+AND+origintime<'2015-01-01'", } b, err := r.Do(ts.URL) if err != nil { t.Error(err) t.Error(string(b)) } body := bytes.NewBuffer(b) res, err := client.Post("http://geojsonlint.com/validate", "application/vnd.geo+json", body) defer res.Body.Close() if err != nil { t.Errorf("Problem contacting geojsonlint for test %s", r.ID) } b, err = ioutil.ReadAll(res.Body) if err != nil { t.Errorf("Problem reading body from geojsonlint for test %s", r.ID) } var v valid err = json.Unmarshal(b, &v) if err != nil { t.Errorf("Problem unmarshalling body from geojsonlint for test %s", r.ID) } if v.Status != "ok" { t.Errorf("invalid geoJSON for test %s" + r.ID) } }
func TestDataTypes(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/type", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var dtr mtrpb.DataTypeResult if err = proto.Unmarshal(b, &dtr); err != nil { t.Error(err) } if dtr.Result == nil { t.Error("got nil for /data/type protobuf") } if len(dtr.Result) != 5 { t.Errorf("expected 5 results, got %d.", len(dtr.Result)) } if dtr.Result[0].TypeID != "latency.files.gnss" { t.Errorf("expected latency.files.gnss got %s", dtr.Result[0].TypeID) } if dtr.Result[0].Display != "ms" { t.Errorf("expected ms got %s", dtr.Result[0].Display) } }
// protobuf of /field/model endpoint func TestFieldModel(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/model", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var ftr mtrpb.FieldModelResult if err = proto.Unmarshal(b, &ftr); err != nil { t.Error(err) } // ftr.Result should be a slice of struct pointers if ftr.Result == nil { t.Error("got nil for /field/model protobuf") } if len(ftr.Result) != 1 { t.Error("expected 1 result.") } m := ftr.Result[0] if m.ModelID != "Trimble NetR9" { t.Errorf("expected Trimble NetR9 got %s", m.ModelID) } }
// 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)) } }
// protobuf for /app endpoint func TestAppIDs(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: "/app", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var dtr mtrpb.AppIDSummaryResult if err = proto.Unmarshal(b, &dtr); err != nil { t.Error(err) } if dtr.Result == nil { t.Error("got nil for /app protobuf") } if len(dtr.Result) != 1 { t.Errorf("expected 1 result, got %d.", len(dtr.Result)) } if dtr.Result[0].ApplicationID != "test-app" { t.Errorf("expected test-app got %s", dtr.Result[0].ApplicationID) } }
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 addData(r wt.Request, t *testing.T) { if _, err := r.Do(testServer.URL); err != nil { t.Error(err) } }
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) }
// All field metric tags as a protobuf. func TestFieldMetricTag(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/tag", Accept: "application/x-protobuf"} var b []byte var err error if b, err = r.Do(testServer.URL); err != nil { t.Error(err) } var tr mtrpb.FieldMetricTagResult if err = proto.Unmarshal(b, &tr); err != nil { t.Error(err) } if tr.Result == nil { t.Error("got nil for /field/metric/tag protobuf") } if len(tr.Result) != 1 { t.Errorf("expected 1 tag result got %d", len(tr.Result)) } if tr.Result[0].Tag != "TAUP" { t.Errorf("expected TAUP as the first tag got %s", tr.Result[0].Tag) } if tr.Result[0].DeviceID != "gps-taupoairport" { t.Errorf("expected gps-taupoairport as the first deviceID got %s", tr.Result[0].DeviceID) } if tr.Result[0].TypeID != "voltage" { t.Errorf("expected voltage as the first typeID got %s", tr.Result[0].TypeID) } // Test tag result for parameter with deviceID+typeID r = wt.Request{ID: wt.L(), URL: "/field/metric/tag?deviceID=gps-taupoairport&typeID=voltage", Accept: "application/x-protobuf"} if err = proto.Unmarshal(b, &tr); err != nil { t.Error(err) } if tr.Result == nil { t.Error("got nil for /field/metric/tag protobuf") } if len(tr.Result) != 1 { t.Errorf("expected 1 tag result got %d", len(tr.Result)) } if tr.Result[0].Tag != "TAUP" { t.Errorf("expected TAUP as the first tag got %s", tr.Result[0].Tag) } if tr.Result[0].DeviceID != "gps-taupoairport" { t.Errorf("expected gps-taupoairport as the first deviceID got %s", tr.Result[0].DeviceID) } if tr.Result[0].TypeID != "voltage" { t.Errorf("expected voltage as the first typeID got %s", tr.Result[0].TypeID) } }
// 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.") } }
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) } }
/* 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) } } }