[HN Gopher] Quartz: A Deterministic Time Testing Library for Go
___________________________________________________________________
Quartz: A Deterministic Time Testing Library for Go
Author : ammario
Score : 127 points
Date : 2024-07-15 18:30 UTC (1 days ago)
(HTM) web link (coder.com)
(TXT) w3m dump (coder.com)
| wizzard0 wrote:
| Very cool! Anything similar for .net?
| neonsunset wrote:
| Comes out of box: https://devblogs.microsoft.com/dotnet/fake-
| it-til-you-make-i...
|
| This is yet another area where .NET offers a better package,
| unfortunately Go community is too self-centered to notice
| what's happening elsewhere.
| lloydatkinson wrote:
| I was about to comment the same - even before ITimeProvider
| existed it was already very common to have an ITime or IDate
| or IDateTime etc that would then be implemented as you need
| for tests.
|
| Having this now as a built-in is excellent.
| Thaxll wrote:
| .NET 8 released 5 months ago, what are you talking about?
| neonsunset wrote:
| It was released 8 months ago. It seems this implies some
| sort of argument, could you expand on that?
| Thaxll wrote:
| OP ask for a similar pattern for .net, you come here with
| unnecessary aggressive stance on something that was
| released 8 month ago, looking at your history it does not
| surprises though since you seems to have a grudge with
| Go.
| neonsunset wrote:
| You are misreading this as aggression towards OP, which
| there is none. Instead, this is a general despair at the
| damage done to our industry by Go and its community that
| keeps touting this mediocre language with weak compiler,
| unsound ecosystem, many footguns, lackluster type system
| and backwards design as something that can even remotely
| hope to compete with Rust or current state of C#.
| dalyons wrote:
| They're in every thread that mentions go, calling it
| terrible and saying people are idiots for not using c#
| instead.
|
| It's become predictable and tiring
| wizzard0 wrote:
| Um, yes, TimeProvider is cool but works only insofar as ...
|
| > If you provide a fake time provider in all those places
|
| I'm looking for something more akin to
| https://go.dev/issue/67434 (i.e. testing the code that calls
| third-party libraries that might just call Thread.Sleep and
| so on)
| dang wrote:
| Can you please stop posting language flamewar comments to HN?
| It's the kind of thing we're trying to avoid here, and you've
| unfortunately been doing it repeatedly.
|
| https://news.ycombinator.com/newsguidelines.html
| neonsunset wrote:
| Alright :)
| playingalong wrote:
| It feels like every second, sorry every other time-related
| library is called Quartz.
| rob74 wrote:
| Well, in PHP the de facto standard library is called Carbon (as
| in radiocarbon dating I guess - which is different, but at the
| risk of sounding, well, fossilized)
| Joker_vD wrote:
| Yeah, why not something like Klepsudra?
| elchief wrote:
| not a great name considering Quartz schedular for java...
| lloydatkinson wrote:
| Or for .NET
| lloydatkinson wrote:
| only on HN would a .NET comment get downvoted
| devjab wrote:
| Why would you say that? It's an archaic framework which
| sticks around because it's "good enough" for anything with
| a complexity low enough to be handled by its "magic". As
| soon as you need something to scale or handle real
| complexity where you have to step outside all the comfort
| zone .net developers tend to operate in, it's one of the
| worst frameworks that will constantly get in your way.
|
| It's also an ecosystem riddled with traps that is still so
| stuck in its OOP past that very few programming languages
| operating on it are even capable of having functions
| without a class object.
|
| Don't get me wrong. It's a good language when you're
| building relatively simple backend APIs that are small
| enough that they can actually use things like entity
| framework. Even more so if you're putting them into Azure
| and letting your security be handled by EntraID.
|
| But how many people on HN do you expect that is?
| neonsunset wrote:
| This may be your personal experience but it is used
| successfully and happily by many in a variety of domains
| way different to "boring OOP back-ends". No popular
| general purpose language is confined to a single scenario
| the way you describe (even Swift and Kotlin are
| expanding). C# lets you do things like writing a
| competitive Redis implementation[0], advanced physics
| engine that beats Jolt[1] or a game engine that does not
| rely on C++ or C[2], cross-platform applications[3] and
| so on and so forth. It is possible to successfully do
| both high level FP style approach for business domain
| modeling and very low-level data crunching that is
| competitive with systems programming languages.
|
| [0]: https://microsoft.github.io/garnet/docs/benchmarking
| /results...
|
| [1]: https://github.com/bepu/bepuphysics2
|
| [2]: https://www.stride3d.net
|
| [3]: https://avaloniaui.net
| 01HNNWZ0MV43FF wrote:
| Or Quartz Composer, the rendering thingy for macOS
| zikani_03 wrote:
| In particular, there is also another library for task
| scheduling named go-quartz: https://github.com/reugn/go-quartz.
|
| Naming is indeed hard.
| neild wrote:
| Of possible interest to anyone testing concurrent Go code in
| general and time in particular, a proposed standard library
| package: https://go.dev/issue/67434
| matttproud wrote:
| This looks infinitely preferable.
| padraicmahoney wrote:
| What do you like better about it?
|
| --- (btw: just read your blog on R -- love it)
| slantedview wrote:
| I'm curious if the author of Quartz has seen this proposal and
| could provide a comparison?
| spikecurtis1 wrote:
| I'm Quartz's primary author, and I hadn't seen this proposal
| until today.
|
| They are similar in the sense of using a faked clock to make
| things deterministic. Other than not having to inject the
| Clock interface, tests using Quartz will probably look fairly
| similar to this proposal in many cases.
|
| The proposal has a simpler API than Quartz, being able to
| just run some goroutines and wait until everything is
| blocked.
|
| However, this brings some limitations on what can be tested,
| such as time elapsing while computation is occurring (not
| just elapsing while things are waiting for something else).
| IMO this is an important limitation, as many interesting
| time-of-check, time-of-use bugs and edge cases occur because
| time does elapse during computation in real systems.
|
| An example of this from coder/coder that motivated the design
| of Quartz's API: https://github.com/coder/coder/blob/a5e4bf38
| fec66c5e7ecc96b0...
| Groxx wrote:
| That looks amazing. Advancing time while things are idle sounds
| practically perfect, and that's _essentially_ impossible to
| build as a library. As much as I like the sound of Quartz (the
| issues they call out are real and very painful and I was
| getting close to building my own version to solve some), that
| issue might remove my need for it entirely.
| bheadmaster wrote:
| Thanks for sharing this. This is one of the best testing
| features I've ever seen - I've had so many troubles with timing
| tests and refactoring around them. I really hope this gets
| merged.
| oefrha wrote:
| Related: the behavior of time in this proposal was implemented
| in Go playground more than a decade ago:
| https://go.dev/blog/playground#faking-time. Unfortunately it
| was never exposed.
| jerf wrote:
| I still don't like that it assumes global monotonic time. It is
| completely possible for an event to be scheduled in 100ms on
| one thread and in 200ms in another, and for the latter to run
| and/or finish first. A time testing system ought to let you
| test that case, because you're going to hit it in production.
|
| For that you really have no choice but to abandon the time
| package's API anyhow because you're going to need some way to
| trigger those things out-of-order.
|
| I've been using this for a while now:
| https://github.com/thejerf/abtime (my package) and it really
| lets me get down and dirty with order of operations, when that
| matters.
| wolfspaw wrote:
| Nice, Golang is Awesome!
| myvoiceismypass wrote:
| Why is Golang awesome? Because in 2024 there is now a decent
| mock clock library for testing? I thought that one of go's
| selling points was the stdlib and tooling being great out of
| the box?
| nsguy wrote:
| I have a fair bit of experience writing tests for concurrent code
| that uses timers on Go. We started with an open source test
| library ( https://pkg.go.dev/github.com/benbjohnson/clock ). It
| had a lot of problems. This was many years ago, looks like it's
| seen some maintenance since so maybe it's better? Then we tried
| to fix it. Fixed all the obvious bugs but still had a lot of
| problems using it in practice. It's not enough to just handle the
| calls without context of who is calling them in concurrent code.
| Then we switched to using gomock which ended up also being hard
| to use.
|
| It's quite tricky is sort of the bottom line. It's not enough to
| just create fake time there's a lot more to it.
| jiveturkey wrote:
| It's been abandoned/archived. I've since been using
| github.com/jonboulle/clockwork which is much less problematic.
| For my use it is perfectly fine.
| alpb wrote:
| I think https://pkg.go.dev/k8s.io/utils/clock and
| https://pkg.go.dev/k8s.io/utils/clock/testing is already doing
| these?
| Groxx wrote:
| At a glance, that looks almost identical to (an older version
| of) https://github.com/jonboulle/clockwork (there are several
| that are structurally very similar)
|
| In which case no, it falls into the same kind of issues that
| the post is describing as being problematic.
| rmetzler wrote:
| For linux, there is faketime, which will set a specific date and
| time for all child processes. This enables you to test software
| you don't even compile for time-based problems, e.g. logic around
| Feb 29th or daylight saving time.
| zokier wrote:
| LD_PRELOAD is bit yucky though in my opinion. I suppose ptrace
| is the only other option though :/
| deivid wrote:
| It's not the _only_ other option! It 's not less yucky, but
| you can creatively stomp on the vDSO functions which back the
| time-related functions (gettimeofday, clock_gettime, time);
| I've written about it at [0] and have a "library" (more like
| a proof of concept) at [1].
|
| [0]: https://blog.davidv.dev/posts/cursing-a-process-vdso-
| for-tim...
|
| [1]: https://github.com/DavidVentura/tpom
| TheDong wrote:
| Since go don't use the libc related time functions on linux,
| but rather makes syscalls directly, faketime will not work for
| any programs written in Go.
| jamesrr39 wrote:
| At the risk of appearing low-tech, a much more simple, Goroutine-
| safe solution for dealing with "now-dependent" code:
|
| type NowFunc func() time.Time
|
| func getGreeting(nowFunc NowFunc) string { now :=
| nowFunc() if now.Hour() < 12 { return
| "Good Morning" } return "Good day"
|
| }
|
| And just pass in `time.Now` in for live code, and your own inline
| function for simulating a time in tests.
___________________________________________________________________
(page generated 2024-07-16 23:01 UTC)