From 446522c6cc0e803e648ea545c501d0c5be4be931 Mon Sep 17 00:00:00 2001 From: Ashwin Gopalsamy <47941624+ashwingopalsamy@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:17:12 +0530 Subject: [PATCH 1/4] Update helper.go --- helper.go | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/helper.go b/helper.go index 169c53a..5e1e830 100644 --- a/helper.go +++ b/helper.go @@ -4,7 +4,6 @@ import ( "encoding/hex" "errors" "fmt" - "strings" ) // Helper function to encode timestamp into the UUID byte array. @@ -31,12 +30,30 @@ func decodeTimestamp(uuidBytes []byte) uint64 { // Helper function to parse and sanitize a UUID string. func parseUUID(uuid string) ([]byte, error) { - uuid = strings.ReplaceAll(uuid, "-", "") - if len(uuid) != 32 { + if len(uuid) == 32 { + // Fast path for UUIDs without dashes + return hex.DecodeString(uuid) + } else if len(uuid) == 36 { + // Validate dash positions + if uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-' { + return nil, errors.New("invalid UUID format") + } + } else { return nil, errors.New("invalid UUID length") } - return hex.DecodeString(uuid) + // Remove dashes while copying characters + result := make([]byte, 32) + j := 0 + for i := 0; i < len(uuid); i++ { + if uuid[i] == '-' { + continue + } + result[j] = uuid[i] + j++ + } + + return hex.DecodeString(string(result)) } // Helper function to check if a UUID is all zeros. From 402341080782048346dd8ab93e63534f02340e23 Mon Sep 17 00:00:00 2001 From: Ashwin Gopalsamy <47941624+ashwingopalsamy@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:32:06 +0530 Subject: [PATCH 2/4] tests: added unit tests for updated `parseUUID` --- uuidv8_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/uuidv8_test.go b/uuidv8_test.go index c224751..6a1c1ad 100644 --- a/uuidv8_test.go +++ b/uuidv8_test.go @@ -561,3 +561,56 @@ func TestNewWithParams_MaxValues(t *testing.T) { t.Errorf("Generated UUID with max values is invalid: %s", uuid) } } + +func TestFromString_InvalidInputs(t *testing.T) { + tests := []string{ + "123", // Too short + "123e4567e89b12d3a4564266141740000000", // Too long + "123e4567e89b12d3a45642661417400g", // Invalid character + "123e-4567-e89b-12d3-a456-426614174000", // Misplaced dashes + } + + for _, input := range tests { + t.Run("Invalid UUID "+input, func(t *testing.T) { + _, err := uuidv8.FromString(input) + if err == nil { + t.Errorf("Expected error, got nil for input: %s", input) + } + }) + } +} + +func TestFromStringOrNil_InvalidInputs(t *testing.T) { + tests := []string{ + "123", // Too short + "123e4567e89b12d3a4564266141740000000", // Too long + "123e4567e89b12d3a45642661417400g", // Invalid character + "", // Empty string + } + + for _, input := range tests { + t.Run("Invalid UUID "+input, func(t *testing.T) { + result := uuidv8.FromStringOrNil(input) + if result != nil { + t.Errorf("Expected nil for input: %s, got %v", input, result) + } + }) + } +} + +func TestIsValidUUIDv8_InvalidUUIDs(t *testing.T) { + invalidUUIDs := []string{ + "123", // Too short + "123e4567e89b12d3a4564266141740000000", // Too long + "123e4567e89b12d3a45642661417400g", // Invalid character + "", // Empty string + } + + for _, uuid := range invalidUUIDs { + t.Run("Invalid UUID "+uuid, func(t *testing.T) { + if uuidv8.IsValidUUIDv8(uuid) { + t.Errorf("Expected UUID %s to be invalid", uuid) + } + }) + } +} From 7b52e058482be6ebcd46ea4b5e1ecea793430d5c Mon Sep 17 00:00:00 2001 From: Ashwin Gopalsamy <47941624+ashwingopalsamy@users.noreply.github.com> Date: Thu, 26 Dec 2024 11:39:25 +0530 Subject: [PATCH 3/4] tests: add more testcases for invalid uuid inputs --- uuidv8_test.go | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/uuidv8_test.go b/uuidv8_test.go index 076feb8..e9ef3e3 100644 --- a/uuidv8_test.go +++ b/uuidv8_test.go @@ -723,17 +723,29 @@ func TestUUIDv8_Scan_EdgeCases(t *testing.T) { func TestFromString_InvalidInputs(t *testing.T) { tests := []string{ - "123", // Too short - "123e4567e89b12d3a4564266141740000000", // Too long - "123e4567e89b12d3a45642661417400g", // Invalid character - "123e-4567-e89b-12d3-a456-426614174000", // Misplaced dashes + "123", // Too short + "123e4567e89b12d3a4564266141740000000", // Too long + "123e4567e89b12d3a45642661417400g", // Invalid character + "123e-4567-e89b-12d3-a456-426614174000", // Misplaced dashes + "123e4567-e89b-12d3-a456-426614174000-", // Extra dash at the end + "--123e4567-e89b-12d3-a456-426614174000", // Extra dash at the start + "123e4567-e89b-12d3-a456-42-6614174000", // Randomly placed dash + "------------------------------------", // 36 dashes + "9a3d4049-0e2c-8080-0102-030405060000", // Valid UUID with dashes } for _, input := range tests { - t.Run("Invalid UUID "+input, func(t *testing.T) { + t.Run("Testing UUID: "+input, func(t *testing.T) { _, err := uuidv8.FromString(input) - if err == nil { - t.Errorf("Expected error, got nil for input: %s", input) + // The last case is valid; others should fail + if input == "9a3d4049-0e2c-8080-0102-030405060000" { + if err != nil { + t.Errorf("Expected valid UUID but got error for input: %s", input) + } + } else { + if err == nil { + t.Errorf("Expected error, got nil for input: %s", input) + } } }) } @@ -741,10 +753,13 @@ func TestFromString_InvalidInputs(t *testing.T) { func TestFromStringOrNil_InvalidInputs(t *testing.T) { tests := []string{ - "123", // Too short - "123e4567e89b12d3a4564266141740000000", // Too long - "123e4567e89b12d3a45642661417400g", // Invalid character - "", // Empty string + "123", // Too short + "123e4567e89b12d3a4564266141740000000", // Too long + "123e4567e89b12d3a45642661417400g", // Invalid character + "", // Empty string + "123e4567-e89b-12d3-a456-426614174000-", // Extra dash at the end + "--123e4567-e89b-12d3-a456-426614174000", // Extra dash at the start + "123e4567-e89b-12d3-a456-42-6614174000", // Randomly placed dash } for _, input := range tests { @@ -759,10 +774,14 @@ func TestFromStringOrNil_InvalidInputs(t *testing.T) { func TestIsValidUUIDv8_InvalidUUIDs(t *testing.T) { invalidUUIDs := []string{ - "123", // Too short - "123e4567e89b12d3a4564266141740000000", // Too long - "123e4567e89b12d3a45642661417400g", // Invalid character - "", // Empty string + "123", // Too short + "123e4567e89b12d3a4564266141740000000", // Too long + "123e4567e89b12d3a45642661417400g", // Invalid character + "", // Empty string + "123e4567-e89b-12d3-a456-426614174000-", // Extra dash at the end + "--123e4567-e89b-12d3-a456-426614174000", // Extra dash at the start + "123e4567-e89b-12d3-a456-42-6614174000", // Randomly placed dash + } for _, uuid := range invalidUUIDs { From 4c42601a4798cd860b22a3fd64c76b7bbce3f08d Mon Sep 17 00:00:00 2001 From: Ashwin Gopalsamy <47941624+ashwingopalsamy@users.noreply.github.com> Date: Thu, 26 Dec 2024 11:54:31 +0530 Subject: [PATCH 4/4] enhance: `parseUUID()` logic handling --- helper.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/helper.go b/helper.go index 5e1e830..70e9952 100644 --- a/helper.go +++ b/helper.go @@ -28,32 +28,32 @@ func decodeTimestamp(uuidBytes []byte) uint64 { uint64(uuidBytes[3])<<16 | uint64(uuidBytes[4])<<8 | uint64(uuidBytes[5]) } +// Helper function to parse and sanitize a UUID string. // Helper function to parse and sanitize a UUID string. func parseUUID(uuid string) ([]byte, error) { - if len(uuid) == 32 { + switch len(uuid) { + case 32: // Fast path for UUIDs without dashes return hex.DecodeString(uuid) - } else if len(uuid) == 36 { + case 36: // Validate dash positions if uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-' { return nil, errors.New("invalid UUID format") } - } else { - return nil, errors.New("invalid UUID length") - } - // Remove dashes while copying characters - result := make([]byte, 32) - j := 0 - for i := 0; i < len(uuid); i++ { - if uuid[i] == '-' { - continue + // Remove dashes while copying characters + result := make([]byte, 32) + j := 0 + for i := 0; i < len(uuid); i++ { + if uuid[i] != '-' { + result[j] = uuid[i] + j++ + } } - result[j] = uuid[i] - j++ + return hex.DecodeString(string(result)) + default: + return nil, errors.New("invalid UUID length") } - - return hex.DecodeString(string(result)) } // Helper function to check if a UUID is all zeros.