Files
realy/timestamp/timestamp_test.go

539 lines
13 KiB
Go

package timestamp
import (
"encoding/binary"
"encoding/json"
"math"
"testing"
"time"
)
func TestNew(t *testing.T) {
// Test with no arguments
ts := New[int]()
if ts == nil {
t.Fatal("New() returned nil")
}
if ts.V != 0 {
t.Errorf("New() with no args: expected V=0, got V=%d", ts.V)
}
// Test with one argument
ts = New(int64(1234567890))
if ts.V != 1234567890 {
t.Errorf("New(1234567890): expected V=1234567890, got V=%d", ts.V)
}
// Test with different integer types
ts = New(int32(123))
if ts.V != 123 {
t.Errorf("New(int32(123)): expected V=123, got V=%d", ts.V)
}
ts = New(uint64(456))
if ts.V != 456 {
t.Errorf("New(uint64(456)): expected V=456, got V=%d", ts.V)
}
// Test with multiple arguments (should only use first)
ts = New(100, 200, 300)
if ts.V != 100 {
t.Errorf("New(100, 200, 300): expected V=100, got V=%d", ts.V)
}
}
func TestNow(t *testing.T) {
before := time.Now().Unix()
ts := Now()
after := time.Now().Unix()
if ts == nil {
t.Fatal("Now() returned nil")
}
if ts.V < before || ts.V > after {
t.Errorf("Now(): timestamp %d not between %d and %d", ts.V, before, after)
}
}
func TestU64(t *testing.T) {
// Test normal case
ts := &T{V: 1234567890}
result := ts.U64()
if result != 1234567890 {
t.Errorf("U64(): expected 1234567890, got %d", result)
}
// Test negative value
ts = &T{V: -123}
result = ts.U64()
expected := uint64(ts.V) // This will wrap around
if result != expected {
t.Errorf("U64() with negative: expected %d, got %d", expected, result)
}
// Test nil receiver (now handled gracefully)
var nilTs *T
result = nilTs.U64()
if result != 0 {
t.Errorf("U64() on nil: expected 0, got %d", result)
}
}
func TestI64(t *testing.T) {
// Test normal case
ts := &T{V: 1234567890}
result := ts.I64()
if result != 1234567890 {
t.Errorf("I64(): expected 1234567890, got %d", result)
}
// Test negative value
ts = &T{V: -123}
result = ts.I64()
if result != -123 {
t.Errorf("I64() with negative: expected -123, got %d", result)
}
// Test nil receiver (now handled gracefully)
var nilTs *T
result = nilTs.I64()
if result != 0 {
t.Errorf("I64() on nil: expected 0, got %d", result)
}
}
func TestTime(t *testing.T) {
// Test normal case
ts := &T{V: 1234567890}
result := ts.Time()
expected := time.Unix(1234567890, 0)
if !result.Equal(expected) {
t.Errorf("Time(): expected %v, got %v", expected, result)
}
// Test zero
ts = &T{V: 0}
result = ts.Time()
expected = time.Unix(0, 0)
if !result.Equal(expected) {
t.Errorf("Time() with zero: expected %v, got %v", expected, result)
}
// Test nil receiver (now handled gracefully)
var nilTs *T
result = nilTs.Time()
expected = time.Unix(0, 0)
if !result.Equal(expected) {
t.Errorf("Time() on nil: expected %v, got %v", expected, result)
}
}
func TestInt(t *testing.T) {
// Test normal case
ts := &T{V: 123}
result := ts.Int()
if result != 123 {
t.Errorf("Int(): expected 123, got %d", result)
}
// Test large value that might overflow int
ts = &T{V: math.MaxInt64}
result = ts.Int()
if result != int(math.MaxInt64) {
t.Errorf("Int() with MaxInt64: expected %d, got %d", int(math.MaxInt64), result)
}
// Test nil receiver
var nilTs *T
result = nilTs.Int()
if result != 0 {
t.Errorf("Int() on nil: expected 0, got %d", result)
}
}
func TestBytes(t *testing.T) {
// Test normal case
ts := &T{V: 1234567890}
result := ts.Bytes()
if len(result) != 8 {
t.Errorf("Bytes(): expected length 8, got %d", len(result))
}
// Verify the bytes are correct
expected := make([]byte, 8)
binary.LittleEndian.PutUint64(expected, uint64(1234567890))
for i, b := range result {
if b != expected[i] {
t.Errorf("Bytes(): byte %d expected %d, got %d", i, expected[i], b)
}
}
// Test zero
ts = &T{V: 0}
result = ts.Bytes()
for i, b := range result {
if b != 0 {
t.Errorf("Bytes() with zero: byte %d expected 0, got %d", i, b)
}
}
// Test nil receiver (now handled gracefully)
var nilTs *T
result = nilTs.Bytes()
if len(result) != 8 {
t.Errorf("Bytes() on nil: expected length 8, got %d", len(result))
}
for i, b := range result {
if b != 0 {
t.Errorf("Bytes() on nil: byte %d expected 0, got %d", i, b)
}
}
}
func TestFromTime(t *testing.T) {
// Test normal case
tm := time.Unix(1234567890, 0)
ts := FromTime(tm)
if ts == nil {
t.Fatal("FromTime() returned nil")
}
if ts.V != 1234567890 {
t.Errorf("FromTime(): expected V=1234567890, got V=%d", ts.V)
}
// Test zero time
tm = time.Unix(0, 0)
ts = FromTime(tm)
if ts.V != 0 {
t.Errorf("FromTime() with zero: expected V=0, got V=%d", ts.V)
}
}
func TestFromUnix(t *testing.T) {
// Test normal case
ts := FromUnix(1234567890)
if ts == nil {
t.Fatal("FromUnix() returned nil")
}
if ts.V != 1234567890 {
t.Errorf("FromUnix(1234567890): expected V=1234567890, got V=%d", ts.V)
}
// Test negative
ts = FromUnix(-123)
if ts.V != -123 {
t.Errorf("FromUnix(-123): expected V=-123, got V=%d", ts.V)
}
// Test zero
ts = FromUnix(0)
if ts.V != 0 {
t.Errorf("FromUnix(0): expected V=0, got V=%d", ts.V)
}
}
func TestFromInt(t *testing.T) {
// Test normal case
ts := &T{}
ts.FromInt(123)
if ts.V != 123 {
t.Errorf("FromInt(123): expected V=123, got V=%d", ts.V)
}
// Test negative
ts.FromInt(-456)
if ts.V != -456 {
t.Errorf("FromInt(-456): expected V=-456, got V=%d", ts.V)
}
// Test zero
ts.FromInt(0)
if ts.V != 0 {
t.Errorf("FromInt(0): expected V=0, got V=%d", ts.V)
}
// Test nil receiver (should panic)
var nilTs *T
defer func() {
if r := recover(); r == nil {
t.Error("FromInt() on nil receiver should panic")
}
}()
nilTs.FromInt(123)
}
func TestFromBytes(t *testing.T) {
// Test normal case
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(1234567890))
ts := FromBytes(b)
if ts == nil {
t.Fatal("FromBytes() returned nil")
}
if ts.V != 1234567890 {
t.Errorf("FromBytes(): expected V=1234567890, got V=%d", ts.V)
}
// Test zero bytes
b = make([]byte, 8)
ts = FromBytes(b)
if ts.V != 0 {
t.Errorf("FromBytes() with zero bytes: expected V=0, got V=%d", ts.V)
}
// Test insufficient bytes (should panic or handle gracefully)
defer func() {
if r := recover(); r == nil {
t.Error("FromBytes() with insufficient bytes should panic or handle error")
}
}()
FromBytes([]byte{1, 2, 3}) // Only 3 bytes instead of 8
}
func TestFromVarint(t *testing.T) {
// Test normal case
b := make([]byte, 10)
n := binary.PutVarint(b, 1234567890)
ts, rem, err := FromVarint(b[:n])
if err != nil {
t.Errorf("FromVarint(): unexpected error: %v", err)
}
if ts == nil {
t.Fatal("FromVarint() returned nil timestamp")
}
if ts.V != 1234567890 {
t.Errorf("FromVarint(): expected V=1234567890, got V=%d", ts.V)
}
// The remainder should be the bytes after the varint
expectedRemLen := len(b[:n]) - n
if len(rem) != expectedRemLen {
t.Errorf("FromVarint(): expected rem length %d, got %d", expectedRemLen, len(rem))
}
// Test zero
b = make([]byte, 10)
n = binary.PutVarint(b, 0)
ts, rem, err = FromVarint(b[:n])
if err != nil {
t.Errorf("FromVarint() with zero: unexpected error: %v", err)
}
if ts.V != 0 {
t.Errorf("FromVarint() with zero: expected V=0, got V=%d", ts.V)
}
// Test negative
b = make([]byte, 10)
n = binary.PutVarint(b, -123)
ts, rem, err = FromVarint(b[:n])
if err != nil {
t.Errorf("FromVarint() with negative: unexpected error: %v", err)
}
if ts.V != -123 {
t.Errorf("FromVarint() with negative: expected V=-123, got V=%d", ts.V)
}
// Test invalid varint
_, _, err = FromVarint([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})
if err == nil {
t.Error("FromVarint() with invalid varint should return error")
}
// Test empty bytes
_, _, err = FromVarint([]byte{})
if err == nil {
t.Error("FromVarint() with empty bytes should return error")
}
}
func TestString(t *testing.T) {
// Test normal case
ts := &T{V: 123}
result := ts.String()
if result != "123" {
t.Errorf("String(): expected '123', got '%s'", result)
}
// Test zero
ts = &T{V: 0}
result = ts.String()
if result != "0" {
t.Errorf("String() with zero: expected '0', got '%s'", result)
}
// Test large number
ts = &T{V: 1234567890}
result = ts.String()
if result != "1234567890" {
t.Errorf("String() with large number: expected '1234567890', got '%s'", result)
}
// Test nil receiver (now handled gracefully)
var nilTs *T
result = nilTs.String()
if result != "0" {
t.Errorf("String() on nil: expected '0', got '%s'", result)
}
}
func TestMarshal(t *testing.T) {
// Test normal case
ts := &T{V: 123}
dst := make([]byte, 0, 10)
result := ts.Marshal(dst)
expected := "123"
if string(result) != expected {
t.Errorf("Marshal(): expected '%s', got '%s'", expected, string(result))
}
// Test with existing data in dst
dst = []byte("prefix")
result = ts.Marshal(dst)
expected = "prefix123"
if string(result) != expected {
t.Errorf("Marshal() with prefix: expected '%s', got '%s'", expected, string(result))
}
// Test nil receiver (now handled gracefully)
var nilTs *T
result = nilTs.Marshal(nil)
expected = "0"
if string(result) != expected {
t.Errorf("Marshal() on nil: expected '%s', got '%s'", expected, string(result))
}
}
func TestUnmarshal(t *testing.T) {
// Test normal case
ts := &T{}
input := []byte("123abc")
rem, err := ts.Unmarshal(input)
if err != nil {
t.Errorf("Unmarshal(): unexpected error: %v", err)
}
if ts.V != 123 {
t.Errorf("Unmarshal(): expected V=123, got V=%d", ts.V)
}
if string(rem) != "abc" {
t.Errorf("Unmarshal(): expected remainder 'abc', got '%s'", string(rem))
}
// Test with leading non-numeric characters
ts = &T{}
input = []byte("abc123def")
rem, err = ts.Unmarshal(input)
if err != nil {
t.Errorf("Unmarshal() with prefix: unexpected error: %v", err)
}
if ts.V != 123 {
t.Errorf("Unmarshal() with prefix: expected V=123, got V=%d", ts.V)
}
// Test zero
ts = &T{}
input = []byte("0")
rem, err = ts.Unmarshal(input)
if err != nil {
t.Errorf("Unmarshal() with zero: unexpected error: %v", err)
}
if ts.V != 0 {
t.Errorf("Unmarshal() with zero: expected V=0, got V=%d", ts.V)
}
// Test empty input
ts = &T{}
_, err = ts.Unmarshal([]byte{})
if err == nil {
t.Error("Unmarshal() with empty input should return error")
}
// Test nil receiver (now returns error)
var nilTs *T
_, err = nilTs.Unmarshal([]byte("123"))
if err == nil {
t.Error("Unmarshal() on nil receiver should return error")
}
}
func TestMarshalJSON(t *testing.T) {
// Test normal case
ts := &T{V: 123}
result, err := ts.MarshalJSON()
if err != nil {
t.Errorf("MarshalJSON(): unexpected error: %v", err)
}
if string(result) != "123" {
t.Errorf("MarshalJSON(): expected '123', got '%s'", string(result))
}
// Test zero
ts = &T{V: 0}
result, err = ts.MarshalJSON()
if err != nil {
t.Errorf("MarshalJSON() with zero: unexpected error: %v", err)
}
if string(result) != "0" {
t.Errorf("MarshalJSON() with zero: expected '0', got '%s'", string(result))
}
// Test integration with json package
ts = &T{V: 456}
jsonData, err := json.Marshal(ts)
if err != nil {
t.Errorf("json.Marshal(): unexpected error: %v", err)
}
// The result should be the custom MarshalJSON output since T implements json.Marshaler
expected := `456`
if string(jsonData) != expected {
t.Errorf("json.Marshal(): expected '%s', got '%s'", expected, string(jsonData))
}
// Test nil receiver (now handled gracefully)
var nilTs *T
result, err = nilTs.MarshalJSON()
if err != nil {
t.Errorf("MarshalJSON() on nil: unexpected error: %v", err)
}
if string(result) != "0" {
t.Errorf("MarshalJSON() on nil: expected '0', got '%s'", string(result))
}
}
func TestConstants(t *testing.T) {
// Test Len constant
if Len != 8 {
t.Errorf("Len constant: expected 8, got %d", Len)
}
}
// Test edge cases and integration
func TestIntegration(t *testing.T) {
// Test round-trip with Time
originalTime := time.Now()
ts := FromTime(originalTime)
convertedTime := ts.Time()
if convertedTime.Unix() != originalTime.Unix() {
t.Errorf("Time round-trip: expected %d, got %d", originalTime.Unix(), convertedTime.Unix())
}
// Test round-trip with Bytes
original := &T{V: 1234567890}
bytes := original.Bytes()
converted := FromBytes(bytes)
if converted.V != original.V {
t.Errorf("Bytes round-trip: expected %d, got %d", original.V, converted.V)
}
// Test round-trip with Marshal/Unmarshal
original = &T{V: 987654321}
marshaled := original.Marshal(nil)
converted = &T{}
_, err := converted.Unmarshal(marshaled)
if err != nil {
t.Errorf("Marshal/Unmarshal round-trip: unexpected error: %v", err)
}
if converted.V != original.V {
t.Errorf("Marshal/Unmarshal round-trip: expected %d, got %d", original.V, converted.V)
}
}