Hi golang-nuts, I am excited to share Gosim: simulation testing for Go ( https://github.com/jellevandenhooff/gosim). Gosim is a project I have been working on for quite a while that aims to make testing distributed systems easier. It implements simulation testing as popularized by FoundationDB ( https://www.youtube.com/watch?v=4fFDFbi3toc).
Gosim runs mostly-standard Go code in its simulated environment. It supports standard packages like `os`, `net`, gRPC, protobuf, and more; the largest real-world program I have successfully run is etcd. Inside of the simulation, Gosim implements fake time, network, disks, and machines. Tests can manipulate the network to eg. partition a host, or restart a machine, and verify that code still behaves as it should -- and all that without needing to manage real VMs or containers. Gosim works by source-translating Go to replace all references to concurrency primitives, the operating system, and non-deterministic code to its own runtime. So `go foo()` becomes `gosimruntime.Go(foo)`, etc. Then, Gosim implements a (subset of) the Linux system call interface to simulate disk and network. More details on the design are in https://github.com/jellevandenhooff/gosim/blob/main/docs/design.md. Gosim's system call implementations are (currently) in https://github.com/jellevandenhooff/gosim/blob/main/internal/simulation/os_linux.go . To give you a taste of the kinds of tests Gosim can write, below is a snippet of a test running Etcd (taken from https://github.com/jellevandenhooff/gosim/blob/main/examples/etcd/etcd_test.go). The test creates several Gosim machines that have their own network stack, disk, global variables, and more, and lets them run and communicate. From the point of view of the code, each Etcd instance runs on its own machine and is its own independent process. The simulation however runs all machines in the same Go process so that you can easily debug what happens, the test is reproducible, and overhead is low. I have tried to make Gosim easy to use. To get started you can run a test by replacing `go test ...` with `gosim test`. If Gosim might be useful for you, I would be happy to chat and prioritize future features. Some things I would certainly like to add are support for running main() functions; simulating clock drift; support for running different versions of code; and built-in simulation of common cloud APIs like S3. Gosim is experimental, so it will change and break, and only runs Go code. So it can test systems that are written in Go, but it will not work with external dependencies. I have some ideas on using eg. Wazero to run Sqlite or Postgres inside of the Go process but those are, well, still ideas. Jelle // TestEtcd runs a 3 node etcd cluster, partitions the network between the > // nodes, and makes sure key-value puts and gets work. > func TestEtcd(t *testing.T) { > gosim.SetSimulationTimeout(2 * time.Minute) > > // run machines: > gosim.NewMachine(gosim.MachineConfig{ > Label: "etcd-1", > Addr: netip.MustParseAddr("10.0.0.1"), > MainFunc: func() { > runEtcdNode("etcd-1", "10.0.0.1") > }, > }) > gosim.NewMachine(gosim.MachineConfig{ > Label: "etcd-2", > Addr: netip.MustParseAddr("10.0.0.2"), > MainFunc: func() { > time.Sleep(100 * time.Millisecond) > runEtcdNode("etcd-2", "10.0.0.2") > }, > }) > gosim.NewMachine(gosim.MachineConfig{ > Label: "etcd-3", > Addr: netip.MustParseAddr("10.0.0.3"), > MainFunc: func() { > time.Sleep(200 * time.Millisecond) > runEtcdNode("etcd-3", "10.0.0.3") > }, > }) > > // mess with the network in the background > go nemesis.Sequence( > nemesis.Sleep{ > Duration: 10 * time.Second, > }, > nemesis.PartitionMachines{ > Addresses: []string{ > "10.0.0.1", > "10.0.0.2", > "10.0.0.3", > }, > Duration: 30 * time.Second, > }, > ).Run() > > -- 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 visit https://groups.google.com/d/msgid/golang-nuts/CAP%3DJquaBu1O5rN6aR6fMs03q4O92cPAc9DfGQZ9fck9zB2sEkw%40mail.gmail.com.