71 lines
2.0 KiB
Go
71 lines
2.0 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
"github.com/novox/mesh-controller/internal/lease"
|
|
)
|
|
|
|
// A command run at a shell (novox/hq to-be 45 §6): under the holder's epoch while a controller holds the
|
|
// lease, read at the moment it acts; under a lease of its own while none does, given back as it ends.
|
|
func TestACommandActsUnderTheHoldersEpochOrItsOwn(t *testing.T) {
|
|
url, kv := aBusForTheLease(t)
|
|
t.Setenv(broker.NATSVar, url)
|
|
ctx := t.Context()
|
|
|
|
// Nobody holds it: the command takes it, and gives it back.
|
|
cmd := &actor{}
|
|
own, err := cmd.epoch(ctx)
|
|
if err != nil || own == 0 {
|
|
t.Fatalf("a command with nobody holding the lease acts as %d (%v)", own, err)
|
|
}
|
|
if h, found, _ := lease.Current(ctx, kv); !found || h.Epoch != own {
|
|
t.Fatalf("the command's lease is not on the bus: %+v", h)
|
|
}
|
|
cmd.release()
|
|
if _, found, _ := lease.Current(ctx, kv); found {
|
|
t.Fatal("the command did not give its lease back as it ended")
|
|
}
|
|
|
|
// A controller holds it: a command acts under that epoch.
|
|
l, err := lease.Open(ctx, mustJetStream(t, url), broker.LeaseBucket, lease.Options{Holder: lease.Holder{Instance: "serving"}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
held, err := l.TryTake(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
borrower := &actor{}
|
|
defer borrower.release()
|
|
if got, err := borrower.epoch(ctx); err != nil || got != held {
|
|
t.Fatalf("a command acts as %d (%v), want the holder's %d", got, err, held)
|
|
}
|
|
// The holder lets go: the command does not go on under an epoch nobody holds.
|
|
l.Release(ctx)
|
|
if _, err := borrower.epoch(ctx); err == nil {
|
|
t.Fatal("a command acted under an epoch nobody holds any more")
|
|
}
|
|
}
|
|
|
|
// mustJetStream is a connection of its own to the test bus.
|
|
func mustJetStream(t *testing.T, url string) jetstream.JetStream {
|
|
t.Helper()
|
|
conn, err := nats.Connect(url)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(conn.Close)
|
|
js, err := jetstream.New(conn)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return js
|
|
}
|