77 lines
2.3 KiB
Go
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
|
|
}
|