xref: /linux/fs/hfsplus/unicode_test.c (revision 6dfafbd0299a60bfb5d5e277fdf100037c7ded07)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * KUnit tests for HFS+ Unicode string operations
4  *
5  * Copyright (C) 2025 Viacheslav Dubeyko <slava@dubeyko.com>
6  */
7 
8 #include <kunit/test.h>
9 #include <linux/nls.h>
10 #include <linux/dcache.h>
11 #include <linux/stringhash.h>
12 #include "hfsplus_fs.h"
13 
14 struct test_mock_string_env {
15 	struct hfsplus_unistr str1;
16 	struct hfsplus_unistr str2;
17 	char *buf;
18 	u32 buf_size;
19 };
20 
21 static struct test_mock_string_env *setup_mock_str_env(u32 buf_size)
22 {
23 	struct test_mock_string_env *env;
24 
25 	env = kzalloc(sizeof(struct test_mock_string_env), GFP_KERNEL);
26 	if (!env)
27 		return NULL;
28 
29 	env->buf = kzalloc(buf_size, GFP_KERNEL);
30 	if (!env->buf) {
31 		kfree(env);
32 		return NULL;
33 	}
34 
35 	env->buf_size = buf_size;
36 
37 	return env;
38 }
39 
40 static void free_mock_str_env(struct test_mock_string_env *env)
41 {
42 	if (env->buf)
43 		kfree(env->buf);
44 	kfree(env);
45 }
46 
47 /* Helper function to create hfsplus_unistr */
48 static void create_unistr(struct hfsplus_unistr *ustr, const char *ascii_str)
49 {
50 	int len = strlen(ascii_str);
51 	int i;
52 
53 	memset(ustr->unicode, 0, sizeof(ustr->unicode));
54 
55 	ustr->length = cpu_to_be16(len);
56 	for (i = 0; i < len && i < HFSPLUS_MAX_STRLEN; i++)
57 		ustr->unicode[i] = cpu_to_be16((u16)ascii_str[i]);
58 }
59 
60 static void corrupt_unistr(struct hfsplus_unistr *ustr)
61 {
62 	ustr->length = cpu_to_be16(U16_MAX);
63 }
64 
65 /* Test hfsplus_strcasecmp function */
66 static void hfsplus_strcasecmp_test(struct kunit *test)
67 {
68 	struct test_mock_string_env *mock_env;
69 
70 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
71 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
72 
73 	/* Test identical strings */
74 	create_unistr(&mock_env->str1, "hello");
75 	create_unistr(&mock_env->str2, "hello");
76 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
77 						    &mock_env->str2));
78 
79 	/* Test case insensitive comparison */
80 	create_unistr(&mock_env->str1, "Hello");
81 	create_unistr(&mock_env->str2, "hello");
82 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
83 						    &mock_env->str2));
84 
85 	create_unistr(&mock_env->str1, "HELLO");
86 	create_unistr(&mock_env->str2, "hello");
87 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
88 						    &mock_env->str2));
89 
90 	/* Test different strings */
91 	create_unistr(&mock_env->str1, "apple");
92 	create_unistr(&mock_env->str2, "banana");
93 	KUNIT_EXPECT_LT(test, hfsplus_strcasecmp(&mock_env->str1,
94 						 &mock_env->str2), 0);
95 
96 	create_unistr(&mock_env->str1, "zebra");
97 	create_unistr(&mock_env->str2, "apple");
98 	KUNIT_EXPECT_GT(test, hfsplus_strcasecmp(&mock_env->str1,
99 						 &mock_env->str2), 0);
100 
101 	/* Test different lengths */
102 	create_unistr(&mock_env->str1, "test");
103 	create_unistr(&mock_env->str2, "testing");
104 	KUNIT_EXPECT_LT(test, hfsplus_strcasecmp(&mock_env->str1,
105 						 &mock_env->str2), 0);
106 
107 	create_unistr(&mock_env->str1, "testing");
108 	create_unistr(&mock_env->str2, "test");
109 	KUNIT_EXPECT_GT(test, hfsplus_strcasecmp(&mock_env->str1,
110 						 &mock_env->str2), 0);
111 
112 	/* Test empty strings */
113 	create_unistr(&mock_env->str1, "");
114 	create_unistr(&mock_env->str2, "");
115 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
116 						    &mock_env->str2));
117 
118 	create_unistr(&mock_env->str1, "");
119 	create_unistr(&mock_env->str2, "test");
120 	KUNIT_EXPECT_LT(test, hfsplus_strcasecmp(&mock_env->str1,
121 						 &mock_env->str2), 0);
122 
123 	/* Test single characters */
124 	create_unistr(&mock_env->str1, "A");
125 	create_unistr(&mock_env->str2, "a");
126 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
127 						    &mock_env->str2));
128 
129 	create_unistr(&mock_env->str1, "A");
130 	create_unistr(&mock_env->str2, "B");
131 	KUNIT_EXPECT_LT(test, hfsplus_strcasecmp(&mock_env->str1,
132 						 &mock_env->str2), 0);
133 
134 	/* Test maximum length strings */
135 	memset(mock_env->buf, 'a', HFSPLUS_MAX_STRLEN);
136 	mock_env->buf[HFSPLUS_MAX_STRLEN] = '\0';
137 	create_unistr(&mock_env->str1, mock_env->buf);
138 	create_unistr(&mock_env->str2, mock_env->buf);
139 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
140 						    &mock_env->str2));
141 
142 	/* Change one character in the middle */
143 	mock_env->buf[HFSPLUS_MAX_STRLEN / 2] = 'b';
144 	create_unistr(&mock_env->str2, mock_env->buf);
145 	KUNIT_EXPECT_LT(test, hfsplus_strcasecmp(&mock_env->str1,
146 						 &mock_env->str2), 0);
147 
148 	/* Test corrupted strings */
149 	create_unistr(&mock_env->str1, "");
150 	corrupt_unistr(&mock_env->str1);
151 	create_unistr(&mock_env->str2, "");
152 	KUNIT_EXPECT_NE(test, 0, hfsplus_strcasecmp(&mock_env->str1,
153 						    &mock_env->str2));
154 
155 	create_unistr(&mock_env->str1, "");
156 	create_unistr(&mock_env->str2, "");
157 	corrupt_unistr(&mock_env->str2);
158 	KUNIT_EXPECT_NE(test, 0, hfsplus_strcasecmp(&mock_env->str1,
159 						    &mock_env->str2));
160 
161 	create_unistr(&mock_env->str1, "test");
162 	corrupt_unistr(&mock_env->str1);
163 	create_unistr(&mock_env->str2, "testing");
164 	KUNIT_EXPECT_GT(test, hfsplus_strcasecmp(&mock_env->str1,
165 						 &mock_env->str2), 0);
166 
167 	create_unistr(&mock_env->str1, "test");
168 	create_unistr(&mock_env->str2, "testing");
169 	corrupt_unistr(&mock_env->str2);
170 	KUNIT_EXPECT_LT(test, hfsplus_strcasecmp(&mock_env->str1,
171 						 &mock_env->str2), 0);
172 
173 	create_unistr(&mock_env->str1, "testing");
174 	corrupt_unistr(&mock_env->str1);
175 	create_unistr(&mock_env->str2, "test");
176 	KUNIT_EXPECT_GT(test, hfsplus_strcasecmp(&mock_env->str1,
177 						 &mock_env->str2), 0);
178 
179 	create_unistr(&mock_env->str1, "testing");
180 	create_unistr(&mock_env->str2, "test");
181 	corrupt_unistr(&mock_env->str2);
182 	KUNIT_EXPECT_LT(test, hfsplus_strcasecmp(&mock_env->str1,
183 						 &mock_env->str2), 0);
184 
185 	free_mock_str_env(mock_env);
186 }
187 
188 /* Test hfsplus_strcmp function (case-sensitive) */
189 static void hfsplus_strcmp_test(struct kunit *test)
190 {
191 	struct test_mock_string_env *mock_env;
192 
193 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
194 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
195 
196 	/* Test identical strings */
197 	create_unistr(&mock_env->str1, "hello");
198 	create_unistr(&mock_env->str2, "hello");
199 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcmp(&mock_env->str1,
200 						&mock_env->str2));
201 
202 	/* Test case sensitive comparison - should NOT be equal */
203 	create_unistr(&mock_env->str1, "Hello");
204 	create_unistr(&mock_env->str2, "hello");
205 	KUNIT_EXPECT_NE(test, 0, hfsplus_strcmp(&mock_env->str1,
206 						&mock_env->str2));
207 	 /* 'H' < 'h' in Unicode */
208 	KUNIT_EXPECT_LT(test, hfsplus_strcmp(&mock_env->str1,
209 					     &mock_env->str2), 0);
210 
211 	/* Test lexicographic ordering */
212 	create_unistr(&mock_env->str1, "apple");
213 	create_unistr(&mock_env->str2, "banana");
214 	KUNIT_EXPECT_LT(test, hfsplus_strcmp(&mock_env->str1,
215 					     &mock_env->str2), 0);
216 
217 	create_unistr(&mock_env->str1, "zebra");
218 	create_unistr(&mock_env->str2, "apple");
219 	KUNIT_EXPECT_GT(test, hfsplus_strcmp(&mock_env->str1,
220 					     &mock_env->str2), 0);
221 
222 	/* Test different lengths with common prefix */
223 	create_unistr(&mock_env->str1, "test");
224 	create_unistr(&mock_env->str2, "testing");
225 	KUNIT_EXPECT_LT(test, hfsplus_strcmp(&mock_env->str1,
226 					     &mock_env->str2), 0);
227 
228 	create_unistr(&mock_env->str1, "testing");
229 	create_unistr(&mock_env->str2, "test");
230 	KUNIT_EXPECT_GT(test, hfsplus_strcmp(&mock_env->str1,
231 					     &mock_env->str2), 0);
232 
233 	/* Test empty strings */
234 	create_unistr(&mock_env->str1, "");
235 	create_unistr(&mock_env->str2, "");
236 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcmp(&mock_env->str1,
237 						&mock_env->str2));
238 
239 	/* Test maximum length strings */
240 	memset(mock_env->buf, 'a', HFSPLUS_MAX_STRLEN);
241 	mock_env->buf[HFSPLUS_MAX_STRLEN] = '\0';
242 	create_unistr(&mock_env->str1, mock_env->buf);
243 	create_unistr(&mock_env->str2, mock_env->buf);
244 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcmp(&mock_env->str1,
245 						&mock_env->str2));
246 
247 	/* Change one character in the middle */
248 	mock_env->buf[HFSPLUS_MAX_STRLEN / 2] = 'b';
249 	create_unistr(&mock_env->str2, mock_env->buf);
250 	KUNIT_EXPECT_LT(test, hfsplus_strcmp(&mock_env->str1,
251 					     &mock_env->str2), 0);
252 
253 	/* Test corrupted strings */
254 	create_unistr(&mock_env->str1, "");
255 	corrupt_unistr(&mock_env->str1);
256 	create_unistr(&mock_env->str2, "");
257 	KUNIT_EXPECT_NE(test, 0, hfsplus_strcmp(&mock_env->str1,
258 						&mock_env->str2));
259 
260 	create_unistr(&mock_env->str1, "");
261 	create_unistr(&mock_env->str2, "");
262 	corrupt_unistr(&mock_env->str2);
263 	KUNIT_EXPECT_NE(test, 0, hfsplus_strcmp(&mock_env->str1,
264 						&mock_env->str2));
265 
266 	create_unistr(&mock_env->str1, "test");
267 	corrupt_unistr(&mock_env->str1);
268 	create_unistr(&mock_env->str2, "testing");
269 	KUNIT_EXPECT_LT(test, hfsplus_strcmp(&mock_env->str1,
270 					     &mock_env->str2), 0);
271 
272 	create_unistr(&mock_env->str1, "test");
273 	create_unistr(&mock_env->str2, "testing");
274 	corrupt_unistr(&mock_env->str2);
275 	KUNIT_EXPECT_LT(test, hfsplus_strcmp(&mock_env->str1,
276 					     &mock_env->str2), 0);
277 
278 	create_unistr(&mock_env->str1, "testing");
279 	corrupt_unistr(&mock_env->str1);
280 	create_unistr(&mock_env->str2, "test");
281 	KUNIT_EXPECT_GT(test, hfsplus_strcmp(&mock_env->str1,
282 					     &mock_env->str2), 0);
283 
284 	create_unistr(&mock_env->str1, "testing");
285 	create_unistr(&mock_env->str2, "test");
286 	corrupt_unistr(&mock_env->str2);
287 	KUNIT_EXPECT_GT(test, hfsplus_strcmp(&mock_env->str1,
288 					     &mock_env->str2), 0);
289 
290 	free_mock_str_env(mock_env);
291 }
292 
293 /* Test Unicode edge cases */
294 static void hfsplus_unicode_edge_cases_test(struct kunit *test)
295 {
296 	struct test_mock_string_env *mock_env;
297 
298 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
299 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
300 
301 	/* Test with special characters */
302 	mock_env->str1.length = cpu_to_be16(3);
303 	mock_env->str1.unicode[0] = cpu_to_be16(0x00E9); /* é */
304 	mock_env->str1.unicode[1] = cpu_to_be16(0x00F1); /* ñ */
305 	mock_env->str1.unicode[2] = cpu_to_be16(0x00FC); /* ü */
306 
307 	mock_env->str2.length = cpu_to_be16(3);
308 	mock_env->str2.unicode[0] = cpu_to_be16(0x00E9); /* é */
309 	mock_env->str2.unicode[1] = cpu_to_be16(0x00F1); /* ñ */
310 	mock_env->str2.unicode[2] = cpu_to_be16(0x00FC); /* ü */
311 
312 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcmp(&mock_env->str1,
313 						&mock_env->str2));
314 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
315 						    &mock_env->str2));
316 
317 	/* Test with different special characters */
318 	mock_env->str2.unicode[1] = cpu_to_be16(0x00F2); /* ò */
319 	KUNIT_EXPECT_NE(test, 0, hfsplus_strcmp(&mock_env->str1,
320 						&mock_env->str2));
321 
322 	/* Test null characters within string (should be handled correctly) */
323 	mock_env->str1.length = cpu_to_be16(3);
324 	mock_env->str1.unicode[0] = cpu_to_be16('a');
325 	mock_env->str1.unicode[1] = cpu_to_be16(0x0000); /* null */
326 	mock_env->str1.unicode[2] = cpu_to_be16('b');
327 
328 	mock_env->str2.length = cpu_to_be16(3);
329 	mock_env->str2.unicode[0] = cpu_to_be16('a');
330 	mock_env->str2.unicode[1] = cpu_to_be16(0x0000); /* null */
331 	mock_env->str2.unicode[2] = cpu_to_be16('b');
332 
333 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcmp(&mock_env->str1,
334 						&mock_env->str2));
335 
336 	free_mock_str_env(mock_env);
337 }
338 
339 /* Test boundary conditions */
340 static void hfsplus_unicode_boundary_test(struct kunit *test)
341 {
342 	struct test_mock_string_env *mock_env;
343 	int i;
344 
345 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
346 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
347 
348 	/* Test maximum length boundary */
349 	mock_env->str1.length = cpu_to_be16(HFSPLUS_MAX_STRLEN);
350 	mock_env->str2.length = cpu_to_be16(HFSPLUS_MAX_STRLEN);
351 
352 	for (i = 0; i < HFSPLUS_MAX_STRLEN; i++) {
353 		mock_env->str1.unicode[i] = cpu_to_be16('A');
354 		mock_env->str2.unicode[i] = cpu_to_be16('A');
355 	}
356 
357 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcmp(&mock_env->str1,
358 						&mock_env->str2));
359 
360 	/* Change last character */
361 	mock_env->str2.unicode[HFSPLUS_MAX_STRLEN - 1] = cpu_to_be16('B');
362 	KUNIT_EXPECT_LT(test, hfsplus_strcmp(&mock_env->str1,
363 					     &mock_env->str2), 0);
364 
365 	/* Test zero length strings */
366 	mock_env->str1.length = cpu_to_be16(0);
367 	mock_env->str2.length = cpu_to_be16(0);
368 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcmp(&mock_env->str1,
369 						&mock_env->str2));
370 	KUNIT_EXPECT_EQ(test, 0, hfsplus_strcasecmp(&mock_env->str1,
371 						    &mock_env->str2));
372 
373 	/* Test one character vs empty */
374 	mock_env->str1.length = cpu_to_be16(1);
375 	mock_env->str1.unicode[0] = cpu_to_be16('A');
376 	mock_env->str2.length = cpu_to_be16(0);
377 	KUNIT_EXPECT_GT(test, hfsplus_strcmp(&mock_env->str1,
378 					     &mock_env->str2), 0);
379 	KUNIT_EXPECT_GT(test, hfsplus_strcasecmp(&mock_env->str1,
380 						 &mock_env->str2), 0);
381 
382 	free_mock_str_env(mock_env);
383 }
384 
385 /* Mock superblock and NLS table for testing hfsplus_uni2asc */
386 struct test_mock_sb {
387 	struct nls_table nls;
388 	struct hfsplus_sb_info sb_info;
389 	struct super_block sb;
390 };
391 
392 static struct test_mock_sb *setup_mock_sb(void)
393 {
394 	struct test_mock_sb *ptr;
395 
396 	ptr = kzalloc(sizeof(struct test_mock_sb), GFP_KERNEL);
397 	if (!ptr)
398 		return NULL;
399 
400 	ptr->nls.charset = "utf8";
401 	ptr->nls.uni2char = NULL; /* Will use default behavior */
402 	ptr->sb_info.nls = &ptr->nls;
403 	ptr->sb.s_fs_info = &ptr->sb_info;
404 
405 	/* Set default flags - no decomposition, no case folding */
406 	clear_bit(HFSPLUS_SB_NODECOMPOSE, &ptr->sb_info.flags);
407 	clear_bit(HFSPLUS_SB_CASEFOLD, &ptr->sb_info.flags);
408 
409 	return ptr;
410 }
411 
412 static void free_mock_sb(struct test_mock_sb *ptr)
413 {
414 	kfree(ptr);
415 }
416 
417 /* Simple uni2char implementation for testing */
418 static int test_uni2char(wchar_t uni, unsigned char *out, int boundlen)
419 {
420 	if (boundlen <= 0)
421 		return -ENAMETOOLONG;
422 
423 	if (uni < 0x80) {
424 		*out = (unsigned char)uni;
425 		return 1;
426 	}
427 
428 	/* For non-ASCII, just use '?' as fallback */
429 	*out = '?';
430 	return 1;
431 }
432 
433 /* Test hfsplus_uni2asc basic functionality */
434 static void hfsplus_uni2asc_basic_test(struct kunit *test)
435 {
436 	struct test_mock_sb *mock_sb;
437 	struct test_mock_string_env *mock_env;
438 	int len, result;
439 
440 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
441 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
442 
443 	mock_sb = setup_mock_sb();
444 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
445 
446 	mock_sb->nls.uni2char = test_uni2char;
447 
448 	/* Test simple ASCII string conversion */
449 	create_unistr(&mock_env->str1, "hello");
450 	len = mock_env->buf_size;
451 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
452 				     mock_env->buf, &len);
453 
454 	KUNIT_EXPECT_EQ(test, 0, result);
455 	KUNIT_EXPECT_EQ(test, 5, len);
456 	KUNIT_EXPECT_STREQ(test, "hello", mock_env->buf);
457 
458 	/* Test empty string */
459 	create_unistr(&mock_env->str1, "");
460 	len = mock_env->buf_size;
461 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
462 				     mock_env->buf, &len);
463 
464 	KUNIT_EXPECT_EQ(test, 0, result);
465 	KUNIT_EXPECT_EQ(test, 0, len);
466 
467 	/* Test single character */
468 	create_unistr(&mock_env->str1, "A");
469 	len = mock_env->buf_size;
470 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
471 				     mock_env->buf, &len);
472 
473 	KUNIT_EXPECT_EQ(test, 0, result);
474 	KUNIT_EXPECT_EQ(test, 1, len);
475 	KUNIT_EXPECT_EQ(test, 'A', mock_env->buf[0]);
476 
477 	free_mock_str_env(mock_env);
478 	free_mock_sb(mock_sb);
479 }
480 
481 /* Test special character handling */
482 static void hfsplus_uni2asc_special_chars_test(struct kunit *test)
483 {
484 	struct test_mock_sb *mock_sb;
485 	struct test_mock_string_env *mock_env;
486 	int len, result;
487 
488 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
489 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
490 
491 	mock_sb = setup_mock_sb();
492 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
493 
494 	mock_sb->nls.uni2char = test_uni2char;
495 
496 	/* Test null character conversion (should become 0x2400) */
497 	mock_env->str1.length = cpu_to_be16(1);
498 	mock_env->str1.unicode[0] = cpu_to_be16(0x0000);
499 	len = mock_env->buf_size;
500 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
501 				     mock_env->buf, &len);
502 
503 	KUNIT_EXPECT_EQ(test, 0, result);
504 	KUNIT_EXPECT_EQ(test, 1, len);
505 	/* Our test implementation returns '?' for non-ASCII */
506 	KUNIT_EXPECT_EQ(test, '?', mock_env->buf[0]);
507 
508 	/* Test forward slash conversion (should become colon) */
509 	mock_env->str1.length = cpu_to_be16(1);
510 	mock_env->str1.unicode[0] = cpu_to_be16('/');
511 	len = mock_env->buf_size;
512 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
513 				     mock_env->buf, &len);
514 
515 	KUNIT_EXPECT_EQ(test, 0, result);
516 	KUNIT_EXPECT_EQ(test, 1, len);
517 	KUNIT_EXPECT_EQ(test, ':', mock_env->buf[0]);
518 
519 	/* Test string with mixed special characters */
520 	mock_env->str1.length = cpu_to_be16(3);
521 	mock_env->str1.unicode[0] = cpu_to_be16('a');
522 	mock_env->str1.unicode[1] = cpu_to_be16('/');
523 	mock_env->str1.unicode[2] = cpu_to_be16('b');
524 	len = mock_env->buf_size;
525 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
526 				     mock_env->buf, &len);
527 
528 	KUNIT_EXPECT_EQ(test, 0, result);
529 	KUNIT_EXPECT_EQ(test, 3, len);
530 	KUNIT_EXPECT_EQ(test, 'a', mock_env->buf[0]);
531 	KUNIT_EXPECT_EQ(test, ':', mock_env->buf[1]);
532 	KUNIT_EXPECT_EQ(test, 'b', mock_env->buf[2]);
533 
534 	free_mock_str_env(mock_env);
535 	free_mock_sb(mock_sb);
536 }
537 
538 /* Test buffer length handling */
539 static void hfsplus_uni2asc_buffer_test(struct kunit *test)
540 {
541 	struct test_mock_sb *mock_sb;
542 	struct test_mock_string_env *mock_env;
543 	int len, result;
544 
545 	mock_env = setup_mock_str_env(10);
546 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
547 
548 	mock_sb = setup_mock_sb();
549 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
550 
551 	mock_sb->nls.uni2char = test_uni2char;
552 
553 	/* Test insufficient buffer space */
554 	create_unistr(&mock_env->str1, "toolongstring");
555 	len = 5; /* Buffer too small */
556 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
557 				     mock_env->buf, &len);
558 
559 	KUNIT_EXPECT_EQ(test, -ENAMETOOLONG, result);
560 	KUNIT_EXPECT_EQ(test, 5, len); /* Should be set to consumed length */
561 
562 	/* Test exact buffer size */
563 	create_unistr(&mock_env->str1, "exact");
564 	len = 5;
565 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
566 				     mock_env->buf, &len);
567 
568 	KUNIT_EXPECT_EQ(test, 0, result);
569 	KUNIT_EXPECT_EQ(test, 5, len);
570 
571 	/* Test zero length buffer */
572 	create_unistr(&mock_env->str1, "test");
573 	len = 0;
574 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
575 				     mock_env->buf, &len);
576 
577 	KUNIT_EXPECT_EQ(test, -ENAMETOOLONG, result);
578 	KUNIT_EXPECT_EQ(test, 0, len);
579 
580 	free_mock_str_env(mock_env);
581 	free_mock_sb(mock_sb);
582 }
583 
584 /* Test corrupted unicode string handling */
585 static void hfsplus_uni2asc_corrupted_test(struct kunit *test)
586 {
587 	struct test_mock_sb *mock_sb;
588 	struct test_mock_string_env *mock_env;
589 	int len, result;
590 
591 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
592 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
593 
594 	mock_sb = setup_mock_sb();
595 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
596 
597 	mock_sb->nls.uni2char = test_uni2char;
598 
599 	/* Test corrupted length (too large) */
600 	create_unistr(&mock_env->str1, "test");
601 	corrupt_unistr(&mock_env->str1); /* Sets length to U16_MAX */
602 	len = mock_env->buf_size;
603 
604 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
605 				     mock_env->buf, &len);
606 
607 	/* Should still work but with corrected length */
608 	KUNIT_EXPECT_EQ(test, 0, result);
609 	/*
610 	 * Length should be corrected to HFSPLUS_MAX_STRLEN
611 	 * and processed accordingly
612 	 */
613 	KUNIT_EXPECT_GT(test, len, 0);
614 
615 	free_mock_str_env(mock_env);
616 	free_mock_sb(mock_sb);
617 }
618 
619 /* Test edge cases and boundary conditions */
620 static void hfsplus_uni2asc_edge_cases_test(struct kunit *test)
621 {
622 	struct test_mock_sb *mock_sb;
623 	struct test_mock_string_env *mock_env;
624 	int len, result;
625 	int i;
626 
627 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN * 2);
628 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
629 
630 	mock_sb = setup_mock_sb();
631 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
632 
633 	mock_sb->nls.uni2char = test_uni2char;
634 
635 	/* Test maximum length string */
636 	mock_env->str1.length = cpu_to_be16(HFSPLUS_MAX_STRLEN);
637 	for (i = 0; i < HFSPLUS_MAX_STRLEN; i++)
638 		mock_env->str1.unicode[i] = cpu_to_be16('a');
639 
640 	len = mock_env->buf_size;
641 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
642 				     mock_env->buf, &len);
643 
644 	KUNIT_EXPECT_EQ(test, 0, result);
645 	KUNIT_EXPECT_EQ(test, HFSPLUS_MAX_STRLEN, len);
646 
647 	/* Verify all characters are 'a' */
648 	for (i = 0; i < HFSPLUS_MAX_STRLEN; i++)
649 		KUNIT_EXPECT_EQ(test, 'a', mock_env->buf[i]);
650 
651 	/* Test string with high Unicode values (non-ASCII) */
652 	mock_env->str1.length = cpu_to_be16(3);
653 	mock_env->str1.unicode[0] = cpu_to_be16(0x00E9); /* é */
654 	mock_env->str1.unicode[1] = cpu_to_be16(0x00F1); /* ñ */
655 	mock_env->str1.unicode[2] = cpu_to_be16(0x00FC); /* ü */
656 	len = mock_env->buf_size;
657 	result = hfsplus_uni2asc_str(&mock_sb->sb, &mock_env->str1,
658 				     mock_env->buf, &len);
659 
660 	KUNIT_EXPECT_EQ(test, 0, result);
661 	KUNIT_EXPECT_EQ(test, 3, len);
662 	/* Our test implementation converts non-ASCII to '?' */
663 	KUNIT_EXPECT_EQ(test, '?', mock_env->buf[0]);
664 	KUNIT_EXPECT_EQ(test, '?', mock_env->buf[1]);
665 	KUNIT_EXPECT_EQ(test, '?', mock_env->buf[2]);
666 
667 	free_mock_str_env(mock_env);
668 	free_mock_sb(mock_sb);
669 }
670 
671 /* Simple char2uni implementation for testing */
672 static int test_char2uni(const unsigned char *rawstring,
673 			 int boundlen, wchar_t *uni)
674 {
675 	if (boundlen <= 0)
676 		return -EINVAL;
677 
678 	*uni = (wchar_t)*rawstring;
679 	return 1;
680 }
681 
682 /* Helper function to check unicode string contents */
683 static void check_unistr_content(struct kunit *test,
684 				 struct hfsplus_unistr *ustr,
685 				 const char *expected_ascii)
686 {
687 	int expected_len = strlen(expected_ascii);
688 	int actual_len = be16_to_cpu(ustr->length);
689 	int i;
690 
691 	KUNIT_EXPECT_EQ(test, expected_len, actual_len);
692 
693 	for (i = 0; i < expected_len && i < actual_len; i++) {
694 		u16 expected_char = (u16)expected_ascii[i];
695 		u16 actual_char = be16_to_cpu(ustr->unicode[i]);
696 
697 		KUNIT_EXPECT_EQ(test, expected_char, actual_char);
698 	}
699 }
700 
701 /* Test hfsplus_asc2uni basic functionality */
702 static void hfsplus_asc2uni_basic_test(struct kunit *test)
703 {
704 	struct test_mock_sb *mock_sb;
705 	struct test_mock_string_env *mock_env;
706 	int result;
707 
708 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
709 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
710 
711 	mock_sb = setup_mock_sb();
712 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
713 
714 	mock_sb->nls.char2uni = test_char2uni;
715 
716 	/* Test simple ASCII string conversion */
717 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
718 				 HFSPLUS_MAX_STRLEN, "hello", 5);
719 
720 	KUNIT_EXPECT_EQ(test, 0, result);
721 	check_unistr_content(test, &mock_env->str1, "hello");
722 
723 	/* Test empty string */
724 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
725 				 HFSPLUS_MAX_STRLEN, "", 0);
726 
727 	KUNIT_EXPECT_EQ(test, 0, result);
728 	KUNIT_EXPECT_EQ(test, 0, be16_to_cpu(mock_env->str1.length));
729 
730 	/* Test single character */
731 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
732 				 HFSPLUS_MAX_STRLEN, "A", 1);
733 
734 	KUNIT_EXPECT_EQ(test, 0, result);
735 	check_unistr_content(test, &mock_env->str1, "A");
736 
737 	/* Test null-terminated string with explicit length */
738 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
739 				 HFSPLUS_MAX_STRLEN, "test\0extra", 4);
740 
741 	KUNIT_EXPECT_EQ(test, 0, result);
742 	check_unistr_content(test, &mock_env->str1, "test");
743 
744 	free_mock_str_env(mock_env);
745 	free_mock_sb(mock_sb);
746 }
747 
748 /* Test special character handling in asc2uni */
749 static void hfsplus_asc2uni_special_chars_test(struct kunit *test)
750 {
751 	struct test_mock_sb *mock_sb;
752 	struct test_mock_string_env *mock_env;
753 	int result;
754 
755 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
756 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
757 
758 	mock_sb = setup_mock_sb();
759 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
760 
761 	mock_sb->nls.char2uni = test_char2uni;
762 
763 	/* Test colon conversion (should become forward slash) */
764 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
765 				 HFSPLUS_MAX_STRLEN, ":", 1);
766 
767 	KUNIT_EXPECT_EQ(test, 0, result);
768 	KUNIT_EXPECT_EQ(test, 1, be16_to_cpu(mock_env->str1.length));
769 	KUNIT_EXPECT_EQ(test, '/', be16_to_cpu(mock_env->str1.unicode[0]));
770 
771 	/* Test string with mixed special characters */
772 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
773 				 HFSPLUS_MAX_STRLEN, "a:b", 3);
774 
775 	KUNIT_EXPECT_EQ(test, 0, result);
776 	KUNIT_EXPECT_EQ(test, 3, be16_to_cpu(mock_env->str1.length));
777 	KUNIT_EXPECT_EQ(test, 'a', be16_to_cpu(mock_env->str1.unicode[0]));
778 	KUNIT_EXPECT_EQ(test, '/', be16_to_cpu(mock_env->str1.unicode[1]));
779 	KUNIT_EXPECT_EQ(test, 'b', be16_to_cpu(mock_env->str1.unicode[2]));
780 
781 	/* Test multiple special characters */
782 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
783 				 HFSPLUS_MAX_STRLEN, ":::", 3);
784 
785 	KUNIT_EXPECT_EQ(test, 0, result);
786 	KUNIT_EXPECT_EQ(test, 3, be16_to_cpu(mock_env->str1.length));
787 	KUNIT_EXPECT_EQ(test, '/', be16_to_cpu(mock_env->str1.unicode[0]));
788 	KUNIT_EXPECT_EQ(test, '/', be16_to_cpu(mock_env->str1.unicode[1]));
789 	KUNIT_EXPECT_EQ(test, '/', be16_to_cpu(mock_env->str1.unicode[2]));
790 
791 	free_mock_str_env(mock_env);
792 	free_mock_sb(mock_sb);
793 }
794 
795 /* Test buffer length limits */
796 static void hfsplus_asc2uni_buffer_limits_test(struct kunit *test)
797 {
798 	struct test_mock_sb *mock_sb;
799 	struct test_mock_string_env *mock_env;
800 	int result;
801 
802 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 10);
803 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
804 
805 	mock_sb = setup_mock_sb();
806 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
807 
808 	mock_sb->nls.char2uni = test_char2uni;
809 
810 	/* Test exact maximum length */
811 	memset(mock_env->buf, 'a', HFSPLUS_MAX_STRLEN);
812 	result = hfsplus_asc2uni(&mock_sb->sb,
813 				 &mock_env->str1, HFSPLUS_MAX_STRLEN,
814 				 mock_env->buf, HFSPLUS_MAX_STRLEN);
815 
816 	KUNIT_EXPECT_EQ(test, 0, result);
817 	KUNIT_EXPECT_EQ(test, HFSPLUS_MAX_STRLEN,
818 			be16_to_cpu(mock_env->str1.length));
819 
820 	/* Test exceeding maximum length */
821 	memset(mock_env->buf, 'a', HFSPLUS_MAX_STRLEN + 5);
822 	result = hfsplus_asc2uni(&mock_sb->sb,
823 				 &mock_env->str1, HFSPLUS_MAX_STRLEN,
824 				 mock_env->buf, HFSPLUS_MAX_STRLEN + 5);
825 
826 	KUNIT_EXPECT_EQ(test, -ENAMETOOLONG, result);
827 	KUNIT_EXPECT_EQ(test, HFSPLUS_MAX_STRLEN,
828 			be16_to_cpu(mock_env->str1.length));
829 
830 	/* Test with smaller max_unistr_len */
831 	result = hfsplus_asc2uni(&mock_sb->sb,
832 				 &mock_env->str1, 5, "toolongstring", 13);
833 
834 	KUNIT_EXPECT_EQ(test, -ENAMETOOLONG, result);
835 	KUNIT_EXPECT_EQ(test, 5, be16_to_cpu(mock_env->str1.length));
836 
837 	/* Test zero max length */
838 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1, 0, "test", 4);
839 
840 	KUNIT_EXPECT_EQ(test, -ENAMETOOLONG, result);
841 	KUNIT_EXPECT_EQ(test, 0, be16_to_cpu(mock_env->str1.length));
842 
843 	free_mock_str_env(mock_env);
844 	free_mock_sb(mock_sb);
845 }
846 
847 /* Test error handling and edge cases */
848 static void hfsplus_asc2uni_edge_cases_test(struct kunit *test)
849 {
850 	struct test_mock_sb *mock_sb;
851 	struct hfsplus_unistr ustr;
852 	char test_str[] = {'a', '\0', 'b'};
853 	int result;
854 
855 	mock_sb = setup_mock_sb();
856 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
857 
858 	mock_sb->nls.char2uni = test_char2uni;
859 
860 	/* Test zero length input */
861 	result = hfsplus_asc2uni(&mock_sb->sb,
862 				 &ustr, HFSPLUS_MAX_STRLEN, "test", 0);
863 
864 	KUNIT_EXPECT_EQ(test, 0, result);
865 	KUNIT_EXPECT_EQ(test, 0, be16_to_cpu(ustr.length));
866 
867 	/* Test input with length mismatch */
868 	result = hfsplus_asc2uni(&mock_sb->sb,
869 				 &ustr, HFSPLUS_MAX_STRLEN, "hello", 3);
870 
871 	KUNIT_EXPECT_EQ(test, 0, result);
872 	check_unistr_content(test, &ustr, "hel");
873 
874 	/* Test with various printable ASCII characters */
875 	result = hfsplus_asc2uni(&mock_sb->sb,
876 				 &ustr, HFSPLUS_MAX_STRLEN, "ABC123!@#", 9);
877 
878 	KUNIT_EXPECT_EQ(test, 0, result);
879 	check_unistr_content(test, &ustr, "ABC123!@#");
880 
881 	/* Test null character in the middle */
882 	result = hfsplus_asc2uni(&mock_sb->sb,
883 				 &ustr, HFSPLUS_MAX_STRLEN, test_str, 3);
884 
885 	KUNIT_EXPECT_EQ(test, 0, result);
886 	KUNIT_EXPECT_EQ(test, 3, be16_to_cpu(ustr.length));
887 	KUNIT_EXPECT_EQ(test, 'a', be16_to_cpu(ustr.unicode[0]));
888 	KUNIT_EXPECT_EQ(test, 0, be16_to_cpu(ustr.unicode[1]));
889 	KUNIT_EXPECT_EQ(test, 'b', be16_to_cpu(ustr.unicode[2]));
890 
891 	free_mock_sb(mock_sb);
892 }
893 
894 /* Test decomposition flag behavior */
895 static void hfsplus_asc2uni_decompose_test(struct kunit *test)
896 {
897 	struct test_mock_sb *mock_sb;
898 	struct test_mock_string_env *mock_env;
899 	int result;
900 
901 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
902 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
903 
904 	mock_sb = setup_mock_sb();
905 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
906 
907 	mock_sb->nls.char2uni = test_char2uni;
908 
909 	/* Test with decomposition disabled (default) */
910 	clear_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
911 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str1,
912 				 HFSPLUS_MAX_STRLEN, "test", 4);
913 
914 	KUNIT_EXPECT_EQ(test, 0, result);
915 	check_unistr_content(test, &mock_env->str1, "test");
916 
917 	/* Test with decomposition enabled */
918 	set_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
919 	result = hfsplus_asc2uni(&mock_sb->sb, &mock_env->str2,
920 				 HFSPLUS_MAX_STRLEN, "test", 4);
921 
922 	KUNIT_EXPECT_EQ(test, 0, result);
923 	check_unistr_content(test, &mock_env->str2, "test");
924 
925 	/* For simple ASCII, both should produce the same result */
926 	KUNIT_EXPECT_EQ(test,
927 			be16_to_cpu(mock_env->str1.length),
928 			be16_to_cpu(mock_env->str2.length));
929 
930 	free_mock_str_env(mock_env);
931 	free_mock_sb(mock_sb);
932 }
933 
934 /* Mock dentry for testing hfsplus_hash_dentry */
935 static struct dentry test_dentry;
936 
937 static void setup_mock_dentry(struct super_block *sb)
938 {
939 	memset(&test_dentry, 0, sizeof(test_dentry));
940 	test_dentry.d_sb = sb;
941 }
942 
943 /* Helper function to create qstr */
944 static void create_qstr(struct qstr *str, const char *name)
945 {
946 	str->name = name;
947 	str->len = strlen(name);
948 	str->hash = 0; /* Will be set by hash function */
949 }
950 
951 /* Test hfsplus_hash_dentry basic functionality */
952 static void hfsplus_hash_dentry_basic_test(struct kunit *test)
953 {
954 	struct test_mock_sb *mock_sb;
955 	struct qstr str1, str2;
956 	int result;
957 
958 	mock_sb = setup_mock_sb();
959 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
960 
961 	setup_mock_dentry(&mock_sb->sb);
962 	mock_sb->nls.char2uni = test_char2uni;
963 
964 	/* Test basic string hashing */
965 	create_qstr(&str1, "hello");
966 	result = hfsplus_hash_dentry(&test_dentry, &str1);
967 
968 	KUNIT_EXPECT_EQ(test, 0, result);
969 	KUNIT_EXPECT_NE(test, 0, str1.hash);
970 
971 	/* Test that identical strings produce identical hashes */
972 	create_qstr(&str2, "hello");
973 	result = hfsplus_hash_dentry(&test_dentry, &str2);
974 
975 	KUNIT_EXPECT_EQ(test, 0, result);
976 	KUNIT_EXPECT_EQ(test, str1.hash, str2.hash);
977 
978 	/* Test empty string */
979 	create_qstr(&str1, "");
980 	result = hfsplus_hash_dentry(&test_dentry, &str1);
981 
982 	/* Empty string should still produce a hash */
983 	KUNIT_EXPECT_EQ(test, 0, result);
984 
985 	/* Test single character */
986 	create_qstr(&str1, "A");
987 	result = hfsplus_hash_dentry(&test_dentry, &str1);
988 
989 	KUNIT_EXPECT_EQ(test, 0, result);
990 	KUNIT_EXPECT_NE(test, 0, str1.hash);
991 
992 	free_mock_sb(mock_sb);
993 }
994 
995 /* Test case folding behavior in hash */
996 static void hfsplus_hash_dentry_casefold_test(struct kunit *test)
997 {
998 	struct test_mock_sb *mock_sb;
999 	struct qstr str1, str2;
1000 	int result;
1001 
1002 	mock_sb = setup_mock_sb();
1003 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1004 
1005 	setup_mock_dentry(&mock_sb->sb);
1006 	mock_sb->nls.char2uni = test_char2uni;
1007 
1008 	/* Test with case folding disabled (default) */
1009 	clear_bit(HFSPLUS_SB_CASEFOLD, &mock_sb->sb_info.flags);
1010 
1011 	create_qstr(&str1, "Hello");
1012 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1013 	KUNIT_EXPECT_EQ(test, 0, result);
1014 
1015 	create_qstr(&str2, "hello");
1016 	result = hfsplus_hash_dentry(&test_dentry, &str2);
1017 	KUNIT_EXPECT_EQ(test, 0, result);
1018 
1019 	/*
1020 	 * Without case folding, different cases
1021 	 * should produce different hashes
1022 	 */
1023 	KUNIT_EXPECT_NE(test, str1.hash, str2.hash);
1024 
1025 	/* Test with case folding enabled */
1026 	set_bit(HFSPLUS_SB_CASEFOLD, &mock_sb->sb_info.flags);
1027 
1028 	create_qstr(&str1, "Hello");
1029 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1030 	KUNIT_EXPECT_EQ(test, 0, result);
1031 
1032 	create_qstr(&str2, "hello");
1033 	result = hfsplus_hash_dentry(&test_dentry, &str2);
1034 	KUNIT_EXPECT_EQ(test, 0, result);
1035 
1036 	/* With case folding, different cases should produce same hash */
1037 	KUNIT_EXPECT_EQ(test, str1.hash, str2.hash);
1038 
1039 	/* Test mixed case */
1040 	create_qstr(&str1, "HeLLo");
1041 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1042 	KUNIT_EXPECT_EQ(test, 0, result);
1043 	KUNIT_EXPECT_EQ(test, str1.hash, str2.hash);
1044 
1045 	free_mock_sb(mock_sb);
1046 }
1047 
1048 /* Test special character handling in hash */
1049 static void hfsplus_hash_dentry_special_chars_test(struct kunit *test)
1050 {
1051 	struct test_mock_sb *mock_sb;
1052 	struct qstr str1, str2;
1053 	int result;
1054 
1055 	mock_sb = setup_mock_sb();
1056 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1057 
1058 	setup_mock_dentry(&mock_sb->sb);
1059 	mock_sb->nls.char2uni = test_char2uni;
1060 
1061 	/* Test colon conversion (: becomes /) */
1062 	create_qstr(&str1, "file:name");
1063 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1064 	KUNIT_EXPECT_EQ(test, 0, result);
1065 
1066 	create_qstr(&str2, "file/name");
1067 	result = hfsplus_hash_dentry(&test_dentry, &str2);
1068 	KUNIT_EXPECT_EQ(test, 0, result);
1069 
1070 	/* After conversion, these should produce the same hash */
1071 	KUNIT_EXPECT_EQ(test, str1.hash, str2.hash);
1072 
1073 	/* Test multiple special characters */
1074 	create_qstr(&str1, ":::");
1075 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1076 	KUNIT_EXPECT_EQ(test, 0, result);
1077 
1078 	create_qstr(&str2, "///");
1079 	result = hfsplus_hash_dentry(&test_dentry, &str2);
1080 	KUNIT_EXPECT_EQ(test, 0, result);
1081 
1082 	KUNIT_EXPECT_EQ(test, str1.hash, str2.hash);
1083 
1084 	free_mock_sb(mock_sb);
1085 }
1086 
1087 /* Test decomposition flag behavior in hash */
1088 static void hfsplus_hash_dentry_decompose_test(struct kunit *test)
1089 {
1090 	struct test_mock_sb *mock_sb;
1091 	struct qstr str1, str2;
1092 	int result;
1093 
1094 	mock_sb = setup_mock_sb();
1095 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1096 
1097 	setup_mock_dentry(&mock_sb->sb);
1098 	mock_sb->nls.char2uni = test_char2uni;
1099 
1100 	/* Test with decomposition disabled (default) */
1101 	clear_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
1102 
1103 	create_qstr(&str1, "test");
1104 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1105 	KUNIT_EXPECT_EQ(test, 0, result);
1106 
1107 	/* Test with decomposition enabled */
1108 	set_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
1109 
1110 	create_qstr(&str2, "test");
1111 	result = hfsplus_hash_dentry(&test_dentry, &str2);
1112 	KUNIT_EXPECT_EQ(test, 0, result);
1113 
1114 	/*
1115 	 * For simple ASCII, decomposition shouldn't change
1116 	 * the hash much but the function should still work correctly
1117 	 */
1118 	KUNIT_EXPECT_NE(test, 0, str2.hash);
1119 
1120 	free_mock_sb(mock_sb);
1121 }
1122 
1123 /* Test hash consistency and distribution */
1124 static void hfsplus_hash_dentry_consistency_test(struct kunit *test)
1125 {
1126 	struct test_mock_sb *mock_sb;
1127 	struct qstr str1, str2, str3;
1128 	unsigned long hash1;
1129 	int result;
1130 
1131 	mock_sb = setup_mock_sb();
1132 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1133 
1134 	setup_mock_dentry(&mock_sb->sb);
1135 	mock_sb->nls.char2uni = test_char2uni;
1136 
1137 	/* Test that same string always produces same hash */
1138 	create_qstr(&str1, "consistent");
1139 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1140 	KUNIT_EXPECT_EQ(test, 0, result);
1141 	hash1 = str1.hash;
1142 
1143 	create_qstr(&str2, "consistent");
1144 	result = hfsplus_hash_dentry(&test_dentry, &str2);
1145 	KUNIT_EXPECT_EQ(test, 0, result);
1146 
1147 	KUNIT_EXPECT_EQ(test, hash1, str2.hash);
1148 
1149 	/* Test that different strings produce different hashes */
1150 	create_qstr(&str3, "different");
1151 	result = hfsplus_hash_dentry(&test_dentry, &str3);
1152 	KUNIT_EXPECT_EQ(test, 0, result);
1153 
1154 	KUNIT_EXPECT_NE(test, str1.hash, str3.hash);
1155 
1156 	/* Test similar strings should have different hashes */
1157 	create_qstr(&str1, "file1");
1158 	result = hfsplus_hash_dentry(&test_dentry, &str1);
1159 	KUNIT_EXPECT_EQ(test, 0, result);
1160 
1161 	create_qstr(&str2, "file2");
1162 	result = hfsplus_hash_dentry(&test_dentry, &str2);
1163 	KUNIT_EXPECT_EQ(test, 0, result);
1164 
1165 	KUNIT_EXPECT_NE(test, str1.hash, str2.hash);
1166 
1167 	free_mock_sb(mock_sb);
1168 }
1169 
1170 /* Test edge cases and boundary conditions */
1171 static void hfsplus_hash_dentry_edge_cases_test(struct kunit *test)
1172 {
1173 	struct test_mock_sb *mock_sb;
1174 	struct test_mock_string_env *mock_env;
1175 	struct qstr str;
1176 	int result;
1177 
1178 	mock_env = setup_mock_str_env(HFSPLUS_MAX_STRLEN + 1);
1179 	KUNIT_ASSERT_NOT_NULL(test, mock_env);
1180 
1181 	mock_sb = setup_mock_sb();
1182 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1183 
1184 	setup_mock_dentry(&mock_sb->sb);
1185 	mock_sb->nls.char2uni = test_char2uni;
1186 
1187 	/* Test very long filename */
1188 	memset(mock_env->buf, 'a', mock_env->buf_size - 1);
1189 	mock_env->buf[mock_env->buf_size - 1] = '\0';
1190 
1191 	create_qstr(&str, mock_env->buf);
1192 	result = hfsplus_hash_dentry(&test_dentry, &str);
1193 
1194 	KUNIT_EXPECT_EQ(test, 0, result);
1195 	KUNIT_EXPECT_NE(test, 0, str.hash);
1196 
1197 	/* Test filename with all printable ASCII characters */
1198 	create_qstr(&str, "!@#$%^&*()_+-=[]{}|;':\",./<>?");
1199 	result = hfsplus_hash_dentry(&test_dentry, &str);
1200 
1201 	KUNIT_EXPECT_EQ(test, 0, result);
1202 	KUNIT_EXPECT_NE(test, 0, str.hash);
1203 
1204 	/* Test with embedded null (though not typical for filenames) */
1205 	str.name = "file\0hidden";
1206 	str.len = 11; /* Include the null and text after it */
1207 	str.hash = 0;
1208 	result = hfsplus_hash_dentry(&test_dentry, &str);
1209 
1210 	KUNIT_EXPECT_EQ(test, 0, result);
1211 	KUNIT_EXPECT_NE(test, 0, str.hash);
1212 
1213 	free_mock_str_env(mock_env);
1214 	free_mock_sb(mock_sb);
1215 }
1216 
1217 /* Test hfsplus_compare_dentry basic functionality */
1218 static void hfsplus_compare_dentry_basic_test(struct kunit *test)
1219 {
1220 	struct test_mock_sb *mock_sb;
1221 	struct qstr name;
1222 	int result;
1223 
1224 	mock_sb = setup_mock_sb();
1225 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1226 
1227 	setup_mock_dentry(&mock_sb->sb);
1228 	mock_sb->nls.char2uni = test_char2uni;
1229 
1230 	/* Test identical strings */
1231 	create_qstr(&name, "hello");
1232 	result = hfsplus_compare_dentry(&test_dentry, 5, "hello", &name);
1233 	KUNIT_EXPECT_EQ(test, 0, result);
1234 
1235 	/* Test different strings - lexicographic order */
1236 	create_qstr(&name, "world");
1237 	result = hfsplus_compare_dentry(&test_dentry, 5, "hello", &name);
1238 	KUNIT_EXPECT_LT(test, result, 0); /* "hello" < "world" */
1239 
1240 	result = hfsplus_compare_dentry(&test_dentry, 5, "world", &name);
1241 	KUNIT_EXPECT_EQ(test, 0, result);
1242 
1243 	create_qstr(&name, "hello");
1244 	result = hfsplus_compare_dentry(&test_dentry, 5, "world", &name);
1245 	KUNIT_EXPECT_GT(test, result, 0); /* "world" > "hello" */
1246 
1247 	/* Test empty strings */
1248 	create_qstr(&name, "");
1249 	result = hfsplus_compare_dentry(&test_dentry, 0, "", &name);
1250 	KUNIT_EXPECT_EQ(test, 0, result);
1251 
1252 	/* Test one empty, one non-empty */
1253 	create_qstr(&name, "test");
1254 	result = hfsplus_compare_dentry(&test_dentry, 0, "", &name);
1255 	KUNIT_EXPECT_LT(test, result, 0); /* "" < "test" */
1256 
1257 	create_qstr(&name, "");
1258 	result = hfsplus_compare_dentry(&test_dentry, 4, "test", &name);
1259 	KUNIT_EXPECT_GT(test, result, 0); /* "test" > "" */
1260 
1261 	free_mock_sb(mock_sb);
1262 }
1263 
1264 /* Test case folding behavior in comparison */
1265 static void hfsplus_compare_dentry_casefold_test(struct kunit *test)
1266 {
1267 	struct test_mock_sb *mock_sb;
1268 	struct qstr name;
1269 	int result;
1270 
1271 	mock_sb = setup_mock_sb();
1272 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1273 
1274 	setup_mock_dentry(&mock_sb->sb);
1275 	mock_sb->nls.char2uni = test_char2uni;
1276 
1277 	/* Test with case folding disabled (default) */
1278 	clear_bit(HFSPLUS_SB_CASEFOLD, &mock_sb->sb_info.flags);
1279 
1280 	create_qstr(&name, "hello");
1281 	result = hfsplus_compare_dentry(&test_dentry, 5, "Hello", &name);
1282 	/* Case sensitive: "Hello" != "hello" */
1283 	KUNIT_EXPECT_NE(test, 0, result);
1284 
1285 	create_qstr(&name, "Hello");
1286 	result = hfsplus_compare_dentry(&test_dentry, 5, "hello", &name);
1287 	/* Case sensitive: "hello" != "Hello" */
1288 	KUNIT_EXPECT_NE(test, 0, result);
1289 
1290 	/* Test with case folding enabled */
1291 	set_bit(HFSPLUS_SB_CASEFOLD, &mock_sb->sb_info.flags);
1292 
1293 	create_qstr(&name, "hello");
1294 	result = hfsplus_compare_dentry(&test_dentry, 5, "Hello", &name);
1295 	/* Case insensitive: "Hello" == "hello" */
1296 	KUNIT_EXPECT_EQ(test, 0, result);
1297 
1298 	create_qstr(&name, "Hello");
1299 	result = hfsplus_compare_dentry(&test_dentry, 5, "hello", &name);
1300 	/* Case insensitive: "hello" == "Hello" */
1301 	KUNIT_EXPECT_EQ(test, 0, result);
1302 
1303 	/* Test mixed case */
1304 	create_qstr(&name, "TeSt");
1305 	result = hfsplus_compare_dentry(&test_dentry, 4, "test", &name);
1306 	KUNIT_EXPECT_EQ(test, 0, result);
1307 
1308 	create_qstr(&name, "test");
1309 	result = hfsplus_compare_dentry(&test_dentry, 4, "TEST", &name);
1310 	KUNIT_EXPECT_EQ(test, 0, result);
1311 
1312 	free_mock_sb(mock_sb);
1313 }
1314 
1315 /* Test special character handling in comparison */
1316 static void hfsplus_compare_dentry_special_chars_test(struct kunit *test)
1317 {
1318 	struct test_mock_sb *mock_sb;
1319 	struct qstr name;
1320 	int result;
1321 
1322 	mock_sb = setup_mock_sb();
1323 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1324 
1325 	setup_mock_dentry(&mock_sb->sb);
1326 	mock_sb->nls.char2uni = test_char2uni;
1327 
1328 	/* Test colon conversion (: becomes /) */
1329 	create_qstr(&name, "file/name");
1330 	result = hfsplus_compare_dentry(&test_dentry, 9, "file:name", &name);
1331 	/* "file:name" == "file/name" after conversion */
1332 	KUNIT_EXPECT_EQ(test, 0, result);
1333 
1334 	create_qstr(&name, "file:name");
1335 	result = hfsplus_compare_dentry(&test_dentry, 9, "file/name", &name);
1336 	/* "file/name" == "file:name" after conversion */
1337 	KUNIT_EXPECT_EQ(test, 0, result);
1338 
1339 	/* Test multiple special characters */
1340 	create_qstr(&name, "///");
1341 	result = hfsplus_compare_dentry(&test_dentry, 3, ":::", &name);
1342 	KUNIT_EXPECT_EQ(test, 0, result);
1343 
1344 	/* Test mixed special and regular characters */
1345 	create_qstr(&name, "a/b:c");
1346 	result = hfsplus_compare_dentry(&test_dentry, 5, "a:b/c", &name);
1347 	/* Both become "a/b/c" after conversion */
1348 	KUNIT_EXPECT_EQ(test, 0, result);
1349 
1350 	free_mock_sb(mock_sb);
1351 }
1352 
1353 /* Test length differences */
1354 static void hfsplus_compare_dentry_length_test(struct kunit *test)
1355 {
1356 	struct test_mock_sb *mock_sb;
1357 	struct qstr name;
1358 	int result;
1359 
1360 	mock_sb = setup_mock_sb();
1361 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1362 
1363 	setup_mock_dentry(&mock_sb->sb);
1364 	mock_sb->nls.char2uni = test_char2uni;
1365 
1366 	/* Test different lengths with common prefix */
1367 	create_qstr(&name, "testing");
1368 	result = hfsplus_compare_dentry(&test_dentry, 4, "test", &name);
1369 	KUNIT_EXPECT_LT(test, result, 0); /* "test" < "testing" */
1370 
1371 	create_qstr(&name, "test");
1372 	result = hfsplus_compare_dentry(&test_dentry, 7, "testing", &name);
1373 	KUNIT_EXPECT_GT(test, result, 0); /* "testing" > "test" */
1374 
1375 	/* Test exact length match */
1376 	create_qstr(&name, "exact");
1377 	result = hfsplus_compare_dentry(&test_dentry, 5, "exact", &name);
1378 	KUNIT_EXPECT_EQ(test, 0, result);
1379 
1380 	/* Test length parameter vs actual string content */
1381 	create_qstr(&name, "hello");
1382 	result = hfsplus_compare_dentry(&test_dentry, 3, "hel", &name);
1383 	KUNIT_EXPECT_LT(test, result, 0); /* "hel" < "hello" */
1384 
1385 	/* Test longer first string but shorter length parameter */
1386 	create_qstr(&name, "hi");
1387 	result = hfsplus_compare_dentry(&test_dentry, 2, "hello", &name);
1388 	/* "he" < "hi" (only first 2 chars compared) */
1389 	KUNIT_EXPECT_LT(test, result, 0);
1390 
1391 	free_mock_sb(mock_sb);
1392 }
1393 
1394 /* Test decomposition flag behavior */
1395 static void hfsplus_compare_dentry_decompose_test(struct kunit *test)
1396 {
1397 	struct test_mock_sb *mock_sb;
1398 	struct qstr name;
1399 	int result;
1400 
1401 	mock_sb = setup_mock_sb();
1402 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1403 
1404 	setup_mock_dentry(&mock_sb->sb);
1405 	mock_sb->nls.char2uni = test_char2uni;
1406 
1407 	/* Test with decomposition disabled (default) */
1408 	clear_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
1409 
1410 	create_qstr(&name, "test");
1411 	result = hfsplus_compare_dentry(&test_dentry, 4, "test", &name);
1412 	KUNIT_EXPECT_EQ(test, 0, result);
1413 
1414 	/* Test with decomposition enabled */
1415 	set_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
1416 
1417 	create_qstr(&name, "test");
1418 	result = hfsplus_compare_dentry(&test_dentry, 4, "test", &name);
1419 	KUNIT_EXPECT_EQ(test, 0, result);
1420 
1421 	/* For simple ASCII, decomposition shouldn't affect the result */
1422 	create_qstr(&name, "different");
1423 	result = hfsplus_compare_dentry(&test_dentry, 4, "test", &name);
1424 	KUNIT_EXPECT_NE(test, 0, result);
1425 
1426 	free_mock_sb(mock_sb);
1427 }
1428 
1429 /* Test edge cases and boundary conditions */
1430 static void hfsplus_compare_dentry_edge_cases_test(struct kunit *test)
1431 {
1432 	struct test_mock_sb *mock_sb;
1433 	struct qstr name;
1434 	char *long_str;
1435 	char *long_str2;
1436 	u32 str_size = HFSPLUS_MAX_STRLEN + 1;
1437 	struct qstr null_name = {
1438 		.name = "a\0b",
1439 		.len = 3,
1440 		.hash = 0
1441 	};
1442 	int result;
1443 
1444 	mock_sb = setup_mock_sb();
1445 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1446 
1447 	setup_mock_dentry(&mock_sb->sb);
1448 	mock_sb->nls.char2uni = test_char2uni;
1449 
1450 	long_str = kzalloc(str_size, GFP_KERNEL);
1451 	KUNIT_ASSERT_NOT_NULL(test, long_str);
1452 
1453 	long_str2 = kzalloc(str_size, GFP_KERNEL);
1454 	KUNIT_ASSERT_NOT_NULL(test, long_str2);
1455 
1456 	/* Test very long strings */
1457 	memset(long_str, 'a', str_size - 1);
1458 	long_str[str_size - 1] = '\0';
1459 
1460 	create_qstr(&name, long_str);
1461 	result = hfsplus_compare_dentry(&test_dentry, str_size - 1,
1462 					long_str, &name);
1463 	KUNIT_EXPECT_EQ(test, 0, result);
1464 
1465 	/* Test with difference at the end of long strings */
1466 	memset(long_str2, 'a', str_size - 1);
1467 	long_str2[str_size - 1] = '\0';
1468 	long_str2[str_size - 2] = 'b';
1469 	create_qstr(&name, long_str2);
1470 	result = hfsplus_compare_dentry(&test_dentry, str_size - 1,
1471 					long_str, &name);
1472 	KUNIT_EXPECT_LT(test, result, 0); /* 'a' < 'b' */
1473 
1474 	/* Test single character differences */
1475 	create_qstr(&name, "b");
1476 	result = hfsplus_compare_dentry(&test_dentry, 1, "a", &name);
1477 	KUNIT_EXPECT_LT(test, result, 0); /* 'a' < 'b' */
1478 
1479 	create_qstr(&name, "a");
1480 	result = hfsplus_compare_dentry(&test_dentry, 1, "b", &name);
1481 	KUNIT_EXPECT_GT(test, result, 0); /* 'b' > 'a' */
1482 
1483 	/* Test with null characters in the middle */
1484 	result = hfsplus_compare_dentry(&test_dentry, 3, "a\0b", &null_name);
1485 	KUNIT_EXPECT_EQ(test, 0, result);
1486 
1487 	/* Test all printable ASCII characters */
1488 	create_qstr(&name, "!@#$%^&*()");
1489 	result = hfsplus_compare_dentry(&test_dentry, 10, "!@#$%^&*()", &name);
1490 	KUNIT_EXPECT_EQ(test, 0, result);
1491 
1492 	kfree(long_str);
1493 	kfree(long_str2);
1494 	free_mock_sb(mock_sb);
1495 }
1496 
1497 /* Test combined flag behaviors */
1498 static void hfsplus_compare_dentry_combined_flags_test(struct kunit *test)
1499 {
1500 	struct test_mock_sb *mock_sb;
1501 	struct qstr name;
1502 	int result;
1503 
1504 	mock_sb = setup_mock_sb();
1505 	KUNIT_ASSERT_NOT_NULL(test, mock_sb);
1506 
1507 	setup_mock_dentry(&mock_sb->sb);
1508 	mock_sb->nls.char2uni = test_char2uni;
1509 
1510 	/* Test with both casefold and decompose enabled */
1511 	set_bit(HFSPLUS_SB_CASEFOLD, &mock_sb->sb_info.flags);
1512 	set_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
1513 
1514 	create_qstr(&name, "hello");
1515 	result = hfsplus_compare_dentry(&test_dentry, 5, "HELLO", &name);
1516 	KUNIT_EXPECT_EQ(test, 0, result);
1517 
1518 	/* Test special chars with case folding */
1519 	create_qstr(&name, "File/Name");
1520 	result = hfsplus_compare_dentry(&test_dentry, 9, "file:name", &name);
1521 	KUNIT_EXPECT_EQ(test, 0, result);
1522 
1523 	/* Test with both flags disabled */
1524 	clear_bit(HFSPLUS_SB_CASEFOLD, &mock_sb->sb_info.flags);
1525 	clear_bit(HFSPLUS_SB_NODECOMPOSE, &mock_sb->sb_info.flags);
1526 
1527 	create_qstr(&name, "hello");
1528 	result = hfsplus_compare_dentry(&test_dentry, 5, "HELLO", &name);
1529 	KUNIT_EXPECT_NE(test, 0, result); /* Case sensitive */
1530 
1531 	/* But special chars should still be converted */
1532 	create_qstr(&name, "file/name");
1533 	result = hfsplus_compare_dentry(&test_dentry, 9, "file:name", &name);
1534 	KUNIT_EXPECT_EQ(test, 0, result);
1535 
1536 	free_mock_sb(mock_sb);
1537 }
1538 
1539 static struct kunit_case hfsplus_unicode_test_cases[] = {
1540 	KUNIT_CASE(hfsplus_strcasecmp_test),
1541 	KUNIT_CASE(hfsplus_strcmp_test),
1542 	KUNIT_CASE(hfsplus_unicode_edge_cases_test),
1543 	KUNIT_CASE(hfsplus_unicode_boundary_test),
1544 	KUNIT_CASE(hfsplus_uni2asc_basic_test),
1545 	KUNIT_CASE(hfsplus_uni2asc_special_chars_test),
1546 	KUNIT_CASE(hfsplus_uni2asc_buffer_test),
1547 	KUNIT_CASE(hfsplus_uni2asc_corrupted_test),
1548 	KUNIT_CASE(hfsplus_uni2asc_edge_cases_test),
1549 	KUNIT_CASE(hfsplus_asc2uni_basic_test),
1550 	KUNIT_CASE(hfsplus_asc2uni_special_chars_test),
1551 	KUNIT_CASE(hfsplus_asc2uni_buffer_limits_test),
1552 	KUNIT_CASE(hfsplus_asc2uni_edge_cases_test),
1553 	KUNIT_CASE(hfsplus_asc2uni_decompose_test),
1554 	KUNIT_CASE(hfsplus_hash_dentry_basic_test),
1555 	KUNIT_CASE(hfsplus_hash_dentry_casefold_test),
1556 	KUNIT_CASE(hfsplus_hash_dentry_special_chars_test),
1557 	KUNIT_CASE(hfsplus_hash_dentry_decompose_test),
1558 	KUNIT_CASE(hfsplus_hash_dentry_consistency_test),
1559 	KUNIT_CASE(hfsplus_hash_dentry_edge_cases_test),
1560 	KUNIT_CASE(hfsplus_compare_dentry_basic_test),
1561 	KUNIT_CASE(hfsplus_compare_dentry_casefold_test),
1562 	KUNIT_CASE(hfsplus_compare_dentry_special_chars_test),
1563 	KUNIT_CASE(hfsplus_compare_dentry_length_test),
1564 	KUNIT_CASE(hfsplus_compare_dentry_decompose_test),
1565 	KUNIT_CASE(hfsplus_compare_dentry_edge_cases_test),
1566 	KUNIT_CASE(hfsplus_compare_dentry_combined_flags_test),
1567 	{}
1568 };
1569 
1570 static struct kunit_suite hfsplus_unicode_test_suite = {
1571 	.name = "hfsplus_unicode",
1572 	.test_cases = hfsplus_unicode_test_cases,
1573 };
1574 
1575 kunit_test_suite(hfsplus_unicode_test_suite);
1576 
1577 MODULE_DESCRIPTION("KUnit tests for HFS+ Unicode string operations");
1578 MODULE_LICENSE("GPL");
1579 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
1580