| index 3c19a51f1..1213e2fe5 100644 |
| --- a/internal/relay/masters_test.go |
| +++ b/internal/relay/masters_test.go |
| @@ -2,7 +2,10 @@ package relay |
| |
| import ( |
| "bytes" |
| + "context" |
| "encoding/base64" |
| + "os" |
| + "path/filepath" |
| "reflect" |
| "strings" |
| "testing" |
| @@ -45,3 +48,55 @@ func TestParseMastersRejectsBadLines(t *testing.T) { |
| } |
| |
| func b64(b []byte) string { return base64.StdEncoding.EncodeToString(b) } |
| + |
| +func TestWatchMastersReloadsOnChange(t *testing.T) { |
| + old := mastersPollInterval |
| + mastersPollInterval = 50 * time.Millisecond |
| + defer func() { mastersPollInterval = old }() |
| + |
| + path := filepath.Join(t.TempDir(), "relay-masters") |
| + write := func(s string) { |
| + if err := os.WriteFile(path, []byte(s), 0o600); err != nil { |
| + t.Fatal(err) |
| + } |
| + } |
| + write("k1 " + b64(bytes.Repeat([]byte{1}, 32)) + " -\n") |
| + ctx, cancel := context.WithCancel(context.Background()) |
| + defer cancel() |
| + got := make(chan []string, 4) |
| + errs := make(chan error, 4) |
| + go WatchMasters(ctx, path, func(m *Masters, err error) { |
| + if err != nil { |
| + errs <- err |
| + return |
| + } |
| + got <- m.Kids() |
| + }) |
| + select { |
| + case k := <-got: |
| + if !reflect.DeepEqual(k, []string{"k1"}) { |
| + t.Fatalf("initial kids = %v", k) |
| + } |
| + case err := <-errs: |
| + t.Fatal(err) |
| + case <-time.After(5 * time.Second): |
| + t.Fatal("no initial load") |
| + } |
| + // Make the mtime observably newer, then rewrite with a second kid. |
| + time.Sleep(20 * time.Millisecond) |
| + write("k1 " + b64(bytes.Repeat([]byte{1}, 32)) + " -\nk2 " + b64(bytes.Repeat([]byte{2}, 32)) + " -\n") |
| + future := time.Now().Add(2 * time.Second) |
| + if err := os.Chtimes(path, future, future); err != nil { |
| + t.Fatal(err) |
| + } |
| + select { |
| + case k := <-got: |
| + if !reflect.DeepEqual(k, []string{"k1", "k2"}) { |
| + t.Fatalf("reloaded kids = %v", k) |
| + } |
| + case err := <-errs: |
| + t.Fatal(err) |
| + case <-time.After(15 * time.Second): |
| + t.Fatal("no reload within three poll ticks") |
| + } |
| +} |