Skip to content

Commit d44864a

Browse files
committed
chore: Refactor to reduce verbosity and improve consistency
1 parent f18cf41 commit d44864a

File tree

9 files changed

+183
-81
lines changed

9 files changed

+183
-81
lines changed

src/main/java/com/endava/cats/command/CatsCommand.java

Lines changed: 41 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.endava.cats.openapi.handler.index.SpecPositionIndex;
2525
import com.endava.cats.report.ExecutionStatisticsListener;
2626
import com.endava.cats.report.TestCaseListener;
27+
import com.endava.cats.util.AnsiUtils;
2728
import com.endava.cats.util.CatsRandom;
2829
import com.endava.cats.util.CatsUtil;
2930
import com.endava.cats.util.ConsoleUtils;
@@ -38,7 +39,6 @@
3839
import jakarta.inject.Inject;
3940
import lombok.Getter;
4041
import org.eclipse.microprofile.config.inject.ConfigProperty;
41-
import org.fusesource.jansi.Ansi;
4242
import picocli.AutoComplete;
4343
import picocli.CommandLine;
4444

@@ -58,8 +58,6 @@
5858
import java.util.concurrent.TimeUnit;
5959
import java.util.stream.Collectors;
6060

61-
import static org.fusesource.jansi.Ansi.ansi;
62-
6361
/**
6462
* Main application command.
6563
*/
@@ -139,11 +137,11 @@ public class CatsCommand implements Runnable, CommandLine.IExitCodeGenerator, Au
139137

140138
@Inject
141139
@CommandLine.ArgGroup(heading = "%n@|bold,underline Authentication Options:|@%n", exclusive = false)
142-
AuthArguments authArgs;
140+
AuthArguments authArguments;
143141

144142
@Inject
145143
@CommandLine.ArgGroup(heading = "%n@|bold,underline Check Options:|@%n", exclusive = false)
146-
CheckArguments checkArgs;
144+
CheckArguments checkArguments;
147145

