package bundle import ( "errors" "strings" "testing" "github.com/novox/mesh-host/internal/declaration" ) func TestADefaultBuildCarriesNothingAndSaysSo(t *testing.T) { // The important one. A host built without a bundle that applied nothing and reported // success would look exactly like a host that raised a first node — and the difference // would surface as a mesh that never came up, with nothing to point at. if !IsEmpty("arch") { t.Fatal("the default build claims to carry a substrate") } _, err := Load("arch") if !errors.Is(err, ErrEmpty) { t.Fatalf("an empty bundle did not refuse: %v", err) } if !strings.Contains(err.Error(), "would look exactly like applying something") { t.Errorf("the refusal does not say why it matters: %v", err) } } func TestABundleWithContentIsParsedByTheSameParserTheLinkWillUse(t *testing.T) { // A bundle that reaches a machine and is then refused by the host carrying it would be a // build-time mistake found at the worst possible moment. // // Comment handling itself is asserted where it now lives, in `declaration`. It was here, and // having it in two places is how it came to be *done* in two places. real := []byte(`// pinned {"declaration":1,"resources":[{"id":"d","type":"directory","path":"/etc/mesh"}]}`) parsed, err := declaration.ParseFileTrusted(real) if err != nil { t.Fatalf("an annotated bundle was refused: %v", err) } if len(parsed.Resources) != 1 { t.Fatalf("got %d resources", len(parsed.Resources)) } } func TestWhatValidatesIsWhatIsApplied(t *testing.T) { // Found on a real machine. `mesh-host bundle` validated the carried bundle through Load, // which strips comments; `reconcile` handed the RAW bytes to the parser, which does not. // So the command whose whole job is to check the bundle said yes, and the command that // uses it said no — two paths to one artefact, disagreeing. // // There is now one path. This asserts the property that made the bug possible cannot // return: whatever Load accepts is what gets applied, byte for byte. annotated := []byte("// a comment\n" + `{"declaration":1,"resources":[{"id":"d","type":"directory","path":"/etc/mesh"}]}`) if _, err := declaration.ParseFileTrusted(annotated); err != nil { t.Fatalf("an annotated bundle was refused: %v", err) } } func TestEverySystemHasABundleAndAndroidsRefuses(t *testing.T) { // The bundle's contents are per system even though its mechanism is not (novox/hq ADR // 0060), so a host must find one built for it — and a host built for a system with no // bundle at all must say that rather than behave like an empty one. for _, system := range []string{"arch", "alpine", "android"} { if _, err := Load(system); err == nil { t.Errorf("%s: a placeholder bundle loaded as if it had contents", system) } else if !errors.Is(err, ErrEmpty) { t.Errorf("%s: refused for the wrong reason: %v", system, err) } } if _, err := Load("debian"); err == nil { t.Error("a bundle was loaded for a system nobody has built") } else if errors.Is(err, ErrEmpty) { t.Error("an unbuilt system was reported as an empty bundle; those are different things") } } func TestAndroidsBundleSaysWhyThereIsNone(t *testing.T) { // Not a placeholder waiting to be filled in. An android host implements neither `package` // nor `container` nor `service`, so every step of the bootstrap is a shape it does not // have — a partial host can JOIN a mesh and cannot BE the first node. text := string(Raw("android")) for _, want := range []string{"cannot raise a mesh", "JOIN", "first node"} { if !strings.Contains(text, want) { t.Errorf("the android bundle does not explain itself; missing %q", want) } } }