Files
mesh-contracts/go/clients/nodeengineclient/have_test.go
T

108 lines
3.9 KiB
Go

package nodeengineclient
import (
"errors"
"strings"
"testing"
"time"
seat "git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
"git.novox.be/novox/mesh-sdk/go/keys"
)
const digestA = "sha256:0000000000000000000000000000000000000000000000000000000000000001"
func TestHaveCodec(t *testing.T) {
good := seat.HaveByNodeModuleValue{Phase: PhaseRunning, Health: HealthOK, Composed: digestA, Fp: "src2:x"}
waiting := seat.HaveByNodeModuleValue{Phase: PhaseWaitingYes, Health: HealthOK, Judgement: JudgedRecreates, Waits: digestA}
pull := &seat.PullWait{Image: "i", Holder: "h"}
tests := map[string]struct {
have seat.HaveByNodeModuleValue
bad string
}{
"running": {good, ""},
"waiting for a yes": {waiting, ""},
"unknown phase": {seat.HaveByNodeModuleValue{Phase: "gone", Health: HealthOK}, "phase"},
"unknown health": {seat.HaveByNodeModuleValue{Phase: PhaseRunning, Health: "fine"}, "health"},
"judgement outside a yes": {seat.HaveByNodeModuleValue{Phase: PhaseRunning, Health: HealthOK, Judgement: JudgedCannot}, "judgement"},
"a yes without a digest": {seat.HaveByNodeModuleValue{Phase: PhaseWaitingYes, Health: HealthOK, Judgement: JudgedCannot, Waits: "x"}, "sha256"},
"pull wait on a running": {seat.HaveByNodeModuleValue{Phase: PhaseRunning, Health: HealthOK, PullWait: pull}, "pull"},
"pull wait without holder": {seat.HaveByNodeModuleValue{Phase: PhaseFailed, Health: HealthFailed, PullWait: &seat.PullWait{Image: "i"}}, "holder"},
"bad composed digest": {seat.HaveByNodeModuleValue{Phase: PhaseRunning, Health: HealthOK, Composed: "abc"}, "sha256"},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
raw, err := EncodeHave(tc.have)
if tc.bad != "" {
if err == nil || !strings.Contains(err.Error(), tc.bad) {
t.Fatalf("encode: %v, want it to name %q", err, tc.bad)
}
return
}
if err != nil {
t.Fatal(err)
}
back, err := DecodeHave(raw)
if err != nil {
t.Fatal(err)
}
tc.have.V = keys.Version
if !SameHave(back, tc.have) {
t.Fatalf("round trip differs: %+v", back)
}
})
}
if _, err := DecodeHave([]byte(`{"v":2,"phase":"running","health":"ok"}`)); !errors.Is(err, keys.ErrUnknownVersion) {
t.Fatalf("version 2: %v", err)
}
if _, err := DecodeHave([]byte(`{"v":1,"phase":"running","health":"ok","extra":1}`)); err == nil {
t.Fatal("an unknown field is read")
}
}
func TestSameHaveComparesTimesAsInstants(t *testing.T) {
at := time.Date(2026, 11, 5, 12, 0, 0, 0, time.UTC)
zone := time.FixedZone("x", 3600)
mk := func(tm time.Time) seat.HaveByNodeModuleValue {
return seat.HaveByNodeModuleValue{Phase: PhaseFailed, Health: HealthFailed,
PullWait: &seat.PullWait{Image: "i", Holder: "h", Began: tm},
UserList: &seat.UserListWritten{Source: "s", At: tm}}
}
if !SameHave(mk(at), mk(at.In(zone))) {
t.Fatal("the same instant in another zone differs")
}
if SameHave(mk(at), mk(at.Add(time.Second))) {
t.Fatal("another instant is the same")
}
}
func TestHaveNodeCodec(t *testing.T) {
n := seat.HaveByNodeNodeValue{Composed: digestA, Composes: ComposesOwn,
Candidates: map[string]seat.CandidateAnswer{"g": {Proposal: "p", Verdict: seat.CandidateAnswerVerdictSame}}}
raw, err := EncodeHaveNode(n)
if err != nil {
t.Fatal(err)
}
back, err := DecodeHaveNode(raw)
if err != nil {
t.Fatal(err)
}
n.V = keys.Version
if !SameHaveNode(back, n) {
t.Fatalf("round trip differs: %+v", back)
}
for name, bad := range map[string]seat.HaveByNodeNodeValue{
"composes": {Composes: "other"},
"no group": {Candidates: map[string]seat.CandidateAnswer{"": {Verdict: "same"}}},
"a verdict": {Candidates: map[string]seat.CandidateAnswer{"g": {Verdict: "maybe"}}},
} {
if _, err := EncodeHaveNode(bad); err == nil {
t.Errorf("%s: encoded", name)
}
}
a, b := seat.NodeRecord{Node: "n", V: 1}, seat.NodeRecord{Node: "n", V: 2}
if !SameNodeRecord(a, b) {
t.Error("a record differs by its version")
}
}