#include "utilities/UndoUtilities.h" #include "unittest/TestSuite.h" #include "stem_core.h" enum itemChangeType { CHANGE_TYPE_ADD, CHANGE_TYPE_REMOVE, CHANGE_TYPE_MODIFY }; struct itemChange { enum itemChangeType changeType; unsigned int index; int item; unsigned int compareResult; }; struct enumerateChangesContextStruct { unsigned int changeCount; struct itemChange * changes; }; static unsigned int compare(void * oldItemUntyped, void * newItemUntyped, void * context) { int * oldItem = oldItemUntyped, * newItem = newItemUntyped; if (*newItem < *oldItem) { return 1; } if (*newItem > *oldItem) { return 2; } return 0; } static void addChange(struct enumerateChangesContextStruct * contextStruct, enum itemChangeType changeType, unsigned int index, int item, unsigned int compareResult) { contextStruct->changes = realloc(contextStruct->changes, (contextStruct->changeCount + 1) * sizeof(*contextStruct->changes)); contextStruct->changes[contextStruct->changeCount].changeType = changeType; contextStruct->changes[contextStruct->changeCount].index = index; contextStruct->changes[contextStruct->changeCount].item = item; contextStruct->changes[contextStruct->changeCount].compareResult = compareResult; contextStruct->changeCount++; } static void itemAdded(unsigned int index, void * newItem, void * context) { addChange(context, CHANGE_TYPE_ADD, index, *(int *) newItem, 3); } static void itemRemoved(unsigned int index, void * oldItem, void * context) { addChange(context, CHANGE_TYPE_REMOVE, index, *(int *) oldItem, 3); } static void itemModified(unsigned int index, void * oldItem, void * newItem, unsigned int compareResult, void * context) { addChange(context, CHANGE_TYPE_MODIFY, index, *(int *) newItem ^ *(int *) oldItem, compareResult); } #define listArgs(number) oldList##number, sizeof(oldList##number) / sizeof(oldList##number[0]), newList##number, sizeof(newList##number) / sizeof(newList##number[0]), sizeof(oldList##number[0]) static void testEnumerateChangesBetweenOldAndNewLists(void) { struct enumerateChangesContextStruct contextStruct = {0, NULL}; int oldList1[] = {1, 2, 3}; int newList1[] = {1, 2, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(1), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 0); int oldList2[] = {1, 2, 3}; int newList2[] = {1, 4, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(2), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 2 ^ 4); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList3[] = {1, 2, 3}; int newList3[] = {2, 2, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(3), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 1 ^ 2); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList4[] = {1, 2, 3}; int newList4[] = {1, 2, 2}; enumerateChangesBetweenOldAndNewLists(listArgs(4), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 2); TestCase_assertIntEqual(contextStruct.changes[0].item, 3 ^ 2); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 1); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList5[] = {1, 2, 3}; int newList5[] = {1, 2, 4, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(5), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 2); TestCase_assertIntEqual(contextStruct.changes[0].item, 4); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList6[] = {1, 2, 3}; int newList6[] = {1, 2, 3, 4}; enumerateChangesBetweenOldAndNewLists(listArgs(6), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 3); TestCase_assertIntEqual(contextStruct.changes[0].item, 4); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList7[] = {1, 2, 3}; int newList7[] = {4, 1, 2, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(7), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 4); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList8[] = {1, 2, 3}; int newList8[] = {1, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(8), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 2); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList9[] = {1, 2, 3}; int newList9[] = {1, 2}; enumerateChangesBetweenOldAndNewLists(listArgs(9), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 2); TestCase_assertIntEqual(contextStruct.changes[0].item, 3); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList10[] = {1, 2, 3}; int newList10[] = {2, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(10), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 1); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList11[] = {1, 2, 3}; int newList11[] = {1, 5, 2, 6, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(11), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 4); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 2); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 5); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[2].index, 2); TestCase_assertIntEqual(contextStruct.changes[2].item, 2); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[3].index, 3); TestCase_assertIntEqual(contextStruct.changes[3].item, 6); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList12[] = {1, 5, 2, 6, 3}; int newList12[] = {1, 2, 3}; enumerateChangesBetweenOldAndNewLists(listArgs(12), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 4); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 5); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 2); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[2].index, 1); TestCase_assertIntEqual(contextStruct.changes[2].item, 6); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[3].index, 1); TestCase_assertIntEqual(contextStruct.changes[3].item, 2); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList13[] = {1, 2, 3}; int newList13[] = {4, 5}; enumerateChangesBetweenOldAndNewLists(listArgs(13), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 5); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 1); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 0); TestCase_assertIntEqual(contextStruct.changes[1].item, 2); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[2].index, 0); TestCase_assertIntEqual(contextStruct.changes[2].item, 3); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[3].index, 0); TestCase_assertIntEqual(contextStruct.changes[3].item, 4); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[4].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[4].index, 1); TestCase_assertIntEqual(contextStruct.changes[4].item, 5); TestCase_assertIntEqual(contextStruct.changes[4].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList14[] = {1, 2, 3}; int newList14[] = {4, 2, 5}; enumerateChangesBetweenOldAndNewLists(listArgs(14), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 1 ^ 4); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 3 ^ 5); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 2); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; int oldList15[] = {1, 2, 3, 4}; int newList15[] = {1, 5, 6, 4}; enumerateChangesBetweenOldAndNewLists(listArgs(15), compare, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 2 ^ 5); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 3 ^ 6); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 2); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } static bool compareIdentifiable(void * oldItemUntyped, void * newItemUntyped, unsigned int * outCompareResult, void * context) { int oldItem = *(int *) oldItemUntyped, newItem = *(int *) newItemUntyped; int oldItemIdentifier = oldItem >> 4, newItemIdentifier = newItem >> 4; int oldItemValue = oldItem & 0xF, newItemValue = newItem & 0xF; if (oldItemIdentifier != newItemIdentifier) { return false; } if (oldItemValue == newItemValue) { *outCompareResult = 0; } else { *outCompareResult = (newItemValue > oldItemValue) + 1; } return true; } static void testEnumerateIdentifiableObjectChanges(void) { struct enumerateChangesContextStruct contextStruct = {0, NULL}; { // No difference int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x22, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 0); } { // One value difference in the middle int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x24, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x22 ^ 0x24); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One value difference at the start int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x10, 0x22, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11 ^ 0x10); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 1); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One value difference at the end int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x22, 0x34}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 2); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x33 ^ 0x34); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One insertion in the middle int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x42, 0x22, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x42); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One insertion at the start int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x00, 0x11, 0x22, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x00); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One insertion at the end int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x22, 0x33, 0x44}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 3); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x44); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One deletion in the middle int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One deletion at the start int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x22, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One deletion at the end int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x22}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 1); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 2); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x33); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One object change (deletion and insertion) in the middle int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x42, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x42); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One object change (deletion and insertion) at the start int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x42, 0x22, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 0); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x42); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // One object change (deletion and insertion) at the end int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x22, 0x42}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 2); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x33); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x42); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple value differences int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x13, 0x24, 0x30}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 3); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11 ^ 0x13); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x22 ^ 0x24); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 2); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[2].index, 2); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x33 ^ 0x30); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 1); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple contiguous insertions in the middle int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x44, 0x55, 0x22, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x44); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple contiguous deletions in the middle int oldList[] = {0x11, 0x22, 0x33, 0x44, 0x55}; int newList[] = {0x11, 0x22, 0x55}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 2); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x33); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x44); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Deletion in the middle followed by 2 insertions int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x44, 0x55, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 3); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x44); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[2].index, 2); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple deletions in the middle followed by insertion int oldList[] = {0x11, 0x22, 0x33, 0x44}; int newList[] = {0x11, 0x55, 0x44}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 3); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x33); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[2].index, 1); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple noncontiguous insertions int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x44, 0x55, 0x22, 0x66, 0x77, 0x33}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 4); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x44); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[2].index, 4); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x66); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[3].index, 5); TestCase_assertIntEqual(contextStruct.changes[3].item, 0x77); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple noncontiguous deletions int oldList[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; int newList[] = {0x11, 0x44, 0x77}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 4); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x33); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[2].index, 2); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[3].index, 2); TestCase_assertIntEqual(contextStruct.changes[3].item, 0x66); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple contiguous modifications between two insertions int oldList[] = {0x11, 0x22, 0x33}; int newList[] = {0x11, 0x44, 0x20, 0x30, 0x55}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 4); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 1); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x44); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x22 ^ 0x20); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 1); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[2].index, 3); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x33 ^ 0x30); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 1); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[3].index, 4); TestCase_assertIntEqual(contextStruct.changes[3].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple contiguous and noncontiguous deletions with a modification in between int oldList[] = {0x11, 0x22, 0x33, 0x44, 0x55}; int newList[] = {0x30}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 5); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 0); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[2].index, 0); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x33 ^ 0x30); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 1); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[3].index, 1); TestCase_assertIntEqual(contextStruct.changes[3].item, 0x44); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[4].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[4].index, 1); TestCase_assertIntEqual(contextStruct.changes[4].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[4].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // All items deleted int oldList[] = {0x11, 0x22}; int newList[] = {}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 0); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Items added to empty list int oldList[] = {}; int newList[] = {0x11, 0x22}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 2); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Multiple contiguous and noncontiguous insertions, deletions, and modifications int oldList[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; int newList[] = {0x0F, 0x30, 0x88, 0x99, 0x4F, 0xAA, 0xBB, 0xCC, 0x70}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 13); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x00 ^ 0x0F); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 2); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[1].index, 7); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x77 ^ 0x70); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 1); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[2].index, 1); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[3].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[3].index, 1); TestCase_assertIntEqual(contextStruct.changes[3].item, 0x22); TestCase_assertIntEqual(contextStruct.changes[3].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[4].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[4].index, 1); TestCase_assertIntEqual(contextStruct.changes[4].item, 0x33 ^ 0x30); TestCase_assertIntEqual(contextStruct.changes[4].compareResult, 1); TestCase_assertIntEqual(contextStruct.changes[5].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[5].index, 2); TestCase_assertIntEqual(contextStruct.changes[5].item, 0x88); TestCase_assertIntEqual(contextStruct.changes[5].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[6].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[6].index, 3); TestCase_assertIntEqual(contextStruct.changes[6].item, 0x99); TestCase_assertIntEqual(contextStruct.changes[6].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[7].changeType, CHANGE_TYPE_MODIFY); TestCase_assertIntEqual(contextStruct.changes[7].index, 4); TestCase_assertIntEqual(contextStruct.changes[7].item, 0x44 ^ 0x4F); TestCase_assertIntEqual(contextStruct.changes[7].compareResult, 2); TestCase_assertIntEqual(contextStruct.changes[8].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[8].index, 5); TestCase_assertIntEqual(contextStruct.changes[8].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[8].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[9].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[9].index, 5); TestCase_assertIntEqual(contextStruct.changes[9].item, 0x66); TestCase_assertIntEqual(contextStruct.changes[9].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[10].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[10].index, 5); TestCase_assertIntEqual(contextStruct.changes[10].item, 0xAA); TestCase_assertIntEqual(contextStruct.changes[10].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[11].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[11].index, 6); TestCase_assertIntEqual(contextStruct.changes[11].item, 0xBB); TestCase_assertIntEqual(contextStruct.changes[11].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[12].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[12].index, 7); TestCase_assertIntEqual(contextStruct.changes[12].item, 0xCC); TestCase_assertIntEqual(contextStruct.changes[12].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Three noncontiguous additions int oldList[] = {0x22, 0x44}; int newList[] = {0x11, 0x22, 0x33, 0x44, 0x55}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 3); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[1].index, 2); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x33); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_ADD); TestCase_assertIntEqual(contextStruct.changes[2].index, 4); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } { // Three noncontiguous deletions int oldList[] = {0x11, 0x22, 0x33, 0x44, 0x55}; int newList[] = {0x22, 0x44}; enumerateIdentifiableObjectChanges(listArgs(), compareIdentifiable, itemAdded, itemRemoved, itemModified, &contextStruct); TestCase_assertUIntEqual(contextStruct.changeCount, 3); TestCase_assertIntEqual(contextStruct.changes[0].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[0].index, 0); TestCase_assertIntEqual(contextStruct.changes[0].item, 0x11); TestCase_assertIntEqual(contextStruct.changes[0].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[1].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[1].index, 1); TestCase_assertIntEqual(contextStruct.changes[1].item, 0x33); TestCase_assertIntEqual(contextStruct.changes[1].compareResult, 3); TestCase_assertIntEqual(contextStruct.changes[2].changeType, CHANGE_TYPE_REMOVE); TestCase_assertIntEqual(contextStruct.changes[2].index, 2); TestCase_assertIntEqual(contextStruct.changes[2].item, 0x55); TestCase_assertIntEqual(contextStruct.changes[2].compareResult, 3); free(contextStruct.changes); contextStruct.changeCount = 0; contextStruct.changes = NULL; } } struct listSwapsContextStruct { unsigned int swapCount; struct { unsigned int oldIndex; unsigned int newIndex; } * swaps; }; static void swapUInt(unsigned int oldIndex, unsigned int newIndex, void * context) { struct listSwapsContextStruct * contextStruct = context; contextStruct->swaps = realloc(contextStruct->swaps, (contextStruct->swapCount + 1) * sizeof(*contextStruct->swaps)); contextStruct->swaps[contextStruct->swapCount].oldIndex = oldIndex; contextStruct->swaps[contextStruct->swapCount].newIndex = newIndex; contextStruct->swapCount++; } static bool compareUInt(void * lhsUntyped, void * rhsUntyped, void * context) { unsigned int * lhs = lhsUntyped, * rhs = rhsUntyped; return *lhs == *rhs; } static void testListReorderSwaps(void) { { struct listSwapsContextStruct contextStruct = {0, NULL}; listReorderSwaps(NULL, NULL, 0, sizeof(unsigned int), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 0); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1}; unsigned int new[sizeof_count(old)] = {0, 1}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 0); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1}; unsigned int new[sizeof_count(old)] = {1, 0}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 1); TestCase_assertUIntEqual(contextStruct.swaps[0].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[0].newIndex, 1); free(contextStruct.swaps); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1, 2, 3}; unsigned int new[sizeof_count(old)] = {0, 3, 1, 2}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 2); TestCase_assertUIntEqual(contextStruct.swaps[0].oldIndex, 1); TestCase_assertUIntEqual(contextStruct.swaps[0].newIndex, 2); TestCase_assertUIntEqual(contextStruct.swaps[1].oldIndex, 1); TestCase_assertUIntEqual(contextStruct.swaps[1].newIndex, 3); free(contextStruct.swaps); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1, 2, 3, 4}; unsigned int new[sizeof_count(old)] = {4, 3, 2, 1, 0}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 2); TestCase_assertUIntEqual(contextStruct.swaps[0].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[0].newIndex, 4); TestCase_assertUIntEqual(contextStruct.swaps[1].oldIndex, 1); TestCase_assertUIntEqual(contextStruct.swaps[1].newIndex, 3); free(contextStruct.swaps); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1, 2, 3, 4, 5}; unsigned int new[sizeof_count(old)] = {1, 2, 3, 4, 5, 0}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 5); TestCase_assertUIntEqual(contextStruct.swaps[0].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[0].newIndex, 5); TestCase_assertUIntEqual(contextStruct.swaps[1].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[1].newIndex, 4); TestCase_assertUIntEqual(contextStruct.swaps[2].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[2].newIndex, 3); TestCase_assertUIntEqual(contextStruct.swaps[3].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[3].newIndex, 2); TestCase_assertUIntEqual(contextStruct.swaps[4].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[4].newIndex, 1); free(contextStruct.swaps); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1, 2, 3, 4, 5}; unsigned int new[sizeof_count(old)] = {5, 0, 1, 2, 3, 4}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 5); TestCase_assertUIntEqual(contextStruct.swaps[0].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[0].newIndex, 1); TestCase_assertUIntEqual(contextStruct.swaps[1].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[1].newIndex, 2); TestCase_assertUIntEqual(contextStruct.swaps[2].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[2].newIndex, 3); TestCase_assertUIntEqual(contextStruct.swaps[3].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[3].newIndex, 4); TestCase_assertUIntEqual(contextStruct.swaps[4].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[4].newIndex, 5); free(contextStruct.swaps); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1, 2, 3, 4, 5, 6}; unsigned int new[sizeof_count(old)] = {1, 2, 0, 3, 5, 6, 4}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 4); TestCase_assertUIntEqual(contextStruct.swaps[0].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[0].newIndex, 2); TestCase_assertUIntEqual(contextStruct.swaps[1].oldIndex, 0); TestCase_assertUIntEqual(contextStruct.swaps[1].newIndex, 1); TestCase_assertUIntEqual(contextStruct.swaps[2].oldIndex, 4); TestCase_assertUIntEqual(contextStruct.swaps[2].newIndex, 6); TestCase_assertUIntEqual(contextStruct.swaps[3].oldIndex, 4); TestCase_assertUIntEqual(contextStruct.swaps[3].newIndex, 5); free(contextStruct.swaps); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 1, 2}; unsigned int new[sizeof_count(old)] = {3, 4, 5}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 0); } { struct listSwapsContextStruct contextStruct = {0, NULL}; unsigned int old[] = {0, 0, 0}; unsigned int new[sizeof_count(old)] = {0, 0, 0}; listReorderSwaps(old, new, sizeof_count(old), sizeof(old[0]), compareUInt, swapUInt, &contextStruct); TestCase_assertUIntEqual(contextStruct.swapCount, 0); } } TEST_SUITE(UndoUtilitiesTest, testEnumerateChangesBetweenOldAndNewLists, testEnumerateIdentifiableObjectChanges, testListReorderSwaps)