diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/stack/dag/DAG.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/stack/dag/DAG.java index 4d4dc4cb..f620e0f3 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/stack/dag/DAG.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/stack/dag/DAG.java @@ -143,7 +143,7 @@ public boolean addEdge(Node fromNode, Node toNode, EdgeInfo edge, boolean create * @param node node * @return true if contains */ - private boolean containsNode(Node node) { + protected boolean containsNode(Node node) { lock.readLock().lock(); try { diff --git a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/ComponentCommandWrapperTest.java b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/ComponentCommandWrapperTest.java new file mode 100644 index 00000000..057b86a1 --- /dev/null +++ b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/ComponentCommandWrapperTest.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.server.stack.dag; + +import org.apache.bigtop.manager.common.enums.Command; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ComponentCommandWrapperTest { + + @Test + public void testEqualsAndHashcode() { + ComponentCommandWrapper wrapper1 = new ComponentCommandWrapper("HDFS", Command.START); + ComponentCommandWrapper wrapper2 = new ComponentCommandWrapper("HDFS", Command.START); + ComponentCommandWrapper wrapper3 = new ComponentCommandWrapper("YARN", Command.START); + ComponentCommandWrapper wrapper4 = new ComponentCommandWrapper("HDFS", Command.STOP); + + // Test equals method + assertEquals(wrapper1, wrapper2); // Same component name and command + assertNotEquals(wrapper1, wrapper3); // Different component name + assertNotEquals(wrapper1, wrapper4); // Same component name but different command + + // Test hashCode method + assertEquals(wrapper1.hashCode(), wrapper2.hashCode()); // Same component name and command + assertNotEquals(wrapper1.hashCode(), wrapper3.hashCode()); // Different component name + assertNotEquals(wrapper1.hashCode(), wrapper4.hashCode()); // Same component name but different command + } + + @Test + public void testComponentNameNull() { + ComponentCommandWrapper wrapper1 = new ComponentCommandWrapper(null, Command.START); + ComponentCommandWrapper wrapper2 = new ComponentCommandWrapper(null, Command.START); + ComponentCommandWrapper wrapper3 = new ComponentCommandWrapper(null, Command.STOP); + + assertEquals(wrapper1, wrapper2); // Same command and both component names are null + assertNotEquals(wrapper1, wrapper3); // Same component name but different command + + assertEquals(wrapper1.hashCode(), wrapper2.hashCode()); // Same command and both component names are null + assertNotEquals(wrapper1.hashCode(), wrapper3.hashCode()); // Same component name but different command + } + + @Test + public void testCommandNull() { + ComponentCommandWrapper wrapper1 = new ComponentCommandWrapper("HDFS", null); + ComponentCommandWrapper wrapper2 = new ComponentCommandWrapper("HDFS", null); + ComponentCommandWrapper wrapper3 = new ComponentCommandWrapper("YARN", null); + + assertEquals(wrapper1, wrapper2); // Same component name and both commands are null + assertNotEquals(wrapper1, wrapper3); // Different component name + + assertEquals(wrapper1.hashCode(), wrapper2.hashCode()); // Same component name and both commands are null + assertNotEquals(wrapper1.hashCode(), wrapper3.hashCode()); // Different component name + } + + @Test + public void testComponentNameAndCommandNull() { + ComponentCommandWrapper wrapper1 = new ComponentCommandWrapper(null, null); + ComponentCommandWrapper wrapper2 = new ComponentCommandWrapper(null, null); + + assertEquals(wrapper1, wrapper2); // Both component name and command are null + + assertEquals(wrapper1.hashCode(), wrapper2.hashCode()); // Both component name and command are null + } + + @Test + public void testToString() { + ComponentCommandWrapper wrapper1 = new ComponentCommandWrapper("HDFS", Command.START); + ComponentCommandWrapper wrapper2 = new ComponentCommandWrapper("YARN", Command.STOP); + + assertEquals("HDFS-START", wrapper1.toString()); // Normal component name and command + assertEquals("YARN-STOP", wrapper2.toString()); // Normal component name and command + } + + @Test + public void testToStringWithComponentNameNull() { + ComponentCommandWrapper wrapper = new ComponentCommandWrapper(null, Command.START); + + assertEquals("null-START", wrapper.toString()); // Component name is null + } + + @Test + public void testToStringWithCommandNull() { + ComponentCommandWrapper wrapper = new ComponentCommandWrapper("HDFS", null); + + assertThrows(NullPointerException.class, wrapper::toString); + } +} diff --git a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/DAGTest.java b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/DAGTest.java new file mode 100644 index 00000000..6544e734 --- /dev/null +++ b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/DAGTest.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.server.stack.dag; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +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; + +class DAGTest { + + private DAG dag; + + @BeforeEach + void setUp() { + dag = new DAG<>(); + } + + // Test if node exists + @Test + void testContainsNode() { + assertFalse(dag.containsNode("A")); + dag.addNodeIfAbsent("A", "Node A"); + assertTrue(dag.containsNode("A")); + } + + // Test getting the number of nodes + @Test + void testGetNodesCount() { + assertEquals(0, dag.getNodesCount()); + dag.addNodeIfAbsent("A", "Node A"); + assertEquals(1, dag.getNodesCount()); + } + + // Test getting the number of edges + @Test + void testGetEdgesCount() { + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + assertEquals(0, dag.getEdgesCount()); + dag.addEdge("A", "B"); + assertEquals(1, dag.getEdgesCount()); + } + + // Test adding nodes and edges normally + @Test + void testAddEdgeHappyPath() { + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + dag.addNodeIfAbsent("C", "Node C"); + assertTrue(dag.addEdge("A", "B")); + assertTrue(dag.addEdge("B", "C")); + assertTrue(dag.addEdge("A", "C")); + assertEquals(3, dag.getNodesCount()); + assertEquals(3, dag.getEdgesCount()); + } + + // Test adding a self-loop edge + @Test + void testAddEdgeSelfLoop() { + dag.addNodeIfAbsent("A", "Node A"); + assertFalse(dag.addEdge("A", "A")); + } + + // Test adding an edge that would form a cycle + @Test + void testAddEdgeCycle() { + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + dag.addNodeIfAbsent("C", "Node C"); + assertTrue(dag.addEdge("A", "B")); + assertTrue(dag.addEdge("B", "C")); + assertFalse(dag.addEdge("C", "A")); + } + + // Test if edge exists + @Test + void testContainsEdge() { + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + assertFalse(dag.containsEdge("A", "B")); + dag.addEdge("A", "B"); + assertTrue(dag.containsEdge("A", "B")); + } + + // Test getting node information + @Test + void testGetNode() { + assertNull(dag.getNode("A")); + dag.addNodeIfAbsent("A", "Node A"); + assertEquals("Node A", dag.getNode("A")); + } + + // Test getting beginning nodes + @Test + void testGetBeginNode() { + assertTrue(dag.getBeginNode().isEmpty()); + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + dag.addEdge("A", "B"); + assertEquals(Collections.singletonList("A"), new LinkedList<>(dag.getBeginNode())); + } + + // Test getting end nodes + @Test + void testGetEndNode() { + assertTrue(dag.getEndNode().isEmpty()); + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + dag.addEdge("A", "B"); + assertEquals(Collections.singletonList("B"), new LinkedList<>(dag.getEndNode())); + } + + // Test getting previous nodes + @Test + void testGetPreviousNodes() { + assertTrue(dag.getPreviousNodes("A").isEmpty()); + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + dag.addEdge("A", "B"); + assertEquals(Collections.singletonList("A"), new LinkedList<>(dag.getPreviousNodes("B"))); + } + + // Test getting subsequent nodes + @Test + void testGetSubsequentNodes() { + assertTrue(dag.getSubsequentNodes("A").isEmpty()); + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + dag.addEdge("A", "B"); + assertEquals(Collections.singletonList("B"), new LinkedList<>(dag.getSubsequentNodes("A"))); + } + + // Test getting the indegree of a node + @Test + void testGetIndegree() { + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + assertEquals(0, dag.getIndegree("A")); + dag.addEdge("A", "B"); + assertEquals(1, dag.getIndegree("B")); + } + + // Test topological sorting + @Test + void testTopologicalSort() throws Exception { + dag.addNodeIfAbsent("A", "Node A"); + dag.addNodeIfAbsent("B", "Node B"); + dag.addNodeIfAbsent("C", "Node C"); + List expected = List.of("A", "B", "C"); + dag.addEdge("A", "B"); + dag.addEdge("B", "C"); + assertEquals(expected, dag.topologicalSort()); + } +} diff --git a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/DagGraphEdgeTest.java b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/DagGraphEdgeTest.java new file mode 100644 index 00000000..1a371daf --- /dev/null +++ b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/stack/dag/DagGraphEdgeTest.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.server.stack.dag; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class DagGraphEdgeTest { + + @Test + public void testNormalCase() { + DagGraphEdge edge = new DagGraphEdge("NodeA", "NodeB"); + assertEquals("NodeA", edge.getStartNode()); + assertEquals("NodeB", edge.getEndNode()); + assertEquals("NodeA -> NodeB", edge.toString()); + } + + @Test + public void testStartNodeEmptyString() { + DagGraphEdge edge = new DagGraphEdge("", "NodeB"); + assertEquals("", edge.getStartNode()); + assertEquals("NodeB", edge.getEndNode()); + assertEquals(" -> NodeB", edge.toString()); + } + + @Test + public void testEndNodeEmptyString() { + DagGraphEdge edge = new DagGraphEdge("NodeA", ""); + assertEquals("NodeA", edge.getStartNode()); + assertEquals("", edge.getEndNode()); + assertEquals("NodeA -> ", edge.toString()); + } + + @Test + public void testBothNodesEmptyString() { + DagGraphEdge edge = new DagGraphEdge("", ""); + assertEquals("", edge.getStartNode()); + assertEquals("", edge.getEndNode()); + assertEquals(" -> ", edge.toString()); + } + + @Test + public void testStartNodeNull() { + DagGraphEdge edge = new DagGraphEdge(null, "NodeB"); + assertNull(edge.getStartNode()); + assertEquals("NodeB", edge.getEndNode()); + assertEquals("null -> NodeB", edge.toString()); + } + + @Test + public void testEndNodeNull() { + DagGraphEdge edge = new DagGraphEdge("NodeA", null); + assertEquals("NodeA", edge.getStartNode()); + assertNull(edge.getEndNode()); + assertEquals("NodeA -> null", edge.toString()); + } + + @Test + public void testBothNodesNull() { + DagGraphEdge edge = new DagGraphEdge(null, null); + assertNull(edge.getStartNode()); + assertNull(edge.getEndNode()); + assertEquals("null -> null", edge.toString()); + } + + @Test + public void testStartNodeEqualsEndNode() { + DagGraphEdge edge = new DagGraphEdge("NodeA", "NodeA"); + assertEquals("NodeA", edge.getStartNode()); + assertEquals("NodeA", edge.getEndNode()); + assertEquals("NodeA -> NodeA", edge.toString()); + } + + @Test + public void testStartNodeWithSpecialChars() { + DagGraphEdge edge = new DagGraphEdge("Node@#1", "NodeB"); + assertEquals("Node@#1", edge.getStartNode()); + assertEquals("NodeB", edge.getEndNode()); + assertEquals("Node@#1 -> NodeB", edge.toString()); + } + + @Test + public void testEndNodeWithSpecialChars() { + DagGraphEdge edge = new DagGraphEdge("NodeA", "Node!@2"); + assertEquals("NodeA", edge.getStartNode()); + assertEquals("Node!@2", edge.getEndNode()); + assertEquals("NodeA -> Node!@2", edge.toString()); + } + + @Test + public void testBothNodesWithSpecialChars() { + DagGraphEdge edge = new DagGraphEdge("Node@#1", "Node!@2"); + assertEquals("Node@#1", edge.getStartNode()); + assertEquals("Node!@2", edge.getEndNode()); + assertEquals("Node@#1 -> Node!@2", edge.toString()); + } +}