package announce import ( "strings" "testing" ) // A module says on the bus which states it keeps and which of them others may read (novox/hq ADR 0495 clause 2), on its // own event subject, in a versioned value the controller keeps by module. func TestAnAnnouncementRoundTripsSortedAndSaysWhatIsReadable(t *testing.T) { data, err := Encode(States{Module: "mesh-controller", Node: "novox", States: []State{ {Name: "plans-building", Readable: true}, {Name: "assignments", Readable: true}, {Name: "own"}, {Name: "hashes", Readers: []string{"mesh-grants"}}}}) if err != nil { t.Fatal(err) } back, err := Decode(data) if err != nil { t.Fatal(err) } if back.V != Version || back.Module != "mesh-controller" || back.Node != "novox" { t.Fatalf("decoded %+v", back) } var names []string for _, s := range back.States { names = append(names, s.Name) } if strings.Join(names, ",") != "assignments,hashes,own,plans-building" { t.Fatalf("the states are not sorted: %v", names) } if !back.Readable("plans-building") || back.Readable("own") || back.Readable("absent") { t.Fatal("Readable does not say what was announced readable") } // Named readers (ADR 0547 clause 9): readable by them alone, and not readable to a composer that knows no readers. if back.Readable("hashes") || !back.ReadableBy("hashes", "mesh-grants") || back.ReadableBy("hashes", "spy") || !back.ReadableBy("plans-building", "spy") || back.ReadableBy("own", "spy") { t.Fatal("ReadableBy does not say who was named") } if !back.Keeps("own") || back.Keeps("absent") { t.Fatal("Keeps does not say what was announced") } if Subject("mesh-controller") != "mesh.mod.mesh-controller.event.states" || SubjectAll != "mesh.mod.*.event.states" { t.Fatalf("the subjects are %q and %q", Subject("mesh-controller"), SubjectAll) } if KeptBucket != "mesh-controller_states-announced" { t.Fatalf("the kept bucket is %q", KeptBucket) } if k, err := Key("mesh-delivery-builder"); err != nil || k != "mesh-delivery-builder" { t.Fatalf("Key = %q, %v", k, err) } if nothing, err := Encode(States{Module: "quiet"}); err != nil || !strings.Contains(string(nothing), `"states":[]`) { t.Fatalf("a module keeping nothing: %s, %v", nothing, err) } } func TestAnAnnouncementRefusesWhatNoBucketCouldBe(t *testing.T) { for _, c := range []struct { s States says string }{ {States{Module: ""}, "no module"}, {States{Module: "a.b"}, `"a.b"`}, {States{Module: "a", States: []State{{Name: "x_y"}}}, `"x_y"`}, {States{Module: "a", States: []State{{Name: ""}}}, `""`}, {States{Module: "a", States: []State{{Name: "x"}, {Name: "x", Readable: true}}}, "twice"}, {States{Module: "a", States: []State{{Name: "x", Readers: []string{"b.c"}}}}, `"b.c"`}, } { if _, err := Encode(c.s); err == nil || !strings.Contains(err.Error(), c.says) { t.Errorf("%+v: %v, wanted a refusal saying %s", c.s, err, c.says) } } if _, err := Decode([]byte(`{"v":2,"module":"a","states":[]}`)); err == nil { t.Error("an unknown version was read") } if _, err := Key("a.b"); err == nil { t.Error("a module with a dot became a key") } }