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 <[email protected]>
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();
- }
-}