content: package org.allaymc.server.datastruct.dag;
  
  import lombok.SneakyThrows;
  import org.junit.jupiter.api.BeforeAll;
  import org.junit.jupiter.api.Test;
  
  import java.util.*;
  
  import static org.junit.jupiter.api.Assertions.*;
  
  /**
   * @author Cool_Loong
   */
  public class HashDirectedAcyclicGraphTest {
      static HashDirectedAcyclicGraph<Base> setABCDEFG;
  
      @BeforeAll
      public static void setUp() {
          setABCDEFG = new HashDirectedAcyclicGraph<>();
          setABCDEFG.add(Base.A);
          setABCDEFG.add(Base.B);
          setABCDEFG.add(Base.C);
          setABCDEFG.add(Base.D);
          setABCDEFG.add(Base.E);
          setABCDEFG.add(Base.F);
          setABCDEFG.add(Base.G);
      }
  
      /**
       * Test of getBefore method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testGetBefore() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(setABCDEFG);
          // Test 1
          try {
              instance.setBefore(Base.A, Base.B);
              instance.setBefore(Base.F, Base.B);
              instance.setBefore(Base.G, Base.B);
              instance.setBefore(Base.B, Base.C);
              Set<Base> expResult = new HashSet<>();
              expResult.add(Base.A);
              expResult.add(Base.F);
              expResult.add(Base.G);
              Set<Base> result = instance.getBefore(Base.B);
              assertEquals(expResult, result);
          } catch (DAGCycleException ignore) {
          }
  
          // Test 2
          assertThrows(DAGCycleException.class, () -> {
              instance.setBefore(Base.B, Base.B);
          });
          // Test 3
          assertThrows(DAGCycleException.class, () -> {
              instance.setBefore(Base.C, Base.B);
          });
      }
  
      /**
       * Test of isBefore method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testIsBefore() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(setABCDEFG);
          try {
              instance.setBefore(Base.A, Base.B);
              instance.setBefore(Base.F, Base.B);
              instance.setBefore(Base.G, Base.B);
              instance.setBefore(Base.B, Base.C);
          } catch (Exception ignore) {
          }
  
          // Test 1
          assertTrue(instance.isBefore(Base.A, Base.B));
          // Test 2
          assertFalse(instance.isBefore(Base.B, Base.A));
          // Test 3
          assertFalse(instance.isBefore(Base.A, Base.A));
          // Test 4
          assertFalse(instance.isBefore(Base.A, Base.D));
          // Test 5
          assertFalse(instance.isBefore(Base.D, Base.A));
          // Test 6
          assertFalse(instance.isBefore(Base.D, Base.D));
          // Test 5
          assertTrue(instance.isBefore(Base.A, Base.C));
          // Test 6
          assertThrows(IllegalArgumentException.class, () -> instance.isBefore(Base.A, Base.H));
          // Test 7
          assertThrows(IllegalArgumentException.class, () -> instance.isBefore(Base.H, Base.A));
      }
  
      /**
       * Test of setBefore method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testSetBefore() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<Base>(setABCDEFG);
          // Test 1
          try {
              instance.setBefore(Base.C, Base.A);
              assertTrue(instance.isBefore(Base.C, Base.A));
          } catch (Exception ignore) {
          }
          // Test 2
          assertThrows(DAGCycleException.class, () -> {
              instance.setBefore(Base.A, Base.C);
          });
          // Test 3
          assertThrows(DAGCycleException.class, () -> {
              instance.setBefore(Base.A, Base.D);
              instance.setBefore(Base.D, Base.C);
          });
          // Test 4
          assertThrows(IllegalArgumentException.class, () -> {
              instance.setBefore(Base.A, Base.H);
          });
          // Test 5
          assertThrows(IllegalArgumentException.class, () -> {
              instance.setBefore(Base.H, Base.A);
          });
      }
  
      /**
       * Test of size method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testSize() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<Base>(setABCDEFG);
          assertEquals(7, instance.size());
      }
  
      /**
       * Test of isEmpty method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testIsEmpty() {
          // Test 1
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<Base>();
          assertTrue(instance.isEmpty());
          // Test 2
          instance = new HashDirectedAcyclicGraph<Base>(setABCDEFG);
          assertFalse(instance.isEmpty());
      }
  
      /**
       * Test of contains method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testContains() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>();
          // Test 1
          assertFalse(instance.contains(null));
          // Test 2
          assertFalse(instance.contains(Base.C));
  
          instance = new HashDirectedAcyclicGraph<>(setABCDEFG);
          // Test 3
          assertFalse(instance.contains(null));
          // Test 4
          assertTrue(instance.contains(Base.C));
          // Test 5
          assertFalse(instance.contains(Base.H));
      }
  
      /**
       * Test of iterator method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testIterator() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(setABCDEFG);
          HashSet<Base> used = new HashSet<>();
          Iterator<Base> iterator = instance.iterator();
          assertTrue(iterator.hasNext());
          Base next = iterator.next();
          iterator.remove();
          assertFalse(used.contains(next));
          used.add(next);
          assertTrue(iterator.hasNext());
          next = iterator.next();
          iterator.remove();
          assertFalse(used.contains(next));
          used.add(next);
          assertTrue(iterator.hasNext());
          next = iterator.next();
          iterator.remove();
          assertFalse(used.contains(next));
          used.add(next);
          assertTrue(iterator.hasNext());
          next = iterator.next();
          iterator.remove();
          assertFalse(used.contains(next));
          used.add(next);
          assertTrue(iterator.hasNext());
          next = iterator.next();
          iterator.remove();
          assertFalse(used.contains(next));
          used.add(next);
          assertTrue(iterator.hasNext());
          next = iterator.next();
          iterator.remove();
          assertFalse(used.contains(next));
          used.add(next);
          assertTrue(iterator.hasNext());
          next = iterator.next();
          iterator.remove();
          assertFalse(used.contains(next));
          used.add(next);
          assertFalse(iterator.hasNext());
          assertEquals(new HashDirectedAcyclicGraph<Base>(), instance);
      }
  
      /**
       * Test of toArray method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testToArrayZeroArgs() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<Base>(Base.A, Base.D, Base.H, Base.C);
          HashDirectedAcyclicGraph<Base> duplicate = new HashDirectedAcyclicGraph<Base>();
          Object[] result = instance.toArray();
          assertEquals(4, result.length);
          for (Object obj : result) {
              assertTrue(instance.contains((Base) obj));
              assertTrue(duplicate.add((Base) obj));
          }
          assertEquals(instance, duplicate);
      }
  
      /**
       * Test of toArray method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testToArrayNull() {
          Base[] prototype = new Base[0];
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<Base>(Base.A, Base.D, Base.H, Base.C);
          HashDirectedAcyclicGraph<Base> duplicate = new HashDirectedAcyclicGraph<Base>();
          Object[] result = instance.toArray(prototype);
          assertEquals(4, result.length);
          for (Object obj : result) {
              assertTrue(instance.contains((Base) obj));
              assertTrue(duplicate.add((Base) obj));
          }
          assertEquals(instance, duplicate);
      }
  
      /**
       * Test of add method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testAdd() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>();
          assertTrue(instance.isEmpty());
          assertTrue(instance.add(Base.B));
          assertTrue(instance.add(Base.D));
          assertTrue(instance.add(Base.H));
          assertFalse(instance.add(Base.H));
          assertTrue(instance.contains(Base.B));
          assertTrue(instance.contains(Base.D));
          assertTrue(instance.contains(Base.H));
          assertFalse(instance.contains(Base.A));
          assertFalse(instance.contains(Base.C));
          assertFalse(instance.contains(Base.E));
          assertFalse(instance.contains(Base.F));
          assertFalse(instance.contains(Base.G));
          assertThrows(NullPointerException.class, () -> instance.add(null));
      }
  
      /**
       * Test of remove method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testRemove() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<Base>(setABCDEFG);
          assertTrue(instance.remove(Base.B));
          assertTrue(instance.remove(Base.D));
          assertFalse(instance.remove(Base.D));
          assertFalse(instance.remove(Base.H));
          assertFalse(instance.contains(Base.B));
          assertFalse(instance.contains(Base.D));
          assertFalse(instance.contains(Base.H));
          assertTrue(instance.contains(Base.A));
          assertTrue(instance.contains(Base.C));
          assertTrue(instance.contains(Base.E));
          assertTrue(instance.contains(Base.F));
          assertTrue(instance.contains(Base.G));
      }
  
      /**
       * Test of containsAll method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testContainsAll() {
          Collection<Base> collection = new HashSet<>();
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(setABCDEFG);
          // Test 1
          assertTrue(instance.containsAll(collection));
          // Test 2
          collection.add(Base.B);
          collection.add(Base.D);
          collection.add(Base.E);
          assertTrue(instance.containsAll(collection));
          // Test 3
          collection.add(Base.H);
          assertFalse(instance.containsAll(collection));
      }
  
      /**
       * Test of addAll method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testAddAll() {
          // Test 1
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(Base.A, Base.B, Base.C);
          assertTrue(instance.addAll(new HashDirectedAcyclicGraph<>(Base.G, Base.H)));
          assertFalse(instance.addAll(new HashDirectedAcyclicGraph<>(Base.A, Base.B)));
          assertEquals(new HashDirectedAcyclicGraph<>(Base.A, Base.B, Base.C, Base.G, Base.H), instance);
      }
  
      /**
       * Test of removeAll method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testRemoveAll() {
          // Test 1
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(Base.A, Base.B, Base.C, Base.G);
          assertTrue(instance.removeAll(new HashDirectedAcyclicGraph<>(Base.G, Base.H)));
          assertEquals(new HashDirectedAcyclicGraph<>(Base.A, Base.B, Base.C), instance);
          // Test 2
          instance = new HashDirectedAcyclicGraph<>(Base.A, Base.B, Base.C, Base.G);
          assertFalse(instance.removeAll(new HashDirectedAcyclicGraph<>(Base.H)));
      }
  
      /**
       * Test of retainAll method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testRetainAll() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(Base.A, Base.B, Base.C, Base.D);
          assertTrue(instance.retainAll(new HashDirectedAcyclicGraph<>(Base.B, Base.C, Base.G, Base.H)));
          assertEquals(new HashDirectedAcyclicGraph<>(Base.B, Base.C), instance);
      }
  
      /**
       * Test of clear method, of class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      public void testClear() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(setABCDEFG);
          instance.clear();
          assertTrue(instance.isEmpty());
      }
  
      /**
       * Test for getSortedList,class HashDirectedAcyclicGraph<Base>.
       */
      @Test
      @SneakyThrows
      public void testGetSortedList() {
          HashDirectedAcyclicGraph<Base> instance = new HashDirectedAcyclicGraph<>(setABCDEFG);
          instance.setBefore(Base.A, Base.B);//A -> B
          instance.setBefore(Base.D, Base.B);//D -> B
          instance.setBefore(Base.E, Base.B);//E -> B
          instance.setBefore(Base.F, Base.B);//F -> B
          instance.setBefore(Base.G, Base.B);//G -> B
          instance.setBefore(Base.B, Base.C);//B -> C
          // ADEFG -> B -> C
          List<Base> sortedList = instance.getSortedList();
          assertEquals(Base.C, sortedList.getLast());
          assertEquals(Base.B, sortedList.get(sortedList.size() - 2));
          // Multiple method calls should return the same result
          assertEquals(sortedList, instance.getSortedList());
      }
  
      enum Base {A, B, C, D, E, F, G, H}
  }
  