123 lines
3.1 KiB
Go
123 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/amenzhinsky/go-gpsd"
|
|
|
|
"macker/datapoint"
|
|
)
|
|
|
|
func TestBackoffFor(t *testing.T) {
|
|
want := []time.Duration{5 * time.Second, 10 * time.Second, 20 * time.Second, 40 * time.Second, 60 * time.Second, 60 * time.Second}
|
|
for i, w := range want {
|
|
if got := backoffFor(i); got != w {
|
|
t.Errorf("backoffFor(%d) = %v, want %v", i, got, w)
|
|
}
|
|
}
|
|
// 100-retry cycle wraps back to the starter delay.
|
|
if got := backoffFor(99); got != 60*time.Second {
|
|
t.Errorf("backoffFor(99) = %v, want 60s", got)
|
|
}
|
|
if got := backoffFor(100); got != 5*time.Second {
|
|
t.Errorf("backoffFor(100) = %v, want 5s", got)
|
|
}
|
|
}
|
|
|
|
func TestSolidifyData(t *testing.T) {
|
|
tpv := &gpsd.TPV{Mode: 3, Speed: 12.5, Lat: 45.5, Lon: -122.6, Alt: 100, Epy: 1.5, Epx: 2.5, Epv: 3.5}
|
|
dp, err := solidifyData(tpv)
|
|
if err != nil {
|
|
t.Fatalf("solidifyData: %v", err)
|
|
}
|
|
if dp.Lat != 45.5 || dp.LatErr != 1.5 || dp.Long != -122.6 || dp.LongErr != 2.5 || dp.Alt != 100 || dp.AltErr != 3.5 {
|
|
t.Errorf("bad mapping: %+v", dp)
|
|
}
|
|
if dp.Speed == nil || *dp.Speed != 12.5 {
|
|
t.Errorf("speed was not preserved: %v", dp.Speed)
|
|
}
|
|
if _, err := solidifyData(&gpsd.TPV{Mode: 1}); err == nil {
|
|
t.Error("expected report without position fix to be rejected")
|
|
}
|
|
if dp.Timestamp != 0 {
|
|
t.Errorf("zero time should leave Timestamp 0, got %d", dp.Timestamp)
|
|
}
|
|
if _, err := solidifyData(&gpsd.SKY{}); err == nil {
|
|
t.Error("expected error for non-TPV report")
|
|
}
|
|
}
|
|
|
|
// Fake server: gob-decode []byte then unzip JSON, as the real receiver does.
|
|
func TestSendLoopEndToEnd(t *testing.T) {
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer ln.Close()
|
|
|
|
type batch struct {
|
|
points []datapoint.DataPoint
|
|
err error
|
|
}
|
|
got := make(chan batch, 4)
|
|
|
|
go func() {
|
|
for {
|
|
con, err := ln.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
var raw []byte
|
|
if err := gob.NewDecoder(con).Decode(&raw); err != nil {
|
|
got <- batch{err: err}
|
|
con.Close()
|
|
continue
|
|
}
|
|
pts, err := datapoint.UnzipBatch(raw)
|
|
if err != nil {
|
|
got <- batch{err: err}
|
|
con.Close()
|
|
continue
|
|
}
|
|
got <- batch{points: pts}
|
|
con.Close()
|
|
}
|
|
}()
|
|
|
|
errorChan := make(chan error, 16)
|
|
go manageErrors(errorChan)
|
|
|
|
batches := make(chan []datapoint.DataPoint, 4)
|
|
_, port, err := net.SplitHostPort(ln.Addr().String())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
go sendLoop("127.0.0.1", port, batches, time.Hour, 2, errorChan)
|
|
|
|
batches <- []datapoint.DataPoint{{Timestamp: 1, Lat: 1}, {Timestamp: 2, Lat: 2}}
|
|
batches <- []datapoint.DataPoint{{Timestamp: 3, Lat: 3}}
|
|
|
|
// First batch trips the size-2 threshold.
|
|
select {
|
|
case b := <-got:
|
|
if b.err != nil {
|
|
t.Fatalf("decode: %v", b.err)
|
|
}
|
|
if len(b.points) != 2 || b.points[0].Lat != 1 || b.points[1].Lat != 2 {
|
|
t.Fatalf("bad first batch: %+v", b.points)
|
|
}
|
|
case <-time.After(3 * time.Second):
|
|
t.Fatal("timeout waiting for first batch")
|
|
}
|
|
|
|
// Second batch waits for the ticker (1h), so just prove it accumulates.
|
|
select {
|
|
case b := <-got:
|
|
t.Fatalf("unexpected flush before interval: %+v", b)
|
|
case <-time.After(300 * time.Millisecond):
|
|
}
|
|
}
|