package collection; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class ArbreBinaireRechercheTest { private ArbreBinaireRecherche arbre; @BeforeEach void setUp() { arbre = new ArbreBinaireRecherche<>(); } @Test void testAdd() { assertTrue(arbre.add(5)); assertTrue(arbre.add(3)); assertTrue(arbre.add(7)); assertFalse(arbre.add(5)); // doublon assertEquals(3, arbre.size()); } @Test void testContains() { arbre.add(5); arbre.add(2); arbre.add(8); assertTrue(arbre.contains(5)); assertTrue(arbre.contains(2)); assertFalse(arbre.contains(10)); assertFalse(arbre.contains(null)); } @Test void testRemoveFeuille() { arbre.add(5); arbre.add(3); arbre.add(8); assertTrue(arbre.remove(3)); assertFalse(arbre.contains(3)); assertEquals(2, arbre.size()); } @Test void testRemoveNoeudAvecUnEnfant() { arbre.add(5); arbre.add(3); arbre.add(2); // enfant de 3 assertTrue(arbre.remove(3)); assertTrue(arbre.contains(2)); assertFalse(arbre.contains(3)); assertEquals(2, arbre.size()); } @Test void testRemoveNoeudDeuxEnfants() { arbre.add(5); arbre.add(3); arbre.add(7); arbre.add(6); arbre.add(8); assertTrue(arbre.remove(7)); assertFalse(arbre.contains(7)); assertEquals(4, arbre.size()); } @Test void testIteratorOrdreCroissant() { arbre.add(5); arbre.add(2); arbre.add(8); arbre.add(1); arbre.add(3); Iterator it = arbre.iterator(); assertEquals(1, it.next()); assertEquals(2, it.next()); assertEquals(3, it.next()); assertEquals(5, it.next()); assertEquals(8, it.next()); assertFalse(it.hasNext()); } @Test void testClear() { arbre.add(4); arbre.add(1); arbre.add(9); arbre.clear(); assertTrue(arbre.isEmpty()); assertEquals(0, arbre.size()); assertFalse(arbre.contains(4)); } @Test void testToArray() { arbre.add(3); arbre.add(1); arbre.add(2); Object[] arr = arbre.toArray(); assertEquals(3, arr.length); assertArrayEquals(new Object[] { 1, 2, 3 }, arr); } @Test void testAddAll() { List list = Arrays.asList(5, 2, 8); assertTrue(arbre.addAll(list)); assertEquals(3, arbre.size()); assertTrue(arbre.contains(8)); } @Test void testRemoveAll() { arbre.add(5); arbre.add(2); arbre.add(8); List list = Arrays.asList(2, 8); assertTrue(arbre.removeAll(list)); assertFalse(arbre.contains(2)); assertFalse(arbre.contains(8)); assertTrue(arbre.contains(5)); } @Test void testRetainAll() { arbre.add(5); arbre.add(2); arbre.add(8); List list = Arrays.asList(5); assertTrue(arbre.retainAll(list)); assertTrue(arbre.contains(5)); assertFalse(arbre.contains(2)); assertFalse(arbre.contains(8)); assertEquals(1, arbre.size()); } @Test void testContainsAvecTypeIncorrect() { arbre.add(5); arbre.add(3); // Un type incompatible doit entraîner catch(ClassCastException) → false assertFalse(arbre.contains("texte")); // String ≠ Integer } @Test void testRemoveNull() { arbre.add(5); assertFalse(arbre.remove(null)); // ne doit jamais lancer d’exception assertEquals(1, arbre.size()); assertTrue(arbre.contains(5)); } @Test void testRemoveRacineNull() { // racine = null assertTrue(arbre.isEmpty()); assertFalse(arbre.remove(10)); // retirer un élément dans un arbre vide => false assertTrue(arbre.isEmpty()); } @Test void testRemoveSansException() { arbre.add(10); arbre.add(5); arbre.add(15); // Cas normaux assertDoesNotThrow(() -> arbre.remove(5)); assertDoesNotThrow(() -> arbre.remove(15)); assertDoesNotThrow(() -> arbre.remove(10)); // Retrait sur arbre vide assertDoesNotThrow(() -> arbre.remove(999)); // Retrait d’un null assertDoesNotThrow(() -> arbre.remove(null)); } @Test void testRemoveAvecSuccesseurProfond() { arbre.add(10); arbre.add(5); arbre.add(20); arbre.add(15); arbre.add(13); // successeur profond // Suppression du nœud ayant deux enfants assertTrue(arbre.remove(10)); // Le successeur (13) doit avoir remplacé la racine Iterator it = arbre.iterator(); assertEquals(5, it.next()); assertEquals(13, it.next()); // remplace 10 assertEquals(15, it.next()); assertEquals(20, it.next()); assertFalse(it.hasNext()); } @Test void testRemoveRacineAvecUnEnfant() { arbre.add(10); arbre.add(20); // enfant droit unique assertTrue(arbre.remove(10)); // La racine doit être remplacée par l’enfant (20) assertEquals(20, arbre.iterator().next()); assertEquals(1, arbre.size()); } @Test void testIsEmpty() { ArbreBinaireRecherche a = new ArbreBinaireRecherche<>(); // L'arbre vide assertTrue(a.isEmpty()); // Après insertion a.add(1); assertFalse(a.isEmpty()); // Après suppression a.remove(1); assertTrue(a.isEmpty()); } @Test void testToArrayComplet() { arbre.add(4); arbre.add(1); arbre.add(3); arbre.add(2); Object[] arr = arbre.toArray(); assertEquals(4, arr.length); assertArrayEquals(new Object[] { 1, 2, 3, 4 }, arr); // Vérification cohérence avec iterator() int index = 0; for (int value : arbre) { assertEquals(value, arr[index++]); } } @Test void testContainsAll() { arbre.add(5); arbre.add(2); arbre.add(8); // Tous présents assertTrue(arbre.containsAll(Arrays.asList(2, 5))); // Un absent assertFalse(arbre.containsAll(Arrays.asList(2, 10))); // Collection vide → doit être true assertTrue(arbre.containsAll(Arrays.asList())); // Mauvais type → contains(o) doit retourner false assertFalse(arbre.containsAll(Arrays.asList("test"))); } @Test void testToArrayGenericRetourNull() { arbre.add(5); arbre.add(2); arbre.add(9); Integer[] cible = new Integer[3]; // L’implémentation actuelle doit renvoyer null assertNull(arbre.toArray(cible)); } }