diff --git a/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/grpc/interceptor/TaskInterceptor.java b/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/grpc/interceptor/TaskInterceptor.java index 3e562bf9..99fdb709 100644 --- a/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/grpc/interceptor/TaskInterceptor.java +++ b/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/grpc/interceptor/TaskInterceptor.java @@ -50,9 +50,7 @@ public void onMessage(ReqT message) { if (isTaskRequest(message)) { try { Method method = message.getClass().getDeclaredMethod("getTaskId"); - method.setAccessible(true); Long taskId = (Long) method.invoke(message); - method.setAccessible(false); truncateLogFile(taskId); MDC.put("taskId", String.valueOf(taskId)); Caches.RUNNING_TASK = taskId; diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/test/java/org/apache/bigtop/manager/ai/core/enums/MessageTypeTest.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/test/java/org/apache/bigtop/manager/ai/core/enums/MessageTypeTest.java new file mode 100644 index 00000000..050160ae --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/test/java/org/apache/bigtop/manager/ai/core/enums/MessageTypeTest.java @@ -0,0 +1,49 @@ +/* + * 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.ai.core.enums; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MessageTypeTest { + + @Test + public void testGetSenders() { + List senders = MessageType.getSenders(); + assertEquals(3, senders.size()); + assertTrue(senders.contains("user")); + assertTrue(senders.contains("ai")); + assertTrue(senders.contains("system")); + } + + @Test + public void testGetMessageSender() { + assertEquals(MessageType.USER, MessageType.getMessageSender("user")); + assertEquals(MessageType.AI, MessageType.getMessageSender("ai")); + assertEquals(MessageType.SYSTEM, MessageType.getMessageSender("system")); + assertNull(MessageType.getMessageSender("")); + assertNull(MessageType.getMessageSender(null)); + assertNull(MessageType.getMessageSender("unknown")); + } +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/test/java/org/apache/bigtop/manager/ai/core/enums/PlatformTypeTest.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/test/java/org/apache/bigtop/manager/ai/core/enums/PlatformTypeTest.java new file mode 100644 index 00000000..863242b9 --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/test/java/org/apache/bigtop/manager/ai/core/enums/PlatformTypeTest.java @@ -0,0 +1,49 @@ +/* + * 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.ai.core.enums; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class PlatformTypeTest { + + @Test + public void testGetPlatforms() { + List senders = PlatformType.getPlatforms(); + assertEquals(3, senders.size()); + assertTrue(senders.contains("openai")); + assertTrue(senders.contains("dashscope")); + assertTrue(senders.contains("qianfan")); + } + + @Test + public void testGetPlatformType() { + assertEquals(PlatformType.OPENAI, PlatformType.getPlatformType("openai")); + assertEquals(PlatformType.DASH_SCOPE, PlatformType.getPlatformType("dashscope")); + assertEquals(PlatformType.QIANFAN, PlatformType.getPlatformType("qianfan")); + assertNull(PlatformType.getPlatformType("")); + assertNull(PlatformType.getPlatformType(null)); + assertNull(PlatformType.getPlatformType("unknown")); + } +} diff --git a/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/CommandTest.java b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/CommandTest.java new file mode 100644 index 00000000..65950271 --- /dev/null +++ b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/CommandTest.java @@ -0,0 +1,208 @@ +/* + * 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.common.enums; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class CommandTest { + + // Test normal path: verify that the code and name of enum values are correct + @Test + public void testCommandNormalPath() { + assertEquals("add", Command.ADD.getCode(), "The code of ADD should be 'add'"); + assertEquals("Add", Command.ADD.getName(), "The name of ADD should be 'Add'"); + + assertEquals("start", Command.START.getCode(), "The code of START should be 'start'"); + assertEquals("Start", Command.START.getName(), "The name of START should be 'Start'"); + + assertEquals("stop", Command.STOP.getCode(), "The code of STOP should be 'stop'"); + assertEquals("Stop", Command.STOP.getName(), "The name of STOP should be 'Stop'"); + + assertEquals("restart", Command.RESTART.getCode(), "The code of RESTART should be 'restart'"); + assertEquals("Restart", Command.RESTART.getName(), "The name of RESTART should be 'Restart'"); + + assertEquals("check", Command.CHECK.getCode(), "The code of CHECK should be 'check'"); + assertEquals("Check", Command.CHECK.getName(), "The name of CHECK should be 'Check'"); + + assertEquals("configure", Command.CONFIGURE.getCode(), "The code of CONFIGURE should be 'configure'"); + assertEquals("Configure", Command.CONFIGURE.getName(), "The name of CONFIGURE should be 'Configure'"); + + assertEquals("custom", Command.CUSTOM.getCode(), "The code of CUSTOM should be 'custom'"); + assertEquals("Custom", Command.CUSTOM.getName(), "The name of CUSTOM should be 'Custom'"); + + assertEquals("init", Command.INIT.getCode(), "The code of INIT should be 'init'"); + assertEquals("Init", Command.INIT.getName(), "The name of INIT should be 'Init'"); + + assertEquals("prepare", Command.PREPARE.getCode(), "The code of PREPARE should be 'prepare'"); + assertEquals("Prepare", Command.PREPARE.getName(), "The name of PREPARE should be 'Prepare'"); + + assertEquals("status", Command.STATUS.getCode(), "The code of STATUS should be 'status'"); + assertEquals("Status", Command.STATUS.getName(), "The name of STATUS should be 'Status'"); + } + + // Test boundary conditions: verify that the fromString method can correctly convert strings in upper case, lower + // case, and mixed case + @Test + public void testFromStringWithVariousCases() { + assertEquals(Command.ADD, Command.fromString("ADD"), "Upper case 'ADD' should be converted to ADD enum value"); + assertEquals(Command.ADD, Command.fromString("add"), "Lower case 'add' should be converted to ADD enum value"); + assertEquals(Command.ADD, Command.fromString("AdD"), "Mixed case 'AdD' should be converted to ADD enum value"); + + assertEquals( + Command.START, + Command.fromString("START"), + "Upper case 'START' should be converted to START enum value"); + assertEquals( + Command.START, + Command.fromString("start"), + "Lower case 'start' should be converted to START enum value"); + assertEquals( + Command.START, + Command.fromString("StArT"), + "Mixed case 'StArT' should be converted to START enum value"); + + assertEquals( + Command.STOP, Command.fromString("STOP"), "Upper case 'STOP' should be converted to STOP enum value"); + assertEquals( + Command.STOP, Command.fromString("stop"), "Lower case 'stop' should be converted to STOP enum value"); + assertEquals( + Command.STOP, Command.fromString("StOp"), "Mixed case 'StOp' should be converted to STOP enum value"); + + assertEquals( + Command.RESTART, + Command.fromString("RESTART"), + "Upper case 'RESTART' should be converted to RESTART enum value"); + assertEquals( + Command.RESTART, + Command.fromString("restart"), + "Lower case 'restart' should be converted to RESTART enum value"); + assertEquals( + Command.RESTART, + Command.fromString("ReStArT"), + "Mixed case 'ReStArT' should be converted to RESTART enum value"); + + assertEquals( + Command.CHECK, + Command.fromString("CHECK"), + "Upper case 'CHECK' should be converted to CHECK enum value"); + assertEquals( + Command.CHECK, + Command.fromString("check"), + "Lower case 'check' should be converted to CHECK enum value"); + assertEquals( + Command.CHECK, + Command.fromString("ChEcK"), + "Mixed case 'ChEcK' should be converted to CHECK enum value"); + + assertEquals( + Command.CONFIGURE, + Command.fromString("CONFIGURE"), + "Upper case 'CONFIGURE' should be converted to CONFIGURE enum value"); + assertEquals( + Command.CONFIGURE, + Command.fromString("configure"), + "Lower case 'configure' should be converted to CONFIGURE enum value"); + assertEquals( + Command.CONFIGURE, + Command.fromString("CoNfIgUrE"), + "Mixed case 'CoNfIgUrE' should be converted to CONFIGURE enum value"); + + assertEquals( + Command.CUSTOM, + Command.fromString("CUSTOM"), + "Upper case 'CUSTOM' should be converted to CUSTOM enum value"); + assertEquals( + Command.CUSTOM, + Command.fromString("custom"), + "Lower case 'custom' should be converted to CUSTOM enum value"); + assertEquals( + Command.CUSTOM, + Command.fromString("CuStOm"), + "Mixed case 'CuStOm' should be converted to CUSTOM enum value"); + + assertEquals( + Command.INIT, Command.fromString("INIT"), "Upper case 'INIT' should be converted to INIT enum value"); + assertEquals( + Command.INIT, Command.fromString("init"), "Lower case 'init' should be converted to INIT enum value"); + assertEquals( + Command.INIT, Command.fromString("InIt"), "Mixed case 'InIt' should be converted to INIT enum value"); + + assertEquals( + Command.PREPARE, + Command.fromString("PREPARE"), + "Upper case 'PREPARE' should be converted to PREPARE enum value"); + assertEquals( + Command.PREPARE, + Command.fromString("prepare"), + "Lower case 'prepare' should be converted to PREPARE enum value"); + assertEquals( + Command.PREPARE, + Command.fromString("PrEpArE"), + "Mixed case 'PrEpArE' should be converted to PREPARE enum value"); + + assertEquals( + Command.STATUS, + Command.fromString("STATUS"), + "Upper case 'STATUS' should be converted to STATUS enum value"); + assertEquals( + Command.STATUS, + Command.fromString("status"), + "Lower case 'status' should be converted to STATUS enum value"); + assertEquals( + Command.STATUS, + Command.fromString("StAtUs"), + "Mixed case 'StAtUs' should be converted to STATUS enum value"); + } + + // Test boundary conditions: verify that the fromString method throws an exception when passed an invalid string + @Test + public void testFromStringWithInvalidString() { + assertThrows( + IllegalArgumentException.class, + () -> Command.fromString("INVALID"), + "Passing invalid string 'INVALID' should throw an IllegalArgumentException"); + assertThrows( + IllegalArgumentException.class, + () -> Command.fromString(""), + "Passing empty string '' should throw an IllegalArgumentException"); + assertThrows( + NullPointerException.class, + () -> Command.fromString(null), + "Passing null should throw a NullPointerException"); + } + + // Test boundary conditions: verify that the toCamelCase method can correctly convert enum values to camel case + // strings + @Test + public void testToCamelCase() { + assertEquals("Add", Command.ADD.toCamelCase(), "ADD should be converted to 'Add'"); + assertEquals("Start", Command.START.toCamelCase(), "START should be converted to 'Start'"); + assertEquals("Stop", Command.STOP.toCamelCase(), "STOP should be converted to 'Stop'"); + assertEquals("Restart", Command.RESTART.toCamelCase(), "RESTART should be converted to 'Restart'"); + assertEquals("Check", Command.CHECK.toCamelCase(), "CHECK should be converted to 'Check'"); + assertEquals("Configure", Command.CONFIGURE.toCamelCase(), "CONFIGURE should be converted to 'Configure'"); + assertEquals("Custom", Command.CUSTOM.toCamelCase(), "CUSTOM should be converted to 'Custom'"); + assertEquals("Init", Command.INIT.toCamelCase(), "INIT should be converted to 'Init'"); + assertEquals("Prepare", Command.PREPARE.toCamelCase(), "PREPARE should be converted to 'Prepare'"); + assertEquals("Status", Command.STATUS.toCamelCase(), "STATUS should be converted to 'Status'"); + } +} diff --git a/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/JobStateTest.java b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/JobStateTest.java new file mode 100644 index 00000000..3165d010 --- /dev/null +++ b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/JobStateTest.java @@ -0,0 +1,143 @@ +/* + * 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.common.enums; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class JobStateTest { + // Test normal path: verify that the code and name of enum values are correct + @Test + public void testJobStateNormalPath() { + assertEquals("pending", JobState.PENDING.getCode(), "The code of PENDING should be 'pending'"); + assertEquals("Pending", JobState.PENDING.getName(), "The name of PENDING should be 'Pending'"); + + assertEquals("processing", JobState.PROCESSING.getCode(), "The code of PROCESSING should be 'processing'"); + assertEquals("Processing", JobState.PROCESSING.getName(), "The name of PROCESSING should be 'Processing'"); + + assertEquals("successful", JobState.SUCCESSFUL.getCode(), "The code of SUCCESSFUL should be 'successful'"); + assertEquals("Successful", JobState.SUCCESSFUL.getName(), "The name of SUCCESSFUL should be 'Successful'"); + + assertEquals("failed", JobState.FAILED.getCode(), "The code of FAILED should be 'failed'"); + assertEquals("Failed", JobState.FAILED.getName(), "The name of FAILED should be 'Failed'"); + + assertEquals("canceled", JobState.CANCELED.getCode(), "The code of CANCELED should be 'canceled'"); + assertEquals("Canceled", JobState.CANCELED.getName(), "The name of CANCELED should be 'Canceled'"); + } + + // Test boundary conditions: verify that the fromString method can correctly convert strings in upper case, lower + // case, and mixed case + @Test + public void testFromStringWithVariousCases() { + assertEquals( + JobState.PENDING, + JobState.fromString("PENDING"), + "Upper case 'PENDING' should be converted to PENDING enum value"); + assertEquals( + JobState.PENDING, + JobState.fromString("pending"), + "Lower case 'pending' should be converted to PENDING enum value"); + assertEquals( + JobState.PENDING, + JobState.fromString("PeNdiNg"), + "Mixed case 'PeNdiNg' should be converted to PENDING enum value"); + + assertEquals( + JobState.PROCESSING, + JobState.fromString("PROCESSING"), + "Upper case 'PROCESSING' should be converted to PROCESSING enum value"); + assertEquals( + JobState.PROCESSING, + JobState.fromString("processing"), + "Lower case 'processing' should be converted to PROCESSING enum value"); + assertEquals( + JobState.PROCESSING, + JobState.fromString("PrOcEsSiNg"), + "Mixed case 'PrOcEsSiNg' should be converted to PROCESSING enum value"); + + assertEquals( + JobState.SUCCESSFUL, + JobState.fromString("SUCCESSFUL"), + "Upper case 'SUCCESSFUL' should be converted to SUCCESSFUL enum value"); + assertEquals( + JobState.SUCCESSFUL, + JobState.fromString("successful"), + "Lower case 'successful' should be converted to SUCCESSFUL enum value"); + assertEquals( + JobState.SUCCESSFUL, + JobState.fromString("SuCcEsSfUl"), + "Mixed case 'SuCcEsSfUl' should be converted to SUCCESSFUL enum value"); + + assertEquals( + JobState.FAILED, + JobState.fromString("FAILED"), + "Upper case 'FAILED' should be converted to FAILED enum value"); + assertEquals( + JobState.FAILED, + JobState.fromString("failed"), + "Lower case 'failed' should be converted to FAILED enum value"); + assertEquals( + JobState.FAILED, + JobState.fromString("FaIlEd"), + "Mixed case 'FaIlEd' should be converted to FAILED enum value"); + + assertEquals( + JobState.CANCELED, + JobState.fromString("CANCELED"), + "Upper case 'CANCELED' should be converted to CANCELED enum value"); + assertEquals( + JobState.CANCELED, + JobState.fromString("canceled"), + "Lower case 'canceled' should be converted to CANCELED enum value"); + assertEquals( + JobState.CANCELED, + JobState.fromString("CaNcElEd"), + "Mixed case 'CaNcElEd' should be converted to CANCELED enum value"); + } + + // Test boundary conditions: verify that the fromString method throws an exception when passed an invalid string + @Test + public void testFromStringWithInvalidString() { + assertThrows( + IllegalArgumentException.class, + () -> JobState.fromString("INVALID"), + "Passing invalid string 'INVALID' should throw an IllegalArgumentException"); + assertThrows( + IllegalArgumentException.class, + () -> JobState.fromString(""), + "Passing empty string '' should throw an IllegalArgumentException"); + assertThrows( + NullPointerException.class, + () -> JobState.fromString(null), + "Passing null should throw a NullPointerException"); + } + + // Test boundary conditions: verify that the toCamelCase method can correctly convert enum values to camel case + // strings + @Test + public void testToCamelCase() { + assertEquals("Pending", JobState.PENDING.toCamelCase(), "PENDING should be converted to 'Pending'"); + assertEquals("Processing", JobState.PROCESSING.toCamelCase(), "PROCESSING should be converted to 'Processing'"); + assertEquals("Successful", JobState.SUCCESSFUL.toCamelCase(), "SUCCESSFUL should be converted to 'Successful'"); + assertEquals("Failed", JobState.FAILED.toCamelCase(), "FAILED should be converted to 'Failed'"); + assertEquals("Canceled", JobState.CANCELED.toCamelCase(), "CANCELED should be converted to 'Canceled'"); + } +} diff --git a/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/MaintainStateTest.java b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/MaintainStateTest.java new file mode 100644 index 00000000..636020e5 --- /dev/null +++ b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/enums/MaintainStateTest.java @@ -0,0 +1,151 @@ +/* + * 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.common.enums; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class MaintainStateTest { + + // Test normal path: verify that the code and name of enum values are correct + @Test + public void testMaintainStateNormalPath() { + assertEquals( + "uninstalled", MaintainState.UNINSTALLED.getCode(), "The code of UNINSTALLED should be 'uninstalled'"); + assertEquals( + "Uninstalled", MaintainState.UNINSTALLED.getName(), "The name of UNINSTALLED should be 'Uninstalled'"); + + assertEquals("installed", MaintainState.INSTALLED.getCode(), "The code of INSTALLED should be 'installed'"); + assertEquals("Installed", MaintainState.INSTALLED.getName(), "The name of INSTALLED should be 'Installed'"); + + assertEquals("maintained", MaintainState.MAINTAINED.getCode(), "The code of MAINTAINED should be 'maintained'"); + assertEquals("Maintained", MaintainState.MAINTAINED.getName(), "The name of MAINTAINED should be 'Maintained'"); + + assertEquals("started", MaintainState.STARTED.getCode(), "The code of STARTED should be 'started'"); + assertEquals("Started", MaintainState.STARTED.getName(), "The name of STARTED should be 'Started'"); + + assertEquals("stopped", MaintainState.STOPPED.getCode(), "The code of STOPPED should be 'stopped'"); + assertEquals("Stopped", MaintainState.STOPPED.getName(), "The name of STOPPED should be 'Stopped'"); + } + + // Test boundary conditions: verify that the fromString method can correctly convert strings in upper case, lower + // case, and mixed case + @Test + public void testFromStringWithVariousCases() { + assertEquals( + MaintainState.UNINSTALLED, + MaintainState.fromString("UNINSTALLED"), + "Upper case 'UNINSTALLED' should be converted to UNINSTALLED enum value"); + assertEquals( + MaintainState.UNINSTALLED, + MaintainState.fromString("uninstalled"), + "Lower case 'uninstalled' should be converted to UNINSTALLED enum value"); + assertEquals( + MaintainState.UNINSTALLED, + MaintainState.fromString("UnInStAlLeD"), + "Mixed case 'UnInStAlLeD' should be converted to UNINSTALLED enum value"); + + assertEquals( + MaintainState.INSTALLED, + MaintainState.fromString("INSTALLED"), + "Upper case 'INSTALLED' should be converted to INSTALLED enum value"); + assertEquals( + MaintainState.INSTALLED, + MaintainState.fromString("installed"), + "Lower case 'installed' should be converted to INSTALLED enum value"); + assertEquals( + MaintainState.INSTALLED, + MaintainState.fromString("InStAlLeD"), + "Mixed case 'InStAlLeD' should be converted to INSTALLED enum value"); + + assertEquals( + MaintainState.MAINTAINED, + MaintainState.fromString("MAINTAINED"), + "Upper case 'MAINTAINED' should be converted to MAINTAINED enum value"); + assertEquals( + MaintainState.MAINTAINED, + MaintainState.fromString("maintained"), + "Lower case 'maintained' should be converted to MAINTAINED enum value"); + assertEquals( + MaintainState.MAINTAINED, + MaintainState.fromString("MaInTaInEd"), + "Mixed case 'MaInTaInEd' should be converted to MAINTAINED enum value"); + + assertEquals( + MaintainState.STARTED, + MaintainState.fromString("STARTED"), + "Upper case 'STARTED' should be converted to STARTED enum value"); + assertEquals( + MaintainState.STARTED, + MaintainState.fromString("started"), + "Lower case 'started' should be converted to STARTED enum value"); + assertEquals( + MaintainState.STARTED, + MaintainState.fromString("StArTeD"), + "Mixed case 'StArTeD' should be converted to STARTED enum value"); + + assertEquals( + MaintainState.STOPPED, + MaintainState.fromString("STOPPED"), + "Upper case 'STOPPED' should be converted to STOPPED enum value"); + assertEquals( + MaintainState.STOPPED, + MaintainState.fromString("stopped"), + "Lower case 'stopped' should be converted to STOPPED enum value"); + assertEquals( + MaintainState.STOPPED, + MaintainState.fromString("StOpPeD"), + "Mixed case 'StOpPeD' should be converted to STOPPED enum value"); + } + + // Test boundary conditions: verify that the fromString method throws an exception when passed an invalid string + @Test + public void testFromStringWithInvalidString() { + assertThrows( + IllegalArgumentException.class, + () -> MaintainState.fromString("INVALID"), + "Passing invalid string 'INVALID' should throw an IllegalArgumentException"); + assertThrows( + IllegalArgumentException.class, + () -> MaintainState.fromString(""), + "Passing empty string '' should throw an IllegalArgumentException"); + assertThrows( + NullPointerException.class, + () -> MaintainState.fromString(null), + "Passing null should throw a NullPointerException"); + } + + // Test boundary conditions: verify that the toCamelCase method can correctly convert enum values to camel case + // strings + @Test + public void testToCamelCase() { + assertEquals( + "Uninstalled", + MaintainState.UNINSTALLED.toCamelCase(), + "UNINSTALLED should be converted to 'Uninstalled'"); + assertEquals( + "Installed", MaintainState.INSTALLED.toCamelCase(), "INSTALLED should be converted to 'Installed'"); + assertEquals( + "Maintained", MaintainState.MAINTAINED.toCamelCase(), "MAINTAINED should be converted to 'Maintained'"); + assertEquals("Started", MaintainState.STARTED.toCamelCase(), "STARTED should be converted to 'Started'"); + assertEquals("Stopped", MaintainState.STOPPED.toCamelCase(), "STOPPED should be converted to 'Stopped'"); + } +} diff --git a/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/shell/ProcessContainerTest.java b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/shell/ProcessContainerTest.java new file mode 100644 index 00000000..c702be53 --- /dev/null +++ b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/shell/ProcessContainerTest.java @@ -0,0 +1,73 @@ +/* + * 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.common.shell; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; + +class ProcessContainerTest { + + @AfterEach + void tearDown() { + // Clean up remaining processes in the container + for (Process process : ProcessContainer.getInstance().values()) { + ProcessContainer.removeProcess(process); + } + } + + @Test + void testPutAndRemoveProcess() { + // Mock a Process object + Process process = Mockito.mock(Process.class); + + // Add process to the container + ProcessContainer.putProcess(process); + + // Verify that the process count in the container increases + assertEquals(1, ProcessContainer.processSize()); + + // Remove the process + ProcessContainer.removeProcess(process); + + // Verify that the process count in the container decreases + assertEquals(0, ProcessContainer.processSize()); + } + + @Test + void testDestroyAllProcess() { + // Mock Process objects + Process process1 = Mockito.mock(Process.class); + Process process2 = Mockito.mock(Process.class); + + // Add two processes + ProcessContainer.putProcess(process1); + ProcessContainer.putProcess(process2); + + // Call the destroyAllProcess method + ProcessContainer.destroyAllProcess(); + + // Verify that the destroy method is called + verify(process1).destroy(); + verify(process2).destroy(); + } +} diff --git a/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/shell/ShellResultTest.java b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/shell/ShellResultTest.java new file mode 100644 index 00000000..831a1ad8 --- /dev/null +++ b/bigtop-manager-common/src/test/java/org/apache/bigtop/manager/common/shell/ShellResultTest.java @@ -0,0 +1,48 @@ +/* + * 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.common.shell; + +import org.apache.bigtop.manager.common.constants.MessageConstants; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ShellResultTest { + + @Test + void testExecCommandSuccess() throws IOException { + // Simulate successful shell command execution + ShellResult result = ShellResult.success(); + assertEquals(MessageConstants.SUCCESS_CODE, result.getExitCode()); + assertEquals("Run shell success.", result.getOutput()); + assertEquals("", result.getErrMsg()); + } + + @Test + void testExecCommandFailure() throws IOException { + // Simulate failed shell command execution + ShellResult result = ShellResult.fail(); + assertEquals(MessageConstants.FAIL_CODE, result.getExitCode()); + assertEquals("Run shell fail.", result.getOutput()); + assertEquals("", result.getErrMsg()); + } +} diff --git a/bigtop-manager-grpc/src/main/resources/proto/component_command.proto b/bigtop-manager-grpc/src/main/resources/proto/component_command.proto index 3b3d1c5c..180b8b8f 100644 --- a/bigtop-manager-grpc/src/main/resources/proto/component_command.proto +++ b/bigtop-manager-grpc/src/main/resources/proto/component_command.proto @@ -18,8 +18,6 @@ */ syntax = "proto3"; -import "google/protobuf/struct.proto"; - option java_multiple_files = true; option java_package = "org.apache.bigtop.manager.grpc.generated"; option java_outer_classname = "ComponentCommandProto"; diff --git a/bigtop-manager-grpc/src/main/resources/proto/job_cache.proto b/bigtop-manager-grpc/src/main/resources/proto/job_cache.proto index baa83104..adc44046 100644 --- a/bigtop-manager-grpc/src/main/resources/proto/job_cache.proto +++ b/bigtop-manager-grpc/src/main/resources/proto/job_cache.proto @@ -18,8 +18,6 @@ */ syntax = "proto3"; -import "google/protobuf/struct.proto"; - option java_multiple_files = true; option java_package = "org.apache.bigtop.manager.grpc.generated"; option java_outer_classname = "JobCacheProto"; diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/service/ServiceAddJob.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/service/ServiceAddJob.java index fb4ba777..7ffadc05 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/service/ServiceAddJob.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/service/ServiceAddJob.java @@ -38,6 +38,7 @@ import org.apache.bigtop.manager.server.model.dto.ServiceDTO; import org.apache.bigtop.manager.server.model.dto.StackDTO; import org.apache.bigtop.manager.server.model.dto.command.ServiceCommandDTO; +import org.apache.bigtop.manager.server.utils.StackConfigUtils; import org.apache.bigtop.manager.server.utils.StackUtils; import java.util.ArrayList; @@ -169,8 +170,10 @@ private void saveService(ServiceCommandDTO serviceCommand) { // Persist current configs Map confMap = new HashMap<>(); - List configs = serviceCommand.getConfigs(); - List serviceConfigPOList = ServiceConfigConverter.INSTANCE.fromDTO2PO(configs); + List oriConfigs = StackUtils.SERVICE_CONFIG_MAP.get(serviceName); + List newConfigs = serviceCommand.getConfigs(); + List mergedConfigs = StackConfigUtils.mergeServiceConfigs(oriConfigs, newConfigs); + List serviceConfigPOList = ServiceConfigConverter.INSTANCE.fromDTO2PO(mergedConfigs); for (ServiceConfigPO serviceConfigPO : serviceConfigPOList) { serviceConfigPO.setClusterId(clusterId); serviceConfigPO.setServiceId(servicePO.getId()); diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java index a3481239..703bf868 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java @@ -21,6 +21,7 @@ import org.apache.bigtop.manager.dao.po.ServiceConfigPO; import org.apache.bigtop.manager.server.config.MapStructSharedConfig; import org.apache.bigtop.manager.server.model.dto.ServiceConfigDTO; +import org.apache.bigtop.manager.server.model.req.ServiceConfigReq; import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO; import org.mapstruct.Mapper; @@ -36,6 +37,10 @@ public interface ServiceConfigConverter { ServiceConfigConverter INSTANCE = Mappers.getMapper(ServiceConfigConverter.class); + ServiceConfigDTO fromReq2DTO(ServiceConfigReq serviceConfigReq); + + List fromReq2DTO(List serviceConfigReqList); + @Mapping(target = "properties", source = "propertiesJson", qualifiedByName = "json2PropertyDTOList") ServiceConfigDTO fromPO2DTO(ServiceConfigPO serviceConfigPO); diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java index d9c86556..9c99ddbf 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java @@ -34,6 +34,7 @@ import org.apache.bigtop.manager.server.model.converter.ServiceConfigConverter; import org.apache.bigtop.manager.server.model.converter.ServiceConfigSnapshotConverter; import org.apache.bigtop.manager.server.model.converter.ServiceConverter; +import org.apache.bigtop.manager.server.model.dto.ServiceConfigDTO; import org.apache.bigtop.manager.server.model.query.PageQuery; import org.apache.bigtop.manager.server.model.req.ServiceConfigReq; import org.apache.bigtop.manager.server.model.req.ServiceConfigSnapshotReq; @@ -43,6 +44,8 @@ import org.apache.bigtop.manager.server.model.vo.ServiceVO; import org.apache.bigtop.manager.server.service.ServiceService; import org.apache.bigtop.manager.server.utils.PageUtils; +import org.apache.bigtop.manager.server.utils.StackConfigUtils; +import org.apache.bigtop.manager.server.utils.StackUtils; import org.apache.commons.collections4.CollectionUtils; @@ -54,7 +57,6 @@ import lombok.extern.slf4j.Slf4j; import jakarta.annotation.Resource; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -116,15 +118,26 @@ public List listConf(Long clusterId, Long serviceId) { @Override public List updateConf(Long clusterId, Long serviceId, List reqs) { - List list = new ArrayList<>(); - for (ServiceConfigReq req : reqs) { - ServiceConfigPO serviceConfigPO = new ServiceConfigPO(); - serviceConfigPO.setId(req.getId()); - serviceConfigPO.setPropertiesJson(JsonUtils.writeAsString(req.getProperties())); - list.add(serviceConfigPO); - } - - serviceConfigDao.partialUpdateByIds(list); + ServicePO servicePO = serviceDao.findById(serviceId); + List configs = serviceConfigDao.findByServiceId(serviceId); + + List oriConfigs; + List newConfigs; + List mergedConfigs; + + // Merge stack config with existing config first, in case new property has been added to stack config. + oriConfigs = StackUtils.SERVICE_CONFIG_MAP.get(servicePO.getName()); + newConfigs = ServiceConfigConverter.INSTANCE.fromPO2DTO(configs); + mergedConfigs = StackConfigUtils.mergeServiceConfigs(oriConfigs, newConfigs); + + // Merge existing config with new config in request object + oriConfigs = mergedConfigs; + newConfigs = ServiceConfigConverter.INSTANCE.fromReq2DTO(reqs); + mergedConfigs = StackConfigUtils.mergeServiceConfigs(oriConfigs, newConfigs); + + // Save merged config + List serviceConfigPOList = ServiceConfigConverter.INSTANCE.fromDTO2PO(mergedConfigs); + serviceConfigDao.partialUpdateByIds(serviceConfigPOList); return listConf(clusterId, serviceId); } diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackConfigUtils.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackConfigUtils.java index 64e800e4..430172e4 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackConfigUtils.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackConfigUtils.java @@ -20,12 +20,17 @@ import org.apache.bigtop.manager.server.model.dto.AttrsDTO; import org.apache.bigtop.manager.server.model.dto.PropertyDTO; +import org.apache.bigtop.manager.server.model.dto.ServiceConfigDTO; import org.apache.bigtop.manager.server.stack.model.AttrsModel; import org.apache.bigtop.manager.server.stack.model.PropertyModel; import org.apache.bigtop.manager.server.stack.xml.ConfigurationXml; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -68,23 +73,81 @@ private static PropertyDTO getPropertyDTO(PropertyModel propertyModel) { return propertyDTO; } + public static List mergeServiceConfigs( + List oriConfigs, List overrideConfigs) { + // To avoid to change the original configs, we use cloned object + List mergedConfigs = new ArrayList<>(); + for (ServiceConfigDTO oriConfig : oriConfigs) { + ServiceConfigDTO mergedConfig = new ServiceConfigDTO(); + BeanUtils.copyProperties(oriConfig, mergedConfig); + mergedConfigs.add(mergedConfig); + } + + if (CollectionUtils.isEmpty(overrideConfigs)) { + return mergedConfigs; + } + + // Assign id for each service config + for (ServiceConfigDTO config : mergedConfigs) { + config.setId(overrideConfigs.stream() + .filter(x -> x.getName().equals(config.getName())) + .findFirst() + .map(ServiceConfigDTO::getId) + .orElse(null)); + } + + Map> overrideConfigsMap = serviceConfig2Map(overrideConfigs); + for (ServiceConfigDTO mergedConfig : mergedConfigs) { + String configName = mergedConfig.getName(); + if (!overrideConfigsMap.containsKey(configName)) { + continue; + } + + // Override existing properties + Map overridePropertiesMap = overrideConfigsMap.get(configName); + for (PropertyDTO property : mergedConfig.getProperties()) { + String propertyName = property.getName(); + String value = overridePropertiesMap.remove(propertyName); + if (value != null) { + property.setValue(value); + } + } + + // We may still have some properties added by user manually + if (MapUtils.isNotEmpty(overridePropertiesMap)) { + for (Map.Entry entry : overridePropertiesMap.entrySet()) { + PropertyDTO property = new PropertyDTO(); + property.setName(entry.getKey()); + property.setValue(entry.getValue()); + mergedConfig.getProperties().add(property); + } + } + } + + return mergedConfigs; + } + /** - * extract config from List> to Map + * extract config from List to Map> * - * @param list List - * @return Map + * @param configs List + * @return Map> */ - public static Map extractConfigMap(List list) { - if (list == null) { - return null; + private static Map> serviceConfig2Map(List configs) { + Map> outerMap = new HashMap<>(); + if (CollectionUtils.isEmpty(configs)) { + return outerMap; } - Map hashMap = new HashMap<>(); - for (PropertyDTO property : list) { - String key = property.getName(); - Object value = property.getValue(); - hashMap.put(key, value); + for (ServiceConfigDTO config : configs) { + Map innerMap = new HashMap<>(); + for (PropertyDTO property : config.getProperties()) { + innerMap.put(property.getName(), property.getValue()); + } + + outerMap.put(config.getName(), innerMap); } - return hashMap; + + return outerMap; } }