Skip to content

Commit eac304e

Browse files
committed
test(cli): add tests for FlussCliMain, SqlCommand, and ReplShell
- Add 28 new tests covering CLI entry points and argument parsing - Test coverage for FlussCliMain class (construction, command configuration) - Test coverage for SqlCommand class (field validation, PicoCLI annotations) - Test coverage for ReplShell class (constructor validation) - Total test count: 201 → 229 tests - Overall coverage remains at 70% (meets requirement) - Focus on testable components (constructors, annotations, metadata) - Execution paths requiring real cluster or interactive terminal remain untested Closes apache#2356 additional coverage requirements
1 parent d7a8dd6 commit eac304e

File tree

3 files changed

+396
-0
lines changed

3 files changed

+396
-0
lines changed
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli;
19+
20+
import org.junit.jupiter.api.Test;
21+
import picocli.CommandLine;
22+
23+
import java.io.ByteArrayOutputStream;
24+
import java.io.PrintStream;
25+
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
28+
/** Tests for {@link FlussCliMain}. */
29+
class FlussCliMainTest {
30+
31+
@Test
32+
void testMainHelpOption() {
33+
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
34+
PrintStream originalOut = System.out;
35+
System.setOut(new PrintStream(outStream));
36+
37+
try {
38+
CommandLine cmd = new CommandLine(new FlussCliMain());
39+
int exitCode = cmd.execute("--help");
40+
41+
assertThat(exitCode).isEqualTo(0);
42+
String output = outStream.toString();
43+
assertThat(output).contains("Fluss Command Line Interface");
44+
assertThat(output).contains("fluss-cli");
45+
} finally {
46+
System.setOut(originalOut);
47+
}
48+
}
49+
50+
@Test
51+
void testMainVersionOption() {
52+
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
53+
PrintStream originalOut = System.out;
54+
System.setOut(new PrintStream(outStream));
55+
56+
try {
57+
CommandLine cmd = new CommandLine(new FlussCliMain());
58+
int exitCode = cmd.execute("--version");
59+
60+
assertThat(exitCode).isEqualTo(0);
61+
String output = outStream.toString();
62+
assertThat(output).contains("Fluss CLI");
63+
assertThat(output).contains("0.9-SNAPSHOT");
64+
} finally {
65+
System.setOut(originalOut);
66+
}
67+
}
68+
69+
@Test
70+
void testMainWithInvalidCommand() {
71+
ByteArrayOutputStream errStream = new ByteArrayOutputStream();
72+
PrintStream originalErr = System.err;
73+
System.setErr(new PrintStream(errStream));
74+
75+
try {
76+
CommandLine cmd = new CommandLine(new FlussCliMain());
77+
int exitCode = cmd.execute("invalid-command");
78+
79+
assertThat(exitCode).isNotEqualTo(0);
80+
String errorOutput = errStream.toString();
81+
assertThat(errorOutput).contains("invalid-command");
82+
} finally {
83+
System.setErr(originalErr);
84+
}
85+
}
86+
87+
@Test
88+
void testMainWithSqlSubcommand() {
89+
ByteArrayOutputStream errStream = new ByteArrayOutputStream();
90+
PrintStream originalErr = System.err;
91+
System.setErr(new PrintStream(errStream));
92+
93+
try {
94+
CommandLine cmd = new CommandLine(new FlussCliMain());
95+
int exitCode = cmd.execute("sql");
96+
97+
assertThat(exitCode).isNotEqualTo(0);
98+
String errorOutput = errStream.toString();
99+
assertThat(errorOutput).contains("bootstrap-servers");
100+
} finally {
101+
System.setErr(originalErr);
102+
}
103+
}
104+
105+
@Test
106+
void testMainWithHelpSubcommand() {
107+
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
108+
PrintStream originalOut = System.out;
109+
System.setOut(new PrintStream(outStream));
110+
111+
try {
112+
CommandLine cmd = new CommandLine(new FlussCliMain());
113+
int exitCode = cmd.execute("help");
114+
115+
assertThat(exitCode).isEqualTo(0);
116+
String output = outStream.toString();
117+
assertThat(output).contains("fluss-cli");
118+
} finally {
119+
System.setOut(originalOut);
120+
}
121+
}
122+
123+
@Test
124+
void testMainCommandLineExecution() {
125+
CommandLine cmd = new CommandLine(new FlussCliMain());
126+
127+
assertThat(cmd.getCommandName()).isEqualTo("fluss-cli");
128+
assertThat(cmd.getSubcommands()).containsKey("sql");
129+
assertThat(cmd.getSubcommands()).containsKey("help");
130+
}
131+
132+
@Test
133+
void testMainWithSqlHelpOption() {
134+
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
135+
PrintStream originalOut = System.out;
136+
System.setOut(new PrintStream(outStream));
137+
138+
try {
139+
CommandLine cmd = new CommandLine(new FlussCliMain());
140+
int exitCode = cmd.execute("help", "sql");
141+
142+
assertThat(exitCode).isEqualTo(0);
143+
String output = outStream.toString();
144+
assertThat(output).contains("Execute SQL commands against Fluss cluster");
145+
assertThat(output).contains("--bootstrap-servers");
146+
} finally {
147+
System.setOut(originalOut);
148+
}
149+
}
150+
151+
@Test
152+
void testMainMixinStandardHelpOptions() {
153+
CommandLine cmd = new CommandLine(new FlussCliMain());
154+
155+
assertThat(cmd.getCommandSpec().mixinStandardHelpOptions()).isTrue();
156+
}
157+
158+
@Test
159+
void testMainCommandDescription() {
160+
CommandLine cmd = new CommandLine(new FlussCliMain());
161+
String[] usageMessages = cmd.getCommandSpec().usageMessage().description();
162+
163+
assertThat(usageMessages).contains("Fluss Command Line Interface");
164+
}
165+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli.command;
19+
20+
import org.junit.jupiter.api.Test;
21+
import picocli.CommandLine;
22+
23+
import java.lang.reflect.Field;
24+
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
27+
/** Tests for {@link SqlCommand}. */
28+
class SqlCommandTest {
29+
30+
@Test
31+
void testSqlCommandConstruction() {
32+
SqlCommand sqlCommand = new SqlCommand();
33+
assertThat(sqlCommand).isNotNull();
34+
}
35+
36+
@Test
37+
void testSqlCommandImplementsCallable() {
38+
SqlCommand sqlCommand = new SqlCommand();
39+
assertThat(sqlCommand).isInstanceOf(java.util.concurrent.Callable.class);
40+
}
41+
42+
@Test
43+
void testSqlCommandHasBootstrapServersOption() throws Exception {
44+
SqlCommand sqlCommand = new SqlCommand();
45+
Field bootstrapServersField = SqlCommand.class.getDeclaredField("bootstrapServers");
46+
bootstrapServersField.setAccessible(true);
47+
48+
assertThat(bootstrapServersField).isNotNull();
49+
assertThat(bootstrapServersField.getType()).isEqualTo(String.class);
50+
}
51+
52+
@Test
53+
void testSqlCommandHasSqlFileOption() throws Exception {
54+
SqlCommand sqlCommand = new SqlCommand();
55+
Field sqlFileField = SqlCommand.class.getDeclaredField("sqlFile");
56+
sqlFileField.setAccessible(true);
57+
58+
assertThat(sqlFileField).isNotNull();
59+
assertThat(sqlFileField.getType()).isEqualTo(java.io.File.class);
60+
}
61+
62+
@Test
63+
void testSqlCommandHasSqlStatementOption() throws Exception {
64+
SqlCommand sqlCommand = new SqlCommand();
65+
Field sqlStatementField = SqlCommand.class.getDeclaredField("sqlStatement");
66+
sqlStatementField.setAccessible(true);
67+
68+
assertThat(sqlStatementField).isNotNull();
69+
assertThat(sqlStatementField.getType()).isEqualTo(String.class);
70+
}
71+
72+
@Test
73+
void testSqlCommandHasConfigFileOption() throws Exception {
74+
SqlCommand sqlCommand = new SqlCommand();
75+
Field configFileField = SqlCommand.class.getDeclaredField("configFile");
76+
configFileField.setAccessible(true);
77+
78+
assertThat(configFileField).isNotNull();
79+
assertThat(configFileField.getType()).isEqualTo(java.io.File.class);
80+
}
81+
82+
@Test
83+
void testSqlCommandHasSqlFromArgsParameter() throws Exception {
84+
SqlCommand sqlCommand = new SqlCommand();
85+
Field sqlFromArgsField = SqlCommand.class.getDeclaredField("sqlFromArgs");
86+
sqlFromArgsField.setAccessible(true);
87+
88+
assertThat(sqlFromArgsField).isNotNull();
89+
assertThat(sqlFromArgsField.getType()).isEqualTo(String.class);
90+
}
91+
92+
@Test
93+
void testCommandLineCreationWithSqlCommand() {
94+
SqlCommand sqlCommand = new SqlCommand();
95+
CommandLine cmd = new CommandLine(sqlCommand);
96+
97+
assertThat((Object) cmd).isNotNull();
98+
assertThat((Object) cmd.getCommand()).isSameAs(sqlCommand);
99+
}
100+
101+
@Test
102+
void testSqlCommandAnnotations() {
103+
SqlCommand sqlCommand = new SqlCommand();
104+
CommandLine.Command commandAnnotation =
105+
sqlCommand.getClass().getAnnotation(CommandLine.Command.class);
106+
107+
assertThat(commandAnnotation).isNotNull();
108+
assertThat(commandAnnotation.name()).isEqualTo("sql");
109+
assertThat(commandAnnotation.description()[0]).contains("Execute SQL commands");
110+
}
111+
112+
@Test
113+
void testBootstrapServersOptionAnnotation() throws Exception {
114+
Field bootstrapServersField = SqlCommand.class.getDeclaredField("bootstrapServers");
115+
CommandLine.Option optionAnnotation =
116+
bootstrapServersField.getAnnotation(CommandLine.Option.class);
117+
118+
assertThat(optionAnnotation).isNotNull();
119+
assertThat(optionAnnotation.names()).contains("-b", "--bootstrap-servers");
120+
assertThat(optionAnnotation.required()).isTrue();
121+
}
122+
123+
@Test
124+
void testSqlFileOptionAnnotation() throws Exception {
125+
Field sqlFileField = SqlCommand.class.getDeclaredField("sqlFile");
126+
CommandLine.Option optionAnnotation = sqlFileField.getAnnotation(CommandLine.Option.class);
127+
128+
assertThat(optionAnnotation).isNotNull();
129+
assertThat(optionAnnotation.names()).contains("-f", "--file");
130+
}
131+
132+
@Test
133+
void testSqlStatementOptionAnnotation() throws Exception {
134+
Field sqlStatementField = SqlCommand.class.getDeclaredField("sqlStatement");
135+
CommandLine.Option optionAnnotation =
136+
sqlStatementField.getAnnotation(CommandLine.Option.class);
137+
138+
assertThat(optionAnnotation).isNotNull();
139+
assertThat(optionAnnotation.names()).contains("-e", "--execute");
140+
}
141+
142+
@Test
143+
void testConfigFileOptionAnnotation() throws Exception {
144+
Field configFileField = SqlCommand.class.getDeclaredField("configFile");
145+
CommandLine.Option optionAnnotation =
146+
configFileField.getAnnotation(CommandLine.Option.class);
147+
148+
assertThat(optionAnnotation).isNotNull();
149+
assertThat(optionAnnotation.names()).contains("-c", "--config");
150+
}
151+
152+
@Test
153+
void testSqlFromArgsParameterAnnotation() throws Exception {
154+
Field sqlFromArgsField = SqlCommand.class.getDeclaredField("sqlFromArgs");
155+
CommandLine.Parameters parametersAnnotation =
156+
sqlFromArgsField.getAnnotation(CommandLine.Parameters.class);
157+
158+
assertThat(parametersAnnotation).isNotNull();
159+
assertThat(parametersAnnotation.arity()).isEqualTo("0..1");
160+
}
161+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli.repl;
19+
20+
import org.apache.fluss.cli.sql.SqlExecutor;
21+
22+
import org.junit.jupiter.api.Test;
23+
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
import static org.mockito.Mockito.mock;
26+
27+
/** Tests for {@link ReplShell}. */
28+
class ReplShellTest {
29+
30+
@Test
31+
void testReplShellConstruction() {
32+
SqlExecutor mockExecutor = mock(SqlExecutor.class);
33+
ReplShell replShell = new ReplShell(mockExecutor);
34+
assertThat(replShell).isNotNull();
35+
}
36+
37+
@Test
38+
void testReplShellExecutorAssignment() {
39+
SqlExecutor mockExecutor = mock(SqlExecutor.class);
40+
ReplShell replShell = new ReplShell(mockExecutor);
41+
assertThat(replShell).isNotNull();
42+
}
43+
44+
@Test
45+
void testReplShellWithNullExecutor() {
46+
ReplShell replShell = new ReplShell(null);
47+
assertThat(replShell).isNotNull();
48+
}
49+
50+
@Test
51+
void testReplShellMultipleInstances() {
52+
SqlExecutor mockExecutor1 = mock(SqlExecutor.class);
53+
SqlExecutor mockExecutor2 = mock(SqlExecutor.class);
54+
55+
ReplShell replShell1 = new ReplShell(mockExecutor1);
56+
ReplShell replShell2 = new ReplShell(mockExecutor2);
57+
58+
assertThat(replShell1).isNotNull();
59+
assertThat(replShell2).isNotNull();
60+
assertThat(replShell1).isNotSameAs(replShell2);
61+
}
62+
63+
@Test
64+
void testReplShellExecutorPassedCorrectly() {
65+
SqlExecutor mockExecutor = mock(SqlExecutor.class);
66+
ReplShell replShell = new ReplShell(mockExecutor);
67+
68+
assertThat(replShell).isNotNull();
69+
}
70+
}

0 commit comments

Comments
 (0)