示例#1
0
void testEnd_setGroup(CuTest* testCase) {
    cactusEndTestSetup();
    Flower *flower2 = flower_construct(cactusDisk);
    Group *group2 = group_construct2(flower2);
    End *end2 = end_construct(1, flower2);
    End *end3 = end_construct(1, flower2);
    CuAssertTrue(testCase, group_getEndNumber(group2) == 0);
    CuAssertTrue(testCase, end_getGroup(end2) == NULL);
    CuAssertTrue(testCase, end_getGroup(end3) == NULL);
    end_setGroup(end2, group2);
    CuAssertTrue(testCase, group_getEndNumber(group2) == 1);
    CuAssertTrue(testCase, end_getGroup(end2) == group2);
    CuAssertTrue(testCase, group_getEnd(group2, end_getName(end2)) == end2);
    CuAssertTrue(testCase, end_getGroup(end3) == NULL);
    end_setGroup(end3, group2);
    CuAssertTrue(testCase, group_getEndNumber(group2) == 2);
    CuAssertTrue(testCase, end_getGroup(end2) == group2);
    CuAssertTrue(testCase, group_getEnd(group2, end_getName(end2)) == end2);
    CuAssertTrue(testCase, end_getGroup(end3) == group2);
    CuAssertTrue(testCase, group_getEnd(group2, end_getName(end3)) == end3);
    end_setGroup(end3, NULL);
    end_setGroup(end2, group2);
    CuAssertTrue(testCase, group_getEndNumber(group2) == 1);
    CuAssertTrue(testCase, end_getGroup(end2) == group2);
    CuAssertTrue(testCase, group_getEnd(group2, end_getName(end2)) == end2);
    CuAssertTrue(testCase, end_getGroup(end3) == NULL);
    cactusEndTestTeardown();
}
示例#2
0
void testFlower_isLeaf(CuTest *testCase) {
    cactusFlowerTestSetup();
    CuAssertTrue(testCase, flower_isLeaf(flower));
    Group *group = group_construct2(flower);
    CuAssertTrue(testCase, flower_isLeaf(flower));
    group_makeNestedFlower(group);
    CuAssertTrue(testCase, !flower_isLeaf(flower));
    cactusFlowerTestTeardown();
}
示例#3
0
void testFlower_isTerminal(CuTest *testCase) {
    cactusFlowerTestSetup();
    CuAssertTrue(testCase, flower_isTerminal(flower));
    group_construct2(flower);
    CuAssertTrue(testCase, flower_isTerminal(flower));
    end_construct(0, flower);
    CuAssertTrue(testCase, flower_isTerminal(flower));
    block_construct(1, flower);
    CuAssertTrue(testCase, !flower_isTerminal(flower));
    cactusFlowerTestTeardown();
}
示例#4
0
void testBlock_isTrivialChain(CuTest *testCase) {
    cactusBlockTestSetup();
    Group *group = group_construct2(flower);
    end_setGroup(block_get5End(block), group);
    end_setGroup(block_get3End(block), group);
    Chain *chain = chain_construct(flower);
    Group *group2 = group_construct2(flower);
    CuAssertTrue(testCase, block_isTrivialChain(block));
    Block *block1 = block_construct(1, flower);
    Block *block2 = block_construct(1, flower);
    end_setGroup(block_get5End(block2), group2);
    end_setGroup(block_get3End(block1), group2);
    link_construct(block_get3End(block1), block_get5End(block2), group2, chain);
    end_setGroup(block_get5End(block1), group);
    end_setGroup(block_get3End(block2), group);
    CuAssertTrue(testCase, block_isTrivialChain(block));
    CuAssertTrue(testCase, !block_isTrivialChain(block1));
    CuAssertTrue(testCase, !block_isTrivialChain(block2));
    cactusBlockTestTeardown();
}
示例#5
0
void testFlower_getTrivialChainNumber(CuTest* testCase) {
    cactusFlowerTestSetup();
    CuAssertIntEquals(testCase, 0, flower_getTrivialChainNumber(flower));
    chain = chain_construct(flower);
    chain2 = chain_construct(flower);
    CuAssertIntEquals(testCase, 0, flower_getTrivialChainNumber(flower));
    group = group_construct2(flower);
    group2 = group_construct2(flower);
    block = block_construct(1, flower);
    end_setGroup(block_get5End(block), group);
    end_setGroup(block_get3End(block), group2);
    CuAssertIntEquals(testCase, 1, flower_getTrivialChainNumber(flower));
    block2 = block_construct(1, flower);
    end_setGroup(block_get5End(block2), group2);
    end_setGroup(block_get3End(block2), group);
    CuAssertIntEquals(testCase, 2, flower_getTrivialChainNumber(flower));
    link_construct(block_get3End(block), block_get5End(block2), group2, chain);
    CuAssertIntEquals(testCase, 0, flower_getTrivialChainNumber(flower));
    link_construct(block_get3End(block2), block_get5End(block), group, chain);
    CuAssertIntEquals(testCase, 0, flower_getTrivialChainNumber(flower));
    cactusFlowerTestTeardown();
}
示例#6
0
static void cactusGroupTestSetup() {
    cactusGroupTestTeardown();
    cactusDisk = testCommon_getTemporaryCactusDisk();
    flower = flower_construct(cactusDisk);
    nestedFlower = flower_construct(cactusDisk);
    end1 = end_construct2(0, 0, flower);
    end2 = end_construct(0, flower);
    end3 = end_construct(0, flower);
    nestedEnd1 = end_copyConstruct(end1, nestedFlower);
    nestedEnd2 = end_copyConstruct(end2, nestedFlower);
    group = group_construct(flower, nestedFlower);
    group2 = group_construct2(flower);
    end4 = end_construct(0, flower);
}
示例#7
0
bool flower_removeIfRedundant(Flower *flower) {
    if (!flower_isLeaf(flower) && flower_getParentGroup(flower) != NULL && flower_getBlockNumber(flower) == 0) { //We will remove this flower..
        Group *parentGroup = flower_getParentGroup(flower); //This group will be destructed
        //Deal with any parent chain..
        if (group_isLink(parentGroup)) {
            link_split(group_getLink(parentGroup));
        }
        Flower *parentFlower = group_getFlower(parentGroup); //We will add the groups in the flower to the parent

        /*
         * For each group in the flower we take its nested flower and attach it to the parent.
         */
        Group *group;
        Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
        while ((group = flower_getNextGroup(groupIt)) != NULL) {
            if (!group_isLeaf(group)) {
                //Copy the group into the parent..
                Flower *nestedFlower = group_getNestedFlower(group);
                assert(nestedFlower != NULL);
                Group *newParentGroup = group_construct(parentFlower, nestedFlower);
                flower_setParentGroup(nestedFlower, newParentGroup);
                group_constructChainForLink(newParentGroup);
            } else {
                Group *newParentGroup = group_construct2(parentFlower);
                End *end;
                Group_EndIterator *endIt = group_getEndIterator(group);
                while ((end = group_getNextEnd(endIt)) != NULL) {
                    End *parentEnd = flower_getEnd(parentFlower, end_getName(end));
                    assert(parentEnd != NULL);
                    end_setGroup(parentEnd, newParentGroup);
                }
                group_destructEndIterator(endIt);
                group_constructChainForLink(newParentGroup);
            }
        }
        flower_destructGroupIterator(groupIt);

        //The group attached to the flower should now be empty
        assert(group_getEndNumber(parentGroup) == 0);
        group_destruct(parentGroup);

        //Now wipe the flower out..
        cactusDisk_deleteFlowerFromDisk(flower_getCactusDisk(flower), flower);
        flower_destruct(flower, 0);
        return 1;
    }
    return 0;
}
示例#8
0
void testGroup_constructChainForLink(CuTest *testCase) {
    cactusGroupTestSetup();
    //Create a link group and test function works!
    Group *group3 = group_construct2(flower);
    End *_5End = end_construct2(1, 1, flower);
    End *_3End = end_construct2(0, 1, flower);
    End *stubEnd = end_construct2(1, 0, flower);
    end_setGroup(_5End, group3);
    end_setGroup(_3End, group3);
    end_setGroup(stubEnd, group3);
    CuAssertTrue(testCase, group_isTangle(group3));
    CuAssertTrue(testCase, group_getEndNumber(group3) == 3);
    group_constructChainForLink(group3);
    CuAssertTrue(testCase, group_isLink(group3));
    Link *link = group_getLink(group3);
    CuAssertTrue(testCase, link_get5End(link) == _5End);
    CuAssertTrue(testCase, link_get3End(link) == _3End);
    cactusGroupTestTeardown();
}
示例#9
0
void testEventTree_addSiblingUnaryEvent(CuTest *testCase) {
	cactusEventTreeTestSetup();
	//Create two sibling flowers with the basic event tree..
	//then try adding events from on into the other.
	Group *group1 = group_construct2(flower);
	Group *group2 = group_construct2(flower);
	Flower *flower2 = flower_construct(cactusDisk);
	Flower *flower3 = flower_construct(cactusDisk);
	flower_setParentGroup(flower2, group1);
	flower_setParentGroup(flower3, group2);
	EventTree *eventTree2 = eventTree_copyConstruct(flower_getEventTree(flower), flower2, NULL);
	Event *parentUnaryEvent1 = event_construct4("UNARY1", 0.1, internalEvent, leafEvent1, eventTree);
	Event *parentUnaryEvent2 = event_construct4("UNARY2", 0.1, parentUnaryEvent1, leafEvent1, eventTree);
	Event *parentUnaryEvent3 = event_construct4("UNARY3", 0.1, internalEvent, leafEvent2, eventTree);
	//now event tree contains the added unary events.
	EventTree *eventTree3 = eventTree_copyConstruct(flower_getEventTree(flower), flower3, NULL);
	//add a couple of denovo events into the new event tree
	Event *internalEventChild = eventTree_getEvent(eventTree3, event_getName(internalEvent));
	Event *unaryEvent1 = eventTree_getEvent(eventTree3, event_getName(parentUnaryEvent1));
	Event *unaryEvent2 = eventTree_getEvent(eventTree3, event_getName(parentUnaryEvent2));
	Event *unaryEvent3 = eventTree_getEvent(eventTree3, event_getName(parentUnaryEvent3));
	Event *unaryEvent4 = event_construct4("UNARY4", 0.1,
			internalEventChild, unaryEvent3, eventTree3);
	Event *unaryEvent5 = event_construct4("UNARY5", 0.1,
				internalEventChild, unaryEvent4, eventTree3);
	//Now event-tree 2 does not contain the unary events but event-tree 3 does..

	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent1)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent2)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent3)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent4)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent5)) == NULL);

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent1);
	Event *unaryEvent12 = eventTree_getEvent(eventTree2, event_getName(unaryEvent1));
	CuAssertTrue(testCase, unaryEvent12 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent12)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent12) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent12, 0)) == event_getName(leafEvent1));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent2);
	Event *unaryEvent22 = eventTree_getEvent(eventTree2, event_getName(unaryEvent2));
	CuAssertTrue(testCase, unaryEvent22 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent22)) == event_getName(unaryEvent1));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent22) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent22, 0)) == event_getName(leafEvent1));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent3);
	Event *unaryEvent32 = eventTree_getEvent(eventTree2, event_getName(unaryEvent3));
	CuAssertTrue(testCase, unaryEvent32 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent32)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent32) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent32, 0)) == event_getName(leafEvent2));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent4);
	Event *unaryEvent42 = eventTree_getEvent(eventTree2, event_getName(unaryEvent4));
	CuAssertTrue(testCase, unaryEvent42 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent42)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent42) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent42, 0)) == event_getName(unaryEvent3));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent5);
	Event *unaryEvent52 = eventTree_getEvent(eventTree2, event_getName(unaryEvent5));
	CuAssertTrue(testCase, unaryEvent52 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent52)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent52) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent52, 0)) == event_getName(unaryEvent4));

	//uglyf("Event-tree-1 %s\n", eventTree_makeNewickString(eventTree));
	//uglyf("Event-tree-2 %s\n", eventTree_makeNewickString(eventTree3));
	//uglyf("Event-tree-3 %s\n", eventTree_makeNewickString(eventTree2));

	cactusEventTreeTestTeardown();
}
示例#10
0
int main(int argc, char *argv[]) {
    /*
     * Open the database.
     * Construct a flower.
     * Construct an event tree representing the species tree.
     * For each sequence contruct two ends each containing an cap.
     * Make a file for the sequence.
     * Link the two caps.
     * Finish!
     */

    int64_t key, j;
    Group *group;
    Flower_EndIterator *endIterator;
    End *end;
    bool makeEventHeadersAlphaNumeric = 0;

    /*
     * Arguments/options
     */
    char * logLevelString = NULL;
    char * speciesTree = NULL;
    char * outgroupEvents = NULL;

    ///////////////////////////////////////////////////////////////////////////
    // (0) Parse the inputs handed by genomeCactus.py / setup stuff.
    ///////////////////////////////////////////////////////////////////////////

    while (1) {
        static struct option long_options[] = { { "logLevel", required_argument, 0, 'a' }, { "cactusDisk", required_argument, 0, 'b' }, {
                "speciesTree", required_argument, 0, 'f' }, { "outgroupEvents", required_argument, 0, 'g' },
                { "help", no_argument, 0, 'h' }, { "makeEventHeadersAlphaNumeric", no_argument, 0, 'i' }, { 0, 0, 0, 0 } };

        int option_index = 0;

        key = getopt_long(argc, argv, "a:b:f:hg:i", long_options, &option_index);

        if (key == -1) {
            break;
        }

        switch (key) {
            case 'a':
                logLevelString = optarg;
                break;
            case 'b':
                cactusDiskDatabaseString = optarg;
                break;
            case 'f':
                speciesTree = optarg;
                break;
            case 'g':
                outgroupEvents = optarg;
                break;
            case 'h':
                usage();
                return 0;
            case 'i':
                makeEventHeadersAlphaNumeric = 1;
                break;
            default:
                usage();
                return 1;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // (0) Check the inputs.
    ///////////////////////////////////////////////////////////////////////////

    //assert(logLevelString == NULL || strcmp(logLevelString, "CRITICAL") == 0 || strcmp(logLevelString, "INFO") == 0 || strcmp(logLevelString, "DEBUG") == 0);
    assert(cactusDiskDatabaseString != NULL);
    assert(speciesTree != NULL);

    //////////////////////////////////////////////
    //Set up logging
    //////////////////////////////////////////////

    st_setLogLevelFromString(logLevelString);

    //////////////////////////////////////////////
    //Log (some of) the inputs
    //////////////////////////////////////////////

    st_logInfo("Flower disk name : %s\n", cactusDiskDatabaseString);

    for (j = optind; j < argc; j++) {
        st_logInfo("Sequence file/directory %s\n", argv[j]);
    }

    //////////////////////////////////////////////
    //Load the database
    //////////////////////////////////////////////

    stKVDatabaseConf *kvDatabaseConf = kvDatabaseConf = stKVDatabaseConf_constructFromString(cactusDiskDatabaseString);
    if (stKVDatabaseConf_getType(kvDatabaseConf) == stKVDatabaseTypeTokyoCabinet || stKVDatabaseConf_getType(kvDatabaseConf)
            == stKVDatabaseTypeKyotoTycoon) {
        assert(stKVDatabaseConf_getDir(kvDatabaseConf) != NULL);
        cactusDisk = cactusDisk_construct2(kvDatabaseConf, "cactusSequences");
    } else {
        cactusDisk = cactusDisk_construct(kvDatabaseConf, 1);
    }
    st_logInfo("Set up the flower disk\n");

    //////////////////////////////////////////////
    //Construct the flower
    //////////////////////////////////////////////

    if (cactusDisk_getFlower(cactusDisk, 0) != NULL) {
        cactusDisk_destruct(cactusDisk);
        st_logInfo("The first flower already exists\n");
        return 0;
    }
    flower = flower_construct2(0, cactusDisk);
    assert(flower_getName(flower) == 0);
    st_logInfo("Constructed the flower\n");

    //////////////////////////////////////////////
    //Construct the event tree
    //////////////////////////////////////////////

    st_logInfo("Going to build the event tree with newick string: %s\n", speciesTree);
    stTree *tree = stTree_parseNewickString(speciesTree);
    st_logInfo("Parsed the tree\n");
    if (makeEventHeadersAlphaNumeric) {
        makeEventHeadersAlphaNumericFn(tree);
    }
    stTree_setBranchLength(tree, INT64_MAX);
    checkBranchLengthsAreDefined(tree);
    eventTree = eventTree_construct2(flower); //creates the event tree and the root even
    totalEventNumber = 1;
    st_logInfo("Constructed the basic event tree\n");

    // Construct a set of outgroup names so that ancestral outgroups
    // get recognized.
    stSet *outgroupNameSet = stSet_construct3(stHash_stringKey,
                                              stHash_stringEqualKey,
                                              free);
    if(outgroupEvents != NULL) {
        stList *outgroupNames = stString_split(outgroupEvents);
        for(int64_t i = 0; i < stList_length(outgroupNames); i++) {
            char *outgroupName = stList_get(outgroupNames, i);
            stSet_insert(outgroupNameSet, stString_copy(outgroupName));
        }
        stList_destruct(outgroupNames);
    }

    //now traverse the tree
    j = optind;
    assignEventsAndSequences(eventTree_getRootEvent(eventTree), tree,
                             outgroupNameSet, argv, &j);

    char *eventTreeString = eventTree_makeNewickString(eventTree);
    st_logInfo(
            "Constructed the initial flower with %" PRIi64 " sequences and %" PRIi64 " events with string: %s\n",
            totalSequenceNumber, totalEventNumber, eventTreeString);
    assert(event_getSubTreeBranchLength(eventTree_getRootEvent(eventTree)) >= 0.0);
    free(eventTreeString);
    //assert(0);

    //////////////////////////////////////////////
    //Label any outgroup events.
    //////////////////////////////////////////////

    if (outgroupEvents != NULL) {
        stList *outgroupEventsList = stString_split(outgroupEvents);
        for (int64_t i = 0; i < stList_length(outgroupEventsList); i++) {
            char *outgroupEvent = makeEventHeadersAlphaNumeric ? makeAlphaNumeric(stList_get(outgroupEventsList, i)) : stString_copy(stList_get(outgroupEventsList, i));
            Event *event = eventTree_getEventByHeader(eventTree, outgroupEvent);
            if (event == NULL) {
                st_errAbort("Got an outgroup string that does not match an event, outgroup string %s", outgroupEvent);
            }
            assert(!event_isOutgroup(event));
            event_setOutgroupStatus(event, 1);
            assert(event_isOutgroup(event));
            free(outgroupEvent);
        }
        stList_destruct(outgroupEventsList);
    }

    //////////////////////////////////////////////
    //Construct the terminal group.
    //////////////////////////////////////////////

    if (flower_getEndNumber(flower) > 0) {
        group = group_construct2(flower);
        endIterator = flower_getEndIterator(flower);
        while ((end = flower_getNextEnd(endIterator)) != NULL) {
            end_setGroup(end, group);
        }
        flower_destructEndIterator(endIterator);
        assert(group_isLeaf(group));

        // Create a one link chain if there is only one pair of attached ends..
        group_constructChainForLink(group);
        assert(!flower_builtBlocks(flower));
    } else {
        flower_setBuiltBlocks(flower, 1);
    }

    ///////////////////////////////////////////////////////////////////////////
    // Write the flower to disk.
    ///////////////////////////////////////////////////////////////////////////

    //flower_check(flower);
    cactusDisk_write(cactusDisk);
    st_logInfo("Updated the flower on disk\n");

    ///////////////////////////////////////////////////////////////////////////
    // Cleanup.
    ///////////////////////////////////////////////////////////////////////////

    cactusDisk_destruct(cactusDisk);

    return 0; //Exit without clean up is quicker, enable cleanup when doing memory leak detection.

    stSet_destruct(outgroupNameSet);
    stTree_destruct(tree);
    stKVDatabaseConf_destruct(kvDatabaseConf);

    return 0;
}
示例#11
0
void testFlower_removeIfRedundant(CuTest *testCase) {
    /*
     * Do a simple test to see if function can remove a redundant flower.
     */
    cactusFlowerTestSetup();
    endsSetup();

    //First construct a redundant flower from the root.
    Flower *flower2 = flower_construct(cactusDisk);
    Group *group = group_construct(flower, flower2);
    end_setGroup(end, group);
    end_setGroup(end2, group);

    //Now hang another couple of flowers of that.
    Flower *flower3 = flower_construct(cactusDisk);
    group_construct(flower2, flower3);

    //Now hang another flower of that.
    Group *group3b = group_construct2(flower2);

    //Finally hang one more flower on the end..
    Flower *flower4 = flower_construct(cactusDisk);
    group_construct(flower3, flower4);

    //Copy the ends into the flowers.
    end_copyConstruct(end, flower2);
    end_copyConstruct(end2, flower2);
    end_copyConstruct(end, flower3);
    end_setGroup(flower_getEnd(flower2, end_getName(end2)), group3b);
    end_copyConstruct(end, flower4);

    //st_uglyf("I got %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 "\n", flower_getName(flower), flower_getName(flower2), flower_getName(flower3), flower_getName(flower4));

    //Write the mess to disk.
    cactusDisk_write(cactusDisk);

    //Now test the removal function (check we get a negative on this leaf).
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower4));
    //Check we can't remove the root..
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower));

    //We will remove flower2

    //Before
    CuAssertTrue(testCase, flower_getGroupNumber(flower) == 1);
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower2)) == flower);

    CuAssertTrue(testCase, flower_removeIfRedundant(flower2));

    //After, check the flower/group connections
    CuAssertTrue(testCase, flower_getGroupNumber(flower) == 2);
    CuAssertTrue(testCase, !flower_isLeaf(flower));
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower3)) == flower);
    group3b = end_getGroup(end2);
    CuAssertTrue(testCase, group_getFlower(group3b) == flower);
    CuAssertTrue(testCase, group_isLeaf(group3b));
    CuAssertTrue(testCase, flower_getGroup(flower, flower_getName(flower3)) == flower_getParentGroup(flower3));
    //Check the ends..
    CuAssertTrue(testCase, flower_getEndNumber(flower) == 2);
    CuAssertTrue(testCase, flower_getEndNumber(flower3) == 1);
    CuAssertTrue(testCase, group_getEndNumber(group3b) == 1);
    CuAssertTrue(testCase, end_getGroup(end) == flower_getParentGroup(flower3));
    CuAssertTrue(testCase, end_getGroup(end2) == group3b);
    CuAssertTrue(testCase, flower_getEnd(flower3, end_getName(end)) != NULL);
    //Check the child of 3 is still okay..
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower4)) == flower3);

    //Now do removal of flower3
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower));
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower4));
    CuAssertTrue(testCase, flower_removeIfRedundant(flower3));
    //Check groups again
    CuAssertTrue(testCase, flower_getGroupNumber(flower) == 2);
    CuAssertTrue(testCase, !flower_isLeaf(flower));
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower4)) == flower);
    CuAssertTrue(testCase, group_getFlower(group3b) == flower);
    CuAssertTrue(testCase, flower_getGroup(flower, flower_getName(flower4)) == flower_getParentGroup(flower4));
    //Check the ends again..
    CuAssertTrue(testCase, flower_getEndNumber(flower) == 2);
    CuAssertTrue(testCase, flower_getEndNumber(flower4) == 1);
    CuAssertTrue(testCase, group_getEndNumber(group3b) == 1);
    CuAssertTrue(testCase, end_getGroup(end) == flower_getParentGroup(flower4));
    CuAssertTrue(testCase, end_getGroup(end2) == group3b);
    CuAssertTrue(testCase, flower_getEnd(flower4, end_getName(end)) != NULL);

    cactusFlowerTestTeardown();
}