135 lines
3.2 KiB
Go
135 lines
3.2 KiB
Go
package legacysql
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDBTime_ValueAndString_ZeroAndNonZero(t *testing.T) {
|
|
zero := NewDBTime(time.Time{})
|
|
if v, err := zero.Value(); err != nil {
|
|
t.Fatalf("unexpected error for zero Value: %v", err)
|
|
} else if v != nil {
|
|
t.Fatalf("expected nil driver.Value for zero time, got %#v", v)
|
|
}
|
|
if s := zero.String(); s != "" {
|
|
t.Fatalf("expected empty string for zero DBTime.String(), got %q", s)
|
|
}
|
|
|
|
tt := time.Date(2023, 10, 5, 13, 14, 15, 0, time.UTC)
|
|
dt := NewDBTime(tt)
|
|
|
|
val, err := dt.Value()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error for non-zero Value: %v", err)
|
|
}
|
|
strVal, ok := val.(string)
|
|
if !ok {
|
|
t.Fatalf("expected Value to be string, got %T", val)
|
|
}
|
|
expected := tt.Format(time.DateTime)
|
|
if strVal != expected {
|
|
t.Fatalf("Value() = %q, want %q", strVal, expected)
|
|
}
|
|
|
|
if s := dt.String(); s != expected {
|
|
t.Fatalf("String() = %q, want %q", s, expected)
|
|
}
|
|
}
|
|
|
|
func TestDBTime_Scan_VariousInputs(t *testing.T) {
|
|
base := time.Date(2022, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
layout := time.DateTime
|
|
formatted := base.Format(layout)
|
|
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
wantTime time.Time
|
|
wantIsZero bool
|
|
expectError bool
|
|
}{
|
|
{"nil sets zero", nil, time.Time{}, true, false},
|
|
{"scan from string", formatted, base, false, false},
|
|
{"scan from []byte", []byte(formatted), base, false, false},
|
|
{"scan from time.Time", base, base, false, false},
|
|
{"invalid parse", "not-a-time", time.Time{}, true, true},
|
|
{"unsupported type", 12345, time.Time{}, true, true},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
var dt DBTime
|
|
err := dt.Scan(tc.input)
|
|
if tc.expectError {
|
|
if err == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
// when expecting error, no further checks
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if tc.wantIsZero {
|
|
if !dt.IsZero() {
|
|
t.Fatalf("expected DBTime to be zero, got %v", dt.Time)
|
|
}
|
|
return
|
|
}
|
|
if dt.IsZero() {
|
|
t.Fatalf("expected non-zero time, got zero")
|
|
}
|
|
// Compare times using Equal to ignore monotonic clock bits
|
|
if !dt.Equal(tc.wantTime) {
|
|
t.Fatalf("scanned time = %v, want %v", dt.Time, tc.wantTime)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDBTime_Scan_ParseErrorDetails(t *testing.T) {
|
|
var dt DBTime
|
|
err := dt.Scan("garbage")
|
|
if err == nil {
|
|
t.Fatalf("expected parse error, got nil")
|
|
}
|
|
// error message should mention parse
|
|
if !contains(err.Error(), "could not parse time") {
|
|
t.Fatalf("unexpected error message: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDBTime_Scan_UnsupportedTypeMessage(t *testing.T) {
|
|
var dt DBTime
|
|
typ := struct{}{}
|
|
err := dt.Scan(typ)
|
|
if err == nil {
|
|
t.Fatalf("expected unsupported-type error, got nil")
|
|
}
|
|
want := fmt.Sprintf("could not scan type %T into DBTime", typ)
|
|
if err.Error() != want {
|
|
t.Fatalf("error = %q, want %q", err.Error(), want)
|
|
}
|
|
}
|
|
|
|
// small helper to avoid importing strings for a single contains check
|
|
func contains(s, substr string) bool {
|
|
return len(substr) == 0 || (len(s) >= len(substr) && indexOf(s, substr) >= 0)
|
|
}
|
|
|
|
func indexOf(s, substr string) int {
|
|
n := len(s)
|
|
m := len(substr)
|
|
if m == 0 {
|
|
return 0
|
|
}
|
|
for i := 0; i <= n-m; i++ {
|
|
if s[i:i+m] == substr {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|