Skip to content

Commit

Permalink
test: cover 100% internal package
Browse files Browse the repository at this point in the history
  • Loading branch information
ggicci committed Dec 27, 2023
1 parent 970dbdc commit dc11ac4
Showing 1 changed file with 157 additions and 16 deletions.
173 changes: 157 additions & 16 deletions internal/stringable_test.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
package internal

import (
"fmt"
"reflect"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestString(t *testing.T) {
var s string
sv := (*String)(&s)
sv.FromString("Alice")
assert.Equal(t, "Alice", s)
}

func TestInt(t *testing.T) {
var i int
iv := (*Int)(&i)
iv.FromString("18")
assert.Equal(t, 18, i)
}

func TestNewStringable_string(t *testing.T) {
var s string = "hello"
rvString := reflect.ValueOf(s)
Expand All @@ -39,6 +26,81 @@ func TestNewStringable_string(t *testing.T) {
assert.Equal(t, "world", s)
}

func TestNewStringable_bool(t *testing.T) {
var b bool = true
rvBool := reflect.ValueOf(b)
assert.Panics(t, func() {
NewStringable(rvBool)
})

rvBoolPointer := reflect.ValueOf(&b)
sv, err := NewStringable(rvBoolPointer)
assert.NoError(t, err)
got, err := sv.ToString()
assert.NoError(t, err)
assert.Equal(t, "true", got)
sv.FromString("false")
assert.Equal(t, false, b)

assert.Error(t, sv.FromString("hello"))
}

func TestNewStringable_int(t *testing.T) {
testInteger[int](t, 2045, "hello")
}

func TestNewStringable_int8(t *testing.T) {
testInteger[int8](t, int8(127), "128")
}

func TestNewStringable_int16(t *testing.T) {
testInteger[int16](t, int16(32767), "32768")
}

func TestNewStringable_int32(t *testing.T) {
testInteger[int32](t, int32(2147483647), "2147483648")
}

func TestNewStringable_int64(t *testing.T) {
testInteger[int64](t, int64(9223372036854775807), "9223372036854775808")
}

func TestNewStringable_uint(t *testing.T) {
testInteger[uint](t, uint(2045), "-1")
}

func TestNewStringable_uint8(t *testing.T) {
testInteger[uint8](t, uint8(255), "256")
}

func TestNewStringable_uint16(t *testing.T) {
testInteger[uint16](t, uint16(65535), "65536")
}

func TestNewStringable_uint32(t *testing.T) {
testInteger[uint32](t, uint32(4294967295), "4294967296")
}

func TestNewStringable_uint64(t *testing.T) {
testInteger[uint64](t, uint64(18446744073709551615), "18446744073709551616")
}

func TestNewStringable_float32(t *testing.T) {
testInteger[float32](t, float32(3.1415926), "hello")
}

func TestNewStringable_float64(t *testing.T) {
testInteger[float64](t, float64(3.14159265358979323846264338327950288419716939937510582097494459), "hello")
}

func TestNewStringable_complex64(t *testing.T) {
testInteger[complex64](t, complex64(3.1415926+2.71828i), "hello")
}

func TestNewStringable_complex128(t *testing.T) {
testInteger[complex128](t, complex128(3.14159265358979323846264338327950288419716939937510582097494459+2.71828182845904523536028747135266249775724709369995957496696763i), "hello")
}

func TestNewStringable_Time(t *testing.T) {
var now = time.Now()
rvTime := reflect.ValueOf(now)
Expand All @@ -49,6 +111,85 @@ func TestNewStringable_Time(t *testing.T) {
rvTimePointer := reflect.ValueOf(&now)
sv, err := NewStringable(rvTimePointer)
assert.NoError(t, err)
assert.NoError(t, sv.FromString("1991-11-10T08:00:00+08:00"))
assert.Equal(t, "1991-11-10T00:00:00Z", now.Format(time.RFC3339))

// RFC3339Nano
testTime(t, sv, "1991-11-10T08:00:00+08:00", time.Date(1991, 11, 10, 8, 0, 0, 0, time.FixedZone("Asia/Shanghai", +8*3600)), "1991-11-10T00:00:00Z")
// Date string
testTime(t, sv, "1991-11-10", time.Date(1991, 11, 10, 0, 0, 0, 0, time.UTC), "1991-11-10T00:00:00Z")

// Unix timestamp
testTime(t, sv, "678088800", time.Date(1991, 6, 28, 6, 0, 0, 0, time.UTC), "1991-06-28T06:00:00Z")

// Unix timestamp fraction
testTime(t, sv, "678088800.123456789", time.Date(1991, 6, 28, 6, 0, 0, 123456789, time.UTC), "1991-06-28T06:00:00.123456789Z")

// Unsupported format
assert.Error(t, sv.FromString("hello"))
}

func TestNewStringable_ByteSlice(t *testing.T) {
var b []byte = []byte("hello")
rvByteSlice := reflect.ValueOf(b)
assert.NotPanics(t, func() {
NewStringable(rvByteSlice)
})

rvByteSlicePointer := reflect.ValueOf(&b)
sv, err := NewStringable(rvByteSlicePointer)
assert.NoError(t, err)
got, err := sv.ToString()
assert.NoError(t, err)
assert.Equal(t, "aGVsbG8=", got)

sv.FromString("d29ybGQ=")
assert.Equal(t, []byte("world"), b)

assert.Error(t, sv.FromString("hello"))
}

func TestNewStringable_ErrUnsupportedType(t *testing.T) {
type MyStruct struct{ Name string }
var s MyStruct
rvStruct := reflect.ValueOf(s)
assert.Panics(t, func() {
NewStringable(rvStruct)
})
rvStructPointer := reflect.ValueOf(&s)
sv, err := NewStringable(rvStructPointer)
assert.ErrorIs(t, err, ErrUnsupportedType)
assert.Nil(t, sv)
}

type Numeric interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 | complex64 | complex128
}

func testInteger[T Numeric](t *testing.T, vSuccess T, invalidStr string) {
rv := reflect.ValueOf(vSuccess)
assert.Panics(t, func() {
NewStringable(rv)
})

rvPointer := reflect.ValueOf(&vSuccess)
sv, err := NewStringable(rvPointer)
assert.NoError(t, err)
got, err := sv.ToString()
assert.NoError(t, err)
assert.Equal(t, fmt.Sprintf("%v", vSuccess), got)
sv.FromString("2")
assert.Equal(t, T(2), vSuccess)

assert.Error(t, sv.FromString(invalidStr))
}

func testTime(t *testing.T, sv Stringable, fromStr string, expected time.Time, expectedToStr string) {
assert.NoError(t, sv.FromString(fromStr))
assert.True(t, equalTime(expected, time.Time(*sv.(*Time))))
ts, err := sv.ToString()
assert.NoError(t, err)
assert.Equal(t, expectedToStr, ts)
}

func equalTime(expected, actual time.Time) bool {
return expected.UTC() == actual.UTC()
}

0 comments on commit dc11ac4

Please sign in to comment.