Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add comprehensive test coverage #183

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions marshal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
"encoding/json"
"testing"
)

func TestMarshalText(t *testing.T) {
u := UUID{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}
expected := "01234567-89ab-cdef-fedc-ba9876543210"

data, err := u.MarshalText()
if err != nil {
t.Fatalf("MarshalText failed: %v", err)
}

if string(data) != expected {
t.Errorf("MarshalText() = %s; want %s", data, expected)
}
}

func TestUnmarshalText(t *testing.T) {
var u UUID
input := []byte("01234567-89ab-cdef-fedc-ba9876543210")
expected := UUID{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}

err := u.UnmarshalText(input)
if err != nil {
t.Fatalf("UnmarshalText failed: %v", err)
}

if u != expected {
t.Errorf("UnmarshalText() = %v; want %v", u, expected)
}
}

func TestUnmarshalTextInvalidFormat(t *testing.T) {
var u UUID
input := []byte("invalid-uuid-format")

err := u.UnmarshalText(input)
if err == nil {
t.Fatalf("UnmarshalText should have failed for invalid format")
}
}

func TestMarshalBinary(t *testing.T) {
u := UUID{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}
expected := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}

data, err := u.MarshalBinary()
if err != nil {
t.Fatalf("MarshalBinary failed: %v", err)
}

if string(data) != string(expected) {
t.Errorf("MarshalBinary() = %v; want %v", data, expected)
}
}

func TestUnmarshalBinary(t *testing.T) {
var u UUID
input := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}
expected := UUID{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}

err := u.UnmarshalBinary(input)
if err != nil {
t.Fatalf("UnmarshalBinary failed: %v", err)
}

if u != expected {
t.Errorf("UnmarshalBinary() = %v; want %v", u, expected)
}
}

func TestUnmarshalBinaryInvalidLength(t *testing.T) {
var u UUID
input := []byte{0x01, 0x23, 0x45} // Invalid length

err := u.UnmarshalBinary(input)
if err == nil {
t.Fatalf("UnmarshalBinary should have failed for invalid length")
}
}

func TestJSONSerialization(t *testing.T) {
u := UUID{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}
expected := `"01234567-89ab-cdef-fedc-ba9876543210"`

jsonData, err := json.Marshal(u)
if err != nil {
t.Fatalf("JSON serialization failed: %v", err)
}

if string(jsonData) != expected {
t.Errorf("JSON serialization = %s; want %s", jsonData, expected)
}
}

func TestJSONDeserialization(t *testing.T) {
var u UUID
input := `"01234567-89ab-cdef-fedc-ba9876543210"`
expected := UUID{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}

err := json.Unmarshal([]byte(input), &u)
if err != nil {
t.Fatalf("JSON deserialization failed: %v", err)
}

if u != expected {
t.Errorf("JSON deserialization = %v; want %v", u, expected)
}
}
98 changes: 78 additions & 20 deletions null_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,33 +103,47 @@ func TestNullUUIDMarshalText(t *testing.T) {

func TestNullUUIDUnmarshalText(t *testing.T) {
tests := []struct {
nullUUID NullUUID
name string
data []byte
expected NullUUID
expectedErr bool
}{
{
nullUUID: NullUUID{},
name: "null text",
data: []byte("null"),
expected: NullUUID{Valid: false},
expectedErr: true, // "null" is not a valid UUID format
},
{
nullUUID: NullUUID{
UUID: MustParse("12345678-abcd-1234-abcd-0123456789ab"),
Valid: true,
},
name: "valid UUID",
data: []byte("12345678-abcd-1234-abcd-0123456789ab"),
expected: NullUUID{UUID: MustParse("12345678-abcd-1234-abcd-0123456789ab"), Valid: true},
expectedErr: false,
},
{
name: "invalid text",
data: []byte("invalid"),
expected: NullUUID{Valid: false},
expectedErr: true,
},
}

for _, test := range tests {
var uText []byte
var uErr error
nuText, nuErr := test.nullUUID.MarshalText()
if test.nullUUID.Valid {
uText, uErr = test.nullUUID.UUID.MarshalText()
} else {
uText = []byte("null")
}
if nuErr != uErr {
t.Errorf("expected error %e, got %e", nuErr, uErr)
}
if !bytes.Equal(nuText, uText) {
t.Errorf("expected text data %s, got %s", string(nuText), string(uText))
}
t.Run(test.name, func(t *testing.T) {
var nu NullUUID
err := nu.UnmarshalText(test.data)
if (err != nil) != test.expectedErr {
t.Errorf("expected error %v, got %v", test.expectedErr, err)
}
if !test.expectedErr {
if nu.Valid != test.expected.Valid {
t.Errorf("expected Valid %v, got %v", test.expected.Valid, nu.Valid)
}
if nu.Valid && nu.UUID != test.expected.UUID {
t.Errorf("expected UUID %v, got %v", test.expected.UUID, nu.UUID)
}
}
})
}
}

Expand Down Expand Up @@ -165,6 +179,50 @@ func TestNullUUIDMarshalBinary(t *testing.T) {
}
}

