package com.thealgorithms.graph;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@link HierholzerEulerianPath}.
*
* This test suite validates Hierholzer's Algorithm implementation
* for finding Eulerian Paths and Circuits in directed graphs.
*
*
Coverage includes:
*
* - Basic Eulerian Circuit
* - Eulerian Path
* - Disconnected graphs
* - Single-node graphs
* - Graphs with no edges
* - Graphs that do not have any Eulerian Path/Circuit
*
*
*/
class HierholzerEulerianPathTest {
@Test
void testSimpleEulerianCircuit() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(3);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 0);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Eulerian Circuit: [0, 1, 2, 0]
List expected = Arrays.asList(0, 1, 2, 0);
assertEquals(expected, result);
}
@Test
void testEulerianPathDifferentStartEnd() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(4);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 3);
graph.addEdge(3, 1);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Eulerian Path: [0, 1, 2, 3, 1]
List expected = Arrays.asList(0, 1, 2, 3, 1);
assertEquals(expected, result);
}
@Test
void testNoEulerianPathExists() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(3);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
// Edge 2->0 missing, so it's not Eulerian Circuit
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
assertEquals(result, Arrays.asList(0, 1, 2));
}
@Test
void testDisconnectedGraph() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(4);
graph.addEdge(0, 1);
graph.addEdge(2, 3); // disconnected component
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Disconnected graph cannot have an Eulerian path
assertTrue(result.isEmpty());
}
@Test
void testGraphWithSelfLoop() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(3);
graph.addEdge(0, 0); // self loop
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 0);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Eulerian Circuit with self-loop included: [0, 0, 1, 2, 0]
assertEquals(Arrays.asList(0, 0, 1, 2, 0), result);
}
@Test
void testSingleNodeNoEdges() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(1);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Only one vertex and no edges
assertEquals(Collections.singletonList(0), result);
}
@Test
void testSingleNodeWithLoop() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(1);
graph.addEdge(0, 0);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Eulerian circuit on a single node with a self-loop
assertEquals(Arrays.asList(0, 0), result);
}
@Test
void testComplexEulerianCircuit() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(5);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 3);
graph.addEdge(3, 4);
graph.addEdge(4, 0);
graph.addEdge(1, 3);
graph.addEdge(3, 1);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Verify all edges are used
int totalEdges = 7;
assertEquals(totalEdges + 1, result.size(), "Path must contain all edges + 1 vertices");
assertEquals(result.get(0), result.get(result.size() - 1), "Must form a circuit");
}
@Test
void testMultipleEdgesBetweenSameNodes() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(3);
graph.addEdge(0, 1);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 0);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Hava a Eulerian Path but not a Eulerian Circuit
assertEquals(result, Arrays.asList(0, 1, 2, 0, 1));
}
@Test
void testCoverageForEmptyGraph() {
HierholzerEulerianPath.Graph graph = new HierholzerEulerianPath.Graph(0);
HierholzerEulerianPath solver = new HierholzerEulerianPath(graph);
List result = solver.findEulerianPath();
// Empty graph has no vertices or path
assertTrue(result.isEmpty());
}
}