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) } }