-
Notifications
You must be signed in to change notification settings - Fork 78
Closed
Description
I'd like to use the dataloaders in a unit test with synctest in go 1.25. However, there is an issue with this test:
package goexp1_test
import (
"context"
"strconv"
"testing"
"testing/synctest"
"time"
"github.com/graph-gophers/dataloader/v7"
)
func TestDataLoaderSync(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
dl := dataloader.NewBatchedLoader(func(ctx context.Context, ints []int) []*dataloader.Result[string] {
// simple resolve function that "resolves" an int into a string
results := make([]*dataloader.Result[string], len(ints))
for i := range ints {
results[i] = &dataloader.Result[string]{
Data: strconv.Itoa(ints[i]),
}
}
return results
})
t1 := dl.LoadMany(t.Context(), []int{1})
time.Sleep(10 * time.Millisecond) // data loaders default batch time is 16ms so make it less
t2 := dl.LoadMany(t.Context(), []int{1})
t1()
t2()
})
}
The simulated time does not advance because it's not durably blocked. Here is the state that the program is in:
goexp1 % go test ./... -timeout 5s
panic: test timed out after 5s
running tests:
TestDataLoaderSync (5s)
goroutine 40 [running]:
testing.(*M).startAlarm.func1()
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:2682 +0x2b0
created by time.goFunc
/opt/homebrew/Cellar/go/1.25.1/libexec/src/time/sleep.go:215 +0x38
goroutine 1 [chan receive]:
testing.(*T).Run(0x14000102380, {0x102fa5ee2?, 0x14000118b38?}, 0x1030265c0)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:2005 +0x378
testing.runTests.func1(0x14000102380)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:2477 +0x38
testing.tRunner(0x14000102380, 0x14000118c68)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:1934 +0xc8
testing.runTests(0x1400012c018, {0x10311cc60, 0x1, 0x1}, {0x14000130160?, 0x7?, 0x103126b00?})
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:2475 +0x3b8
testing.(*M).Run(0x1400011c140)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:2337 +0x530
main.main()
_testmain.go:45 +0x80
goroutine 35 [synctest.Run (durable), synctest bubble 1]:
internal/synctest.Run(0x140001301a0)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/runtime/synctest.go:218 +0x1b4
testing/synctest.Test(0x14000102540, 0x103026650)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/synctest/synctest.go:282 +0x88
goexp1_test.TestDataLoaderSync(0x14000102540?)
/Users/harry/GolandProjects/goexp1/dl_test.go:14 +0x24
testing.tRunner(0x14000102540, 0x1030265c0)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:1934 +0xc8
created by testing.(*T).Run in goroutine 1
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:1997 +0x364
goroutine 36 [chan receive (durable), synctest bubble 1]:
testing/synctest.testingSynctestTest(0x14000102540, 0x103026650)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:2047 +0x210
testing/synctest.Test.func1()
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/synctest/synctest.go:283 +0x28
created by testing/synctest.Test in goroutine 35
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/synctest/synctest.go:282 +0x88
goroutine 37 [chan receive (durable), synctest bubble 1]:
github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany.func3()
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:387 +0x114
goexp1_test.TestDataLoaderSync.func1(0x14000102a80)
/Users/harry/GolandProjects/goexp1/dl_test.go:29 +0x104
testing.tRunner(0x14000102a80, 0x103026650)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:1934 +0xc8
created by testing/synctest.testingSynctestTest in goroutine 36
/opt/homebrew/Cellar/go/1.25.1/libexec/src/testing/testing.go:2046 +0x1fc
goroutine 38 [chan receive (durable), synctest bubble 1]:
github.com/graph-gophers/dataloader/v7.(*Loader[...]).Load.func1()
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:263 +0x154
github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany.func1(0x0?)
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:348 +0xa0
created by github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany in goroutine 37
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:355 +0x17c
goroutine 39 [sync.WaitGroup.Wait (durable), synctest bubble 1]:
sync.runtime_SemacquireWaitGroup(0x0?, 0x0?)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/runtime/sema.go:114 +0x38
sync.(*WaitGroup).Wait(0x140001100c0)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/sync/waitgroup.go:206 +0xa8
github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany.func2()
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:359 +0x48
created by github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany in goroutine 37
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:358 +0x254
goroutine 2 [chan receive (durable), synctest bubble 1]:
github.com/graph-gophers/dataloader/v7.(*batcher[...]).batch(0x103029860, {0x1030289d8, 0x1400015c140})
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:475 +0xc4
created by github.com/graph-gophers/dataloader/v7.(*Loader[...]).Load in goroutine 38
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:289 +0x4c4
goroutine 3 [select (durable), synctest bubble 1]:
github.com/graph-gophers/dataloader/v7.(*Loader[...]).sleeper(0x10302a2a0, 0x14000072000, 0x14000074000)
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:535 +0x64
created by github.com/graph-gophers/dataloader/v7.(*Loader[...]).Load in goroutine 38
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:292 +0x574
goroutine 20 [sync.RWMutex.RLock, synctest bubble 1]:
sync.runtime_SemacquireRWMutexR(0x1400015c140?, 0xe0?, 0x0?)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/runtime/sema.go:100 +0x28
sync.(*RWMutex).RLock(...)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/sync/rwmutex.go:74
github.com/graph-gophers/dataloader/v7.(*Loader[...]).Load.func1()
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:257 +0xa8
github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany.func1(0x0?)
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:348 +0xa0
created by github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany in goroutine 37
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:355 +0x17c
goroutine 21 [sync.WaitGroup.Wait (durable), synctest bubble 1]:
sync.runtime_SemacquireWaitGroup(0x0?, 0x0?)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/runtime/sema.go:114 +0x38
sync.(*WaitGroup).Wait(0x14000096010)
/opt/homebrew/Cellar/go/1.25.1/libexec/src/sync/waitgroup.go:206 +0xa8
github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany.func2()
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:359 +0x48
created by github.com/graph-gophers/dataloader/v7.(*Loader[...]).LoadMany in goroutine 37
/Users/harry/go/pkg/mod/github.com/graph-gophers/dataloader/v7@v7.1.2/dataloader.go:358 +0x254
FAIL goexp1 5.168s
FAIL
I initially thought it was a bug with synctest, but it was explained: golang/go#75626
The problem is that "waiting" on a mutex isn't "waiting" as for as synctest is concerned. I think the Thunk and ThunkMany logic can be simplified and work with synctest.
Metadata
Metadata
Assignees
Labels
No labels