carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package activator
2
3import (
4 "strings"
5 "testing"
6
7 "github.com/carlosframework/platform/internal/provision"
8 "github.com/carlosframework/platform/internal/registry"
9)
10
11func managed(host, db, sock string) registry.Route {
12 return registry.Route{Host: host, Kind: "instance", Hibernate: true, DBPath: db, Socket: sock}
13}
14
15func TestClassifyFlatAndNested(t *testing.T) {
16 in := LayoutInputs{DataDir: "/data"}
17 if l, _ := Classify(managed("h.example.com", "/data/h.example.com.db", "/run/carlos/h.example.com.sock"), in); l != LayoutFlat {
18 t.Errorf("flat row = %s", l)
19 }
20 if l, _ := Classify(managed("h.example.com", provision.NestedDBPath("/data", "h.example.com"), provision.NestedSocket("h.example.com")), in); l != LayoutNested {
21 t.Errorf("nested row = %s", l)
22 }
23 if l, r := Classify(managed("h.example.com", "/data/sub/store.db", "/run/carlos/h.example.com.sock"), in); l != LayoutForeign || !strings.Contains(r, "store.db") {
24 t.Errorf("custom row = %s %q", l, r)
25 }
26 // A nested DB with a flat socket is not nested: both columns must agree.
27 if l, _ := Classify(managed("h.example.com", provision.NestedDBPath("/data", "h.example.com"), "/run/carlos/h.example.com.sock"), in); l != LayoutForeign {
28 t.Errorf("half-migrated row = %s", l)
29 }
30}
31
32func TestClassifyFencedWinsOverEverything(t *testing.T) {
33 in := LayoutInputs{DataDir: "/data", Journal: func(h string) bool { return h == "h.example.com" }}
34 if l, r := Classify(managed("h.example.com", "/data/h.example.com.db", "/run/carlos/h.example.com.sock"), in); l != LayoutFenced || r == "" {
35 t.Errorf("fenced = %s %q", l, r)
36 }
37 if l, _ := Classify(managed("o.example.com", "/data/o.example.com.db", "/run/carlos/o.example.com.sock"), in); l != LayoutFlat {
38 t.Errorf("other host = %s", l)
39 }
40}
41
42// The identifier collision is exercised through the SameID seam rather than
43// a real hash collision: two nested rows for different hosts, SameID forced
44// to report them equal, must classify as a conflict that names the other
45// host.
46func TestClassifyConflictRefusesBothHosts(t *testing.T) {
47 long := strings.Repeat("a", 60) + ".example.com"
48 twin := strings.Repeat("a", 60) + ".example.org"
49 a := managed(long, provision.NestedDBPath("/data", long), provision.NestedSocket(long))
50 b := managed(twin, provision.NestedDBPath("/data", twin), provision.NestedSocket(twin))
51 in := LayoutInputs{DataDir: "/data", Peers: func() ([]registry.Route, error) { return []registry.Route{a, b}, nil }, SameID: func(x, y string) bool { return true }}
52 if l, r := Classify(a, in); l != LayoutConflict || !strings.Contains(r, twin) {
53 t.Errorf("conflict = %s %q", l, r)
54 }
55}
56
57func TestClassifyIgnoresUnmanagedPeers(t *testing.T) {
58 a := managed("h.example.com", "/data/h.example.com.db", "/run/carlos/h.example.com.sock")
59 ext := registry.Route{Host: "x.example.com", Kind: "instance", Hibernate: false, Socket: "/run/carlos/x.example.com.sock"}
60 in := LayoutInputs{DataDir: "/data", Peers: func() ([]registry.Route, error) { return []registry.Route{a, ext}, nil }, SameID: func(x, y string) bool { return true }}
61 if l, _ := Classify(a, in); l != LayoutFlat {
62 t.Errorf("an unmanaged peer must not conflict: %s", l)
63 }
64 if ActivatorManaged(ext) {
65 t.Error("unflagged socket route reported managed")
66 }
67}
68