Shit ton of tests

This commit is contained in:
Melody Becker 2025-04-24 15:59:15 +02:00
parent 99b00887a8
commit ccf98c2f6e
Signed by: mstar
SSH key fingerprint: SHA256:9VAo09aaVNTWKzPW7Hq2LW+ox9OdwmTSHRoD4mlz1yI
13 changed files with 1157 additions and 1 deletions

95
containers/queues_test.go Normal file
View file

@ -0,0 +1,95 @@
package containers_test
import (
"testing"
"git.mstar.dev/mstar/goutils/containers"
"git.mstar.dev/mstar/goutils/other"
)
func TestQueue(t *testing.T) {
queue := containers.BuildQueue[int]()
elem, err := queue.Top()
switch err {
case containers.ErrEmptyQueue:
// Expected, continue
case containers.ErrInvalidQueue:
t.Fatal("New queue is invalid")
case nil:
t.Fatalf("New queue shouldn't have any elements yet: %v", elem)
}
elem, err = queue.Pop()
switch err {
case containers.ErrEmptyQueue:
// Expected, continue
case containers.ErrInvalidQueue:
t.Fatal("New queue is invalid")
case nil:
t.Fatalf("New queue shouldn't have any elements yet: %v", elem)
}
if !queue.IsEmpty() {
t.Fatal("New queue isn't empty")
}
if err = queue.Push(other.IntoPointer(10)); err != nil {
t.Fatal("Failed to push value onto new queue")
}
if queue.IsEmpty() {
t.Fatal("Queue is empty after pushing a value")
}
if err = queue.Push(other.IntoPointer(20)); err != nil {
t.Fatal("Failed to push value onto queue")
}
elem, err = queue.Top()
if err != nil {
t.Fatalf("Failed to get top element from queue after inserting one: %v", err)
}
switch {
case elem == nil:
t.Fatal("Got nil elem; want &10")
case *elem == 10:
// Expected, continue
default:
t.Fatalf("Got %v; want &10", *elem)
}
if queue.IsEmpty() {
t.Fatal("Top shouldn't pop an element from the queue")
}
elem, err = queue.Pop()
if err != nil {
t.Fatalf("Expected no error while popping a value: %v", err)
}
switch {
case elem == nil:
t.Fatal("Got nil elem; want &10")
case *elem == 10:
// Expected, continue
default:
t.Fatalf("Got %v; want &10", *elem)
}
if queue.IsEmpty() {
t.Fatal("Queue should still have one element left")
}
elem, err = queue.Pop()
if err != nil {
t.Fatalf("Expected no error while popping a value: %v", err)
}
switch {
case elem == nil:
t.Fatal("Got nil elem; want &20")
case *elem == 20:
// Expected, continue
default:
t.Fatalf("Got %v; want &20", *elem)
}
if !queue.IsEmpty() {
t.Fatal("Queue should be empty now")
}
}

108
containers/stacks_test.go Normal file
View file

