//go:build unix package motd import ( "os" "path/filepath" "testing" "motd-assist/internal/assets" ) func TestExecuteAppliesPlanAndRestore(t *testing.T) { root := setupDir(t, map[string]string{ "00-header": "#!/bin/sh\necho header\n", "10-sysinfo": "#!/bin/sh\necho sysinfo\n", }) dir := MotdDir(root) if err := os.Chmod(filepath.Join(dir, "10-sysinfo"), 0o644); err != nil { t.Fatal(err) } current, err := Discover(root) if err != nil { t.Fatal(err) } // Ziel: sysinfo vor header, sysinfo aktiv, header aus. desired := []DesiredEntry{ {Name: "10-sysinfo", Enabled: true}, {Name: "00-header", Enabled: false}, } plan := Diff(current, desired) if plan.Empty() { t.Fatal("Plan sollte Änderungen enthalten") } if err := Execute(root, plan); err != nil { t.Fatalf("Execute: %v", err) } after, err := Discover(root) if err != nil { t.Fatal(err) } if len(after) != 2 { t.Fatalf("nach Execute: %v", after) } if after[0].Name != "00-sysinfo" || !after[0].Enabled { t.Errorf("after[0] = %+v, want 00-sysinfo aktiv", after[0]) } if after[1].Name != "10-header" || after[1].Enabled { t.Errorf("after[1] = %+v, want 10-header inaktiv", after[1]) } if _, err := os.Stat(SnapshotPath(root)); err != nil { t.Errorf("Snapshot fehlt: %v", err) } if err := Restore(root); err != nil { t.Fatalf("Restore: %v", err) } restored, err := Discover(root) if err != nil { t.Fatal(err) } if restored[0].Name != "00-header" || !restored[0].Enabled { t.Errorf("restored[0] = %+v, want 00-header aktiv", restored[0]) } if restored[1].Name != "10-sysinfo" || restored[1].Enabled { t.Errorf("restored[1] = %+v, want 10-sysinfo inaktiv", restored[1]) } } func TestExecuteInstallAndRemove(t *testing.T) { root := setupDir(t, map[string]string{ "00-header": "#!/bin/sh\necho header\n", "95-footer": "#!/bin/sh\ntrue\n", // wird unten als gebündelt ersetzt }) dir := MotdDir(root) // echtes gebündeltes Script einsetzen, damit Remove validiert content, ok := assets.ScriptContent("footer") if !ok { t.Fatal("footer-Vorlage nicht gefunden") } if err := os.WriteFile(filepath.Join(dir, "95-footer"), []byte(content), 0o755); err != nil { t.Fatal(err) } current, err := Discover(root) if err != nil { t.Fatal(err) } desired := []DesiredEntry{ {Name: "10-brand-header", Enabled: true, Install: "brand-header"}, {Name: "00-header", Enabled: true}, {Name: "95-footer", Remove: true}, } if err := Execute(root, Diff(current, desired)); err != nil { t.Fatalf("Execute: %v", err) } after, err := Discover(root) if err != nil { t.Fatal(err) } var names []string for _, s := range after { names = append(names, s.Name) } want := []string{"00-brand-header", "10-header"} if len(names) != 2 || names[0] != want[0] || names[1] != want[1] { t.Errorf("names = %v, want %v", names, want) } if !after[0].Bundled { t.Error("brand-header sollte als gebündelt erkannt werden") } if !after[0].Enabled || !after[1].Enabled { t.Errorf("Modi falsch: %+v", after) } }