diff --git a/go/compose/network.go b/go/compose/network.go index 0ea9d56..afc8363 100644 --- a/go/compose/network.go +++ b/go/compose/network.go @@ -242,7 +242,9 @@ func (c *composer) whereEveryoneIs() (map[string]string, error) { } // onTheNetwork is every placed machine that resolves the private network: has an address AND runs what puts it there -// (novox/hq issue 079). A machine that does not resolve is not counted, and said. +// (novox/hq issue 079). A machine that does not resolve keeps its place when it holds one (a key and an address), by the +// same rule as network(), so its name and its address stay where the tunnel to it does (issue 1833); one without is not +// counted, and said. func (c *composer) onTheNetwork() []Node { var out []Node for _, n := range c.in.sorted() { @@ -256,6 +258,12 @@ func (c *composer) onTheNetwork() []Node { catalogue.Node{Name: n.Name, Site: n.Place.Site, Capabilities: n.Capabilities}, catalogue.World{Unchecked: true, Holdings: c.in.Holdings}) if err != nil { + if n.Place.Key != "" { + c.say("%s could not be resolved and keeps its place on the private network at %s, so the others keep their path to it", + n.Name, n.Place.Address) + out = append(out, n) + continue + } c.say("%s is not counted as on the network: it does not resolve: %v", n.Name, err) continue } diff --git a/go/compose/node_test.go b/go/compose/node_test.go index b7be07a..c2485dc 100644 --- a/go/compose/node_test.go +++ b/go/compose/node_test.go @@ -387,9 +387,11 @@ func TestAnotherNodesKeptBuildDoesNotChangeTheRestOfTheMeshOrWhoIsOnTheNetwork(t func overlayName() string { return overlay.Name } -// Round 1, finding 6: the nodes the composition did not count as on the network are returned, said, not lost. +// Round 1, finding 6: the nodes the composition did not count as on the network are returned, said, not lost. laptop holds no +// complete place (no key): one that does keeps it on the network (issue 1833) and is counted. func TestANodeNotCountedAsOnTheNetworkIsSaidInTheResult(t *testing.T) { in := aMesh(t) + nodeOf(t, &in, "laptop").Place.Key = "" in.Catalogue["rival-one"] = catalogue.Manifest{Module: "rival-one", Version: "1", Claims: []catalogue.Claim{{Name: "the-seat", Scope: catalogue.ScopeNode}}} in.Catalogue["rival-two"] = catalogue.Manifest{Module: "rival-two", Version: "1", Claims: []catalogue.Claim{{Name: "the-seat", Scope: catalogue.ScopeNode}}} laptop := nodeOf(t, &in, "laptop") diff --git a/go/compose/one_machine_alone_test.go b/go/compose/one_machine_alone_test.go index 3fc89e5..aa6b4c9 100644 --- a/go/compose/one_machine_alone_test.go +++ b/go/compose/one_machine_alone_test.go @@ -1,6 +1,7 @@ package compose import ( + "slices" "strings" "testing" @@ -140,3 +141,27 @@ func TestANetworkThatCannotBeComposedFromWhatRemainsStillFails(t *testing.T) { t.Error("a declaration was composed over a network that cannot be") } } + +// 1833/AC2, a failure the composition's unchecked pass refuses too (two modules claiming one seat on the hub, the 1360/AC3 +// shape): the hub keeps its place in what every other machine is sent besides the tunnel -- its internal name and its address +// among the sources "from the mesh" -- and another machine still composes. +func TestAMachineThatDoesNotResolveKeepsItsNameAndItsAddressInTheMesh(t *testing.T) { + in := fourOnTheNetwork(t) + in.Catalogue["rival-one"] = catalogue.Manifest{Module: "rival-one", Version: "1", Claims: []catalogue.Claim{{Name: "the-seat", Scope: catalogue.ScopeNode}}} + in.Catalogue["rival-two"] = catalogue.Manifest{Module: "rival-two", Version: "1", Claims: []catalogue.Claim{{Name: "the-seat", Scope: catalogue.ScopeNode}}} + hub := nodeOf(t, &in, "anchor") + hub.Assigned = append(hub.Assigned, "rival-one", "rival-two") + if _, err := Resolve(in, "anchor"); !IsUnresolvable(err) { + t.Fatalf("the hub is meant not to resolve: %v", err) + } + c := newComposer(in) + if got := c.namesInTheMesh()["anchor."+c.suffix()]; got != "10.77.0.1" { + t.Errorf("the hub's name is not in the mesh's names: %v", c.namesInTheMesh()) + } + if got := c.onThePrivateNetwork(); !slices.Contains(got, "10.77.0.1") || len(got) != 4 { + t.Errorf("the sources from the mesh are %v, want all four machines with the hub", got) + } + if _, problems, err := Compose(in, "ace"); err != nil || len(problems) != 0 { + t.Errorf("another machine does not compose: %v %v", err, problems) + } +}