@ -0,0 +1,108 @@
package containers_test
import (
"testing"
"git.mstar.dev/mstar/goutils/containers"
"git.mstar.dev/mstar/goutils/other"
)
func TestStack(t *testing.T) {
stack := containers.BuildStack[int]()
elem, err := stack.Top()
switch err {
case containers.ErrEmptyQueue:
// Expected, continue
case containers.ErrInvalidQueue:
t.Fatal("New queue is invalid")
case nil:
t.Fatalf("New queue shouldn't have any elements yet: %v", elem)
}
elem, err = stack.Pop()
switch err {
case containers.ErrEmptyQueue:
// Expected, continue
case containers.ErrInvalidQueue:
t.Fatal("New queue is invalid")
case nil:
t.Fatalf("New queue shouldn't have any elements yet: %v", elem)
}
if !stack.IsEmpty() {
t.Fatal("New queue isn't empty")
}
if err = stack.Push(other.IntoPointer(10)); err != nil {
t.Fatal("Failed to push value onto new queue")
}
if stack.IsEmpty() {
t.Fatal("Queue is empty after pushing a value")
}
elem, err = stack.Top()
if err != nil {
t.Fatalf("Failed to get top element from queue after inserting one: %v", err)
}
switch {
case elem == nil:
t.Fatal("Got nil elem; want &10")
case *elem == 10:
// Expected, continue
default:
t.Fatalf("Got %v; want &10", *elem)
}
if err = stack.Push(other.IntoPointer(20)); err != nil {
t.Fatal("Failed to push value onto queue")
}
elem, err = stack.Top()
if err != nil {
t.Fatalf("Failed to get top element from queue after inserting one: %v", err)
}
switch {
case elem == nil:
t.Fatal("Got nil elem; want &20")
case *elem == 20:
// Expected, continue
default:
t.Fatalf("Got %v; want &20", *elem)
}
if stack.IsEmpty() {
t.Fatal("Top shouldn't pop an element from the queue")
}
elem, err = stack.Pop()
if err != nil {
t.Fatalf("Expected no error while popping a value: %v", err)
}
switch {
case elem == nil:
t.Fatal("Got nil elem; want &20")
case *elem == 20:
// Expected, continue
default:
t.Fatalf("Got %v; want &20", *elem)
}
if stack.IsEmpty() {
t.Fatal("Queue should still have one element left")
}
elem, err = stack.Pop()
if err != nil {
t.Fatalf("Expected no error while popping a value: %v", err)
}
switch {
case elem == nil:
t.Fatal("Got nil elem; want &10")
case *elem == 10:
// Expected, continue
default:
t.Fatalf("Got %v; want &10", *elem)
}
if !stack.IsEmpty() {
t.Fatal("Queue should be empty now")
}
}

BIN
coverage_badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,27 @@
package embedFsWrapper_test
import (
"io"
"testing"
"testing/fstest"
"git.mstar.dev/mstar/goutils/embedFsWrapper"
)
func TestFSWrapper(t *testing.T) {
mfs := fstest.MapFS{
"baz/foo": &fstest.MapFile{Data: []byte("bar")},
}
wrapped := embedFsWrapper.NewFSWrapper(mfs, "baz/")
f, err := wrapped.Open("foo")
if err != nil {
t.Fatalf("Expected to open file foo (baz/foo), got %v", err)
}
data, err := io.ReadAll(f)
if err != nil {
t.Fatal(err)
}
if string(data) != "bar" {
t.Fatalf("Expected file to have \"bar\" as content, found %v", string(data))
}
}

33
http/chain_test.go Normal file
View file

@ -0,0 +1,33 @@
package webutils_test
import (
"net/http"
"net/http/httptest"
"testing"
webutils "git.mstar.dev/mstar/goutils/http"
)
func TestChainMiddlewares(t *testing.T) {
wrapper1 := webutils.HandlerBuilder(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.Header.Add("X-Foo", "bar")
h.ServeHTTP(w, r)
})
})
wrapper2 := webutils.HandlerBuilder(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.Header.Add("X-Foos", r.Header.Get("X-Foo")+"baz")
h.ServeHTTP(w, r)
})
})
baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if x := r.Header.Get("X-Foos"); x != "barbaz" {
t.Fatalf(`Expected header "X-Foos" to be "barbaz", got %v`, x)
}
})
handler := webutils.ChainMiddlewares(baseHandler, wrapper1, wrapper2)
recorder := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/", nil)
handler.ServeHTTP(recorder, req)
}

23
http/context_test.go Normal file
View file

@ -0,0 +1,23 @@
package webutils_test
import (
"net/http"
"net/http/httptest"
"testing"
webutils "git.mstar.dev/mstar/goutils/http"
)
func TestContextValsMiddleware(t *testing.T) {
builder := webutils.ContextValsMiddleware(map[any]any{"foo": "bar"})
baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if val, _ := r.Context().Value("foo").(string); val != "bar" {
t.Fatalf(`Expected context value "foo" to be "bar", got %v`, val)
}
})
wrapped := builder(baseHandler)
recorder := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/", nil)
wrapped.ServeHTTP(recorder, req)
// At this point baseHandler should have been called and checked for the context value
}

235
http/httpErr_test.go Normal file
View file

@ -0,0 +1,235 @@
package webutils_test
import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"testing"
webutils "git.mstar.dev/mstar/goutils/http"
"git.mstar.dev/mstar/goutils/maputils"
"git.mstar.dev/mstar/goutils/other"
"git.mstar.dev/mstar/goutils/sliceutils"
)
func TestHttpErr(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.HttpErr(recorder, 1, "some error", 500)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
res := recorder.Result()
if res.StatusCode != 500 {
t.Fatalf("Expected status code 500, got %v", res.StatusCode)
}
body := string(other.Must(io.ReadAll(res.Body)))
expected := `{"id": 1, "message": "some error"}`
if body != expected {
t.Fatalf("Expected body %q, got %q", expected, body)
}
}
func TestProblemDetailsStatusOnly(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.ProblemDetailsStatusOnly(recorder, 500)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
res := recorder.Result()
if ct := res.Header.Get("Content-Type"); ct != "application/problem+json" {
t.Fatalf("Expected content type to be \"application/problem+json\" got %v", ct)
}
body := string(other.Must(io.ReadAll(res.Body)))
data := map[string]any{}
err = json.Unmarshal([]byte(body), &data)
if err != nil {
t.Fatalf("response body is not json: %v", err)
}
if dt, ok := data["type"].(string); !ok || dt != "about:blank" {
t.Fatalf(`Expected key "type" as "about:blank", got %v`, dt)
}
if dt, ok := data["title"].(string); !ok || dt != http.StatusText(500) {
t.Fatalf(`Expected key "title" as "%v", got %v`, http.StatusText(500), dt)
}
if dt, ok := data["status"].(float64); !ok || dt != 500 {
t.Fatalf(`Expected key "status" as 500, got %v`, dt)
}
if dt, ok := data["reference"].(string); !ok || dt != "RFC 9457" {
t.Fatalf(`Expected key "reference" as "RFC 9457", got %v`, dt)
}
}
func TestProblemDetailsNoDetailsOrExtras(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.ProblemDetails(
recorder,
500,
"error-type",
"error-title",
nil,
nil,
)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
res := recorder.Result()
if ct := res.Header.Get("Content-Type"); ct != "application/problem+json" {
t.Fatalf("Expected content type to be \"application/problem+json\" got %v", ct)
}
body := string(other.Must(io.ReadAll(res.Body)))
data := map[string]any{}
err = json.Unmarshal([]byte(body), &data)
if err != nil {
t.Fatalf("response body is not json: %v", err)
}
expectedFields := []string{"type", "title", "status"}
gotFields := maputils.KeysFromMap(data)
if !sliceutils.CompareUnordered(gotFields, expectedFields) {
t.Fatalf("Expected fields %v, got %v", expectedFields, gotFields)
}
if dt, ok := data["type"].(string); !ok || dt != "error-type" {
t.Fatalf(`Expected key "type" as "error-type", got %v`, dt)
}
if dt, ok := data["title"].(string); !ok || dt != "error-title" {
t.Fatalf(`Expected key "title" as "error-title", got %v`, dt)
}
if dt, ok := data["status"].(float64); !ok || dt != 500 {
t.Fatalf(`Expected key "status" as 500, got %v`, dt)
}
}
func TestProblemDetailsNoDetailsWithExtras(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.ProblemDetails(
recorder,
500,
"error-type",
"error-title",
nil,
map[string]any{"foo": "bar"},
)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
res := recorder.Result()
if ct := res.Header.Get("Content-Type"); ct != "application/problem+json" {
t.Fatalf("Expected content type to be \"application/problem+json\" got %v", ct)
}
body := string(other.Must(io.ReadAll(res.Body)))
data := map[string]any{}
err = json.Unmarshal([]byte(body), &data)
if err != nil {
t.Fatalf("response body is not json: %v", err)
}
expectedFields := []string{"type", "title", "status", "foo"}
gotFields := maputils.KeysFromMap(data)
if !sliceutils.CompareUnordered(gotFields, expectedFields) {
t.Fatalf("Expected fields %v, got %v", expectedFields, gotFields)
}
if dt, ok := data["type"].(string); !ok || dt != "error-type" {
t.Fatalf(`Expected key "type" as "error-type", got %v`, dt)
}
if dt, ok := data["title"].(string); !ok || dt != "error-title" {
t.Fatalf(`Expected key "title" as "error-title", got %v`, dt)
}
if dt, ok := data["status"].(float64); !ok || dt != 500 {
t.Fatalf(`Expected key "status" as 500, got %v`, dt)
}
if dt, ok := data["foo"].(string); !ok || dt != "bar" {
t.Fatalf(`Expected key "foo" as "bar", got %v`, dt)
}
}
func TestProblemDetailsWithDetailsNoExtras(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.ProblemDetails(
recorder,
500,
"error-type",
"error-title",
other.IntoPointer("error-details"),
nil,
)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
res := recorder.Result()
if ct := res.Header.Get("Content-Type"); ct != "application/problem+json" {
t.Fatalf("Expected content type to be \"application/problem+json\" got %v", ct)
}
body := string(other.Must(io.ReadAll(res.Body)))
data := map[string]any{}
err = json.Unmarshal([]byte(body), &data)
if err != nil {
t.Fatalf("response body is not json: %v", err)
}
expectedFields := []string{"type", "title", "status", "detail"}
gotFields := maputils.KeysFromMap(data)
if !sliceutils.CompareUnordered(gotFields, expectedFields) {
t.Fatalf("Expected fields %v, got %v", expectedFields, gotFields)
}
if dt, ok := data["type"].(string); !ok || dt != "error-type" {
t.Fatalf(`Expected key "type" as "error-type", got %v`, dt)
}
if dt, ok := data["title"].(string); !ok || dt != "error-title" {
t.Fatalf(`Expected key "title" as "error-title", got %v`, dt)
}
if dt, ok := data["status"].(float64); !ok || dt != 500 {
t.Fatalf(`Expected key "status" as 500, got %v`, dt)
}
if dt, ok := data["detail"].(string); !ok || dt != "error-details" {
t.Fatalf(`Expected key "detail" as "error-details", got %v`, dt)
}
}
func TestProblemDetailsWithDetailsWithExtras(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.ProblemDetails(
recorder,
500,
"error-type",
"error-title",
other.IntoPointer("error-details"),
map[string]any{"foo": "bar", "type": "should not be set in the end"},
)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
res := recorder.Result()
if ct := res.Header.Get("Content-Type"); ct != "application/problem+json" {
t.Fatalf("Expected content type to be \"application/problem+json\" got %v", ct)
}
body := string(other.Must(io.ReadAll(res.Body)))
data := map[string]any{}
err = json.Unmarshal([]byte(body), &data)
if err != nil {
t.Fatalf("response body is not json: %v", err)
}
expectedFields := []string{"type", "title", "status", "detail", "foo"}
gotFields := maputils.KeysFromMap(data)
if !sliceutils.CompareUnordered(gotFields, expectedFields) {
t.Fatalf("Expected fields %v, got %v", expectedFields, gotFields)
}
if dt, ok := data["type"].(string); !ok || dt != "error-type" {
t.Fatalf(`Expected key "type" as "error-type", got %v`, dt)
}
if dt, ok := data["title"].(string); !ok || dt != "error-title" {
t.Fatalf(`Expected key "title" as "error-title", got %v`, dt)
}
if dt, ok := data["status"].(float64); !ok || dt != 500 {
t.Fatalf(`Expected key "status" as 500, got %v`, dt)
}
if dt, ok := data["detail"].(string); !ok || dt != "error-details" {
t.Fatalf(`Expected key "detail" as "error-details", got %v`, dt)
}
if dt, ok := data["foo"].(string); !ok || dt != "bar" {
t.Fatalf(`Expected key "foo" as "bar", got %v`, dt)
}
}

