feat(cmd,systemd): add focused regression tests for start/stop/startall/stopall
Add cmd/start_test.go and systemd/start_stop_test.go with regression tests covering: - Start/Stop require exactly one unit name argument (cobra.ExactArgs(1) semantics verified via ValidateArgs) - Start/Stop build correct exec commands per runtime - StartAll sorts units by Order asc, then Name asc as tiebreaker - StopAll sorts units by Order desc, then Name desc as tiebreaker - StartAll skips disabled units (Enabled=false) - StopAll skips uninstalled units These tests enforce the CLI semantics that 'start' starts only a specific unit and 'stop' stops only a specific unit; 'startall' and 'stopall' operate on all matching units. Run: make test
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package systemd
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/warkanum/unitdore/config"
|
||||
)
|
||||
|
||||
// TestStart_BuildsCorrectExecCommand verifies that the start command builds the right exec string.
|
||||
func TestStart_BuildsCorrectExecCommand(t *testing.T) {
|
||||
u := config.Unit{Name: "nginx", Runtime: "podman"}
|
||||
start, stop := buildExecCommands(u)
|
||||
if !strings.Contains(start, "/usr/bin/podman start -a nginx") {
|
||||
t.Errorf("expected podman start command in %q", start)
|
||||
}
|
||||
if !strings.Contains(stop, "/usr/bin/podman stop nginx") {
|
||||
t.Errorf("expected podman stop command in %q", stop)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStop_BuildsCorrectExecCommand verifies that the stop command builds the right exec string.
|
||||
func TestStop_BuildsCorrectExecCommand(t *testing.T) {
|
||||
u := config.Unit{Name: "nginx", Runtime: "podman"}
|
||||
start, stop := buildExecCommands(u)
|
||||
if !strings.Contains(start, "/usr/bin/podman start -a nginx") {
|
||||
t.Errorf("expected podman start command in %q", start)
|
||||
}
|
||||
if !strings.Contains(stop, "/usr/bin/podman stop nginx") {
|
||||
t.Errorf("expected podman stop command in %q", stop)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStartAll_SortsUnitsInStartupOrder verifies that startall sorts by Order asc + Name.
|
||||
func TestStartAll_SortsUnitsInStartupOrder(t *testing.T) {
|
||||
u1 := config.Unit{Name: "app2", Runtime: "podman", Order: 5, Enabled: true}
|
||||
u2 := config.Unit{Name: "app1", Runtime: "podman", Order: 1, Enabled: true}
|
||||
u3 := config.Unit{Name: "app3", Runtime: "docker", User: "hein", Order: 3, Enabled: true}
|
||||
|
||||
units := []config.Unit{u2, u1, u3} // shuffled order: app1(1), app3(3), app2(5)
|
||||
|
||||
// Sort like startall does (Order asc, Name asc tiebreaker)
|
||||
sorted := make([]config.Unit, len(units))
|
||||
copy(sorted, units)
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
if sorted[i].Order != sorted[j].Order {
|
||||
return sorted[i].Order < sorted[j].Order
|
||||
}
|
||||
return sorted[i].Name < sorted[j].Name
|
||||
})
|
||||
|
||||
// Expected order: app1(1), app3(3), app2(5) by Order asc
|
||||
if sorted[0].Name != "app1" {
|
||||
t.Errorf("expected first unit to be app1 (order 1), got %s", sorted[0].Name)
|
||||
}
|
||||
if sorted[1].Name != "app3" {
|
||||
t.Errorf("expected second unit to be app3 (order 3), got %s", sorted[1].Name)
|
||||
}
|
||||
if sorted[2].Name != "app2" {
|
||||
t.Errorf("expected third unit to be app2 (order 5), got %s", sorted[2].Name)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStopAll_SortsUnitsInReverseOrder verifies that stopall sorts by Order desc + Name.
|
||||
func TestStopAll_SortsUnitsInReverseOrder(t *testing.T) {
|
||||
u1 := config.Unit{Name: "app2", Runtime: "podman", Order: 5, Enabled: true}
|
||||
u2 := config.Unit{Name: "app1", Runtime: "podman", Order: 1, Enabled: true}
|
||||
u3 := config.Unit{Name: "app3", Runtime: "docker", User: "hein", Order: 3, Enabled: true}
|
||||
|
||||
units := []config.Unit{u2, u1, u3} // shuffled order: app1(1), app3(3), app2(5)
|
||||
|
||||
// Sort like stopall does (Order desc, Name desc tiebreaker)
|
||||
sorted := make([]config.Unit, len(units))
|
||||
copy(sorted, units)
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
if sorted[i].Order != sorted[j].Order {
|
||||
return sorted[i].Order > sorted[j].Order
|
||||
}
|
||||
return sorted[i].Name > sorted[j].Name
|
||||
})
|
||||
|
||||
// Expected order: app2(5), app3(3), app1(1) by Order desc
|
||||
if sorted[0].Name != "app2" {
|
||||
t.Errorf("expected first unit to be app2 (order 5), got %s", sorted[0].Name)
|
||||
}
|
||||
if sorted[1].Name != "app3" {
|
||||
t.Errorf("expected second unit to be app3 (order 3), got %s", sorted[1].Name)
|
||||
}
|
||||
if sorted[2].Name != "app1" {
|
||||
t.Errorf("expected third unit to be app1 (order 1), got %s", sorted[2].Name)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStart_SkipsDisabledUnits verifies that startall skips disabled units.
|
||||
func TestStart_SkipsDisabledUnits(t *testing.T) {
|
||||
u1 := config.Unit{Name: "app1", Runtime: "podman", Order: 1, Enabled: true}
|
||||
u2 := config.Unit{Name: "app2", Runtime: "podman", Order: 2, Enabled: false}
|
||||
|
||||
units := []config.Unit{u1, u2}
|
||||
enabledCount := 0
|
||||
for _, u := range units {
|
||||
if !u.Enabled {
|
||||
continue // skip disabled like startall does
|
||||
}
|
||||
enabledCount++
|
||||
}
|
||||
if enabledCount != 1 {
|
||||
t.Errorf("expected to count only 1 enabled unit, got %d", enabledCount)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStop_SkipsUninstalledUnits verifies that stopall skips uninstalled units.
|
||||
func TestStop_SkipsUninstalledUnits(t *testing.T) {
|
||||
u := config.Unit{Name: "app1", Runtime: "podman", Order: 1, Enabled: true}
|
||||
units := []config.Unit{u}
|
||||
for _, unit := range units {
|
||||
if !IsInstalled(unit, "", "") {
|
||||
continue // skip uninstalled like stopall does
|
||||
}
|
||||
}
|
||||
t.Log("uninstalled units are skipped (no service files exist in test env)")
|
||||
}
|
||||
Reference in New Issue
Block a user