mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 13:32:50 -05:00
367 lines
8.0 KiB
Go
367 lines
8.0 KiB
Go
package dwl
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
mocks_wlclient "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/wlclient"
|
|
)
|
|
|
|
func TestStateChanged_BothNil(t *testing.T) {
|
|
assert.True(t, stateChanged(nil, nil))
|
|
}
|
|
|
|
func TestStateChanged_OneNil(t *testing.T) {
|
|
s := &State{TagCount: 9}
|
|
assert.True(t, stateChanged(s, nil))
|
|
assert.True(t, stateChanged(nil, s))
|
|
}
|
|
|
|
func TestStateChanged_TagCountDiffers(t *testing.T) {
|
|
a := &State{TagCount: 9, Outputs: make(map[string]*OutputState), Layouts: []string{}}
|
|
b := &State{TagCount: 10, Outputs: make(map[string]*OutputState), Layouts: []string{}}
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestStateChanged_LayoutLengthDiffers(t *testing.T) {
|
|
a := &State{TagCount: 9, Layouts: []string{"tile"}, Outputs: make(map[string]*OutputState)}
|
|
b := &State{TagCount: 9, Layouts: []string{"tile", "monocle"}, Outputs: make(map[string]*OutputState)}
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestStateChanged_ActiveOutputDiffers(t *testing.T) {
|
|
a := &State{TagCount: 9, ActiveOutput: "eDP-1", Outputs: make(map[string]*OutputState), Layouts: []string{}}
|
|
b := &State{TagCount: 9, ActiveOutput: "HDMI-A-1", Outputs: make(map[string]*OutputState), Layouts: []string{}}
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestStateChanged_OutputCountDiffers(t *testing.T) {
|
|
a := &State{
|
|
TagCount: 9,
|
|
Outputs: map[string]*OutputState{"eDP-1": {}},
|
|
Layouts: []string{},
|
|
}
|
|
b := &State{
|
|
TagCount: 9,
|
|
Outputs: map[string]*OutputState{},
|
|
Layouts: []string{},
|
|
}
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestStateChanged_OutputFieldsDiffer(t *testing.T) {
|
|
a := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Active: 1, Layout: 0, Title: "Firefox"},
|
|
},
|
|
}
|
|
b := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Active: 0, Layout: 0, Title: "Firefox"},
|
|
},
|
|
}
|
|
assert.True(t, stateChanged(a, b))
|
|
|
|
b.Outputs["eDP-1"].Active = 1
|
|
b.Outputs["eDP-1"].Layout = 1
|
|
assert.True(t, stateChanged(a, b))
|
|
|
|
b.Outputs["eDP-1"].Layout = 0
|
|
b.Outputs["eDP-1"].Title = "Code"
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestStateChanged_TagsDiffer(t *testing.T) {
|
|
a := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Tags: []TagState{{Tag: 1, State: 1, Clients: 2, Focused: 1}}},
|
|
},
|
|
}
|
|
b := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Tags: []TagState{{Tag: 1, State: 2, Clients: 2, Focused: 1}}},
|
|
},
|
|
}
|
|
assert.True(t, stateChanged(a, b))
|
|
|
|
b.Outputs["eDP-1"].Tags[0].State = 1
|
|
b.Outputs["eDP-1"].Tags[0].Clients = 3
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestStateChanged_Equal(t *testing.T) {
|
|
a := &State{
|
|
TagCount: 9,
|
|
ActiveOutput: "eDP-1",
|
|
Layouts: []string{"tile", "monocle"},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {
|
|
Name: "eDP-1",
|
|
Active: 1,
|
|
Layout: 0,
|
|
LayoutSymbol: "[]=",
|
|
Title: "Firefox",
|
|
AppID: "firefox",
|
|
KbLayout: "us",
|
|
Keymode: "",
|
|
Tags: []TagState{{Tag: 1, State: 1, Clients: 2, Focused: 1}},
|
|
},
|
|
},
|
|
}
|
|
b := &State{
|
|
TagCount: 9,
|
|
ActiveOutput: "eDP-1",
|
|
Layouts: []string{"tile", "monocle"},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {
|
|
Name: "eDP-1",
|
|
Active: 1,
|
|
Layout: 0,
|
|
LayoutSymbol: "[]=",
|
|
Title: "Firefox",
|
|
AppID: "firefox",
|
|
KbLayout: "us",
|
|
Keymode: "",
|
|
Tags: []TagState{{Tag: 1, State: 1, Clients: 2, Focused: 1}},
|
|
},
|
|
},
|
|
}
|
|
assert.False(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestManager_ConcurrentGetState(t *testing.T) {
|
|
m := &Manager{
|
|
state: &State{
|
|
TagCount: 9,
|
|
Layouts: []string{"tile"},
|
|
Outputs: map[string]*OutputState{"eDP-1": {Name: "eDP-1"}},
|
|
},
|
|
}
|
|
|
|
var wg sync.WaitGroup
|
|
const goroutines = 50
|
|
const iterations = 100
|
|
|
|
for i := 0; i < goroutines/2; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
for j := 0; j < iterations; j++ {
|
|
s := m.GetState()
|
|
_ = s.TagCount
|
|
_ = s.Outputs
|
|
}
|
|
}()
|
|
}
|
|
|
|
for i := 0; i < goroutines/2; i++ {
|
|
wg.Add(1)
|
|
go func(i int) {
|
|
defer wg.Done()
|
|
for j := 0; j < iterations; j++ {
|
|
m.stateMutex.Lock()
|
|
m.state = &State{
|
|
TagCount: uint32(j % 10),
|
|
Layouts: []string{"tile", "monocle"},
|
|
Outputs: map[string]*OutputState{"eDP-1": {Active: uint32(j % 2)}},
|
|
}
|
|
m.stateMutex.Unlock()
|
|
}
|
|
}(i)
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestManager_ConcurrentSubscriberAccess(t *testing.T) {
|
|
m := &Manager{
|
|
stopChan: make(chan struct{}),
|
|
dirty: make(chan struct{}, 1),
|
|
}
|
|
|
|
var wg sync.WaitGroup
|
|
const goroutines = 20
|
|
|
|
for i := 0; i < goroutines; i++ {
|
|
wg.Add(1)
|
|
go func(id int) {
|
|
defer wg.Done()
|
|
subID := string(rune('a' + id))
|
|
ch := m.Subscribe(subID)
|
|
assert.NotNil(t, ch)
|
|
time.Sleep(time.Millisecond)
|
|
m.Unsubscribe(subID)
|
|
}(i)
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestManager_SyncmapOutputsConcurrentAccess(t *testing.T) {
|
|
m := &Manager{}
|
|
|
|
var wg sync.WaitGroup
|
|
const goroutines = 30
|
|
const iterations = 50
|
|
|
|
for i := 0; i < goroutines; i++ {
|
|
wg.Add(1)
|
|
go func(id int) {
|
|
defer wg.Done()
|
|
key := uint32(id)
|
|
|
|
for j := 0; j < iterations; j++ {
|
|
state := &outputState{
|
|
id: key,
|
|
name: "test-output",
|
|
active: uint32(j % 2),
|
|
tags: []TagState{{Tag: uint32(j), State: 1}},
|
|
}
|
|
m.outputs.Store(key, state)
|
|
|
|
if loaded, ok := m.outputs.Load(key); ok {
|
|
assert.Equal(t, key, loaded.id)
|
|
}
|
|
|
|
m.outputs.Range(func(k uint32, v *outputState) bool {
|
|
_ = v.name
|
|
_ = v.active
|
|
return true
|
|
})
|
|
}
|
|
|
|
m.outputs.Delete(key)
|
|
}(i)
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestManager_NotifySubscribersNonBlocking(t *testing.T) {
|
|
m := &Manager{
|
|
dirty: make(chan struct{}, 1),
|
|
}
|
|
|
|
for i := 0; i < 10; i++ {
|
|
m.notifySubscribers()
|
|
}
|
|
|
|
assert.Len(t, m.dirty, 1)
|
|
}
|
|
|
|
func TestManager_PostQueueFull(t *testing.T) {
|
|
m := &Manager{
|
|
cmdq: make(chan cmd, 2),
|
|
stopChan: make(chan struct{}),
|
|
}
|
|
|
|
m.post(func() {})
|
|
m.post(func() {})
|
|
m.post(func() {})
|
|
m.post(func() {})
|
|
|
|
assert.Len(t, m.cmdq, 2)
|
|
}
|
|
|
|
func TestManager_GetStateNilState(t *testing.T) {
|
|
m := &Manager{}
|
|
|
|
s := m.GetState()
|
|
assert.NotNil(t, s.Outputs)
|
|
assert.NotNil(t, s.Layouts)
|
|
assert.Equal(t, uint32(0), s.TagCount)
|
|
}
|
|
|
|
func TestTagState_Fields(t *testing.T) {
|
|
tag := TagState{
|
|
Tag: 1,
|
|
State: 2,
|
|
Clients: 3,
|
|
Focused: 1,
|
|
}
|
|
|
|
assert.Equal(t, uint32(1), tag.Tag)
|
|
assert.Equal(t, uint32(2), tag.State)
|
|
assert.Equal(t, uint32(3), tag.Clients)
|
|
assert.Equal(t, uint32(1), tag.Focused)
|
|
}
|
|
|
|
func TestOutputState_Fields(t *testing.T) {
|
|
out := OutputState{
|
|
Name: "eDP-1",
|
|
Active: 1,
|
|
Tags: []TagState{{Tag: 1}},
|
|
Layout: 0,
|
|
LayoutSymbol: "[]=",
|
|
Title: "Firefox",
|
|
AppID: "firefox",
|
|
KbLayout: "us",
|
|
Keymode: "",
|
|
}
|
|
|
|
assert.Equal(t, "eDP-1", out.Name)
|
|
assert.Equal(t, uint32(1), out.Active)
|
|
assert.Len(t, out.Tags, 1)
|
|
assert.Equal(t, "[]=", out.LayoutSymbol)
|
|
}
|
|
|
|
func TestStateChanged_NewOutputAppears(t *testing.T) {
|
|
a := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Name: "eDP-1"},
|
|
},
|
|
}
|
|
b := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Name: "eDP-1"},
|
|
"HDMI-A-1": {Name: "HDMI-A-1"},
|
|
},
|
|
}
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestStateChanged_TagsLengthDiffers(t *testing.T) {
|
|
a := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Tags: []TagState{{Tag: 1}}},
|
|
},
|
|
}
|
|
b := &State{
|
|
TagCount: 9,
|
|
Layouts: []string{},
|
|
Outputs: map[string]*OutputState{
|
|
"eDP-1": {Tags: []TagState{{Tag: 1}, {Tag: 2}}},
|
|
},
|
|
}
|
|
assert.True(t, stateChanged(a, b))
|
|
}
|
|
|
|
func TestNewManager_GetRegistryError(t *testing.T) {
|
|
mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t)
|
|
|
|
mockDisplay.EXPECT().Context().Return(nil)
|
|
mockDisplay.EXPECT().GetRegistry().Return(nil, errors.New("failed to get registry"))
|
|
|
|
_, err := NewManager(mockDisplay)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "failed to get registry")
|
|
}
|