aboutsummaryrefslogtreecommitdiffstats
path: root/prog/collide.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2021-12-01 17:53:13 +0000
committerAleksandr Nogikh <wp32pw@gmail.com>2021-12-10 12:30:07 +0100
commit15439f1624735bde5ae3f3b66c1b964a980415b3 (patch)
tree4e9aacba8e41b511f8fb8c60d09d5c4b1c98287d /prog/collide.go
parent18f846ca807cfc6df9c3da3c0ab08251277dfefb (diff)
all: add the `DoubleExecCollide` strategy
Add a strategy that resembles the previous collide mode, but detaches not every other call, rather all calls during the second execution (or at least as much as possible). Follow the strategy for 33% of all collide executions. It was shown during the experiments that this strategy has a positive effect on the number of discovered crashes and bugs.
Diffstat (limited to 'prog/collide.go')
-rw-r--r--prog/collide.go28
1 files changed, 27 insertions, 1 deletions
diff --git a/prog/collide.go b/prog/collide.go
index 77065147f..fea8cc146 100644
--- a/prog/collide.go
+++ b/prog/collide.go
@@ -5,7 +5,10 @@
package prog
-import "math/rand"
+import (
+ "fmt"
+ "math/rand"
+)
// The executor has no more than 32 threads that are used both for async calls and for calls
// that timed out. If we just ignore that limit, we could end up generating programs that
@@ -71,3 +74,26 @@ func AssignRandomRerun(prog *Prog, rand *rand.Rand) {
i++
}
}
+
+// We append prog to itself, but let the second part only reference resource from the first one.
+// Then we execute all the duplicated calls simultaneously.
+// This somehow resembles the way the previous collide mode was implemented - a program was executed
+// normally and then one more time again, while keeping resource values from the first execution and
+// not waiting until every other call finishes.
+func DoubleExecCollide(origProg *Prog, rand *rand.Rand) (*Prog, error) {
+ if len(origProg.Calls)*2 > MaxCalls {
+ return nil, fmt.Errorf("the prog is too big for the DoubleExecCollide transformation")
+ }
+ prog := origProg.Clone()
+ dupCalls := cloneCalls(prog.Calls, nil)
+ leftAsync := maxAsyncPerProg
+ for _, c := range dupCalls {
+ if leftAsync == 0 {
+ break
+ }
+ c.Props.Async = true
+ leftAsync--
+ }
+ prog.Calls = append(prog.Calls, dupCalls...)
+ return prog, nil
+}