Skip to content

Commit

Permalink
Improve javadoc
Browse files Browse the repository at this point in the history
  • Loading branch information
en-milie committed Oct 20, 2023
1 parent 4ea895f commit 42ce8b5
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 19 deletions.
15 changes: 15 additions & 0 deletions src/main/java/com/endava/cats/args/ApiArguments.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,20 @@ public class ApiArguments {
description = "Base URL of the service")
private String server;

/**
* Verifies if the supplied OpenAPI spec is from a local location or a http one.
*
* @return true if the contract is from a http location, false otherwise
*/
public boolean isRemoteContract() {
return contract != null && contract.startsWith("http");
}

/**
* Validates the required {@code --contract} and {@code --server} arguments are present.
*
* @param spec the PicoCli command spec
*/
public void validateRequired(CommandLine.Model.CommandSpec spec) {
if (this.contract == null) {
throw new CommandLine.ParameterException(spec.commandLine(), "Missing required option --contract=<contract>");
Expand All @@ -57,6 +67,11 @@ public void validateRequired(CommandLine.Model.CommandSpec spec) {
}
}

/**
* Sets a custom user agent based on the CATS version.
*
* @param version the current CATS version
*/
public void setUserAgent(String version) {
if (userAgent == null) {
userAgent = "cats/" + version;
Expand Down
28 changes: 27 additions & 1 deletion src/main/java/com/endava/cats/args/AuthArguments.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.endava.cats.args;

import jakarta.inject.Singleton;
import lombok.Getter;
import picocli.CommandLine;

import jakarta.inject.Singleton;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -52,14 +52,29 @@ public class AuthArguments {
private int authRefreshInterval;


/**
* Checks if proxy details were supplied via the {@code --proxyXXX} arguments.
*
* @return true if proxy arguments are supplied, false otherwise
*/
public boolean isProxySupplied() {
return proxyHost != null && proxyPort != 0;
}

/**
* Checks is basic auth details were supplied via the {@code --basicAuth} argument.
*
* @return true if basic auth details were supplied, false otherwise
*/
public boolean isBasicAuthSupplied() {
return basicAuth != null;
}

/**
* Checks if SSL keystore was supplied via the {@code --sslKeystore} argument.
*
* @return true if a SSL keystore was supplied, false otherwise
*/
public boolean isMutualTls() {
return sslKeystore != null;
}
Expand All @@ -77,11 +92,22 @@ public Proxy getProxy() {
return proxy;
}

/**
* Creates a basic auth header based on the supplied --basicAuth argument.
*
* @return base64 encoded basic auth header
*/
public String getBasicAuthHeader() {
byte[] encodedAuth = Base64.getEncoder().encode(this.basicAuth.getBytes(StandardCharsets.UTF_8));
return "Basic " + new String(encodedAuth, StandardCharsets.UTF_8);
}

/**
* Creates a Map with the following elements "auth_script"=--authRefreshScript argument
* and "auth_refresh"=--authRefreshInterval.
*
* @return a Map with auth refresh details
*/
public Map<String, String> getAuthScriptAsMap() {
return Map.of("auth_script", this.getAuthRefreshScript(), "auth_refresh", String.valueOf(getAuthRefreshInterval()));
}
Expand Down
52 changes: 42 additions & 10 deletions src/main/java/com/endava/cats/args/FilesArguments.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import java.util.Map;
import java.util.Optional;

/**
* Holds all arguments related to different files used by CATS like: headers, reference data, etc.
*/
@Singleton
public class FilesArguments {
private static final String ALL = "all";
Expand Down Expand Up @@ -100,34 +103,57 @@ public void loadConfig() throws IOException {
loadQueryParams();
}

/**
* Loads the supplied security fuzzer file into a Map.
*
* @throws IOException if something happens while reading the file
*/
public void loadSecurityFuzzerFile() throws IOException {
if (securityFuzzerFile == null) {
log.debug("No SecurityFuzzer file provided. SecurityFuzzer will be skipped!");
} else {
log.config(Ansi.ansi().bold().a("Security Fuzzer file: {}").reset().toString(),
Ansi.ansi().fg(Ansi.Color.YELLOW).a(securityFuzzerFile.getCanonicalPath()));
securityFuzzerDetails = this.parseYaml(securityFuzzerFile.getCanonicalPath());
securityFuzzerDetails = parseYaml(securityFuzzerFile.getCanonicalPath());
}
}

/**
* Loads the supplied functional fuzzer file into a Map.
*
* @throws IOException if something happens while reading the file
*/
public void loadCustomFuzzerFile() throws IOException {
if (customFuzzerFile == null) {
log.debug("No FunctionalFuzzer file provided. FunctionalFuzzer will be skipped!");
} else {
log.config(Ansi.ansi().bold().a("Functional Fuzzer file: {}").reset().toString(),
Ansi.ansi().fg(Ansi.Color.YELLOW).a(customFuzzerFile.getCanonicalPath()));
customFuzzerDetails = this.parseYaml(customFuzzerFile.getCanonicalPath());
customFuzzerDetails = parseYaml(customFuzzerFile.getCanonicalPath());
}
}

/**
* Loads the supplied reference data file into a Map.
*
* @throws IOException if something happens while reading the file
*/
public void loadRefData() throws IOException {
this.refData = this.loadFileAsMapOfMapsOfStrings(refDataFile, "Reference Data");
}

/**
* Loads the supplied query params file into a Map.
*
* @throws IOException if something happens while reading the file
*/
public void loadQueryParams() throws IOException {
this.queryParams = this.loadFileAsMapOfMapsOfStrings(queryFile, "Query Params");
}

/**
* Loads the supplied url params into a Map.
*/
public void loadURLParams() {
if (params == null) {
log.debug("No URL parameters provided!");
Expand All @@ -137,6 +163,12 @@ public void loadURLParams() {
}
}

/**
* Loads the supplied headers file into a Map. The method also merges the headers supplied
* in the file with the ones supplied via the {@code -H} argument.
*
* @throws IOException if something happens while reading the file
*/
public void loadHeaders() throws IOException {
this.headers = this.loadFileAsMapOfMapsOfStrings(headersFile, "Headers");

Expand All @@ -163,8 +195,8 @@ public List<String> getUrlParamsList() {
* Replaces the current URL parameters with the {@code --urlParams} arguments supplied.
* The URL parameters are expected to be included in curly brackets.
*
* @param startingUrl the base url; http://localhost:8080/{petId}
* @return the initial URL with the parameters replaced with --urlParams supplied values
* @param startingUrl the base url: {@code http://localhost:8080/{petId}}
* @return the initial URL with the parameters replaced with --urlParams supplied values: {@code http://localhost:8080/123}
*/
public String replacePathWithUrlParams(String startingUrl) {
for (String line : this.getUrlParamsList()) {
Expand All @@ -185,7 +217,7 @@ public String replacePathWithUrlParams(String startingUrl) {
* @return a Map representation of the --headers file with paths being the Map keys
*/
public Map<String, Object> getHeaders(String path) {
return getPathAndAll(headers, path);
return mergePathAndAll(headers, path);
}

/**
Expand All @@ -197,7 +229,7 @@ public Map<String, Object> getHeaders(String path) {
* @return a Map with the supplied --refData
*/
public Map<String, Object> getRefData(String currentPath) {
return getPathAndAll(refData, currentPath);
return mergePathAndAll(refData, currentPath);
}

/**
Expand All @@ -208,11 +240,11 @@ public Map<String, Object> getRefData(String currentPath) {
* @return a key-value map with all additional query params
*/
public Map<String, Object> getAdditionalQueryParamsForPath(String path) {
return getPathAndAll(queryParams, path);
return mergePathAndAll(queryParams, path);
}


static Map<String, Object> getPathAndAll(Map<String, Map<String, Object>> collection, String path) {
static Map<String, Object> mergePathAndAll(Map<String, Map<String, Object>> collection, String path) {
return collection.entrySet().stream()
.filter(entry -> entry.getKey().equalsIgnoreCase(path) || entry.getKey().equalsIgnoreCase(ALL))
.map(Map.Entry::getValue).collect(HashMap::new, Map::putAll, Map::putAll);
Expand All @@ -225,13 +257,13 @@ private Map<String, Map<String, Object>> loadFileAsMapOfMapsOfStrings(File file,
} else {
log.config(Ansi.ansi().bold().a("{} file: {}").reset().toString(), fileType,
Ansi.ansi().fg(Ansi.Color.YELLOW).a(file.getCanonicalPath()));
fromFile = this.parseYaml(file.getCanonicalPath());
fromFile = parseYaml(file.getCanonicalPath());
log.debug("{} file loaded successfully: {}", fileType, fromFile);
}
return fromFile;
}

public Map<String, Map<String, Object>> parseYaml(String yaml) throws IOException {
static Map<String, Map<String, Object>> parseYaml(String yaml) throws IOException {
Map<String, Map<String, Object>> result = new LinkedHashMap<>();
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try (Reader reader = new InputStreamReader(new FileInputStream(yaml), StandardCharsets.UTF_8)) {
Expand Down
41 changes: 34 additions & 7 deletions src/main/java/com/endava/cats/args/FilterArguments.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.endava.cats.args;

import com.endava.cats.annotations.LinterFuzzer;
import com.endava.cats.annotations.ControlCharFuzzer;
import com.endava.cats.annotations.EmojiFuzzer;
import com.endava.cats.annotations.FieldFuzzer;
import com.endava.cats.annotations.HeaderFuzzer;
import com.endava.cats.annotations.HttpFuzzer;
import com.endava.cats.annotations.LinterFuzzer;
import com.endava.cats.annotations.SanitizeAndValidate;
import com.endava.cats.annotations.SecondPhaseFuzzer;
import com.endava.cats.annotations.SpecialFuzzer;
Expand All @@ -15,13 +15,13 @@
import com.endava.cats.annotations.WhitespaceFuzzer;
import com.endava.cats.fuzzer.api.Fuzzer;
import com.endava.cats.http.HttpMethod;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import lombok.Getter;
import org.springframework.core.annotation.AnnotationUtils;
import picocli.CommandLine;

import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -70,19 +70,40 @@ public class FilterArguments {
description = "Simulate a possible run without actually invoking the service. This will print how many tests will actually be executed and with which Fuzzers")
private boolean dryRun;


/**
* Creates a list with the fuzzers to be skipped based on the supplied {@code --skipFuzzers} argument.
*
* @return the list of fuzzers to skip if any supplied, an empty list otherwise
*/
public List<String> getSkipFuzzers() {
return Optional.ofNullable(this.skipFuzzers).orElse(Collections.emptyList());
}

/**
* Creates a list with the paths to be skipped based on the supplied {@code --skipPaths} argument.
*
* @return the list of paths to skip if any supplied, an empty list otherwise
*/
public List<String> getSkipPaths() {
return Optional.ofNullable(this.skipPaths).orElse(Collections.emptyList());
}

/**
* Creates a list with the fuzzers to be included based on the supplied {@code --fuzzers} argument.
* If no fuzzer is explicitly supplied, ALL fuzzers will be considered.
*
* @return the list of fuzzers to include if any supplied, an empty list otherwise
*/
public List<String> getSuppliedFuzzers() {
return Optional.ofNullable(this.suppliedFuzzers).orElse(Collections.emptyList());
}

/**
* Creates a list with the paths to be included based on the supplied {@code --paths} argument.
* If no path is explicitly supplied, ALL fuzzers will be considered.
*
* @return the list of paths to include if any supplied, an empty list otherwise
*/
public List<String> getPaths() {
return Optional.ofNullable(this.paths).orElse(Collections.emptyList());
}
Expand Down Expand Up @@ -131,6 +152,12 @@ private boolean onlySpecialFuzzers(List<String> candidates) {
return !candidates.isEmpty() && new HashSet<>(specialFuzzers).containsAll(candidates);
}


/**
* Returns a list with ALL registered fuzzers.
*
* @return a list with all the fuzzers
*/
public List<Fuzzer> getAllRegisteredFuzzers() {
if (ALL_CATS_FUZZERS.isEmpty()) {
List<String> interimFuzzersList = fuzzers.stream().map(Object::toString).toList();
Expand All @@ -145,15 +172,15 @@ public List<Fuzzer> getAllRegisteredFuzzers() {
return ALL_CATS_FUZZERS;
}

public List<String> removeBasedOnSanitizationStrategy(List<String> currentFuzzers) {
List<String> removeBasedOnSanitizationStrategy(List<String> currentFuzzers) {
Class<? extends Annotation> filterAnnotation = processingArguments.getSanitizationStrategy() == ProcessingArguments.SanitizationStrategy.SANITIZE_AND_VALIDATE
? ValidateAndSanitize.class : SanitizeAndValidate.class;
List<String> trimFuzzers = this.filterFuzzersByAnnotationWhenCheckArgumentSupplied(true, filterAnnotation);

return currentFuzzers.stream().filter(fuzzer -> !trimFuzzers.contains(fuzzer)).toList();
}

public List<String> removeBasedOnTrimStrategy(List<String> currentFuzzers) {
List<String> removeBasedOnTrimStrategy(List<String> currentFuzzers) {
Class<? extends Annotation> filterAnnotation = processingArguments.getEdgeSpacesStrategy() == ProcessingArguments.TrimmingStrategy.TRIM_AND_VALIDATE
? ValidateAndTrim.class : TrimAndValidate.class;
List<String> trimFuzzers = this.filterFuzzersByAnnotationWhenCheckArgumentSupplied(true, filterAnnotation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class ProcessingArguments {

@Setter
@CommandLine.Option(names = {"--contentType"},
description = "A custom mime type if the OpenAPI spec uses content type negotiation versioning. Default: @|bold,underline ${DEFAULT-VALUE}|@")
description = "A custom mime type if the OpenAPI spec uses content type negotiation versioning.")
private String contentType;

public static final String JSON_WILDCARD = "application\\/.*\\+?json;?.*";
Expand Down

0 comments on commit 42ce8b5

Please sign in to comment.