45
http/json_test.go Normal file
View file

@ -0,0 +1,45 @@
package webutils_test
import (
"io"
"net/http/httptest"
"testing"
webutils "git.mstar.dev/mstar/goutils/http"
)
func TestSendJsonOk(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.SendJson(recorder, map[string]any{
"a": 1,
"b": "b",
"c": nil,
})
if err != nil {
t.Fatalf("error while sending json: %v", err)
}
res := recorder.Result()
if ctype := res.Header.Get("Content-Type"); ctype != "application/json" {
t.Fatalf("expected content type \"application/json\", got %v", ctype)
}
// httptest guarantees body to be functional and only returned error will be EOL
// so no need to watch for error
bodyBytes, _ := io.ReadAll(res.Body)
body := string(bodyBytes)
expected := `{"a":1,"b":"b","c":null}`
if body != expected {
t.Fatalf("Expected %v as body, got %v", expected, body)
}
}
func TestSendJsonNotMarshallable(t *testing.T) {
recorder := httptest.NewRecorder()
err := webutils.SendJson(recorder, map[string]any{
"a": 1,
"b": "b",
"c": make(chan any),
})
if err == nil {
t.Fatal("expected json marshalling error")
}
}

274
maputils/mapUtils_test.go Normal file
View file

@ -0,0 +1,274 @@
package maputils_test
import (
"reflect"
"testing"
"git.mstar.dev/mstar/goutils/maputils"
"git.mstar.dev/mstar/goutils/sliceutils"
)
func TestMapSameKeys(t *testing.T) {
type args struct {
dic map[string]int
apply func(string, int) int
}
tests := []struct {
name string
args args
want map[string]int
}{
{
name: "map",
args: args{
dic: map[string]int{
"a": 1,
"b": 2,
"c": 3,
},
apply: func(s string, i int) int { return i + 1 },
},
want: map[string]int{
"a": 2,
"b": 3,
"c": 4,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := maputils.MapSameKeys(tt.args.dic, tt.args.apply); !reflect.DeepEqual(
got,
tt.want,
) {
t.Errorf("MapSameKeys() = %v, want %v", got, tt.want)
}
})
}
}
func TestMapNewKeys(t *testing.T) {
type args struct {
in map[string]int
apply func(string, int) (string, int)
}
tests := []struct {
name string
args args
want map[string]int
}{
{
name: "new keys",
args: args{
in: map[string]int{
"a": 1,
"b": 2,
"c": 3,
},
apply: func(s string, i int) (string, int) { return s + "-", i + 1 },
},
want: map[string]int{
"a-": 2,
"b-": 3,
"c-": 4,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := maputils.MapNewKeys(tt.args.in, tt.args.apply); !reflect.DeepEqual(
got,
tt.want,
) {
t.Errorf("MapNewKeys() = %v, want %v", got, tt.want)
}
})
}
}
func TestFilterMap(t *testing.T) {
type args struct {
dic map[string]int
filter func(string, int) bool
}
tests := []struct {
name string
args args
want map[string]int
}{
{
name: "filter",
args: args{
dic: map[string]int{
"a": 1,
"b": 2,
"c": 3,
},
filter: func(s string, i int) bool { return s == "a" },
},
want: map[string]int{"a": 1},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := maputils.FilterMap(tt.args.dic, tt.args.filter); !reflect.DeepEqual(
got,
tt.want,
) {
t.Errorf("FilterMap() = %v, want %v", got, tt.want)
}
})
}
}
func TestKeysFromMap(t *testing.T) {
type args struct {
m map[string]int
}
tests := []struct {
name string
args args
want []string
}{
{
name: "keys",
args: args{
m: map[string]int{
"a": 1,
"b": 2,
"c": 3,
},
},
want: []string{"a", "b", "c"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := maputils.KeysFromMap(tt.args.m); !sliceutils.CompareUnordered(got, tt.want) {
t.Errorf("KeysFromMap() = %v, want %v", got, tt.want)
}
})
}
}
func TestCompareMap(t *testing.T) {
type args struct {
a map[string]int
b map[string]int
}
tests := []struct {
name string
args args
want bool
}{
{
name: "equal",
args: args{
a: map[string]int{
"a": 1,
"b": 2,
"c": 3,
},
b: map[string]int{
"b": 2,
"a": 1,
"c": 3,
},
},
want: true,
},
{
name: "not equal, same len, same keys",
args: args{
a: map[string]int{
"a": 5,
"b": 6,
"c": 7,
},
b: map[string]int{
"a": 1,
"b": 2,
"c": 3,
},
},
want: false,
},
{
name: "not equal, diff len",
args: args{
a: map[string]int{
"a": 5,
"b": 6,
"c": 7,
},
b: map[string]int{
"a": 1,
"b": 2,
},
},
want: false,
},
{
name: "not equal, same len, diff keys",
args: args{
a: map[string]int{
"a": 5,
"b": 6,
"c": 7,
},
b: map[string]int{
"e": 1,
"f": 2,
"g": 3,
},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := maputils.CompareMap(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("CompareMap() = %v, want %v", got, tt.want)
}
})
}
}
func TestCompact(t *testing.T) {
type args struct {
m map[int]int
compactor func(accK int, accV int, nextK int, nextV int) (int, int)
}
tests := []struct {
name string
args args
want int
want1 int
}{
// TODO: Add test cases.
{
name: "compact",
args: args{
m: map[int]int{
4: 1,
5: 2,
6: 3,
},
compactor: func(accK int, accV int, nextK int, nextV int) (int, int) { return accK + nextK, accV + nextV },
},
want: 4 + 5 + 6,
want1: 1 + 2 + 3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1 := maputils.Compact(tt.args.m, tt.args.compactor)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Compact() got = %v, want %v", got, tt.want)
}
if !reflect.DeepEqual(got1, tt.want1) {
t.Errorf("Compact() got1 = %v, want %v", got1, tt.want1)
}
})
}
}