func TestNullUUIDUnmarshalBinary(t *testing.T) {
validUUID := MustParse("12345678-abcd-1234-abcd-0123456789ab")
validData := validUUID[:]
invalidData := []byte{1, 2, 3}

tests := []struct {
name string
data []byte
expected NullUUID
expectedErr bool
}{
{
name: "valid data",
data: validData,
expected: NullUUID{UUID: validUUID, Valid: true},
expectedErr: false,
},
{
name: "invalid length",
data: invalidData,
expected: NullUUID{},
expectedErr: true,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var nu NullUUID
err := nu.UnmarshalBinary(test.data)
if (err != nil) != test.expectedErr {
t.Errorf("expected error %v, got %v", test.expectedErr, err)
}
if !test.expectedErr {
if nu.Valid != test.expected.Valid {
t.Errorf("expected Valid %v, got %v", test.expected.Valid, nu.Valid)
}
if nu.Valid && nu.UUID != test.expected.UUID {
t.Errorf("expected UUID %v, got %v", test.expected.UUID, nu.UUID)
}
}
})
}
}

func TestNullUUIDMarshalJSON(t *testing.T) {
jsonNull, _ := json.Marshal(nil)
jsonUUID, _ := json.Marshal(MustParse("12345678-abcd-1234-abcd-0123456789ab"))
Expand Down
74 changes: 74 additions & 0 deletions time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,77 @@ func TestGetTime(t *testing.T) {
})
}
}

func TestClockSequenceInitialization(t *testing.T) {
// Backup and reset global state
timeMu.Lock()
origSeq := clockSeq
clockSeq = 0 // Force initialization
timeMu.Unlock()
defer func() {
timeMu.Lock()
clockSeq = origSeq
timeMu.Unlock()
}()

// First call initializes the sequence
seq := ClockSequence()
if seq == 0 {
t.Error("ClockSequence() should not return 0 after initialization")
}

// Ensure the sequence is within 14-bit mask
if seq&0xc000 != 0 {
t.Errorf("ClockSequence() = %x, expected 14-bit value (mask 0x3fff)", seq)
}

// Subsequent call should return the same sequence
seq2 := ClockSequence()
if seq2 != seq {
t.Errorf("Expected sequence %x, got %x", seq, seq2)
}
}

func TestTime(t *testing.T) {
tests := []struct {
name string
uuid UUID
version int
want Time
}{
{
name: "Version 6",
uuid: UUID{0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0x6D, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
version: 6,
want: Time((0x12345678 << 28) | (0x9ABC << 12) | 0xDEF),
},
{
name: "Version 7",
uuid: UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
version: 7,
want: Time(g1582ns100),
},
{
name: "Default Version",
uuid: UUID{0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0x1D, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
version: 1,
want: Time(int64(0x12345678) | (int64(0x9ABC) << 32) | (int64(0xDEF) << 48)),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.uuid.Time(); got != tt.want {
t.Errorf("UUID.Time() = %v, want %v", got, tt.want)
}
})
}
}

func TestClockSequence(t *testing.T) {
uuid := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
expected := 0x1234 & 0x3fff
if got := uuid.ClockSequence(); got != expected {
t.Errorf("ClockSequence() = %x, want %x", got, expected)
}
}
57 changes: 57 additions & 0 deletions util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
"bytes"
"errors"
"testing"
)

// mockReader is a mock implementation of io.Reader for testing
type mockReader struct {
data []byte // Data to be read
err error // Error to return during read
}

func (m *mockReader) Read(p []byte) (n int, err error) {
if m.err != nil {
return 0, m.err
}
n = copy(p, m.data)
return n, nil
}

// TestRandomBits tests the randomBits function
func TestRandomBits(t *testing.T) {
originalRander := rander
defer func() { rander = originalRander }()

t.Run("fills slice with random data", func(t *testing.T) {
mockData := []byte{0x01, 0x02, 0x03, 0x04}
rander = &mockReader{data: mockData}

b := make([]byte, len(mockData))
randomBits(b)

if !bytes.Equal(b, mockData) {
t.Errorf("expected %v, got %v", mockData, b)
}
})

t.Run("panics on read error", func(t *testing.T) {
rander = &mockReader{err: errors.New("read error")}

defer func() {
if r := recover(); r == nil {
t.Error("expected panic, but did not occur")
} else if errMsg, ok := r.(string); !ok || errMsg != "read error" {
t.Errorf("expected panic with message 'read error', got %v", r)
}
}()

randomBits(make([]byte, 4))
})
}