test(wayland): fold the presentation ring tests into one table
The five makeRoomLocked tests (merge past the bound, flip before a flip-less report, interleaved outputs, incoming takes over a flip, no successor) are subtests of TestPresentationRingMakeRoom with the same rings, inputs and assertions. The rate-limited warning test stays apart: it drives enqueueLocked.
- commit
- fa55dc9edd58e3e6f5b552a54d96b73c47cf2b80
- author
- brice · · 2026-10-14 03:43 UTC
- committer
- brice · · 2026-10-14 04:34 UTC
- parent
- 5273ef5
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +118 -78
M internal/adapters/wayland/presented_test.go +118 -78
| @@ -174,84 +174,124 @@ func flipOf(seq uint64, shows ...ports.WindowID) *ports.FlipInfo { | |||
| 174 | 174 | return f | |
| 175 | 175 | } | |
| 176 | 176 | ||
| 177 | - | // A full ring merges the oldest flip of an output into its next flip. | |
| 178 | - | func TestPresentationRingMergesPastBound(t *testing.T) { | |
| 179 | - | p := ringOf() | |
| 180 | - | for i := range maxPresentRing { | |
| 181 | - | p.ring = append(p.ring, ports.OutputPresented{Output: "A", Flip: flipOf(uint64(i + 1))}) | |
| 182 | - | } | |
| 183 | - | in := ports.OutputPresented{Output: "A", Flip: flipOf(maxPresentRing + 1)} | |
| 184 | - | if !p.makeRoomLocked(&in) { | |
| 185 | - | t.Fatal("two flips merged but not reported") | |
| 186 | - | } | |
| 187 | - | if len(p.ring) != maxPresentRing-1 || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 1 { | |
| 188 | - | t.Fatalf("ring %d, first seq %d merged %d", len(p.ring), p.ring[0].Flip.Seq, p.ring[0].Flip.Merged) | |
| 189 | - | } | |
| 190 | - | } | |
| 191 | - | ||
| 192 | - | // A flip followed by a flip-less report of the same output is not lost: the | |
| 193 | - | // later report carries it. | |
| 194 | - | func TestPresentationRingKeepsFlipBeforeFliplessReport(t *testing.T) { | |
| 195 | - | p := ringOf("A", "A") | |
| 196 | - | p.ring[0].Flip = flipOf(7, 3) | |
| 197 | - | p.fill() | |
| 198 | - | p.ring = p.ring[:maxPresentRing] | |
| 199 | - | in := ports.OutputPresented{Output: "B", Flip: flipOf(9)} | |
| 200 | - | if p.makeRoomLocked(&in) { | |
| 201 | - | t.Fatal("no flips merged, yet reported") | |
| 202 | - | } | |
| 203 | - | if len(p.ring) != maxPresentRing-1 || p.ring[0].Output != "A" || p.ring[0].Flip == nil || p.ring[0].Flip.Seq != 7 || p.ring[0].Flip.Merged != 0 { | |
| 204 | - | t.Fatalf("flip lost: ring %d, first %+v", len(p.ring), p.ring[0]) | |
| 205 | - | } | |
| 206 | - | } | |
| 207 | - | ||
| 208 | - | // With several outputs interleaved, the victim is the oldest report that has | |
| 209 | - | // a successor of its own output; other outputs' reports are untouched. | |
| 210 | - | func TestPresentationRingInterleavedOutputs(t *testing.T) { | |
| 211 | - | p := ringOf("A", "B", "A", "B") | |
| 212 | - | p.ring[0].Flip, p.ring[1].Flip = flipOf(1, 10), flipOf(2, 20) | |
| 213 | - | p.ring[2].Flip, p.ring[3].Flip = flipOf(3, 11), nil | |
| 214 | - | p.fill() | |
| 215 | - | in := ports.OutputPresented{Output: "C"} | |
| 216 | - | if !p.makeRoomLocked(&in) { | |
| 217 | - | t.Fatal("merge not reported") | |
| 218 | - | } | |
| 219 | - | if p.ring[0].Output != "B" || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 0 { | |
| 220 | - | t.Fatalf("B's flip touched: %+v", p.ring[0]) | |
| 221 | - | } | |
| 222 | - | a := p.ring[1] | |
| 223 | - | if a.Output != "A" || a.Flip.Seq != 3 || a.Flip.Merged != 1 || a.Flip.Shows[10] != 1 || a.Flip.Shows[11] != 3 { | |
| 224 | - | t.Fatalf("A's flips not merged: %+v", a.Flip) | |
| 225 | - | } | |
| 226 | - | if p.ring[2].Output != "B" || p.ring[2].Flip != nil { | |
| 227 | - | t.Fatalf("B's flip-less report moved: %+v", p.ring[2]) | |
| 228 | - | } | |
| 229 | - | } | |
| 230 | - | ||
| 231 | - | // The incoming report counts as the successor of a ring report. | |
| 232 | - | func TestPresentationRingIncomingTakesOverFlip(t *testing.T) { | |
| 233 | - | p := ringOf("A") | |
| 234 | - | p.ring[0].Flip = flipOf(4) | |
| 235 | - | p.fill() | |
| 236 | - | in := ports.OutputPresented{Output: "A"} | |
| 237 | - | if p.makeRoomLocked(&in) { | |
| 238 | - | t.Fatal("no merge expected") | |
| 239 | - | } | |
| 240 | - | if in.Flip == nil || in.Flip.Seq != 4 || len(p.ring) != maxPresentRing-1 { | |
| 241 | - | t.Fatalf("incoming %+v, ring %d", in.Flip, len(p.ring)) | |
| 242 | - | } | |
| 243 | - | } | |
| 244 | - | ||
| 245 | - | // With no successor for any report (more outputs than ring slots) nothing is | |
| 246 | - | // dropped: the ring grows by one and every flip is still delivered. | |
| 247 | - | func TestPresentationRingWithoutSuccessorKeepsEverything(t *testing.T) { | |
| 248 | - | p := ringOf() | |
| 249 | - | for i := range maxPresentRing { | |
| 250 | - | p.ring = append(p.ring, ports.OutputPresented{Output: "o" + string(rune('A'+i/26)) + string(rune('a'+i%26)), Flip: flipOf(uint64(i + 1))}) | |
| 251 | - | } | |
| 252 | - | in := ports.OutputPresented{Output: "other", Flip: flipOf(99)} | |
| 253 | - | if p.makeRoomLocked(&in) || len(p.ring) != maxPresentRing { | |
| 254 | - | t.Fatalf("merged or dropped: ring %d", len(p.ring)) | |
| 177 | + | // makeRoomLocked on a full ring: which report it merges or moves, and what it | |
| 178 | + | // reports. | |
| 179 | + | func TestPresentationRingMakeRoom(t *testing.T) { | |
| 180 | + | tests := []struct { | |
| 181 | + | name string | |
| 182 | + | ring func() *presentSink | |
| 183 | + | in ports.OutputPresented | |
| 184 | + | wantMerged bool | |
| 185 | + | check func(t *testing.T, p *presentSink, in *ports.OutputPresented) | |
| 186 | + | }{ | |
| 187 | + | { | |
| 188 | + | // A full ring merges the oldest flip of an output into its next flip. | |
| 189 | + | name: "merges past the bound", | |
| 190 | + | ring: func() *presentSink { | |
| 191 | + | p := ringOf() | |
| 192 | + | for i := range maxPresentRing { | |
| 193 | + | p.ring = append(p.ring, ports.OutputPresented{Output: "A", Flip: flipOf(uint64(i + 1))}) | |
| 194 | + | } | |
| 195 | + | return p | |
| 196 | + | }, | |
| 197 | + | in: ports.OutputPresented{Output: "A", Flip: flipOf(maxPresentRing + 1)}, | |
| 198 | + | wantMerged: true, | |
| 199 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { | |
| 200 | + | if len(p.ring) != maxPresentRing-1 || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 1 { | |
| 201 | + | t.Fatalf("ring %d, first seq %d merged %d", len(p.ring), p.ring[0].Flip.Seq, p.ring[0].Flip.Merged) | |
| 202 | + | } | |
| 203 | + | }, | |
| 204 | + | }, | |
| 205 | + | { | |
| 206 | + | // A flip followed by a flip-less report of the same output is not | |
| 207 | + | // lost: the later report carries it. | |
| 208 | + | name: "keeps a flip before a flip-less report", | |
| 209 | + | ring: func() *presentSink { | |
| 210 | + | p := ringOf("A", "A") | |
| 211 | + | p.ring[0].Flip = flipOf(7, 3) | |
| 212 | + | p.fill() | |
| 213 | + | p.ring = p.ring[:maxPresentRing] | |
| 214 | + | return p | |
| 215 | + | }, | |
| 216 | + | in: ports.OutputPresented{Output: "B", Flip: flipOf(9)}, | |
| 217 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { | |
| 218 | + | if len(p.ring) != maxPresentRing-1 || p.ring[0].Output != "A" || p.ring[0].Flip == nil || p.ring[0].Flip.Seq != 7 || p.ring[0].Flip.Merged != 0 { | |
| 219 | + | t.Fatalf("flip lost: ring %d, first %+v", len(p.ring), p.ring[0]) | |
| 220 | + | } | |
| 221 | + | }, | |
| 222 | + | }, | |
| 223 | + | { | |
| 224 | + | // With several outputs interleaved, the victim is the oldest report | |
| 225 | + | // that has a successor of its own output; other outputs' reports are | |
| 226 | + | // untouched. | |
| 227 | + | name: "interleaved outputs", | |
| 228 | + | ring: func() *presentSink { | |
| 229 | + | p := ringOf("A", "B", "A", "B") | |
| 230 | + | p.ring[0].Flip, p.ring[1].Flip = flipOf(1, 10), flipOf(2, 20) | |
| 231 | + | p.ring[2].Flip, p.ring[3].Flip = flipOf(3, 11), nil | |
| 232 | + | p.fill() | |
| 233 | + | return p | |
| 234 | + | }, | |
| 235 | + | in: ports.OutputPresented{Output: "C"}, | |
| 236 | + | wantMerged: true, | |
| 237 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { | |
| 238 | + | if p.ring[0].Output != "B" || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 0 { | |
| 239 | + | t.Fatalf("B's flip touched: %+v", p.ring[0]) | |
| 240 | + | } | |
| 241 | + | a := p.ring[1] | |
| 242 | + | if a.Output != "A" || a.Flip.Seq != 3 || a.Flip.Merged != 1 || a.Flip.Shows[10] != 1 || a.Flip.Shows[11] != 3 { | |
| 243 | + | t.Fatalf("A's flips not merged: %+v", a.Flip) | |
| 244 | + | } | |
| 245 | + | if p.ring[2].Output != "B" || p.ring[2].Flip != nil { | |
| 246 | + | t.Fatalf("B's flip-less report moved: %+v", p.ring[2]) | |
| 247 | + | } | |
| 248 | + | }, | |
| 249 | + | }, | |
| 250 | + | { | |
| 251 | + | // The incoming report counts as the successor of a ring report. | |
| 252 | + | name: "incoming takes over a flip", | |
| 253 | + | ring: func() *presentSink { | |
| 254 | + | p := ringOf("A") | |
| 255 | + | p.ring[0].Flip = flipOf(4) | |
| 256 | + | p.fill() | |
| 257 | + | return p | |
| 258 | + | }, | |
| 259 | + | in: ports.OutputPresented{Output: "A"}, | |
| 260 | + | check: func(t *testing.T, p *presentSink, in *ports.OutputPresented) { | |
| 261 | + | if in.Flip == nil || in.Flip.Seq != 4 || len(p.ring) != maxPresentRing-1 { | |
| 262 | + | t.Fatalf("incoming %+v, ring %d", in.Flip, len(p.ring)) | |
| 263 | + | } | |
| 264 | + | }, | |
| 265 | + | }, | |
| 266 | + | { | |
| 267 | + | // With no successor for any report (more outputs than ring slots) | |
| 268 | + | // nothing is dropped: the ring grows by one and every flip is still | |
| 269 | + | // delivered. | |
| 270 | + | name: "without a successor keeps everything", | |
| 271 | + | ring: func() *presentSink { | |
| 272 | + | p := ringOf() | |
| 273 | + | for i := range maxPresentRing { | |
| 274 | + | p.ring = append(p.ring, ports.OutputPresented{Output: "o" + string(rune('A'+i/26)) + string(rune('a'+i%26)), Flip: flipOf(uint64(i + 1))}) | |
| 275 | + | } | |
| 276 | + | return p | |
| 277 | + | }, | |
| 278 | + | in: ports.OutputPresented{Output: "other", Flip: flipOf(99)}, | |
| 279 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { | |
| 280 | + | if len(p.ring) != maxPresentRing { | |
| 281 | + | t.Fatalf("merged or dropped: ring %d", len(p.ring)) | |
| 282 | + | } | |
| 283 | + | }, | |
| 284 | + | }, | |
| 285 | + | } | |
| 286 | + | for _, tt := range tests { | |
| 287 | + | t.Run(tt.name, func(t *testing.T) { | |
| 288 | + | p := tt.ring() | |
| 289 | + | in := tt.in | |
| 290 | + | if merged := p.makeRoomLocked(&in); merged != tt.wantMerged { | |
| 291 | + | t.Fatalf("merged %v, want %v", merged, tt.wantMerged) | |
| 292 | + | } | |
| 293 | + | tt.check(t, p, &in) | |
| 294 | + | }) | |
| 255 | 295 | } | |
| 256 | 296 | } | |
| 257 | 297 | ||
| @@ -174,84 +174,124 @@ func flipOf(seq uint64, shows ...ports.WindowID) *ports.FlipInfo { | |||||
| 174 | return f | 174 | return f | ||
| 175 | } | 175 | } | ||
| 176 | 176 | ||||
| 177 | - | // A full ring merges the oldest flip of an output into its next flip. | 177 | + | // makeRoomLocked on a full ring: which report it merges or moves, and what it |
| 178 | - | func TestPresentationRingMergesPastBound(t *testing.T) { | 178 | + | // reports. |
| 179 | - | p := ringOf() | 179 | + | func TestPresentationRingMakeRoom(t *testing.T) { |
| 180 | - | for i := range maxPresentRing { | 180 | + | tests := []struct { |
| 181 | - | p.ring = append(p.ring, ports.OutputPresented{Output: "A", Flip: flipOf(uint64(i + 1))}) | 181 | + | name string |
| 182 | - | } | 182 | + | ring func() *presentSink |
| 183 | - | in := ports.OutputPresented{Output: "A", Flip: flipOf(maxPresentRing + 1)} | 183 | + | in ports.OutputPresented |
| 184 | - | if !p.makeRoomLocked(&in) { | 184 | + | wantMerged bool |
| 185 | - | t.Fatal("two flips merged but not reported") | 185 | + | check func(t *testing.T, p *presentSink, in *ports.OutputPresented) |
| 186 | - | } | 186 | + | }{ |
| 187 | - | if len(p.ring) != maxPresentRing-1 || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 1 { | 187 | + | { |
| 188 | - | t.Fatalf("ring %d, first seq %d merged %d", len(p.ring), p.ring[0].Flip.Seq, p.ring[0].Flip.Merged) | 188 | + | // A full ring merges the oldest flip of an output into its next flip. |
| 189 | - | } | 189 | + | name: "merges past the bound", |
| 190 | - | } | 190 | + | ring: func() *presentSink { |
| 191 | - | 191 | + | p := ringOf() | |
| 192 | - | // A flip followed by a flip-less report of the same output is not lost: the | 192 | + | for i := range maxPresentRing { |
| 193 | - | // later report carries it. | 193 | + | p.ring = append(p.ring, ports.OutputPresented{Output: "A", Flip: flipOf(uint64(i + 1))}) |
| 194 | - | func TestPresentationRingKeepsFlipBeforeFliplessReport(t *testing.T) { | 194 | + | } |
| 195 | - | p := ringOf("A", "A") | 195 | + | return p |
| 196 | - | p.ring[0].Flip = flipOf(7, 3) | 196 | + | }, |
| 197 | - | p.fill() | 197 | + | in: ports.OutputPresented{Output: "A", Flip: flipOf(maxPresentRing + 1)}, |
| 198 | - | p.ring = p.ring[:maxPresentRing] | 198 | + | wantMerged: true, |
| 199 | - | in := ports.OutputPresented{Output: "B", Flip: flipOf(9)} | 199 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { |
| 200 | - | if p.makeRoomLocked(&in) { | 200 | + | if len(p.ring) != maxPresentRing-1 || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 1 { |
| 201 | - | t.Fatal("no flips merged, yet reported") | 201 | + | t.Fatalf("ring %d, first seq %d merged %d", len(p.ring), p.ring[0].Flip.Seq, p.ring[0].Flip.Merged) |
| 202 | - | } | 202 | + | } |
| 203 | - | if len(p.ring) != maxPresentRing-1 || p.ring[0].Output != "A" || p.ring[0].Flip == nil || p.ring[0].Flip.Seq != 7 || p.ring[0].Flip.Merged != 0 { | 203 | + | }, |
| 204 | - | t.Fatalf("flip lost: ring %d, first %+v", len(p.ring), p.ring[0]) | 204 | + | }, |
| 205 | - | } | 205 | + | { |
| 206 | - | } | 206 | + | // A flip followed by a flip-less report of the same output is not |
| 207 | - | 207 | + | // lost: the later report carries it. | |
| 208 | - | // With several outputs interleaved, the victim is the oldest report that has | 208 | + | name: "keeps a flip before a flip-less report", |
| 209 | - | // a successor of its own output; other outputs' reports are untouched. | 209 | + | ring: func() *presentSink { |
| 210 | - | func TestPresentationRingInterleavedOutputs(t *testing.T) { | 210 | + | p := ringOf("A", "A") |
| 211 | - | p := ringOf("A", "B", "A", "B") | 211 | + | p.ring[0].Flip = flipOf(7, 3) |
| 212 | - | p.ring[0].Flip, p.ring[1].Flip = flipOf(1, 10), flipOf(2, 20) | 212 | + | p.fill() |
| 213 | - | p.ring[2].Flip, p.ring[3].Flip = flipOf(3, 11), nil | 213 | + | p.ring = p.ring[:maxPresentRing] |
| 214 | - | p.fill() | 214 | + | return p |
| 215 | - | in := ports.OutputPresented{Output: "C"} | 215 | + | }, |
| 216 | - | if !p.makeRoomLocked(&in) { | 216 | + | in: ports.OutputPresented{Output: "B", Flip: flipOf(9)}, |
| 217 | - | t.Fatal("merge not reported") | 217 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { |
| 218 | - | } | 218 | + | if len(p.ring) != maxPresentRing-1 || p.ring[0].Output != "A" || p.ring[0].Flip == nil || p.ring[0].Flip.Seq != 7 || p.ring[0].Flip.Merged != 0 { |
| 219 | - | if p.ring[0].Output != "B" || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 0 { | 219 | + | t.Fatalf("flip lost: ring %d, first %+v", len(p.ring), p.ring[0]) |
| 220 | - | t.Fatalf("B's flip touched: %+v", p.ring[0]) | 220 | + | } |
| 221 | - | } | 221 | + | }, |
| 222 | - | a := p.ring[1] | 222 | + | }, |
| 223 | - | if a.Output != "A" || a.Flip.Seq != 3 || a.Flip.Merged != 1 || a.Flip.Shows[10] != 1 || a.Flip.Shows[11] != 3 { | 223 | + | { |
| 224 | - | t.Fatalf("A's flips not merged: %+v", a.Flip) | 224 | + | // With several outputs interleaved, the victim is the oldest report |
| 225 | - | } | 225 | + | // that has a successor of its own output; other outputs' reports are |
| 226 | - | if p.ring[2].Output != "B" || p.ring[2].Flip != nil { | 226 | + | // untouched. |
| 227 | - | t.Fatalf("B's flip-less report moved: %+v", p.ring[2]) | 227 | + | name: "interleaved outputs", |
| 228 | - | } | 228 | + | ring: func() *presentSink { |
| 229 | - | } | 229 | + | p := ringOf("A", "B", "A", "B") |
| 230 | - | 230 | + | p.ring[0].Flip, p.ring[1].Flip = flipOf(1, 10), flipOf(2, 20) | |
| 231 | - | // The incoming report counts as the successor of a ring report. | 231 | + | p.ring[2].Flip, p.ring[3].Flip = flipOf(3, 11), nil |
| 232 | - | func TestPresentationRingIncomingTakesOverFlip(t *testing.T) { | 232 | + | p.fill() |
| 233 | - | p := ringOf("A") | 233 | + | return p |
| 234 | - | p.ring[0].Flip = flipOf(4) | 234 | + | }, |
| 235 | - | p.fill() | 235 | + | in: ports.OutputPresented{Output: "C"}, |
| 236 | - | in := ports.OutputPresented{Output: "A"} | 236 | + | wantMerged: true, |
| 237 | - | if p.makeRoomLocked(&in) { | 237 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { |
| 238 | - | t.Fatal("no merge expected") | 238 | + | if p.ring[0].Output != "B" || p.ring[0].Flip.Seq != 2 || p.ring[0].Flip.Merged != 0 { |
| 239 | - | } | 239 | + | t.Fatalf("B's flip touched: %+v", p.ring[0]) |
| 240 | - | if in.Flip == nil || in.Flip.Seq != 4 || len(p.ring) != maxPresentRing-1 { | 240 | + | } |
| 241 | - | t.Fatalf("incoming %+v, ring %d", in.Flip, len(p.ring)) | 241 | + | a := p.ring[1] |
| 242 | - | } | 242 | + | if a.Output != "A" || a.Flip.Seq != 3 || a.Flip.Merged != 1 || a.Flip.Shows[10] != 1 || a.Flip.Shows[11] != 3 { |
| 243 | - | } | 243 | + | t.Fatalf("A's flips not merged: %+v", a.Flip) |
| 244 | - | 244 | + | } | |
| 245 | - | // With no successor for any report (more outputs than ring slots) nothing is | 245 | + | if p.ring[2].Output != "B" || p.ring[2].Flip != nil { |
| 246 | - | // dropped: the ring grows by one and every flip is still delivered. | 246 | + | t.Fatalf("B's flip-less report moved: %+v", p.ring[2]) |
| 247 | - | func TestPresentationRingWithoutSuccessorKeepsEverything(t *testing.T) { | 247 | + | } |
| 248 | - | p := ringOf() | 248 | + | }, |
| 249 | - | for i := range maxPresentRing { | 249 | + | }, |
| 250 | - | p.ring = append(p.ring, ports.OutputPresented{Output: "o" + string(rune('A'+i/26)) + string(rune('a'+i%26)), Flip: flipOf(uint64(i + 1))}) | 250 | + | { |
| 251 | - | } | 251 | + | // The incoming report counts as the successor of a ring report. |
| 252 | - | in := ports.OutputPresented{Output: "other", Flip: flipOf(99)} | 252 | + | name: "incoming takes over a flip", |
| 253 | - | if p.makeRoomLocked(&in) || len(p.ring) != maxPresentRing { | 253 | + | ring: func() *presentSink { |
| 254 | - | t.Fatalf("merged or dropped: ring %d", len(p.ring)) | 254 | + | p := ringOf("A") |
| 255 | + | p.ring[0].Flip = flipOf(4) | |||
| 256 | + | p.fill() | |||
| 257 | + | return p | |||
| 258 | + | }, | |||
| 259 | + | in: ports.OutputPresented{Output: "A"}, | |||
| 260 | + | check: func(t *testing.T, p *presentSink, in *ports.OutputPresented) { | |||
| 261 | + | if in.Flip == nil || in.Flip.Seq != 4 || len(p.ring) != maxPresentRing-1 { | |||
| 262 | + | t.Fatalf("incoming %+v, ring %d", in.Flip, len(p.ring)) | |||
| 263 | + | } | |||
| 264 | + | }, | |||
| 265 | + | }, | |||
| 266 | + | { | |||
| 267 | + | // With no successor for any report (more outputs than ring slots) | |||
| 268 | + | // nothing is dropped: the ring grows by one and every flip is still | |||
| 269 | + | // delivered. | |||
| 270 | + | name: "without a successor keeps everything", | |||
| 271 | + | ring: func() *presentSink { | |||
| 272 | + | p := ringOf() | |||
| 273 | + | for i := range maxPresentRing { | |||
| 274 | + | p.ring = append(p.ring, ports.OutputPresented{Output: "o" + string(rune('A'+i/26)) + string(rune('a'+i%26)), Flip: flipOf(uint64(i + 1))}) | |||
| 275 | + | } | |||
| 276 | + | return p | |||
| 277 | + | }, | |||
| 278 | + | in: ports.OutputPresented{Output: "other", Flip: flipOf(99)}, | |||
| 279 | + | check: func(t *testing.T, p *presentSink, _ *ports.OutputPresented) { | |||
| 280 | + | if len(p.ring) != maxPresentRing { | |||
| 281 | + | t.Fatalf("merged or dropped: ring %d", len(p.ring)) | |||
| 282 | + | } | |||
| 283 | + | }, | |||
| 284 | + | }, | |||
| 285 | + | } | |||
| 286 | + | for _, tt := range tests { | |||
| 287 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 288 | + | p := tt.ring() | |||
| 289 | + | in := tt.in | |||
| 290 | + | if merged := p.makeRoomLocked(&in); merged != tt.wantMerged { | |||
| 291 | + | t.Fatalf("merged %v, want %v", merged, tt.wantMerged) | |||
| 292 | + | } | |||
| 293 | + | tt.check(t, p, &in) | |||
| 294 | + | }) | |||
| 255 | } | 295 | } | ||
| 256 | } | 296 | } | ||
| 257 | 297 | ||||