/* Cas limites et comparaisons avec des algorithmes de référence simples. */ #define main banque_main #include "../banque.c" #undef main #include #include static int comparer_reference(const void *a, const void *b) { const Transaction *ta = a; const Transaction *tb = b; if (ta->montant < tb->montant) return -1; if (ta->montant > tb->montant) return 1; if (ta->id < tb->id) return -1; return ta->id > tb->id; } static void verifier_tri(Transaction *t, int n) { Transaction attendu[128]; assert(n <= 128); memcpy(attendu, t, (size_t)n * sizeof(*t)); qsort(attendu, (size_t)n, sizeof(*attendu), comparer_reference); trier_par_montant(t, n); for (int i = 0; i < n; i++) { assert(t[i].id == attendu[i].id); assert(t[i].client == attendu[i].client); assert(t[i].jour == attendu[i].jour); assert(t[i].montant == attendu[i].montant); } } static void tester_tri(void) { trier_par_montant(NULL, 0); Transaction limites[] = { {INT_MAX, 1, 2, LONG_MAX}, {3, 4, 5, 0}, {INT_MIN, 6, 7, LONG_MIN}, {1, 8, 9, 0}, {2, 10, 11, LONG_MAX} }; verifier_tri(limites, 5); verifier_tri(limites, 5); /* déjà trié */ Transaction t[128]; for (int n = 1; n <= 128; n++) { for (int i = 0; i < n; i++) t[i] = (Transaction){n - i, i, i + 1, (i * 37) % 11 - 5}; verifier_tri(t, n); for (int i = 0; i < n; i++) t[i] = (Transaction){i, i, i + 1, n - i}; verifier_tri(t, n); /* ordre inverse */ } } static void tester_clients_distincts(void) { assert(nb_clients_distincts(NULL, 0) == 0); Transaction t[NB_CLIENTS]; for (int i = 0; i < NB_CLIENTS; i++) t[i] = (Transaction){i, NB_CLIENTS - 1, 0, 0}; assert(nb_clients_distincts(t, NB_CLIENTS) == 1); t[0].client = 0; assert(nb_clients_distincts(t, NB_CLIENTS) == 2); for (int i = 0; i < NB_CLIENTS; i++) t[i].client = i; assert(nb_clients_distincts(t, NB_CLIENTS) == NB_CLIENTS); assert(nb_clients_distincts(t, 1) == 1); } static void tester_totaux_clients(void) { Transaction t[] = { {0, 0, 0, 100}, {1, NB_CLIENTS - 1, 1, -50}, {2, 0, 2, -40}, {3, NB_CLIENTS - 1, 3, 50}, {4, 7, 4, 0} }; long totaux[NB_CLIENTS]; for (int i = 0; i < NB_CLIENTS; i++) totaux[i] = 123; total_par_client(t, 5, totaux); for (int c = 0; c < NB_CLIENTS; c++) { long attendu = 0; for (int i = 0; i < 5; i++) if (t[i].client == c) attendu += t[i].montant; assert(totaux[c] == attendu); } total_par_client(NULL, 0, totaux); for (int c = 0; c < NB_CLIENTS; c++) assert(totaux[c] == 0); } static void tester_totaux_jours(void) { Transaction t[] = { {0, 0, NB_JOURS - 1, 100}, {1, 1, 0, -50}, {2, 2, NB_JOURS - 1, -40}, {3, 3, 0, 50}, {4, 4, 7, 0} }; long totaux[NB_JOURS]; for (int i = 0; i < NB_JOURS; i++) totaux[i] = 123; total_par_jour(t, 5, totaux); for (int j = 0; j < NB_JOURS; j++) { long attendu = 0; for (int i = 0; i < 5; i++) if (t[i].jour == j) attendu += t[i].montant; assert(totaux[j] == attendu); } total_par_jour(NULL, 0, totaux); for (int j = 0; j < NB_JOURS; j++) assert(totaux[j] == 0); } static long periode_reference(const long *t, int n, int *debut, int *fin) { long meilleur = t[0]; *debut = 0; *fin = 0; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { long somme = 0; for (int k = i; k <= j; k++) somme += t[k]; if (somme > meilleur) { meilleur = somme; *debut = i; *fin = j; } } } return meilleur; } static void tester_periodes(void) { long t[7]; int nb_cas = 1; for (int n = 1; n <= 7; n++) { nb_cas *= 5; for (int cas = 0; cas < nb_cas; cas++) { int valeurs = cas; for (int i = 0; i < n; i++) { t[i] = valeurs % 5 - 2; valeurs /= 5; } int debut, fin, debut_attendu, fin_attendue; long attendu = periode_reference(t, n, &debut_attendu, &fin_attendue); assert(meilleure_periode(t, n, &debut, &fin) == attendu); assert(debut == debut_attendu); assert(fin == fin_attendue); } } } static void tester_recherches(void) { assert(rechercher_par_id(NULL, 0, 0) == NULL); assert(rechercher_par_id(NULL, 0, -1) == NULL); Transaction t[128]; const Transaction *index_ids[128]; for (int n = 1; n <= 128; n++) { for (int i = 0; i < n; i++) t[i] = (Transaction){n - 1 - i, i, i, i * 77 - 12}; indexer_par_id(t, n, index_ids); for (int id = 0; id < n; id++) { const Transaction *attendu = NULL; for (int i = 0; i < n; i++) if (t[i].id == id) attendu = &t[i]; assert(rechercher_par_id(index_ids, n, id) == attendu); } assert(rechercher_par_id(index_ids, n, -1) == NULL); assert(rechercher_par_id(index_ids, n, n) == NULL); assert(rechercher_par_id(index_ids, n, INT_MAX) == NULL); } } static long paires_reference(const Transaction *t, int n) { long nb = 0; for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) if (t[i].montant + t[j].montant == 0) nb++; return nb; } static void tester_paires(void) { assert(nb_paires_opposees(NULL, 0) == 0); Transaction t[7], original[7]; int nb_cas = 1; for (int n = 1; n <= 7; n++) { nb_cas *= 5; for (int cas = 0; cas < nb_cas; cas++) { int valeurs = cas; for (int i = 0; i < n; i++) { t[i] = (Transaction){i, i, i, valeurs % 5 - 2}; valeurs /= 5; } memcpy(original, t, (size_t)n * sizeof(*t)); assert(nb_paires_opposees(t, n) == paires_reference(t, n)); assert(memcmp(original, t, (size_t)n * sizeof(*t)) == 0); } } } static long monnaie_reference(int somme, int nb_pieces) { if (somme == 0) return 1; if (somme < 0 || nb_pieces == 0) return 0; return monnaie_reference(somme - PIECES[nb_pieces - 1], nb_pieces) + monnaie_reference(somme, nb_pieces - 1); } static void tester_monnaie(void) { for (int s = -2; s <= 40; s++) for (int k = 0; k <= NB_PIECES; k++) assert(nb_facons_rendre(s, k) == monnaie_reference(s, k)); } int main(void) { tester_tri(); tester_clients_distincts(); tester_totaux_clients(); tester_totaux_jours(); tester_periodes(); tester_recherches(); tester_paires(); tester_monnaie(); puts("Tests banque : OK"); return 0; }