148146
@Inject
149147
@CommandLine.ArgGroup(heading = "%n@|bold,underline Files Options:|@%n", exclusive = false)
@@ -231,26 +229,9 @@ void printVersion(Future<VersionChecker.CheckResult> newVersion) throws Executio
231229
VersionChecker.CheckResult checkResult = newVersion.get();
232230
logger.debug("Current version {}. Latest version {}", appVersion, checkResult.getVersion());
233231
if (checkResult.isNewVersion()) {
234-
String message = ansi()
235-
.bold()
236-
.fgBrightBlue()
237-
.a("A new version is available: {}. Download url: {}")
238-
.reset()
239-
.toString();
240-
String currentVersionFormatted = ansi()
241-
.bold()
242-
.fgBrightBlue()
243-
.a(checkResult.getVersion())
244-
.reset()
245-
.bold()
246-
.fgBrightBlue()
247-
.toString();
248-
String downloadUrlFormatted = ansi()
249-
.bold()
250-
.fgGreen()
251-
.a(checkResult.getDownloadUrl())
252-
.reset()
253-
.toString();
232+
String message = AnsiUtils.boldBrightBlue("A new version is available: {}. Download url: {}");
233+
String currentVersionFormatted = AnsiUtils.boldBrightBlue(checkResult.getVersion());
234+
String downloadUrlFormatted = AnsiUtils.boldGreen(checkResult.getDownloadUrl());
254235
logger.star(message, currentVersionFormatted, downloadUrlFormatted);
255236
}
256237
}
@@ -295,21 +276,11 @@ Future<VersionChecker.CheckResult> checkForNewVersion() {
295276

296277
private void printSuggestions() {
297278
if (executionStatisticsListener.areManyAuthErrors()) {
298-
String message = ansi()
299-
.bold()
300-
.fgBrightYellow()
301-
.a("There were {} tests failing with authorisation errors. Either supply authentication details or check if the supplied credentials are correct!")
302-
.reset()
303-
.toString();
279+
String message = AnsiUtils.boldYellow("There were {} tests failing with authorisation errors. Either supply authentication details or check if the supplied credentials are correct!");
304280
logger.star(message, executionStatisticsListener.getAuthErrors());
305281
}
306282
if (executionStatisticsListener.areManyIoErrors()) {
307-
String message = ansi()
308-
.bold()
309-
.fgBrightYellow()
310-
.a("There were {} tests failing with i/o errors. Make sure that you have access to the service or that the --server url is correct!")
311-
.reset()
312-
.toString();
283+
String message = AnsiUtils.boldYellow("There were {} tests failing with i/o errors. Make sure that you have access to the service or that the --server url is correct!");
313284
logger.star(message, executionStatisticsListener.getIoErrors());
314285
}
315286
}
@@ -363,7 +334,7 @@ private void executeCustomFuzzer() throws IOException {
363334
}
364335

365336
OpenAPI createOpenAPI() throws IOException {
366-
String finishMessage = ansi().fgGreen().a("Finished parsing the contract in {} ms").reset().toString();
337+
String finishMessage = AnsiUtils.green("Finished parsing the contract in {} ms");
367338
long t0 = System.currentTimeMillis();
368339
OpenAPI openAPI = OpenApiUtils.readOpenApi(apiArguments.getContract());
369340
logger.debug(finishMessage, (System.currentTimeMillis() - t0));
@@ -381,41 +352,41 @@ void prepareRun() throws IOException {
381352
}
382353

383354
private void printConfiguration(OpenAPI openAPI) {
384-
logger.config(ansi().bold().a("OpenAPI specs: {}").reset().toString(), ansi().fg(Ansi.Color.BLUE).a(apiArguments.getContract()).reset());
385-
logger.config(ansi().bold().a("API base url: {}").reset().toString(), ansi().fg(Ansi.Color.BLUE).a(apiArguments.getServer()).reset());
386-
logger.config(ansi().bold().a("Reporting path: {}").reset().toString(), ansi().fg(Ansi.Color.BLUE).a(reportingArguments.getOutputReportFolder()).reset());
387-
logger.config(ansi().bold().a("{} configured fuzzers out of {} total fuzzers").bold().reset().toString(),
388-
ansi().fg(Ansi.Color.BLUE).a(filterArguments.getFirstPhaseFuzzersForPath().size()).reset().bold(),
389-
ansi().fg(Ansi.Color.BLUE).a(filterArguments.getAllRegisteredFuzzers().size()).reset().bold());
390-
logger.config(ansi().bold().a("{} configured paths out of {} total OpenAPI paths").bold().reset().toString(),
391-
ansi().fg(Ansi.Color.BLUE).a(filterArguments.getPathsToRun(openAPI).size()).bold().reset().bold(),
392-
ansi().fg(Ansi.Color.BLUE).a(openAPI.getPaths().size()).reset().bold());
393-
logger.config(ansi().bold().a("HTTP methods in scope: {}").reset().toString(), ansi().fg(Ansi.Color.BLUE).a(filterArguments.getHttpMethods()).reset());
394-
logger.config(ansi().bold().bold().a("Example flags: useRequestBodyExamples {}, useSchemaExamples {}, usePropertyExamples {}, useResponseBodyExamples {}, useDefaults {}").reset().toString(),
395-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.isUseRequestBodyExamples()).reset().bold(),
396-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.isUseSchemaExamples()).reset().bold(),
397-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.isUsePropertyExamples()).reset().bold(),
398-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.isUseResponseBodyExamples()).reset().bold(),
399-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.isUseDefaults()).reset().bold());
400-
logger.config(ansi().bold().a("selfReferenceDepth {}, largeStringsSize {}, randomHeadersNumber {}, limitFuzzedFields {}, limitXxxOfCombinations {}").reset().toString(),
401-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.getSelfReferenceDepth()).reset().bold(),
402-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.getLargeStringsSize()).reset().bold(),
403-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.getRandomHeadersNumber()).reset().bold(),
404-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.getLimitNumberOfFields()).reset().bold(),
405-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.getLimitXxxOfCombinations()).reset().bold());
406-
logger.config(ansi().bold().a("How the service handles whitespaces and random unicodes: edgeSpacesStrategy {}, sanitizationStrategy {}").reset().toString(),
407-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.getEdgeSpacesStrategy()).reset().bold(),
408-
ansi().fg(Ansi.Color.BLUE).a(processingArguments.getSanitizationStrategy()).reset().bold());
409-
logger.config(ansi().bold().a("Seed value: {}").reset().toString(),
410-
ansi().fg(Ansi.Color.BLUE).a(CatsRandom.getStoredSeed()).reset().bold());
355+
logger.config(AnsiUtils.bold("OpenAPI specs: {}"), AnsiUtils.blue(apiArguments.getContract()));
356+
logger.config(AnsiUtils.bold("API base url: {}"), AnsiUtils.blue(apiArguments.getServer()));
357+
logger.config(AnsiUtils.bold("Reporting path: {}"), AnsiUtils.blue(reportingArguments.getOutputReportFolder()));
358+
logger.config(AnsiUtils.bold("{} configured fuzzers out of {} total fuzzers"),
359+
AnsiUtils.boldBlue(filterArguments.getFirstPhaseFuzzersForPath().size()),
360+
AnsiUtils.boldBlue(filterArguments.getAllRegisteredFuzzers().size()));
361+
logger.config(AnsiUtils.bold("{} configured paths out of {} total OpenAPI paths"),
362+
AnsiUtils.boldBlue(filterArguments.getPathsToRun(openAPI).size()),
363+
AnsiUtils.boldBlue(openAPI.getPaths().size()));
364+
logger.config(AnsiUtils.bold("HTTP methods in scope: {}"), AnsiUtils.blue(filterArguments.getHttpMethods()));
365+
logger.config(AnsiUtils.bold("Example flags: useRequestBodyExamples {}, useSchemaExamples {}, usePropertyExamples {}, useResponseBodyExamples {}, useDefaults {}"),
366+
AnsiUtils.boldBlue(processingArguments.isUseRequestBodyExamples()),
367+
AnsiUtils.boldBlue(processingArguments.isUseSchemaExamples()),
368+
AnsiUtils.boldBlue(processingArguments.isUsePropertyExamples()),
369+
AnsiUtils.boldBlue(processingArguments.isUseResponseBodyExamples()),
370+
AnsiUtils.boldBlue(processingArguments.isUseDefaults()));
371+
logger.config(AnsiUtils.bold("selfReferenceDepth {}, largeStringsSize {}, randomHeadersNumber {}, limitFuzzedFields {}, limitXxxOfCombinations {}"),
372+
AnsiUtils.boldBlue(processingArguments.getSelfReferenceDepth()),
373+
AnsiUtils.boldBlue(processingArguments.getLargeStringsSize()),
374+
AnsiUtils.boldBlue(processingArguments.getRandomHeadersNumber()),
375+
AnsiUtils.boldBlue(processingArguments.getLimitNumberOfFields()),
376+
AnsiUtils.boldBlue(processingArguments.getLimitXxxOfCombinations()));
377+
logger.config(AnsiUtils.bold("How the service handles whitespaces and random unicodes: edgeSpacesStrategy {}, sanitizationStrategy {}"),
378+
AnsiUtils.boldBlue(processingArguments.getEdgeSpacesStrategy()),
379+
AnsiUtils.boldBlue(processingArguments.getSanitizationStrategy()));
380+
logger.config(AnsiUtils.bold("Seed value: {}"),
381+
AnsiUtils.boldBlue(CatsRandom.getStoredSeed()));
411382

