From 472e8cc8ecb53907fe45f7f8c8e8d2d356587846 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 2 Apr 2026 16:54:02 +0200 Subject: [PATCH 1/3] tests --- .gitea/workflow/tests_basics.c | 28 ++++ .../Fundamentals/basics/basics.c | 8 +- tests/test_basic.c | 151 ++++++++++++++++++ 3 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 .gitea/workflow/tests_basics.c create mode 100644 tests/test_basic.c diff --git a/.gitea/workflow/tests_basics.c b/.gitea/workflow/tests_basics.c new file mode 100644 index 0000000..ad1659b --- /dev/null +++ b/.gitea/workflow/tests_basics.c @@ -0,0 +1,28 @@ +name: Tests Basics avec Criterion + +on: [push] + +jobs: + test: + runs-on: ubuntu-latest + container: + image: git.blackbucket.fr/lucas/epita_tp_c:latest + + steps: + - name: installation de l'env + run: pacman -Syu --noconfirm nodejs git gcc criterion + + - name: checkout + uses: actions/checkout@v4 + + - name: Compilation + run: > + gcc -Wall -Wextra + -I./Chains_across_the_Island/Fundamentals/basics + -o test + Chains_across_the_Island/Fundamentals/basics/basics.c + tests/test_basics.c + -lcriterion -fsanitize=address -g + + - name: Tests + run: ./test diff --git a/Chains_across_the_Island/Fundamentals/basics/basics.c b/Chains_across_the_Island/Fundamentals/basics/basics.c index 0160f51..93a59f9 100644 --- a/Chains_across_the_Island/Fundamentals/basics/basics.c +++ b/Chains_across_the_Island/Fundamentals/basics/basics.c @@ -13,7 +13,7 @@ struct list *list_append(struct list *l, int e) new_node->data = e; if(!l) return new_node; - while (tmp->next) tmp = tmp->next; + while (tmp->next != NULL) tmp = tmp->next; tmp->next = new_node; return l; @@ -21,17 +21,17 @@ struct list *list_append(struct list *l, int e) size_t list_count(struct list *l){ int nbr_nodes = 0; - if (!l) return nbr_nodes; + //if (!l) return nbr_nodes; struct list *tmp = l; //nbr_nodes ++; - while(tmp->next != NULL) { + while(tmp != NULL) { nbr_nodes ++; tmp = tmp->next; } - return nbr_nodes + 1; + return nbr_nodes; } diff --git a/tests/test_basic.c b/tests/test_basic.c new file mode 100644 index 0000000..1a07ae5 --- /dev/null +++ b/tests/test_basic.c @@ -0,0 +1,151 @@ +#include +#include +#include "../Chains_across_the_Island/Fundamentals/basics/basics.h" + +// Test pour list_append +Test(basics_suite, test_append) { + struct list *l = NULL; + + l = list_append(l, 42); + cr_assert_not_null(l, "la liste ne peux pas etre null apres un ajout"); + cr_assert_eq(l->data, 42, "la data du 1er noeud doit être 42"); + + l = list_append(l, 7); + cr_assert_not_null(l->next, "le deuxième noeud doit exister"); + cr_assert_eq(l->next->data, 7, "la data du 2 eme noeud doit etre 7"); + + list_destroy(l); +} + +// Test pour list_count +Test(basics_suite, test_count) { + struct list *l = NULL; + + cr_assert_eq(list_count(l), 0, "Une liste vide doit avoir une taille de 0."); + + l = list_append(l, 10); + l = list_append(l, 20); + l = list_append(l, 30); + + cr_assert_eq(list_count(l), 3, "La liste doit contenir 3 éléments."); + list_destroy(l); +} + +// Test pour list_insert +Test(basics_suite, test_insert) { + struct list *l = NULL; + + int res1 = list_insert(&l, 0, 100); + cr_assert_eq(res1, 0, "L'insertion à l'index 0 doit réussir."); + cr_assert_not_null(l, "La liste ne doit pas être NULL."); + cr_assert_eq(l->data, 100, "La valeur insérée doit être 100."); + + int res2 = list_insert(&l, 5, 200); + cr_assert_eq(res2, 1, "L'insertion hors limite doit échouer et renvoyer 1."); + + list_destroy(l); +} + +//Test pour list_get +Test(basics_suite, test_get){ + struct list *l = NULL; + + l = list_append(l, 30); + l = list_append(l, 20); + l = list_append(l, 10); // L'ordre final est [30] -> [20] -> [10] + + struct list *rslt = list_get(l, 0); + cr_assert_not_null(rslt, "Le pointeur ne doit pas être NULL pour l'index 0"); + cr_assert_eq(rslt->data, 30, "pointer to node with data=30"); + + rslt = list_get(l, 2); + cr_assert_not_null(rslt, "Le pointeur ne doit pas être NULL pour l'index 2"); + cr_assert_eq(rslt->data, 10, "pointer to node with data=10"); + + rslt = list_get(l, 5); + cr_assert_null(rslt, "Le pointeur doit etre null"); + + list_destroy(l); + // On ne détruit SURTOUT PAS rslt ici, car il appartient déjà à l ! +} + +//Test list_find +Test(basics_suite, test_find){ + struct list *l = NULL; + + l = list_append(l, 3); + l = list_append(l, 7); + l = list_append(l, 1); + + struct list *rslt = list_find(l, 7); + cr_assert_not_null(rslt, "Le noeud doit être trouvé"); + cr_assert_eq(rslt->data, 7, "pointer to node with data=7"); + + rslt = list_find(l, 42); + cr_assert_null(rslt, "pointeur doit etre null"); + + list_destroy(l); +} + +//Test list_delete_at +Test(basics_suite, test_delete_at){ + struct list *l = NULL; + + l = list_append(l, 30); + l = list_append(l, 20); + l = list_append(l, 10); // [30] -> [20] -> [10] + + struct list *rslt = NULL; + + rslt = list_delete_at(&l, 1); // Retire le 20. l devient [30] -> [10] + cr_assert_not_null(rslt, "Le noeud retiré ne doit pas être NULL"); + cr_assert_eq(rslt->data, 20, "La data du noeud supprimé doit etre de 20"); + + size_t count = list_count(l); + cr_assert_eq(count, 2, "La taille de la liste doit etre de 2"); + + struct list *tmp = list_get(l, 0); + cr_assert_not_null(tmp, "Le noeud 0 ne doit pas être NULL"); + cr_assert_eq(tmp->data, 30, "La data du noeud 1 doit etre de 30"); + + tmp = list_get(l, 1); + cr_assert_not_null(tmp, "Le noeud 1 ne doit pas être NULL"); + cr_assert_eq(tmp->data, 10, "La data du noeud 2 doit etre de 10"); + + tmp = list_get(l, 3); + cr_assert_null(tmp, "Le pointeur doit etre null"); + + list_destroy(l); + free(rslt); // rslt est totalement détaché de l, on le libère avec un simple free() +} + +//Test list_remove +Test(basics_suite, test_list_remove){ + struct list *l = NULL; + + l = list_append(l, 7); + l = list_append(l, 3); + l = list_append(l, 7); + l = list_append(l, 1); // [7] -> [3] -> [7] -> [1] + + int rm = list_remove(&l, 7); // Retire le premier 7. l devient [3] -> [7] -> [1] + cr_assert_eq(rm, 1, "Le noeud 7 doit etre supprimé"); + + struct list *tmp = list_get(l, 0); + cr_assert_not_null(tmp, "Le noeud 0 existe"); + cr_assert_eq(tmp->data, 3, "Le noeud 1 a changé et devient 3 !"); + + tmp = list_get(l, 1); + cr_assert_not_null(tmp, "Le noeud 1 existe"); + cr_assert_eq(tmp->data, 7, "Le noeud 2 doit etre egal a 7"); + + tmp = list_get(l, 2); + cr_assert_not_null(tmp, "Le noeud 2 existe"); + cr_assert_eq(tmp->data, 1, "Le 3 eme noeud doit etre de 1"); + + rm = list_remove(&l, 42); + cr_assert_eq(rm, 0, "Doit renvoyer 0 car 42 n'existe pas !"); + + list_destroy(l); +} + -- 2.52.0 From 3ffa5c3bad2bcec9aa86ce4621a441939c4e4b38 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 2 Apr 2026 16:56:26 +0200 Subject: [PATCH 2/3] test --- tests/{test_basic.c => test_basics.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test_basic.c => test_basics.c} (100%) diff --git a/tests/test_basic.c b/tests/test_basics.c similarity index 100% rename from tests/test_basic.c rename to tests/test_basics.c -- 2.52.0 From 3d0dd9e99376cfa5e2fa616d6acbc739e1f51dff Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 2 Apr 2026 19:00:43 +0200 Subject: [PATCH 3/3] retout --- .../Fundamentals/basics/basics.c | 28 +++++++++++------- .../Fundamentals/basics/test | Bin 20896 -> 20720 bytes 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Chains_across_the_Island/Fundamentals/basics/basics.c b/Chains_across_the_Island/Fundamentals/basics/basics.c index 93a59f9..c1db8ea 100644 --- a/Chains_across_the_Island/Fundamentals/basics/basics.c +++ b/Chains_across_the_Island/Fundamentals/basics/basics.c @@ -5,6 +5,15 @@ struct list *list_append(struct list *l, int e) { + + struct list *new_node = malloc(sizeof(struct list)); + if(!new_node) return NULL; + + new_node->data = e; + new_node->next = l; + + return new_node; +/* struct list *tmp = l; struct list *new_node = calloc(1, sizeof(struct list)); @@ -16,7 +25,7 @@ struct list *list_append(struct list *l, int e) while (tmp->next != NULL) tmp = tmp->next; tmp->next = new_node; return l; - + */ } size_t list_count(struct list *l){ @@ -162,26 +171,23 @@ void list_print(struct list *l){ } printf("\n"); } -/* + int main(void) { struct list *l = NULL; - l = list_append(l, 42); // l = [42] -> NULL - list_print(l); - l = list_append(l, 7); // l = [7] -> [42] -> NULL - list_print(l); + l = list_append(l, 3); + l = list_append(l, 2); + l = list_append(l, 1); - // l = [1] -> [2] -> [3] + // l = [1] -> [2] -> [3] list_insert(&l, 1, 99); // l = [1] -> [99] -> [2] -> [3], and list_insert returns 0 list_insert(&l, 9, 99); // list unchanged, returns 1 + list_print(l); - list_count(NULL); // 0 - printf("count : %li\n",list_count(l)); // 3 - list_destroy(l); return 0; } -*/ + diff --git a/Chains_across_the_Island/Fundamentals/basics/test b/Chains_across_the_Island/Fundamentals/basics/test index ed2becae6a4790aae62c8c5241b3cddb0aa9fb24..cd4545873a4e891e6045f549a6aa3e90a57f69c0 100755 GIT binary patch literal 20720 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 literal 20896 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 cuI7L_Kcf9(^b -- 2.52.0