metadata_userid_test.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //go:build unit
  2. package service
  3. import (
  4. "testing"
  5. "github.com/stretchr/testify/require"
  6. )
  7. // ============ ParseMetadataUserID Tests ============
  8. func TestParseMetadataUserID_LegacyFormat_WithoutAccountUUID(t *testing.T) {
  9. raw := "user_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2_account__session_123e4567-e89b-12d3-a456-426614174000"
  10. parsed := ParseMetadataUserID(raw)
  11. require.NotNil(t, parsed)
  12. require.Equal(t, "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2", parsed.DeviceID)
  13. require.Equal(t, "", parsed.AccountUUID)
  14. require.Equal(t, "123e4567-e89b-12d3-a456-426614174000", parsed.SessionID)
  15. require.False(t, parsed.IsNewFormat)
  16. }
  17. func TestParseMetadataUserID_LegacyFormat_WithAccountUUID(t *testing.T) {
  18. raw := "user_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2_account_550e8400-e29b-41d4-a716-446655440000_session_123e4567-e89b-12d3-a456-426614174000"
  19. parsed := ParseMetadataUserID(raw)
  20. require.NotNil(t, parsed)
  21. require.Equal(t, "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2", parsed.DeviceID)
  22. require.Equal(t, "550e8400-e29b-41d4-a716-446655440000", parsed.AccountUUID)
  23. require.Equal(t, "123e4567-e89b-12d3-a456-426614174000", parsed.SessionID)
  24. require.False(t, parsed.IsNewFormat)
  25. }
  26. func TestParseMetadataUserID_JSONFormat_WithoutAccountUUID(t *testing.T) {
  27. raw := `{"device_id":"d61f76d0aabbccdd00112233445566778899aabbccddeeff0011223344556677","account_uuid":"","session_id":"c72554f2-1234-5678-abcd-123456789abc"}`
  28. parsed := ParseMetadataUserID(raw)
  29. require.NotNil(t, parsed)
  30. require.Equal(t, "d61f76d0aabbccdd00112233445566778899aabbccddeeff0011223344556677", parsed.DeviceID)
  31. require.Equal(t, "", parsed.AccountUUID)
  32. require.Equal(t, "c72554f2-1234-5678-abcd-123456789abc", parsed.SessionID)
  33. require.True(t, parsed.IsNewFormat)
  34. }
  35. func TestParseMetadataUserID_JSONFormat_WithAccountUUID(t *testing.T) {
  36. raw := `{"device_id":"d61f76d0aabbccdd00112233445566778899aabbccddeeff0011223344556677","account_uuid":"550e8400-e29b-41d4-a716-446655440000","session_id":"c72554f2-1234-5678-abcd-123456789abc"}`
  37. parsed := ParseMetadataUserID(raw)
  38. require.NotNil(t, parsed)
  39. require.Equal(t, "d61f76d0aabbccdd00112233445566778899aabbccddeeff0011223344556677", parsed.DeviceID)
  40. require.Equal(t, "550e8400-e29b-41d4-a716-446655440000", parsed.AccountUUID)
  41. require.Equal(t, "c72554f2-1234-5678-abcd-123456789abc", parsed.SessionID)
  42. require.True(t, parsed.IsNewFormat)
  43. }
  44. func TestParseMetadataUserID_InvalidInputs(t *testing.T) {
  45. tests := []struct {
  46. name string
  47. raw string
  48. }{
  49. {"empty string", ""},
  50. {"whitespace only", " "},
  51. {"random text", "not-a-valid-user-id"},
  52. {"partial legacy format", "session_123e4567-e89b-12d3-a456-426614174000"},
  53. {"invalid JSON", `{"device_id":}`},
  54. {"JSON missing device_id", `{"account_uuid":"","session_id":"c72554f2-1234-5678-abcd-123456789abc"}`},
  55. {"JSON missing session_id", `{"device_id":"d61f76d0aabbccdd00112233445566778899aabbccddeeff0011223344556677","account_uuid":""}`},
  56. {"JSON empty device_id", `{"device_id":"","account_uuid":"","session_id":"c72554f2-1234-5678-abcd-123456789abc"}`},
  57. {"JSON empty session_id", `{"device_id":"d61f76d0aabbccdd00112233445566778899aabbccddeeff0011223344556677","account_uuid":"","session_id":""}`},
  58. {"legacy format short hex", "user_a1b2c3d4_account__session_123e4567-e89b-12d3-a456-426614174000"},
  59. }
  60. for _, tt := range tests {
  61. t.Run(tt.name, func(t *testing.T) {
  62. require.Nil(t, ParseMetadataUserID(tt.raw), "should return nil for: %s", tt.raw)
  63. })
  64. }
  65. }
  66. func TestParseMetadataUserID_HexCaseInsensitive(t *testing.T) {
  67. // Legacy format should accept both upper and lower case hex
  68. rawUpper := "user_A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2_account__session_123e4567-e89b-12d3-a456-426614174000"
  69. parsed := ParseMetadataUserID(rawUpper)
  70. require.NotNil(t, parsed, "legacy format should accept uppercase hex")
  71. require.Equal(t, "A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2", parsed.DeviceID)
  72. }
  73. // ============ FormatMetadataUserID Tests ============
  74. func TestFormatMetadataUserID_LegacyVersion(t *testing.T) {
  75. result := FormatMetadataUserID("deadbeef"+"00112233445566778899aabbccddeeff0011223344556677", "acc-uuid", "sess-uuid", "2.1.77")
  76. require.Equal(t, "user_deadbeef00112233445566778899aabbccddeeff0011223344556677_account_acc-uuid_session_sess-uuid", result)
  77. }
  78. func TestFormatMetadataUserID_NewVersion(t *testing.T) {
  79. result := FormatMetadataUserID("deadbeef"+"00112233445566778899aabbccddeeff0011223344556677", "acc-uuid", "sess-uuid", "2.1.78")
  80. require.Equal(t, `{"device_id":"deadbeef00112233445566778899aabbccddeeff0011223344556677","account_uuid":"acc-uuid","session_id":"sess-uuid"}`, result)
  81. }
  82. func TestFormatMetadataUserID_EmptyVersion_Legacy(t *testing.T) {
  83. result := FormatMetadataUserID("deadbeef"+"00112233445566778899aabbccddeeff0011223344556677", "", "sess-uuid", "")
  84. require.Equal(t, "user_deadbeef00112233445566778899aabbccddeeff0011223344556677_account__session_sess-uuid", result)
  85. }
  86. func TestFormatMetadataUserID_EmptyAccountUUID(t *testing.T) {
  87. // Legacy format with empty account UUID → double underscore
  88. result := FormatMetadataUserID("deadbeef"+"00112233445566778899aabbccddeeff0011223344556677", "", "sess-uuid", "2.1.22")
  89. require.Contains(t, result, "_account__session_")
  90. // New format with empty account UUID → empty string in JSON
  91. result = FormatMetadataUserID("deadbeef"+"00112233445566778899aabbccddeeff0011223344556677", "", "sess-uuid", "2.1.78")
  92. require.Contains(t, result, `"account_uuid":""`)
  93. }
  94. // ============ IsNewMetadataFormatVersion Tests ============
  95. func TestIsNewMetadataFormatVersion(t *testing.T) {
  96. tests := []struct {
  97. version string
  98. want bool
  99. }{
  100. {"", false},
  101. {"2.1.77", false},
  102. {"2.1.78", true},
  103. {"2.1.79", true},
  104. {"2.2.0", true},
  105. {"3.0.0", true},
  106. {"2.0.100", false},
  107. {"1.9.99", false},
  108. }
  109. for _, tt := range tests {
  110. t.Run(tt.version, func(t *testing.T) {
  111. require.Equal(t, tt.want, IsNewMetadataFormatVersion(tt.version))
  112. })
  113. }
  114. }
  115. // ============ Round-trip Tests ============
  116. func TestParseFormat_RoundTrip_Legacy(t *testing.T) {
  117. deviceID := "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
  118. accountUUID := "550e8400-e29b-41d4-a716-446655440000"
  119. sessionID := "123e4567-e89b-12d3-a456-426614174000"
  120. formatted := FormatMetadataUserID(deviceID, accountUUID, sessionID, "2.1.22")
  121. parsed := ParseMetadataUserID(formatted)
  122. require.NotNil(t, parsed)
  123. require.Equal(t, deviceID, parsed.DeviceID)
  124. require.Equal(t, accountUUID, parsed.AccountUUID)
  125. require.Equal(t, sessionID, parsed.SessionID)
  126. require.False(t, parsed.IsNewFormat)
  127. }
  128. func TestParseFormat_RoundTrip_JSON(t *testing.T) {
  129. deviceID := "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
  130. accountUUID := "550e8400-e29b-41d4-a716-446655440000"
  131. sessionID := "123e4567-e89b-12d3-a456-426614174000"
  132. formatted := FormatMetadataUserID(deviceID, accountUUID, sessionID, "2.1.78")
  133. parsed := ParseMetadataUserID(formatted)
  134. require.NotNil(t, parsed)
  135. require.Equal(t, deviceID, parsed.DeviceID)
  136. require.Equal(t, accountUUID, parsed.AccountUUID)
  137. require.Equal(t, sessionID, parsed.SessionID)
  138. require.True(t, parsed.IsNewFormat)
  139. }
  140. func TestParseFormat_RoundTrip_EmptyAccountUUID(t *testing.T) {
  141. deviceID := "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
  142. sessionID := "123e4567-e89b-12d3-a456-426614174000"
  143. // Legacy round-trip with empty account UUID
  144. formatted := FormatMetadataUserID(deviceID, "", sessionID, "2.1.22")
  145. parsed := ParseMetadataUserID(formatted)
  146. require.NotNil(t, parsed)
  147. require.Equal(t, deviceID, parsed.DeviceID)
  148. require.Equal(t, "", parsed.AccountUUID)
  149. require.Equal(t, sessionID, parsed.SessionID)
  150. // JSON round-trip with empty account UUID
  151. formatted = FormatMetadataUserID(deviceID, "", sessionID, "2.1.78")
  152. parsed = ParseMetadataUserID(formatted)
  153. require.NotNil(t, parsed)
  154. require.Equal(t, deviceID, parsed.DeviceID)
  155. require.Equal(t, "", parsed.AccountUUID)
  156. require.Equal(t, sessionID, parsed.SessionID)
  157. }