package main import ( "errors" "strings" "testing" ) // One machine that cannot be worked out is not a reason to leave the mesh unconverged. // // A whole-mesh push refused outright the moment any single node failed to resolve, so a module on // the anchor requiring a provision nobody had assigned a provider for stopped every OTHER machine // from being sent anything — machines with no relation to the fault, and nothing wrong with them. // The failure and the punishment were on different machines. // // It is the same rule an un-hostable module already follows one level down (a92c11b: one module on // the wrong machine no longer refuses the whole node), applied one level up. func TestOneUnresolvableNodeStillLetsTheRestBeSent(t *testing.T) { sending, refusals := composeEach( []string{"anchor", "home-server", "laptop"}, func(node string) ([]map[string]any, error) { if node == "anchor" { return nil, errors.New(`nothing provides "acme-ca", wanted by route-proxy`) } return []map[string]any{{"id": node + ".thing"}}, nil }) var told []string for _, s := range sending { told = append(told, s.node) } if strings.Join(told, ",") != "home-server,laptop" { t.Errorf("a machine with nothing wrong with it was not sent: %v", told) } if len(refusals) != 1 || !strings.Contains(refusals[0], "anchor") || !strings.Contains(refusals[0], "acme-ca") { t.Errorf("the machine that could not be worked out was not named with its reason: %v", refusals) } } // And a machine assigned nothing is neither sent nor a refusal — it is nothing to say. func TestAMachineAssignedNothingIsNotARefusal(t *testing.T) { sending, refusals := composeEach([]string{"spare"}, func(string) ([]map[string]any, error) { return nil, nil }) if len(sending) != 0 || len(refusals) != 0 { t.Errorf("a machine assigned nothing was treated as something: %v / %v", sending, refusals) } } // A push that skipped a machine still ends badly, and says what was sent. // // **Skipping is not succeeding.** The mesh is not in the state somebody asked for, so the command // exits non-zero — but it says how many machines it did reach, because the old message ("nothing // was sent") was the very claim that had become untrue. func TestASkippedMachineIsStillAnError(t *testing.T) { if err := couldNotBeResolved(nil, 3); err != nil { t.Fatalf("a push that resolved every machine reported a problem: %v", err) } err := couldNotBeResolved([]string{"anchor:\nnothing provides \"acme-ca\""}, 2) if err == nil { t.Fatal("a push that could not work out a machine reported success") } said := err.Error() if strings.Contains(said, "nothing was sent") { t.Errorf("the push says nothing was sent, and it sent two machines: %q", said) } for _, want := range []string{"anchor", "acme-ca", "2 other node(s) were"} { if !strings.Contains(said, want) { t.Errorf("the refusal does not say %q: %q", want, said) } } }