228 lines
6.6 KiB
Go
228 lines
6.6 KiB
Go
package system
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"nadir/internal/oscmd"
|
|
|
|
"github.com/danielgtaylor/huma/v2"
|
|
"github.com/danielgtaylor/huma/v2/adapters/humago"
|
|
"github.com/danielgtaylor/huma/v2/humatest"
|
|
)
|
|
|
|
func TestSystemHandlers(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
api := humatest.Wrap(t, humago.New(mux, huma.DefaultConfig("Test", "1.0.0")))
|
|
|
|
registerHostname(api)
|
|
registerTimedate(api)
|
|
registerLocale(api)
|
|
registerPower(api)
|
|
registerInfo(api)
|
|
|
|
// Mock uname for GET /api/system/info
|
|
oscmd.SetMock("uname", func(args []string) oscmd.MockCommand {
|
|
if reflect.DeepEqual(args, []string{"-r"}) {
|
|
return oscmd.MockCommand{Stdout: "6.9.1-1-test\n", ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"-m"}) {
|
|
return oscmd.MockCommand{Stdout: "x86_64\n", ExitCode: 0}
|
|
}
|
|
return oscmd.MockCommand{ExitCode: 1}
|
|
})
|
|
defer oscmd.ClearMocks()
|
|
|
|
// 1. Test GET /api/system/info
|
|
resp := api.Get("/api/system/info")
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("get info: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
// 2. Test GET & POST /api/system/hostname
|
|
oscmd.SetMock("hostnamectl", func(args []string) oscmd.MockCommand {
|
|
if reflect.DeepEqual(args, []string{"hostname"}) {
|
|
return oscmd.MockCommand{Stdout: "server01\n", ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"set-hostname", "--", "server02"}) {
|
|
return oscmd.MockCommand{ExitCode: 0}
|
|
}
|
|
return oscmd.MockCommand{ExitCode: 1}
|
|
})
|
|
|
|
resp = api.Get("/api/system/hostname")
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("get hostname: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
var hostnameRes GetHostnameOutput
|
|
if err := json.Unmarshal(resp.Body.Bytes(), &hostnameRes.Body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if hostnameRes.Body.Hostname != "server01" {
|
|
t.Errorf("got hostname %q, want %q", hostnameRes.Body.Hostname, "server01")
|
|
}
|
|
|
|
resp = api.Post("/api/system/hostname", struct {
|
|
Hostname string `json:"hostname"`
|
|
}{
|
|
Hostname: "server02",
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("set hostname: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
// 3. Test GET & POST /api/system/time
|
|
oscmd.SetMock("timedatectl", func(args []string) oscmd.MockCommand {
|
|
if reflect.DeepEqual(args, []string{"show"}) {
|
|
showOut := "Timezone=Europe/Rome\nLocalRTC=no\nNTP=yes\nNTPSynchronized=yes\nCanNTP=yes\n"
|
|
return oscmd.MockCommand{Stdout: showOut, ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"list-timezones"}) {
|
|
return oscmd.MockCommand{Stdout: "Europe/Rome\nUTC\n", ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"set-timezone", "Europe/Rome"}) {
|
|
return oscmd.MockCommand{ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"set-ntp", "true"}) {
|
|
return oscmd.MockCommand{ExitCode: 0}
|
|
}
|
|
if len(args) == 2 && args[0] == "set-time" {
|
|
return oscmd.MockCommand{ExitCode: 0}
|
|
}
|
|
return oscmd.MockCommand{ExitCode: 1}
|
|
})
|
|
|
|
resp = api.Get("/api/system/time")
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("get time: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
var timeRes GetTimeOutput
|
|
if err := json.Unmarshal(resp.Body.Bytes(), &timeRes.Body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if timeRes.Body.Timezone != "Europe/Rome" || !timeRes.Body.NTP {
|
|
t.Errorf("got time settings: %+v", timeRes.Body)
|
|
}
|
|
|
|
resp = api.Get("/api/system/timezones")
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("list timezones: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
resp = api.Post("/api/system/timezone", struct {
|
|
Timezone string `json:"timezone"`
|
|
}{
|
|
Timezone: "Europe/Rome",
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("set timezone: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
resp = api.Post("/api/system/ntp", struct {
|
|
Enabled bool `json:"enabled"`
|
|
}{
|
|
Enabled: true,
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("set ntp: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
resp = api.Post("/api/system/time", struct {
|
|
Time string `json:"time"`
|
|
}{
|
|
Time: "2026-06-20T12:00:00Z",
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("set time: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
// 4. Test GET & POST /api/system/locale
|
|
oscmd.SetMock("localectl", func(args []string) oscmd.MockCommand {
|
|
if reflect.DeepEqual(args, []string{"status"}) {
|
|
statusOut := " System Locale: LANG=it_IT.UTF-8\n VC Keymap: it\n X11 Layout: it\n"
|
|
return oscmd.MockCommand{Stdout: statusOut, ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"list-locales"}) {
|
|
return oscmd.MockCommand{Stdout: "it_IT.UTF-8\nen_US.UTF-8\n", ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"set-locale", "LANG=it_IT.UTF-8"}) {
|
|
return oscmd.MockCommand{ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"list-keymaps"}) {
|
|
return oscmd.MockCommand{Stdout: "it\nus\n", ExitCode: 0}
|
|
}
|
|
if reflect.DeepEqual(args, []string{"set-keymap", "it"}) {
|
|
return oscmd.MockCommand{ExitCode: 0}
|
|
}
|
|
return oscmd.MockCommand{ExitCode: 1}
|
|
})
|
|
|
|
resp = api.Get("/api/system/locale")
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("get locale: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
var localeRes GetLocaleOutput
|
|
if err := json.Unmarshal(resp.Body.Bytes(), &localeRes.Body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if localeRes.Body.Lang != "it_IT.UTF-8" || localeRes.Body.VCKeymap != "it" {
|
|
t.Errorf("got locale status: %+v", localeRes.Body)
|
|
}
|
|
|
|
resp = api.Get("/api/system/locales")
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("list locales: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
resp = api.Post("/api/system/locale", struct {
|
|
Lang string `json:"lang"`
|
|
}{
|
|
Lang: "it_IT.UTF-8",
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("set locale: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
resp = api.Get("/api/system/keymaps")
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("list keymaps: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
resp = api.Post("/api/system/keymap", struct {
|
|
Keymap string `json:"keymap"`
|
|
}{
|
|
Keymap: "it",
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("set keymap: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
// 5. Test POST /api/system/reboot and /api/system/poweroff
|
|
oscmd.SetMock("shutdown", func(args []string) oscmd.MockCommand {
|
|
if reflect.DeepEqual(args, []string{"-r", "now"}) || reflect.DeepEqual(args, []string{"-h", "now"}) {
|
|
return oscmd.MockCommand{ExitCode: 0}
|
|
}
|
|
return oscmd.MockCommand{ExitCode: 1}
|
|
})
|
|
|
|
resp = api.Post("/api/system/reboot", struct {
|
|
When string `json:"when"`
|
|
}{
|
|
When: "now",
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("reboot: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
|
|
resp = api.Post("/api/system/poweroff", struct {
|
|
When string `json:"when"`
|
|
}{
|
|
When: "now",
|
|
})
|
|
if resp.Code != http.StatusOK {
|
|
t.Errorf("poweroff: got %d, want %d", resp.Code, http.StatusOK)
|
|
}
|
|
}
|