simtest is heavily inspired by TigerBeetle's VOPR.
If you're new to the idea of deterministic simulation testing I recommend you watch this video of ThePrimeagen talking with Joran Greef.
In the context of software determinism simply means we can predict exactly what our software will do given its initial state.
It seems simple but is notoriously difficult to implement and achieve. To appreciate this difficulty we need to consider what causes software to be non-deterministic, what forces push our software towards the territory of the unknown.
Consider a simple function that adds two numbers.
func add(a, b int) int {
return a + b
}You can look at it and very confidently say it'll return the sum of any two numbers you give it. What if the function was changed slightly.
func add(a, b *int) int {
return *a + *b
}Can you now say with complete confidence what this function will return? No. The reason why we can't be sure is because we don't know, from the function's perspective, if the variables that the pointers are pointing to are modified while the function is being executed. This is an example of non-determinism.
Non-determinism has many sources. Here are some:
- OS thread scheduling
- Goroutine scheduling
- I/O
- Timers
- Random number generators
To build a simulator that is deterministic means to eliminate the sources of non-determinism.
If software is deterministic it means we can predict what it will do given some initial state. In theory there are only a finite number of states that your application can be in. This number is probably huge but it's finite. What is important and of interest to us is that some of these states lead to errors. If we can find all such states then we will know how our software can fail and handle them.