stop()
})
t.Run("stop", func(t *testing.T) {
- next, stop := Pull(panicSeq())
+ next, stop := Pull(panicCleanupSeq())
+ x, ok := next()
+ if !ok || x != 55 {
+ t.Fatalf("expected (55, true) from next, got (%d, %t)", x, ok)
+ }
if !panicsWith("boom", func() { stop() }) {
- t.Fatal("failed to propagate panic on first stop")
+ t.Fatal("failed to propagate panic on stop")
}
// Make sure we don't panic again if we try to call next or stop.
if _, ok := next(); ok {
}
}
+func panicCleanupSeq() Seq[int] {
+ return func(yield func(int) bool) {
+ for {
+ if !yield(55) {
+ panic("boom")
+ }
+ }
+ }
+}
+
func TestPull2Panic(t *testing.T) {
t.Run("next", func(t *testing.T) {
next, stop := Pull2(panicSeq2())
stop()
})
t.Run("stop", func(t *testing.T) {
- next, stop := Pull2(panicSeq2())
+ next, stop := Pull2(panicCleanupSeq2())
+ x, y, ok := next()
+ if !ok || x != 55 || y != 100 {
+ t.Fatalf("expected (55, 100, true) from next, got (%d, %d, %t)", x, y, ok)
+ }
if !panicsWith("boom", func() { stop() }) {
- t.Fatal("failed to propagate panic on first stop")
+ t.Fatal("failed to propagate panic on stop")
}
// Make sure we don't panic again if we try to call next or stop.
if _, _, ok := next(); ok {
}
}
+func panicCleanupSeq2() Seq2[int, int] {
+ return func(yield func(int, int) bool) {
+ for {
+ if !yield(55, 100) {
+ panic("boom")
+ }
+ }
+ }
+}
+
func panicsWith(v any, f func()) (panicked bool) {
defer func() {
if r := recover(); r != nil {
t.Fatal("failed to Goexit from next")
}
if x, ok := next(); x != 0 || ok {
- t.Fatal("iterator returned valid value after Goexit")
+ t.Fatal("iterator returned valid value after iterator Goexited")
}
stop()
})
t.Run("stop", func(t *testing.T) {
- var next func() (int, bool)
- var stop func()
+ next, stop := Pull(goexitCleanupSeq())
+ x, ok := next()
+ if !ok || x != 55 {
+ t.Fatalf("expected (55, true) from next, got (%d, %t)", x, ok)
+ }
if !goexits(t, func() {
- next, stop = Pull(goexitSeq())
stop()
}) {
t.Fatal("failed to Goexit from stop")
}
+ // Make sure we don't panic again if we try to call next or stop.
if x, ok := next(); x != 0 || ok {
- t.Fatal("iterator returned valid value after Goexit")
+ t.Fatal("next returned true or non-zero value after iterator Goexited")
}
+ // Calling stop again should be a no-op.
stop()
})
}
}
}
+func goexitCleanupSeq() Seq[int] {
+ return func(yield func(int) bool) {
+ for {
+ if !yield(55) {
+ runtime.Goexit()
+ }
+ }
+ }
+}
+
func TestPull2Goexit(t *testing.T) {
t.Run("next", func(t *testing.T) {
var next func() (int, int, bool)
t.Fatal("failed to Goexit from next")
}
if x, y, ok := next(); x != 0 || y != 0 || ok {
- t.Fatal("iterator returned valid value after Goexit")
+ t.Fatal("iterator returned valid value after iterator Goexited")
}
stop()
})
t.Run("stop", func(t *testing.T) {
- var next func() (int, int, bool)
- var stop func()
+ next, stop := Pull2(goexitCleanupSeq2())
+ x, y, ok := next()
+ if !ok || x != 55 || y != 100 {
+ t.Fatalf("expected (55, 100, true) from next, got (%d, %d, %t)", x, y, ok)
+ }
if !goexits(t, func() {
- next, stop = Pull2(goexitSeq2())
stop()
}) {
t.Fatal("failed to Goexit from stop")
}
+ // Make sure we don't panic again if we try to call next or stop.
if x, y, ok := next(); x != 0 || y != 0 || ok {
- t.Fatal("iterator returned valid value after Goexit")
+ t.Fatal("next returned true or non-zero after iterator Goexited")
}
+ // Calling stop again should be a no-op.
stop()
})
}
}
}
+func goexitCleanupSeq2() Seq2[int, int] {
+ return func(yield func(int, int) bool) {
+ for {
+ if !yield(55, 100) {
+ runtime.Goexit()
+ }
+ }
+ }
+}
+
func goexits(t *testing.T, f func()) bool {
t.Helper()
}()
return <-exit
}
+
+func TestPullImmediateStop(t *testing.T) {
+ next, stop := Pull(panicSeq())
+ stop()
+ // Make sure we don't panic if we try to call next or stop.
+ if _, ok := next(); ok {
+ t.Fatal("next returned true after iterator was stopped")
+ }
+}
+
+func TestPull2ImmediateStop(t *testing.T) {
+ next, stop := Pull2(panicSeq2())
+ stop()
+ // Make sure we don't panic if we try to call next or stop.
+ if _, _, ok := next(); ok {
+ t.Fatal("next returned true after iterator was stopped")
+ }
+}