diff --git a/Contains.go b/Contains.go new file mode 100644 index 0000000..cc66a96 --- /dev/null +++ b/Contains.go @@ -0,0 +1,95 @@ +package assert + +import ( + "reflect" + "strings" + "testing" +) + +// Contains asserts that a contains b. +func Contains(t testing.TB, a any, b any) { + if contains(a, b) { + return + } + + t.Errorf(` +file: %s +assert: Contains +container:%v +element: %v`, file(t), a, b) + t.FailNow() +} + +// NotContains asserts that a doesn't contain b. +func NotContains(t testing.TB, a any, b any) { + if !contains(a, b) { + return + } + + t.Errorf(` +file: %s +assert: NotContains +container:%v +element: %v`, file(t), a, b) + t.FailNow() +} + +// contains returns whether container contains the given the element. +// It works with strings, maps and slices. +func contains(container any, element any) bool { + containerValue := reflect.ValueOf(container) + + switch containerValue.Kind() { + case reflect.String: + elementValue := reflect.ValueOf(element) + return strings.Contains(containerValue.String(), elementValue.String()) + + case reflect.Map: + keys := containerValue.MapKeys() + + for _, key := range keys { + if key.Interface() == element { + return true + } + } + + case reflect.Slice: + elementValue := reflect.ValueOf(element) + + if elementValue.Kind() == reflect.Slice { + elementLength := elementValue.Len() + + if elementLength == 0 { + return true + } + + if elementLength > containerValue.Len() { + return false + } + + matchingElements := 0 + + for i := 0; i < containerValue.Len(); i++ { + if containerValue.Index(i).Interface() == elementValue.Index(matchingElements).Interface() { + matchingElements++ + } else { + matchingElements = 0 + } + + if matchingElements == elementLength { + return true + } + } + + return false + } + + for i := 0; i < containerValue.Len(); i++ { + if containerValue.Index(i).Interface() == element { + return true + } + } + } + + return false +} diff --git a/Contains_test.go b/Contains_test.go new file mode 100644 index 0000000..c801692 --- /dev/null +++ b/Contains_test.go @@ -0,0 +1,29 @@ +package assert_test + +import ( + "testing" + + "git.akyoto.dev/go/assert" +) + +func TestContains(t *testing.T) { + assert.Contains(t, "Hello", "H") + assert.Contains(t, "Hello", "Hello") + assert.Contains(t, []string{"Hello", "World"}, "Hello") + assert.Contains(t, []int{1, 2, 3}, 2) + assert.Contains(t, []int{1, 2, 3}, []int{}) + assert.Contains(t, []int{1, 2, 3}, []int{1, 2}) + assert.Contains(t, []byte{'H', 'e', 'l', 'l', 'o'}, byte('e')) + assert.Contains(t, []byte{'H', 'e', 'l', 'l', 'o'}, []byte{'e', 'l'}) + assert.Contains(t, map[string]int{"Hello": 1, "World": 2}, "Hello") +} + +func TestNotContains(t *testing.T) { + assert.NotContains(t, "Hello", "404") + assert.NotContains(t, []string{"Hello", "World"}, "404") + assert.NotContains(t, []int{1, 2, 3}, 4) + assert.NotContains(t, []int{1, 2, 3}, []int{2, 1}) + assert.NotContains(t, []byte{'H', 'e', 'l', 'l', 'o'}, byte('a')) + assert.NotContains(t, []byte{'H', 'e', 'l', 'l', 'o'}, []byte{'l', 'e'}) + assert.NotContains(t, map[string]int{"Hello": 1, "World": 2}, "404") +} diff --git a/Nil.go b/Nil.go new file mode 100644 index 0000000..cc2aa9f --- /dev/null +++ b/Nil.go @@ -0,0 +1,50 @@ +package assert + +import ( + "reflect" + "testing" +) + +// Nil asserts that the given parameter equals nil. +func Nil(t testing.TB, a any) { + if isNil(a) { + return + } + + t.Errorf(` +file: %s +assert: Nil +value: %v +expected: nil`, file(t), a) + t.FailNow() +} + +// NotNil asserts that the given parameter does not equal nil. +func NotNil(t testing.TB, a any) { + if !isNil(a) { + return + } + + t.Errorf(` +file: %s +assert: NotNil +value: %v +expected: not nil`, file(t), a) + t.FailNow() +} + +// isNil returns true if the object is nil. +func isNil(object any) bool { + if object == nil { + return true + } + + value := reflect.ValueOf(object) + + switch value.Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: + return value.IsNil() + } + + return false +} diff --git a/Nil_test.go b/Nil_test.go new file mode 100644 index 0000000..83ee265 --- /dev/null +++ b/Nil_test.go @@ -0,0 +1,25 @@ + +package assert_test + +import ( + "testing" + + "git.akyoto.dev/go/assert" +) + +func TestNil(t *testing.T) { + var nilPointer *T + var nilSlice []byte + + assert.Nil(t, nil) + assert.Nil(t, nilPointer) + assert.Nil(t, nilSlice) +} + +func TestNotNil(t *testing.T) { + assert.NotNil(t, 0) + assert.NotNil(t, "Hello") + assert.NotNil(t, []byte{}) + assert.NotNil(t, T{}) + assert.NotNil(t, &T{}) +} diff --git a/True.go b/True.go new file mode 100644 index 0000000..2e4b00b --- /dev/null +++ b/True.go @@ -0,0 +1,13 @@ +package assert + +import "testing" + +// True asserts that the given parameter is true. +func True(t testing.TB, a bool) { + Equal(t, a, true) +} + +// False asserts that the given parameter is false. +func False(t testing.TB, a bool) { + Equal(t, a, false) +} diff --git a/True_test.go b/True_test.go new file mode 100644 index 0000000..2862862 --- /dev/null +++ b/True_test.go @@ -0,0 +1,12 @@ +package assert_test + +import ( + "testing" + + "git.akyoto.dev/go/assert" +) + +func TestTrue(t *testing.T) { + assert.True(t, true) + assert.False(t, false) +}