tinyrelayfile
tinyrelay/internal/daemon/lifecycle_test.go/

internal/daemon/lifecycle_test.go raw
1package daemon
2
3import (
4 "context"
5 "github.com/FelineStateMachine/tinyrelay/internal/event"
6 "strings"
7 "testing"
8 "time"
9)
10
11func TestServingLifecycleRecoversAndReconcilesCatalog(t *testing.T) {
12 ctx := context.Background()
13 dir := t.TempDir()
14 app, err := New(ctx, Config{DataDir: dir, DefaultTenant: "main"})
15 if err != nil {
16 t.Fatal(err)
17 }
18 owner, err := event.PublicKey(strings.Repeat("0", 63) + "1")
19 if err != nil {
20 t.Fatal(err)
21 }
22 main, err := app.Create(ctx, CreateOptions{Name: "main", Owner: owner, Template: "default"})
23 if err != nil {
24 t.Fatal(err)
25 }
26 if len(app.tenants) != 0 {
27 t.Fatal("catalog-only create started tenant workers")
28 }
29 if err := app.Start(ctx, "http://127.0.0.1:7447"); err != nil {
30 t.Fatal(err)
31 }
32 if app.tenants[main.ID].publicURL != "http://127.0.0.1:7447" {
33 t.Fatal("default relay URL lost its listener port")
34 }
35 other, err := app.Create(ctx, CreateOptions{Name: "other", Owner: owner, Template: "default"})
36 if err != nil {
37 t.Fatal(err)
38 }
39 if app.tenants[other.ID].publicURL != "http://127.0.0.1:7447/r/other" {
40 t.Fatal("new relay was not started with its tenant path")
41 }
42 second, err := New(ctx, Config{DataDir: dir})
43 if err != nil {
44 t.Fatal(err)
45 }
46 t.Cleanup(func() { _ = second.Close(ctx) })
47 if err := second.Start(ctx, "http://127.0.0.1:7448"); err == nil {
48 t.Fatal("second serving process acquired the directory")
49 }
50 old := app.tenants[other.ID]
51 if err := app.Catalog().Disable(ctx, other.ID); err != nil {
52 t.Fatal(err)
53 }
54 if err := app.reconcileTenants(ctx, "http://127.0.0.1:7447"); err != nil {
55 t.Fatal(err)
56 }
57 if old.workCtx.Err() == nil {
58 t.Fatal("disabled tenant workers still run")
59 }
60 if err := app.Close(ctx); err != nil {
61 t.Fatal(err)
62 }
63 if err := second.Start(ctx, "http://127.0.0.1:7448"); err != nil {
64 t.Fatal(err)
65 }
66 if second.tenants[main.ID] == nil || second.tenants[other.ID] != nil {
67 t.Fatal("restart did not eagerly recover exactly the ready tenants")
68 }
69 if err := second.Catalog().Enable(ctx, other.ID); err != nil {
70 t.Fatal(err)
71 }
72 deadline := time.Now().Add(3 * time.Second)
73 for time.Now().Before(deadline) {
74 second.mu.Lock()
75 loaded := second.tenants[other.ID] != nil
76 second.mu.Unlock()
77 if loaded {
78 return
79 }
80 time.Sleep(10 * time.Millisecond)
81 }
82 t.Fatal("enabled tenant did not restart through catalog reconciliation")
83}
84
85func TestProcessLockExcludesSecondServer(t *testing.T) {
86 dir := t.TempDir()
87 first, err := AcquireProcessLock(dir)
88 if err != nil {
89 t.Fatal(err)
90 }
91 defer first.Close()
92 second, err := AcquireProcessLock(dir)
93 if err == nil {
94 _ = second.Close()
95 t.Fatal("second serving process acquired the lock")
96 }
97 if second != nil {
98 t.Fatal("failed lock returned a handle")
99 }
100}
101
102func TestProcessLockCanBeReacquiredAfterClose(t *testing.T) {
103 dir := t.TempDir()
104 first, err := AcquireProcessLock(dir)
105 if err != nil {
106 t.Fatal(err)
107 }
108 if err := first.Close(); err != nil {
109 t.Fatal(err)
110 }
111 second, err := AcquireProcessLock(dir)
112 if err != nil {
113 t.Fatal(err)
114 }
115 if err := second.Close(); err != nil {
116 t.Fatal(err)
117 }
118}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs