package main import ( "strings" "testing" ) func TestParseConfigFindsShares(t *testing.T) { doc, err := ParseConfig(` # comment [global] workgroup = WORKGROUP [media] path = /srv/media valid users = alice, bob guest ok = no `) if err != nil { t.Fatalf("ParseConfig() error = %v", err) } shares := doc.ShareSections() if len(shares) != 1 { t.Fatalf("expected 1 share, got %d", len(shares)) } cfg := ShareFromSection(shares[0]) if cfg.Name != "media" { t.Fatalf("expected share name media, got %q", cfg.Name) } if cfg.Path != "/srv/media" { t.Fatalf("expected path /srv/media, got %q", cfg.Path) } if strings.Join(cfg.ValidUsers, ",") != "alice,bob" { t.Fatalf("expected users alice,bob, got %v", cfg.ValidUsers) } } func TestBuildShareSectionUpdatesValues(t *testing.T) { section := &Section{ Name: "public", Lines: []Line{ {Key: "path", Value: "/old", IsKV: true}, {Key: "comment", Value: "old", IsKV: true}, }, } updated := BuildShareSection(section, ShareConfig{ Name: "public", Path: "/srv/public", Comment: "", Browseable: "yes", ReadOnly: "no", GuestOK: "yes", ValidUsers: []string{"alice"}, }) cfg := ShareFromSection(updated) if cfg.Path != "/srv/public" { t.Fatalf("expected updated path, got %q", cfg.Path) } if cfg.Comment != "" { t.Fatalf("expected comment removed, got %q", cfg.Comment) } if strings.Join(cfg.ValidUsers, ",") != "alice" { t.Fatalf("expected alice, got %v", cfg.ValidUsers) } } func TestSerializeProducesSectionHeaders(t *testing.T) { doc := &Document{ Preamble: []string{"# smb.conf"}, Sections: []*Section{ BuildShareSection(nil, ShareConfig{ Name: "docs", Path: "/srv/docs", Browseable: "yes", ReadOnly: "no", GuestOK: "no", }), }, } out := doc.Serialize() for _, want := range []string{ "# smb.conf", "[docs]", "path = /srv/docs", "browseable = yes", } { if !strings.Contains(out, want) { t.Fatalf("serialized output missing %q:\n%s", want, out) } } } func TestDetectSambaInstallPlanPrefersApt(t *testing.T) { lookPath := func(file string) (string, error) { switch file { case "apt-get", "sudo": return "/usr/bin/" + file, nil default: return "", execErr(file) } } plan, ok := DetectSambaInstallPlan(lookPath, false) if !ok { t.Fatalf("expected install plan") } if plan.ManagerName != "apt" { t.Fatalf("expected apt manager, got %q", plan.ManagerName) } if plan.DisplayCommand() != "sudo sh -c apt-get update && apt-get install -y samba" { t.Fatalf("unexpected command: %q", plan.DisplayCommand()) } } func TestDetectSambaInstallPlanWithoutSudo(t *testing.T) { lookPath := func(file string) (string, error) { switch file { case "pacman": return "/usr/bin/pacman", nil default: return "", execErr(file) } } plan, ok := DetectSambaInstallPlan(lookPath, false) if !ok { t.Fatalf("expected install plan") } if plan.DisplayCommand() != "pacman -Sy --noconfirm samba" { t.Fatalf("unexpected command: %q", plan.DisplayCommand()) } } func TestShareUserReferences(t *testing.T) { doc := &Document{ Sections: []*Section{ BuildShareSection(nil, ShareConfig{ Name: "media", Path: "/srv/media", ValidUsers: []string{"alice", "bob"}, }), BuildShareSection(nil, ShareConfig{ Name: "photos", Path: "/srv/photos", ValidUsers: []string{"alice"}, }), }, } refs := shareUserReferences(doc) if len(refs) != 2 { t.Fatalf("expected 2 refs, got %d", len(refs)) } if refs[0].User != "alice" || strings.Join(refs[0].Shares, ",") != "media,photos" { t.Fatalf("unexpected first ref: %+v", refs[0]) } if refs[1].User != "bob" || strings.Join(refs[1].Shares, ",") != "media" { t.Fatalf("unexpected second ref: %+v", refs[1]) } } func TestUnusedAccountCandidates(t *testing.T) { entries := []PasswdEntry{ {Name: "alice", UID: 1001, Shell: "/usr/sbin/nologin"}, {Name: "bob", UID: 1002, Shell: "/bin/bash"}, {Name: "daemon", UID: 1, Shell: "/usr/sbin/nologin"}, {Name: "carol", UID: 1003, Shell: "/bin/false"}, } active := map[string]struct{}{ "alice": {}, } candidates := unusedAccountCandidates(entries, active) if len(candidates) != 1 { t.Fatalf("expected 1 candidate, got %d", len(candidates)) } if candidates[0].Name != "carol" { t.Fatalf("unexpected candidate: %+v", candidates[0]) } } func TestBuildFstabLine(t *testing.T) { line := buildFstabLine(CIFSMountConfig{ Server: "fileserver", Share: "media", MountPoint: "/mnt/media", Username: "alice", Password: "p@ ss,word", UID: "1000", GID: "1000", FileMode: "0664", DirMode: "0775", AutoMount: true, ReadOnly: false, }) want := "//fileserver/media /mnt/media cifs username=alice,password=p@\\040ss\\,word,iocharset=utf8,uid=1000,gid=1000,file_mode=0664,dir_mode=0775,rw 0 0" if line != want { t.Fatalf("unexpected fstab line:\nwant: %s\ngot: %s", want, line) } } type execErr string func (e execErr) Error() string { return "not found: " + string(e) }