1+ package com .thealgorithms .datastructures .graphs ;
2+
3+ import static org .junit .jupiter .api .Assertions .assertEquals ;
4+ import static org .junit .jupiter .api .Assertions .assertThrows ;
5+ import static org .junit .jupiter .api .Assertions .assertTrue ;
6+
7+ import java .util .List ;
8+ import org .junit .jupiter .api .Test ;
9+
10+ /**
11+ * JUnit 5 tests for {@link TopologicalSortDFS}.
12+ *
13+ * Test cases cover:
14+ * - Standard DAG with a clear expected topological order
15+ * - Multiple valid orderings (validated by constraint checking)
16+ * - Graphs with cycles (must throw IllegalStateException)
17+ * - Single-node graph
18+ * - Disconnected graph
19+ */
20+ class TopologicalSortDFSTest {
21+
22+ /**
23+ * Checks that every edge u → v satisfies: u appears before v in the result.
24+ */
25+ private static void assertValidTopologicalOrder (List <Integer > order , int [][] edges ) {
26+ for (int [] edge : edges ) {
27+ int u = edge [0 ];
28+ int v = edge [1 ];
29+ assertTrue (
30+ order .indexOf (u ) < order .indexOf (v ),
31+ "Expected " + u + " to appear before " + v + " in topological order. Got: " + order );
32+ }
33+ }
34+
35+ @ Test
36+ void testSimpleLinearGraph () {
37+ // 0 → 1 → 2 → 3
38+ TopologicalSortDFS graph = new TopologicalSortDFS ();
39+ graph .addEdge (0 , 1 );
40+ graph .addEdge (1 , 2 );
41+ graph .addEdge (2 , 3 );
42+
43+ List <Integer > result = graph .topologicalSort ();
44+ assertEquals (List .of (0 , 1 , 2 , 3 ), result );
45+ }
46+
47+ @ Test
48+ void testDAGWithMultiplePaths () {
49+ // Graph:
50+ // 5 → 2
51+ // 5 → 0
52+ // 4 → 0
53+ // 4 → 1
54+ // 2 → 3
55+ // 3 → 1
56+ TopologicalSortDFS graph = new TopologicalSortDFS ();
57+ int [][] edges = { { 5 , 2 }, { 5 , 0 }, { 4 , 0 }, { 4 , 1 }, { 2 , 3 }, { 3 , 1 } };
58+ for (int [] edge : edges ) {
59+ graph .addEdge (edge [0 ], edge [1 ]);
60+ }
61+
62+ List <Integer > result = graph .topologicalSort ();
63+ assertEquals (6 , result .size ());
64+ assertValidTopologicalOrder (result , edges );
65+ }
66+
67+ @ Test
68+ void testBuildOrderDAG () {
69+ // Simulates build dependency: A depends on nothing, B depends on A, C depends
70+ // on A and B
71+ // A=0, B=1, C=2, D=3
72+ // 0 → 1, 0 → 2, 1 → 3, 2 → 3
73+ TopologicalSortDFS graph = new TopologicalSortDFS ();
74+ int [][] edges = { { 0 , 1 }, { 0 , 2 }, { 1 , 3 }, { 2 , 3 } };
75+ for (int [] edge : edges ) {
76+ graph .addEdge (edge [0 ], edge [1 ]);
77+ }
78+
79+ List <Integer > result = graph .topologicalSort ();
80+ assertEquals (4 , result .size ());
81+ assertValidTopologicalOrder (result , edges );
82+ }
83+
84+ @ Test
85+ void testSingleVertex () {
86+ TopologicalSortDFS graph = new TopologicalSortDFS ();
87+ graph .addVertex (42 );
88+
89+ List <Integer > result = graph .topologicalSort ();
90+ assertEquals (List .of (42 ), result );
91+ }
92+
93+ @ Test
94+ void testDisconnectedGraph () {
95+ // Two disconnected components: 0 → 1 and 2 → 3
96+ TopologicalSortDFS graph = new TopologicalSortDFS ();
97+ int [][] edges = { { 0 , 1 }, { 2 , 3 } };
98+ for (int [] edge : edges ) {
99+ graph .addEdge (edge [0 ], edge [1 ]);
100+ }
101+
102+ List <Integer > result = graph .topologicalSort ();
103+ assertEquals (4 , result .size ());
104+ assertValidTopologicalOrder (result , edges );
105+ }
106+
107+ @ Test
108+ void testSimpleCycleThrowsException () {
109+ // 0 → 1 → 2 → 0 (cycle)
110+ TopologicalSortDFS graph = new TopologicalSortDFS ();
111+ graph .addEdge (0 , 1 );
112+ graph .addEdge (1 , 2 );
113+ graph .addEdge (2 , 0 );
114+
115+ assertThrows (
116+ IllegalStateException .class ,
117+ graph ::topologicalSort ,
118+ "Expected IllegalStateException for cyclic graph" );
119+ }
120+
121+ @ Test
122+ void testSelfLoopThrowsException () {
123+ // A self-loop is a trivial cycle: 0 → 0
124+ TopologicalSortDFS graph = new TopologicalSortDFS ();
125+ graph .addEdge (0 , 0 );
126+
127+ assertThrows (
128+ IllegalStateException .class ,
129+ graph ::topologicalSort ,
130+ "Expected IllegalStateException for self-loop" );
131+ }
132+
133+ @ Test
134+ void testLargerCycleThrowsException () {
135+ // 0 → 1 → 2 → 3 → 4 → 2 (cycle at 2 → 3 → 4 → 2)
136+ TopologicalSortDFS graph = new TopologicalSortDFS ();
137+ graph .addEdge (0 , 1 );
138+ graph .addEdge (1 , 2 );
139+ graph .addEdge (2 , 3 );
140+ graph .addEdge (3 , 4 );
141+ graph .addEdge (4 , 2 );
142+
143+ assertThrows (
144+ IllegalStateException .class ,
145+ graph ::topologicalSort ,
146+ "Expected IllegalStateException for graph with cycle" );
147+ }
148+ }
0 commit comments