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

apkhmv pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new eab1c58007 IGNITE-16520 Refactor IgniteCliInterfaceTest (#3762)
eab1c58007 is described below

commit eab1c580077ed5655928a954a93e7d7cdc6c5489
Author: Vadim Pakhnushev <8614891+valep...@users.noreply.github.com>
AuthorDate: Wed May 15 12:45:19 2024 +0300

    IGNITE-16520 Refactor IgniteCliInterfaceTest (#3762)
---
 .../ignite/internal/cli/CliIntegrationTest.java    |   9 +-
 .../cli/commands/ItClusterCommandTest.java         | 220 ---------
 .../internal/cli/commands/ItNodeNameTest.java      |   1 -
 .../commands/cluster/init/ItClusterInitTest.java   |  15 +-
 .../configuration/ItConfigCommandTest.java         |   4 -
 .../cli/commands/connect/ItConnectCommandTest.java |   1 -
 ...tConnectWithBasicAuthenticationCommandTest.java |   6 -
 .../commands/questions/ItConnectToClusterTest.java |   2 -
 .../cli/commands/sql/ItSqlConnectSslTest.java      |   3 +-
 .../cli/commands/sql/ItSqlReplCommandTest.java     |   6 -
 .../cli/commands/unit/ItDeploymentUnitTest.java    |  13 -
 .../apache/ignite/internal/cli/ssl/ItSslTest.java  |   2 -
 .../internal/cli/IgniteCliInterfaceTest.java       | 527 ---------------------
 .../internal/cli/commands/CliCommandTestBase.java  |  80 ++--
 .../cli/commands/IgniteCliInterfaceTestBase.java   |  50 ++
 .../cliconfig/CliConfigGetCommandTest.java         |   6 +-
 .../cliconfig/CliConfigProfileListCommandTest.java |  22 +-
 .../cliconfig/CliConfigShowCommandTest.java        |  10 +-
 .../cli/commands/cluster/ClusterInitTest.java      | 199 ++++++++
 .../commands/cluster/config/ClusterConfigTest.java |  84 ++++
 .../cli/commands/node/config/NodeConfigTest.java   |  86 ++++
 .../cli/commands/node/metric/NodeMetricTest.java   |  93 ++++
 .../ignite/internal/cli/AbstractCliTest.java       |  74 ---
 23 files changed, 590 insertions(+), 923 deletions(-)

diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
index 62a9ce76ae..0f657fccc9 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
@@ -45,6 +45,7 @@ import 
org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.apache.ignite.internal.cli.event.EventPublisher;
 import org.apache.ignite.internal.cli.event.Events;
 import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import picocli.CommandLine;
 
@@ -90,6 +91,11 @@ public abstract class CliIntegrationTest extends 
ClusterPerClassIntegrationTest
     @Inject
     private EventListeningActivationPoint eventListeningActivationPoint;
 
+    @BeforeAll
+    static void setDumbTerminal() {
+        System.setProperty("org.jline.terminal.dumb", "true");
+    }
+
     @BeforeEach
     void setUp() {
         
configManagerProvider.setConfigFile(TestConfigManagerHelper.createIntegrationTestsConfig());
@@ -105,7 +111,7 @@ public abstract class CliIntegrationTest extends 
ClusterPerClassIntegrationTest
         eventPublisher.publish(Events.disconnect());
     }
 
-    protected void resetOutput() {
+    private void resetOutput() {
         sout = new StringWriter();
         serr = new StringWriter();
         cmd.setOut(new PrintWriter(sout));
@@ -117,6 +123,7 @@ public abstract class CliIntegrationTest extends 
ClusterPerClassIntegrationTest
     }
 
     protected void execute(String... args) {
+        resetOutput();
         exitCode = cmd.execute(args);
     }
 
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItClusterCommandTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItClusterCommandTest.java
deleted file mode 100644
index fbdc32f4dd..0000000000
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItClusterCommandTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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
- *
- *      http://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.ignite.internal.cli.commands;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static java.util.stream.Collectors.collectingAndThen;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
-import static org.awaitility.Awaitility.await;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import org.apache.ignite.IgnitionManager;
-import org.apache.ignite.internal.cli.AbstractCliTest;
-import org.apache.ignite.internal.testframework.TestIgnitionManager;
-import org.apache.ignite.internal.testframework.WorkDirectory;
-import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
-import org.apache.ignite.internal.testframework.log4j2.LogInspector;
-import org.hamcrest.Matcher;
-import org.hamcrest.Matchers;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-/**
- * Integration test for {@code ignite cluster} commands.
- */
-@ExtendWith(WorkDirectoryExtension.class)
-class ItClusterCommandTest extends AbstractCliTest {
-    private static final String TOPOLOGY_SNAPSHOT_LOG_RECORD_PREFIX = 
"Topology snapshot [nodes=";
-
-    private static final Node FIRST_NODE = new Node(0, 10100, 10300);
-
-    private static final Node SECOND_NODE = new Node(1, 11100, 11300);
-
-    private static final Node THIRD_NODE = new Node(2, 12100, 12300);
-
-    private static final Node FOURTH_NODE = new Node(3, 13100, 13300);
-
-    private static final List<Node> NODES = List.of(FIRST_NODE, SECOND_NODE, 
THIRD_NODE, FOURTH_NODE);
-
-    private static final String NL = System.lineSeparator();
-
-    @BeforeEach
-    void setup(@WorkDirectory Path workDir, TestInfo testInfo) throws 
Exception {
-        CountDownLatch allNodesAreInPhysicalTopology = new CountDownLatch(1);
-
-        LogInspector topologyLogInspector = new LogInspector(
-                
"org.apache.ignite.internal.network.scalecube.ScaleCubeTopologyService",
-                evt -> {
-                    String msg = evt.getMessage().getFormattedMessage();
-                    if (msg.startsWith(TOPOLOGY_SNAPSHOT_LOG_RECORD_PREFIX)) {
-                        var ids = 
msg.substring(TOPOLOGY_SNAPSHOT_LOG_RECORD_PREFIX.length(), 
msg.lastIndexOf(']'))
-                                .split(",");
-
-                        return ids.length == NODES.size();
-                    }
-                    return false;
-                },
-                allNodesAreInPhysicalTopology::countDown);
-
-        topologyLogInspector.start();
-
-        try {
-            startClusterWithoutInit(workDir, testInfo);
-
-            
waitTillAllNodesJoinPhysicalTopology(allNodesAreInPhysicalTopology);
-        } finally {
-            topologyLogInspector.stop();
-        }
-    }
-
-    private void startClusterWithoutInit(Path workDir, TestInfo testInfo) {
-        NODES.parallelStream().forEach(node -> startNodeWithoutInit(node, 
workDir, testInfo));
-    }
-
-    private void waitTillAllNodesJoinPhysicalTopology(CountDownLatch 
allNodesAreInPhysicalTopology) throws InterruptedException {
-        assertTrue(allNodesAreInPhysicalTopology.await(10, SECONDS), "Physical 
topology was not formed in time");
-    }
-
-    /**
-     * Initiates node start and waits till it makes its REST endpoints 
available, but does NOT invoke init.
-     *
-     * @param node      node
-     * @param workDir   working directory
-     * @param testInfo  test info
-     */
-    private void startNodeWithoutInit(Node node, Path workDir, TestInfo 
testInfo) {
-        String nodeName = testNodeName(testInfo, node.nodeIndex);
-
-        String config;
-        try {
-            config = configJsonFor(node);
-        } catch (IOException e) {
-            throw new RuntimeException("Cannot load config", e);
-        }
-
-        TestIgnitionManager.start(nodeName, config, workDir.resolve(nodeName));
-    }
-
-    private String configJsonFor(Node node) throws IOException {
-        String config = 
Files.readString(Path.of("src/integrationTest/resources/hardcoded-ports-config.json"));
-        config = config.replaceAll("<NETWORK_PORT>", 
String.valueOf(node.networkPort));
-        config = config.replaceAll("<REST_PORT>", 
String.valueOf(node.restPort));
-        config = config.replaceAll("<CLIENT_PORT>", 
String.valueOf(node.restPort + 7000));
-        config = config.replaceAll("<NET_CLUSTER_NODES>", netClusterNodes());
-
-        return config;
-    }
-
-    private String netClusterNodes() {
-        return NODES.stream()
-                .map(Node::networkHostPort)
-                .map(s -> "\"" + s + "\"")
-                .collect(joining(", ", "[", "]"));
-    }
-
-    @AfterEach
-    void tearDown(TestInfo testInfo) {
-        for (int i = 0; i < NODES.size(); i++) {
-            IgnitionManager.stop(testNodeName(testInfo, i));
-        }
-    }
-
-    /**
-     * Starts a cluster of 4 nodes and executes init command on it. First node 
is used to issue the command via REST endpoint,
-     * second will host the Meta Storage, third will host the Cluster 
Management Group (CMG), fourth
-     * will be just a node.
-     *
-     * @param testInfo test info (used to derive node names)
-     */
-    @Test
-    void initClusterWithNodesOfDifferentRoles(TestInfo testInfo) throws 
InterruptedException {
-        int exitCode = execute(
-                "cluster", "init",
-                "--cluster-endpoint-url", FIRST_NODE.restHostPort(),
-                "--meta-storage-node", SECOND_NODE.nodeName(testInfo),
-                "--cmg-node", THIRD_NODE.nodeName(testInfo),
-                "--cluster-name", "ignite-cluster"
-        );
-
-        assertThat(
-                String.format("Wrong exit code; std is '%s', stderr is '%s'", 
out.toString(UTF_8), err.toString(UTF_8)),
-                exitCode, is(0)
-        );
-
-        assertThat(out.toString(UTF_8), is("Cluster was initialized 
successfully" + NL));
-
-        Matcher<String> nodeNameMatcher = NODES.stream()
-                .map(node -> node.nodeName(testInfo))
-                .map(Matchers::containsString)
-                .collect(collectingAndThen(toList(), (List<Matcher<? super 
String>> matchers) -> allOf(matchers)));
-
-        await().untilAsserted(() -> {
-            out.reset();
-            err.reset();
-
-            int code = execute(
-                    "cluster", "topology", "logical",
-                    "--cluster-endpoint-url", FIRST_NODE.restHostPort()
-            );
-
-            assertThat(
-                    String.format("Wrong exit code; std is '%s', stderr is 
'%s'", out.toString(UTF_8), err.toString(UTF_8)),
-                    code, is(0)
-            );
-            assertThat(out.toString(UTF_8), nodeNameMatcher);
-        });
-    }
-
-    private static class Node {
-        private final int nodeIndex;
-        private final int networkPort;
-        private final int restPort;
-
-        private Node(int nodeIndex, int networkPort, int restPort) {
-            this.nodeIndex = nodeIndex;
-            this.networkPort = networkPort;
-            this.restPort = restPort;
-        }
-
-        String nodeName(TestInfo testInfo) {
-            return testNodeName(testInfo, nodeIndex);
-        }
-
-        String networkHostPort() {
-            return "localhost:" + networkPort;
-        }
-
-        String restHostPort() {
-            return "http://localhost:"; + restPort;
-        }
-    }
-}
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItNodeNameTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItNodeNameTest.java
index c4c219ac67..7838d3074f 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItNodeNameTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItNodeNameTest.java
@@ -40,7 +40,6 @@ public class ItNodeNameTest extends CliIntegrationTest {
     @BeforeEach
     void connect() {
         execute("connect");
-        resetOutput();
         // wait to pulling node names
         await().until(() -> !nodeNameRegistry.names().isEmpty());
     }
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/cluster/init/ItClusterInitTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/cluster/init/ItClusterInitTest.java
index 6eee56dcfe..938ae3f7c6 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/cluster/init/ItClusterInitTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/cluster/init/ItClusterInitTest.java
@@ -47,18 +47,18 @@ public class ItClusterInitTest extends 
CliCommandTestNotInitializedIntegrationBa
         // when
         connect(NODE_URL);
 
-        resetOutput();
-
         File clusterConfigurationFile = 
TestConfigManagerHelper.readClusterConfigurationWithEnabledAuthFile();
 
         execute(
                 "cluster", "init",
-                "--meta-storage-node", testNodeName(TEST_INFO, 0),
+                "--meta-storage-node", testNodeName(TEST_INFO, 1),
+                "--cmg-node", testNodeName(TEST_INFO, 2),
                 "--cluster-name", "cluster",
                 "--cluster-config-file", 
clusterConfigurationFile.getAbsolutePath()
         );
 
         assertAll(
+                this::assertExitCodeIsZero,
                 this::assertErrOutputIsEmpty,
                 () -> assertOutputContains("Cluster was initialized 
successfully")
         );
@@ -75,6 +75,12 @@ public class ItClusterInitTest extends 
CliCommandTestNotInitializedIntegrationBa
 
         // REST is available
         assertRestIsAvailable();
+
+        execute("cluster", "topology", "logical");
+        assertExitCodeIsZero();
+        for (int i = 0; i < initialNodes(); i++) {
+            assertOutputContains(testNodeName(TEST_INFO, i));
+        }
     }
 
     private void awaitClusterInitialized() throws InterruptedException {
@@ -82,7 +88,6 @@ public class ItClusterInitTest extends 
CliCommandTestNotInitializedIntegrationBa
     }
 
     private void assertRestIsUnavailable() {
-        resetOutput();
         execute("cluster", "config", "show");
 
         assertAll(
@@ -92,7 +97,6 @@ public class ItClusterInitTest extends 
CliCommandTestNotInitializedIntegrationBa
     }
 
     private void assertRestIsAvailable() {
-        resetOutput();
         execute("cluster", "config", "show");
 
         assertAll(
@@ -100,5 +104,4 @@ public class ItClusterInitTest extends 
CliCommandTestNotInitializedIntegrationBa
                 this::assertOutputIsNotEmpty
         );
     }
-
 }
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/configuration/ItConfigCommandTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/configuration/ItConfigCommandTest.java
index 24a33ac214..ed82c0760e 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/configuration/ItConfigCommandTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/configuration/ItConfigCommandTest.java
@@ -188,8 +188,6 @@ class ItConfigCommandTest extends CliIntegrationTest {
                 this::assertOutputIsEmpty
         );
 
-        resetOutput();
-
         execute("cluster", "config", "update", "--cluster-endpoint-url", 
NODE_URL,
                 
"\"security.authentication.providers.default={type=basic,users=[{username: 
--verbose, password=--verbose}]}\"");
 
@@ -210,8 +208,6 @@ class ItConfigCommandTest extends CliIntegrationTest {
                 this::assertOutputIsEmpty
         );
 
-        resetOutput();
-
         execute("node", "config", "update", "--node-url", NODE_URL, 
"network.shutdownQuietPeriod=asd");
 
         assertAll(
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectCommandTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectCommandTest.java
index df4120cb1b..caacb4d43a 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectCommandTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectCommandTest.java
@@ -106,7 +106,6 @@ class ItConnectCommandTest extends 
ItConnectToClusterTestBase {
         assertThat(getPrompt()).isEqualTo("[" + nodeName() + "]> ");
 
         // When connect again
-        resetOutput();
         execute("connect");
 
         // Then
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectWithBasicAuthenticationCommandTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectWithBasicAuthenticationCommandTest.java
index 0a3e23430a..8254daa849 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectWithBasicAuthenticationCommandTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/connect/ItConnectWithBasicAuthenticationCommandTest.java
@@ -310,8 +310,6 @@ class ItConnectWithBasicAuthenticationCommandTest extends 
ItConnectToClusterTest
         // And prompt shows username and node name
         assertThat(getPrompt()).isEqualTo("[admin:" + nodeName() + "]> ");
 
-        resetOutput();
-
         // Should ask user to reconnect with different user, answer "y"
         bindAnswers("y");
 
@@ -348,8 +346,6 @@ class ItConnectWithBasicAuthenticationCommandTest extends 
ItConnectToClusterTest
         // And prompt shows username and node name
         assertThat(getPrompt()).isEqualTo("[admin:" + nodeName() + "]> ");
 
-        resetOutput();
-
         // Should ask user to reconnect with different user, answer "y"
         bindAnswers("y");
 
@@ -386,8 +382,6 @@ class ItConnectWithBasicAuthenticationCommandTest extends 
ItConnectToClusterTest
         // And prompt shows username from parameters and node name
         assertThat(getPrompt()).isEqualTo("[admin1:" + nodeName() + "]> ");
 
-        resetOutput();
-
         // Should ask user to reconnect with different user, answer "y"
         bindAnswers("y");
 
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java
index 525595462a..fb28a2ee1d 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java
@@ -105,11 +105,9 @@ class ItConnectToClusterTest extends 
ItConnectToClusterTestBase {
         bindAnswers("y");
 
         // And disconnect
-        resetOutput();
         execute("disconnect");
 
         // When connect to different URL
-        resetOutput();
         execute("connect", "http://localhost:10301";);
 
         // Then
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlConnectSslTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlConnectSslTest.java
index d8e006a7e8..8485683081 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlConnectSslTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlConnectSslTest.java
@@ -62,12 +62,13 @@ class ItSqlConnectSslTest extends 
CliSqlConnectCommandTestBase {
         // Given connected state
         execute("connect");
 
+        assertOutputIs("Connected to " + NODE_URL + System.lineSeparator());
+
         // When
         execute("sql", "select * from person");
 
         // Then the query is failed
         assertAll(
-                () -> assertOutputIs("Connected to " + NODE_URL + 
System.lineSeparator()),
                 () -> assertErrOutputContains("Connection failed"),
                 () -> assertErrOutputContains("Handshake error")
         );
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
index 780db3d804..8901e999a1 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
@@ -54,8 +54,6 @@ class ItSqlReplCommandTest extends CliIntegrationTest {
                 this::assertErrOutputIsEmpty
         );
 
-        resetOutput();
-
         execute("--jdbc-url", JDBC_URL);
 
         assertAll(
@@ -74,8 +72,6 @@ class ItSqlReplCommandTest extends CliIntegrationTest {
                 this::assertErrOutputIsEmpty
         );
 
-        resetOutput();
-
         execute("SELECT COUNT(*) FROM MULTILINE_TABLE;", "--jdbc-url", 
JDBC_URL);
 
         assertAll(
@@ -93,8 +89,6 @@ class ItSqlReplCommandTest extends CliIntegrationTest {
                 () -> assertErrOutputContains("nonexisting] not found")
         );
 
-        resetOutput();
-
         execute("--jdbc-url", JDBC_URL);
 
         assertAll(
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/unit/ItDeploymentUnitTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/unit/ItDeploymentUnitTest.java
index f7aa377dfb..967a14484b 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/unit/ItDeploymentUnitTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/unit/ItDeploymentUnitTest.java
@@ -132,7 +132,6 @@ public class ItDeploymentUnitTest extends 
CliIntegrationTest {
         );
 
         await().untilAsserted(() -> {
-            resetOutput();
             execute("cluster", "unit", "list", "--plain", id);
 
             assertDeployed(id);
@@ -169,25 +168,21 @@ public class ItDeploymentUnitTest extends 
CliIntegrationTest {
         );
 
         await().untilAsserted(() -> {
-            resetOutput();
             execute("cluster", "unit", "list", "--plain", id);
 
             // Unit is deployed on all requested nodes
             assertDeployed(id);
 
-            resetOutput();
             execute("node", "unit", "list", "--plain", "--node-url", 
"http://localhost:10300";, id);
 
             // Unit is deployed on the CMG node
             assertDeployed(id);
 
-            resetOutput();
             execute("node", "unit", "list", "--plain", "--node-url", 
"http://localhost:10301";, id);
 
             // Unit is deployed on the requested node
             assertDeployed(id);
 
-            resetOutput();
             execute("node", "unit", "list", "--plain", "--node-url", 
"http://localhost:10302";, id);
 
             // Unit is not deployed on the other node
@@ -214,15 +209,12 @@ public class ItDeploymentUnitTest extends 
CliIntegrationTest {
         );
 
         await().untilAsserted(() -> {
-            resetOutput();
             execute("cluster", "unit", "list", "--plain", id);
 
             // Unit is deployed on all requested nodes
             assertDeployed(id);
 
             CLUSTER.runningNodes().forEach(ignite -> {
-                resetOutput();
-
                 String nodeUrl = "http://"; + 
ignite.restHttpAddress().toString();
                 execute("node", "unit", "list", "--plain", "--node-url", 
nodeUrl, id);
 
@@ -246,7 +238,6 @@ public class ItDeploymentUnitTest extends 
CliIntegrationTest {
         );
 
         // When deploy second unit with version
-        resetOutput();
         execute("cluster", "unit", "deploy", "test-unit2", "--version", "2.1", 
"--path", testFile2);
 
         // Then
@@ -257,13 +248,11 @@ public class ItDeploymentUnitTest extends 
CliIntegrationTest {
         );
 
         await().untilAsserted(() -> {
-            resetOutput();
             execute("cluster", "unit", "list", "--plain", "test-unit");
 
             assertDeployed("test-unit");
         });
 
-        resetOutput();
         execute("node", "unit", "list", "--plain", "test-unit");
 
         assertDeployed("test-unit");
@@ -275,7 +264,6 @@ public class ItDeploymentUnitTest extends 
CliIntegrationTest {
         execute("cluster", "unit", "deploy", "test-unit", "--version", 
"1.0.0", "--path", testFile);
 
         await().untilAsserted(() -> {
-            resetOutput();
             execute("cluster", "unit", "list", "--plain", "test-unit");
 
             assertDeployed("test-unit");
@@ -284,7 +272,6 @@ public class ItDeploymentUnitTest extends 
CliIntegrationTest {
         execute("cluster", "unit", "deploy", "test-unit", "--version", 
"2.0.0", "--path", testFile);
 
         await().untilAsserted(() -> {
-            resetOutput();
             execute("cluster", "unit", "list", "--plain", "test-unit");
 
             assertDeployed(List.of(new UnitIdVersion("test-unit", "1.0.0"), 
new UnitIdVersion("test-unit", "*2.0.0")));
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/ssl/ItSslTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/ssl/ItSslTest.java
index 457c242944..d900ad4d3f 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/ssl/ItSslTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/ssl/ItSslTest.java
@@ -67,7 +67,6 @@ public class ItSslTest extends 
CliSslNotInitializedIntegrationTestBase {
         setConfigProperty(CliConfigKeys.REST_TRUST_STORE_PASSWORD, 
NodeConfig.trustStorePassword);
         setConfigProperty(CliConfigKeys.REST_KEY_STORE_PATH, 
NodeConfig.resolvedKeystorePath);
         setConfigProperty(CliConfigKeys.REST_KEY_STORE_PASSWORD, 
"wrong-password");
-        resetOutput();
 
         // And connect via HTTPS
         connect("https://localhost:10401";);
@@ -125,7 +124,6 @@ public class ItSslTest extends 
CliSslNotInitializedIntegrationTestBase {
         execute("cli", "config", "set", "ignite.rest.key-store.password=" + 
NodeConfig.keyStorePassword);
         execute("cli", "config", "set", "ignite.rest.trust-store.path=" + 
NodeConfig.resolvedTruststorePath + "-wrong-path");
         execute("cli", "config", "set", "ignite.rest.trust-store.password=" + 
NodeConfig.keyStorePassword);
-        resetOutput();
 
         // And connect via HTTPS
         connect("https://localhost:10401";);
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/IgniteCliInterfaceTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/IgniteCliInterfaceTest.java
deleted file mode 100644
index 7ce754c99b..0000000000
--- 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/IgniteCliInterfaceTest.java
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * 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
- *
- *      http://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.ignite.internal.cli;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.stream.Collectors.toList;
-import static 
org.apache.ignite.internal.cli.commands.cliconfig.TestConfigManagerHelper.copyResourceToTempFile;
-import static org.apache.ignite.internal.cli.core.style.AnsiStringSupport.fg;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.startsWith;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockserver.matchers.MatchType.ONLY_MATCHING_FIELDS;
-import static org.mockserver.model.HttpRequest.request;
-import static org.mockserver.model.HttpResponse.response;
-import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500;
-import static org.mockserver.model.HttpStatusCode.OK_200;
-import static org.mockserver.model.JsonBody.json;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.apache.ignite.internal.cli.core.style.AnsiStringSupport.Color;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.mockserver.integration.ClientAndServer;
-import org.mockserver.junit.jupiter.MockServerExtension;
-import org.mockserver.model.MediaType;
-
-/**
- * Smoke test for Ignite CLI features and its UI. Structure of tests should be 
self-documented and repeat the structure of Ignite CLI
- * subcommands.
- */
-@DisplayName("ignite")
-@ExtendWith(MockitoExtension.class)
-@ExtendWith(MockServerExtension.class)
-public class IgniteCliInterfaceTest extends AbstractCliTest {
-    private final ClientAndServer clientAndServer;
-
-    private final String mockUrl;
-
-    public IgniteCliInterfaceTest(ClientAndServer clientAndServer) {
-        this.clientAndServer = clientAndServer;
-        mockUrl = "http://localhost:"; + clientAndServer.getPort();
-    }
-
-    /**
-     * Sets up environment before test execution.
-     */
-    @BeforeEach
-    void setup() {
-        resetStreams();
-
-        clientAndServer.reset();
-    }
-
-    private int execute(String cmdLine) {
-        return execute(cmdLine.split(" "));
-    }
-
-    /**
-     * Tests "node" command.
-     */
-    @Nested
-    @DisplayName("node")
-    class Node {
-
-        /**
-         * Tests "config" command.
-         */
-        @Nested
-        @DisplayName("config")
-        class Config {
-            @Test
-            @DisplayName("show --node-url http://localhost:10300";)
-            void show() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("GET")
-                                .withPath("/management/v1/configuration/node")
-                        )
-                        
.respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
-
-                int exitCode = execute("node config show --node-url " + 
mockUrl);
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("{\n"
-                                + "  \"autoAdjust\" : {\n"
-                                + "    \"enabled\" : true\n"
-                                + "  }\n"
-                                + "}\n"
-                );
-                assertThatStderrIsEmpty();
-            }
-
-            @Test
-            @DisplayName("show --node-url http://localhost:10300 
local.baseline")
-            void showSubtree() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("GET")
-                                
.withPath("/management/v1/configuration/node/local.baseline")
-                        )
-                        
.respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
-
-                int exitCode = execute("node config show --node-url " + 
mockUrl + " local.baseline");
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("{\n"
-                                + "  \"autoAdjust\" : {\n"
-                                + "    \"enabled\" : true\n"
-                                + "  }\n"
-                                + "}\n"
-                );
-                assertThatStderrIsEmpty();
-            }
-
-            @Test
-            @DisplayName("update --node-url http://localhost:10300 
local.baseline.autoAdjust.enabled=true")
-            void updateHocon() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("PATCH")
-                                .withPath("/management/v1/configuration/node")
-                                
.withBody("local.baseline.autoAdjust.enabled=true")
-                        )
-                        .respond(response(null));
-
-                int exitCode = execute("node config update --node-url " + 
mockUrl + " local.baseline.autoAdjust.enabled=true");
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("Node configuration updated. "
-                        + fg(Color.YELLOW).mark("Restart the node to apply 
changes."));
-                assertThatStderrIsEmpty();
-            }
-        }
-
-        @Nested
-        @DisplayName("metric")
-        class Metric {
-            @Test
-            @DisplayName("metric source enable srcName")
-            void enable() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("POST")
-                                .withPath("/management/v1/metric/node/enable")
-                                .withBody("srcName")
-                        )
-                        .respond(response(null));
-
-                int exitCode = execute("node metric source enable --node-url " 
+ mockUrl + " srcName");
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("Metric source was enabled successfully");
-                assertThatStderrIsEmpty();
-            }
-
-            @Test
-            @DisplayName("metric source disable srcName")
-            void disable() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("POST")
-                                .withPath("/management/v1/metric/node/disable")
-                                .withBody("srcName")
-                        )
-                        .respond(response(null));
-
-                int exitCode = execute("node metric source disable --node-url 
" + mockUrl + " srcName");
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("Metric source was disabled successfully");
-                assertThatStderrIsEmpty();
-            }
-
-            @Test
-            @DisplayName("metric source list")
-            void listSources() {
-                String responseBody = 
"[{\"name\":\"enabledMetric\",\"enabled\":true},{\"name\":\"disabledMetric\",\"enabled\":false}]";
-                clientAndServer
-                        .when(request()
-                                .withMethod("GET")
-                                .withPath("/management/v1/metric/node/source")
-                        )
-                        .respond(response(responseBody));
-
-                int exitCode = execute("node metric source list --plain 
--node-url " + mockUrl);
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("Set 
name\tEnabled\nenabledMetric\tenabled\ndisabledMetric\tdisabled\n");
-                assertThatStderrIsEmpty();
-            }
-
-            @Test
-            @DisplayName("metric list")
-            void listSets() {
-                String responseBody = 
"[{\"name\":\"metricSet\",\"metrics\":[{\"name\":\"metric\",\"desc\":\"description\"}]}]";
-                clientAndServer
-                        .when(request()
-                                .withMethod("GET")
-                                .withPath("/management/v1/metric/node/set")
-                        )
-                        .respond(response(responseBody));
-
-                int exitCode = execute("node metric list --plain --node-url " 
+ mockUrl);
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("Set name\tMetric 
name\tDescription\nmetricSet\t\t\n\tmetric\tdescription");
-                assertThatStderrIsEmpty();
-            }
-        }
-    }
-
-    /**
-     * Tests "cluster" command.
-     */
-    @Nested
-    @DisplayName("cluster")
-    class Cluster {
-        @Test
-        @DisplayName("init --cluster-endpoint-url http://localhost:10300 
--meta-storage-node node1ConsistentId --meta-storage-node node2ConsistentId "
-                + "--cmg-node node2ConsistentId --cmg-node node3ConsistentId 
--cluster-name cluster")
-        void initSuccess() {
-            var expectedSentContent = 
"{\"metaStorageNodes\":[\"node1ConsistentId\",\"node2ConsistentId\"],"
-                    + 
"\"cmgNodes\":[\"node2ConsistentId\",\"node3ConsistentId\"],"
-                    + "\"clusterName\":\"cluster\"}";
-
-            clientAndServer
-                    .when(request()
-                            .withMethod("POST")
-                            .withPath("/management/v1/cluster/init")
-                            .withBody(json(expectedSentContent, 
ONLY_MATCHING_FIELDS))
-                            .withContentType(MediaType.APPLICATION_JSON_UTF_8)
-                    )
-                    .respond(response(null));
-
-
-            int exitCode = execute(
-                    "cluster", "init",
-                    "--cluster-endpoint-url", mockUrl,
-                    "--meta-storage-node", "node1ConsistentId",
-                    "--meta-storage-node", "node2ConsistentId",
-                    "--cmg-node", "node2ConsistentId",
-                    "--cmg-node", "node3ConsistentId",
-                    "--cluster-name", "cluster"
-            );
-
-            assertThatExitCodeMeansSuccess(exitCode);
-
-            assertOutputEqual("Cluster was initialized successfully");
-            assertThatStderrIsEmpty();
-        }
-
-        @Test
-        @DisplayName(
-                "init --cluster-endpoint-url http://localhost:10300 
--meta-storage-node node1ConsistentId --meta-storage-node node2ConsistentId "
-                        + "--cmg-node node2ConsistentId --cmg-node 
node3ConsistentId --cluster-name cluster "
-                        + "--auth-enabled --basic-auth-username admin 
--basic-auth-password password")
-        void initWithAuthenticationSuccess() throws IOException {
-
-            Path clusterConfigurationFile = 
copyResourceToTempFile("cluster-configuration-with-enabled-auth.conf").toPath();
-            String clusterConfiguration = 
Files.readString(clusterConfigurationFile);
-
-            var expectedSentContent = "{\n"
-                    + "  \"metaStorageNodes\": [\n"
-                    + "    \"node1ConsistentId\",\n"
-                    + "    \"node2ConsistentId\"\n"
-                    + "  ],\n"
-                    + "  \"cmgNodes\": [\n"
-                    + "    \"node2ConsistentId\",\n"
-                    + "    \"node3ConsistentId\"\n"
-                    + "  ],\n"
-                    + "  \"clusterName\": \"cluster\",\n"
-                    + "  \"clusterConfiguration\": \"" + clusterConfiguration 
+ "\"\n"
-                    + "}";
-
-            clientAndServer
-                    .when(request()
-                            .withMethod("POST")
-                            .withPath("/management/v1/cluster/init")
-                            .withBody(json(expectedSentContent, 
ONLY_MATCHING_FIELDS))
-                            .withContentType(MediaType.APPLICATION_JSON_UTF_8)
-                    )
-                    .respond(response(null));
-
-            int exitCode = execute(
-                    "cluster", "init",
-                    "--cluster-endpoint-url", mockUrl,
-                    "--meta-storage-node", "node1ConsistentId",
-                    "--meta-storage-node", "node2ConsistentId",
-                    "--cmg-node", "node2ConsistentId",
-                    "--cmg-node", "node3ConsistentId",
-                    "--cluster-name", "cluster",
-                    "--cluster-config-file", 
clusterConfigurationFile.toString()
-            );
-
-            assertThatExitCodeMeansSuccess(exitCode);
-
-            assertOutputEqual("Cluster was initialized successfully");
-            assertThatStderrIsEmpty();
-        }
-
-        @Test
-        void initError() {
-            clientAndServer
-                    .when(request()
-                            .withMethod("POST")
-                            .withPath("/management/v1/cluster/init")
-                    )
-                    .respond(response()
-                            .withStatusCode(INTERNAL_SERVER_ERROR_500.code())
-                            .withBody("{\"status\":500, \"detail\":\"Oops\"}")
-                    );
-
-            int exitCode = execute(
-                    "cluster", "init",
-                    "--cluster-endpoint-url", mockUrl,
-                    "--meta-storage-node", "node1ConsistentId",
-                    "--meta-storage-node", "node2ConsistentId",
-                    "--cmg-node", "node2ConsistentId",
-                    "--cmg-node", "node3ConsistentId",
-                    "--cluster-name", "cluster"
-            );
-
-            assertThatExitCodeIs(1, exitCode);
-
-            assertThatStdoutIsEmpty();
-            assertErrOutputEqual("Oops");
-        }
-
-        @Test
-        @DisplayName("init --cluster-endpoint-url http://localhost:10300 
--cmg-node node2ConsistentId --cmg-node node3ConsistentId")
-        void metastorageNodesAreMandatoryForInit() {
-            int exitCode = execute(
-                    "cluster", "init",
-                    "--cluster-endpoint-url", mockUrl,
-                    "--cmg-node", "node2ConsistentId",
-                    "--cmg-node", "node3ConsistentId",
-                    "--cluster-name", "cluster"
-            );
-
-            assertThatExitCodeIs(2, exitCode);
-
-            assertThatStdoutIsEmpty();
-            assertThat(err.toString(UTF_8), startsWith("Missing required 
option: '--meta-storage-node=<metaStorageNodes>'"));
-        }
-
-        @Test
-        @DisplayName("init --cluster-endpoint-url http://localhost:10300 
--meta-storage-node node2ConsistentId --meta-storage-node node3ConsistentId")
-        void cmgNodesAreNotMandatoryForInit() {
-            clientAndServer
-                    .when(request()
-                            .withMethod("POST")
-                            .withPath("/management/v1/cluster/init")
-                    )
-                    .respond(response().withStatusCode(OK_200.code()));
-
-            int exitCode = execute(
-                    "cluster", "init",
-                    "--cluster-endpoint-url", mockUrl,
-                    "--meta-storage-node", "node1ConsistentId",
-                    "--meta-storage-node", "node2ConsistentId",
-                    "--cluster-name", "cluster"
-            );
-
-            assertThatExitCodeMeansSuccess(exitCode);
-
-            assertOutputEqual("Cluster was initialized successfully");
-            assertThatStderrIsEmpty();
-        }
-
-        @Test
-        @DisplayName("init --cluster-endpoint-url http://localhost:10300 
--meta-storage-node node1ConsistentId --cmg-node node2ConsistentId")
-        void clusterNameIsMandatoryForInit() {
-            int exitCode = execute(
-                    "cluster", "init",
-                    "--cluster-endpoint-url", mockUrl,
-                    "--meta-storage-node", "node1ConsistentId",
-                    "--cmg-node", "node2ConsistentId"
-            );
-
-            assertThatExitCodeIs(2, exitCode);
-
-            assertThatStdoutIsEmpty();
-            assertThat(err.toString(UTF_8), startsWith("Missing required 
option: '--cluster-name=<clusterName>'"));
-        }
-
-        @Nested
-        @DisplayName("config")
-        class Config {
-            @Test
-            @DisplayName("show --cluster-endpoint-url http://localhost:10300";)
-            void show() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("GET")
-                                
.withPath("/management/v1/configuration/cluster")
-                        )
-                        
.respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
-
-                int exitCode = execute("cluster config show 
--cluster-endpoint-url " + mockUrl);
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("{\n"
-                        + "  \"autoAdjust\" : {\n"
-                        + "    \"enabled\" : true\n"
-                        + "  }\n"
-                        + "}\n");
-                assertThatStderrIsEmpty();
-            }
-
-            @Test
-            @DisplayName("show --cluster-endpoint-url http://localhost:10300 
local.baseline")
-            void showSubtree() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("GET")
-                                
.withPath("/management/v1/configuration/cluster/local.baseline")
-                        )
-                        
.respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
-
-                int exitCode = execute("cluster config show 
--cluster-endpoint-url " + mockUrl + " local.baseline");
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("{\n"
-                        + "  \"autoAdjust\" : {\n"
-                        + "    \"enabled\" : true\n"
-                        + "  }\n"
-                        + "}\n");
-                assertThatStderrIsEmpty();
-            }
-
-            @Test
-            @DisplayName("update --cluster-endpoint-url http://localhost:10300 
local.baseline.autoAdjust.enabled=true")
-            void updateHocon() {
-                clientAndServer
-                        .when(request()
-                                .withMethod("PATCH")
-                                
.withPath("/management/v1/configuration/cluster")
-                                
.withBody("local.baseline.autoAdjust.enabled=true")
-                        )
-                        .respond(response(null));
-
-                int exitCode = execute("cluster config update 
--cluster-endpoint-url "
-                        + mockUrl + " local.baseline.autoAdjust.enabled=true");
-
-                assertThatExitCodeMeansSuccess(exitCode);
-
-                assertOutputEqual("Cluster configuration was updated 
successfully");
-                assertThatStderrIsEmpty();
-            }
-        }
-    }
-
-    private void assertThatStdoutIsEmpty() {
-        assertThat(out.toString(UTF_8), is(""));
-    }
-
-    private void assertThatStderrIsEmpty() {
-        assertThat(err.toString(UTF_8), is(""));
-    }
-
-    private void assertThatExitCodeMeansSuccess(int exitCode) {
-        assertThatExitCodeIs(0, exitCode);
-    }
-
-    private void assertThatExitCodeIs(int expectedCode, int exitCode) {
-        assertEquals(expectedCode, exitCode, outputStreams());
-    }
-
-    private String outputStreams() {
-        return "stdout:\n" + out.toString(UTF_8) + "\n" + "stderr:\n" + 
err.toString(UTF_8);
-    }
-
-    /**
-     * <em>Assert</em> that {@code expected} and {@code actual} are equals 
ignoring differences in line separators.
-     *
-     * <p>If both are {@code null}, they are considered equal.
-     *
-     * @param exp Expected result.
-     * @param actual Actual result.
-     * @see Object#equals(Object)
-     */
-    private static void assertEqualsIgnoreLineSeparators(String exp, String 
actual) {
-        assertEquals(
-                exp.lines().collect(toList()),
-                actual.lines().collect(toList())
-        );
-    }
-
-    private void assertOutputEqual(String exp) {
-        assertEqualsIgnoreLineSeparators(exp, out.toString(UTF_8));
-    }
-
-    private void assertErrOutputEqual(String exp) {
-        assertEqualsIgnoreLineSeparators(exp, err.toString(UTF_8));
-    }
-}
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java
index 19994ab7a6..4ecbb12070 100644
--- 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java
@@ -17,7 +17,15 @@
 
 package org.apache.ignite.internal.cli.commands;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static java.util.stream.Collectors.toList;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.emptyString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -30,10 +38,14 @@ import jakarta.inject.Inject;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Arrays;
+import java.util.List;
 import org.apache.ignite.internal.cli.core.call.Call;
 import org.apache.ignite.internal.cli.core.call.CallInput;
 import org.apache.ignite.internal.cli.core.call.DefaultCallOutput;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.BeforeAll;
 import org.mockito.ArgumentCaptor;
 import picocli.CommandLine;
 
@@ -51,6 +63,11 @@ public abstract class CliCommandTestBase extends 
BaseIgniteAbstractTest {
 
     private int exitCode = Integer.MIN_VALUE;
 
+    @BeforeAll
+    static void setDumbTerminal() {
+        System.setProperty("org.jline.terminal.dumb", "true");
+    }
+
     protected abstract Class<?> getCommandClass();
 
     protected void execute(String argsLine) {
@@ -70,9 +87,7 @@ public abstract class CliCommandTestBase extends 
BaseIgniteAbstractTest {
     }
 
     protected void assertExitCodeIs(int expectedExitCode) {
-        assertThat(exitCode)
-                .as("Expected exit code to be: " + expectedExitCode + " but 
was " + exitCode)
-                .isEqualTo(expectedExitCode);
+        assertThat("Unexpected exit code", exitCode, is(expectedExitCode));
     }
 
     protected void assertExitCodeIsZero() {
@@ -80,51 +95,60 @@ public abstract class CliCommandTestBase extends 
BaseIgniteAbstractTest {
     }
 
     protected void assertOutputIsNotEmpty() {
-        assertThat(sout.toString())
-                .as("Expected command output not to be empty")
-                .isNotEmpty();
+        assertThat("Unexpected command output", sout.toString(), 
is(not(emptyString())));
     }
 
     protected void assertOutputIs(String expectedOutput) {
-        assertThat(sout.toString())
-                .as("Expected command output to be: " + expectedOutput + " but 
was " + sout.toString())
-                .isEqualTo(expectedOutput);
+        assertEqualsIgnoreLineSeparators("Unexpected command output", 
sout.toString(), expectedOutput);
     }
 
     protected void assertOutputContains(String... expectedOutput) {
-        assertThat(sout.toString())
-                .as("Expected command output to contain: " + 
Arrays.toString(expectedOutput) + " but was " + sout.toString())
-                .contains(expectedOutput);
+        List<Matcher<? super String>> matchers = 
Arrays.stream(expectedOutput).map(Matchers::containsString).collect(toList());
+        assertThat("Unexpected command output", sout.toString(), 
allOf(matchers));
     }
 
     protected void assertOutputIsEmpty() {
-        assertThat(sout.toString())
-                .as("Expected command output to be empty")
-                .isEmpty();
+        assertThat("Unexpected command output", sout.toString(), 
is(emptyString()));
     }
 
     protected void assertErrOutputIsNotEmpty() {
-        assertThat(serr.toString())
-                .as("Expected command error output not to be empty")
-                .isNotEmpty();
+        assertThat("Unexpected command error output", serr.toString(), 
is(not(emptyString())));
     }
 
     protected void assertErrOutputIsEmpty() {
-        assertThat(serr.toString())
-                .as("Expected command error output to be empty")
-                .isEmpty();
+        assertThat("Unexpected command error output", serr.toString(), 
is(emptyString()));
     }
 
     protected void assertErrOutputIs(String expectedErrOutput) {
-        assertThat(serr.toString())
-                .as("Expected command error output to be equal to: " + 
expectedErrOutput)
-                .isEqualTo(expectedErrOutput);
+        assertEqualsIgnoreLineSeparators("Unexpected command error output", 
serr.toString(), expectedErrOutput);
     }
 
     protected void assertErrOutputContains(String expectedErrOutput) {
-        assertThat(serr.toString())
-                .as("Expected command error output to contain: " + 
expectedErrOutput + " but was " + serr.toString())
-                .contains(expectedErrOutput);
+        assertThat("Unexpected command error output", serr.toString(), 
containsString(expectedErrOutput));
+    }
+
+    /**
+     * Asserts that the command's exit code is zero, output is equal to the 
expected output and the error output is empty.
+     *
+     * @param expectedOutput Expected command output.
+     */
+    protected void assertSuccessfulOutputIs(String expectedOutput) {
+        assertAll(
+                this::assertExitCodeIsZero,
+                () -> assertOutputIs(expectedOutput),
+                this::assertErrOutputIsEmpty
+        );
+    }
+
+    /**
+     * Asserts that {@code expected} and {@code actual} are equals ignoring 
differences in line separators.
+     *
+     * @param reason Description of the assertion.
+     * @param exp Expected result.
+     * @param actual Actual result.
+     */
+    private static void assertEqualsIgnoreLineSeparators(String reason, String 
exp, String actual) {
+        assertThat(reason, exp.lines().collect(toList()), 
contains(actual.lines().toArray(String[]::new)));
     }
 
     protected <IT extends CallInput, OT, T extends Call<IT, OT>> T 
registerMockCall(Class<T> callClass) {
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/IgniteCliInterfaceTestBase.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/IgniteCliInterfaceTestBase.java
new file mode 100644
index 0000000000..157581b0e6
--- /dev/null
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/IgniteCliInterfaceTestBase.java
@@ -0,0 +1,50 @@
+/*
+ * 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
+ *
+ *      http://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.ignite.internal.cli.commands;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockserver.integration.ClientAndServer;
+import org.mockserver.junit.jupiter.MockServerExtension;
+
+/**
+ * Base class for testing CLI interface.
+ */
+@ExtendWith(MockServerExtension.class)
+public class IgniteCliInterfaceTestBase extends CliCommandTestBase {
+    protected static ClientAndServer clientAndServer;
+
+    protected static String mockUrl;
+
+    @Override
+    protected Class<?> getCommandClass() {
+        return TopLevelCliCommand.class;
+    }
+
+    @BeforeAll
+    static void initMockServer(ClientAndServer clientAndServer) {
+        IgniteCliInterfaceTestBase.clientAndServer = clientAndServer;
+        mockUrl = "http://localhost:"; + clientAndServer.getPort();
+    }
+
+    @BeforeEach
+    void resetMockServer() {
+        clientAndServer.reset();
+    }
+}
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigGetCommandTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigGetCommandTest.java
index d0054f2cf6..863d4e52f1 100644
--- 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigGetCommandTest.java
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigGetCommandTest.java
@@ -47,11 +47,7 @@ class CliConfigGetCommandTest extends 
CliConfigCommandTestBase {
         // When executed with single key
         execute("server");
 
-        assertAll(
-                this::assertExitCodeIsZero,
-                () -> assertOutputIs("127.0.0.1" + System.lineSeparator()),
-                this::assertErrOutputIsEmpty
-        );
+        assertSuccessfulOutputIs("127.0.0.1" + System.lineSeparator());
     }
 
     @Test
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigProfileListCommandTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigProfileListCommandTest.java
index 506e13da0e..d034cace59 100644
--- 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigProfileListCommandTest.java
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigProfileListCommandTest.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.internal.cli.commands.cliconfig;
 
-import static org.junit.jupiter.api.Assertions.assertAll;
-
 import 
org.apache.ignite.internal.cli.commands.cliconfig.profile.CliConfigProfileListCommand;
 import org.junit.jupiter.api.Test;
 
@@ -32,12 +30,8 @@ class CliConfigProfileListCommandTest extends 
CliConfigCommandTestBase {
     public void testWithDefaultProfile() {
         execute();
 
-        String expectedResult = "owner" + System.lineSeparator()
-                + "database" + System.lineSeparator();
-        assertAll(
-                () -> assertOutputIs(expectedResult),
-                this::assertErrOutputIsEmpty
-        );
+        assertSuccessfulOutputIs("owner" + System.lineSeparator()
+                + "database" + System.lineSeparator());
     }
 
     @Test
@@ -45,11 +39,7 @@ class CliConfigProfileListCommandTest extends 
CliConfigCommandTestBase {
         
configManagerProvider.setConfigFile(TestConfigManagerHelper.createOneSectionWithDefaultProfileConfig());
         execute();
 
-        String expectedResult = "default" + System.lineSeparator();
-        assertAll(
-                () -> assertOutputIs(expectedResult),
-                this::assertErrOutputIsEmpty
-        );
+        assertSuccessfulOutputIs("default" + System.lineSeparator());
     }
 
     @Test
@@ -57,10 +47,6 @@ class CliConfigProfileListCommandTest extends 
CliConfigCommandTestBase {
         
configManagerProvider.setConfigFile(TestConfigManagerHelper.createEmptyConfig());
         execute();
 
-        String expectedResult = "default" + System.lineSeparator();
-        assertAll(
-                () -> assertOutputIs(expectedResult),
-                this::assertErrOutputIsEmpty
-        );
+        assertSuccessfulOutputIs("default" + System.lineSeparator());
     }
 }
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigShowCommandTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigShowCommandTest.java
index 04f13910dd..8807e94a3c 100644
--- 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigShowCommandTest.java
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cliconfig/CliConfigShowCommandTest.java
@@ -51,14 +51,8 @@ class CliConfigShowCommandTest extends 
CliConfigCommandTestBase {
     public void testWithProfile() {
         execute("--profile owner");
 
-        String expectedResult = "[owner]" + System.lineSeparator()
+        assertSuccessfulOutputIs("[owner]" + System.lineSeparator()
                 + "name=John Smith" + System.lineSeparator()
-                + "organization=Apache Ignite" + System.lineSeparator();
-
-        assertAll(
-                this::assertExitCodeIsZero,
-                () -> assertOutputIs(expectedResult),
-                this::assertErrOutputIsEmpty
-        );
+                + "organization=Apache Ignite" + System.lineSeparator());
     }
 }
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cluster/ClusterInitTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cluster/ClusterInitTest.java
new file mode 100644
index 0000000000..32e0139532
--- /dev/null
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cluster/ClusterInitTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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
+ *
+ *      http://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.ignite.internal.cli.commands.cluster;
+
+import static 
org.apache.ignite.internal.cli.commands.cliconfig.TestConfigManagerHelper.copyResourceToTempFile;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.mockserver.matchers.MatchType.ONLY_MATCHING_FIELDS;
+import static org.mockserver.model.HttpRequest.request;
+import static org.mockserver.model.HttpResponse.response;
+import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500;
+import static org.mockserver.model.HttpStatusCode.OK_200;
+import static org.mockserver.model.JsonBody.json;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.ignite.internal.cli.commands.IgniteCliInterfaceTestBase;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockserver.model.MediaType;
+
+/** Tests "cluster init" command. */
+@DisplayName("cluster init")
+class ClusterInitTest extends IgniteCliInterfaceTestBase {
+    @Test
+    @DisplayName("--cluster-endpoint-url http://localhost:10300 
--meta-storage-node node1ConsistentId"
+            + " --meta-storage-node node2ConsistentId --cmg-node 
node2ConsistentId --cmg-node node3ConsistentId --cluster-name cluster")
+    void initSuccess() {
+        var expectedSentContent = 
"{\"metaStorageNodes\":[\"node1ConsistentId\",\"node2ConsistentId\"],"
+                + "\"cmgNodes\":[\"node2ConsistentId\",\"node3ConsistentId\"],"
+                + "\"clusterName\":\"cluster\"}";
+
+        clientAndServer
+                .when(request()
+                        .withMethod("POST")
+                        .withPath("/management/v1/cluster/init")
+                        .withBody(json(expectedSentContent, 
ONLY_MATCHING_FIELDS))
+                        .withContentType(MediaType.APPLICATION_JSON_UTF_8)
+                )
+                .respond(response(null));
+
+        execute(
+                "cluster", "init",
+                "--cluster-endpoint-url", mockUrl,
+                "--meta-storage-node", "node1ConsistentId",
+                "--meta-storage-node", "node2ConsistentId",
+                "--cmg-node", "node2ConsistentId",
+                "--cmg-node", "node3ConsistentId",
+                "--cluster-name", "cluster"
+        );
+
+        assertSuccessfulOutputIs("Cluster was initialized successfully");
+    }
+
+    @Test
+    @DisplayName("--cluster-endpoint-url http://localhost:10300 
--meta-storage-node node1ConsistentId --meta-storage-node node2ConsistentId"
+            + " --cmg-node node2ConsistentId --cmg-node node3ConsistentId 
--cluster-name cluster"
+            + " --auth-enabled --basic-auth-username admin 
--basic-auth-password password")
+    void initWithAuthenticationSuccess() throws IOException {
+
+        Path clusterConfigurationFile = 
copyResourceToTempFile("cluster-configuration-with-enabled-auth.conf").toPath();
+        String clusterConfiguration = 
Files.readString(clusterConfigurationFile);
+
+        var expectedSentContent = "{\n"
+                + "  \"metaStorageNodes\": [\n"
+                + "    \"node1ConsistentId\",\n"
+                + "    \"node2ConsistentId\"\n"
+                + "  ],\n"
+                + "  \"cmgNodes\": [\n"
+                + "    \"node2ConsistentId\",\n"
+                + "    \"node3ConsistentId\"\n"
+                + "  ],\n"
+                + "  \"clusterName\": \"cluster\",\n"
+                + "  \"clusterConfiguration\": \"" + clusterConfiguration + 
"\"\n"
+                + "}";
+
+        clientAndServer
+                .when(request()
+                        .withMethod("POST")
+                        .withPath("/management/v1/cluster/init")
+                        .withBody(json(expectedSentContent, 
ONLY_MATCHING_FIELDS))
+                        .withContentType(MediaType.APPLICATION_JSON_UTF_8)
+                )
+                .respond(response(null));
+
+        execute(
+                "cluster", "init",
+                "--cluster-endpoint-url", mockUrl,
+                "--meta-storage-node", "node1ConsistentId",
+                "--meta-storage-node", "node2ConsistentId",
+                "--cmg-node", "node2ConsistentId",
+                "--cmg-node", "node3ConsistentId",
+                "--cluster-name", "cluster",
+                "--cluster-config-file", clusterConfigurationFile.toString()
+        );
+
+        assertSuccessfulOutputIs("Cluster was initialized successfully");
+    }
+
+    @Test
+    void initError() {
+        clientAndServer
+                .when(request()
+                        .withMethod("POST")
+                        .withPath("/management/v1/cluster/init")
+                )
+                .respond(response()
+                        .withStatusCode(INTERNAL_SERVER_ERROR_500.code())
+                        .withBody("{\"status\":500, \"detail\":\"Oops\"}")
+                );
+
+        execute(
+                "cluster", "init",
+                "--cluster-endpoint-url", mockUrl,
+                "--meta-storage-node", "node1ConsistentId",
+                "--meta-storage-node", "node2ConsistentId",
+                "--cmg-node", "node2ConsistentId",
+                "--cmg-node", "node3ConsistentId",
+                "--cluster-name", "cluster"
+        );
+
+        assertAll(
+                () -> assertExitCodeIs(1),
+                this::assertOutputIsEmpty,
+                () -> assertErrOutputIs("Oops")
+        );
+    }
+
+    @Test
+    @DisplayName("--cluster-endpoint-url http://localhost:10300 --cmg-node 
node2ConsistentId --cmg-node node3ConsistentId")
+    void metastorageNodesAreMandatoryForInit() {
+        execute(
+                "cluster", "init",
+                "--cluster-endpoint-url", mockUrl,
+                "--cmg-node", "node2ConsistentId",
+                "--cmg-node", "node3ConsistentId",
+                "--cluster-name", "cluster"
+        );
+
+        assertAll(
+                () -> assertExitCodeIs(2),
+                this::assertOutputIsEmpty,
+                () -> assertErrOutputContains("Missing required option: 
'--meta-storage-node=<metaStorageNodes>'")
+        );
+    }
+
+    @Test
+    @DisplayName("--cluster-endpoint-url http://localhost:10300 
--meta-storage-node node2ConsistentId --meta-storage-node node3ConsistentId")
+    void cmgNodesAreNotMandatoryForInit() {
+        clientAndServer
+                .when(request()
+                        .withMethod("POST")
+                        .withPath("/management/v1/cluster/init")
+                )
+                .respond(response().withStatusCode(OK_200.code()));
+
+        execute(
+                "cluster", "init",
+                "--cluster-endpoint-url", mockUrl,
+                "--meta-storage-node", "node1ConsistentId",
+                "--meta-storage-node", "node2ConsistentId",
+                "--cluster-name", "cluster"
+        );
+
+        assertSuccessfulOutputIs("Cluster was initialized successfully");
+    }
+
+    @Test
+    @DisplayName("--cluster-endpoint-url http://localhost:10300 
--meta-storage-node node1ConsistentId --cmg-node node2ConsistentId")
+    void clusterNameIsMandatoryForInit() {
+        execute(
+                "cluster", "init",
+                "--cluster-endpoint-url", mockUrl,
+                "--meta-storage-node", "node1ConsistentId",
+                "--cmg-node", "node2ConsistentId"
+        );
+
+        assertAll(
+                () -> assertExitCodeIs(2),
+                this::assertOutputIsEmpty,
+                () -> assertErrOutputContains("Missing required option: 
'--cluster-name=<clusterName>'")
+        );
+    }
+}
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cluster/config/ClusterConfigTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cluster/config/ClusterConfigTest.java
new file mode 100644
index 0000000000..5d6283d8ed
--- /dev/null
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cluster/config/ClusterConfigTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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
+ *
+ *      http://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.ignite.internal.cli.commands.cluster.config;
+
+import static org.mockserver.model.HttpRequest.request;
+import static org.mockserver.model.HttpResponse.response;
+
+import org.apache.ignite.internal.cli.commands.IgniteCliInterfaceTestBase;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/** Tests "cluster config" commands. */
+@DisplayName("cluster config")
+class ClusterConfigTest extends IgniteCliInterfaceTestBase {
+    @Test
+    @DisplayName("show --cluster-endpoint-url http://localhost:10300";)
+    void show() {
+        clientAndServer
+                .when(request()
+                        .withMethod("GET")
+                        .withPath("/management/v1/configuration/cluster")
+                )
+                .respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
+
+        execute("cluster config show --cluster-endpoint-url " + mockUrl);
+
+        assertSuccessfulOutputIs("{\n"
+                + "  \"autoAdjust\" : {\n"
+                + "    \"enabled\" : true\n"
+                + "  }\n"
+                + "}\n");
+    }
+
+    @Test
+    @DisplayName("show --cluster-endpoint-url http://localhost:10300 
local.baseline")
+    void showSubtree() {
+        clientAndServer
+                .when(request()
+                        .withMethod("GET")
+                        
.withPath("/management/v1/configuration/cluster/local.baseline")
+                )
+                .respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
+
+        execute("cluster config show --cluster-endpoint-url " + mockUrl + " 
local.baseline");
+
+        assertSuccessfulOutputIs("{\n"
+                + "  \"autoAdjust\" : {\n"
+                + "    \"enabled\" : true\n"
+                + "  }\n"
+                + "}\n");
+    }
+
+    @Test
+    @DisplayName("update --cluster-endpoint-url http://localhost:10300 
local.baseline.autoAdjust.enabled=true")
+    void updateHocon() {
+        clientAndServer
+                .when(request()
+                        .withMethod("PATCH")
+                        .withPath("/management/v1/configuration/cluster")
+                        .withBody("local.baseline.autoAdjust.enabled=true")
+                )
+                .respond(response(null));
+
+        execute("cluster config update --cluster-endpoint-url "
+                + mockUrl + " local.baseline.autoAdjust.enabled=true");
+
+        assertSuccessfulOutputIs("Cluster configuration was updated 
successfully");
+    }
+}
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/node/config/NodeConfigTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/node/config/NodeConfigTest.java
new file mode 100644
index 0000000000..f25e0984cd
--- /dev/null
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/node/config/NodeConfigTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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
+ *
+ *      http://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.ignite.internal.cli.commands.node.config;
+
+import static org.apache.ignite.internal.cli.core.style.AnsiStringSupport.fg;
+import static org.mockserver.model.HttpRequest.request;
+import static org.mockserver.model.HttpResponse.response;
+
+import org.apache.ignite.internal.cli.commands.IgniteCliInterfaceTestBase;
+import org.apache.ignite.internal.cli.core.style.AnsiStringSupport.Color;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/** Tests "node config" commands. */
+@DisplayName("node config")
+public class NodeConfigTest extends IgniteCliInterfaceTestBase {
+    @Test
+    @DisplayName("show --node-url http://localhost:10300";)
+    void show() {
+        clientAndServer
+                .when(request()
+                        .withMethod("GET")
+                        .withPath("/management/v1/configuration/node")
+                )
+                .respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
+
+        execute("node config show --node-url " + mockUrl);
+
+        assertSuccessfulOutputIs("{\n"
+                + "  \"autoAdjust\" : {\n"
+                + "    \"enabled\" : true\n"
+                + "  }\n"
+                + "}\n");
+    }
+
+    @Test
+    @DisplayName("show --node-url http://localhost:10300 local.baseline")
+    void showSubtree() {
+        clientAndServer
+                .when(request()
+                        .withMethod("GET")
+                        
.withPath("/management/v1/configuration/node/local.baseline")
+                )
+                .respond(response("{\"autoAdjust\":{\"enabled\":true}}"));
+
+        execute("node config show --node-url " + mockUrl + " local.baseline");
+
+        assertSuccessfulOutputIs("{\n"
+                + "  \"autoAdjust\" : {\n"
+                + "    \"enabled\" : true\n"
+                + "  }\n"
+                + "}\n");
+    }
+
+    @Test
+    @DisplayName("update --node-url http://localhost:10300 
local.baseline.autoAdjust.enabled=true")
+    void updateHocon() {
+        clientAndServer
+                .when(request()
+                        .withMethod("PATCH")
+                        .withPath("/management/v1/configuration/node")
+                        .withBody("local.baseline.autoAdjust.enabled=true")
+                )
+                .respond(response(null));
+
+        execute("node config update --node-url " + mockUrl + " 
local.baseline.autoAdjust.enabled=true");
+
+        assertSuccessfulOutputIs("Node configuration updated. "
+                + fg(Color.YELLOW).mark("Restart the node to apply changes."));
+    }
+}
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricTest.java
new file mode 100644
index 0000000000..65fe0ba0b6
--- /dev/null
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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
+ *
+ *      http://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.ignite.internal.cli.commands.node.metric;
+
+import static org.mockserver.model.HttpRequest.request;
+import static org.mockserver.model.HttpResponse.response;
+
+import org.apache.ignite.internal.cli.commands.IgniteCliInterfaceTestBase;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/** Tests "node metric" commands. */
+@DisplayName("node metric")
+class NodeMetricTest extends IgniteCliInterfaceTestBase {
+    @Test
+    @DisplayName("source enable srcName")
+    void enable() {
+        clientAndServer
+                .when(request()
+                        .withMethod("POST")
+                        .withPath("/management/v1/metric/node/enable")
+                        .withBody("srcName")
+                )
+                .respond(response(null));
+
+        execute("node metric source enable --node-url " + mockUrl + " 
srcName");
+
+        assertSuccessfulOutputIs("Metric source was enabled successfully");
+    }
+
+    @Test
+    @DisplayName("source disable srcName")
+    void disable() {
+        clientAndServer
+                .when(request()
+                        .withMethod("POST")
+                        .withPath("/management/v1/metric/node/disable")
+                        .withBody("srcName")
+                )
+                .respond(response(null));
+
+        execute("node metric source disable --node-url " + mockUrl + " 
srcName");
+
+        assertSuccessfulOutputIs("Metric source was disabled successfully");
+    }
+
+    @Test
+    @DisplayName("source list")
+    void listSources() {
+        String responseBody = 
"[{\"name\":\"enabledMetric\",\"enabled\":true},{\"name\":\"disabledMetric\",\"enabled\":false}]";
+        clientAndServer
+                .when(request()
+                        .withMethod("GET")
+                        .withPath("/management/v1/metric/node/source")
+                )
+                .respond(response(responseBody));
+
+        execute("node metric source list --plain --node-url " + mockUrl);
+
+        assertSuccessfulOutputIs("Set 
name\tEnabled\nenabledMetric\tenabled\ndisabledMetric\tdisabled\n");
+    }
+
+    @Test
+    @DisplayName("list")
+    void listSets() {
+        String responseBody = 
"[{\"name\":\"metricSet\",\"metrics\":[{\"name\":\"metric\",\"desc\":\"description\"}]}]";
+        clientAndServer
+                .when(request()
+                        .withMethod("GET")
+                        .withPath("/management/v1/metric/node/set")
+                )
+                .respond(response(responseBody));
+
+        execute("node metric list --plain --node-url " + mockUrl);
+
+        assertSuccessfulOutputIs("Set name\tMetric 
name\tDescription\nmetricSet\t\t\n\tmetric\tdescription");
+    }
+}
diff --git 
a/modules/cli/src/testFixtures/java/org/apache/ignite/internal/cli/AbstractCliTest.java
 
b/modules/cli/src/testFixtures/java/org/apache/ignite/internal/cli/AbstractCliTest.java
deleted file mode 100644
index 983a241acb..0000000000
--- 
a/modules/cli/src/testFixtures/java/org/apache/ignite/internal/cli/AbstractCliTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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
- *
- *      http://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.ignite.internal.cli;
-
-import io.micronaut.configuration.picocli.MicronautFactory;
-import io.micronaut.context.ApplicationContext;
-import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
-import jakarta.inject.Inject;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-import org.apache.ignite.internal.cli.commands.TopLevelCliCommand;
-import org.junit.jupiter.api.BeforeAll;
-import picocli.CommandLine;
-
-/**
- * Base class for any CLI tests.
- */
-@MicronautTest(rebuildContext = true)
-public abstract class AbstractCliTest {
-    @Inject
-    private ApplicationContext ctx;
-
-    /** stderr. */
-    protected ByteArrayOutputStream err = new ByteArrayOutputStream();
-
-    /** stdout. */
-    protected ByteArrayOutputStream out = new ByteArrayOutputStream();
-
-    /**
-     * Creates a new command line interpreter.
-     *
-     * @return New command line instance.
-     */
-    private CommandLine cmd() {
-        return new CommandLine(TopLevelCliCommand.class, new 
MicronautFactory(ctx))
-                .setErr(new PrintWriter(err, true))
-                .setOut(new PrintWriter(out, true));
-    }
-
-    protected final int execute(String... args) {
-        return cmd().execute(args);
-    }
-
-    /**
-     * Sets up a dumb terminal before tests.
-     */
-    @BeforeAll
-    static void beforeAll() {
-        System.setProperty("org.jline.terminal.dumb", "true");
-    }
-
-    /**
-     * Reset stderr and stdout streams.
-     */
-    protected void resetStreams() {
-        err.reset();
-        out.reset();
-    }
-}

Reply via email to