diff --git a/go.mod b/go.mod index b6e0fea38..d13c9ea4b 100644 --- a/go.mod +++ b/go.mod @@ -39,4 +39,5 @@ require ( golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 google.golang.org/grpc v1.39.0 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect + pgregory.net/rapid v0.4.7 // indirect ) diff --git a/go.sum b/go.sum index 55e08e088..ed2f127b2 100644 --- a/go.sum +++ b/go.sum @@ -1437,6 +1437,8 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7 h1:HT3e4Krq+IE44tiN36RvVEb6tvqeIdtsVSsxmNPqlFU= mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7/go.mod h1:hBpJkZE8H/sb+VRFvw2+rBpHNsTBcvSpk61hr8mzXZE= +pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= +pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/libs/clist/clist_property_test.go b/internal/libs/clist/clist_property_test.go new file mode 100644 index 000000000..422899aa5 --- /dev/null +++ b/internal/libs/clist/clist_property_test.go @@ -0,0 +1,55 @@ +package clist_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/internal/libs/clist" + "pgregory.net/rapid" +) + +func TestCListProperties(t *testing.T) { + rapid.Check(t, rapid.Run(&clistModel{})) +} + +type clistModel struct { + clist *clist.CList + + state []*clist.CElement +} + +func (m *clistModel) Init(t *rapid.T) { + m.clist = clist.New() + m.state = []*clist.CElement{} +} + +func (m *clistModel) PushBack(t *rapid.T) { + value := rapid.String().Draw(t, "value").(string) + el := m.clist.PushBack(value) + m.state = append(m.state, el) +} + +func (m *clistModel) Remove(t *rapid.T) { + if len(m.state) == 0 { + return + } + ix := rapid.IntRange(0, len(m.state)-1).Draw(t, "index").(int) + value := m.state[ix] + m.state = append(m.state[:ix], m.state[ix+1:]...) + m.clist.Remove(value) +} + +func (m *clistModel) Check(t *rapid.T) { + require.Equal(t, len(m.state), m.clist.Len()) + if len(m.state) == 0 { + return + } + require.Equal(t, m.state[0], m.clist.Front()) + require.Equal(t, m.state[len(m.state)-1], m.clist.Back()) + + iter := m.clist.Front() + for _, val := range m.state { + require.Equal(t, val, iter) + iter = iter.Next() + } +}