package list import ( "regexp" "strings" "testing" "github.com/stretchr/testify/assert" "pgregory.net/rapid" ) // intListGen returns a generator for either empty list or random ints func intListGen() *rapid.Generator[IList] { return rapid.OneOf(rapid.Custom(func(t *rapid.T) IList { myList := Empty() t.Repeat(map[string]func(*rapid.T){ "conj": func(t *rapid.T) { myList = myList.Conj(rapid.Int().Draw(t, "el")) }, }) return myList }), rapid.Just(Empty())) } // descSortedIntListGen returns a generator for list of at least several descending ints func descSortedIntListGen() *rapid.Generator[IList] { return rapid.Custom(func(t *rapid.T) IList { myList := New(0) i := 1 t.Repeat(map[string]func(*rapid.T){ "conj": func(t *rapid.T) { myList = myList.Conj(i) i += 1 }, }) return myList }).Filter(func(l IList) bool { return l.Len() > 1 }) } func TestFirstIsNilOnlyWhenEmpty(t *testing.T) { assert.Equal(t, 1, New(3).Conj(2).Conj(1).First()) rapid.Check(t, func(t *rapid.T) { myList := intListGen().Draw(t, "myList") assert.Equal(t, myList.IsEmpty(), myList.First() == nil, "first is nil only when list is empty") }) } func TestConj(t *testing.T) { rapid.Check(t, func(t *rapid.T) { myList := intListGen().Draw(t, "myList") newElem := rapid.Int().Draw(t, "newElem") myList2 := myList.Conj(newElem) assert.Equal(t, myList.Len()+1, myList2.Len(), "conj increases length") assert.Equal(t, newElem, myList2.First(), "first after conj returns inserted number") }) } func TestRest(t *testing.T) { rapid.Check(t, func(t *rapid.T) { myList := intListGen().Draw(t, "myList") if myList.IsEmpty() { assert.Equal(t, myList.Len(), myList.Rest().Len(), "rest does not change length for empty list") } else { assert.Equal(t, myList.Len()-1, myList.Rest().Len(), "rest decreases length of non-empty list") } }) rapid.Check(t, func(t *rapid.T) { myList := descSortedIntListGen().Draw(t, "myList") assert.Greater(t, myList.First(), myList.Rest().First(), "rest decreases value in list head") }) } func TestStringifyIntList(t *testing.T) { assert.Equal(t, "(1 2 3)", New(3).Conj(2).Conj(1).String()) rapid.Check(t, func(t *rapid.T) { myList := intListGen().Draw(t, "myList") s := myList.String() r := regexp.MustCompile(`^\([\d\s-]*\)$`) assert.True(t, r.Match([]byte(s)), s+" looks like a stringified list") if !myList.IsEmpty() { assert.Equal(t, myList.Len(), strings.Count(s, " ")+1, "number of spaces in string should match count of elements") } else { assert.Equal(t, 0, strings.Count(s, " "), "no spaces in string for empty list") } }) }