16
math/math_test.go Normal file
View file

@ -0,0 +1,16 @@
package mathutils_test
import (
"testing"
mathutils "git.mstar.dev/mstar/goutils/math"
)
func TestAbs(t *testing.T) {
if x := mathutils.Abs(-5); x != 5 {
t.Fatalf("Received %v, wanted 5", x)
}
if x := mathutils.Abs(6); x != 6 {
t.Fatalf("Received %v, wanted 6", x)
}
}

55
other/other_test.go Normal file
View file

@ -0,0 +1,55 @@
package other_test
import (
"errors"
"testing"
"git.mstar.dev/mstar/goutils/other"
)
func TestOutputIntoChannel(t *testing.T) {
c := make(chan int)
go func() {
other.OutputIntoChannel(10, c)
}()
x := <-c
if x != 10 {
t.Fatalf("sent %v, expected 10", x)
}
}
func TestMust_mustPanic(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("Must didn't panic on error")
}
}()
_ = other.Must(10, errors.New("some error"))
}
func TestMust_noPanic(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Fatalf("Must panicked: %v", r)
}
}()
x := other.Must(10, nil)
if x != 10 {
t.Fatalf("got %v, expected 10", x)
}
}
func TestIntoPointer(t *testing.T) {
p := other.IntoPointer(10)
if *p != 10 {
t.Fatalf("other.IntoPointer(10) = %v, want &10", p)
}
}
func TestError(t *testing.T) {
e := errors.New("some error")
we := other.Error("source", "message", e)
if we.Error() != "source: message: some error" {
t.Fatalf("Got %v, expected \"source: message: some error\"", we)
}
}

