|
17 | 17 | package common |
18 | 18 |
|
19 | 19 | import ( |
| 20 | + "strings" |
20 | 21 | "testing" |
| 22 | + "unicode/utf8" |
21 | 23 |
|
22 | 24 | "github.com/stretchr/testify/assert" |
23 | 25 |
|
@@ -181,3 +183,81 @@ func TestUtil_CheckValidString(t *testing.T) { |
181 | 183 | err = CheckValidString("aaaaa", 5, fieldSchema) |
182 | 184 | assert.NoError(t, err) |
183 | 185 | } |
| 186 | + |
| 187 | +func TestUtil_SafeStringForError(t *testing.T) { |
| 188 | + // Test valid UTF-8 string |
| 189 | + validStr := "Hello, 世界!" |
| 190 | + result := SafeStringForError(validStr) |
| 191 | + assert.Equal(t, validStr, result) |
| 192 | + |
| 193 | + // Test invalid UTF-8 string |
| 194 | + invalidStr := string([]byte{0xC0, 0xAF, 'a', 'b', 'c'}) |
| 195 | + result = SafeStringForError(invalidStr) |
| 196 | + assert.Contains(t, result, "\\xc0") |
| 197 | + assert.Contains(t, result, "\\xaf") |
| 198 | + assert.Contains(t, result, "abc") |
| 199 | + |
| 200 | + // Test empty string |
| 201 | + result = SafeStringForError("") |
| 202 | + assert.Equal(t, "", result) |
| 203 | + |
| 204 | + // Test string with mixed valid and invalid UTF-8 |
| 205 | + mixedStr := "valid" + string([]byte{0xFF, 0xFE}) + "text" |
| 206 | + result = SafeStringForError(mixedStr) |
| 207 | + assert.Contains(t, result, "valid") |
| 208 | + assert.Contains(t, result, "\\xff") |
| 209 | + assert.Contains(t, result, "\\xfe") |
| 210 | + assert.Contains(t, result, "text") |
| 211 | +} |
| 212 | + |
| 213 | +func TestUtil_SafeStringForErrorWithLimit(t *testing.T) { |
| 214 | + // Test string within limit |
| 215 | + shortStr := "short" |
| 216 | + result := SafeStringForErrorWithLimit(shortStr, 10) |
| 217 | + assert.Equal(t, shortStr, result) |
| 218 | + |
| 219 | + // Test string exceeding limit |
| 220 | + longStr := "this is a very long string that exceeds the limit" |
| 221 | + result = SafeStringForErrorWithLimit(longStr, 20) |
| 222 | + assert.Equal(t, 23, len(result)) // 20 chars + "..." |
| 223 | + assert.True(t, strings.HasSuffix(result, "...")) |
| 224 | + |
| 225 | + // Test invalid UTF-8 string with limit |
| 226 | + invalidStr := string([]byte{0xC0, 0xAF, 0xFF, 0xFE, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}) |
| 227 | + result = SafeStringForErrorWithLimit(invalidStr, 15) |
| 228 | + assert.True(t, len(result) <= 18) // 15 chars + "..." |
| 229 | + assert.True(t, strings.HasSuffix(result, "...")) |
| 230 | +} |
| 231 | + |
| 232 | +func TestUtil_CheckValidUTF8_WithSafeError(t *testing.T) { |
| 233 | + fieldSchema := &schemapb.FieldSchema{ |
| 234 | + FieldID: 1, |
| 235 | + Name: "test_field", |
| 236 | + DataType: schemapb.DataType_VarChar, |
| 237 | + TypeParams: []*commonpb.KeyValuePair{ |
| 238 | + { |
| 239 | + Key: common.MaxLengthKey, |
| 240 | + Value: "1000", |
| 241 | + }, |
| 242 | + }, |
| 243 | + } |
| 244 | + |
| 245 | + // Test with invalid UTF-8 - should not cause gRPC serialization error |
| 246 | + invalidStr := string([]byte{0xC0, 0xAF, 0xFF, 0xFE}) |
| 247 | + err := CheckValidUTF8(invalidStr, fieldSchema) |
| 248 | + assert.Error(t, err) |
| 249 | + |
| 250 | + // Verify the error message contains safe representation |
| 251 | + errMsg := err.Error() |
| 252 | + assert.Contains(t, errMsg, "test_field") |
| 253 | + assert.Contains(t, errMsg, "invalid UTF-8 data") |
| 254 | + assert.Contains(t, errMsg, "\\xc0") // Should contain hex representation |
| 255 | + assert.Contains(t, errMsg, "\\xaf") |
| 256 | + |
| 257 | + // Verify the error message is valid UTF-8 itself |
| 258 | + assert.True(t, utf8.ValidString(errMsg), "Error message should be valid UTF-8") |
| 259 | + |
| 260 | + // Test with valid UTF-8 |
| 261 | + err = CheckValidUTF8("valid string", fieldSchema) |
| 262 | + assert.NoError(t, err) |
| 263 | +} |
0 commit comments