diff --git a/.gitignore b/.gitignore index fa3d5f1..ef61743 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ tmp .air.toml +*/testdata/* diff --git a/go.mod b/go.mod index 7b7fcac..399a76e 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,5 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.11.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + pgregory.net/rapid v1.2.0 // indirect ) diff --git a/go.sum b/go.sum index cc8b3f4..50277fe 100644 --- a/go.sum +++ b/go.sum @@ -7,3 +7,5 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= diff --git a/list/list.go b/list/list.go index a404392..2a62437 100644 --- a/list/list.go +++ b/list/list.go @@ -5,13 +5,13 @@ import ( "strings" ) - type IList interface { Conj(data any) IList First() any Rest() IList String() string IsEmpty() bool + Len() int } type EmptyList struct{} @@ -121,3 +121,11 @@ func (this *List) String() string { func (this *EmptyList) String() string { return "()" } + +func (this *EmptyList) Len() int { + return 0 +} + +func (this *List) Len() int { + return 1 + this.Rest().Len() +} diff --git a/list/list_test.go b/list/list_test.go index 93d9d06..55e3cfd 100644 --- a/list/list_test.go +++ b/list/list_test.go @@ -2,14 +2,21 @@ package list import ( "github.com/stretchr/testify/assert" + "pgregory.net/rapid" "testing" ) -func TestReadString(t *testing.T) { +func TestListLen(t *testing.T) { + assert.Equal(t, 0, Empty().Len(), "should insert at head") + assert.Equal(t, 1, Empty().Conj(1).Len(), "should insert at head") + assert.Equal(t, 2, Empty().Conj(1).Conj(2).Len(), "should insert at head") +} + +func TestListString(t *testing.T) { assert.Equal(t, "()", Empty().String(), "should insert at head") } -func TestReadConj(t *testing.T) { +func TestListConj(t *testing.T) { var l IList assert.Equal(t, "()", Empty().String(), "should insert at head") l = New(5) @@ -18,13 +25,13 @@ func TestReadConj(t *testing.T) { assert.Equal(t, "(4)", l.String(), "should insert at head") } -func TestReadFirst(t *testing.T) { +func TestListFirst(t *testing.T) { l := Empty().Conj(5).Conj(6).Conj(7) assert.Equal(t, 7, l.First(), "should return first element") assert.Equal(t, nil, Empty().First(), "should return nil") } -func TestReadRest(t *testing.T) { +func TestListRest(t *testing.T) { l := Empty().Conj(5).Conj(6).Conj(7) assert.Equal(t, "(6 5)", l.Rest().String(), "should return rest sublist") assert.Equal(t, "(5)", l.Rest().Rest().String(), "should return rest sublist") @@ -32,3 +39,21 @@ func TestReadRest(t *testing.T) { assert.Equal(t, Empty(), Empty().Rest(), "should return rest sublist") assert.Equal(t, Empty(), Rest(Empty().Rest()), "should return rest sublist") } + +type listGen struct{} + +// generative tests +func TestConjIncreasesLen(t *testing.T) { + l := Empty() + expectedSized := 0 + rapid.Check(t, func(t *rapid.T) { + t.Repeat(map[string]func(*rapid.T){ + "conj": func(t *rapid.T) { + expectedSized += 0 + }, + "": func(t *rapid.T) { + assert.Equal(t, l.Len(), expectedSized, "must be equal") + }, + }) + }) +}