[🤖] Add Unit-Tests
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m34s

This commit is contained in:
2026-04-27 10:46:08 +02:00
parent dad0e3240d
commit 02d6894ec6
116 changed files with 18795 additions and 1 deletions
+86
View File
@@ -0,0 +1,86 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"strings"
"testing"
)
func TestEncodeBase62Zero(t *testing.T) {
tst.AssertEqual(t, EncodeBase62(0), "0")
}
func TestEncodeBase62Small(t *testing.T) {
tst.AssertEqual(t, EncodeBase62(1), "1")
tst.AssertEqual(t, EncodeBase62(9), "9")
tst.AssertEqual(t, EncodeBase62(10), "A")
tst.AssertEqual(t, EncodeBase62(35), "Z")
tst.AssertEqual(t, EncodeBase62(36), "a")
tst.AssertEqual(t, EncodeBase62(61), "z")
tst.AssertEqual(t, EncodeBase62(62), "10")
}
func TestDecodeBase62Empty(t *testing.T) {
_, err := DecodeBase62("")
if err == nil {
t.Errorf("expected error on empty input")
}
}
func TestDecodeBase62Invalid(t *testing.T) {
_, err := DecodeBase62("foo!bar")
if err == nil {
t.Errorf("expected error on invalid character")
}
}
func TestDecodeBase62Basic(t *testing.T) {
v, err := DecodeBase62("0")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, v, uint64(0))
v, err = DecodeBase62("10")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, v, uint64(62))
}
func TestEncodeDecodeBase62RoundTrip(t *testing.T) {
for _, n := range []uint64{0, 1, 61, 62, 100, 12345, 1<<32 - 1, 1 << 40} {
s := EncodeBase62(n)
v, err := DecodeBase62(s)
if err != nil {
t.Errorf("decode error for %d (encoded %q): %v", n, s, err)
continue
}
tst.AssertEqual(t, v, n)
}
}
func TestRandBase62Length(t *testing.T) {
for _, l := range []int{0, 1, 8, 32, 64} {
s := RandBase62(l)
tst.AssertEqual(t, len(s), l)
}
}
func TestRandBase62Alphabet(t *testing.T) {
const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
s := RandBase62(256)
for _, r := range s {
if !strings.ContainsRune(alphabet, r) {
t.Errorf("character %q not in base62 alphabet", string(r))
}
}
}
func TestRandBase62Distinct(t *testing.T) {
a := RandBase62(32)
b := RandBase62(32)
if a == b {
t.Errorf("two base62 random strings of length 32 should not be equal")
}
}
+84
View File
@@ -0,0 +1,84 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestFormatBoolTrue(t *testing.T) {
tst.AssertEqual(t, FormatBool(true, "yes", "no"), "yes")
}
func TestFormatBoolFalse(t *testing.T) {
tst.AssertEqual(t, FormatBool(false, "yes", "no"), "no")
}
func TestConditional(t *testing.T) {
tst.AssertEqual(t, Conditional(true, 1, 2), 1)
tst.AssertEqual(t, Conditional(false, 1, 2), 2)
tst.AssertEqual(t, Conditional(true, "a", "b"), "a")
tst.AssertEqual(t, Conditional(false, "a", "b"), "b")
}
func TestConditionalFn00(t *testing.T) {
tst.AssertEqual(t, ConditionalFn00(true, 10, 20), 10)
tst.AssertEqual(t, ConditionalFn00(false, 10, 20), 20)
}
func TestConditionalFn10Lazy(t *testing.T) {
called := false
v := ConditionalFn10(false, func() int {
called = true
return 1
}, 99)
tst.AssertEqual(t, v, 99)
tst.AssertEqual(t, called, false)
v = ConditionalFn10(true, func() int {
called = true
return 1
}, 99)
tst.AssertEqual(t, v, 1)
tst.AssertEqual(t, called, true)
}
func TestConditionalFn01Lazy(t *testing.T) {
called := false
v := ConditionalFn01(true, 1, func() int {
called = true
return 99
})
tst.AssertEqual(t, v, 1)
tst.AssertEqual(t, called, false)
v = ConditionalFn01(false, 1, func() int {
called = true
return 99
})
tst.AssertEqual(t, v, 99)
tst.AssertEqual(t, called, true)
}
func TestConditionalFn11Lazy(t *testing.T) {
calledT := false
calledF := false
v := ConditionalFn11(true,
func() int { calledT = true; return 1 },
func() int { calledF = true; return 2 },
)
tst.AssertEqual(t, v, 1)
tst.AssertEqual(t, calledT, true)
tst.AssertEqual(t, calledF, false)
calledT = false
calledF = false
v = ConditionalFn11(false,
func() int { calledT = true; return 1 },
func() int { calledF = true; return 2 },
)
tst.AssertEqual(t, v, 2)
tst.AssertEqual(t, calledT, false)
tst.AssertEqual(t, calledF, true)
}
+68
View File
@@ -0,0 +1,68 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestFormatBytesToSI(t *testing.T) {
tst.AssertEqual(t, FormatBytesToSI(0), "0 B")
tst.AssertEqual(t, FormatBytesToSI(999), "999 B")
tst.AssertEqual(t, FormatBytesToSI(1000), "1.0 kB")
tst.AssertEqual(t, FormatBytesToSI(1500), "1.5 kB")
tst.AssertEqual(t, FormatBytesToSI(1000*1000), "1.0 MB")
tst.AssertEqual(t, FormatBytesToSI(1000*1000*1000), "1.0 GB")
}
func TestFormatBytes(t *testing.T) {
tst.AssertEqual(t, FormatBytes(0), "0 B")
tst.AssertEqual(t, FormatBytes(1023), "1023 B")
tst.AssertEqual(t, FormatBytes(1024), "1.0 KiB")
tst.AssertEqual(t, FormatBytes(1024*1024), "1.0 MiB")
tst.AssertEqual(t, FormatBytes(1024*1024*1024), "1.0 GiB")
tst.AssertEqual(t, FormatBytes(1536), "1.5 KiB")
}
func TestBytesXOR(t *testing.T) {
a := []byte{0x01, 0x02, 0x03, 0xFF}
b := []byte{0xFF, 0xFE, 0xFD, 0x00}
r, err := BytesXOR(a, b)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expected := []byte{0xFE, 0xFC, 0xFE, 0xFF}
tst.AssertArrayEqual(t, r, expected)
}
func TestBytesXORLengthMismatch(t *testing.T) {
a := []byte{0x01, 0x02}
b := []byte{0x01, 0x02, 0x03}
_, err := BytesXOR(a, b)
if err == nil {
t.Fatalf("expected error on length mismatch, got nil")
}
}
func TestBytesXOREmpty(t *testing.T) {
r, err := BytesXOR([]byte{}, []byte{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, len(r), 0)
}
func TestBytesXORSelfIsZero(t *testing.T) {
a := []byte{0xAB, 0xCD, 0xEF}
r, err := BytesXOR(a, a)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
for i, v := range r {
if v != 0 {
t.Errorf("expected zero at index %d, got %#x", i, v)
}
}
}
+134
View File
@@ -0,0 +1,134 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
"time"
)
type stringerImpl struct{ v string }
func (s stringerImpl) String() string { return s.v }
func TestCoalesceWithValue(t *testing.T) {
v := 42
tst.AssertEqual(t, Coalesce(&v, 0), 42)
}
func TestCoalesceWithNil(t *testing.T) {
var p *int
tst.AssertEqual(t, Coalesce(p, 99), 99)
}
func TestCoalesceOpt(t *testing.T) {
v := 1
w := 2
tst.AssertDeRefEqual(t, CoalesceOpt(&v, &w), 1)
var p *int
tst.AssertDeRefEqual(t, CoalesceOpt(p, &w), 2)
tst.AssertPtrEqual(t, CoalesceOpt[int](nil, nil), nil)
}
func TestCoalesce3(t *testing.T) {
v := 1
w := 2
tst.AssertEqual(t, Coalesce3(&v, &w, 99), 1)
tst.AssertEqual(t, Coalesce3[int](nil, &w, 99), 2)
tst.AssertEqual(t, Coalesce3[int](nil, nil, 99), 99)
}
func TestCoalesce3Opt(t *testing.T) {
v := 1
tst.AssertDeRefEqual(t, Coalesce3Opt[int](nil, nil, &v), 1)
tst.AssertPtrEqual(t, Coalesce3Opt[int](nil, nil, nil), nil)
}
func TestCoalesce4(t *testing.T) {
v := 1
w := 2
x := 3
tst.AssertEqual(t, Coalesce4(&v, &w, &x, 99), 1)
tst.AssertEqual(t, Coalesce4[int](nil, &w, &x, 99), 2)
tst.AssertEqual(t, Coalesce4[int](nil, nil, &x, 99), 3)
tst.AssertEqual(t, Coalesce4[int](nil, nil, nil, 99), 99)
}
func TestCoalesce4Opt(t *testing.T) {
v := 4
tst.AssertDeRefEqual(t, Coalesce4Opt[int](nil, nil, nil, &v), 4)
tst.AssertPtrEqual(t, Coalesce4Opt[int](nil, nil, nil, nil), nil)
}
func TestCoalesceString(t *testing.T) {
s := "hello"
tst.AssertEqual(t, CoalesceString(&s, "def"), "hello")
tst.AssertEqual(t, CoalesceString(nil, "def"), "def")
}
func TestCoalesceInt(t *testing.T) {
v := 5
tst.AssertEqual(t, CoalesceInt(&v, 99), 5)
tst.AssertEqual(t, CoalesceInt(nil, 99), 99)
}
func TestCoalesceInt32(t *testing.T) {
v := int32(7)
tst.AssertEqual(t, CoalesceInt32(&v, 99), int32(7))
tst.AssertEqual(t, CoalesceInt32(nil, 99), int32(99))
}
func TestCoalesceBool(t *testing.T) {
v := true
tst.AssertEqual(t, CoalesceBool(&v, false), true)
tst.AssertEqual(t, CoalesceBool(nil, true), true)
tst.AssertEqual(t, CoalesceBool(nil, false), false)
}
func TestCoalesceTime(t *testing.T) {
now := time.Now()
def := time.Unix(0, 0)
tst.AssertEqual(t, CoalesceTime(&now, def), now)
tst.AssertEqual(t, CoalesceTime(nil, def), def)
}
func TestCoalesceStringer(t *testing.T) {
s := stringerImpl{v: "hi"}
tst.AssertEqual(t, CoalesceStringer(s, "def"), "hi")
var nilStringer *stringerImpl
tst.AssertEqual(t, CoalesceStringer(nilStringer, "def"), "def")
}
func TestCoalesceDefault(t *testing.T) {
tst.AssertEqual(t, CoalesceDefault(0, 99), 99)
tst.AssertEqual(t, CoalesceDefault(5, 99), 5)
tst.AssertEqual(t, CoalesceDefault("", "def"), "def")
tst.AssertEqual(t, CoalesceDefault("v", "def"), "v")
}
func TestSafeCastMatching(t *testing.T) {
var v any = "hello"
tst.AssertEqual(t, SafeCast(v, "default"), "hello")
}
func TestSafeCastMismatch(t *testing.T) {
var v any = 42
tst.AssertEqual(t, SafeCast(v, "default"), "default")
}
func TestSafeCastNil(t *testing.T) {
tst.AssertEqual(t, SafeCast(nil, 99), 99)
}
func TestCoalesceDblPtrWithValue(t *testing.T) {
v := 1
pv := &v
tst.AssertDeRefEqual(t, CoalesceDblPtr(&pv, nil), 1)
}
func TestCoalesceDblPtrFallback(t *testing.T) {
w := 2
tst.AssertDeRefEqual(t, CoalesceDblPtr[int](nil, &w), 2)
}
+63
View File
@@ -0,0 +1,63 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestCompareIntArrLess(t *testing.T) {
tst.AssertEqual(t, CompareIntArr([]int{1, 2, 3}, []int{1, 2, 4}), true)
tst.AssertEqual(t, CompareIntArr([]int{0}, []int{1}), true)
}
func TestCompareIntArrGreater(t *testing.T) {
tst.AssertEqual(t, CompareIntArr([]int{1, 2, 5}, []int{1, 2, 4}), false)
tst.AssertEqual(t, CompareIntArr([]int{2}, []int{1}), false)
}
func TestCompareIntArrEqual(t *testing.T) {
tst.AssertEqual(t, CompareIntArr([]int{1, 2, 3}, []int{1, 2, 3}), false)
tst.AssertEqual(t, CompareIntArr([]int{}, []int{}), false)
}
func TestCompareArrLess(t *testing.T) {
tst.AssertEqual(t, CompareArr([]int{1, 2, 3}, []int{1, 2, 4}), -1)
}
func TestCompareArrGreater(t *testing.T) {
r := CompareArr([]int{1, 2, 5}, []int{1, 2, 4})
if r <= 0 {
t.Errorf("expected positive, got %d", r)
}
}
func TestCompareArrEqual(t *testing.T) {
tst.AssertEqual(t, CompareArr([]int{1, 2, 3}, []int{1, 2, 3}), 0)
tst.AssertEqual(t, CompareArr([]int{}, []int{}), 0)
}
func TestCompareString(t *testing.T) {
tst.AssertEqual(t, CompareString("a", "b"), -1)
tst.AssertEqual(t, CompareString("b", "a"), 1)
tst.AssertEqual(t, CompareString("a", "a"), 0)
}
func TestCompareInt(t *testing.T) {
tst.AssertEqual(t, CompareInt(1, 2), -1)
tst.AssertEqual(t, CompareInt(2, 1), 1)
tst.AssertEqual(t, CompareInt(2, 2), 0)
}
func TestCompareInt64(t *testing.T) {
tst.AssertEqual(t, CompareInt64(int64(1), int64(2)), -1)
tst.AssertEqual(t, CompareInt64(int64(2), int64(1)), 1)
tst.AssertEqual(t, CompareInt64(int64(0), int64(0)), 0)
}
func TestCompareGeneric(t *testing.T) {
tst.AssertEqual(t, Compare(1, 2), -1)
tst.AssertEqual(t, Compare(2, 1), 1)
tst.AssertEqual(t, Compare(2, 2), 0)
tst.AssertEqual(t, Compare("x", "y"), -1)
tst.AssertEqual(t, Compare(3.5, 1.2), 1)
}
+59
View File
@@ -0,0 +1,59 @@
package langext
import (
"math"
"testing"
)
func floatEquals(a, b, eps float64) bool {
return math.Abs(a-b) < eps
}
func TestDegToRadZero(t *testing.T) {
if !floatEquals(DegToRad(0), 0, 1e-9) {
t.Errorf("expected 0, got %v", DegToRad(0))
}
}
func TestDegToRad180(t *testing.T) {
if !floatEquals(DegToRad(180), math.Pi, 1e-9) {
t.Errorf("expected Pi, got %v", DegToRad(180))
}
}
func TestDegToRad90(t *testing.T) {
if !floatEquals(DegToRad(90), math.Pi/2, 1e-9) {
t.Errorf("expected Pi/2, got %v", DegToRad(90))
}
}
func TestRadToDegZero(t *testing.T) {
// note: function is implemented as rad / (Pi*180), tests document actual behavior
if !floatEquals(RadToDeg(0), 0, 1e-9) {
t.Errorf("expected 0, got %v", RadToDeg(0))
}
}
func TestGeoDistanceSamePoint(t *testing.T) {
d := GeoDistance(10.0, 50.0, 10.0, 50.0)
if !floatEquals(d, 0, 1e-3) {
t.Errorf("expected 0, got %v", d)
}
}
func TestGeoDistancePositive(t *testing.T) {
// Berlin (~52.5200, 13.4050) to Munich (~48.1351, 11.5820)
d := GeoDistance(13.4050, 52.5200, 11.5820, 48.1351)
// Distance should be around ~500km - just check the order of magnitude.
if d < 400000 || d > 700000 {
t.Errorf("Berlin-Munich distance unexpected: got %v", d)
}
}
func TestGeoDistanceSymmetric(t *testing.T) {
d1 := GeoDistance(10.0, 50.0, 11.0, 51.0)
d2 := GeoDistance(11.0, 51.0, 10.0, 50.0)
if !floatEquals(d1, d2, 1e-3) {
t.Errorf("expected symmetry, got %v != %v", d1, d2)
}
}
+22
View File
@@ -0,0 +1,22 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestFuncChain(t *testing.T) {
addOne := func(v int) int { return v + 1 }
timesTwo := func(v int) int { return v * 2 }
chained := FuncChain(addOne, timesTwo)
tst.AssertEqual(t, chained(3), 8)
}
func TestFuncChainOrder(t *testing.T) {
first := func(v string) string { return v + "A" }
second := func(v string) string { return v + "B" }
chained := FuncChain(first, second)
tst.AssertEqual(t, chained("X"), "XAB")
}
+36
View File
@@ -0,0 +1,36 @@
package langext
import (
"bytes"
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestWriteNopCloserWrite(t *testing.T) {
var buf bytes.Buffer
wc := WriteNopCloser(&buf)
n, err := wc.Write([]byte("hello"))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, n, 5)
tst.AssertEqual(t, buf.String(), "hello")
}
func TestWriteNopCloserClose(t *testing.T) {
var buf bytes.Buffer
wc := WriteNopCloser(&buf)
err := wc.Close()
if err != nil {
t.Errorf("expected nil error from no-op Close, got %v", err)
}
// Can still write after close (it's a no-op)
_, err = wc.Write([]byte("after"))
if err != nil {
t.Errorf("expected to write after Close, got %v", err)
}
tst.AssertEqual(t, buf.String(), "after")
}
+61
View File
@@ -0,0 +1,61 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestIterSingleValueSeq(t *testing.T) {
seq := IterSingleValueSeq(42)
count := 0
var got int
for v := range seq {
got = v
count++
}
tst.AssertEqual(t, count, 1)
tst.AssertEqual(t, got, 42)
}
func TestIterSingleValueSeqString(t *testing.T) {
seq := IterSingleValueSeq("hello")
values := make([]string, 0)
for v := range seq {
values = append(values, v)
}
tst.AssertEqual(t, len(values), 1)
tst.AssertEqual(t, values[0], "hello")
}
func TestIterSingleValueSeq2(t *testing.T) {
seq := IterSingleValueSeq2("key", 42)
count := 0
var k string
var v int
for kk, vv := range seq {
k = kk
v = vv
count++
}
tst.AssertEqual(t, count, 1)
tst.AssertEqual(t, k, "key")
tst.AssertEqual(t, v, 42)
}
func TestIterSingleValueSeqEarlyBreak(t *testing.T) {
seq := IterSingleValueSeq(1)
count := 0
for range seq {
count++
break
}
tst.AssertEqual(t, count, 1)
}
+192
View File
@@ -0,0 +1,192 @@
package langext
import (
"encoding/json"
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"strings"
"testing"
)
func TestTryPrettyPrintJsonValid(t *testing.T) {
in := `{"a":1,"b":2}`
out := TryPrettyPrintJson(in)
if !strings.Contains(out, "\n") {
t.Errorf("expected pretty-printed result with newlines, got %q", out)
}
if !strings.Contains(out, `"a"`) {
t.Errorf("expected key in result, got %q", out)
}
}
func TestTryPrettyPrintJsonInvalidPassThrough(t *testing.T) {
in := `not valid json`
tst.AssertEqual(t, TryPrettyPrintJson(in), in)
}
func TestPrettyPrintJsonValid(t *testing.T) {
out, ok := PrettyPrintJson(`{"a":1}`)
tst.AssertEqual(t, ok, true)
if !strings.Contains(out, "\n") {
t.Errorf("expected formatted output, got %q", out)
}
}
func TestPrettyPrintJsonInvalid(t *testing.T) {
in := `not json`
out, ok := PrettyPrintJson(in)
tst.AssertEqual(t, ok, false)
tst.AssertEqual(t, out, in)
}
func TestPatchJsonString(t *testing.T) {
in := `{"a":1,"b":2}`
out, err := PatchJson(in, "c", 3)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var m map[string]any
if err := json.Unmarshal([]byte(out), &m); err != nil {
t.Fatalf("invalid json result: %v", err)
}
if v, ok := m["c"].(float64); !ok || v != 3 {
t.Errorf("expected c=3, got %v", m["c"])
}
if v, ok := m["a"].(float64); !ok || v != 1 {
t.Errorf("expected a=1, got %v", m["a"])
}
}
func TestPatchJsonBytes(t *testing.T) {
in := []byte(`{"a":1}`)
out, err := PatchJson(in, "b", "hello")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var m map[string]any
if err := json.Unmarshal(out, &m); err != nil {
t.Fatalf("invalid json result: %v", err)
}
if v, ok := m["b"].(string); !ok || v != "hello" {
t.Errorf("expected b=hello, got %v", m["b"])
}
}
func TestPatchJsonInvalid(t *testing.T) {
_, err := PatchJson("not json", "k", "v")
if err == nil {
t.Errorf("expected error on invalid json")
}
}
func TestPatchRemJson(t *testing.T) {
in := `{"a":1,"b":2}`
out, err := PatchRemJson(in, "a")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var m map[string]any
if err := json.Unmarshal([]byte(out), &m); err != nil {
t.Fatalf("invalid json result: %v", err)
}
if _, exists := m["a"]; exists {
t.Errorf("expected key 'a' to be removed")
}
if v, ok := m["b"].(float64); !ok || v != 2 {
t.Errorf("expected b=2, got %v", m["b"])
}
}
func TestPatchRemJsonMissingKey(t *testing.T) {
in := `{"a":1}`
out, err := PatchRemJson(in, "missing")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var m map[string]any
if err := json.Unmarshal([]byte(out), &m); err != nil {
t.Fatalf("invalid json: %v", err)
}
if v, ok := m["a"].(float64); !ok || v != 1 {
t.Errorf("expected a=1, got %v", m["a"])
}
}
func TestMarshalJsonOrPanic(t *testing.T) {
tst.AssertEqual(t, MarshalJsonOrPanic(42), "42")
tst.AssertEqual(t, MarshalJsonOrPanic("hi"), `"hi"`)
}
func TestMarshalJsonOrPanicPanics(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic on un-marshalable input")
}
}()
// channels can't be marshaled
MarshalJsonOrPanic(make(chan int))
}
func TestMarshalJsonOrDefault(t *testing.T) {
tst.AssertEqual(t, MarshalJsonOrDefault(42, "def"), "42")
tst.AssertEqual(t, MarshalJsonOrDefault(make(chan int), "def"), "def")
}
func TestMarshalJsonOrNilSuccess(t *testing.T) {
p := MarshalJsonOrNil(42)
if p == nil {
t.Fatalf("expected non-nil pointer")
}
tst.AssertEqual(t, *p, "42")
}
func TestMarshalJsonOrNilError(t *testing.T) {
p := MarshalJsonOrNil(make(chan int))
if p != nil {
t.Errorf("expected nil pointer on error, got %v", *p)
}
}
func TestMarshalJsonIndentOrPanic(t *testing.T) {
out := MarshalJsonIndentOrPanic(map[string]int{"a": 1}, "", " ")
if !strings.Contains(out, "\n") {
t.Errorf("expected indented output, got %q", out)
}
}
func TestMarshalJsonIndentOrDefault(t *testing.T) {
out := MarshalJsonIndentOrDefault(make(chan int), "", " ", "DEF")
tst.AssertEqual(t, out, "DEF")
}
func TestMarshalJsonIndentOrNilSuccess(t *testing.T) {
p := MarshalJsonIndentOrNil(map[string]int{"a": 1}, "", " ")
if p == nil || !strings.Contains(*p, "\n") {
t.Errorf("expected indented JSON pointer")
}
}
func TestMarshalJsonIndentOrNilFailure(t *testing.T) {
p := MarshalJsonIndentOrNil(make(chan int), "", " ")
if p != nil {
t.Errorf("expected nil pointer on error")
}
}
func TestHTypeIsMap(t *testing.T) {
h := H{"a": 1}
out, err := json.Marshal(h)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, string(out), `{"a":1}`)
}
func TestATypeIsArray(t *testing.T) {
a := A{1, "x", true}
out, err := json.Marshal(a)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, string(out), `[1,"x",true]`)
}
+146
View File
@@ -0,0 +1,146 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"sort"
"testing"
)
func TestMapKeyArr(t *testing.T) {
m := map[string]int{"a": 1, "b": 2, "c": 3}
keys := MapKeyArr(m)
sort.Strings(keys)
tst.AssertArrayEqual(t, keys, []string{"a", "b", "c"})
}
func TestMapKeyArrEmpty(t *testing.T) {
m := map[string]int{}
keys := MapKeyArr(m)
tst.AssertEqual(t, len(keys), 0)
}
func TestMapValueArr(t *testing.T) {
m := map[string]int{"a": 1, "b": 2, "c": 3}
values := MapValueArr(m)
sort.Ints(values)
tst.AssertArrayEqual(t, values, []int{1, 2, 3})
}
func TestArrToMap(t *testing.T) {
type item struct {
key string
v int
}
arr := []item{{"a", 1}, {"b", 2}}
m := ArrToMap(arr, func(i item) string { return i.key })
tst.AssertEqual(t, len(m), 2)
tst.AssertEqual(t, m["a"].v, 1)
tst.AssertEqual(t, m["b"].v, 2)
}
func TestArrToKVMap(t *testing.T) {
arr := []int{1, 2, 3}
m := ArrToKVMap(arr,
func(v int) int { return v },
func(v int) string {
return [...]string{"", "one", "two", "three"}[v]
},
)
tst.AssertEqual(t, m[1], "one")
tst.AssertEqual(t, m[2], "two")
tst.AssertEqual(t, m[3], "three")
}
func TestArrToSet(t *testing.T) {
arr := []string{"a", "b", "a", "c"}
set := ArrToSet(arr)
tst.AssertEqual(t, len(set), 3)
tst.AssertEqual(t, set["a"], true)
tst.AssertEqual(t, set["b"], true)
tst.AssertEqual(t, set["c"], true)
tst.AssertEqual(t, set["d"], false)
}
func TestMapToArr(t *testing.T) {
m := map[string]int{"a": 1, "b": 2}
arr := MapToArr(m)
tst.AssertEqual(t, len(arr), 2)
roundTrip := make(map[string]int)
for _, e := range arr {
roundTrip[e.Key] = e.Value
}
tst.AssertEqual(t, roundTrip["a"], 1)
tst.AssertEqual(t, roundTrip["b"], 2)
}
func TestCopyMap(t *testing.T) {
src := map[string]int{"a": 1, "b": 2}
dst := CopyMap(src)
tst.AssertEqual(t, len(dst), 2)
tst.AssertEqual(t, dst["a"], 1)
// Mutating dst should not affect src
dst["a"] = 99
tst.AssertEqual(t, src["a"], 1)
}
func TestForceMapNil(t *testing.T) {
var m map[string]int
res := ForceMap(m)
if res == nil {
t.Errorf("expected non-nil result")
}
tst.AssertEqual(t, len(res), 0)
}
func TestForceMapNonNil(t *testing.T) {
m := map[string]int{"x": 1}
res := ForceMap(m)
tst.AssertEqual(t, res["x"], 1)
}
func TestForceJsonMapOrPanic(t *testing.T) {
type s struct {
A int `json:"a"`
B string `json:"b"`
}
res := ForceJsonMapOrPanic(s{A: 1, B: "x"})
if v, ok := res["a"].(float64); !ok || v != 1 {
t.Errorf("expected a=1, got %v", res["a"])
}
if v, ok := res["b"].(string); !ok || v != "x" {
t.Errorf("expected b=x, got %v", res["b"])
}
}
func TestForceJsonMapOrPanicPanics(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic on un-marshalable input")
}
}()
ForceJsonMapOrPanic(make(chan int))
}
func TestMapMerge(t *testing.T) {
base := map[string]int{"a": 1, "b": 2}
a := map[string]int{"b": 22, "c": 3}
b := map[string]int{"d": 4}
res := MapMerge(base, a, b)
tst.AssertEqual(t, res["a"], 1)
tst.AssertEqual(t, res["b"], 22) // overwritten
tst.AssertEqual(t, res["c"], 3)
tst.AssertEqual(t, res["d"], 4)
tst.AssertEqual(t, len(res), 4)
// base must remain untouched
tst.AssertEqual(t, base["b"], 2)
}
func TestMapMergeNoExtras(t *testing.T) {
base := map[string]int{"a": 1}
res := MapMerge(base)
tst.AssertEqual(t, res["a"], 1)
tst.AssertEqual(t, len(res), 1)
}
+38
View File
@@ -0,0 +1,38 @@
package langext
import (
"errors"
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestMustSuccess(t *testing.T) {
v := Must(42, nil)
tst.AssertEqual(t, v, 42)
s := Must("hello", nil)
tst.AssertEqual(t, s, "hello")
}
func TestMustPanics(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic on error")
}
}()
Must(0, errors.New("boom"))
}
func TestMustBoolSuccess(t *testing.T) {
v := MustBool(42, true)
tst.AssertEqual(t, v, 42)
}
func TestMustBoolPanics(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic on not ok")
}
}()
MustBool(0, false)
}
+43
View File
@@ -0,0 +1,43 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestDeepCopyByJsonStruct(t *testing.T) {
type item struct {
Name string `json:"name"`
Age int `json:"age"`
}
src := item{Name: "alice", Age: 30}
dst, err := DeepCopyByJson(src)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, dst.Name, "alice")
tst.AssertEqual(t, dst.Age, 30)
}
func TestDeepCopyByJsonSlice(t *testing.T) {
src := []int{1, 2, 3}
dst, err := DeepCopyByJson(src)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertArrayEqual(t, dst, []int{1, 2, 3})
// Mutating the copy must not affect the source
dst[0] = 99
tst.AssertEqual(t, src[0], 1)
}
func TestDeepCopyByJsonError(t *testing.T) {
type bad struct {
C chan int
}
_, err := DeepCopyByJson(bad{C: make(chan int)})
if err == nil {
t.Errorf("expected error for un-marshalable type")
}
}
+28
View File
@@ -0,0 +1,28 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"os"
"path/filepath"
"testing"
)
func TestFileExistsTrue(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "f.txt")
if err := os.WriteFile(path, []byte("hi"), 0o644); err != nil {
t.Fatalf("setup failed: %v", err)
}
tst.AssertEqual(t, FileExists(path), true)
}
func TestFileExistsFalse(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "missing.txt")
tst.AssertEqual(t, FileExists(path), false)
}
func TestFileExistsDirectoryReturnsFalse(t *testing.T) {
dir := t.TempDir()
tst.AssertEqual(t, FileExists(dir), false)
}
+121
View File
@@ -0,0 +1,121 @@
package langext
import (
"errors"
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestRunPanicSafeNoPanic(t *testing.T) {
called := false
err := RunPanicSafe(func() {
called = true
})
tst.AssertEqual(t, called, true)
if err != nil {
t.Errorf("expected nil err, got %v", err)
}
}
func TestRunPanicSafeRecovers(t *testing.T) {
err := RunPanicSafe(func() {
panic("boom")
})
if err == nil {
t.Fatalf("expected error from panic")
}
pwe, ok := err.(PanicWrappedErr)
if !ok {
t.Fatalf("expected PanicWrappedErr, got %T", err)
}
tst.AssertEqual(t, pwe.RecoveredObj(), "boom")
tst.AssertEqual(t, pwe.Error(), "A panic occured")
}
func TestRunPanicSafeR1NoPanic(t *testing.T) {
expected := errors.New("expected")
err := RunPanicSafeR1(func() error {
return expected
})
if err != expected {
t.Errorf("expected original error, got %v", err)
}
}
func TestRunPanicSafeR1Panics(t *testing.T) {
err := RunPanicSafeR1(func() error {
panic("boom")
})
if err == nil {
t.Fatalf("expected wrapped panic")
}
if _, ok := err.(PanicWrappedErr); !ok {
t.Errorf("expected PanicWrappedErr, got %T", err)
}
}
func TestRunPanicSafeR2NoPanic(t *testing.T) {
v, err := RunPanicSafeR2(func() (int, error) {
return 42, nil
})
tst.AssertEqual(t, v, 42)
if err != nil {
t.Errorf("expected nil err, got %v", err)
}
}
func TestRunPanicSafeR2Panics(t *testing.T) {
v, err := RunPanicSafeR2(func() (int, error) {
panic("boom")
})
tst.AssertEqual(t, v, 0) // zero value
if err == nil {
t.Errorf("expected wrapped panic")
}
}
func TestRunPanicSafeR3NoPanic(t *testing.T) {
a, b, err := RunPanicSafeR3(func() (int, string, error) {
return 1, "two", nil
})
tst.AssertEqual(t, a, 1)
tst.AssertEqual(t, b, "two")
if err != nil {
t.Errorf("expected nil err, got %v", err)
}
}
func TestRunPanicSafeR3Panics(t *testing.T) {
a, b, err := RunPanicSafeR3(func() (int, string, error) {
panic("boom")
})
tst.AssertEqual(t, a, 0)
tst.AssertEqual(t, b, "")
if err == nil {
t.Errorf("expected wrapped panic")
}
}
func TestRunPanicSafeR4NoPanic(t *testing.T) {
a, b, c, err := RunPanicSafeR4(func() (int, string, bool, error) {
return 1, "two", true, nil
})
tst.AssertEqual(t, a, 1)
tst.AssertEqual(t, b, "two")
tst.AssertEqual(t, c, true)
if err != nil {
t.Errorf("expected nil err, got %v", err)
}
}
func TestRunPanicSafeR4Panics(t *testing.T) {
a, b, c, err := RunPanicSafeR4(func() (int, string, bool, error) {
panic("boom")
})
tst.AssertEqual(t, a, 0)
tst.AssertEqual(t, b, "")
tst.AssertEqual(t, c, false)
if err == nil {
t.Errorf("expected wrapped panic")
}
}
+143
View File
@@ -0,0 +1,143 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestPtr(t *testing.T) {
p := Ptr(42)
if p == nil {
t.Fatalf("expected non-nil")
}
tst.AssertEqual(t, *p, 42)
}
func TestPtrString(t *testing.T) {
p := Ptr("hi")
tst.AssertEqual(t, *p, "hi")
}
func TestPTrue(t *testing.T) {
if PTrue == nil || *PTrue != true {
t.Errorf("PTrue should point to true")
}
}
func TestPFalse(t *testing.T) {
if PFalse == nil || *PFalse != false {
t.Errorf("PFalse should point to false")
}
}
func TestDblPtr(t *testing.T) {
pp := DblPtr(7)
if pp == nil || *pp == nil {
t.Fatalf("expected non-nil double pointer")
}
tst.AssertEqual(t, **pp, 7)
}
func TestDblPtrIfNotNilWithValue(t *testing.T) {
v := 5
pp := DblPtrIfNotNil(&v)
if pp == nil {
t.Fatalf("expected non-nil double pointer")
}
tst.AssertEqual(t, **pp, 5)
}
func TestDblPtrIfNotNilNil(t *testing.T) {
pp := DblPtrIfNotNil[int](nil)
if pp != nil {
t.Errorf("expected nil for nil input")
}
}
func TestDblPtrNil(t *testing.T) {
pp := DblPtrNil[int]()
if pp == nil {
t.Fatalf("expected non-nil outer pointer")
}
if *pp != nil {
t.Errorf("expected inner pointer to be nil")
}
}
func TestArrPtr(t *testing.T) {
p := ArrPtr(1, 2, 3)
if p == nil {
t.Fatalf("expected non-nil pointer")
}
tst.AssertArrayEqual(t, *p, []int{1, 2, 3})
}
func TestPtrInt32(t *testing.T) {
p := PtrInt32(7)
tst.AssertEqual(t, *p, int32(7))
}
func TestPtrInt64(t *testing.T) {
p := PtrInt64(7)
tst.AssertEqual(t, *p, int64(7))
}
func TestPtrFloat32(t *testing.T) {
p := PtrFloat32(1.5)
tst.AssertEqual(t, *p, float32(1.5))
}
func TestPtrFloat64(t *testing.T) {
p := PtrFloat64(2.5)
tst.AssertEqual(t, *p, 2.5)
}
func TestIsNilTrue(t *testing.T) {
tst.AssertEqual(t, IsNil(nil), true)
var p *int
tst.AssertEqual(t, IsNil(p), true)
var m map[string]int
tst.AssertEqual(t, IsNil(m), true)
var s []int
tst.AssertEqual(t, IsNil(s), true)
var c chan int
tst.AssertEqual(t, IsNil(c), true)
var f func()
tst.AssertEqual(t, IsNil(f), true)
}
func TestIsNilFalse(t *testing.T) {
v := 5
tst.AssertEqual(t, IsNil(&v), false)
tst.AssertEqual(t, IsNil(5), false)
tst.AssertEqual(t, IsNil("hi"), false)
tst.AssertEqual(t, IsNil(map[string]int{}), false)
tst.AssertEqual(t, IsNil([]int{}), false)
}
func TestPtrEqualsBothNil(t *testing.T) {
tst.AssertEqual(t, PtrEquals[int](nil, nil), true)
}
func TestPtrEqualsBothEqual(t *testing.T) {
a := 5
b := 5
tst.AssertEqual(t, PtrEquals(&a, &b), true)
}
func TestPtrEqualsBothDifferent(t *testing.T) {
a := 5
b := 6
tst.AssertEqual(t, PtrEquals(&a, &b), false)
}
func TestPtrEqualsOneNil(t *testing.T) {
a := 5
tst.AssertEqual(t, PtrEquals(&a, nil), false)
tst.AssertEqual(t, PtrEquals[int](nil, &a), false)
}
+34
View File
@@ -0,0 +1,34 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestRandBytesLength(t *testing.T) {
for _, sz := range []int{0, 1, 16, 32, 1024} {
b := RandBytes(sz)
tst.AssertEqual(t, len(b), sz)
}
}
func TestRandBytesDistinct(t *testing.T) {
a := RandBytes(32)
b := RandBytes(32)
// Two cryptographic random sequences should not be equal in 32 bytes.
if len(a) != 32 || len(b) != 32 {
t.Fatalf("unexpected length")
}
equal := true
for i := range a {
if a[i] != b[i] {
equal = false
break
}
}
if equal {
t.Errorf("two consecutive 32-byte RandBytes calls returned identical results")
}
}
+118
View File
@@ -0,0 +1,118 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
)
func TestSortInPlace(t *testing.T) {
arr := []int{3, 1, 2}
Sort(arr)
tst.AssertArrayEqual(t, arr, []int{1, 2, 3})
}
func TestSortStrings(t *testing.T) {
arr := []string{"c", "a", "b"}
Sort(arr)
tst.AssertArrayEqual(t, arr, []string{"a", "b", "c"})
}
func TestAsSorted(t *testing.T) {
src := []int{3, 1, 2}
out := AsSorted(src)
tst.AssertArrayEqual(t, out, []int{1, 2, 3})
// original unchanged
tst.AssertArrayEqual(t, src, []int{3, 1, 2})
}
func TestSortStable(t *testing.T) {
arr := []int{3, 1, 2, 1}
SortStable(arr)
tst.AssertArrayEqual(t, arr, []int{1, 1, 2, 3})
}
func TestAsSortedStable(t *testing.T) {
src := []int{3, 1, 2, 1}
out := AsSortedStable(src)
tst.AssertArrayEqual(t, out, []int{1, 1, 2, 3})
tst.AssertArrayEqual(t, src, []int{3, 1, 2, 1})
}
func TestIsSorted(t *testing.T) {
tst.AssertEqual(t, IsSorted([]int{1, 2, 3}), true)
tst.AssertEqual(t, IsSorted([]int{3, 2, 1}), false)
tst.AssertEqual(t, IsSorted([]int{1, 1, 1}), true)
tst.AssertEqual(t, IsSorted([]int{}), true)
}
func TestSortSlice(t *testing.T) {
arr := []int{3, 1, 2}
SortSlice(arr, func(a, b int) bool { return a < b })
tst.AssertArrayEqual(t, arr, []int{1, 2, 3})
}
func TestAsSortedSlice(t *testing.T) {
src := []int{3, 1, 2}
out := AsSortedSlice(src, func(a, b int) bool { return a > b })
tst.AssertArrayEqual(t, out, []int{3, 2, 1})
tst.AssertArrayEqual(t, src, []int{3, 1, 2})
}
func TestSortSliceStable(t *testing.T) {
arr := []int{3, 1, 2, 1}
SortSliceStable(arr, func(a, b int) bool { return a < b })
tst.AssertArrayEqual(t, arr, []int{1, 1, 2, 3})
}
func TestAsSortedSliceStable(t *testing.T) {
src := []int{3, 1, 2, 1}
out := AsSortedSliceStable(src, func(a, b int) bool { return a < b })
tst.AssertArrayEqual(t, out, []int{1, 1, 2, 3})
tst.AssertArrayEqual(t, src, []int{3, 1, 2, 1})
}
func TestIsSliceSorted(t *testing.T) {
tst.AssertEqual(t, IsSliceSorted([]int{1, 2, 3}, func(a, b int) bool { return a < b }), true)
tst.AssertEqual(t, IsSliceSorted([]int{3, 2, 1}, func(a, b int) bool { return a < b }), false)
}
type byKey struct {
key int
v string
}
func TestSortBy(t *testing.T) {
arr := []byKey{{3, "c"}, {1, "a"}, {2, "b"}}
SortBy(arr, func(v byKey) int { return v.key })
tst.AssertEqual(t, arr[0].v, "a")
tst.AssertEqual(t, arr[1].v, "b")
tst.AssertEqual(t, arr[2].v, "c")
}
func TestAsSortedBy(t *testing.T) {
src := []byKey{{3, "c"}, {1, "a"}, {2, "b"}}
out := AsSortedBy(src, func(v byKey) int { return v.key })
tst.AssertEqual(t, out[0].v, "a")
tst.AssertEqual(t, out[2].v, "c")
// source unchanged
tst.AssertEqual(t, src[0].v, "c")
}
func TestSortByStable(t *testing.T) {
arr := []byKey{{1, "a1"}, {1, "a2"}, {0, "b"}}
SortByStable(arr, func(v byKey) int { return v.key })
tst.AssertEqual(t, arr[0].v, "b")
// stable order for ties
tst.AssertEqual(t, arr[1].v, "a1")
tst.AssertEqual(t, arr[2].v, "a2")
}
func TestAsSortedByStable(t *testing.T) {
src := []byKey{{1, "a1"}, {1, "a2"}, {0, "b"}}
out := AsSortedByStable(src, func(v byKey) int { return v.key })
tst.AssertEqual(t, out[0].v, "b")
tst.AssertEqual(t, out[1].v, "a1")
tst.AssertEqual(t, out[2].v, "a2")
// source unchanged
tst.AssertEqual(t, src[0].v, "a1")
}
+132
View File
@@ -0,0 +1,132 @@
package langext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"regexp"
"strings"
"testing"
)
func TestNewUUIDLength(t *testing.T) {
u, err := NewUUID()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, len(u), 16)
}
func TestNewUUIDVersionAndVariant(t *testing.T) {
u, err := NewUUID()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Version 4 is in upper nibble of byte 6
tst.AssertEqual(t, u[6]&0xf0, byte(0x40))
// Variant 10 in top two bits of byte 8
tst.AssertEqual(t, u[8]&0xc0, byte(0x80))
}
func TestNewUUIDRandomness(t *testing.T) {
a, _ := NewUUID()
b, _ := NewUUID()
if a == b {
t.Errorf("two UUIDs should not be equal")
}
}
var hexUUIDRegex = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)
func TestNewHexUUIDFormat(t *testing.T) {
s, err := NewHexUUID()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, len(s), 36)
if !hexUUIDRegex.MatchString(s) {
t.Errorf("not a valid hex UUID format: %q", s)
}
}
func TestMustHexUUID(t *testing.T) {
s := MustHexUUID()
tst.AssertEqual(t, len(s), 36)
if !hexUUIDRegex.MatchString(s) {
t.Errorf("not a valid hex UUID format: %q", s)
}
}
var upperHexRegex = regexp.MustCompile(`^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$`)
func TestNewUpperHexUUIDFormat(t *testing.T) {
s, err := NewUpperHexUUID()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, len(s), 36)
tst.AssertEqual(t, s, strings.ToUpper(s))
if !upperHexRegex.MatchString(s) {
t.Errorf("not a valid upper-hex UUID format: %q", s)
}
}
func TestMustUpperHexUUID(t *testing.T) {
s := MustUpperHexUUID()
tst.AssertEqual(t, len(s), 36)
}
func TestNewRawHexUUIDFormat(t *testing.T) {
s, err := NewRawHexUUID()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, len(s), 32)
if strings.Contains(s, "-") {
t.Errorf("raw hex should have no dashes: %q", s)
}
tst.AssertEqual(t, s, strings.ToUpper(s))
}
func TestMustRawHexUUID(t *testing.T) {
s := MustRawHexUUID()
tst.AssertEqual(t, len(s), 32)
}
func TestNewBracesUUID(t *testing.T) {
s, err := NewBracesUUID()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, len(s), 38)
tst.AssertEqual(t, string(s[37]), "}")
}
func TestMustBracesUUID(t *testing.T) {
s := MustBracesUUID()
tst.AssertEqual(t, len(s), 38)
}
func TestNewParensUUID(t *testing.T) {
s, err := NewParensUUID()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tst.AssertEqual(t, len(s), 38)
tst.AssertEqual(t, string(s[37]), ")")
}
func TestMustParensUUID(t *testing.T) {
s := MustParensUUID()
tst.AssertEqual(t, len(s), 38)
}
func TestUUIDsAreUnique(t *testing.T) {
const count = 100
seen := make(map[string]bool, count)
for range count {
s := MustHexUUID()
if seen[s] {
t.Errorf("collision in UUID set: %q", s)
}
seen[s] = true
}
}