// Pruebas del módulo en C. En el paso 4 las pasan a lab/test_grade_book.cpp.
#include <assert.h>
#include <stdio.h>
#include <string.h>

#include "grade_book.h"

static void test_starts_empty(void) {
    GradeBook *book = grade_book_new();
    assert(book != NULL);
    assert(grade_book_size(book) == 0);
    assert(grade_book_get(book, "Ana") == -1);
    assert(grade_book_name_at(book, 0) == NULL);
    grade_book_free(book);
}

static void test_add_and_get(void) {
    GradeBook *book = grade_book_new();
    assert(grade_book_add(book, "Ana", 14) == 1);
    assert(grade_book_add(book, "Luis", 9) == 1);
    assert(grade_book_size(book) == 2);
    assert(grade_book_get(book, "Ana") == 14);
    assert(grade_book_get(book, "Luis") == 9);
    assert(strcmp(grade_book_name_at(book, 1), "Luis") == 0);
    grade_book_free(book);
}

static void test_rejects_invalid(void) {
    GradeBook *book = grade_book_new();
    assert(grade_book_add(book, "Ana", -1) == 0);
    assert(grade_book_add(book, "Ana", 21) == 0);
    assert(grade_book_add(book, "", 10) == 0);
    assert(grade_book_size(book) == 0);
    assert(grade_book_add(book, "Ana", 0) == 1);
    assert(grade_book_add(book, "Ana", 20) == 0);
    assert(grade_book_get(book, "Ana") == 0);
    assert(grade_book_size(book) == 1);
    grade_book_free(book);
}

static void test_set(void) {
    GradeBook *book = grade_book_new();
    assert(grade_book_add(book, "Ana", 14) == 1);
    assert(grade_book_set(book, "Ana", 20) == 1);
    assert(grade_book_get(book, "Ana") == 20);
    assert(grade_book_set(book, "Ana", 21) == 0);
    assert(grade_book_get(book, "Ana") == 20);
    assert(grade_book_set(book, "Luis", 10) == 0);
    assert(grade_book_size(book) == 1);
    grade_book_free(book);
}

static void test_remove_keeps_order(void) {
    GradeBook *book = grade_book_new();
    assert(grade_book_add(book, "Ana", 14) == 1);
    assert(grade_book_add(book, "Luis", 9) == 1);
    assert(grade_book_add(book, "Rosa", 17) == 1);
    assert(grade_book_remove(book, "Luis") == 1);
    assert(grade_book_remove(book, "Luis") == 0);
    assert(grade_book_size(book) == 2);
    assert(strcmp(grade_book_name_at(book, 0), "Ana") == 0);
    assert(strcmp(grade_book_name_at(book, 1), "Rosa") == 0);
    grade_book_free(book);
}

static void test_keeps_its_own_copy_of_the_name(void) {
    GradeBook *book = grade_book_new();
    char name[] = "Ana";
    assert(grade_book_add(book, name, 14) == 1);
    name[0] = 'E';
    assert(grade_book_get(book, "Ana") == 14);
    assert(grade_book_get(book, "Ena") == -1);
    grade_book_free(book);
}

static void test_grows_past_initial_capacity(void) {
    GradeBook *book = grade_book_new();
    for (int i = 0; i < 100; i++) {
        char name[16];
        snprintf(name, sizeof name, "e%d", i);
        assert(grade_book_add(book, name, i % 21) == 1);
    }
    assert(grade_book_size(book) == 100);
    assert(grade_book_get(book, "e0") == 0);
    assert(grade_book_get(book, "e99") == 99 % 21);
    grade_book_free(book);
}

int main(void) {
    test_starts_empty();
    test_add_and_get();
    test_rejects_invalid();
    test_set();
    test_remove_keeps_order();
    test_keeps_its_own_copy_of_the_name();
    test_grows_past_initial_capacity();
    printf("módulo en C: todas las pruebas pasaron\n");
    return 0;
}
