package profile import ( "context" "os" "path/filepath" "strings" "testing" ) // Defends novox/hq ADR 0255: a machine says whether a battery powers it and whether anything on it // measures the power it draws, read from the kernel, so the controller composes a battery's or a power // draw's block only where there is one. func write(t *testing.T, path, content string) { t.Helper() if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(path, []byte(content+"\n"), 0o644); err != nil { t.Fatal(err) } } // sysfs points every power source at a directory of its own, empty unless a case fills it. func sysfs(t *testing.T) string { t.Helper() dir := t.TempDir() old := [4]string{PowerSupplySource, PowercapSource, SeatSource, NvidiaSource} PowerSupplySource = filepath.Join(dir, "power_supply") PowercapSource = filepath.Join(dir, "powercap") SeatSource = filepath.Join(dir, "drm") NvidiaSource = filepath.Join(dir, "nvidia") t.Cleanup(func() { PowerSupplySource, PowercapSource, SeatSource, NvidiaSource = old[0], old[1], old[2], old[3] }) return dir } func TestALaptopHasABatteryAndAMeter(t *testing.T) { dir := sysfs(t) write(t, dir+"/power_supply/ACAD/type", "Mains") write(t, dir+"/power_supply/BAT1/type", "Battery") write(t, dir+"/power_supply/BAT1/scope", "System") write(t, dir+"/power_supply/BAT1/present", "1") write(t, dir+"/powercap/intel-rapl:0/name", "package-0") write(t, dir+"/powercap/intel-rapl:0/energy_uj", "1") b := battery{}.Detect(context.Background()) if !b.Present || b.Detail != "BAT1" { t.Fatalf("battery: %+v", b) } m := powerMeter{}.Detect(context.Background()) if !m.Present || m.Detail != "battery BAT1, processor package-0" { t.Fatalf("power meter: %+v", m) } } func TestADevicesBatteryIsNotTheMachines(t *testing.T) { // The case worth a test: a desktop with a wireless mouse reports a Battery, and a battery block // composed for it would show the mouse's charge as the machine's. dir := sysfs(t) write(t, dir+"/power_supply/hidpp_battery_0/type", "Battery") write(t, dir+"/power_supply/hidpp_battery_0/scope", "Device") write(t, dir+"/power_supply/BAT0/type", "Battery") write(t, dir+"/power_supply/BAT0/present", "0") if b := (battery{}).Detect(context.Background()); b.Present { t.Fatalf("a mouse's battery, or an empty bay, was taken for the machine's: %+v", b) } if m := (powerMeter{}).Detect(context.Background()); m.Present { t.Fatalf("a device's battery was taken for a meter: %+v", m) } } func TestADesktopMeasuresItsProcessorAndItsGraphics(t *testing.T) { dir := sysfs(t) write(t, dir+"/powercap/intel-rapl:0/name", "package-0") write(t, dir+"/powercap/intel-rapl:0/energy_uj", "1") // A sub-domain is part of the package, not a second meter. write(t, dir+"/powercap/intel-rapl:0:0/name", "core") write(t, dir+"/powercap/intel-rapl:0:0/energy_uj", "1") write(t, dir+"/drm/card1/device/hwmon/hwmon4/power1_average", "8000000") write(t, dir+"/drm/card1/device/mem_info_vram_vendor", "samsung") write(t, dir+"/nvidia/0000:01:00.0/information", "x") if b := (battery{}).Detect(context.Background()); b.Present { t.Fatalf("a desktop has a battery: %+v", b) } m := powerMeter{}.Detect(context.Background()) if !m.Present || m.Detail != "processor package-0, graphics card1, graphics nvidia" { t.Fatalf("power meter: %+v", m) } } func TestAMachineWithNothingToReadHasNeither(t *testing.T) { sysfs(t) b, m := battery{}.Detect(context.Background()), powerMeter{}.Detect(context.Background()) if b.Present || m.Present || b.How == "" || m.How == "" || !strings.Contains(m.Detail, "nothing") { t.Fatalf("%+v %+v", b, m) } } func TestAPackageShownTwiceIsOneMeterAndIntegratedGraphicsAreNone(t *testing.T) { dir := sysfs(t) write(t, dir+"/powercap/intel-rapl:0/name", "package-0") write(t, dir+"/powercap/intel-rapl:0/energy_uj", "1") write(t, dir+"/powercap/intel-rapl-mmio:0/name", "package-0") write(t, dir+"/powercap/intel-rapl-mmio:0/energy_uj", "1") // An APU's graphics: power reported, no memory of its own. write(t, dir+"/drm/card1/device/hwmon/hwmon5/power1_average", "19000000") m := powerMeter{}.Detect(context.Background()) if !m.Present || m.Detail != "processor package-0" { t.Fatalf("power meter: %+v", m) } } func TestOnlyIntegratedGraphicsMeasureNothing(t *testing.T) { dir := sysfs(t) write(t, dir+"/drm/card0/device/hwmon/hwmon1/power1_input", "5000000") if m := (powerMeter{}).Detect(context.Background()); m.Present { t.Fatalf("integrated graphics were taken for a meter: %+v", m) } } func TestABatteryOfUnknownScopeIsTheMachines(t *testing.T) { // Many laptops' firmware says nothing of scope; the kernel reports Unknown. Only Device is a // peripheral's. dir := sysfs(t) write(t, dir+"/power_supply/BAT0/type", "Battery") write(t, dir+"/power_supply/BAT0/scope", "Unknown") if b := (battery{}).Detect(context.Background()); !b.Present || b.Detail != "BAT0" { t.Fatalf("battery: %+v", b) } }