<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif">On Fri, Aug 16, 2019 at 12:36 PM Torben Hoffmann <<a href="mailto:torben.lehoff@gmail.com">torben.lehoff@gmail.com</a>> wrote:</span><br></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">When testing I prefer to mock time so that I don't have to wait for the timeout to occur.<br></div><div class="gmail_quote"><div></div></div></div></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">The key observation is this:</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">You want time to be an injected parameter.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">First, note that there is no concept of "now". Any call to e.g., `erlang:monotonic_time()` is behind as soon as your code has that value, by a small epsilon. In many cases, it is late by a lot; several milliseconds. So it is better to have your code take a parameter which is a point in time. When this is received, you roll time forward to that point in your internal state.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Second, timers are the scourge of testing. They are side-effects which means they are usually handled by mocking. And mocking is never the answer if there is a decent way around it. However, if a timer turns into a message, then we can choose to have timers handled outside the component and then send messages into the component. This helps testing, as we can run with a time-compression component, removing typical long waits in our test cases. In fact, separation of effects from computation is almost always a win for code in general.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Third, in systems you want a clock that is stationary and only moves when you call `advance_time(Ms)` or something such. A clock which moves behind your back is just going to create a lot of havoc in your code and computation. So it is better to ignore the real physical world, and then use messaging to handle the advance of the clock.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">When I did some QuickCheck work, I built up a submodel which plays the role as the internal erlang timers. This means the model can simulate timers in the system and make choices as to when a timer fires, when time advances, what the interesting timestamps are, and so on. In particular, the order in which timers fire is nondeterministic. This is a mocking solution to the problem, and it required the code to be structured around being easy to hook. In QuickCheck tests, you must know in advance what is going to happen to the system-under-test. Perhaps a way to ask a component for its current timers, a way to disable the firing of timers and a way to inject a given timer back would give a tester the tooling for doing dynamic interaction, like most unit tests are doing.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Also, I've been toying a bit with Janes St. Incremental implementation (In ocaml). They also have a stationary clock which can be advanced from the outside[0].</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">[0] Getting self-adjusting computations into Erlang is actually a hard problem. The implementation relies on being able to control the firing schedule of incremental nodes, something you cannot easily do in Erlang processes say.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><br></div></div></div>