Files
mesh-tools/node-tools/cmd/node-tools/seatlist_test.go
T

70 lines
1.9 KiB
Go

package main
import (
"encoding/json"
"errors"
"strings"
"sync/atomic"
"testing"
"time"
)
// busOfAStandIn is a seat mesh-catalog that answers after release, or never (a refusal).
type busOfAStandIn struct {
release chan struct{}
asked atomic.Int32
}
func (b *busOfAStandIn) Ask(string, any) (json.RawMessage, error) {
b.asked.Add(1)
<-b.release
return nil, errors.New("the seat does not answer")
}
func (b *busOfAStandIn) Subscribe(string, func(string, json.RawMessage) error) error { return nil }
// ADR 0636 §1: the runner waits for the first read of the seat list on the reader's Ready, but only to a bound that the
// test gives as a channel; past it, it serves with the bootstrapped seats and says so, and nothing sleeps.
func TestTheRunnerWaitsForTheFirstReadOfTheSeatListOnlyToItsBound(t *testing.T) {
for _, row := range []struct {
name string
release bool // the seat ends its first read (here by refusing) before the bound
wantSaid string
wantReady bool
}{
{"the first read ends before the bound", true, "", true},
{"the bound passes with the seat silent", false, "the seat list is not read yet", false},
} {
t.Run(row.name, func(t *testing.T) {
b := &busOfAStandIn{release: make(chan struct{})}
bound := make(chan time.Time, 1)
var said []string
if row.release {
close(b.release)
} else {
bound <- time.Time{}
}
r := startSeatListOn(b, bound, func(f string, a ...any) { said = append(said, f) })
if r == nil {
t.Fatal("no reader")
}
ended := false
select {
case <-r.Ready():
ended = true
default:
}
if ended != row.wantReady {
t.Errorf("first read ended = %v, want %v", ended, row.wantReady)
}
if got := strings.Join(said, ";"); !strings.Contains(got, row.wantSaid) || (row.wantSaid == "" && got != "") {
t.Errorf("said %q, want %q", got, row.wantSaid)
}
if !row.release {
close(b.release)
<-r.Ready()
}
})
}
}