20 #include <CUnit/CUnit.h> 25 #include "string_operations.h" 30 int token_search_diff(
char* text,
char*
search,
unsigned int maxAllowedDiff,
31 size_t expectedMatchCount,
size_t expectedAdditionsCount,
size_t expectedRemovalsCount, ...) {
36 char* textCopy = g_strdup(text);
37 char* searchCopy = g_strdup(search);
39 GArray* tokenizedText = tokenize(textCopy,
"^");
40 GArray* tokenizedSearch = tokenize(searchCopy,
"^");
42 GArray* matched = g_array_new(TRUE, FALSE,
sizeof (
size_t));
43 GArray* additions = g_array_new(TRUE, FALSE,
sizeof (
size_t));
44 GArray* removals = g_array_new(TRUE, FALSE,
sizeof (
size_t));
46 size_t textStartPosition = 0;
47 DiffResult* diffResult = findMatchAsDiffs(tokenizedText, tokenizedSearch, textStartPosition, 0, maxAllowedDiff, 1);
48 if(expectedAdditionsCount + expectedMatchCount + expectedRemovalsCount == 0) {
49 CU_ASSERT_PTR_NULL(diffResult);
50 result = diffResult != NULL;
53 CU_ASSERT_PTR_NOT_NULL(diffResult);
55 printf(
"null result unexpected\n");
60 GArray* matchedInfo = diffResult->matchedInfo;
62 size_t matchedCount = 0;
63 size_t additionCount = 0;
64 size_t removalCount = 0;
66 for (
size_t i=0; i<matchedInfo->len; i++) {
68 if (strcmp(diffInfo.diffType, DIFF_TYPE_ADDITION) == 0) {
69 additionCount += diffInfo.text.length;
70 for (
size_t j=diffInfo.text.start;
71 j<diffInfo.text.start + diffInfo.text.length;
73 g_array_append_val(additions, j);
75 if (strcmp(diffInfo.diffType, DIFF_TYPE_MATCH) == 0) {
76 for (
size_t j=diffInfo.text.start;
77 j<diffInfo.text.start + diffInfo.text.length;
79 g_array_append_val(matched, j);
80 matchedCount += diffInfo.text.length;
82 if (strcmp(diffInfo.diffType, DIFF_TYPE_REMOVAL) == 0) {
83 g_array_append_val(removals, diffInfo.text.start);
86 if (strcmp(diffInfo.diffType, DIFF_TYPE_REPLACE) == 0) {
87 additionCount += diffInfo.text.length;
88 for (
size_t j=diffInfo.text.start;
89 j<diffInfo.text.start + diffInfo.text.length;
91 g_array_append_val(additions, j);
93 g_array_append_val(removals, diffInfo.text.start);
96 CU_ASSERT_EQUAL(matchedCount, expectedMatchCount);
97 CU_ASSERT_EQUAL(additionCount, expectedAdditionsCount);
98 CU_ASSERT_EQUAL(removalCount, expectedRemovalsCount);
99 CU_ASSERT_EQUAL(matched->len, expectedMatchCount);
100 CU_ASSERT_EQUAL(additions->len, expectedAdditionsCount);
101 CU_ASSERT_EQUAL(removals->len, expectedRemovalsCount);
104 va_start(argptr, expectedRemovalsCount);
106 if (expectedMatchCount == matchedCount) {
107 if (expectedAdditionsCount == additionCount) {
108 if (expectedRemovalsCount == removalCount) {
112 for (i = 0; i < expectedMatchCount; i++) {
113 expected = va_arg(argptr,
int);
114 actual = g_array_index(matched,
size_t, i);
115 CU_ASSERT_EQUAL(actual, expected);
116 if (actual != expected) {
117 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"):\n", text, search);
118 printf(
"matched[%ld] == %ld != %ld\n", i, actual, expected);
122 for (i = 0; i < expectedAdditionsCount; i++) {
123 expected = va_arg(argptr,
int);
124 actual = g_array_index(additions,
size_t, i);
125 CU_ASSERT_EQUAL(actual, expected);
126 if (actual != expected) {
127 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"):\n", text, search);
128 printf(
"additions[%ld] == %ld != %ld\n", i, actual, expected);
132 for (i = 0; i < expectedRemovalsCount; i++) {
133 expected = va_arg(argptr,
int);
134 actual = g_array_index(removals,
size_t, i);
135 CU_ASSERT_EQUAL(actual, expected);
136 if (actual != expected) {
137 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"):\n", text, search);
138 printf(
"removals[%ld] == %ld != %ld\n", i, actual, expected);
143 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"): removals(%zu) != expected(%ld)\n",
144 text, search, removalCount, expectedRemovalsCount);
146 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"): additions(%zu) != expected(%ld)\n",
147 text, search, additionCount, expectedAdditionsCount);
149 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"): matched(%zu) != expected(%ld)\n",
150 text, search, matchedCount, expectedMatchCount);
158 diffResult_free(diffResult);
159 g_array_free(matched, TRUE);
160 g_array_free(additions, TRUE);
161 g_array_free(removals, TRUE);
163 g_array_free(tokenizedText, TRUE);
164 g_array_free(tokenizedSearch, TRUE);
172 void test_token_search_diffs() {
174 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"one",
178 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"bar",
182 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"two",
186 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"3^foo",
190 CU_ASSERT_FALSE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"",
195 CU_ASSERT_FALSE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"one^^foo^^bar^^3",
198 CU_ASSERT_FALSE(token_search_diff(
"^one^^two^^3^^bar",
"one^^3^3^^bar^^z^d^5",
201 CU_ASSERT_FALSE(token_search_diff(
"one^two^^three^^bas",
"one^^3^3^^bar^^z",
206 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"one^^foo^^bar",
214 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^z",
"one^^3^3^^5^^bar^^y^^z",
222 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^bar^z",
"one^^3^3^^bar^^z",
230 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^1^2^3^4^5^z",
"one^^1^2^3^4^5^4^z",
238 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^5^e",
"one^^3^bar^^4^e",
246 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^5^z",
"one^^3^bar^^4^a^^z",
254 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^5^6^z",
"one^^3^bar^^4^^z",
262 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^bar",
"one^^3^3^^bar^^z",
271 CU_ASSERT_TRUE(token_search_diff(
"^foo^^one^two^three^^bar",
"foo^1^two^three^bar",
279 CU_ASSERT_TRUE(token_search_diff(
"^foo^^one^bar^two^three^^bar",
"foo^1^two^three^bar",
287 CU_ASSERT_TRUE(token_search_diff(
"^foo^^one^two^three^^bar",
"foo^1^2^two^three^bar",
296 int token_search(
char* text,
char* search,
size_t expectedStart) {
297 char* textCopy = g_strdup(text);
298 char* searchCopy = g_strdup(search);
300 GArray* tokenizedText = tokenize(textCopy,
"^");
301 GArray* tokenizedSearch = tokenize(searchCopy,
"^");
303 size_t matchStart = 0;
304 size_t textStartPosition = 0;
305 DiffResult* diffResult = findMatchAsDiffs(tokenizedText, tokenizedSearch, textStartPosition, 0, 0, 1);
310 matched = diffResult->matchedInfo->len == 1;
311 matchStart = g_array_index(diffResult->matchedInfo,
DiffPoint, 0).start;
312 diffResult_free(diffResult);
314 CU_ASSERT_EQUAL(expectedStart, matchStart);
316 g_array_free(tokenizedText, TRUE);
317 g_array_free(tokenizedSearch, TRUE);
324 void test_token_search() {
325 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"one", 0));
326 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"bar", 4));
327 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"two", 1));
328 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"3^foo", 2));
330 CU_ASSERT_FALSE(token_search(
"^^",
"one", 0));
331 CU_ASSERT_FALSE(token_search(
"^one^",
"^^", 0));
333 CU_ASSERT_FALSE(token_search(
"^one^^two^^3^^foo^^bar^",
"3^^foo^two", 0));
335 CU_ASSERT_FALSE(token_search(
"^3^one^^two^^3^^foo^^bar^",
"3^^foo", 0));
336 CU_ASSERT_TRUE(token_search(
"one^^two^^3^^foo^^bar^",
"3^^foo", 2));
339 void test_matchNTokens(){
340 char* text = g_strdup(
"a.b.c.d.e.f.g");
341 char* search = g_strdup(
"a.b.c.d.E.E.f.g");
343 GArray* textTokens = tokenize(text,
".");
344 GArray* searchTokens = tokenize(search,
".");
346 CU_ASSERT_TRUE(matchNTokens(textTokens, 1, textTokens->len,
347 searchTokens, 1, searchTokens->len,
350 CU_ASSERT_TRUE(matchNTokens(textTokens, 5, textTokens->len,
351 searchTokens, 6, searchTokens->len,
354 CU_ASSERT_FALSE(matchNTokens(textTokens, 1, textTokens->len,
355 searchTokens, 1, searchTokens->len,
358 g_array_free(textTokens, TRUE);
359 g_array_free(searchTokens, TRUE);
364 void test_matchNTokensCorners(){
365 char* empty = g_strdup(
"....");
366 char* search = g_strdup(
"a.b.c.d.E.E.f.g");
368 GArray* emptyTokens = tokenize(empty,
".");
369 GArray* secondTokens = tokenize(search,
".");
371 CU_ASSERT_FALSE(matchNTokens(emptyTokens, 0, emptyTokens->len,
372 secondTokens, 1, secondTokens->len,
375 CU_ASSERT_FALSE(matchNTokens(emptyTokens, 5, emptyTokens->len,
376 secondTokens, 6, secondTokens->len,
379 CU_ASSERT_FALSE(matchNTokens(secondTokens, 0, secondTokens->len,
380 emptyTokens, 0, emptyTokens->len,
383 g_array_free(emptyTokens, TRUE);
384 g_array_free(secondTokens, TRUE);
389 int _test_lookForAdditions(
char* text,
char* search,
390 int textPosition,
int searchPosition,
int maxAllowedDiff,
int minTrailingMatches,
391 int expectedTextPosition,
int expectedSearchPosition) {
392 char* testText = g_strdup(text);
393 char* testSearch = g_strdup(search);
395 GArray* textTokens = tokenize(testText,
"^");
396 GArray* searchTokens = tokenize(testSearch,
"^");
399 int ret = lookForDiff(textTokens, searchTokens,
400 textPosition, searchPosition, maxAllowedDiff, minTrailingMatches,
404 if (result.search.start != expectedSearchPosition) {
405 printf(
"adds(%s,%s): result.search.start == %zu != %d\n", text, search,
406 result.search.start, expectedSearchPosition);
408 if (result.text.start != expectedTextPosition) {
409 printf(
"adds(%s,%s): result.text.start == %zu != %d\n", text, search,
410 result.text.start, expectedTextPosition);
413 CU_ASSERT_TRUE(result.search.start == expectedSearchPosition);
414 CU_ASSERT_TRUE(result.text.start == expectedTextPosition);
417 g_array_free(textTokens, TRUE);
418 g_array_free(searchTokens, TRUE);
425 int _test_lookForRemovals(
char* text,
char* search,
426 int textPosition,
int searchPosition,
int maxAllowedDiff,
int minTrailingMatches,
427 int expectedTextPosition,
int expectedSearchPosition) {
428 char* testText = g_strdup(text);
429 char* testSearch = g_strdup(search);
431 GArray* textTokens = tokenize(testText,
"^");
432 GArray* searchTokens = tokenize(testSearch,
"^");
435 int ret = lookForDiff(textTokens, searchTokens,
436 textPosition, searchPosition, maxAllowedDiff, minTrailingMatches,
440 if (result.search.start != expectedSearchPosition) {
441 printf(
"rems(%s,%s): result.search.start == %zu != %d\n", text, search,
442 result.search.start, expectedSearchPosition);
444 if (result.text.start != expectedTextPosition) {
445 printf(
"rems(%s,%s): result.text.start == %zu != %d\n", text, search,
446 result.text.start, expectedTextPosition);
449 CU_ASSERT_TRUE(result.search.start == expectedSearchPosition);
450 CU_ASSERT_TRUE(result.text.start == expectedTextPosition);
453 g_array_free(textTokens, TRUE);
454 g_array_free(searchTokens, TRUE);
460 void test_lookForReplacesNotOverflowing() {
461 int max = MAX_ALLOWED_DIFF_LENGTH+1;
462 int length = max + 1;
463 char* testText = malloc((length)*2+1);
464 char* testSearch = malloc((length)*2+1);
466 char* ptr1 =testSearch;
467 char* ptr2 =testText;
468 for (
int i = 0; i<length; i++) {
478 int matchPosition = length;
479 *(testSearch + 2*(matchPosition-1))=
'm';
484 GArray* textTokens = tokenize(testText,
"^");
485 GArray* searchTokens = tokenize(testSearch,
"^");
488 CU_ASSERT_FALSE(lookForDiff(textTokens, searchTokens,
489 0, 0, max, 1, &result));
491 g_array_free(textTokens, TRUE);
492 g_array_free(searchTokens, TRUE);
497 int _test_lookForReplaces(
char* text,
char* search,
498 int textPosition,
int searchPosition,
int maxAllowedDiff,
int minTrailingMatches,
499 int expectedTextPosition,
int expectedSearchPosition) {
500 char* testText = g_strdup(text);
501 char* testSearch = g_strdup(search);
503 GArray* textTokens = tokenize(testText,
"^");
504 GArray* searchTokens = tokenize(testSearch,
"^");
507 int ret = lookForDiff(textTokens, searchTokens,
508 textPosition, searchPosition, maxAllowedDiff, minTrailingMatches, &result);
511 if (result.search.start != expectedSearchPosition) {
512 printf(
"replS(%s,%s): result.search.start == %zu != %d\n", text, search,
513 result.search.start, expectedSearchPosition);
515 if (result.text.start != expectedTextPosition) {
516 printf(
"replS(%s,%s): result.text.start == %zu != %d\n", text, search,
517 result.text.start, expectedTextPosition);
520 CU_ASSERT_TRUE(result.search.start == expectedSearchPosition);
521 CU_ASSERT_TRUE(result.text.start == expectedTextPosition);
524 g_array_free(textTokens, TRUE);
525 g_array_free(searchTokens, TRUE);
532 void test_lookForAdditions() {
533 CU_ASSERT_TRUE(_test_lookForAdditions(
539 CU_ASSERT_FALSE(_test_lookForAdditions(
540 "one^two^three^four^five",
545 CU_ASSERT_FALSE(_test_lookForAdditions(
546 "one^two^three^four",
551 CU_ASSERT_TRUE(_test_lookForAdditions(
552 "1^d^a^test_starts_here^two^three",
553 "v^test_starts_here^^three",
557 CU_ASSERT_FALSE(_test_lookForAdditions(
558 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
559 "v^test_starts_here^^eight",
563 CU_ASSERT_FALSE(_test_lookForAdditions(
564 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
565 "v^test_starts_here^^seven",
570 void test_lookForRemovals() {
571 CU_ASSERT_TRUE(_test_lookForRemovals(
577 CU_ASSERT_FALSE(_test_lookForRemovals(
579 "one^two^three^four^five",
583 CU_ASSERT_FALSE(_test_lookForRemovals(
585 "five^two^three^four^five",
589 CU_ASSERT_TRUE(_test_lookForRemovals(
590 "1^d^a^test_starts_here^three",
591 "v^test_starts_here^two^three",
595 CU_ASSERT_FALSE(_test_lookForRemovals(
596 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
597 "v^test_starts_here^^eight",
601 CU_ASSERT_FALSE(_test_lookForRemovals(
602 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
603 "v^test_starts_here^^seven",
608 void test_lookForReplaces1() {
609 CU_ASSERT_TRUE(_test_lookForReplaces(
615 CU_ASSERT_TRUE(_test_lookForReplaces(
621 CU_ASSERT_FALSE(_test_lookForReplaces(
622 "one^two^three^four^five",
627 CU_ASSERT_TRUE(_test_lookForReplaces(
628 "1^d^a^test_starts_here^one^three",
629 "v^test_starts_here^two^three",
633 CU_ASSERT_FALSE(_test_lookForReplaces(
634 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
635 "v^test_starts_here^^eight",
639 CU_ASSERT_FALSE(_test_lookForReplaces(
640 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
641 "v^test_starts_here^^seven",
645 CU_ASSERT_TRUE(_test_lookForReplaces(
651 CU_ASSERT_TRUE(_test_lookForReplaces(
657 CU_ASSERT_FALSE(_test_lookForReplaces(
659 "eins^zwei^drei^vier^five",
663 CU_ASSERT_TRUE(_test_lookForReplaces(
664 "1^d^a^test_starts_here^one^three",
665 "v^test_starts_here^two^three",
669 CU_ASSERT_FALSE(_test_lookForReplaces(
670 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
671 "v^test_starts_here^^eight",
675 CU_ASSERT_FALSE(_test_lookForReplaces(
676 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
677 "v^test_starts_here^^seven",
682 void test_lookForReplaces2() {
684 CU_ASSERT_TRUE(_test_lookForReplaces(
685 "0^a^a^a^1^2^3^4^1^5",
689 CU_ASSERT_FALSE(token_search_diff(
690 "0^a^a^a^1^2^3^4^1^5",
696 CU_TestInfo diff_testcases[] = {
697 {
"Testing token search:", test_token_search},
698 {
"Testing token diff functions, additions:", test_lookForAdditions},
699 {
"Testing token diff functions, removals:", test_lookForRemovals},
700 {
"Testing token diff functions, replaces:", test_lookForReplaces1},
701 {
"Testing token diff functions, replaces complex cases:", test_lookForReplaces2},
702 {
"Testing token diff functions, replaces correctly handles max diff: ", test_lookForReplacesNotOverflowing},
703 {
"Testing token diff functions, matchNTokens:", test_matchNTokens},
704 {
"Testing token diff functions, matchNTokens corner cases:", test_matchNTokensCorners},
705 {
"Testing token search_diffs:", test_token_search_diffs},
FUNCTION int max(int permGroup, int permPublic)
Get the maximum group privilege.