View file

@ -1,5 +1,8 @@
package other package other
// Can't really test zerolog setup functions as they rely on
// CLI flags
import ( import (
"flag" "flag"
"io" "io"
@ -72,5 +75,4 @@ func configOutputs(logWriter io.Writer) {
append([]io.Writer{log.Logger}, extraLogWriters...)..., append([]io.Writer{log.Logger}, extraLogWriters...)...,
)).With().Timestamp().Logger() )).With().Timestamp().Logger()
} }
return
} }

View file

@ -0,0 +1,243 @@
package sliceutils_test
import (
"reflect"
"testing"
"git.mstar.dev/mstar/goutils/sliceutils"
)
func TestMap(t *testing.T) {
in := []int8{1, 2, 3, 4}
out := []int16{2, 4, 6, 8}
got := sliceutils.Map(in, func(t int8) int16 { return int16(t) * 2 })
if !reflect.DeepEqual(out, got) {
t.Fatalf("Map() = %v, want %v", got, out)
}
}
func TestFilter(t *testing.T) {
in := []int8{1, 2, 3, 4}
out := []int8{2, 4}
got := sliceutils.Filter(in, func(t int8) bool { return t%2 == 0 })
if !reflect.DeepEqual(out, got) {
t.Fatalf("Map() = %v, want %v", got, out)
}
}
func TestRemoveDuplicate(t *testing.T) {
in := []int8{1, 2, 2, 3, 3, 3, 4}
out := []int8{1, 2, 3, 4}
got := sliceutils.RemoveDuplicate(in)
if !reflect.DeepEqual(out, got) {
t.Fatalf("Map() = %v, want %v", got, out)
}
}
func TestReverse(t *testing.T) {
in := []int8{1, 2, 3, 4}
out := []int8{4, 3, 2, 1}
sliceutils.Reverse(in)
if !reflect.DeepEqual(out, in) {
t.Fatalf("Map() = %v, want %v", in, out)
}
}
func TestCompareOrdered(t *testing.T) {
type args struct {
a []int
b []int
}
tests := []struct {
name string
args args
want bool
}{
{
name: "equal",
args: args{
a: []int{1, 2, 3, 4},
b: []int{1, 2, 3, 4},
},
want: true,
},
{
name: "not equal, same len",
args: args{
a: []int{1, 2, 3, 4},
b: []int{0, 1, 2, 3},
},
want: false,
},
{
name: "not equal, diff len",
args: args{
a: []int{1, 2, 3, 4},
b: []int{0, 1, 2},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sliceutils.CompareOrdered(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("CompareOrdered() = %v, want %v", got, tt.want)
}
})
}
}
func TestCompareUnordered(t *testing.T) {
type args struct {
a []int
b []int
}
tests := []struct {
name string
args args
want bool
}{
{
name: "equal ordered",
args: args{
a: []int{1, 2, 3, 4},
b: []int{1, 2, 3, 4},
},
want: true,
},
{
name: "equal unordered",
args: args{
a: []int{1, 2, 3, 4},
b: []int{2, 4, 3, 1},
},
want: true,
},
{
name: "not equal, same len",
args: args{
a: []int{1, 2, 3, 4},
b: []int{0, 2, 3, 4},
},
want: false,
},
{
name: "not equal, diff len",
args: args{
a: []int{1, 2, 3, 4},
b: []int{0, 1, 2},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sliceutils.CompareUnordered(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("CompareUnordered() = %v, want %v", got, tt.want)
}
})
}
}
func TestContains(t *testing.T) {
type args struct {
a []int
b int
}
tests := []struct {
name string
args args
want bool
}{
{
name: "contains",
args: args{
a: []int{1, 2, 3, 4},
b: 3,
},
want: true,
},
{
name: "doesnt contain",
args: args{
a: []int{1, 2, 3, 4},
b: 0,
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sliceutils.Contains(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("Contains() = %v, want %v", got, tt.want)
}
})
}
}
func TestContainsFunc(t *testing.T) {
type args struct {
a []int
f func(t int) bool
}
tests := []struct {
name string
args args
want bool
}{
{
name: "contains",
args: args{
a: []int{1, 2, 3, 4},
f: func(t int) bool { return t == 2 },
},
want: true,
},
{
name: "doesnt contain",
args: args{
a: []int{1, 2, 3, 4},
f: func(t int) bool { return t == 9 },
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sliceutils.ContainsFunc(tt.args.a, tt.args.f); got != tt.want {
t.Errorf("ContainsFunc() = %v, want %v", got, tt.want)
}
})
}
}
func TestCompact(t *testing.T) {
type args struct {
a []int
compactor func(acc int, next int) int
}
tests := []struct {
name string
args args
want int
}{
{
name: "sum",
args: args{
a: []int{1, 2, 3, 4},
compactor: func(acc, next int) int { return acc + next },
},
want: 1 + 2 + 3 + 4,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sliceutils.Compact(tt.args.a, tt.args.compactor); !reflect.DeepEqual(
got,
tt.want,
) {
t.Errorf("Compact() = %v, want %v", got, tt.want)
}
})
}
}