gur111 icon

Mtm Spring 2020 Ex1 Dry Pt1 Tester

gur111 | PRO | 04/09/20 06:19:43 PM UTC | 0 ⭐ | 1077 👁️ | Never ⏰ | []
C |

6.87 KB

|

None

|

0 👍

/

0 👎

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
 
#include "q1.h"
 
#define LIST_AS_STR_MAX_SIZE 3000
#define NODE_AS_STR_MAX_SIZE 50
 
Node copyNode(Node n) {
    Node newNode = malloc(sizeof(*n));
    newNode->x = n->x;
    return newNode;
}
 
void freeListSol(Node list) {
    if (list == NULL) {
        return;
    }
    Node prev;
    while (list) {
        prev = list;
        list = list->next;
        free(prev);
    }
}
 
int getListLength(Node list) {
    int count = 0;
 
    while (list) {
        count++;
        list = list->next;
    }
    return count;
}
 
bool isListSorted(Node list) {
    if (list == NULL) {
        return true;
    }
 
    int prev = list->x;
    list = list->next;
 
    while (list != NULL) {
        if (prev > list->x) {
            return false;
        }
        prev = list->x;
        list = list->next;
    }
 
    return true;
}
 
Node copyList(Node list) {
    Node head = malloc(sizeof(*head)), curr = head;
    head->next = NULL;
 
    while (list) {
        curr->next = malloc(sizeof(*curr));
        curr = curr->next;
        curr->next = NULL;
        curr->x = list->x;
        list = list->next;
    }
 
    if (curr == head) {
        free(head);
        return NULL;
    }
    curr = head->next;
    free(head);
 
    return curr;
}
 
Node sortedMergeSol(Node a, Node b) {
    Node result = NULL; /* Base cases */
    if (a == NULL)
        return copyList(b);
    else if (b == NULL)
        return copyList(a); /* Pick either a or b, and recur */
    if (a->x <= b->x) {
        result = copyNode(a);
        result->next = sortedMergeSol(a->next, b);
    } else {
        result = copyNode(b);
        result->next = sortedMergeSol(a, b->next);
    }
    return (result);
}
 
char *listToString(Node list) {
    char *str = malloc(sizeof(char) * LIST_AS_STR_MAX_SIZE);
    assert(str != NULL);
    str[0] = '\0';
    char buff[NODE_AS_STR_MAX_SIZE];
 
    while (list != NULL) {
        sprintf(buff, "%d->", list->x);
        strncat(str, buff, NODE_AS_STR_MAX_SIZE);
        list = list->next;
    }
    strcat(str, "NULL");
    return str;
}
 
bool areListsEqual(Node list1, Node list2) {
    while (list1 != NULL || list2 != NULL) {
        if (list1 == NULL || list2 == NULL || list1->x != list2->x) {
            return false;
        }
        list1 = list1->next;
        list2 = list2->next;
    }
    return true;
}
 
bool testOnce(int test_num) {
    Node lists[] = {malloc(sizeof(*lists[0])), malloc(sizeof(*lists[1]))};
    for (int i = 0; i < 2; i++) {
        Node curr = lists[i];
        curr->x = rand() % 100 - 40;
        int count = rand() % 20;  // Random length for the list
        int tmp_value;
        while (count > 0) {
            curr->next = malloc(sizeof(*lists[i]));
            // tmp_value = rand() % 1;
            tmp_value = rand() % 400;
            tmp_value = tmp_value ? (rand() % 5) : (-1);
            curr->next->x =
                curr->x +
                tmp_value;  // Generate a series which is likely rising
            curr = curr->next;
            count--;
        }
        curr->next = NULL;
        curr = lists[i];
        lists[i] = lists[i]->next;
        free(curr);
    }
 
    char *list1_before = listToString(lists[0]);
    char *list2_before = listToString(lists[1]);
    // printf("List1 before:\n\t%s\n", list1_before);
 
    Node merged_actual = NULL, merged_expected = NULL;
    Node *merge_actual_address = (rand() % 10) ? &merged_actual : NULL;
    ErrorCode merge_status =
        mergeSortedLists(lists[0], lists[1], merge_actual_address);
    char *list1_after = listToString(lists[0]);
    char *list2_after = listToString(lists[1]);
    if (merge_actual_address && lists[0] && lists[1] &&
        isListSorted(lists[0]) && isListSorted(lists[1])) {
        merged_expected = sortedMergeSol(lists[0], lists[1]);
    }
 
    bool status = true;
    if (lists[0] == NULL || lists[1] == NULL) {
        if (merge_status != EMPTY_LIST) {
            printf("Extecped status EMPTY_LIST (%d) but got %d\n", EMPTY_LIST,
                   merge_status);
            status = false;
        }
    } else if (!isListSorted(lists[0]) || !isListSorted(lists[1])) {
        if (merge_status != UNSORTED_LIST) {
            printf("Extecped status UNSORTED_LIST (%d) but got %d\n",
                   UNSORTED_LIST, merge_status);
            status = false;
        }
    } else if (merge_actual_address == NULL) {
        if (merge_status != NULL_ARGUMENT) {
            printf("Extecped status NULL_ARGUMENT (%d) but got %d\n",
                   NULL_ARGUMENT, merge_status);
            status = false;
        }
    } else if (merge_status == MEMORY_ERROR) {
        if (merged_actual != NULL) {
            printf(
                "Extecped merged_actual (MEMORY_ERROR) to be NULL but got %p\n",
                (void *)merged_actual);
            status = false;
        }
    } else {
        status = status && areListsEqual(merged_actual, merged_expected);
    }
    char *merged_expected_str = NULL, *merged_actual_str = NULL;
 
    if (strcmp(list1_before, list1_after) ||
        strcmp(list2_before, list2_after) || !status) {
        fprintf(stderr, "\n\n======= Test #%d Failed ========\n", test_num);
 
        fprintf(stderr, "List1 before:\n");
        fprintf(stderr, "\t%s\n", list1_before);
        fprintf(stderr, "List2 before:\n");
        fprintf(stderr, "\t%s\n", list2_before);
 
        fprintf(stderr, "List1 after:\n");
        fprintf(stderr, "\t%s\n", list1_after);
        fprintf(stderr, "List2 after:\n");
        fprintf(stderr, "\t%s\n", list2_after);
 
        fprintf(stderr, "Merged expected:\n");
        merged_expected_str = listToString(merged_expected);
        fprintf(stderr, "\t%s\n", merged_expected_str);
        fprintf(stderr, "Merged actual:\n");
        merged_actual_str = listToString(merged_actual);
        fprintf(stderr, "\t%s\n", merged_actual_str);
        status = false;
    }
    free(list1_before);
    free(list1_after);
    free(list2_before);
    free(list2_after);
    free(merged_expected_str);
    free(merged_actual_str);
 
    freeListSol(merged_actual);
    freeListSol(merged_expected);
    freeListSol(lists[0]);
    freeListSol(lists[1]);
    return status;
}
 
void printUsage(char *name) { printf("Usage:\n%s [NUM_OF_TESTS]\n", name); }
 
int main(int argc, char **argv) {
    int count = 0, failures = 0;
 
    if (argc == 2 && sscanf(argv[1], "%d", &count) == 1) {
        printf("Running %d random tests...\n", count);
    } else {
        printUsage(argv[0]);
        return 1;
    }
    srand(time(0));
 
    for (int i = 0; i < count; i++) {
        if (!testOnce(i)) {
            failures++;
        }
    }
 
    printf("%d failures out of %d tests\n", failures, count);
}

Comments