Skip to content

Instantly share code, notes, and snippets.

@rciorba
Last active May 1, 2021 13:02
Show Gist options
  • Save rciorba/79e17881b1739afe2ff504b7edbcfc73 to your computer and use it in GitHub Desktop.
Save rciorba/79e17881b1739afe2ff504b7edbcfc73 to your computer and use it in GitHub Desktop.
foo
module github.com/rciorba/gopterbugreport
go 1.16
require github.com/leanovate/gopter v0.2.9 // indirect
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
package gopterbugreport
import (
"fmt"
"reflect"
"testing"
"github.com/leanovate/gopter"
"github.com/leanovate/gopter/commands"
"github.com/leanovate/gopter/gen"
)
// The Tests
// simplified SUT, if true we should fail the next PostCondition
type SUT = bool
// simplified state is gonna be just the length of the original state
type baState = int
// the setCommand type.
type setCommand struct {
Index int
Value bool
}
func (cmd setCommand) Run(sut commands.SystemUnderTest) commands.Result {
// fmt.Printf("Run got CMD: %v \n", cmd)
if cmd.Index == 12 {
// Intentional "bug" in our SUT, from now on fail the postcondition
return true
}
return sut
}
func (cmd setCommand) NextState(state commands.State) commands.State {
fmt.Printf("NextState got CMD: %v \n", cmd)
st := state.(baState)
if cmd.Index < 0 || cmd.Index >= st {
panic(fmt.Sprintf("Index out of range [0, %v]: %v", st-1, cmd.Index))
}
return st
}
func (setCommand) PreCondition(state commands.State) bool {
return true
}
func (setCommand) PostCondition(state commands.State, result commands.Result) *gopter.PropResult {
sut := result.(SUT)
if sut {
fmt.Printf("We've encountered the fake bug, so we'll fail the PostCondition\n")
return &gopter.PropResult{Status: gopter.PropFalse}
}
return &gopter.PropResult{Status: gopter.PropTrue}
}
func (cmd setCommand) String() string {
return fmt.Sprintf("Set(%v, %v)", cmd.Index, cmd.Value)
}
// We will use this in combination with gen.OneConstOf, to work arround the issue with IntRange
// generating values outside the declared range.
func makeIntSequence(start, end int) []interface{} {
seq := make([]interface{}, end+1-start)
for i := start; i <= end; i++ {
seq[i-start] = i
}
return seq
}
func makeGenSetCommand(state baState) gopter.Gen {
genCommand := gen.Struct(
reflect.TypeOf(setCommand{}),
map[string]gopter.Gen{
// Despite the declared range we will see out of bounds indexes.
"Index": gen.IntRange(6, state-1),
// Using OneConstOf avoids the index-out-of-range issue.
// "Index": gen.OneConstOf(makeIntSequence(0, state-1)...),
"Value": gen.Bool(),
},
)
return genCommand
}
var bitarrayCommands = &commands.ProtoCommands{
NewSystemUnderTestFunc: func(initialState commands.State) commands.SystemUnderTest {
return false
},
InitialStateGen: gen.Const(16),
GenCommandFunc: func(state commands.State) gopter.Gen {
st := state.(baState)
return makeGenSetCommand(st)
},
}
func TestIntRangeShrinking(t *testing.T) {
var params *gopter.TestParameters
params = gopter.DefaultTestParameters()
params.Rng.Seed(1) // Just for this example to generate reproducible results
params.Workers = 1
properties := gopter.NewProperties(params)
properties.Property("always equivalent", commands.Prop(bitarrayCommands))
properties.TestingRun(t)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment