10 #include <CUnit/CUnit.h>
15 #include "string_operations.h"
20 int token_search_diff(
char* text,
char*
search,
unsigned int maxAllowedDiff,
21 size_t expectedMatchCount,
size_t expectedAdditionsCount,
size_t expectedRemovalsCount, ...) {
26 char* textCopy = g_strdup(text);
27 char* searchCopy = g_strdup(
search);
29 GArray* tokenizedText = tokenize(textCopy,
"^");
30 GArray* tokenizedSearch = tokenize(searchCopy,
"^");
32 GArray* matched = g_array_new(TRUE, FALSE,
sizeof (
size_t));
33 GArray* additions = g_array_new(TRUE, FALSE,
sizeof (
size_t));
34 GArray* removals = g_array_new(TRUE, FALSE,
sizeof (
size_t));
36 size_t textStartPosition = 0;
37 DiffResult* diffResult = findMatchAsDiffs(tokenizedText, tokenizedSearch, textStartPosition, 0, maxAllowedDiff, 1);
38 if(expectedAdditionsCount + expectedMatchCount + expectedRemovalsCount == 0) {
39 CU_ASSERT_PTR_NULL(diffResult);
40 result = diffResult != NULL;
43 CU_ASSERT_PTR_NOT_NULL(diffResult);
45 printf(
"null result unexpected\n");
50 GArray* matchedInfo = diffResult->matchedInfo;
52 size_t matchedCount = 0;
53 size_t additionCount = 0;
54 size_t removalCount = 0;
56 for (
size_t i=0; i<matchedInfo->len; i++) {
58 if (strcmp(diffInfo.diffType, DIFF_TYPE_ADDITION) == 0) {
59 additionCount += diffInfo.text.length;
60 for (
size_t j=diffInfo.text.start;
61 j<diffInfo.text.start + diffInfo.text.length;
63 g_array_append_val(additions, j);
65 if (strcmp(diffInfo.diffType, DIFF_TYPE_MATCH) == 0) {
66 for (
size_t j=diffInfo.text.start;
67 j<diffInfo.text.start + diffInfo.text.length;
69 g_array_append_val(matched, j);
70 matchedCount += diffInfo.text.length;
72 if (strcmp(diffInfo.diffType, DIFF_TYPE_REMOVAL) == 0) {
73 g_array_append_val(removals, diffInfo.text.start);
76 if (strcmp(diffInfo.diffType, DIFF_TYPE_REPLACE) == 0) {
77 additionCount += diffInfo.text.length;
78 for (
size_t j=diffInfo.text.start;
79 j<diffInfo.text.start + diffInfo.text.length;
81 g_array_append_val(additions, j);
83 g_array_append_val(removals, diffInfo.text.start);
86 CU_ASSERT_EQUAL(matchedCount, expectedMatchCount);
87 CU_ASSERT_EQUAL(additionCount, expectedAdditionsCount);
88 CU_ASSERT_EQUAL(removalCount, expectedRemovalsCount);
89 CU_ASSERT_EQUAL(matched->len, expectedMatchCount);
90 CU_ASSERT_EQUAL(additions->len, expectedAdditionsCount);
91 CU_ASSERT_EQUAL(removals->len, expectedRemovalsCount);
94 va_start(argptr, expectedRemovalsCount);
96 if (expectedMatchCount == matchedCount) {
97 if (expectedAdditionsCount == additionCount) {
98 if (expectedRemovalsCount == removalCount) {
102 for (i = 0; i < expectedMatchCount; i++) {
103 expected = va_arg(argptr,
int);
104 actual = g_array_index(matched,
size_t, i);
105 CU_ASSERT_EQUAL(actual, expected);
106 if (actual != expected) {
107 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"):\n", text,
search);
108 printf(
"matched[%ld] == %ld != %ld\n", i, actual, expected);
112 for (i = 0; i < expectedAdditionsCount; i++) {
113 expected = va_arg(argptr,
int);
114 actual = g_array_index(additions,
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(
"additions[%ld] == %ld != %ld\n", i, actual, expected);
122 for (i = 0; i < expectedRemovalsCount; i++) {
123 expected = va_arg(argptr,
int);
124 actual = g_array_index(removals,
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(
"removals[%ld] == %ld != %ld\n", i, actual, expected);
133 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"): removals(%zu) != expected(%ld)\n",
134 text,
search, removalCount, expectedRemovalsCount);
136 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"): additions(%zu) != expected(%ld)\n",
137 text,
search, additionCount, expectedAdditionsCount);
139 printf(
"ASSERT ERROR: findMatchAsDiffs(\"%s\", \"%s\"): matched(%zu) != expected(%ld)\n",
140 text,
search, matchedCount, expectedMatchCount);
148 diffResult_free(diffResult);
149 g_array_free(matched, TRUE);
150 g_array_free(additions, TRUE);
151 g_array_free(removals, TRUE);
153 g_array_free(tokenizedText, TRUE);
154 g_array_free(tokenizedSearch, TRUE);
162 void test_token_search_diffs() {
164 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"one",
168 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"bar",
172 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"two",
176 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"3^foo",
180 CU_ASSERT_FALSE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"",
185 CU_ASSERT_FALSE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"one^^foo^^bar^^3",
188 CU_ASSERT_FALSE(token_search_diff(
"^one^^two^^3^^bar",
"one^^3^3^^bar^^z^d^5",
191 CU_ASSERT_FALSE(token_search_diff(
"one^two^^three^^bas",
"one^^3^3^^bar^^z",
196 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^foo^^bar^",
"one^^foo^^bar",
204 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^z",
"one^^3^3^^5^^bar^^y^^z",
212 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^bar^z",
"one^^3^3^^bar^^z",
220 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^1^2^3^4^5^z",
"one^^1^2^3^4^5^4^z",
228 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^5^e",
"one^^3^bar^^4^e",
236 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^5^z",
"one^^3^bar^^4^a^^z",
244 CU_ASSERT_TRUE(token_search_diff(
"^one^^3^^bar^5^6^z",
"one^^3^bar^^4^^z",
252 CU_ASSERT_TRUE(token_search_diff(
"^one^^two^^3^^bar",
"one^^3^3^^bar^^z",
261 CU_ASSERT_TRUE(token_search_diff(
"^foo^^one^two^three^^bar",
"foo^1^two^three^bar",
269 CU_ASSERT_TRUE(token_search_diff(
"^foo^^one^bar^two^three^^bar",
"foo^1^two^three^bar",
277 CU_ASSERT_TRUE(token_search_diff(
"^foo^^one^two^three^^bar",
"foo^1^2^two^three^bar",
286 int token_search(
char* text,
char*
search,
size_t expectedStart) {
287 char* textCopy = g_strdup(text);
288 char* searchCopy = g_strdup(
search);
290 GArray* tokenizedText = tokenize(textCopy,
"^");
291 GArray* tokenizedSearch = tokenize(searchCopy,
"^");
293 size_t matchStart = 0;
294 size_t textStartPosition = 0;
295 DiffResult* diffResult = findMatchAsDiffs(tokenizedText, tokenizedSearch, textStartPosition, 0, 0, 1);
300 matched = diffResult->matchedInfo->len == 1;
301 matchStart = g_array_index(diffResult->matchedInfo,
DiffPoint, 0).start;
302 diffResult_free(diffResult);
304 CU_ASSERT_EQUAL(expectedStart, matchStart);
306 g_array_free(tokenizedText, TRUE);
307 g_array_free(tokenizedSearch, TRUE);
314 void test_token_search() {
315 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"one", 0));
316 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"bar", 4));
317 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"two", 1));
318 CU_ASSERT_TRUE(token_search(
"^one^^two^^3^^foo^^bar^",
"3^foo", 2));
320 CU_ASSERT_FALSE(token_search(
"^^",
"one", 0));
321 CU_ASSERT_FALSE(token_search(
"^one^",
"^^", 0));
323 CU_ASSERT_FALSE(token_search(
"^one^^two^^3^^foo^^bar^",
"3^^foo^two", 0));
325 CU_ASSERT_FALSE(token_search(
"^3^one^^two^^3^^foo^^bar^",
"3^^foo", 0));
326 CU_ASSERT_TRUE(token_search(
"one^^two^^3^^foo^^bar^",
"3^^foo", 2));
329 void test_matchNTokens(){
330 char* text = g_strdup(
"a.b.c.d.e.f.g");
331 char*
search = g_strdup(
"a.b.c.d.E.E.f.g");
333 GArray* textTokens = tokenize(text,
".");
334 GArray* searchTokens = tokenize(
search,
".");
336 CU_ASSERT_TRUE(matchNTokens(textTokens, 1, textTokens->len,
337 searchTokens, 1, searchTokens->len,
340 CU_ASSERT_TRUE(matchNTokens(textTokens, 5, textTokens->len,
341 searchTokens, 6, searchTokens->len,
344 CU_ASSERT_FALSE(matchNTokens(textTokens, 1, textTokens->len,
345 searchTokens, 1, searchTokens->len,
348 g_array_free(textTokens, TRUE);
349 g_array_free(searchTokens, TRUE);
354 void test_matchNTokensCorners(){
355 char* empty = g_strdup(
"....");
356 char*
search = g_strdup(
"a.b.c.d.E.E.f.g");
358 GArray* emptyTokens = tokenize(empty,
".");
359 GArray* secondTokens = tokenize(
search,
".");
361 CU_ASSERT_FALSE(matchNTokens(emptyTokens, 0, emptyTokens->len,
362 secondTokens, 1, secondTokens->len,
365 CU_ASSERT_FALSE(matchNTokens(emptyTokens, 5, emptyTokens->len,
366 secondTokens, 6, secondTokens->len,
369 CU_ASSERT_FALSE(matchNTokens(secondTokens, 0, secondTokens->len,
370 emptyTokens, 0, emptyTokens->len,
373 g_array_free(emptyTokens, TRUE);
374 g_array_free(secondTokens, TRUE);
379 int _test_lookForAdditions(
char* text,
char*
search,
380 int textPosition,
int searchPosition,
int maxAllowedDiff,
int minTrailingMatches,
381 size_t expectedTextPosition,
size_t expectedSearchPosition) {
382 char* testText = g_strdup(text);
383 char* testSearch = g_strdup(
search);
385 GArray* textTokens = tokenize(testText,
"^");
386 GArray* searchTokens = tokenize(testSearch,
"^");
389 int ret = lookForDiff(textTokens, searchTokens,
390 textPosition, searchPosition, maxAllowedDiff, minTrailingMatches,
394 if (result.search.start != expectedSearchPosition) {
395 printf(
"adds(%s,%s): result.search.start == %zu != %ld\n", text,
search,
396 result.search.start, expectedSearchPosition);
398 if (result.text.start != expectedTextPosition) {
399 printf(
"adds(%s,%s): result.text.start == %zu != %ld\n", text,
search,
400 result.text.start, expectedTextPosition);
403 CU_ASSERT_TRUE(result.search.start == expectedSearchPosition);
404 CU_ASSERT_TRUE(result.text.start == expectedTextPosition);
407 g_array_free(textTokens, TRUE);
408 g_array_free(searchTokens, TRUE);
415 int _test_lookForRemovals(
char* text,
char*
search,
416 int textPosition,
int searchPosition,
int maxAllowedDiff,
int minTrailingMatches,
417 size_t expectedTextPosition,
size_t expectedSearchPosition) {
418 char* testText = g_strdup(text);
419 char* testSearch = g_strdup(
search);
421 GArray* textTokens = tokenize(testText,
"^");
422 GArray* searchTokens = tokenize(testSearch,
"^");
425 int ret = lookForDiff(textTokens, searchTokens,
426 textPosition, searchPosition, maxAllowedDiff, minTrailingMatches,
430 if (result.search.start != expectedSearchPosition) {
431 printf(
"rems(%s,%s): result.search.start == %zu != %ld\n", text,
search,
432 result.search.start, expectedSearchPosition);
434 if (result.text.start != expectedTextPosition) {
435 printf(
"rems(%s,%s): result.text.start == %zu != %ld\n", text,
search,
436 result.text.start, expectedTextPosition);
439 CU_ASSERT_TRUE(result.search.start == expectedSearchPosition);
440 CU_ASSERT_TRUE(result.text.start == expectedTextPosition);
443 g_array_free(textTokens, TRUE);
444 g_array_free(searchTokens, TRUE);
450 void test_lookForReplacesNotOverflowing() {
451 int max = MAX_ALLOWED_DIFF_LENGTH+1;
452 int length =
max + 1;
453 char* testText = malloc((length)*2+1);
454 char* testSearch = malloc((length)*2+1);
456 char* ptr1 =testSearch;
457 char* ptr2 =testText;
458 for (
int i = 0; i<length; i++) {
468 int matchPosition = length;
469 *(testSearch + 2*(matchPosition-1))=
'm';
474 GArray* textTokens = tokenize(testText,
"^");
475 GArray* searchTokens = tokenize(testSearch,
"^");
478 CU_ASSERT_FALSE(lookForDiff(textTokens, searchTokens,
479 0, 0,
max, 1, &result));
481 g_array_free(textTokens, TRUE);
482 g_array_free(searchTokens, TRUE);
487 int _test_lookForReplaces(
char* text,
char*
search,
488 int textPosition,
int searchPosition,
int maxAllowedDiff,
int minTrailingMatches,
489 size_t expectedTextPosition,
size_t expectedSearchPosition) {
490 char* testText = g_strdup(text);
491 char* testSearch = g_strdup(
search);
493 GArray* textTokens = tokenize(testText,
"^");
494 GArray* searchTokens = tokenize(testSearch,
"^");
497 int ret = lookForDiff(textTokens, searchTokens,
498 textPosition, searchPosition, maxAllowedDiff, minTrailingMatches, &result);
501 if (result.search.start != expectedSearchPosition) {
502 printf(
"replS(%s,%s): result.search.start == %zu != %ld\n", text,
search,
503 result.search.start, expectedSearchPosition);
505 if (result.text.start != expectedTextPosition) {
506 printf(
"replS(%s,%s): result.text.start == %zu != %ld\n", text,
search,
507 result.text.start, expectedTextPosition);
510 CU_ASSERT_TRUE(result.search.start == expectedSearchPosition);
511 CU_ASSERT_TRUE(result.text.start == expectedTextPosition);
514 g_array_free(textTokens, TRUE);
515 g_array_free(searchTokens, TRUE);
522 void test_lookForAdditions() {
523 CU_ASSERT_TRUE(_test_lookForAdditions(
529 CU_ASSERT_FALSE(_test_lookForAdditions(
530 "one^two^three^four^five",
535 CU_ASSERT_FALSE(_test_lookForAdditions(
536 "one^two^three^four",
541 CU_ASSERT_TRUE(_test_lookForAdditions(
542 "1^d^a^test_starts_here^two^three",
543 "v^test_starts_here^^three",
547 CU_ASSERT_FALSE(_test_lookForAdditions(
548 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
549 "v^test_starts_here^^eight",
553 CU_ASSERT_FALSE(_test_lookForAdditions(
554 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
555 "v^test_starts_here^^seven",
560 void test_lookForRemovals() {
561 CU_ASSERT_TRUE(_test_lookForRemovals(
567 CU_ASSERT_FALSE(_test_lookForRemovals(
569 "one^two^three^four^five",
573 CU_ASSERT_FALSE(_test_lookForRemovals(
575 "five^two^three^four^five",
579 CU_ASSERT_TRUE(_test_lookForRemovals(
580 "1^d^a^test_starts_here^three",
581 "v^test_starts_here^two^three",
585 CU_ASSERT_FALSE(_test_lookForRemovals(
586 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
587 "v^test_starts_here^^eight",
591 CU_ASSERT_FALSE(_test_lookForRemovals(
592 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
593 "v^test_starts_here^^seven",
598 void test_lookForReplaces1() {
599 CU_ASSERT_TRUE(_test_lookForReplaces(
605 CU_ASSERT_TRUE(_test_lookForReplaces(
611 CU_ASSERT_FALSE(_test_lookForReplaces(
612 "one^two^three^four^five",
617 CU_ASSERT_TRUE(_test_lookForReplaces(
618 "1^d^a^test_starts_here^one^three",
619 "v^test_starts_here^two^three",
623 CU_ASSERT_FALSE(_test_lookForReplaces(
624 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
625 "v^test_starts_here^^eight",
629 CU_ASSERT_FALSE(_test_lookForReplaces(
630 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
631 "v^test_starts_here^^seven",
635 CU_ASSERT_TRUE(_test_lookForReplaces(
641 CU_ASSERT_TRUE(_test_lookForReplaces(
647 CU_ASSERT_FALSE(_test_lookForReplaces(
649 "eins^zwei^drei^vier^five",
653 CU_ASSERT_TRUE(_test_lookForReplaces(
654 "1^d^a^test_starts_here^one^three",
655 "v^test_starts_here^two^three",
659 CU_ASSERT_FALSE(_test_lookForReplaces(
660 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
661 "v^test_starts_here^^eight",
665 CU_ASSERT_FALSE(_test_lookForReplaces(
666 "1^d^a^test_starts_here^two^three^four^five^six^seven^",
667 "v^test_starts_here^^seven",
672 void test_lookForReplaces2() {
674 CU_ASSERT_TRUE(_test_lookForReplaces(
675 "0^a^a^a^1^2^3^4^1^5",
679 CU_ASSERT_FALSE(token_search_diff(
680 "0^a^a^a^1^2^3^4^1^5",
686 CU_TestInfo diff_testcases[] = {
687 {
"Testing token search:", test_token_search},
688 {
"Testing token diff functions, additions:", test_lookForAdditions},
689 {
"Testing token diff functions, removals:", test_lookForRemovals},
690 {
"Testing token diff functions, replaces:", test_lookForReplaces1},
691 {
"Testing token diff functions, replaces complex cases:", test_lookForReplaces2},
692 {
"Testing token diff functions, replaces correctly handles max diff: ", test_lookForReplacesNotOverflowing},
693 {
"Testing token diff functions, matchNTokens:", test_matchNTokens},
694 {
"Testing token diff functions, matchNTokens corner cases:", test_matchNTokensCorners},
695 {
"Testing token search_diffs:", test_token_search_diffs},
FUNCTION int max(int permGroup, int permPublic)
Get the maximum group privilege.