package main import ( "encoding/gob" "encoding/json" "net" "net/http/httptest" "testing" "time" "macker/datapoint" ) func TestReceiveAndServeLocation(t *testing.T) { tr := &tracker{} server, client := net.Pipe() done := make(chan struct{}) go func() { tr.receive(server); close(done) }() speed := 12.5 now := time.Now().UTC().Truncate(time.Millisecond) point := datapoint.DataPoint{Timestamp: uint64(now.UnixMilli()), Lat: 41.8, Long: -87.6, Speed: &speed} raw, err := json.Marshal([]datapoint.DataPoint{point}) if err != nil { t.Fatal(err) } if err = gob.NewEncoder(client).Encode(raw); err != nil { t.Fatal(err) } client.Close() <-done rr := httptest.NewRecorder() tr.handler().ServeHTTP(rr, httptest.NewRequest("GET", "/api/location", nil)) var got location if err = json.Unmarshal(rr.Body.Bytes(), &got); err != nil { t.Fatal(err) } if rr.Code != 200 || got.Point.Lat != point.Lat || got.Point.Speed == nil || *got.Point.Speed != speed || !got.UpdatedAt.Equal(now) { t.Fatalf("unexpected location: %s", rr.Body.String()) } // A delayed batch must not replace the current position. tr.accept([]datapoint.DataPoint{{Timestamp: uint64(now.Add(-time.Minute).UnixMilli()), Lat: 20}}, now) if tr.latest.Point.Lat != point.Lat { t.Fatal("older fix replaced current position") } } func TestEmptyInvalidAndMissingTimestamp(t *testing.T) { tr := &tracker{} rr := httptest.NewRecorder() tr.handler().ServeHTTP(rr, httptest.NewRequest("GET", "/api/location", nil)) if rr.Body.String() != "null\n" { t.Fatal(rr.Body.String()) } now := time.Now().UTC() tr.accept([]datapoint.DataPoint{{Lat: 91}, {Long: 181}, {Timestamp: uint64(now.Add(time.Hour).UnixMilli())}}, now) if tr.latest != nil { t.Fatal("accepted invalid point") } tr.accept([]datapoint.DataPoint{{Lat: 0, Long: 0}}, now) if tr.latest == nil || !tr.latest.UpdatedAt.Equal(now) { t.Fatal("missing timestamp should use receipt time") } }