412383
int nofOfOperations = OpenApiUtils.getNumberOfOperations(openAPI);
413-
logger.config(ansi().bold().a("Total number of OpenAPI operations: {}").reset().toString(), ansi().fg(Ansi.Color.BLUE).a(nofOfOperations));
384+
logger.config(AnsiUtils.bold("Total number of OpenAPI operations: {}"), AnsiUtils.blue(nofOfOperations));
414385
}
415386

416387
private void fuzzPath(Map.Entry<String, PathItem> pathItemEntry, OpenAPI openAPI) {
417388
/* WE NEED TO ITERATE THROUGH EACH HTTP OPERATION CORRESPONDING TO THE CURRENT PATH ENTRY*/
418-
String ansiString = ansi().bold().a("Start fuzzing path {}").reset().toString();
389+
String ansiString = AnsiUtils.bold("Start fuzzing path {}");
419390
logger.start(ansiString, pathItemEntry.getKey());
420391
List<FuzzingData> fuzzingDataList = fuzzingDataFactory.fromPathItem(pathItemEntry.getKey(), pathItemEntry.getValue(), openAPI);
421392

@@ -453,7 +424,7 @@ private void runFuzzers(List<FuzzingData> fuzzingDataListWithHttpMethodsFiltered
453424
private void runSingleFuzzer(Fuzzer fuzzer, FuzzingData data) {
454425
if (data.shouldSkipFuzzerForPath(fuzzer.toString())) {
455426
logger.skip("Skipping Fuzzer {} for path {} due to OpenAPI extension configuration",
456-
ansi().fgYellow().a(fuzzer.toString()).reset(), data.getPath());
427+
AnsiUtils.yellow(fuzzer.toString()), data.getPath());
457428
return;
458429
}
459430

@@ -473,12 +444,12 @@ private void runSingleFuzzer(Fuzzer fuzzer, FuzzingData data) {
473444
}
474445

475446
private void logFuzzerEnd(Fuzzer fuzzer, FuzzingData data) {
476-
logger.complete("Finishing Fuzzer {}, http method {}, path {}", ansi().fgGreen().a(fuzzer.toString()).reset(), data.getMethod(), data.getPath());
447+
logger.complete("Finishing Fuzzer {}, http method {}, path {}", AnsiUtils.green(fuzzer.toString()), data.getMethod(), data.getPath());
477448
logger.info("{}", SEPARATOR);
478449
}
479450

480451
private void logFuzzerStart(Fuzzer fuzzer, FuzzingData data) {
481-
logger.start("Starting Fuzzer {}, http method {}, path {}", ansi().fgGreen().a(fuzzer.toString()).reset(), data.getMethod(), data.getPath());
452+
logger.start("Starting Fuzzer {}, http method {}, path {}", AnsiUtils.green(fuzzer.toString()), data.getMethod(), data.getPath());
482453
logger.debug("Fuzzing payload: {}", data.getPayload());
483454
}
484455

src/main/java/com/endava/cats/command/LintCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.endava.cats.args.NamingArguments;
55
import com.endava.cats.args.ReportingArguments;
66
import com.endava.cats.command.model.ConfigOptions;
7+
import com.endava.cats.fuzzer.FuzzerTypes;
78
import com.endava.cats.util.VersionProvider;
89
import io.quarkus.arc.Unremovable;
910
import jakarta.inject.Inject;
@@ -70,7 +71,7 @@ public class LintCommand implements Runnable, CommandLine.IExitCodeGenerator {
7071
public void run() {
7172
catsCommand.apiArguments.setContract(contract);
7273
catsCommand.apiArguments.setServer("http://empty");
73-
catsCommand.filterArguments.customFilter("Linter");
74+
catsCommand.filterArguments.customFilter(FuzzerTypes.LINTER);
7475
catsCommand.filterArguments.setSkipFuzzers(Optional.ofNullable(skipLinters).orElse(Collections.emptyList()));
7576
catsCommand.filterArguments.getSkipPaths().addAll(Optional.ofNullable(skipPaths).orElse(Collections.emptyList()));
7677
catsCommand.filterArguments.getCheckArguments().setIncludeContract(true);

src/main/java/com/endava/cats/command/RandomCommand.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.endava.cats.args.ReportingArguments;
88
import com.endava.cats.args.StopArguments;
99
import com.endava.cats.command.model.ConfigOptions;
10+
import com.endava.cats.fuzzer.FuzzerTypes;
1011
import com.endava.cats.http.HttpMethod;
1112
import com.endava.cats.util.VersionProvider;
1213
import io.quarkus.arc.Unremovable;
@@ -51,7 +52,7 @@ public class RandomCommand implements Runnable, CommandLine.IExitCodeGenerator {
5152

5253
@Inject
5354
@CommandLine.ArgGroup(heading = "%n@|bold,underline Authentication Options:|@%n", exclusive = false)
54-
AuthArguments authArgs;
55+
AuthArguments authArguments;
5556

5657
@Inject
5758
@CommandLine.ArgGroup(heading = "%n@|bold,underline Reporting Options:|@%n", exclusive = false)
@@ -100,7 +101,7 @@ public void run() {
100101
// these are all throwing a ParameterException in case a mandatory argument is not provided
101102
apiArguments.validateRequired(spec);
102103

103-
catsCommand.filterArguments.customFilter("RandomFuzzer");
104+
catsCommand.filterArguments.customFilter(FuzzerTypes.RANDOM);
104105
catsCommand.filesArguments = filesArguments;
105106
catsCommand.processingArguments.setContentType(this.contentType);
106107
catsCommand.processingArguments.setXxxOfSelections(this.xxxOfSelections);

src/main/java/com/endava/cats/command/ReplayCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public class ReplayCommand implements Runnable {
6666

6767
@Inject
6868
@CommandLine.ArgGroup(heading = "%n@|bold,underline Authentication Options:|@%n", exclusive = false)
69-
AuthArguments authArgs;
69+
AuthArguments authArguments;
7070

7171
@CommandLine.Option(names = {"-D", "--debug"},
7272
description = "Set CATS log level to ALL. Useful for diagnosing when raising bugs")
@@ -287,7 +287,7 @@ private void loadHeadersIfSupplied(CatsTestCase testCase) {
287287
headersFromFile.addAll(headersMap.entrySet().stream().map(entry -> new KeyValuePair<>(entry.getKey(), entry.getValue())).toList());
288288

289289
//see if any header is dynamic and it needs a parser
290-
headersFromFile.forEach(header -> header.setValue(CatsDSLParser.parseAndGetResult(header.getValue().toString(), authArgs.getAuthScriptAsMap())));
290+
headersFromFile.forEach(header -> header.setValue(CatsDSLParser.parseAndGetResult(header.getValue().toString(), authArguments.getAuthScriptAsMap())));
291291
}
292292

293293
private CatsTestCase loadTestCaseFile(String testCaseFileName) throws IOException {

src/main/java/com/endava/cats/command/RunCommand.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.endava.cats.args.IgnoreArguments;
66
import com.endava.cats.args.ReportingArguments;
77
import com.endava.cats.command.model.ConfigOptions;
8+
import com.endava.cats.fuzzer.FuzzerTypes;
89
import com.endava.cats.util.CatsDSLWords;
910
import com.endava.cats.util.CatsUtil;
1011
import com.endava.cats.util.VersionProvider;
@@ -61,7 +62,7 @@ public class RunCommand implements Runnable, CommandLine.IExitCodeGenerator {
6162

6263
@Inject
6364
@CommandLine.ArgGroup(heading = "%n@|bold,underline Authentication Options:|@%n", exclusive = false)
64-
AuthArguments authArgs;
65+
AuthArguments authArguments;
6566

6667
@Inject
6768
@CommandLine.ArgGroup(heading = "%n@|bold,underline Reporting Options:|@%n", exclusive = false)
@@ -122,10 +123,10 @@ public void run() {
122123

123124
try {
124125
if (this.isFunctionalFuzzerFile()) {
125-
catsCommand.filterArguments.customFilter("FunctionalFuzzer");
126+
catsCommand.filterArguments.customFilter(FuzzerTypes.FUNCTIONAL);
126127
catsCommand.filesArguments.setCustomFuzzerFile(file);
127128
} else {
128-
catsCommand.filterArguments.customFilter("SecurityFuzzer");
129+
catsCommand.filterArguments.customFilter(FuzzerTypes.SECURITY);
129130
catsCommand.filesArguments.setSecurityFuzzerFile(file);
130131
}
131132
catsCommand.filesArguments.setHeadersFile(headersFile);

src/main/java/com/endava/cats/command/TemplateFuzzCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public class TemplateFuzzCommand implements Runnable {
9595

9696
@Inject
9797
@CommandLine.ArgGroup(heading = "%n@|bold,underline Authentication Options:|@%n", exclusive = false)
98-
AuthArguments authArgs;
98+
AuthArguments authArguments;
9999

100100
@Inject
101101
@CommandLine.ArgGroup(heading = "%n@|bold,underline Reporting Options:|@%n", exclusive = false)
@@ -238,7 +238,7 @@ private Set<CatsHeader> getHeaders() {
238238
.stream()
239239
.map(entry -> CatsHeader.builder()
240240
.name(entry.getKey().trim())
241-
.value(CatsDSLParser.parseAndGetResult(entry.getValue().trim(), authArgs.getAuthScriptAsMap()))
241+
.value(CatsDSLParser.parseAndGetResult(entry.getValue().trim(), authArguments.getAuthScriptAsMap()))
242242
.build())
243243
.collect(Collectors.toSet());
244244
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.endava.cats.fuzzer;
2+
3+
/**
4+
* Constants for special fuzzer type names used in command execution.
5+
* Use these constants instead of magic strings to prevent typos and enable refactoring.
6+
*/
7+
public final class FuzzerTypes {
8+
9+
private FuzzerTypes() {
10+
// Constants class
11+
}
12+
13+
/**
14+
* FunctionalFuzzer - runs functional tests from YAML files.
15+
*/
16+
public static final String FUNCTIONAL = "FunctionalFuzzer";
17+
18+
/**
19+
* SecurityFuzzer - runs security tests from YAML files.
20+
*/
21+
public static final String SECURITY = "SecurityFuzzer";
22+
23+
/**
24+
* RandomFuzzer - runs continuous random fuzzing.
25+
*/
26+
public static final String RANDOM = "RandomFuzzer";
27+
28+
/**
29+
* Linter - runs OpenAPI contract linting.
30+
*/
31+
public static final String LINTER = "Linter";
32+
}

0 commit comments

Comments
 (0)