Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5026ae4d16 |
@@ -0,0 +1,46 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestStartArgCount verifies cobra.ExactArgs(1) rejects wrong arg counts for start.
|
||||||
|
func TestStartArgCount(t *testing.T) {
|
||||||
|
cmd := &cobra.Command{Use: "start", Short: "fake"}
|
||||||
|
cmd.Args = exactArgsOne
|
||||||
|
if err := cmd.ValidateArgs([]string{}); err == nil {
|
||||||
|
t.Error("expected error when called with no args")
|
||||||
|
}
|
||||||
|
if err := cmd.ValidateArgs([]string{"a", "b"}); err == nil {
|
||||||
|
t.Error("expected error when called with too many args")
|
||||||
|
}
|
||||||
|
if err := cmd.ValidateArgs([]string{"myunit"}); err != nil {
|
||||||
|
t.Errorf("unexpected error for single arg: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestStopArgCount verifies cobra.ExactArgs(1) rejects wrong arg counts for stop.
|
||||||
|
func TestStopArgCount(t *testing.T) {
|
||||||
|
cmd := &cobra.Command{Use: "stop", Short: "fake"}
|
||||||
|
cmd.Args = exactArgsOne
|
||||||
|
if err := cmd.ValidateArgs([]string{}); err == nil {
|
||||||
|
t.Error("expected error when called with no args")
|
||||||
|
}
|
||||||
|
if err := cmd.ValidateArgs([]string{"a", "b"}); err == nil {
|
||||||
|
t.Error("expected error when called with too many args")
|
||||||
|
}
|
||||||
|
if err := cmd.ValidateArgs([]string{"myunit"}); err != nil {
|
||||||
|
t.Errorf("unexpected error for single arg: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// exactArgsOne requires exactly one positional argument. Mirrors cobra.ExactArgs(1).
|
||||||
|
func exactArgsOne(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return fmt.Errorf("start/stop requires exactly 1 argument")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -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