Skip to content

Commit

Permalink
More exhaustive tests
Browse files Browse the repository at this point in the history
  • Loading branch information
clipperhouse committed Jul 29, 2024
1 parent 38b72aa commit 7609127
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/gotest.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Test
name: Go Test

on:
push:
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ for split.Next() {
fmt.Println(split.Value())
}
```
### Performance

Some initial benchmarks:

Expand All @@ -35,6 +36,16 @@ Some initial benchmarks:
1267 ns/op 378.07 MB/s 1280 B/op 1 allocs/op
```

Overall, this package is a bit faster, but perhaps more importantly, notice the difference in allocations. `strings.Split` seems to have some sort of multiplying effect, as this benchmark uses a 400B string.

### Testing

We work to ensure that `split.Bytes` and `split.String` offer an identical API and results as their standard library counterparts, `bytes.Split` and `strings.Split`. Have a look at the tests to verify that this is true.

[![Test](https://github.com/clipperhouse/split/actions/workflows/gotest.yml/badge.svg)](https://github.com/clipperhouse/split/actions/workflows/gotest.yml)

### Status

Not ready for production yet! More testing and API consideration to come.

PR's are welcome, perhaps you'd like to [implement a range iterator](https://tip.golang.org/doc/go1.23).
44 changes: 11 additions & 33 deletions bytes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,43 +39,21 @@ func BenchmarkBytesSplit(b *testing.B) {
}
}

func TestBytesEmpty(t *testing.T) {
sep := []byte{}

input := []byte("Hello, how a,re, you 👍 ")
split := split.Bytes(input, sep)

var got [][]byte
for split.Next() {
got = append(got, split.Value())
}

expected := bytes.Split(input, sep)

if !reflect.DeepEqual(got, expected) {
t.Fatalf("\nexpected: %v,\ngot: %v", expected, got)
}
}

func TestBytes(t *testing.T) {
sep := []byte(", ")

input := []byte("Hello, how a,re, you ")
split := split.Bytes(input, sep)

var got [][]byte
for split.Next() {
got = append(got, split.Value())
}

expected := bytes.Split(input, sep)

if !reflect.DeepEqual(got, expected) {
t.Fatalf("\nexpected: %v,\ngot: %v", expected, got)
for _, sep := range testSeparators {
sepb := []byte(sep)
for _, s := range testStrings {
b := []byte(s)
got := split.Bytes(b, sepb).ToArray() // this package
expected := bytes.Split(b, sepb) // standard library
if !reflect.DeepEqual(got, expected) {
t.Fatalf("\nexpected: %v,\ngot: %v", expected, got)
}
}
}
}

func TestBytesOnAny(t *testing.T) {
func TestBytesAny(t *testing.T) {
seps := []byte(", ")

input := []byte("Hello, how a,re, you ")
Expand Down
10 changes: 3 additions & 7 deletions iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ type funcs[T ByteSeq] struct {

func split[T ByteSeq](s T, sep T, funcs funcs[T]) *iterator[T] {
var mode = sequence
if len(s) == 0 {
mode = done
} else if len(sep) == 0 {
if len(sep) == 0 {
mode = emptySequence
}

Expand All @@ -29,9 +27,7 @@ func split[T ByteSeq](s T, sep T, funcs funcs[T]) *iterator[T] {

func splitAny[T ByteSeq](s T, separators T, funcs funcs[T]) *iterator[T] {
var mode = any
if len(s) == 0 {
mode = done
} else if len(separators) == 0 {
if len(separators) == 0 {
mode = emptySequence
}

Expand Down Expand Up @@ -96,7 +92,7 @@ func (it *iterator[T]) Next() bool {
}

func (it *iterator[T]) ToArray() []T {
var result []T
var result []T = make([]T, 0)

for it.Next() {
result = append(result, it.Value())
Expand Down
89 changes: 9 additions & 80 deletions strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,90 +38,19 @@ func BenchmarkStringsSplit(b *testing.B) {
}
}

type SplitTest struct {
s string
sep string
n int
a []string
}

var abcd = "abcd"
var faces = "☺☻☹"
var commas = "1,2,3,4"
var dots = "1....2....3....4"

var splittests = []SplitTest{
{"", "a", -1, []string{}},
{"", "", -1, []string{}},
// {abcd, "", 2, []string{"a", "bcd"}},
// {abcd, "", 4, []string{"a", "b", "c", "d"}},
{abcd, "", -1, []string{"a", "b", "c", "d"}},
{faces, "", -1, []string{"☺", "☻", "☹"}},
// {faces, "", 3, []string{"☺", "☻", "☹"}},
// {faces, "", 17, []string{"☺", "☻", "☹"}},
{"☺�☹", "", -1, []string{"☺", "�", "☹"}},
// {abcd, "a", 0, nil},
{abcd, "a", -1, []string{"", "bcd"}},
{abcd, "z", -1, []string{"abcd"}},
{commas, ",", -1, []string{"1", "2", "3", "4"}},
{dots, "...", -1, []string{"1", ".2", ".3", ".4"}},
{faces, "☹", -1, []string{"☺☻", ""}},
{faces, "~", -1, []string{faces}},
// {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
// {"1 2", " ", 3, []string{"1", "2"}},
// {"", "T", math.MaxInt / 4, []string{""}},
{"\xff-\xff", "", -1, []string{"\xff", "-", "\xff"}},
{"\xff-\xff", "-", -1, []string{"\xff", "\xff"}},
}

func eq(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
func TestStrings(t *testing.T) {
for _, sep := range testSeparators {
for _, s := range testStrings {
got := split.String(s, sep).ToArray() // this package
expected := strings.Split(s, sep) // standard library
if !reflect.DeepEqual(got, expected) {
t.Fatalf("\nFor input %q, separator %q\nexpected: %q,\ngot: %q", s, sep, expected, got)
}
}
}
return true
}

func TestSplit(t *testing.T) {
for i, tt := range splittests {
a := split.String(tt.s, tt.sep).ToArray()
if !eq(a, tt.a) {
t.Errorf("%d: Split(%q, %q, %d) = %v; want %v", i, tt.s, tt.sep, tt.n, a, tt.a)
continue
}
if tt.n == 0 {
continue
}
s := strings.Join(a, tt.sep)
if s != tt.s {
t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s)
}
}
}

func TestString(t *testing.T) {
var sep = ", "

input := "Hello, how a,re, you "
split := split.String(input, sep)

var got []string
for split.Next() {
got = append(got, split.Value())
}

expected := strings.Split(input, sep)

if !reflect.DeepEqual(got, expected) {
t.Fatalf("\nexpected: %v,\ngot: %v", expected, got)
}
}

func TestStringOnAnyChar(t *testing.T) {
func TestStringAny(t *testing.T) {
var sep = ", "

input := "Hello, how a,re, you "
Expand Down
21 changes: 21 additions & 0 deletions tests_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package split_test

var abcd = "abc𝚫"
var emoji = "👍🐶"
var efghi = "éfghi"

var testSeparators = []string{" ", ",", ", ", "🐶", "𝚫", "🌏👍", ""}

var testStrings []string

func init() {
testStrings = append(testStrings, "") // empty

for _, sep := range testSeparators {
center := abcd + sep + emoji + sep + efghi
testStrings = append(testStrings, sep) // leading
testStrings = append(testStrings, sep+center) // leading
testStrings = append(testStrings, center+sep) // trailing
testStrings = append(testStrings, sep+center+sep) // both
}
}

0 comments on commit 7609127

Please sign in to comment.