Impressive stuff! Some potentially interesting overlap with the new
"synctest" package. Do you have any thoughts on that?


On Tue, 10 Dec 2024 at 17:41, Jelle van den Hooff <je...@vandenhooff.name>
wrote:

> 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
> <https://groups.google.com/d/msgid/golang-nuts/CAP%3DJquaBu1O5rN6aR6fMs03q4O92cPAc9DfGQZ9fck9zB2sEkw%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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/CAJhgacjRqnaJhagjGnq%3DpMvfy8LLa40nDGYBiiA%3DcPnEkyVD-A%40mail.gmail.com.

Reply via email to