Try something like github.com/facebookgo/clock
On Thursday, 28 January 2021 at 21:15:50 UTC Christian Worm Mortensen wrote: > Hi! > > Suppose I want to unit test this function: > > func generator() <-chan int { > ret := make(chan int) > go func() { > for i := 0; i < 10; i++ { > ret <- i > time.Sleep(time.Second) > } > }() > return ret > } > > What is a good way to do that? One way is to do it is like this: > > func testGenerator() { > start := time.Now() > g := generator() > for i := 0; i < 10; i++ { > v := <-g > if v != i { > panic("Wrong value") > } > } > elapsed := time.Now().Sub(start) > if elapsed < 9*time.Second || elapsed > 11*time.Second { > panic("Wrong execution time") > } > } > > However there are several issues with this: > > 1) The unit test takes a long time to run - 10 seconds. > 2) The unit test is fragile to fluctuations in CPU availability > 3) The unit test is not very accurate > > Of course this is a simple example. But what if I want to test a > complicated piece of code with many go routines interacting in complicated > ways and with long timeouts? > > In other programming languages, I have been able to implement a form of > virtual time which increases only when all threads are waiting for time to > increase. This allows functions like generator above to be tested basically > instantly and this has been extremely useful for me in many projects over > the years. > > Can I do something similar in Go? I would expect I would need to wrap > time.Now, time.Sleep and time.After which I will be happy to do. > > I can see that Go has a deadlock detector. If somehow it was possible to > have Go start a new Go routine when a deadlock was detected, I think it > would be pretty straight forward to implement virtual time as described. I > could then do something like: > > runtime.registerDeadlockCallback(func () { > // Increase virtual time and by that: > // * Make one or more wrapped time.Sleep calls return or > // * Write to one or more channels returned by wrapped time.After. > }) > > Obviously this would only be needed for test code, not production code. > > Thanks, > > Christian > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/d58a4e2a-eead-4ec9-b9a9-c0a43a699e89n%40googlegroups.com.