Files
mesh-catalog/modules/mesh-vault/cmd/mesh-vault/placementview_test.go
T

77 lines
2.3 KiB
Go

package main
import (
"context"
"encoding/json"
"errors"
"sync"
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/views"
)
// ADR 0615 §6: the vault started while the assigner is down keeps asking, never reads its bucket, and past the bound
// writes a finding naming the owner and the tool for the condition keeper; the answer deletes it. Before the answer a read
// of the placement is an error.
func TestAnUnansweredFirstViewOfThePlacementIsAFindingTheAnswerClears(t *testing.T) {
var mu sync.Mutex
up := false
held := map[string]json.RawMessage{}
ask := func(string, any) (json.RawMessage, error) {
mu.Lock()
defer mu.Unlock()
if !up {
return nil, errors.New("nats: no responders available for request")
}
raw, _ := json.Marshal(views.Answer{V: 1, Owner: "mesh-delivery-assigner", State: "placement", Revision: 1, Created: time.Now(),
Values: map[string]json.RawMessage{"g14.node": json.RawMessage(`{}`)}})
return raw, nil
}
f := newPlacementView(ask, func(string) {}, nil, heldFindings{&mu, held})
f.Bound, f.Wait = 30*time.Millisecond, 10*time.Millisecond
reader := viewPlacement(func() *views.Follower { return f })
if _, err := reader.Keys(); err == nil {
t.Fatal("the placement was read before its first view")
}
done := make(chan error, 1)
go func() { done <- f.Start(context.Background()) }()
count := func() int { mu.Lock(); defer mu.Unlock(); return len(held) }
for end := time.Now().Add(5 * time.Second); count() == 0 && time.Now().Before(end); time.Sleep(10 * time.Millisecond) {
}
if count() != 1 {
t.Fatalf("past its bound the vault wrote %d findings, want one", count())
}
mu.Lock()
up = true
mu.Unlock()
if err := <-done; err != nil {
t.Fatal(err)
}
if count() != 0 {
t.Errorf("the answer left %d findings", count())
}
if keys, err := reader.Keys(); err != nil || len(keys) != 1 || keys[0] != "g14.node" {
t.Errorf("keys %v, %v", keys, err)
}
}
// heldFindings keeps the findings written, by the finding's kind and subject.
type heldFindings struct {
mu *sync.Mutex
held map[string]json.RawMessage
}
func (h heldFindings) Put(f views.Finding) error {
h.mu.Lock()
defer h.mu.Unlock()
h.held[f.ID+"."+f.Kind] = json.RawMessage(f.Summary)
return nil
}
func (h heldFindings) Delete(f views.Finding) error {
h.mu.Lock()
defer h.mu.Unlock()
delete(h.held, f.ID+"."+f.Kind)
return nil
}