static void test_stSet_getUnion(CuTest* testCase) { testSetup(); // Check union of empty sets is empty stSet *set2 = stSet_construct(); stSet *set3 = stSet_construct(); stSet *set4 = stSet_getUnion(set2, set3); CuAssertTrue(testCase, stSet_size(set4) == 0); stSet_destruct(set2); stSet_destruct(set3); stSet_destruct(set4); // Check union of non empty set and empty set is non-empty set2 = stSet_construct(); set3 = stSet_getUnion(set0, set2); CuAssertTrue(testCase, stSet_size(set3) == 6); stSet_destruct(set2); stSet_destruct(set3); // Check union of two non-empty overlapping sets is correct set2 = stSet_construct(); set3 = stSet_construct(); stIntTuple **uniqs = (stIntTuple **) st_malloc(sizeof(*uniqs) * 4); uniqs[0] = stIntTuple_construct2(9, 0); uniqs[1] = stIntTuple_construct2(9, 1); uniqs[2] = stIntTuple_construct2(9, 2); uniqs[3] = stIntTuple_construct2(9, 3); stIntTuple **common = (stIntTuple **) st_malloc(sizeof(*uniqs) * 5); common[0] = stIntTuple_construct2(5, 0); common[1] = stIntTuple_construct2(5, 1); common[2] = stIntTuple_construct2(5, 2); common[3] = stIntTuple_construct2(5, 3); common[4] = stIntTuple_construct2(5, 4); for (int i = 0; i < 5; ++i) { stSet_insert(set2, common[i]); stSet_insert(set3, common[i]); } stSet_insert(set2, uniqs[0]); stSet_insert(set2, uniqs[1]); stSet_insert(set3, uniqs[2]); stSet_insert(set3, uniqs[3]); set4 = stSet_getUnion(set2, set3); CuAssertTrue(testCase, stSet_size(set4) == 9); for (int i = 0; i < 4; ++i) { CuAssertTrue(testCase, stSet_search(set4, uniqs[i]) != NULL); } for (int i = 0; i < 5; ++i) { CuAssertTrue(testCase, stSet_search(set4, common[i]) != NULL); } stSet_destruct(set2); stSet_destruct(set3); stSet_destruct(set4); // Check we get an exception with sets with different functions. stTry { stSet_getUnion(set0, set1); } stCatch(except) { CuAssertTrue(testCase, stExcept_getId(except) == SET_EXCEPTION_ID); } stTryEnd testTeardown(); }
static void testSetup() { // compare by value of memory address set0 = stSet_construct(); // compare by value of ints. set1 = stSet_construct3((uint64_t(*)(const void *)) stIntTuple_hashKey, (int(*)(const void *, const void *)) stIntTuple_equalsFn, (void(*)(void *)) stIntTuple_destruct); one = stIntTuple_construct1( 0); two = stIntTuple_construct1( 1); three = stIntTuple_construct1( 2); four = stIntTuple_construct1( 3); five = stIntTuple_construct1( 4); six = stIntTuple_construct1( 5); stSet_insert(set0, one); stSet_insert(set0, two); stSet_insert(set0, three); stSet_insert(set0, four); stSet_insert(set0, five); stSet_insert(set0, six); stSet_insert(set1, one); stSet_insert(set1, two); stSet_insert(set1, three); stSet_insert(set1, four); stSet_insert(set1, five); stSet_insert(set1, six); }
static void test_stSet_size(CuTest *testCase) { /* * Tests the size function of the hash. */ testSetup(); CuAssertTrue(testCase, stSet_size(set0) == 6); CuAssertTrue(testCase, stSet_size(set1) == 6); stSet *set2 = stSet_construct(); CuAssertTrue(testCase, stSet_size(set2) == 0); stSet_destruct(set2); testTeardown(); }
stTree *stTree_getMRCA(stTree *node1, stTree *node2) { // Find all of node 1's parents (inclusive of node 1) stSet *parents = stSet_construct(); stTree *curNode = node1; do { stSet_insert(parents, curNode); } while ((curNode = stTree_getParent(curNode)) != NULL); // Find the first parent of node 2 that is a parent of node 1 stTree *ret = NULL; curNode = node2; do { if (stSet_search(parents, curNode) != NULL) { ret = curNode; break; } } while ((curNode = stTree_getParent(curNode)) != NULL); stSet_destruct(parents); return ret; }
static void test_stSet_testIterator(CuTest *testCase) { testSetup(); stSetIterator *iterator = stSet_getIterator(set0); stSetIterator *iteratorCopy = stSet_copyIterator(iterator); int64_t i = 0; stSet *seen = stSet_construct(); for (i = 0; i < 6; i++) { void *o = stSet_getNext(iterator); CuAssertTrue(testCase, o != NULL); CuAssertTrue(testCase, stSet_search(set0, o) != NULL); CuAssertTrue(testCase, stSet_search(seen, o) == NULL); CuAssertTrue(testCase, stSet_getNext(iteratorCopy) == o); stSet_insert(seen, o); } CuAssertTrue(testCase, stSet_getNext(iterator) == NULL); CuAssertTrue(testCase, stSet_getNext(iterator) == NULL); CuAssertTrue(testCase, stSet_getNext(iteratorCopy) == NULL); stSet_destruct(seen); stSet_destructIterator(iterator); stSet_destructIterator(iteratorCopy); testTeardown(); }
// Compute the connected components, if they haven't been computed // already since the last modification. static void computeConnectedComponents(stNaiveConnectivity *connectivity) { if (connectivity->connectedComponentCache != NULL) { // Already computed the connected components. return; } stHashIterator *nodeIt = stHash_getIterator(connectivity->nodesToAdjList); void *node; stNaiveConnectedComponent *componentsHead = NULL; while ((node = stHash_getNext(nodeIt)) != NULL) { stSet *myNodeSet = stSet_construct(); stSet_insert(myNodeSet, node); struct adjacency *adjList = stHash_search(connectivity->nodesToAdjList, node); if (adjList != NULL) { while (adjList != NULL) { stSet_insert(myNodeSet, adjList->toNode); adjList = adjList->next; } } // Now go through the existing connected components and see if // this overlaps any of them. If it's not a full overlap, then // this set becomes the union, and we continue looking for // additional overlaps, then this becomes a new connected // component. If we find that this is a subset of an existing // component, we can quit early, since we can't possibly add // to it or any others. stNaiveConnectedComponent *curComponent = componentsHead; while (curComponent != NULL) { stNaiveConnectedComponent *next = curComponent->next; // Find out whether our node set is a subset of this // connected component, or if it shares any overlap. bool isSubset = true; bool overlap = false; stSetIterator *myNodeIt = stSet_getIterator(myNodeSet); void *node; while ((node = stSet_getNext(myNodeIt)) != NULL) { if (stSet_search(curComponent->nodes, node)) { overlap = true; } else { isSubset = false; } } stSet_destructIterator(myNodeIt); if (isSubset) { assert(overlap == true); // Quit early. stSet_destruct(myNodeSet); myNodeSet = NULL; break; } else if (overlap) { stSet *newNodeSet = stSet_getUnion(myNodeSet, curComponent->nodes); stSet_destruct(myNodeSet); removeComponent(&componentsHead, curComponent); myNodeSet = newNodeSet; } curComponent = next; } if (myNodeSet != NULL) { // We have a new (or possibly merged) connected component to // add to the list. stNaiveConnectedComponent *newComponent = malloc(sizeof(stNaiveConnectedComponent)); newComponent->nodes = myNodeSet; newComponent->next = componentsHead; componentsHead = newComponent; } } stHash_destructIterator(nodeIt); connectivity->connectedComponentCache = componentsHead; }