2026-10-28 10:54:15 -05:00
|
|
|
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}
|
2026-10-28 13:43:27 -05:00
|
|
|
raw, err := datapoint.ZipBatch([]datapoint.DataPoint{point})
|
2026-10-28 10:54:15 -05:00
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
}
|