test(daemon): coordinate atomic theme snapshot reads
- commit
- adce876489a69cc962df715a5999c3bd228e638c
- author
- brice · · 2026-07-17 09:23 UTC
- parent
- 00f573e
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +18 -6
M internal/usecase/daemon/config_test.go +18 -6
| @@ -197,16 +197,22 @@ func TestThemeConfigSnapshotIsAtomic(t *testing.T) { | |||
| 197 | 197 | {mode: domain.ThemeAuto, paletteOff: true}: {}, | |
| 198 | 198 | {mode: domain.ThemeDark, paletteOff: false}: {}, | |
| 199 | 199 | } | |
| 200 | - | ready := make(chan struct{}) | |
| 201 | - | readerStarted := make(chan struct{}) | |
| 200 | + | firstPublished := make(chan struct{}) | |
| 201 | + | firstObserved := make(chan struct{}) | |
| 202 | + | secondPublished := make(chan struct{}) | |
| 203 | + | secondObserved := make(chan struct{}) | |
| 204 | + | observed := make(chan themeConfigSnapshot, 2) | |
| 202 | 205 | invalid := make(chan themeConfigSnapshot, 1) | |
| 203 | 206 | var wg sync.WaitGroup | |
| 204 | 207 | wg.Add(2) | |
| 205 | 208 | go func() { | |
| 206 | 209 | defer wg.Done() | |
| 207 | 210 | d.storeThemeConfig(first) | |
| 208 | - | close(ready) | |
| 209 | - | <-readerStarted | |
| 211 | + | close(firstPublished) | |
| 212 | + | <-firstObserved | |
| 213 | + | d.storeThemeConfig(second) | |
| 214 | + | close(secondPublished) | |
| 215 | + | <-secondObserved | |
| 210 | 216 | for range 10_000 { | |
| 211 | 217 | d.storeThemeConfig(second) | |
| 212 | 218 | d.storeThemeConfig(first) | |
| @@ -214,8 +220,12 @@ func TestThemeConfigSnapshotIsAtomic(t *testing.T) { | |||
| 214 | 220 | }() | |
| 215 | 221 | go func() { | |
| 216 | 222 | defer wg.Done() | |
| 217 | - | <-ready | |
| 218 | - | close(readerStarted) | |
| 223 | + | <-firstPublished | |
| 224 | + | observed <- d.currentThemeConfig() | |
| 225 | + | close(firstObserved) | |
| 226 | + | <-secondPublished | |
| 227 | + | observed <- d.currentThemeConfig() | |
| 228 | + | close(secondObserved) | |
| 219 | 229 | for range 20_000 { | |
| 220 | 230 | snapshot := d.currentThemeConfig() | |
| 221 | 231 | if _, ok := allowed[snapshot]; !ok { | |
| @@ -228,6 +238,8 @@ func TestThemeConfigSnapshotIsAtomic(t *testing.T) { | |||
| 228 | 238 | } | |
| 229 | 239 | }() | |
| 230 | 240 | wg.Wait() | |
| 241 | + | require.Equal(t, themeConfigSnapshot{mode: domain.ThemeAuto, paletteOff: true}, <-observed) | |
| 242 | + | require.Equal(t, themeConfigSnapshot{mode: domain.ThemeDark, paletteOff: false}, <-observed) | |
| 231 | 243 | select { | |
| 232 | 244 | case snapshot := <-invalid: | |
| 233 | 245 | t.Fatalf("observed mixed theme configuration: %#v", snapshot) | |
| @@ -197,16 +197,22 @@ func TestThemeConfigSnapshotIsAtomic(t *testing.T) { | |||||
| 197 | {mode: domain.ThemeAuto, paletteOff: true}: {}, | 197 | {mode: domain.ThemeAuto, paletteOff: true}: {}, | ||
| 198 | {mode: domain.ThemeDark, paletteOff: false}: {}, | 198 | {mode: domain.ThemeDark, paletteOff: false}: {}, | ||
| 199 | } | 199 | } | ||
| 200 | - | ready := make(chan struct{}) | 200 | + | firstPublished := make(chan struct{}) |
| 201 | - | readerStarted := make(chan struct{}) | 201 | + | firstObserved := make(chan struct{}) |
| 202 | + | secondPublished := make(chan struct{}) | |||
| 203 | + | secondObserved := make(chan struct{}) | |||
| 204 | + | observed := make(chan themeConfigSnapshot, 2) | |||
| 202 | invalid := make(chan themeConfigSnapshot, 1) | 205 | invalid := make(chan themeConfigSnapshot, 1) | ||
| 203 | var wg sync.WaitGroup | 206 | var wg sync.WaitGroup | ||
| 204 | wg.Add(2) | 207 | wg.Add(2) | ||
| 205 | go func() { | 208 | go func() { | ||
| 206 | defer wg.Done() | 209 | defer wg.Done() | ||
| 207 | d.storeThemeConfig(first) | 210 | d.storeThemeConfig(first) | ||
| 208 | - | close(ready) | 211 | + | close(firstPublished) |
| 209 | - | <-readerStarted | 212 | + | <-firstObserved |
| 213 | + | d.storeThemeConfig(second) | |||
| 214 | + | close(secondPublished) | |||
| 215 | + | <-secondObserved | |||
| 210 | for range 10_000 { | 216 | for range 10_000 { | ||
| 211 | d.storeThemeConfig(second) | 217 | d.storeThemeConfig(second) | ||
| 212 | d.storeThemeConfig(first) | 218 | d.storeThemeConfig(first) | ||
| @@ -214,8 +220,12 @@ func TestThemeConfigSnapshotIsAtomic(t *testing.T) { | |||||
| 214 | }() | 220 | }() | ||
| 215 | go func() { | 221 | go func() { | ||
| 216 | defer wg.Done() | 222 | defer wg.Done() | ||
| 217 | - | <-ready | 223 | + | <-firstPublished |
| 218 | - | close(readerStarted) | 224 | + | observed <- d.currentThemeConfig() |
| 225 | + | close(firstObserved) | |||
| 226 | + | <-secondPublished | |||
| 227 | + | observed <- d.currentThemeConfig() | |||
| 228 | + | close(secondObserved) | |||
| 219 | for range 20_000 { | 229 | for range 20_000 { | ||
| 220 | snapshot := d.currentThemeConfig() | 230 | snapshot := d.currentThemeConfig() | ||
| 221 | if _, ok := allowed[snapshot]; !ok { | 231 | if _, ok := allowed[snapshot]; !ok { | ||
| @@ -228,6 +238,8 @@ func TestThemeConfigSnapshotIsAtomic(t *testing.T) { | |||||
| 228 | } | 238 | } | ||
| 229 | }() | 239 | }() | ||
| 230 | wg.Wait() | 240 | wg.Wait() | ||
| 241 | + | require.Equal(t, themeConfigSnapshot{mode: domain.ThemeAuto, paletteOff: true}, <-observed) | |||
| 242 | + | require.Equal(t, themeConfigSnapshot{mode: domain.ThemeDark, paletteOff: false}, <-observed) | |||
| 231 | select { | 243 | select { | ||
| 232 | case snapshot := <-invalid: | 244 | case snapshot := <-invalid: | ||
| 233 | t.Fatalf("observed mixed theme configuration: %#v", snapshot) | 245 | t.Fatalf("observed mixed theme configuration: %#v", snapshot) | ||