package brightness import ( "os" "path/filepath" "testing" mocks_brightness "github.com/AvengeMedia/DankMaterialShell/backend/internal/mocks/brightness" mock_dbus "github.com/AvengeMedia/DankMaterialShell/backend/internal/mocks/github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5" "github.com/stretchr/testify/mock" ) func TestManager_SetBrightness_LogindSuccess(t *testing.T) { tmpDir := t.TempDir() backlightDir := filepath.Join(tmpDir, "backlight", "test_backlight") if err := os.MkdirAll(backlightDir, 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(backlightDir, "max_brightness"), []byte("100\n"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(backlightDir, "brightness"), []byte("50\n"), 0644); err != nil { t.Fatal(err) } mockConn := mocks_brightness.NewMockDBusConn(t) mockObj := mock_dbus.NewMockBusObject(t) mockLogind := NewLogindBackendWithConn(mockConn) sysfs := &SysfsBackend{ basePath: tmpDir, classes: []string{"backlight"}, deviceCache: make(map[string]*sysfsDevice), } if err := sysfs.scanDevices(); err != nil { t.Fatal(err) } m := &Manager{ logindBackend: mockLogind, sysfsBackend: sysfs, logindReady: true, sysfsReady: true, subscribers: make(map[string]chan State), updateSubscribers: make(map[string]chan DeviceUpdate), stopChan: make(chan struct{}), } m.state = State{ Devices: []Device{ { Class: ClassBacklight, ID: "backlight:test_backlight", Name: "test_backlight", Current: 50, Max: 100, CurrentPercent: 50, Backend: "sysfs", }, }, } mockConn.EXPECT(). Object("org.freedesktop.login1", dbus.ObjectPath("/org/freedesktop/login1/session/auto")). Return(mockObj). Once() mockObj.EXPECT(). Call("org.freedesktop.login1.Session.SetBrightness", mock.Anything, "backlight", "test_backlight", uint32(75)). Return(&dbus.Call{Err: nil}). Once() err := m.SetBrightness("backlight:test_backlight", 75) if err != nil { t.Errorf("SetBrightness() with logind error = %v, want nil", err) } data, _ := os.ReadFile(filepath.Join(backlightDir, "brightness")) if string(data) == "75\n" { t.Error("Direct sysfs write occurred when logind should have been used") } } func TestManager_SetBrightness_LogindFailsFallbackToSysfs(t *testing.T) { tmpDir := t.TempDir() backlightDir := filepath.Join(tmpDir, "backlight", "test_backlight") if err := os.MkdirAll(backlightDir, 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(backlightDir, "max_brightness"), []byte("100\n"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(backlightDir, "brightness"), []byte("50\n"), 0644); err != nil { t.Fatal(err) } mockConn := mocks_brightness.NewMockDBusConn(t) mockObj := mock_dbus.NewMockBusObject(t) mockLogind := NewLogindBackendWithConn(mockConn) sysfs := &SysfsBackend{ basePath: tmpDir, classes: []string{"backlight"}, deviceCache: make(map[string]*sysfsDevice), } if err := sysfs.scanDevices(); err != nil { t.Fatal(err) } m := &Manager{ logindBackend: mockLogind, sysfsBackend: sysfs, logindReady: true, sysfsReady: true, subscribers: make(map[string]chan State), updateSubscribers: make(map[string]chan DeviceUpdate), stopChan: make(chan struct{}), } m.state = State{ Devices: []Device{ { Class: ClassBacklight, ID: "backlight:test_backlight", Name: "test_backlight", Current: 50, Max: 100, CurrentPercent: 50, Backend: "sysfs", }, }, } mockConn.EXPECT(). Object("org.freedesktop.login1", dbus.ObjectPath("/org/freedesktop/login1/session/auto")). Return(mockObj). Once() mockObj.EXPECT(). Call("org.freedesktop.login1.Session.SetBrightness", mock.Anything, "backlight", "test_backlight", mock.Anything). Return(&dbus.Call{Err: dbus.ErrMsgNoObject}). Once() err := m.SetBrightness("backlight:test_backlight", 75) if err != nil { t.Errorf("SetBrightness() with fallback error = %v, want nil", err) } data, _ := os.ReadFile(filepath.Join(backlightDir, "brightness")) brightness := string(data) if brightness != "75" { t.Errorf("Fallback sysfs write did not occur, got brightness = %q, want %q", brightness, "75") } } func TestManager_SetBrightness_NoLogind(t *testing.T) { tmpDir := t.TempDir() backlightDir := filepath.Join(tmpDir, "backlight", "test_backlight") if err := os.MkdirAll(backlightDir, 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(backlightDir, "max_brightness"), []byte("100\n"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(backlightDir, "brightness"), []byte("50\n"), 0644); err != nil { t.Fatal(err) } sysfs := &SysfsBackend{ basePath: tmpDir, classes: []string{"backlight"}, deviceCache: make(map[string]*sysfsDevice), } if err := sysfs.scanDevices(); err != nil { t.Fatal(err) } m := &Manager{ logindBackend: nil, sysfsBackend: sysfs, logindReady: false, sysfsReady: true, subscribers: make(map[string]chan State), updateSubscribers: make(map[string]chan DeviceUpdate), stopChan: make(chan struct{}), } m.state = State{ Devices: []Device{ { Class: ClassBacklight, ID: "backlight:test_backlight", Name: "test_backlight", Current: 50, Max: 100, CurrentPercent: 50, Backend: "sysfs", }, }, } err := m.SetBrightness("backlight:test_backlight", 75) if err != nil { t.Errorf("SetBrightness() without logind error = %v, want nil", err) } data, _ := os.ReadFile(filepath.Join(backlightDir, "brightness")) brightness := string(data) if brightness != "75" { t.Errorf("Direct sysfs write = %q, want %q", brightness, "75") } } func TestManager_SetBrightness_LEDWithLogind(t *testing.T) { tmpDir := t.TempDir() ledsDir := filepath.Join(tmpDir, "leds", "test_led") if err := os.MkdirAll(ledsDir, 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(ledsDir, "max_brightness"), []byte("255\n"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(ledsDir, "brightness"), []byte("128\n"), 0644); err != nil { t.Fatal(err) } mockConn := mocks_brightness.NewMockDBusConn(t) mockObj := mock_dbus.NewMockBusObject(t) mockLogind := NewLogindBackendWithConn(mockConn) sysfs := &SysfsBackend{ basePath: tmpDir, classes: []string{"leds"}, deviceCache: make(map[string]*sysfsDevice), } if err := sysfs.scanDevices(); err != nil { t.Fatal(err) } m := &Manager{ logindBackend: mockLogind, sysfsBackend: sysfs, logindReady: true, sysfsReady: true, subscribers: make(map[string]chan State), updateSubscribers: make(map[string]chan DeviceUpdate), stopChan: make(chan struct{}), } m.state = State{ Devices: []Device{ { Class: ClassLED, ID: "leds:test_led", Name: "test_led", Current: 128, Max: 255, CurrentPercent: 50, Backend: "sysfs", }, }, } mockConn.EXPECT(). Object("org.freedesktop.login1", dbus.ObjectPath("/org/freedesktop/login1/session/auto")). Return(mockObj). Once() mockObj.EXPECT(). Call("org.freedesktop.login1.Session.SetBrightness", mock.Anything, "leds", "test_led", uint32(0)). Return(&dbus.Call{Err: nil}). Once() err := m.SetBrightness("leds:test_led", 0) if err != nil { t.Errorf("SetBrightness() LED with logind error = %v, want nil", err) } }