Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parallel command sequences #20

Open
oker1 opened this issue Jun 6, 2017 · 5 comments
Open

Parallel command sequences #20

oker1 opened this issue Jun 6, 2017 · 5 comments

Comments

@oker1
Copy link

oker1 commented Jun 6, 2017

I've been skimming through the docs, and coming from ScalaCheck i was looking for generating parallel command sequences. Is it supported?

@untoldwind
Copy link
Collaborator

No, that is still on the todo-list. Unluckily it's the most complicated part and since parallel processing in go is quite different to multi-threading in java/scala, I still have to find a suitable example (in go) where it would make sense to have this feature.

@oker1
Copy link
Author

oker1 commented Jun 8, 2017

Thanks for the clarification!

@prateek
Copy link
Contributor

prateek commented Jun 23, 2018

I have a use-case in mind for this - testing the different parts of a timeseries database with concurrent operations (user operations - reads/writes; housekeeping tasks - serialisation to disk/cleanup/etc). We've reproduced numerous bugs by running operations in parallel, some examples - m3db/m3#773, m3db/m3#502, m3db/m3#409, m3db/m3#372. We currently create such tests once we see issues in production but we'd obviously prefer to catch them earlier. To that effect, we're looking to add parallel stateful property tests.

Here's how I'm thinking the implementation in gopter might end up looking like (based on some ideas from Erlang): generate a linear sequence of operations A -> B -> C -> D -> E -> F -> G, and then transform that into two forks:

      ,-> C -> E -> G
A -> B
      '-> D -> F

And then simulate the operations using go-routines (with a gate to ensure all are up and runnable before execution starts).

Open questions:

  1. How many bugs this will catch in regular tests (i.e. will go test -race be enough).

Ideas to try if doesn't work very well:
i. Simulate all interleavings of the commands too - i.e. not just the forked tree, but also ensure that the execution switches after each command execution
ii. Compare state of the system after the operations run against state of the system after running each possible interleavings of the operation sequentially, at least one of them should match. This'd required State to implement Equal(other State) bool.
iii. Add support for yield points in end user code by adding a new subpackage gopter/commands/parallel, something like:

// +build parallel
// gopter/commands/parallel/yield_enabled.go
import "runtime"
func Yield() {
  runtime.Gosched() // or time.Sleep(0)
}

// +build !parallel
// gopter/commands/parallel/yield_enabled.go
import "runtime"
func Yield() {}

@prateek
Copy link
Contributor

prateek commented Jun 23, 2018

@untoldwind I'd love to get your feedback before I start implementing any of this.

@untoldwind
Copy link
Collaborator

ScalaCheck operates a bit more simple to my understanding. It "just" generates several sequences of commands/operations and applies them in parallel on the system under test checking the expected state within each thread.

The "problem" with this approach is that usually you just see that something goes haywire without a clear idea what exactly caused the problem. Even though in most cases it's already enough to know that there is a problem, the branching idea might generate some more helpful insights.

I'm not so sure about the Yield() though (maybe just because I'm not very keen on build switches in general). For starters it might be more helpful just to run the command-sequences with twice the number of GOMAXPROCS. Or maybe add a WaitGroup after each command (i.e. at all or some of the '->' in your diagram), though this might have a huge impact on the runtime of the tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants