package main import ( "context" "strings" "testing" ) // What asusctl 6.4 and supergfxctl 5.2 said on the laptop on 2026-10-04. const fanCurveQuiet = ` Fan curves for Quiet [ ( fan: CPU, pwm: (2, 0, 10, 20, 35, 55, 80, 100), temp: (35, 45, 50, 55, 60, 65, 70, 80), enabled: true, ), ( fan: GPU, pwm: (0, 0, 10, 20, 35, 65, 90, 115), temp: (35, 45, 50, 55, 60, 65, 70, 80), enabled: false, ), ] ` const asusdRon = `( charge_control_end_threshold: 80, base_charge_control_end_threshold: 0, disable_nvidia_powerd_on_battery: true, ac_command: "supergfxctl -m Hybrid", bat_command: "supergfxctl -m Integrated", platform_profile_linked_epp: true, platform_profile_on_battery: Quiet, change_platform_profile_on_battery: true, platform_profile_on_ac: Balanced, change_platform_profile_on_ac: true, ac_profile_tunings: { Quiet: ( enabled: false, group: {}, ), }, )` func TestAsusctlsAnswersAreRead(t *testing.T) { p, err := ParseProfileGet(profileGetBalanced) if err != nil || p.Active != "Balanced" || p.OnAC != "Balanced" || p.Battery != "Quiet" { t.Fatalf("%+v %v", p, err) } if _, err := ParseProfileGet("something else"); err == nil { t.Fatal("an answer with no profile was read as one") } if l, err := ParseLeds("Current keyboard led brightness: High\n"); err != nil || l != "high" { t.Fatalf("%q %v", l, err) } curves := ParseFanCurves(fanCurveQuiet) if len(curves) != 2 || curves[0].Fan != "CPU" || curves[0].PWM[7] != 100 || curves[0].Temp[0] != 35 || curves[1].Enabled { t.Fatalf("%+v", curves) } if got := ParseSupported("[Integrated, Hybrid, AsusMuxDgpu]\n"); strings.Join(got, ",") != "Integrated,Hybrid,AsusMuxDgpu" { t.Fatalf("%v", got) } } func TestAsusdsFileIsReadForWhatDecidesTheModulesCodeAndNothingNested(t *testing.T) { c := ParseAsusdRon(asusdRon) if *c.ChargeLimit != 80 || c.ProfileOnAC != "Balanced" || c.ProfileOnBattery != "Quiet" || c.ACCommand != "supergfxctl -m Hybrid" || c.BatteryCommand != "supergfxctl -m Integrated" || !*c.ChangesProfileOnAC || !*c.DisablesPowerdOnBatt { t.Fatalf("%+v", c) } } func TestAMissingVendorClientIsNamedWithWhyItIsMissing(t *testing.T) { f := newFake(t) f.fails["supergfxctl"] = notFound _, err := f.machine().GPU(context.Background()) if err == nil || !strings.Contains(err.Error(), "research 027") { t.Fatalf("%v", err) } f.fails["asusctl"] = notFound _, err = f.machine().Profile(context.Background()) if err == nil || !strings.Contains(err.Error(), "package resource installs it") { t.Fatalf("%v", err) } } func TestAGPUModeIsSetOnlyWhenTheMachineSupportsItAndAsusdsSwitchingIsSaid(t *testing.T) { f := newFake(t) f.answers["supergfxctl -g"] = "Hybrid\n" f.answers["supergfxctl -s"] = "[Integrated, Hybrid, AsusMuxDgpu]\n" f.file("/etc/asusd/asusd.ron", asusdRon) m := f.machine() if _, err := GPUModeTool(context.Background(), m, map[string]any{"mode": "Vfio"}); err == nil { t.Fatal("an unsupported mode was accepted") } out, err := GPUModeTool(context.Background(), m, map[string]any{"mode": "integrated"}) if err != nil { t.Fatal(err) } if !f.called("supergfxctl -m Integrated") { t.Fatalf("calls %v", f.calls) } if _, said := out.(map[string]any)["asusd_switches_it"]; !said { t.Fatalf("asusd's own switching of the mode was not said: %+v", out) } } func TestTheChargeLimitIsBoundedAndSetThroughAsusd(t *testing.T) { f := newFake(t) f.answers["asusctl battery info"] = "Current battery charge limit: 60%\n" m := f.machine() for _, bad := range []any{float64(10), float64(101), "x", 55.5} { if _, err := ChargeLimitTool(context.Background(), m, map[string]any{"limit": bad}); err == nil { t.Errorf("limit %v was accepted", bad) } } out, err := ChargeLimitTool(context.Background(), m, map[string]any{"limit": float64(60)}) if err != nil || !f.called("asusctl battery limit 60") || out.(map[string]any)["asusd_limit_percent"] != 60 { t.Fatalf("%+v %v %v", out, err, f.calls) } } func TestAProfileSetByToolIsHeldAndAnUnknownOneRefused(t *testing.T) { f := newFake(t) f.onMains() f.answers["asusctl profile get"] = profileGetBalanced m := f.machine() sw := NewSwitcher(m, nil) if _, err := ProfileTool(context.Background(), m, sw, map[string]any{"profile": "Turbo"}); err == nil { t.Fatal("an unknown profile was accepted") } out, err := ProfileTool(context.Background(), m, sw, map[string]any{"profile": "performance", "hold_minutes": float64(30)}) if err != nil || !f.called("asusctl profile set Performance") { t.Fatalf("%v %v", err, f.calls) } if _, held := out.(map[string]any)["held_until"]; !held { t.Fatalf("not held: %+v", out) } if r := sw.Report(); r.Held != "Performance" { t.Fatalf("%+v", r) } }