This is an automated email from the ASF dual-hosted git repository.

wuzhiguo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/bigtop-manager.git


The following commit(s) were added to refs/heads/main by this push:
     new 5b61ee74 BIGTOP-4363: Add some unit tests for stack core module (#178)
5b61ee74 is described below

commit 5b61ee74f5cf8b02e2f709b4941c11f9122af28d
Author: xianrenzw <[email protected]>
AuthorDate: Tue Feb 18 14:41:58 2025 +0800

    BIGTOP-4363: Add some unit tests for stack core module (#178)
---
 .../manager/stack/core/spi/hook/AddHook.java       |   2 +-
 .../manager/stack/core/utils/LocalSettings.java    |  16 +-
 .../stack/core/utils/linux/LinuxAccountUtils.java  |   2 +-
 .../manager/stack/core/spi/hook/AddHookTest.java   |  97 +++++++++
 .../stack/core/spi/hook/RestartHookTest.java       |  62 ++++++
 .../manager/stack/core/spi/hook/StartHookTest.java |  62 ++++++
 .../manager/stack/core/spi/hook/StopHookTest.java  |  62 ++++++
 .../stack/core/spi/param/BaseParamsTest.java       | 186 +++++++++++++++++
 .../stack/core/spi/repo/AptPackageManagerTest.java |  97 +++++++++
 .../stack/core/spi/repo/DnfPackageManagerTest.java |  97 +++++++++
 .../stack/core/spi/repo/YumPackageManagerTest.java |  97 +++++++++
 .../core/spi/script/AbstractClientScriptTest.java  |  81 ++++++++
 .../stack/core/tarball/ChecksumValidatorTest.java  | 110 ++++++++++
 .../stack/core/utils/LocalSettingsTest.java        | 224 ++++++++++++++++++++
 .../manager/stack/core/utils/PackageUtilsTest.java |  91 ++++++++
 .../stack/core/utils/PropertiesUtilsTest.java      | 101 +++++++++
 .../core/utils/linux/LinuxAccountUtilsTest.java    | 228 +++++++++++++++++++++
 .../stack/core/utils/linux/LinuxOSUtilsTest.java   | 174 ++++++++++++++++
 .../core/utils/template/TemplateUtilsTest.java     | 109 ++++++++++
 19 files changed, 1890 insertions(+), 8 deletions(-)

diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/spi/hook/AddHook.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/spi/hook/AddHook.java
index 8e9da6e9..14633910 100644
--- 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/spi/hook/AddHook.java
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/spi/hook/AddHook.java
@@ -46,7 +46,7 @@ public class AddHook extends AbstractHook {
         return NAME;
     }
 
-    private void addUserAndGroup(Params params) {
+    protected void addUserAndGroup(Params params) {
         String user = params.user();
         String group = params.group();
 
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/LocalSettings.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/LocalSettings.java
index 1c1f230f..ba0b7363 100644
--- 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/LocalSettings.java
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/LocalSettings.java
@@ -43,7 +43,7 @@ public class LocalSettings {
     public static Map<String, Object> configurations(String service, String 
type) {
 
         Map<String, Object> configDataMap = new HashMap<>();
-        File file = new File(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.CONFIGURATIONS_INFO);
+        File file = createFile(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.CONFIGURATIONS_INFO);
         try {
             if (file.exists()) {
                 Map<String, Map<String, Object>> configJson = 
JsonUtils.readFromFile(file, new TypeReference<>() {});
@@ -67,7 +67,7 @@ public class LocalSettings {
     public static Map<String, List<String>> hosts() {
 
         Map<String, List<String>> hostJson = new HashMap<>();
-        File file = new File(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.HOSTS_INFO);
+        File file = createFile(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.HOSTS_INFO);
         if (file.exists()) {
             hostJson = JsonUtils.readFromFile(file, new TypeReference<>() {});
         }
@@ -77,7 +77,7 @@ public class LocalSettings {
     public static Map<String, Object> basicInfo() {
 
         Map<String, Object> settings = new HashMap<>();
-        File file = new File(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.SETTINGS_INFO);
+        File file = createFile(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.SETTINGS_INFO);
         if (file.exists()) {
             settings = JsonUtils.readFromFile(file, new TypeReference<>() {});
         }
@@ -87,7 +87,7 @@ public class LocalSettings {
     public static Map<String, String> users() {
 
         Map<String, String> userMap = new HashMap<>();
-        File file = new File(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.USERS_INFO);
+        File file = createFile(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.USERS_INFO);
         if (file.exists()) {
             userMap = JsonUtils.readFromFile(file, new TypeReference<>() {});
         }
@@ -101,7 +101,7 @@ public class LocalSettings {
     public static List<RepoInfo> repos() {
 
         List<RepoInfo> repoInfoList = List.of();
-        File file = new File(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.REPOS_INFO);
+        File file = createFile(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.REPOS_INFO);
         if (file.exists()) {
             repoInfoList = JsonUtils.readFromFile(file, new TypeReference<>() 
{});
         }
@@ -111,10 +111,14 @@ public class LocalSettings {
     public static ClusterInfo cluster() {
 
         ClusterInfo clusterInfo = new ClusterInfo();
-        File file = new File(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.CLUSTER_INFO);
+        File file = createFile(ProjectPathUtils.getAgentCachePath() + 
CacheFiles.CLUSTER_INFO);
         if (file.exists()) {
             clusterInfo = JsonUtils.readFromFile(file, new TypeReference<>() 
{});
         }
         return clusterInfo;
     }
+
+    protected static File createFile(String fileName) {
+        return new File(fileName);
+    }
 }
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxAccountUtils.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxAccountUtils.java
index 91bd67c8..0a4139dc 100644
--- 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxAccountUtils.java
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/main/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxAccountUtils.java
@@ -328,7 +328,7 @@ public class LinuxAccountUtils {
         return null;
     }
 
-    private static ShellResult sudoExecCmd(List<String> params) throws 
IOException {
+    protected static ShellResult sudoExecCmd(List<String> params) throws 
IOException {
         if ("root".equals(System.getProperty("user.name"))) {
             return ShellExecutor.execCommand(params);
         } else {
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/AddHookTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/AddHookTest.java
new file mode 100644
index 00000000..d53493d2
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/AddHookTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.stack.core.spi.hook;
+
+import org.apache.bigtop.manager.stack.core.spi.param.Params;
+import org.apache.bigtop.manager.stack.core.utils.linux.LinuxAccountUtils;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class AddHookTest {
+
+    @Mock
+    private AddHook addHook;
+
+    @Mock
+    private Params params;
+
+    @Test
+    public void testDoBefore() {
+        doNothing().when(addHook).addUserAndGroup(any());
+        doCallRealMethod().when(addHook).doBefore(any());
+        addHook.doBefore(params);
+        verify(addHook, times(1)).addUserAndGroup(params);
+    }
+
+    @Test
+    public void testDoAfter() {
+        doCallRealMethod().when(addHook).doAfter(any());
+        addHook.doAfter(params);
+        verify(addHook, never()).addUserAndGroup(params);
+    }
+
+    @Test
+    public void testGetName() {
+        doCallRealMethod().when(addHook).getName();
+        String name = addHook.getName();
+        assert name.equals("add");
+    }
+
+    @Test
+    public void testAddUserAndGroup() {
+        try (MockedStatic<LinuxAccountUtils> linuxAccountUtilsMockedStatic = 
mockStatic(LinuxAccountUtils.class)) {
+            when(params.user()).thenReturn("testUser");
+            when(params.group()).thenReturn("testGroup1");
+            doCallRealMethod().when(addHook).addUserAndGroup(any());
+
+            linuxAccountUtilsMockedStatic
+                    .when(() -> LinuxAccountUtils.userAdd(any(), any()))
+                    .thenAnswer(invocation -> null);
+            linuxAccountUtilsMockedStatic
+                    .when(() -> LinuxAccountUtils.groupAdd(any()))
+                    .thenAnswer(invocation -> null);
+
+            linuxAccountUtilsMockedStatic
+                    .when(() -> LinuxAccountUtils.getUserPrimaryGroup(any()))
+                    .thenReturn("testGroup1");
+            addHook.addUserAndGroup(params);
+            linuxAccountUtilsMockedStatic.verify(() -> 
LinuxAccountUtils.userAdd(any(), any()), never());
+
+            linuxAccountUtilsMockedStatic
+                    .when(() -> LinuxAccountUtils.getUserPrimaryGroup(any()))
+                    .thenReturn("testGroup2");
+            addHook.addUserAndGroup(params);
+            linuxAccountUtilsMockedStatic.verify(() -> 
LinuxAccountUtils.userAdd(any(), any()), times(1));
+        }
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/RestartHookTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/RestartHookTest.java
new file mode 100644
index 00000000..d450fb0c
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/RestartHookTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.stack.core.spi.hook;
+
+import org.apache.bigtop.manager.stack.core.spi.param.Params;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+public class RestartHookTest {
+
+    @Mock
+    private RestartHook restartHook;
+
+    @Mock
+    private Params params;
+
+    @Test
+    public void testDoBefore() {
+        doCallRealMethod().when(restartHook).doBefore(any());
+        restartHook.doBefore(params);
+        verify(restartHook, times(1)).doBefore(params);
+    }
+
+    @Test
+    public void testDoAfter() {
+        doCallRealMethod().when(restartHook).doAfter(any());
+        restartHook.doAfter(params);
+        verify(restartHook, times(1)).doAfter(params);
+    }
+
+    @Test
+    public void testGetName() {
+        doCallRealMethod().when(restartHook).getName();
+        String name = restartHook.getName();
+        assert name.equals("restart");
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/StartHookTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/StartHookTest.java
new file mode 100644
index 00000000..1cdf5089
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/StartHookTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.stack.core.spi.hook;
+
+import org.apache.bigtop.manager.stack.core.spi.param.Params;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+public class StartHookTest {
+
+    @Mock
+    private StartHook startHook;
+
+    @Mock
+    private Params params;
+
+    @Test
+    public void testDoBefore() {
+        doCallRealMethod().when(startHook).doBefore(any());
+        startHook.doBefore(params);
+        verify(startHook, times(1)).doBefore(params);
+    }
+
+    @Test
+    public void testDoAfter() {
+        doCallRealMethod().when(startHook).doAfter(any());
+        startHook.doAfter(params);
+        verify(startHook, times(1)).doAfter(params);
+    }
+
+    @Test
+    public void testGetName() {
+        doCallRealMethod().when(startHook).getName();
+        String name = startHook.getName();
+        assert name.equals("start");
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/StopHookTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/StopHookTest.java
new file mode 100644
index 00000000..43597de3
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/hook/StopHookTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.stack.core.spi.hook;
+
+import org.apache.bigtop.manager.stack.core.spi.param.Params;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+public class StopHookTest {
+
+    @Mock
+    private StopHook stopHook;
+
+    @Mock
+    private Params params;
+
+    @Test
+    public void testDoBefore() {
+        doCallRealMethod().when(stopHook).doBefore(any());
+        stopHook.doBefore(params);
+        verify(stopHook, times(1)).doBefore(params);
+    }
+
+    @Test
+    public void testDoAfter() {
+        doCallRealMethod().when(stopHook).doAfter(any());
+        stopHook.doAfter(params);
+        verify(stopHook, times(1)).doAfter(params);
+    }
+
+    @Test
+    public void testGetName() {
+        doCallRealMethod().when(stopHook).getName();
+        String name = stopHook.getName();
+        assert name.equals("stop");
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/param/BaseParamsTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/param/BaseParamsTest.java
new file mode 100644
index 00000000..eeed94b1
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/param/BaseParamsTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.stack.core.spi.param;
+
+import org.apache.bigtop.manager.common.utils.NetUtils;
+import org.apache.bigtop.manager.common.utils.os.OSDetection;
+import org.apache.bigtop.manager.grpc.payload.ComponentCommandPayload;
+import org.apache.bigtop.manager.grpc.pojo.ClusterInfo;
+import org.apache.bigtop.manager.grpc.pojo.PackageInfo;
+import org.apache.bigtop.manager.grpc.pojo.PackageSpecificInfo;
+import org.apache.bigtop.manager.grpc.pojo.RepoInfo;
+import org.apache.bigtop.manager.grpc.pojo.TemplateInfo;
+import org.apache.bigtop.manager.stack.core.utils.LocalSettings;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mockStatic;
+
+@ExtendWith(MockitoExtension.class)
+public class BaseParamsTest {
+
+    private MockedStatic<LocalSettings> localSettingsMockedStatic;
+    private MockedStatic<OSDetection> osDetectionMockedStatic;
+    private MockedStatic<NetUtils> netUtilsMockedStatic;
+
+    private final ClusterInfo clusterInfo = new ClusterInfo();
+
+    private final ComponentCommandPayload payload = new 
ComponentCommandPayload();
+
+    private MockBaseParams mockBaseParams;
+
+    @BeforeEach
+    public void setUp() {
+        List<RepoInfo> repos = new ArrayList<>();
+        repos.add(new RepoInfo("repo1", "mockArch", "testURL", 2));
+        repos.add(new RepoInfo("repo2", "mockArch", "testURL", 1));
+        repos.add(new RepoInfo("repo3", "mockArch", "testURL", 1));
+
+        List<String> arch = new ArrayList<>();
+        arch.add("mockArch");
+
+        List<PackageInfo> packages = new ArrayList<>();
+        packages.add(new PackageInfo("package1", "testChecksum1"));
+        packages.add(new PackageInfo("package2", "testChecksum2"));
+
+        List<PackageSpecificInfo> packageSpecifics = new ArrayList<>();
+        PackageSpecificInfo packageSpecific = new PackageSpecificInfo();
+        packageSpecific.setArch(arch);
+        packageSpecific.setPackages(packages);
+        packageSpecifics.add(packageSpecific);
+
+        List<TemplateInfo> templates = new ArrayList<>();
+        TemplateInfo template = new TemplateInfo();
+        template.setSrc("mockSrc");
+        template.setDest("mockDest");
+        template.setContent("mockContent");
+        templates.add(template);
+
+        payload.setServiceUser("mockUser");
+        payload.setPackageSpecifics(packageSpecifics);
+        payload.setTemplates(templates);
+
+        clusterInfo.setRootDir("/mockRoot");
+        clusterInfo.setUserGroup("mockGroup");
+
+        mockBaseParams = new MockBaseParams(payload);
+
+        localSettingsMockedStatic = mockStatic(LocalSettings.class);
+        osDetectionMockedStatic = mockStatic(OSDetection.class);
+        netUtilsMockedStatic = mockStatic(NetUtils.class);
+        
netUtilsMockedStatic.when(NetUtils::getHostname).thenReturn("mockHostname");
+        localSettingsMockedStatic.when(LocalSettings::repos).thenReturn(repos);
+        
localSettingsMockedStatic.when(LocalSettings::cluster).thenReturn(clusterInfo);
+        
osDetectionMockedStatic.when(OSDetection::getArch).thenReturn("mockArch");
+    }
+
+    @AfterEach
+    public void tearDown() {
+        localSettingsMockedStatic.close();
+        osDetectionMockedStatic.close();
+        netUtilsMockedStatic.close();
+    }
+
+    @Test
+    public void testHostname() {
+        String hostname = mockBaseParams.hostname();
+        assertEquals("mockHostname", hostname);
+    }
+
+    @Test
+    public void testConfDir() {
+        String confDir = mockBaseParams.confDir();
+        assertEquals("/mockRoot/services/mockService/conf", confDir);
+    }
+
+    @Test
+    public void testUser() {
+        String user = mockBaseParams.user();
+        assertEquals("mockUser", user);
+    }
+
+    @Test
+    public void testGroup() {
+        String group = mockBaseParams.group();
+        assertEquals("mockGroup", group);
+    }
+
+    @Test
+    public void testRepo() {
+        RepoInfo repo = mockBaseParams.repo();
+        assertEquals(1, repo.getType());
+        assertEquals("repo2", repo.getName());
+        assertEquals("mockArch", repo.getArch());
+    }
+
+    @Test
+    public void testPackages() {
+        List<PackageInfo> packages = mockBaseParams.packages();
+        assertEquals(2, packages.size());
+        assertEquals("package1", packages.get(0).getName());
+        assertEquals("package2", packages.get(1).getName());
+    }
+
+    @Test
+    public void testTemplates() {
+        List<TemplateInfo> templates = mockBaseParams.templates();
+        assertEquals(1, templates.size());
+        assertEquals("mockSrc", templates.get(0).getSrc());
+        assertEquals("mockDest", templates.get(0).getDest());
+        assertEquals("mockContent", templates.get(0).getContent());
+    }
+
+    @Test
+    public void testJavaHome() {
+        String javaHome = mockBaseParams.javaHome();
+        assertEquals("/mockRoot/tools/jdk", javaHome);
+    }
+
+    @Test
+    public void testStackHome() {
+        String stackHome = mockBaseParams.stackHome();
+        assertEquals("/mockRoot/services", stackHome);
+    }
+
+    @Test
+    public void testServiceHome() {
+        String serviceHome = mockBaseParams.serviceHome();
+        assertEquals("/mockRoot/services/mockService", serviceHome);
+    }
+
+    private static class MockBaseParams extends BaseParams {
+        public MockBaseParams(ComponentCommandPayload payload) {
+            this.payload = payload;
+        }
+
+        @Override
+        public String getServiceName() {
+            return "mockService";
+        }
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/AptPackageManagerTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/AptPackageManagerTest.java
new file mode 100644
index 00000000..42290801
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/AptPackageManagerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.stack.core.spi.repo;
+
+import org.apache.bigtop.manager.common.shell.ShellExecutor;
+import org.apache.bigtop.manager.common.shell.ShellResult;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.mockStatic;
+
+public class AptPackageManagerTest {
+
+    private MockedStatic<ShellExecutor> mockStatic;
+
+    private final AptPackageManager aptPackageManager = new 
AptPackageManager();
+
+    @BeforeEach
+    public void setUp() {
+        mockStatic = mockStatic(ShellExecutor.class);
+        mockStatic
+                .when(() -> ShellExecutor.execCommand(anyList(), anyBoolean()))
+                .thenAnswer(invocation -> {
+                    List<String> cmd = invocation.getArgument(0);
+                    return ShellResult.success(cmd.toString());
+                });
+    }
+
+    @AfterEach
+    public void tearDown() {
+        mockStatic.close();
+    }
+
+    @Test
+    public void testInstallPackage() {
+        String packageToInstall = "testPackage";
+        ShellResult result = 
aptPackageManager.installPackage(List.of(packageToInstall));
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList(), 
anyBoolean()));
+        assertEquals("[/usr/bin/apt-get, install, -y, testPackage]", 
result.getOutput());
+    }
+
+    @Test
+    public void testUninstallPackage() {
+        String packageToInstall = "testPackage";
+        ShellResult result = 
aptPackageManager.uninstallPackage(List.of(packageToInstall));
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList(), 
anyBoolean()));
+        assertEquals("[/usr/bin/apt-get, remove, -y, testPackage]", 
result.getOutput());
+    }
+
+    @Test
+    public void testListPackages() {
+
+        mockStatic.when(() -> 
ShellExecutor.execCommand(anyList())).thenAnswer(invocation -> {
+            List<String> mockOutput = List.of(
+                    "Listing... Done",
+                    "package1/now 1.2.3-1 amd64 [installed,local]",
+                    "package2/stable 4.5.6-1 amd64 [installed]",
+                    "package3/stable 7.8.9-1 amd64 [installed]");
+            return ShellResult.success(String.join("\n", mockOutput));
+        });
+        List<String> packagesResult = aptPackageManager.listPackages();
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList()));
+        assertEquals(3, packagesResult.size());
+        assertEquals("package1", packagesResult.get(0));
+        assertEquals("package2", packagesResult.get(1));
+        assertEquals("package3", packagesResult.get(2));
+    }
+
+    @Test
+    public void testGetName() {
+        assertEquals("APT", aptPackageManager.getName());
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/DnfPackageManagerTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/DnfPackageManagerTest.java
new file mode 100644
index 00000000..594752bf
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/DnfPackageManagerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.stack.core.spi.repo;
+
+import org.apache.bigtop.manager.common.shell.ShellExecutor;
+import org.apache.bigtop.manager.common.shell.ShellResult;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.mockStatic;
+
+public class DnfPackageManagerTest {
+
+    private MockedStatic<ShellExecutor> mockStatic;
+
+    private final DnfPackageManager dnfPackageManager = new 
DnfPackageManager();
+
+    @BeforeEach
+    public void setUp() {
+        mockStatic = mockStatic(ShellExecutor.class);
+        mockStatic
+                .when(() -> ShellExecutor.execCommand(anyList(), anyBoolean()))
+                .thenAnswer(invocation -> {
+                    List<String> cmd = invocation.getArgument(0);
+                    return ShellResult.success(cmd.toString());
+                });
+    }
+
+    @AfterEach
+    public void tearDown() {
+        mockStatic.close();
+    }
+
+    @Test
+    public void testInstallPackage() {
+        String packageToInstall = "testPackage";
+        ShellResult result = 
dnfPackageManager.installPackage(List.of(packageToInstall));
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList(), 
anyBoolean()));
+        assertEquals("[/usr/bin/dnf, install, -y, testPackage]", 
result.getOutput());
+    }
+
+    @Test
+    public void testUninstallPackage() {
+        String packageToRemove = "testPackage";
+        ShellResult result = 
dnfPackageManager.uninstallPackage(List.of(packageToRemove));
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList(), 
anyBoolean()));
+        assertEquals("[/usr/bin/dnf, remove, -y, testPackage]", 
result.getOutput());
+    }
+
+    @Test
+    public void testListPackages() {
+        mockStatic.when(() -> 
ShellExecutor.execCommand(anyList())).thenAnswer(invocation -> {
+            List<String> mockOutput = List.of(
+                    "Listing... Done",
+                    "package1.x86_64 1.2.3-1 @updates",
+                    "package2.noarch 4.5.6-1 @fedora",
+                    "package3.i686 7.8.9-1 @fedora");
+            return ShellResult.success(String.join("\n", mockOutput));
+        });
+
+        List<String> packagesResult = dnfPackageManager.listPackages();
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList()));
+        assertEquals(3, packagesResult.size());
+        assertEquals("package1", packagesResult.get(0));
+        assertEquals("package2", packagesResult.get(1));
+        assertEquals("package3", packagesResult.get(2));
+    }
+
+    @Test
+    public void testGetName() {
+        assertEquals("DNF", dnfPackageManager.getName());
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/YumPackageManagerTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/YumPackageManagerTest.java
new file mode 100644
index 00000000..8c545de2
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/repo/YumPackageManagerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.stack.core.spi.repo;
+
+import org.apache.bigtop.manager.common.shell.ShellExecutor;
+import org.apache.bigtop.manager.common.shell.ShellResult;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.mockStatic;
+
+public class YumPackageManagerTest {
+
+    private MockedStatic<ShellExecutor> mockStatic;
+
+    private final YumPackageManager yumPackageManager = new 
YumPackageManager();
+
+    @BeforeEach
+    public void setUp() {
+        mockStatic = mockStatic(ShellExecutor.class);
+        mockStatic
+                .when(() -> ShellExecutor.execCommand(anyList(), anyBoolean()))
+                .thenAnswer(invocation -> {
+                    List<String> cmd = invocation.getArgument(0);
+                    return ShellResult.success(cmd.toString());
+                });
+    }
+
+    @AfterEach
+    public void tearDown() {
+        mockStatic.close();
+    }
+
+    @Test
+    public void testInstallPackage() {
+        String packageToInstall = "testPackage";
+        ShellResult result = 
yumPackageManager.installPackage(List.of(packageToInstall));
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList(), 
anyBoolean()));
+        assertEquals("[/usr/bin/yum, install, -y, testPackage]", 
result.getOutput());
+    }
+
+    @Test
+    public void testUninstallPackage() {
+        String packageToRemove = "testPackage";
+        ShellResult result = 
yumPackageManager.uninstallPackage(List.of(packageToRemove));
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList(), 
anyBoolean()));
+        assertEquals("[/usr/bin/yum, remove, -y, testPackage]", 
result.getOutput());
+    }
+
+    @Test
+    public void testListPackages() {
+        mockStatic.when(() -> 
ShellExecutor.execCommand(anyList())).thenAnswer(invocation -> {
+            List<String> mockOutput = List.of(
+                    "Installed Packages",
+                    "package1.x86_64 1.2.3-1",
+                    "package2.noarch 4.5.6-1",
+                    "package3.i686 7.8.9-1");
+            return ShellResult.success(String.join("\n", mockOutput));
+        });
+
+        List<String> packagesResult = yumPackageManager.listPackages();
+        mockStatic.verify(() -> ShellExecutor.execCommand(anyList()));
+        assertEquals(3, packagesResult.size());
+        assertEquals("package1", packagesResult.get(0));
+        assertEquals("package2", packagesResult.get(1));
+        assertEquals("package3", packagesResult.get(2));
+    }
+
+    @Test
+    public void testGetName() {
+        assertEquals("YUM", yumPackageManager.getName());
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/script/AbstractClientScriptTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/script/AbstractClientScriptTest.java
new file mode 100644
index 00000000..e2a2a6f1
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/spi/script/AbstractClientScriptTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.stack.core.spi.script;
+
+import org.apache.bigtop.manager.common.constants.MessageConstants;
+import org.apache.bigtop.manager.common.shell.ShellResult;
+import org.apache.bigtop.manager.stack.core.spi.param.Params;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@ExtendWith(MockitoExtension.class)
+public class AbstractClientScriptTest {
+
+    @Mock
+    private Params params;
+
+    @Test
+    public void testStart() {
+        MockClientScript clientScript = new MockClientScript();
+        ShellResult result = clientScript.start(params);
+        assertEquals(MessageConstants.SUCCESS_CODE, result.getExitCode());
+    }
+
+    @Test
+    public void testStop() {
+        MockClientScript clientScript = new MockClientScript();
+        ShellResult result = clientScript.stop(params);
+        assertEquals(MessageConstants.SUCCESS_CODE, result.getExitCode());
+    }
+
+    @Test
+    public void testStatus() {
+        MockClientScript clientScript = new MockClientScript();
+        ShellResult result = clientScript.status(params);
+        assertEquals(MessageConstants.SUCCESS_CODE, result.getExitCode());
+    }
+
+    private static class MockClientScript extends AbstractClientScript {
+
+        @Override
+        public ShellResult start(Params params) {
+            return super.start(params);
+        }
+
+        @Override
+        public ShellResult stop(Params params) {
+            return super.stop(params);
+        }
+
+        @Override
+        public ShellResult status(Params params) {
+            return super.status(params);
+        }
+
+        @Override
+        public String getComponentName() {
+            return "MockClientScript";
+        }
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/tarball/ChecksumValidatorTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/tarball/ChecksumValidatorTest.java
new file mode 100644
index 00000000..beb375a4
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/tarball/ChecksumValidatorTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.stack.core.tarball;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@Slf4j
+class ChecksumValidatorTest {
+
+    @TempDir
+    private Path tempDir;
+
+    @Test
+    void testValidateChecksum_HappyPath() throws Exception {
+        // Create an empty temporary file
+        Path tempFilePath = tempDir.resolve("testfile.txt");
+        Files.write(tempFilePath, new byte[0]);
+        File file = tempFilePath.toFile();
+
+        String expectedChecksum = 
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+        boolean result = ChecksumValidator.validateChecksum("SHA-256", 
expectedChecksum, file);
+
+        assertTrue(result, "Checksum validation should succeed for valid 
case");
+    }
+
+    @Test
+    void testValidateChecksum_EdgeCase_UnsupportedAlgorithm() throws Exception 
{
+        // Create an empty temporary file
+        Path tempFilePath = tempDir.resolve("testfile.txt");
+        Files.write(tempFilePath, new byte[0]);
+        File file = tempFilePath.toFile();
+
+        boolean result = 
ChecksumValidator.validateChecksum("INVALID-ALGORITHM", "any-checksum", file);
+
+        assertFalse(result, "Should return false for unsupported algorithm");
+    }
+
+    @Test
+    void testValidateChecksum_EdgeCase_FileNotExist() {
+        // Use a non-existent file path
+        File file = tempDir.resolve("non_existent.txt").toFile();
+        boolean result = ChecksumValidator.validateChecksum("SHA-256", 
"any-checksum", file);
+
+        assertFalse(result, "Should return false for non-existent file");
+    }
+
+    @Test
+    void testValidateChecksum_EdgeCase_EmptyFile() throws Exception {
+        // Create an empty temporary file
+        Path tempFilePath = tempDir.resolve("emptyfile.txt");
+        Files.write(tempFilePath, new byte[0]);
+        File file = tempFilePath.toFile();
+
+        String expectedChecksum = 
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+        boolean result = ChecksumValidator.validateChecksum("SHA-256", 
expectedChecksum, file);
+
+        assertTrue(result, "Checksum validation should succeed for empty 
file");
+    }
+
+    @Test
+    void testValidateChecksum_EdgeCase_ChecksumMismatch() throws Exception {
+        // Create a temporary file with content
+        Path tempFilePath = tempDir.resolve("datafile.txt");
+        Files.write(tempFilePath, "test_data".getBytes());
+        File file = tempFilePath.toFile();
+
+        boolean result = ChecksumValidator.validateChecksum("SHA-256", 
"wrong_checksum", file);
+
+        assertFalse(result, "Should return false for checksum mismatch");
+    }
+
+    @Test
+    void testValidateChecksum_EdgeCase_CaseInsensitive() throws Exception {
+        // Create an empty temporary file
+        Path tempFilePath = tempDir.resolve("casefile.txt");
+        Files.write(tempFilePath, new byte[0]);
+        File file = tempFilePath.toFile();
+
+        String expectedChecksum = 
"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855";
+        boolean result = ChecksumValidator.validateChecksum("sha-256", 
expectedChecksum, file);
+
+        assertTrue(result, "Checksum validation should be case-insensitive");
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/LocalSettingsTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/LocalSettingsTest.java
new file mode 100644
index 00000000..fef270bf
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/LocalSettingsTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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.stack.core.utils;
+
+import org.apache.bigtop.manager.common.utils.JsonUtils;
+import org.apache.bigtop.manager.common.utils.ProjectPathUtils;
+import org.apache.bigtop.manager.grpc.pojo.ClusterInfo;
+import org.apache.bigtop.manager.grpc.pojo.RepoInfo;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
+public class LocalSettingsTest {
+
+    private MockedStatic<JsonUtils> jsonUtilsMockedStatic;
+
+    private MockedStatic<ProjectPathUtils> projectPathUtilsMockedStatic;
+
+    private MockedStatic<LocalSettings> localSettingsMockedStatic;
+
+    @BeforeEach
+    public void setUp() {
+        jsonUtilsMockedStatic = mockStatic(JsonUtils.class);
+        projectPathUtilsMockedStatic = mockStatic(ProjectPathUtils.class);
+        localSettingsMockedStatic = mockStatic(LocalSettings.class);
+    }
+
+    @AfterEach
+    public void tearDown() {
+        jsonUtilsMockedStatic.close();
+        projectPathUtilsMockedStatic.close();
+        localSettingsMockedStatic.close();
+    }
+
+    @Test
+    public void testConfigurations() throws Exception {
+        String service = "serviceA";
+        String type = "typeA";
+        String key = "keyA";
+        String defaultValue = "defaultValue";
+
+        Map<String, Object> configDataMap = new HashMap<>();
+        configDataMap.put(key, "valueA");
+        String configDataMapJson = new 
ObjectMapper().writeValueAsString(configDataMap);
+
+        Map<String, Map<String, Object>> configJson = new HashMap<>();
+        configJson.put(service, new HashMap<>());
+        configJson.get(service).put(type, configDataMapJson);
+
+        File file = mock(File.class);
+        
localSettingsMockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn("/mock/path/");
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.createFile(anyString()))
+                .thenReturn(file);
+        when(file.exists()).thenReturn(true);
+        localSettingsMockedStatic
+                .when(() -> JsonUtils.readFromFile(any(File.class), 
any(TypeReference.class)))
+                .thenReturn(configJson);
+        localSettingsMockedStatic
+                .when(() -> JsonUtils.readFromString(anyString(), 
any(TypeReference.class)))
+                .thenCallRealMethod();
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.configurations(anyString(), 
anyString(), anyString(), any()))
+                .thenCallRealMethod();
+
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.configurations(anyString(), 
anyString()))
+                .thenCallRealMethod();
+        assertEquals("valueA", LocalSettings.configurations(service, type, 
key, defaultValue));
+
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.configurations(anyString(), 
anyString()))
+                .thenReturn(null);
+        assertEquals("defaultValue", LocalSettings.configurations(service, 
type, key, defaultValue));
+    }
+
+    @Test
+    public void testHosts() {
+        String componentName = "componentA";
+
+        Map<String, List<String>> hostJson = new HashMap<>();
+        hostJson.put(componentName, List.of("host1", "host2"));
+
+        File file = mock(File.class);
+        
localSettingsMockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn("/mock/path/");
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.createFile(anyString()))
+                .thenReturn(file);
+        when(file.exists()).thenReturn(true);
+        localSettingsMockedStatic
+                .when(() -> JsonUtils.readFromFile(any(File.class), 
any(TypeReference.class)))
+                .thenReturn(hostJson);
+        localSettingsMockedStatic.when(() -> 
LocalSettings.hosts(anyString())).thenCallRealMethod();
+        
localSettingsMockedStatic.when(LocalSettings::hosts).thenCallRealMethod();
+
+        List<String> expectedHosts = List.of("host1", "host2");
+        assertEquals(expectedHosts, LocalSettings.hosts(componentName));
+    }
+
+    @Test
+    public void testBasicInfo() {
+        Map<String, Object> settingsData = new HashMap<>();
+        settingsData.put("key1", "value1");
+
+        File file = mock(File.class);
+        
localSettingsMockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn("/mock/path/");
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.createFile(anyString()))
+                .thenReturn(file);
+        when(file.exists()).thenReturn(true);
+        localSettingsMockedStatic
+                .when(() -> JsonUtils.readFromFile(any(File.class), 
any(TypeReference.class)))
+                .thenReturn(settingsData);
+        
localSettingsMockedStatic.when(LocalSettings::basicInfo).thenCallRealMethod();
+
+        Map<String, Object> expectedSettings = new HashMap<>();
+        expectedSettings.put("key1", "value1");
+        assertEquals(expectedSettings, LocalSettings.basicInfo());
+    }
+
+    @Test
+    public void testUsers() {
+        Map<String, String> userMap = new HashMap<>();
+        userMap.put("user1", "password1");
+
+        File file = mock(File.class);
+        
localSettingsMockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn("/mock/path/");
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.createFile(anyString()))
+                .thenReturn(file);
+        when(file.exists()).thenReturn(true);
+        localSettingsMockedStatic
+                .when(() -> JsonUtils.readFromFile(any(File.class), 
any(TypeReference.class)))
+                .thenReturn(userMap);
+        
localSettingsMockedStatic.when(LocalSettings::users).thenCallRealMethod();
+
+        Map<String, String> expectedUserMap = new HashMap<>();
+        expectedUserMap.put("user1", "password1");
+        assertEquals(expectedUserMap, LocalSettings.users());
+    }
+
+    @Test
+    public void testRepos() {
+        RepoInfo repo1 = new RepoInfo("repo1", "x86_64", "http://repo1.com";, 
1);
+        RepoInfo repo2 = new RepoInfo("repo2", "arch64", "http://repo2.com";, 
2);
+        List<RepoInfo> repoInfoList = List.of(repo1, repo2);
+
+        File file = mock(File.class);
+        
localSettingsMockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn("/mock/path/");
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.createFile(anyString()))
+                .thenReturn(file);
+        when(file.exists()).thenReturn(true);
+        localSettingsMockedStatic
+                .when(() -> JsonUtils.readFromFile(any(File.class), 
any(TypeReference.class)))
+                .thenReturn(repoInfoList);
+        
localSettingsMockedStatic.when(LocalSettings::repos).thenCallRealMethod();
+
+        List<RepoInfo> expectedRepoInfoList = List.of(
+                new RepoInfo("repo1", "x86_64", "http://repo1.com";, 1),
+                new RepoInfo("repo2", "arch64", "http://repo2.com";, 2));
+        assertEquals(expectedRepoInfoList, LocalSettings.repos());
+    }
+
+    @Test
+    public void testCluster() {
+        ClusterInfo clusterInfo = new ClusterInfo();
+        clusterInfo.setName("Test Cluster");
+
+        File file = mock(File.class);
+        
localSettingsMockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn("/mock/path/");
+        localSettingsMockedStatic
+                .when(() -> LocalSettings.createFile(anyString()))
+                .thenReturn(file);
+        when(file.exists()).thenReturn(true);
+        localSettingsMockedStatic
+                .when(() -> JsonUtils.readFromFile(any(File.class), 
any(TypeReference.class)))
+                .thenReturn(clusterInfo);
+        
localSettingsMockedStatic.when(LocalSettings::cluster).thenCallRealMethod();
+
+        ClusterInfo expectedClusterInfo = new ClusterInfo();
+        expectedClusterInfo.setName("Test Cluster");
+        assertEquals(expectedClusterInfo, LocalSettings.cluster());
+    }
+
+    @Test
+    public void testPackages() {
+        List<String> expectedPackages = List.of();
+        assertEquals(expectedPackages, LocalSettings.packages());
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/PackageUtilsTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/PackageUtilsTest.java
new file mode 100644
index 00000000..18565cde
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/PackageUtilsTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.stack.core.utils;
+
+import org.apache.bigtop.manager.common.shell.ShellResult;
+import org.apache.bigtop.manager.stack.core.spi.repo.YumPackageManager;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class PackageUtilsTest {
+
+    @Mock
+    private YumPackageManager yumPackageManager;
+
+    private MockedStatic<PackageUtils> packageUtilsMockedStatic;
+
+    @BeforeEach
+    public void setUp() {
+        packageUtilsMockedStatic = mockStatic(PackageUtils.class);
+        
packageUtilsMockedStatic.when(PackageUtils::getPackageManager).thenReturn(yumPackageManager);
+    }
+
+    @AfterEach
+    public void tearDown() {
+        packageUtilsMockedStatic.close();
+    }
+
+    @Test
+    public void testInstall() {
+        packageUtilsMockedStatic.when(() -> 
PackageUtils.install(any())).thenCallRealMethod();
+
+        ShellResult expectedResult = new ShellResult();
+        expectedResult.setExitCode(0);
+        expectedResult.setErrMsg("Installation successful");
+
+        
when(yumPackageManager.installPackage(any())).thenReturn(expectedResult);
+
+        ShellResult result = PackageUtils.install(Arrays.asList("package1", 
"package2"));
+
+        assertEquals(0, result.getExitCode());
+        assertEquals("Installation successful", result.getErrMsg());
+
+        verify(yumPackageManager, times(1)).installPackage(any());
+    }
+
+    @Test
+    public void testInstallWithEmptyPackageList() {
+        packageUtilsMockedStatic.when(() -> 
PackageUtils.install(any())).thenCallRealMethod();
+
+        ShellResult result = PackageUtils.install(Collections.emptyList());
+
+        assertEquals(-1, result.getExitCode());
+        assertEquals("packageList is empty", result.getErrMsg());
+
+        verify(yumPackageManager, never()).installPackage(any());
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/PropertiesUtilsTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/PropertiesUtilsTest.java
new file mode 100644
index 00000000..f411b113
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/PropertiesUtilsTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.stack.core.utils;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PropertiesUtilsTest {
+
+    private File testFile;
+
+    @BeforeEach
+    public void setUp() throws IOException {
+        testFile = File.createTempFile("test", ".properties");
+    }
+
+    @AfterEach
+    public void tearDown() {
+        if (testFile != null) {
+            testFile.delete();
+        }
+    }
+
+    @Test
+    public void testWritePropertiesWithMap() throws IOException {
+        Map<String, Object> configMap = new HashMap<>();
+        configMap.put("key1", "value1");
+        configMap.put("key2", "value2");
+
+        PropertiesUtils.writeProperties(testFile.getAbsolutePath(), configMap);
+
+        Properties properties = new Properties();
+        properties.load(new FileReader(testFile, StandardCharsets.UTF_8));
+
+        assertEquals("value1", properties.getProperty("key1"));
+        assertEquals("value2", properties.getProperty("key2"));
+    }
+
+    @Test
+    public void testWritePropertiesWithList() throws IOException {
+        Map<String, Object> map1 = new HashMap<>();
+        map1.put("name", "key1");
+        map1.put("value", "value1");
+
+        Map<String, Object> map2 = new HashMap<>();
+        map2.put("name", "key2");
+        map2.put("value", "value2");
+
+        List<Map<String, Object>> configList = List.of(map1, map2);
+
+        PropertiesUtils.writeProperties(testFile.getAbsolutePath(), 
configList);
+
+        Properties properties = new Properties();
+        properties.load(new FileReader(testFile, StandardCharsets.UTF_8));
+
+        assertEquals("value1", properties.getProperty("key1"));
+        assertEquals("value2", properties.getProperty("key2"));
+    }
+
+    @Test
+    public void testReadProperties() {
+        Map<String, Object> configMap = new HashMap<>();
+        configMap.put("key1", "value1");
+        configMap.put("key2", "value2");
+
+        PropertiesUtils.writeProperties(testFile.getAbsolutePath(), configMap);
+
+        Map<Object, Object> properties = 
PropertiesUtils.readProperties(testFile.getAbsolutePath());
+
+        assertEquals("value1", properties.get("key1"));
+        assertEquals("value2", properties.get("key2"));
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxAccountUtilsTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxAccountUtilsTest.java
new file mode 100644
index 00000000..96dcf7ce
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxAccountUtilsTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.stack.core.utils.linux;
+
+import org.apache.bigtop.manager.common.shell.ShellResult;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedStatic;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.isNull;
+import static org.mockito.Mockito.mockStatic;
+
+public class LinuxAccountUtilsTest {
+
+    private MockedStatic<LinuxAccountUtils> mockStatic;
+
+    @BeforeEach
+    public void setUp() {
+        mockStatic = mockStatic(LinuxAccountUtils.class);
+
+        // Mock sudoExecCmd method to simulate successful command execution
+        mockStatic.when(() -> 
LinuxAccountUtils.sudoExecCmd(anyList())).thenAnswer(invocation -> {
+            List<String> cmd = invocation.getArgument(0);
+            return ShellResult.success(cmd.toString());
+        });
+
+        // Mock isUserExists and isGroupExists methods to return false by 
default
+        mockStatic.when(() -> 
LinuxAccountUtils.isUserExists(anyString())).thenReturn(false);
+        mockStatic.when(() -> 
LinuxAccountUtils.isGroupExists(anyString())).thenReturn(false);
+    }
+
+    @AfterEach
+    public void tearDown() {
+        mockStatic.close();
+    }
+
+    @Test
+    public void testUserDel() {
+        String user = "testUser";
+
+        // Mock isUserExists to return true for the test user
+        mockStatic.when(() -> 
LinuxAccountUtils.isUserExists(user)).thenReturn(true);
+        mockStatic.when(() -> 
LinuxAccountUtils.userDel(anyString())).thenCallRealMethod();
+
+        // Capture the arguments passed to sudoExecCmd
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+
+        // Call the method under test
+        LinuxAccountUtils.userDel(user);
+
+        // Verify that sudoExecCmd was called and capture the arguments
+        mockStatic.verify(() -> 
LinuxAccountUtils.sudoExecCmd(captor.capture()));
+
+        // Get the captured arguments and perform assertions
+        List<String> builderParameters = captor.getValue();
+        assertNotNull(builderParameters);
+        assertEquals(2, builderParameters.size());
+        assertTrue(builderParameters.contains("/usr/sbin/userdel"));
+        assertTrue(builderParameters.contains(user));
+    }
+
+    @Test
+    public void testUserAdd() {
+        String user = "testUser";
+        String group = "testGroup";
+
+        // Mock isGroupExists to return true for the test group
+        mockStatic.when(() -> 
LinuxAccountUtils.isGroupExists(group)).thenReturn(true);
+        mockStatic
+                .when(() -> LinuxAccountUtils.userAdd(anyString(), 
anyString()))
+                .thenCallRealMethod();
+        mockStatic
+                .when(() -> LinuxAccountUtils.userAdd(
+                        anyString(), anyString(), isNull(), isNull(), 
isNull(), isNull(), isNull(), eq(false)))
+                .thenCallRealMethod();
+
+        // Capture the arguments passed to sudoExecCmd
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+
+        // Call the method under test
+        LinuxAccountUtils.userAdd(user, group);
+
+        // Verify that sudoExecCmd was called and capture the arguments
+        mockStatic.verify(() -> 
LinuxAccountUtils.sudoExecCmd(captor.capture()));
+
+        // Get the captured arguments and perform assertions
+        List<String> builderParameters = captor.getValue();
+        assertNotNull(builderParameters);
+        assertTrue(builderParameters.contains("/usr/sbin/useradd"));
+        assertTrue(builderParameters.contains("-m"));
+        assertTrue(builderParameters.contains("-g"));
+        assertTrue(builderParameters.contains(group));
+        assertTrue(builderParameters.contains(user));
+    }
+
+    @Test
+    public void testGroupDel() {
+        String group = "testGroup";
+
+        // Mock isGroupExists to return true for the test group
+        mockStatic.when(() -> 
LinuxAccountUtils.isGroupExists(group)).thenReturn(true);
+        mockStatic.when(() -> 
LinuxAccountUtils.groupDel(anyString())).thenCallRealMethod();
+
+        // Capture the arguments passed to sudoExecCmd
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+
+        // Call the method under test
+        LinuxAccountUtils.groupDel(group);
+
+        // Verify that sudoExecCmd was called and capture the arguments
+        mockStatic.verify(() -> 
LinuxAccountUtils.sudoExecCmd(captor.capture()));
+
+        // Get the captured arguments and perform assertions
+        List<String> builderParameters = captor.getValue();
+        assertNotNull(builderParameters);
+        assertEquals(2, builderParameters.size());
+        assertTrue(builderParameters.contains("/usr/sbin/groupdel"));
+        assertTrue(builderParameters.contains(group));
+    }
+
+    @Test
+    public void testGroupAdd() {
+        String group = "testGroup";
+
+        // Mock isGroupExists to return false, so groupAdd will be called
+        mockStatic.when(() -> 
LinuxAccountUtils.isGroupExists(group)).thenReturn(false);
+        mockStatic.when(() -> 
LinuxAccountUtils.groupAdd(anyString())).thenCallRealMethod();
+        mockStatic
+                .when(() -> LinuxAccountUtils.groupAdd(anyString(), isNull(), 
isNull()))
+                .thenCallRealMethod();
+
+        // Capture the arguments passed to sudoExecCmd
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+
+        // Call the method under test
+        LinuxAccountUtils.groupAdd(group);
+
+        // Verify that sudoExecCmd was called and capture the arguments
+        mockStatic.verify(() -> 
LinuxAccountUtils.sudoExecCmd(captor.capture()));
+
+        // Get the captured arguments and perform assertions
+        List<String> builderParameters = captor.getValue();
+        assertNotNull(builderParameters);
+        assertEquals(2, builderParameters.size());
+        assertTrue(builderParameters.contains("/usr/sbin/groupadd"));
+        assertTrue(builderParameters.contains(group));
+    }
+
+    @Test
+    public void testIsUserExists() throws IOException {
+        String user = "testUser";
+
+        // Mock sudoExecCmd to simulate successful user existence check
+        mockStatic.when(() -> 
LinuxAccountUtils.isUserExists(user)).thenCallRealMethod();
+        mockStatic.when(() -> 
LinuxAccountUtils.sudoExecCmd(anyList())).thenReturn(new ShellResult(0, "", 
""));
+
+        // Call the method under test
+        boolean exists = LinuxAccountUtils.isUserExists(user);
+
+        // Perform assertions
+        assertTrue(exists);
+
+        // Capture the arguments passed to sudoExecCmd
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+        mockStatic.verify(() -> 
LinuxAccountUtils.sudoExecCmd(captor.capture()));
+
+        // Get the captured arguments and perform assertions
+        List<String> builderParameters = captor.getValue();
+        assertNotNull(builderParameters);
+        assertTrue(builderParameters.contains("sh"));
+        assertTrue(builderParameters.contains("-c"));
+        assertTrue(builderParameters.get(2).contains("grep"));
+    }
+
+    @Test
+    public void testIsGroupExists() throws IOException {
+        String group = "testGroup";
+
+        // Mock sudoExecCmd to simulate successful group existence check
+        mockStatic.when(() -> 
LinuxAccountUtils.isGroupExists(group)).thenCallRealMethod();
+        mockStatic.when(() -> 
LinuxAccountUtils.sudoExecCmd(anyList())).thenReturn(new ShellResult(0, "", 
""));
+
+        // Call the method under test
+        boolean exists = LinuxAccountUtils.isGroupExists(group);
+
+        // Perform assertions
+        assertTrue(exists);
+
+        // Capture the arguments passed to sudoExecCmd
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+        mockStatic.verify(() -> 
LinuxAccountUtils.sudoExecCmd(captor.capture()));
+
+        // Get the captured arguments and perform assertions
+        List<String> builderParameters = captor.getValue();
+        assertNotNull(builderParameters);
+        assertTrue(builderParameters.contains("sh"));
+        assertTrue(builderParameters.contains("-c"));
+        assertTrue(builderParameters.get(2).contains("grep"));
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxOSUtilsTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxOSUtilsTest.java
new file mode 100644
index 00000000..051cff20
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/linux/LinuxOSUtilsTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.stack.core.utils.linux;
+
+import org.apache.bigtop.manager.common.shell.ShellExecutor;
+import org.apache.bigtop.manager.common.shell.ShellResult;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedStatic;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.mockStatic;
+
+public class LinuxOSUtilsTest {
+
+    private MockedStatic<LinuxAccountUtils> mockLinuxAccountUtils;
+    private MockedStatic<ShellExecutor> mockShellExecutor;
+
+    @BeforeEach
+    public void setUp() {
+        mockLinuxAccountUtils = mockStatic(LinuxAccountUtils.class);
+        mockShellExecutor = mockStatic(ShellExecutor.class);
+    }
+
+    @AfterEach
+    public void tearDown() {
+        mockLinuxAccountUtils.close();
+        mockShellExecutor.close();
+    }
+
+    @Test
+    public void testSudoExecCmdWithTenant() throws IOException {
+        String command = "echo Hello";
+        String tenant = "testUser";
+
+        // Mock the behavior of execCmd method
+        mockLinuxAccountUtils.when(() -> 
LinuxAccountUtils.isUserExists(tenant)).thenReturn(true);
+        mockShellExecutor.when(() -> 
ShellExecutor.execCommand(anyList())).thenReturn(new ShellResult(0, "Hello", 
""));
+
+        // Call the method under test
+        ShellResult result = LinuxOSUtils.sudoExecCmd(command, tenant);
+
+        // Capture the arguments passed to ShellExecutor.execCommand
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+        mockShellExecutor.verify(() -> 
ShellExecutor.execCommand(captor.capture()));
+
+        // Assert the result
+        assertNotNull(result);
+        assertEquals(0, result.getExitCode());
+        assertTrue(result.getOutput().contains("Hello"));
+
+        // Assert that sudoExecCmd passes the correct parameters
+        List<String> commandArgs = captor.getValue();
+        assertTrue(commandArgs.contains("sudo"));
+        assertTrue(commandArgs.contains("-u"));
+        assertTrue(commandArgs.contains(tenant));
+        assertTrue(commandArgs.contains("sh"));
+        assertTrue(commandArgs.contains("-c"));
+        assertTrue(commandArgs.contains(command));
+    }
+
+    @Test
+    public void testSudoExecCmdWithoutTenant() throws IOException {
+        String command = "echo Hello";
+
+        // Mock the behavior of execCmd method
+        mockShellExecutor.when(() -> 
ShellExecutor.execCommand(anyList())).thenReturn(new ShellResult(0, "Hello", 
""));
+
+        // Call the method under test with null tenant
+        ShellResult result = LinuxOSUtils.sudoExecCmd(command, null);
+
+        // Capture the arguments passed to ShellExecutor.execCommand
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+        mockShellExecutor.verify(() -> 
ShellExecutor.execCommand(captor.capture()));
+
+        // Assert the result
+        assertNotNull(result);
+        assertEquals(0, result.getExitCode());
+        assertTrue(result.getOutput().contains("Hello"));
+
+        // Assert that sudoExecCmd passes "root" as the tenant when tenant is 
null
+        List<String> commandArgs = captor.getValue();
+        assertTrue(commandArgs.contains("sudo"));
+        assertTrue(commandArgs.contains("-u"));
+        assertTrue(commandArgs.contains("root"));
+        assertTrue(commandArgs.contains("sh"));
+        assertTrue(commandArgs.contains("-c"));
+        assertTrue(commandArgs.contains(command));
+    }
+
+    @Test
+    public void testGetTenantWithExistingUser() {
+        String tenant = "testUser";
+
+        // Mock the isUserExists method to return true for the test user
+        mockLinuxAccountUtils.when(() -> 
LinuxAccountUtils.isUserExists(tenant)).thenReturn(true);
+
+        // Call the method under test
+        String result = LinuxOSUtils.getTenant(tenant);
+
+        // Assert that the correct tenant is returned
+        assertEquals(tenant, result);
+    }
+
+    @Test
+    public void testGetTenantWithNonExistingUser() {
+        String tenant = "nonExistentUser";
+
+        // Mock the isUserExists method to return false for the non-existent 
user
+        mockLinuxAccountUtils.when(() -> 
LinuxAccountUtils.isUserExists(tenant)).thenReturn(false);
+
+        // Call the method under test
+        String result = LinuxOSUtils.getTenant(tenant);
+
+        // Assert that "root" is returned as the default tenant
+        assertEquals("root", result);
+    }
+
+    @Test
+    public void testCheckProcessWhenPidFileDoesNotExist() {
+        String filepath = "/path/to/pidfile";
+
+        // Mock the behavior of the file check
+        mockShellExecutor.when(() -> 
LinuxFileUtils.readFile(filepath)).thenThrow(IOException.class);
+
+        // Call the method under test
+        ShellResult result = LinuxOSUtils.checkProcess(filepath);
+
+        // Assert that the process is not running
+        assertEquals(-1, result.getExitCode());
+        assertTrue(result.getErrMsg().contains("Component is not running"));
+    }
+
+    @Test
+    public void testExecCmd() throws IOException {
+        String command = "echo Hello";
+
+        // Mock the behavior of execCmd method
+        mockShellExecutor.when(() -> 
ShellExecutor.execCommand(anyList())).thenReturn(new ShellResult(0, "Hello", 
""));
+
+        // Call the method under test
+        ShellResult result = LinuxOSUtils.execCmd(command);
+
+        // Assert the result
+        assertNotNull(result);
+        assertEquals(0, result.getExitCode());
+        assertTrue(result.getOutput().contains("Hello"));
+    }
+}
diff --git 
a/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/template/TemplateUtilsTest.java
 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/template/TemplateUtilsTest.java
new file mode 100644
index 00000000..80c263b4
--- /dev/null
+++ 
b/bigtop-manager-stack/bigtop-manager-stack-core/src/test/java/org/apache/bigtop/manager/stack/core/utils/template/TemplateUtilsTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.stack.core.utils.template;
+
+import org.apache.bigtop.manager.stack.core.enums.ConfigType;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.times;
+
+@ExtendWith(MockitoExtension.class)
+public class TemplateUtilsTest {
+
+    private MockedStatic<BaseTemplate> baseTemplateMockedStatic;
+
+    @BeforeEach
+    public void setUp() {
+        baseTemplateMockedStatic = mockStatic(BaseTemplate.class);
+        baseTemplateMockedStatic
+                .when(() -> BaseTemplate.writeTemplate(anyString(), any(), 
anyString()))
+                .thenAnswer(invocation -> null);
+        baseTemplateMockedStatic
+                .when(() -> BaseTemplate.writeTemplateAsString(any(), 
anyString()))
+                .thenAnswer(invocation -> null);
+        baseTemplateMockedStatic
+                .when(() -> BaseTemplate.writeCustomTemplate(anyString(), 
any(), anyString()))
+                .thenAnswer(invocation -> null);
+    }
+
+    @AfterEach
+    public void tearDown() {
+        baseTemplateMockedStatic.close();
+    }
+
+    @Test
+    public void testMap2TemplateWithoutParamMap() {
+        ConfigType configType = ConfigType.UNKNOWN;
+        String fileName = "fileName";
+        Map<String, Object> configMap = new HashMap<>();
+
+        TemplateUtils.map2Template(configType, fileName, configMap, null);
+        baseTemplateMockedStatic.verify(() -> 
BaseTemplate.writeTemplate(eq(fileName), any(), anyString()), times(1));
+    }
+
+    @Test
+    public void testMap2TemplateWithParamMap() {
+        ConfigType configType = ConfigType.UNKNOWN;
+        String fileName = "fileName";
+        Map<String, Object> configMap = new HashMap<>();
+        Map<String, Object> paramMap = new HashMap<>();
+
+        TemplateUtils.map2Template(configType, fileName, configMap, paramMap);
+        baseTemplateMockedStatic.verify(() -> 
BaseTemplate.writeTemplateAsString(any(), anyString()), times(1));
+        baseTemplateMockedStatic.verify(() -> 
BaseTemplate.writeCustomTemplate(eq(fileName), any(), any()), times(1));
+    }
+
+    @Test
+    public void testMap2CustomTemplateWithoutParamMap() {
+        String template = "template";
+        String fileName = "fileName";
+        Map<String, Object> configMap = new HashMap<>();
+
+        TemplateUtils.map2CustomTemplate(template, fileName, configMap, null);
+        baseTemplateMockedStatic.verify(
+                () -> BaseTemplate.writeCustomTemplate(eq(fileName), 
eq(configMap), any()), times(1));
+    }
+
+    @Test
+    public void testMap2CustomTemplateWithParamMap() {
+        String template = "template";
+        String fileName = "fileName";
+        Map<String, Object> configMap = new HashMap<>();
+        Map<String, Object> paramMap = new HashMap<>();
+
+        TemplateUtils.map2CustomTemplate(template, fileName, configMap, 
paramMap);
+        baseTemplateMockedStatic.verify(
+                () -> BaseTemplate.writeCustomTemplateAsString(eq(configMap), 
eq(template)), times(1));
+        baseTemplateMockedStatic.verify(
+                () -> BaseTemplate.writeCustomTemplate(eq(fileName), 
eq(paramMap), any()), times(1));
+    }
+}

Reply via email to