From 6a28c56be5ea5f8015d06c13794837158b72cc0d Mon Sep 17 00:00:00 2001 From: Tulip Blossom Date: Mon, 16 Dec 2024 02:38:59 -0300 Subject: [PATCH] feat(testing): add basic tests for most modules --- cmd/update.go | 6 +-- drv/brew/brew_test.go | 35 +++++++++++++++ drv/distrobox/distrobox.go | 7 +-- drv/distrobox/distrobox_test.go | 56 ++++++++++++++++++++++++ drv/flatpak/flatpak.go | 7 +-- drv/flatpak/flatpak_test.go | 56 ++++++++++++++++++++++++ drv/generic/generic.go | 13 ++---- drv/generic/generic_test.go | 21 +++++++++ drv/rpmostree/rpmostree.go | 19 +++------ drv/rpmostree/rpmostree_test.go | 35 +++++++++++++++ drv/system/system.go | 7 +-- justfile | 18 ++++++-- pkg/filelock/filelock.go | 6 +-- pkg/percent/incrementer.go | 29 +++++++++++++ pkg/percent/incrementer_test.go | 52 +++++++++++++++++++++++ pkg/percent/progressmanager.go | 31 +------------- pkg/session/session.go | 58 +++++++++++++------------ pkg/session/session_test.go | 75 +++++++++++++++++++++++++++++++++ 18 files changed, 422 insertions(+), 109 deletions(-) create mode 100644 drv/brew/brew_test.go create mode 100644 drv/distrobox/distrobox_test.go create mode 100644 drv/flatpak/flatpak_test.go create mode 100644 drv/rpmostree/rpmostree_test.go create mode 100644 pkg/percent/incrementer.go create mode 100644 pkg/percent/incrementer_test.go create mode 100644 pkg/session/session_test.go diff --git a/cmd/update.go b/cmd/update.go index 28ede9d..055efad 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -84,7 +84,7 @@ func Update(cmd *cobra.Command, args []string) { distroboxUpdater.Config.Enabled = err == nil distroboxUpdater.SetUsers(users) - mainSystemDriver, mainSystemDriverConfig, _, err := system.InitializeSystemDriver(*initConfiguration) + mainSystemDriver, mainSystemDriverConfig, _, _ := system.InitializeSystemDriver(*initConfiguration) enableUpd, err := mainSystemDriver.Check() if err != nil { @@ -137,7 +137,7 @@ func Update(cmd *cobra.Command, args []string) { if systemOutdated { const OUTDATED_WARNING = "There hasn't been an update in over a month. Consider rebooting or running updates manually" - err := session.Notify("System Warning", OUTDATED_WARNING) + err := session.Notify(users, "System Warning", OUTDATED_WARNING) if err != nil { slog.Error("Failed showing warning notification") } @@ -167,7 +167,6 @@ func Update(cmd *cobra.Command, args []string) { if flatpakUpdater.Config.Enabled { slog.Debug(fmt.Sprintf("%s module", flatpakUpdater.Config.Title), slog.String("module_name", flatpakUpdater.Config.Title), slog.Any("module_configuration", flatpakUpdater.Config)) - percent.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, percent.TrackerMessage{Title: flatpakUpdater.Config.Title, Description: flatpakUpdater.Config.Description}) var out *[]drv.CommandOutput out, err = flatpakUpdater.Update() outputs = append(outputs, *out...) @@ -176,7 +175,6 @@ func Update(cmd *cobra.Command, args []string) { if distroboxUpdater.Config.Enabled { slog.Debug(fmt.Sprintf("%s module", distroboxUpdater.Config.Title), slog.String("module_name", distroboxUpdater.Config.Title), slog.Any("module_configuration", distroboxUpdater.Config)) - percent.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, percent.TrackerMessage{Title: distroboxUpdater.Config.Title, Description: distroboxUpdater.Config.Description}) var out *[]drv.CommandOutput out, err = distroboxUpdater.Update() outputs = append(outputs, *out...) diff --git a/drv/brew/brew_test.go b/drv/brew/brew_test.go new file mode 100644 index 0000000..d622250 --- /dev/null +++ b/drv/brew/brew_test.go @@ -0,0 +1,35 @@ +package brew_test + +import ( + "testing" + + "github.com/ublue-os/uupd/drv/brew" + "github.com/ublue-os/uupd/drv/generic" + appLogging "github.com/ublue-os/uupd/pkg/logging" +) + +func InitBaseConfig() brew.BrewUpdater { + var initConfiguration = generic.UpdaterInitConfiguration{ + DryRun: false, + Ci: false, + Verbose: false, + Environment: nil, + Logger: appLogging.NewMuteLogger(), + } + driv, _ := brew.BrewUpdater{}.New(initConfiguration) + return driv +} + +func TestProperSteps(t *testing.T) { + brewUpdater := InitBaseConfig() + brewUpdater.Config.Enabled = false + + if brewUpdater.Steps() != 0 { + t.Fatalf("Expected no steps when module is disabled") + } + + brewUpdater.Config.Enabled = true + if brewUpdater.Steps() == 0 { + t.Fatalf("Expected steps to be added") + } +} diff --git a/drv/distrobox/distrobox.go b/drv/distrobox/distrobox.go index 213d6ac..85818ed 100644 --- a/drv/distrobox/distrobox.go +++ b/drv/distrobox/distrobox.go @@ -43,12 +43,7 @@ func (up DistroboxUpdater) New(config UpdaterInitConfiguration) (DistroboxUpdate up.usersEnabled = false up.Tracker = nil - binaryPath, exists := up.Config.Environment["UUPD_DISTROBOX_BINARY"] - if !exists || binaryPath == "" { - up.binaryPath = "/usr/bin/distrobox" - } else { - up.binaryPath = binaryPath - } + up.binaryPath = EnvOrFallback(up.Config.Environment, "UUPD_DISTROBOX_BINARY", "/usr/bin/distrobox") return up, nil } diff --git a/drv/distrobox/distrobox_test.go b/drv/distrobox/distrobox_test.go new file mode 100644 index 0000000..77d3b27 --- /dev/null +++ b/drv/distrobox/distrobox_test.go @@ -0,0 +1,56 @@ +package distrobox_test + +import ( + "log" + "testing" + + "github.com/ublue-os/uupd/drv/distrobox" + "github.com/ublue-os/uupd/drv/generic" + appLogging "github.com/ublue-os/uupd/pkg/logging" + "github.com/ublue-os/uupd/pkg/session" +) + +func InitBaseConfig() distrobox.DistroboxUpdater { + var initConfiguration = generic.UpdaterInitConfiguration{ + DryRun: false, + Ci: false, + Verbose: false, + Environment: nil, + Logger: appLogging.NewMuteLogger(), + } + driv, _ := distrobox.DistroboxUpdater{}.New(initConfiguration) + return driv +} + +func TestProperSteps(t *testing.T) { + updater := InitBaseConfig() + updater.Config.Enabled = false + + if updater.Steps() != 0 { + t.Fatalf("Expected no steps when module is disabled") + } + + updater.Config.Enabled = true + if updater.Steps() == 0 { + t.Fatalf("Expected steps to be added") + } +} + +func TestProperUserSteps(t *testing.T) { + updater := InitBaseConfig() + + mockUser := []session.User{ + {UID: 0, Name: "root"}, + {UID: 1, Name: "roote"}, + {UID: 2, Name: "rooto"}, + } + updater.SetUsers(mockUser) + + if reported := updater.Steps(); reported != 1+len(mockUser) { + log.Fatalf("Incorrect number of steps for users: %d", reported) + } + updater.Config.Enabled = false + if reported := updater.Steps(); reported != 0 { + log.Fatalf("Incorrect number of steps for users: %d", reported) + } +} diff --git a/drv/flatpak/flatpak.go b/drv/flatpak/flatpak.go index e8cc311..3a99c56 100644 --- a/drv/flatpak/flatpak.go +++ b/drv/flatpak/flatpak.go @@ -44,12 +44,7 @@ func (up FlatpakUpdater) New(config UpdaterInitConfiguration) (FlatpakUpdater, e up.usersEnabled = false up.Tracker = nil - binaryPath, exists := up.Config.Environment["UUPD_FLATPAK_BINARY"] - if !exists || binaryPath == "" { - up.binaryPath = "/usr/bin/flatpak" - } else { - up.binaryPath = binaryPath - } + up.binaryPath = EnvOrFallback(up.Config.Environment, "UUPD_FLATPAK_BINARY", "/usr/bin/flatpak") return up, nil } diff --git a/drv/flatpak/flatpak_test.go b/drv/flatpak/flatpak_test.go new file mode 100644 index 0000000..6974b6f --- /dev/null +++ b/drv/flatpak/flatpak_test.go @@ -0,0 +1,56 @@ +package flatpak_test + +import ( + "log" + "testing" + + "github.com/ublue-os/uupd/drv/flatpak" + "github.com/ublue-os/uupd/drv/generic" + appLogging "github.com/ublue-os/uupd/pkg/logging" + "github.com/ublue-os/uupd/pkg/session" +) + +func InitBaseConfig() flatpak.FlatpakUpdater { + var initConfiguration = generic.UpdaterInitConfiguration{ + DryRun: false, + Ci: false, + Verbose: false, + Environment: nil, + Logger: appLogging.NewMuteLogger(), + } + driv, _ := flatpak.FlatpakUpdater{}.New(initConfiguration) + return driv +} + +func TestProperSteps(t *testing.T) { + updater := InitBaseConfig() + updater.Config.Enabled = false + + if updater.Steps() != 0 { + t.Fatalf("Expected no steps when module is disabled") + } + + updater.Config.Enabled = true + if updater.Steps() == 0 { + t.Fatalf("Expected steps to be added") + } +} + +func TestProperUserSteps(t *testing.T) { + updater := InitBaseConfig() + + mockUser := []session.User{ + {UID: 0, Name: "root"}, + {UID: 1, Name: "roote"}, + {UID: 2, Name: "rooto"}, + } + updater.SetUsers(mockUser) + + if reported := updater.Steps(); reported != 1+len(mockUser) { + log.Fatalf("Incorrect number of steps for users: %d", reported) + } + updater.Config.Enabled = false + if reported := updater.Steps(); reported != 0 { + log.Fatalf("Incorrect number of steps for users: %d", reported) + } +} diff --git a/drv/generic/generic.go b/drv/generic/generic.go index 73f36f5..e885f48 100644 --- a/drv/generic/generic.go +++ b/drv/generic/generic.go @@ -28,11 +28,11 @@ func EnvOrFallback(environment EnvironmentMap, key string, fallback string) stri return fallback } -func GetEnvironment(data []string, getkeyval func(item string) (key, val string)) map[string]string { +func GetEnvironment(data []string) map[string]string { items := make(map[string]string) for _, item := range data { - key, val := getkeyval(item) - items[key] = val + splits := strings.Split(item, "=") + items[splits[0]] = splits[1] } return items } @@ -40,12 +40,7 @@ func GetEnvironment(data []string, getkeyval func(item string) (key, val string) func (up UpdaterInitConfiguration) New() *UpdaterInitConfiguration { up.DryRun = false up.Ci = false - up.Environment = GetEnvironment(os.Environ(), func(item string) (key, val string) { - splits := strings.Split(item, "=") - key = splits[0] - val = splits[1] - return - }) + up.Environment = GetEnvironment(os.Environ()) up.Logger = slog.Default() return &up diff --git a/drv/generic/generic_test.go b/drv/generic/generic_test.go index 94d45fb..e07b3d2 100644 --- a/drv/generic/generic_test.go +++ b/drv/generic/generic_test.go @@ -1,6 +1,7 @@ package generic_test import ( + "log" "testing" "github.com/ublue-os/uupd/drv/generic" @@ -17,3 +18,23 @@ func TestFallBack(t *testing.T) { t.Fatalf("Getting the fallback fails, %s", value) } } + +func TestProperEnvironment(t *testing.T) { + valuesExpected := map[string]string{ + "SIGMA": "true", + "CHUD": "false", + "AMOGUS": "sus", + "NOTHING": "", + } + + for key, value := range valuesExpected { + testmap := generic.GetEnvironment([]string{key + "=" + value}) + valuegot, exists := testmap[key] + if !exists { + log.Fatalf("Could not get environment variable at all: %s", key) + } + if valuegot != value { + log.Fatalf("Value gotten from variable was not expected: Got %s, Expected %s", valuegot, value) + } + } +} diff --git a/drv/rpmostree/rpmostree.go b/drv/rpmostree/rpmostree.go index e401a0a..637b786 100644 --- a/drv/rpmostree/rpmostree.go +++ b/drv/rpmostree/rpmostree.go @@ -25,11 +25,15 @@ type RpmOstreeUpdater struct { BinaryPath string } +// Checks if it is at least a month old considering how that works +func IsOutdatedOneMonthTimestamp(current time.Time, target time.Time) bool { + return target.Before(current.AddDate(0, -1, 0)) +} + func (up RpmOstreeUpdater) Outdated() (bool, error) { if up.Config.DryRun { return false, nil } - oneMonthAgo := time.Now().AddDate(0, -1, 0) var timestamp time.Time cmd := exec.Command(up.BinaryPath, "status", "--json", "--booted") @@ -44,7 +48,7 @@ func (up RpmOstreeUpdater) Outdated() (bool, error) { } timestamp = time.Unix(status.Deployments[0].Timestamp, 0).UTC() - return timestamp.Before(oneMonthAgo), nil + return IsOutdatedOneMonthTimestamp(time.Now(), timestamp), nil } func (up RpmOstreeUpdater) Update() (*[]CommandOutput, error) { @@ -77,16 +81,7 @@ func (up RpmOstreeUpdater) New(config UpdaterInitConfiguration) (RpmOstreeUpdate Environment: config.Environment, } up.Config.Logger = config.Logger.With(slog.String("module", strings.ToLower(up.Config.Title))) - if up.Config.DryRun { - return up, nil - } - - binaryPath, exists := up.Config.Environment["UUPD_RPMOSTREE_BINARY"] - if !exists || binaryPath == "" { - up.BinaryPath = "/usr/bin/rpm-ostree" - } else { - up.BinaryPath = binaryPath - } + up.BinaryPath = EnvOrFallback(up.Config.Environment, "UUPD_RPMOSTREE_BINARY", "/usr/bin/rpm-ostree") return up, nil } diff --git a/drv/rpmostree/rpmostree_test.go b/drv/rpmostree/rpmostree_test.go new file mode 100644 index 0000000..56c1522 --- /dev/null +++ b/drv/rpmostree/rpmostree_test.go @@ -0,0 +1,35 @@ +package rpmostree_test + +import ( + "testing" + + "github.com/ublue-os/uupd/drv/generic" + "github.com/ublue-os/uupd/drv/rpmostree" + appLogging "github.com/ublue-os/uupd/pkg/logging" +) + +func InitBaseConfig() rpmostree.RpmOstreeUpdater { + var initConfiguration = generic.UpdaterInitConfiguration{ + DryRun: false, + Ci: false, + Verbose: false, + Environment: nil, + Logger: appLogging.NewMuteLogger(), + } + driv, _ := rpmostree.RpmOstreeUpdater{}.New(initConfiguration) + return driv +} + +func TestProperSteps(t *testing.T) { + rpmostreeUpdater := InitBaseConfig() + rpmostreeUpdater.Config.Enabled = false + + if rpmostreeUpdater.Steps() != 0 { + t.Fatalf("Expected no steps when module is disabled") + } + + rpmostreeUpdater.Config.Enabled = true + if rpmostreeUpdater.Steps() == 0 { + t.Fatalf("Expected steps to be added") + } +} diff --git a/drv/system/system.go b/drv/system/system.go index a12a604..55649c3 100644 --- a/drv/system/system.go +++ b/drv/system/system.go @@ -43,11 +43,6 @@ type SystemUpdater struct { BinaryPath string } -// Checks if it is at least a month old considering how that works -func IsOutdatedOneMonthTimestamp(current time.Time, target time.Time) bool { - return target.Before(current.AddDate(0, -1, 0)) -} - func (up SystemUpdater) Outdated() (bool, error) { if up.Config.DryRun { return false, nil @@ -69,7 +64,7 @@ func (up SystemUpdater) Outdated() (bool, error) { if err != nil { return false, nil } - return IsOutdatedOneMonthTimestamp(time.Now(), timestamp), nil + return rpmostree.IsOutdatedOneMonthTimestamp(time.Now(), timestamp), nil } func (up SystemUpdater) Update() (*[]CommandOutput, error) { diff --git a/justfile b/justfile index dea3859..f66e4f4 100644 --- a/justfile +++ b/justfile @@ -77,10 +77,20 @@ lint: release: goreleaser -test: - go test -v -cover ./... +test directory="": + #!/usr/bin/env bash + if [ "{{directory}}" != "" ] ; then + go test -v -cover ./{{directory}}/... + else + go test -v -cover ./... + fi -test-interactive: +test-coverage directory="": #!/usr/bin/env bash t="/tmp/go-cover.$$.tmp" - go test -v -coverprofile=$t ./... $@ && go tool cover -html=$t && unlink $t + + if [ "{{directory}}" != "" ] ; then + go test -v -coverprofile=$t ./{{directory}}/... $@ && go tool cover -html=$t && unlink $t + else + go test -v -coverprofile=$t ./... $@ && go tool cover -html=$t && unlink $t + fi diff --git a/pkg/filelock/filelock.go b/pkg/filelock/filelock.go index a9ffe76..3300a53 100644 --- a/pkg/filelock/filelock.go +++ b/pkg/filelock/filelock.go @@ -21,11 +21,7 @@ func GetDefaultLockfile() string { } func OpenLockfile(filepath string) (*os.File, error) { - file, err := os.OpenFile(filepath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666) - if err != nil { - return nil, err - } - return file, err + return os.OpenFile(filepath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666) } type TimeoutConfig struct { diff --git a/pkg/percent/incrementer.go b/pkg/percent/incrementer.go new file mode 100644 index 0000000..ebbf36f --- /dev/null +++ b/pkg/percent/incrementer.go @@ -0,0 +1,29 @@ +package percent + +import "github.com/jedib0t/go-pretty/v6/progress" + +type Incrementer struct { + DoneIncrements int + MaxIncrements int +} + +type IncrementTracker struct { + Tracker *progress.Tracker + Incrementer *Incrementer +} + +func (it *IncrementTracker) IncrementSection(err error) { + if int64(it.Incrementer.DoneIncrements)+int64(1) > int64(it.Incrementer.MaxIncrements) { + return + } + it.Incrementer.DoneIncrements += 1 + if err == nil { + it.Tracker.Increment(1) + } else { + it.Tracker.IncrementWithError(1) + } +} + +func (it *IncrementTracker) CurrentStep() int { + return it.Incrementer.DoneIncrements +} diff --git a/pkg/percent/incrementer_test.go b/pkg/percent/incrementer_test.go new file mode 100644 index 0000000..954f430 --- /dev/null +++ b/pkg/percent/incrementer_test.go @@ -0,0 +1,52 @@ +package percent_test + +import ( + "math" + "testing" + + "github.com/jedib0t/go-pretty/v6/progress" + "github.com/ublue-os/uupd/pkg/percent" +) + +func InitIncrementer(max int) percent.IncrementTracker { + tracker := progress.Tracker{Message: "Updating", Units: progress.UnitsDefault, Total: int64(max)} + incrementer := percent.Incrementer{ + MaxIncrements: max, + DoneIncrements: 0, + } + return percent.IncrementTracker{ + Tracker: &tracker, + Incrementer: &incrementer, + } +} + +func TestOverflow(t *testing.T) { + max := 3 + tracker := InitIncrementer(max) + + iter := 0 + for iter < max { + tracker.IncrementSection(nil) + iter++ + } + // +1 so that it overflows + tracker.IncrementSection(nil) + + if tracker.CurrentStep() > max { + t.Fatalf("Incremented with overflow. Expected: %d, Got: %d", max, tracker.CurrentStep()) + } +} + +func TestProperIncrement(t *testing.T) { + num := math.MaxInt8 + tracker := InitIncrementer(num) + + iter := 0 + for iter < num { + if tracker.CurrentStep() != iter { + t.Fatalf("Misstep increment. Expected: %d, Got: %d", iter, tracker.CurrentStep()) + } + tracker.IncrementSection(nil) + iter++ + } +} diff --git a/pkg/percent/progressmanager.go b/pkg/percent/progressmanager.go index d85aee2..ab945a1 100644 --- a/pkg/percent/progressmanager.go +++ b/pkg/percent/progressmanager.go @@ -14,16 +14,6 @@ import ( "github.com/ublue-os/uupd/pkg/session" ) -type Incrementer struct { - doneIncrements int - MaxIncrements int -} - -type IncrementTracker struct { - Tracker *progress.Tracker - incrementer *Incrementer -} - var CuteColors = progress.StyleColors{ Message: text.Colors{text.FgWhite}, Error: text.Colors{text.FgRed}, @@ -100,7 +90,7 @@ func NewProgressWriter() progress.Writer { func NewIncrementTracker(tracker *progress.Tracker, max_increments int) *IncrementTracker { return &IncrementTracker{ Tracker: tracker, - incrementer: &Incrementer{MaxIncrements: max_increments}, + Incrementer: &Incrementer{MaxIncrements: max_increments}, } } @@ -126,25 +116,6 @@ func ChangeTrackerMessageFancy(writer progress.Writer, tracker *IncrementTracker tracker.Tracker.UpdateMessage(finalMessage) } -func (it *IncrementTracker) IncrementSection(err error) { - var increment_step float64 - if it.incrementer.doneIncrements == 0 { - increment_step = 1 - } else { - increment_step = float64(it.Tracker.Total / int64(it.incrementer.MaxIncrements)) - } - if err == nil { - it.Tracker.Increment(int64(increment_step)) - } else { - it.Tracker.IncrementWithError(int64(increment_step)) - } - it.incrementer.doneIncrements++ -} - -func (it *IncrementTracker) CurrentStep() int { - return it.incrementer.doneIncrements -} - func ResetOscProgress() { // OSC escape sequence to reset all previous OSC progress hints to 0%. // Documentation is on https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC diff --git a/pkg/session/session.go b/pkg/session/session.go index bbc5c1f..5f9bacc 100644 --- a/pkg/session/session.go +++ b/pkg/session/session.go @@ -2,6 +2,7 @@ package session import ( "bufio" + "context" "fmt" "io" "log/slog" @@ -26,13 +27,17 @@ func RunLog(logger *slog.Logger, level slog.Level, command *exec.Cmd) ([]byte, e stderr, _ := command.StderrPipe() multiReader := io.MultiReader(stdout, stderr) - command.Start() + if err := command.Wait(); err != nil { + logger.Warn("Error occoured starting external command", slog.Any("error", err)) + } scanner := bufio.NewScanner(multiReader) scanner.Split(bufio.ScanLines) for scanner.Scan() { - logger.With(slog.Bool("subcommand", true)).Log(nil, level, scanner.Text()) + logger.With(slog.Bool("subcommand", true)).Log(context.TODO(), level, scanner.Text()) + } + if err := command.Wait(); err != nil { + logger.Warn("Error occoured while waiting for external command", slog.Any("error", err)) } - command.Wait() return scanner.Bytes(), scanner.Err() } @@ -56,6 +61,23 @@ func RunUID(logger *slog.Logger, level slog.Level, uid int, command []string, en return RunLog(logger, level, cmd) } +func ParseUserFromVariant(uidVariant dbus.Variant, nameVariant dbus.Variant) (User, error) { + uid, ok := uidVariant.Value().(uint32) + if !ok { + return User{}, fmt.Errorf("invalid UID type, expected uint32") + } + + name, ok := nameVariant.Value().(string) + if !ok { + return User{}, fmt.Errorf("invalid Name type, expected string") + } + + return User{ + UID: int(uid), + Name: name, + }, nil +} + func ListUsers() ([]User, error) { conn, err := dbus.SystemBus() if err != nil { @@ -72,38 +94,20 @@ func ListUsers() ([]User, error) { var users []User for _, data := range resp { - if len(data) < 2 { - return []User{}, fmt.Errorf("Malformed dbus response") - } - uidVariant := data[0] - nameVariant := data[1] - - uid, ok := uidVariant.Value().(uint32) - if !ok { - return []User{}, fmt.Errorf("invalid UID type, expected uint32") + parsed, err := ParseUserFromVariant(data[0], data[1]) + if err != nil { + return nil, err } - name, ok := nameVariant.Value().(string) - if !ok { - return []User{}, fmt.Errorf("invalid Name type, expected string") - } - - users = append(users, User{ - UID: int(uid), - Name: name, - }) + users = append(users, parsed) } return users, nil } -func Notify(summary string, body string) error { - users, err := ListUsers() - if err != nil { - return err - } +func Notify(users []User, summary string, body string) error { for _, user := range users { // we don't care if these exit - _, _ = RunUID(slog.Default(), slog.LevelDebug, user.UID, []string{"/usr/bin/notify-send", "--app-name", "uupd", summary, body}, nil) + _, _ = RunUID(nil, slog.LevelDebug, user.UID, []string{"/usr/bin/notify-send", "--app-name", "uupd", summary, body}, nil) } return nil } diff --git a/pkg/session/session_test.go b/pkg/session/session_test.go new file mode 100644 index 0000000..68935c8 --- /dev/null +++ b/pkg/session/session_test.go @@ -0,0 +1,75 @@ +package session_test + +import ( + "fmt" + "math" + "testing" + + "github.com/godbus/dbus/v5" + "github.com/ublue-os/uupd/pkg/session" +) + +func TestUserParsingInvalidUID(t *testing.T) { + t.Parallel() + testVariants := []dbus.Variant{ + dbus.MakeVariant(0.3), + dbus.MakeVariant(-1), + dbus.MakeVariant(math.MaxInt), + dbus.MakeVariant(math.MinInt), + } + + userName := dbus.MakeVariant("root") + for _, uidVariant := range testVariants { + t.Run(fmt.Sprintf("variant: %v", uidVariant.Value()), func(t *testing.T) { + t.Parallel() + _, err := session.ParseUserFromVariant(uidVariant, userName) + if err == nil { + t.Fatalf("Parser accepted invalid input: %v %v", uidVariant, userName) + } + }) + } +} + +func TestUserParsingInvalidName(t *testing.T) { + t.Parallel() + testVariants := []dbus.Variant{ + dbus.MakeVariant(0.3), + dbus.MakeVariant(-1), + dbus.MakeVariant(math.MaxInt), + dbus.MakeVariant(math.MinInt), + } + + uidVariant := dbus.MakeVariant(uint32(0)) + for _, nameVariant := range testVariants { + t.Run(fmt.Sprintf("variant: %v", uidVariant.Value()), func(t *testing.T) { + t.Parallel() + _, err := session.ParseUserFromVariant(uidVariant, nameVariant) + if err == nil { + t.Fatalf("Parser accepted invalid input: %v", err) + } + }) + } +} + +func TestUserParsingValidUser(t *testing.T) { + t.Parallel() + testVariants := []struct { + UidVariant dbus.Variant + NameVariant dbus.Variant + }{ + {dbus.MakeVariant(uint32(0)), dbus.MakeVariant("root")}, + {dbus.MakeVariant(uint32(10)), dbus.MakeVariant("bob")}, + {dbus.MakeVariant(uint32(20)), dbus.MakeVariant("beatryz")}, + {dbus.MakeVariant(uint32(math.MaxUint16)), dbus.MakeVariant("zorg_the_destroyer")}, + } + + for _, variant := range testVariants { + t.Run(fmt.Sprintf("variant: %v", variant.NameVariant.Value()), func(t *testing.T) { + t.Parallel() + _, err := session.ParseUserFromVariant(variant.UidVariant, variant.NameVariant) + if err != nil { + t.Fatalf("Parser rejected valid input: %v", err) + } + }) + } +}