refactor(e2e): rename Test/E2E/chain -> Test/E2E/suite, run_chain_e2e.sh -> run_e2e.sh
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// ── frame builders (mirror the StreamHub wire format) ───────────────────────
|
||||
|
||||
func putf(b []byte, v float64) []byte {
|
||||
var t [8]byte
|
||||
binary.LittleEndian.PutUint64(t[:], math.Float64bits(v))
|
||||
return append(b, t[:]...)
|
||||
}
|
||||
|
||||
func putSignals(b []byte, sigs map[string]points) []byte {
|
||||
var n [4]byte
|
||||
binary.LittleEndian.PutUint32(n[:], uint32(len(sigs)))
|
||||
b = append(b, n[:]...)
|
||||
for k, p := range sigs {
|
||||
var kl [2]byte
|
||||
binary.LittleEndian.PutUint16(kl[:], uint16(len(k)))
|
||||
b = append(b, kl[:]...)
|
||||
b = append(b, []byte(k)...)
|
||||
var cnt [4]byte
|
||||
binary.LittleEndian.PutUint32(cnt[:], uint32(len(p.T)))
|
||||
b = append(b, cnt[:]...)
|
||||
for _, t := range p.T {
|
||||
b = putf(b, t)
|
||||
}
|
||||
for _, v := range p.V {
|
||||
b = putf(b, v)
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func buildPush(srcID string, sigs map[string]points) []byte {
|
||||
b := []byte{1, byte(len(srcID))}
|
||||
b = append(b, []byte(srcID)...)
|
||||
return putSignals(b, sigs)
|
||||
}
|
||||
|
||||
func buildCapture(trigTime, preSec, postSec float64, sigs map[string]points) []byte {
|
||||
b := []byte{2}
|
||||
b = putf(b, trigTime)
|
||||
b = putf(b, preSec)
|
||||
b = putf(b, postSec)
|
||||
return putSignals(b, sigs)
|
||||
}
|
||||
|
||||
// ── tests ───────────────────────────────────────────────────────────────────
|
||||
|
||||
func TestParsePushRoundTrip(t *testing.T) {
|
||||
in := map[string]points{"Sine": {T: []float64{0, 0.1, 0.2}, V: []float64{1, 2, 3}}}
|
||||
f, err := parsePush(buildPush("src", in))
|
||||
if err != nil {
|
||||
t.Fatalf("parsePush: %v", err)
|
||||
}
|
||||
if f.sourceID != "src" {
|
||||
t.Errorf("sourceID = %q, want src", f.sourceID)
|
||||
}
|
||||
got := f.signals["Sine"]
|
||||
if len(got.T) != 3 || got.T[2] != 0.2 || got.V[1] != 2 {
|
||||
t.Errorf("bad payload: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePushRejectsWrongVersion(t *testing.T) {
|
||||
if _, err := parsePush([]byte{2, 0, 0}); err == nil {
|
||||
t.Error("expected error on non-v1 frame")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePushTruncated(t *testing.T) {
|
||||
full := buildPush("src", map[string]points{"A": {T: []float64{0}, V: []float64{1}}})
|
||||
if _, err := parsePush(full[:len(full)-4]); err == nil {
|
||||
t.Error("expected truncation error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCaptureRoundTrip(t *testing.T) {
|
||||
in := map[string]points{"Sig": {T: []float64{1, 2}, V: []float64{9, 8}}}
|
||||
f, err := parseCapture(buildCapture(100.5, 0.02, 0.08, in))
|
||||
if err != nil {
|
||||
t.Fatalf("parseCapture: %v", err)
|
||||
}
|
||||
if f.trigTime != 100.5 || f.preSec != 0.02 || f.postSec != 0.08 {
|
||||
t.Errorf("header = %v/%v/%v", f.trigTime, f.preSec, f.postSec)
|
||||
}
|
||||
if g := f.signals["Sig"]; len(g.T) != 2 || g.V[0] != 9 {
|
||||
t.Errorf("bad capture payload: %+v", g)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCaptureRejectsWrongVersion(t *testing.T) {
|
||||
if _, err := parseCapture([]byte{1, 0, 0, 0}); err == nil {
|
||||
t.Error("expected error on non-v2 frame")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergedSortsAndDedups(t *testing.T) {
|
||||
c := &client{
|
||||
configs: map[string][]signalInfo{},
|
||||
zooms: map[uint32]map[string]points{},
|
||||
}
|
||||
// two pushes, out of order, with one duplicate timestamp
|
||||
c.pushes = []*pushFrame{
|
||||
{sourceID: "s", signals: map[string]points{"A": {T: []float64{0.2, 0.1}, V: []float64{2, 1}}}},
|
||||
{sourceID: "s", signals: map[string]points{"A": {T: []float64{0.1, 0.3}, V: []float64{1, 3}}}},
|
||||
}
|
||||
m := c.merged()
|
||||
got := m["s:A"]
|
||||
want := []float64{0.1, 0.2, 0.3}
|
||||
if len(got.T) != len(want) {
|
||||
t.Fatalf("len = %d, want %d (%+v)", len(got.T), len(want), got)
|
||||
}
|
||||
for i := range want {
|
||||
if got.T[i] != want[i] {
|
||||
t.Errorf("t[%d] = %v, want %v", i, got.T[i], want[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEdgeCrosses(t *testing.T) {
|
||||
rising := points{T: []float64{0, 1, 2}, V: []float64{-1, 1, 2}}
|
||||
if !edgeCrosses(rising, 0.5, "rising", 0.0) {
|
||||
t.Error("rising cross not detected")
|
||||
}
|
||||
if edgeCrosses(rising, 0.5, "falling", 0.0) {
|
||||
t.Error("false falling detection on rising data")
|
||||
}
|
||||
falling := points{T: []float64{0, 1}, V: []float64{1, -1}}
|
||||
if !edgeCrosses(falling, 0.5, "falling", 0.0) {
|
||||
t.Error("falling cross not detected")
|
||||
}
|
||||
if !edgeCrosses(falling, 0.5, "both", 0.0) {
|
||||
t.Error("both should match a falling edge")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHas(t *testing.T) {
|
||||
if !has("live,zoom,trigger", "zoom") {
|
||||
t.Error("has should find zoom")
|
||||
}
|
||||
if has("live, window", "trigger") {
|
||||
t.Error("has should not find trigger")
|
||||
}
|
||||
if !has("live, window", "window") {
|
||||
t.Error("has should trim spaces")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user