43 lines
1.6 KiB
Go
43 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func backupEvent(node, module string, ok bool, at time.Time, why string) []byte {
|
|
raw, _ := json.Marshal(map[string]any{"node": node, "module": module, "ok": ok, "at": at, "error": why})
|
|
return raw
|
|
}
|
|
|
|
// A backup is done when the holder says so for this node and module, held on its words when it says it failed, and held
|
|
// when it says nothing within the bound; another node's or module's event, or one from before the ask, is not the answer
|
|
// (R6-A A5, novox/hq ADR 0429 §14).
|
|
func TestABackupEndsWhenItsEventSaysSo(t *testing.T) {
|
|
since := time.Now()
|
|
run := func(within time.Duration, events ...[]byte) (done bool, words string) {
|
|
ch := make(chan []byte, len(events))
|
|
for _, e := range events {
|
|
ch <- e
|
|
}
|
|
got := awaitBackup(context.Background(), ch, "n1", "db", since, within)
|
|
return got.Done, got.Words
|
|
}
|
|
if done, _ := run(time.Second,
|
|
backupEvent("n2", "db", true, since, ""), backupEvent("n1", "web", true, since, ""),
|
|
backupEvent("n1", "db", false, since.Add(-time.Hour), "an old night"),
|
|
backupEvent("n1", "db", true, since.Add(time.Second), "")); !done {
|
|
t.Error("the event of this node and module was not the answer")
|
|
}
|
|
if done, words := run(time.Second, backupEvent("n1", "db", false, since, "the repository is locked")); done ||
|
|
!strings.Contains(words, "repository is locked") {
|
|
t.Errorf("a failed backup: done=%v words=%q", done, words)
|
|
}
|
|
if done, words := run(50 * time.Millisecond); done || !strings.Contains(words, "did not say it was done") {
|
|
t.Errorf("silence within the bound: done=%v words=%q", done, words)
|
|
}
|
|
}
|