1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gov.nist.secauto.oscal.tools.cli.core;
28
29 import static org.junit.jupiter.api.Assertions.assertAll;
30 import static org.junit.jupiter.api.Assertions.assertEquals;
31 import static org.junit.jupiter.api.Assertions.assertNull;
32
33 import gov.nist.secauto.metaschema.binding.io.Format;
34 import gov.nist.secauto.metaschema.cli.processor.ExitCode;
35 import gov.nist.secauto.metaschema.cli.processor.ExitStatus;
36 import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionException;
37
38 import org.junit.jupiter.params.ParameterizedTest;
39 import org.junit.jupiter.params.provider.Arguments;
40 import org.junit.jupiter.params.provider.MethodSource;
41
42 import java.nio.file.Path;
43 import java.nio.file.Paths;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.stream.Stream;
49
50 import edu.umd.cs.findbugs.annotations.NonNull;
51
52 public class CLITest {
53 void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode) {
54 status.generateMessage(true);
55 assertAll(
56 () -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
57 () -> assertNull(status.getThrowable(), "expected null Throwable"));
58 }
59
60 void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode,
61 @NonNull Class<? extends Throwable> thrownClass) {
62 status.generateMessage(true);
63 Throwable thrown = status.getThrowable();
64 assert thrown != null;
65 assertAll(
66 () -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
67 () -> assertEquals(thrownClass, thrown.getClass(), "expected Throwable mismatch"));
68 }
69
70 private static Stream<Arguments> providesValues() {
71 final String[] commands = { "ap", "ar", "catalog", "component-definition", "profile", "poam", "ssp" };
72 final Map<Format, List<Format>> formatEntries = Map.of(
73 Format.XML, Arrays.asList(Format.JSON, Format.YAML),
74 Format.JSON, Arrays.asList(Format.XML, Format.JSON),
75 Format.YAML, Arrays.asList(Format.XML, Format.JSON));
76 List<Arguments> values = new ArrayList<>();
77
78 values.add(Arguments.of(new String[] { "--version" }, ExitCode.OK, null));
79
80 Path path = Paths.get("src/test/resources/cli/example_profile_invalid" + Format.XML.getDefaultExtension());
81 values.add(
82 Arguments.of(new String[] { "profile", "resolve", "--to=" + Format.XML.name().toLowerCase(), path.toString() },
83 ExitCode.PROCESSING_ERROR, ProfileResolutionException.class));
84
85 for (String cmd : commands) {
86 values.add(Arguments.of(new String[] { cmd, "validate", "-h" }, ExitCode.OK, null));
87
88 values.add(Arguments.of(new String[] { cmd, "convert", "-h" }, ExitCode.INVALID_COMMAND, null));
89
90 for (Format format : Format.values()) {
91 path = Paths.get("src/test/resources/cli/example_" + cmd + "_invalid" + format.getDefaultExtension());
92 values.add(Arguments.of(new String[] { cmd, "validate", path.toString() }, ExitCode.FAIL, null));
93 path = Paths.get("src/test/resources/cli/example_" + cmd + "_valid" + format.getDefaultExtension());
94 values.add(Arguments.of(new String[] { cmd, "validate", path.toString() }, ExitCode.OK, null));
95 path = Paths.get("src/test/resources/cli/example_profile_valid" + format.getDefaultExtension());
96 List<Format> targetFormats = formatEntries.get(format);
97 for (Format targetFormat : targetFormats) {
98 path = Paths.get("src/test/resources/cli/example_" + cmd + "_valid" + format.getDefaultExtension());
99 String outputPath = path.toString().replace(format.getDefaultExtension(),
100 "_converted" + targetFormat.getDefaultExtension());
101 values.add(Arguments.of(new String[] { cmd, "convert", "--to=" + targetFormat.name().toLowerCase(),
102 path.toString(), outputPath, "--overwrite" }, ExitCode.OK, null));
103
104 path = Paths.get("src/test/resources/cli/example_" + cmd + "_invalid" + format.getDefaultExtension());
105 outputPath = path.toString().replace(format.getDefaultExtension(),
106 "_converted" + targetFormat.getDefaultExtension());
107 values.add(Arguments.of(new String[] { cmd, "convert", "--to=" + targetFormat.name().toLowerCase(),
108 path.toString(), outputPath, "--overwrite" }, ExitCode.OK, null));
109 }
110 if (cmd == "profile") {
111 path = Paths.get("src/test/resources/cli/example_profile_valid" + format.getDefaultExtension());
112 values
113 .add(Arguments.of(new String[] { cmd, "resolve", "--to=" + format.name().toLowerCase(), path.toString() },
114 ExitCode.OK, null));
115 }
116 }
117 }
118
119 return values.stream();
120 }
121
122 @ParameterizedTest
123 @MethodSource("providesValues")
124 void testAllSubCommands(@NonNull String[] args, @NonNull ExitCode expectedExitCode,
125 Class<? extends Throwable> expectedThrownClass) {
126 if (expectedThrownClass == null) {
127 evaluateResult(CLI.runCli(args), expectedExitCode);
128 } else {
129 evaluateResult(CLI.runCli(args), expectedExitCode, expectedThrownClass);
130 }
131 }
132 }