From 6650dbad113d76f762b61ffd9bb8ee31786a2151 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 28 Dec 2018 14:46:49 +0100 Subject: [PATCH] Improve stat document structure Closers gh-787 --- .../actuate/stat/ProjectRequestDocument.java | 457 ++++++++++++------ .../stat/ProjectRequestDocumentFactory.java | 116 ++--- .../MainControllerStatsIntegrationTests.java | 14 +- .../ProjectGenerationStatPublisherTests.java | 170 ++++++- .../ProjectRequestDocumentFactoryTests.java | 123 +++-- .../stat/request-invalid-dependencies.json | 33 ++ .../stat/request-invalid-java-version.json | 28 ++ .../stat/request-invalid-language.json | 28 ++ .../resources/stat/request-invalid-type.json | 27 ++ .../resources/stat/request-no-client.json | 24 + .../test/resources/stat/request-simple.json | 30 ++ 11 files changed, 776 insertions(+), 274 deletions(-) create mode 100644 initializr-actuator/src/test/resources/stat/request-invalid-dependencies.json create mode 100644 initializr-actuator/src/test/resources/stat/request-invalid-java-version.json create mode 100644 initializr-actuator/src/test/resources/stat/request-invalid-language.json create mode 100644 initializr-actuator/src/test/resources/stat/request-invalid-type.json create mode 100644 initializr-actuator/src/test/resources/stat/request-no-client.json create mode 100644 initializr-actuator/src/test/resources/stat/request-simple.json diff --git a/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocument.java b/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocument.java index 03571af0..a9a8ec47 100644 --- a/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocument.java +++ b/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocument.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,15 @@ package io.spring.initializr.actuate.stat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.StringJoiner; + +import io.spring.initializr.util.Agent; +import io.spring.initializr.util.Version; + +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; /** * Define the statistics of a project generation. @@ -28,47 +36,29 @@ public class ProjectRequestDocument { private long generationTimestamp; - private String requestIp; + private String type; - private String requestIpv4; - - private String requestCountry; - - private String clientId; - - private String clientVersion; + private String buildSystem; private String groupId; private String artifactId; - private String packageName; - - private String bootVersion; - private String javaVersion; private String language; private String packaging; - private String type; + private String packageName; - private final List dependencies = new ArrayList<>(); + private VersionInformation version; - private String errorMessage; + private ClientInformation client; - private boolean invalid; + private DependencyInformation dependencies; - private boolean invalidJavaVersion; - - private boolean invalidLanguage; - - private boolean invalidPackaging; - - private boolean invalidType; - - private final List invalidDependencies = new ArrayList<>(); + private ErrorStateInformation errorState; public long getGenerationTimestamp() { return this.generationTimestamp; @@ -78,44 +68,20 @@ public class ProjectRequestDocument { this.generationTimestamp = generationTimestamp; } - public String getRequestIp() { - return this.requestIp; + public String getType() { + return this.type; } - public void setRequestIp(String requestIp) { - this.requestIp = requestIp; + public void setType(String type) { + this.type = type; } - public String getRequestIpv4() { - return this.requestIpv4; + public String getBuildSystem() { + return this.buildSystem; } - public void setRequestIpv4(String requestIpv4) { - this.requestIpv4 = requestIpv4; - } - - public String getRequestCountry() { - return this.requestCountry; - } - - public void setRequestCountry(String requestCountry) { - this.requestCountry = requestCountry; - } - - public String getClientId() { - return this.clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getClientVersion() { - return this.clientVersion; - } - - public void setClientVersion(String clientVersion) { - this.clientVersion = clientVersion; + public void setBuildSystem(String buildSystem) { + this.buildSystem = buildSystem; } public String getGroupId() { @@ -134,22 +100,6 @@ public class ProjectRequestDocument { this.artifactId = artifactId; } - public String getPackageName() { - return this.packageName; - } - - public void setPackageName(String packageName) { - this.packageName = packageName; - } - - public String getBootVersion() { - return this.bootVersion; - } - - public void setBootVersion(String bootVersion) { - this.bootVersion = bootVersion; - } - public String getJavaVersion() { return this.javaVersion; } @@ -174,104 +124,305 @@ public class ProjectRequestDocument { this.packaging = packaging; } - public String getType() { - return this.type; + public String getPackageName() { + return this.packageName; } - public void setType(String type) { - this.type = type; + public void setPackageName(String packageName) { + this.packageName = packageName; } - public String getErrorMessage() { - return this.errorMessage; + public VersionInformation getVersion() { + return this.version; } - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; + public void setVersion(VersionInformation version) { + this.version = version; } - public boolean isInvalid() { - return this.invalid; + public ClientInformation getClient() { + return this.client; } - public void setInvalid(boolean invalid) { - this.invalid = invalid; + public void setClient(ClientInformation client) { + this.client = client; } - public boolean isInvalidJavaVersion() { - return this.invalidJavaVersion; - } - - public void setInvalidJavaVersion(boolean invalidJavaVersion) { - this.invalidJavaVersion = invalidJavaVersion; - } - - public boolean isInvalidLanguage() { - return this.invalidLanguage; - } - - public void setInvalidLanguage(boolean invalidLanguage) { - this.invalidLanguage = invalidLanguage; - } - - public boolean isInvalidPackaging() { - return this.invalidPackaging; - } - - public void setInvalidPackaging(boolean invalidPackaging) { - this.invalidPackaging = invalidPackaging; - } - - public boolean isInvalidType() { - return this.invalidType; - } - - public void setInvalidType(boolean invalidType) { - this.invalidType = invalidType; - } - - public List getDependencies() { + public DependencyInformation getDependencies() { return this.dependencies; } - public List getInvalidDependencies() { - return this.invalidDependencies; + public void setDependencies(DependencyInformation dependencies) { + this.dependencies = dependencies; + } + + public ErrorStateInformation getErrorState() { + return this.errorState; + } + + public ErrorStateInformation triggerError() { + if (this.errorState == null) { + this.errorState = new ErrorStateInformation(); + } + return this.errorState; } @Override public String toString() { - return "ProjectRequestDocument [generationTimestamp=" + this.generationTimestamp - + ", " - + ((this.requestIp != null) ? "requestIp=" + this.requestIp + ", " : "") - + ((this.requestIpv4 != null) ? "requestIpv4=" + this.requestIpv4 + ", " - : "") - + ((this.requestCountry != null) - ? "requestCountry=" + this.requestCountry + ", " : "") - + ((this.clientId != null) ? "clientId=" + this.clientId + ", " : "") - + ((this.clientVersion != null) - ? "clientVersion=" + this.clientVersion + ", " : "") - + ((this.groupId != null) ? "groupId=" + this.groupId + ", " : "") - + ((this.artifactId != null) ? "artifactId=" + this.artifactId + ", " - : "") - + ((this.packageName != null) ? "packageName=" + this.packageName + ", " - : "") - + ((this.bootVersion != null) ? "bootVersion=" + this.bootVersion + ", " - : "") - + ((this.javaVersion != null) ? "javaVersion=" + this.javaVersion + ", " - : "") - + ((this.language != null) ? "language=" + this.language + ", " : "") - + ((this.packaging != null) ? "packaging=" + this.packaging + ", " : "") - + ((this.type != null) ? "type=" + this.type + ", " : "") - + ((this.dependencies != null) - ? "dependencies=" + this.dependencies + ", " : "") - + ((this.errorMessage != null) - ? "errorMessage=" + this.errorMessage + ", " : "") - + "invalid=" + this.invalid + ", invalidJavaVersion=" - + this.invalidJavaVersion + ", invalidLanguage=" + this.invalidLanguage - + ", invalidPackaging=" + this.invalidPackaging + ", invalidType=" - + this.invalidType + ", " + ((this.invalidDependencies != null) - ? "invalidDependencies=" + this.invalidDependencies : "") - + "]"; + return new StringJoiner(", ", ProjectRequestDocument.class.getSimpleName() + "[", + "]").add("generationTimestamp=" + this.generationTimestamp) + .add("type='" + this.type + "'") + .add("buildSystem='" + this.buildSystem + "'") + .add("groupId='" + this.groupId + "'") + .add("artifactId='" + this.artifactId + "'") + .add("javaVersion='" + this.javaVersion + "'") + .add("language='" + this.language + "'") + .add("packaging='" + this.packaging + "'") + .add("packageName='" + this.packageName + "'") + .add("version=" + this.version).add("client=" + this.client) + .add("dependencies=" + this.dependencies) + .add("errorState=" + this.errorState).toString(); + } + + /** + * Spring Boot version information. + */ + public static class VersionInformation { + + private final String id; + + private final String major; + + private final String minor; + + public VersionInformation(Version version) { + this.id = version.toString(); + this.major = String.format("%s", version.getMajor()); + this.minor = (version.getMinor() != null) + ? String.format("%s.%s", version.getMajor(), version.getMinor()) + : null; + } + + public String getId() { + return this.id; + } + + public String getMajor() { + return this.major; + } + + public String getMinor() { + return this.minor; + } + + @Override + public String toString() { + return new StringJoiner(", ", "{", "}").add("id='" + this.id + "'") + .add("major='" + this.major + "'").add("minor='" + this.minor + "'") + .toString(); + } + + } + + /** + * Dependencies information. + */ + public static class DependencyInformation { + + private final String id; + + private final List values; + + private final int count; + + public DependencyInformation(List values) { + this.id = computeDependenciesId(new ArrayList<>(values)); + this.values = values; + this.count = values.size(); + } + + public String getId() { + return this.id; + } + + public List getValues() { + return this.values; + } + + public int getCount() { + return this.count; + } + + private static String computeDependenciesId(List dependencies) { + if (ObjectUtils.isEmpty(dependencies)) { + return "_none"; + } + Collections.sort(dependencies); + return StringUtils.collectionToDelimitedString(dependencies, " "); + } + + @Override + public String toString() { + return new StringJoiner(", ", "{", "}").add("id='" + this.id + "'") + .add("values=" + this.values).add("count=" + this.count).toString(); + } + + } + + /** + * Client information. + */ + public static class ClientInformation { + + private final String id; + + private final String version; + + private final String ip; + + private final String country; + + public ClientInformation(Agent agent, String ip, String country) { + this.id = (agent != null) ? agent.getId().getId() : null; + this.version = (agent != null) ? agent.getVersion() : null; + this.ip = ip; + this.country = country; + } + + public String getId() { + return this.id; + } + + public String getVersion() { + return this.version; + } + + public String getIp() { + return this.ip; + } + + public String getCountry() { + return this.country; + } + + @Override + public String toString() { + return new StringJoiner(", ", "{", "}").add("id='" + this.id + "'") + .add("version='" + this.version + "'").add("ip='" + this.ip + "'") + .add("country='" + this.country + "'").toString(); + } + + } + + /** + * Additional information about what part of the request is invalid. + */ + public static class ErrorStateInformation { + + private boolean invalid = true; + + private Boolean javaVersion; + + private Boolean language; + + private Boolean packaging; + + private Boolean type; + + private InvalidDependencyInformation dependencies; + + private String message; + + public boolean isInvalid() { + return this.invalid; + } + + public Boolean getJavaVersion() { + return this.javaVersion; + } + + public void setJavaVersion(Boolean javaVersion) { + this.javaVersion = javaVersion; + } + + public Boolean getLanguage() { + return this.language; + } + + public void setLanguage(Boolean language) { + this.language = language; + } + + public Boolean getPackaging() { + return this.packaging; + } + + public void setPackaging(Boolean packaging) { + this.packaging = packaging; + } + + public Boolean getType() { + return this.type; + } + + public void setType(Boolean type) { + this.type = type; + } + + public InvalidDependencyInformation getDependencies() { + return this.dependencies; + } + + public void triggerInvalidDependencies(List dependencies) { + this.dependencies = new InvalidDependencyInformation(dependencies); + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return new StringJoiner(", ", "{", "}").add("invalid=" + this.invalid) + .add("javaVersion=" + this.javaVersion) + .add("language=" + this.language).add("packaging=" + this.packaging) + .add("type=" + this.type).add("dependencies=" + this.dependencies) + .add("message='" + this.message + "'").toString(); + } + + } + + /** + * Invalid dependencies information. + */ + public static class InvalidDependencyInformation { + + private boolean invalid = true; + + private final List values; + + public InvalidDependencyInformation(List values) { + this.values = values; + } + + public boolean isInvalid() { + return this.invalid; + } + + public List getValues() { + return this.values; + } + + @Override + public String toString() { + return new StringJoiner(", ", "{", "}").add(String.join(", ", this.values)) + .toString(); + } + } } diff --git a/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactory.java b/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactory.java index 3a11026d..333d3e21 100644 --- a/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactory.java +++ b/initializr-actuator/src/main/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactory.java @@ -18,15 +18,19 @@ package io.spring.initializr.actuate.stat; import java.util.ArrayList; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.stream.Collectors; +import io.spring.initializr.actuate.stat.ProjectRequestDocument.ClientInformation; +import io.spring.initializr.actuate.stat.ProjectRequestDocument.DependencyInformation; +import io.spring.initializr.actuate.stat.ProjectRequestDocument.ErrorStateInformation; +import io.spring.initializr.actuate.stat.ProjectRequestDocument.VersionInformation; import io.spring.initializr.generator.ProjectFailedEvent; import io.spring.initializr.generator.ProjectRequest; import io.spring.initializr.generator.ProjectRequestEvent; import io.spring.initializr.metadata.InitializrMetadata; import io.spring.initializr.metadata.InitializrMetadataProvider; import io.spring.initializr.util.Agent; +import io.spring.initializr.util.Version; import org.springframework.util.StringUtils; @@ -37,9 +41,6 @@ import org.springframework.util.StringUtils; */ public class ProjectRequestDocumentFactory { - private static final Pattern IP_PATTERN = Pattern - .compile("[0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*"); - private final InitializrMetadataProvider metadataProvider; public ProjectRequestDocumentFactory(InitializrMetadataProvider metadataProvider) { @@ -52,93 +53,88 @@ public class ProjectRequestDocumentFactory { ProjectRequestDocument document = new ProjectRequestDocument(); document.setGenerationTimestamp(event.getTimestamp()); - - handleCloudFlareHeaders(request, document); - String candidate = (String) request.getParameters().get("x-forwarded-for"); - if (!StringUtils.hasText(document.getRequestIp()) && candidate != null) { - document.setRequestIp(candidate); - document.setRequestIpv4(extractIpv4(candidate)); - } - - Agent agent = extractAgentInformation(request); - if (agent != null) { - document.setClientId(agent.getId().getId()); - document.setClientVersion(agent.getVersion()); - } - document.setGroupId(request.getGroupId()); document.setArtifactId(request.getArtifactId()); document.setPackageName(request.getPackageName()); - document.setBootVersion(request.getBootVersion()); + document.setVersion(determineVersionInformation(request)); + document.setClient(determineClientInformation(request)); document.setJavaVersion(request.getJavaVersion()); if (StringUtils.hasText(request.getJavaVersion()) && metadata.getJavaVersions().get(request.getJavaVersion()) == null) { - document.setInvalid(true); - document.setInvalidJavaVersion(true); + document.triggerError().setJavaVersion(true); } document.setLanguage(request.getLanguage()); if (StringUtils.hasText(request.getLanguage()) && metadata.getLanguages().get(request.getLanguage()) == null) { - document.setInvalid(true); - document.setInvalidLanguage(true); + document.triggerError().setLanguage(true); } document.setPackaging(request.getPackaging()); if (StringUtils.hasText(request.getPackaging()) && metadata.getPackagings().get(request.getPackaging()) == null) { - document.setInvalid(true); - document.setInvalidPackaging(true); + document.triggerError().setPackaging(true); } document.setType(request.getType()); + document.setBuildSystem(determineBuildSystem(request)); if (StringUtils.hasText(request.getType()) && metadata.getTypes().get(request.getType()) == null) { - document.setInvalid(true); - document.setInvalidType(true); + document.triggerError().setType(true); } // Let's not rely on the resolved dependencies here List dependencies = new ArrayList<>(); dependencies.addAll(request.getStyle()); dependencies.addAll(request.getDependencies()); - dependencies.forEach((id) -> { - if (metadata.getDependencies().get(id) != null) { - document.getDependencies().add(id); - } - else { - document.setInvalid(true); - document.getInvalidDependencies().add(id); - } - }); + List validDependencies = dependencies.stream() + .filter((id) -> metadata.getDependencies().get(id) != null) + .collect(Collectors.toList()); + document.setDependencies(new DependencyInformation(validDependencies)); + List invalidDependencies = dependencies.stream() + .filter((id) -> (!validDependencies.contains(id))) + .collect(Collectors.toList()); + if (!invalidDependencies.isEmpty()) { + document.triggerError().triggerInvalidDependencies(invalidDependencies); + } // Let's make sure that the document is flagged as invalid no matter what if (event instanceof ProjectFailedEvent) { + ErrorStateInformation errorState = document.triggerError(); ProjectFailedEvent failed = (ProjectFailedEvent) event; - document.setInvalid(true); if (failed.getCause() != null) { - document.setErrorMessage(failed.getCause().getMessage()); + errorState.setMessage(failed.getCause().getMessage()); } } - return document; } - private static void handleCloudFlareHeaders(ProjectRequest request, - ProjectRequestDocument document) { - String candidate = (String) request.getParameters().get("cf-connecting-ip"); - if (StringUtils.hasText(candidate)) { - document.setRequestIp(candidate); - document.setRequestIpv4(extractIpv4(candidate)); - } - String country = (String) request.getParameters().get("cf-ipcountry"); - if (StringUtils.hasText(country) && !"xx".equalsIgnoreCase(country)) { - document.setRequestCountry(country); - } + private String determineBuildSystem(ProjectRequest request) { + String type = request.getType(); + String[] elements = type.split("-"); + return (elements.length == 2) ? elements[0] : null; } - private static Agent extractAgentInformation(ProjectRequest request) { + private VersionInformation determineVersionInformation(ProjectRequest request) { + Version version = Version.safeParse(request.getBootVersion()); + if (version != null && version.getMajor() != null) { + return new VersionInformation(version); + } + return null; + } + + private ClientInformation determineClientInformation(ProjectRequest request) { + Agent agent = determineAgent(request); + String ip = determineIp(request); + String country = determineCountry(request); + if (agent != null || ip != null || country != null) { + return new ClientInformation(agent, ip, country); + } + return null; + } + + private Agent determineAgent(ProjectRequest request) { String userAgent = (String) request.getParameters().get("user-agent"); if (StringUtils.hasText(userAgent)) { return Agent.fromUserAgent(userAgent); @@ -146,12 +142,16 @@ public class ProjectRequestDocumentFactory { return null; } - private static String extractIpv4(String candidate) { - if (StringUtils.hasText(candidate)) { - Matcher matcher = IP_PATTERN.matcher(candidate); - if (matcher.find()) { - return matcher.group(); - } + private String determineIp(ProjectRequest request) { + String candidate = (String) request.getParameters().get("cf-connecting-ip"); + return (StringUtils.hasText(candidate)) ? candidate + : (String) request.getParameters().get("x-forwarded-for"); + } + + private String determineCountry(ProjectRequest request) { + String candidate = (String) request.getParameters().get("cf-ipcountry"); + if (StringUtils.hasText(candidate) && !"xx".equalsIgnoreCase(candidate)) { + return candidate; } return null; } diff --git a/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/MainControllerStatsIntegrationTests.java b/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/MainControllerStatsIntegrationTests.java index 74db3193..833f486b 100755 --- a/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/MainControllerStatsIntegrationTests.java +++ b/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/MainControllerStatsIntegrationTests.java @@ -73,7 +73,7 @@ class MainControllerStatsIntegrationTests JsonNode json = parseJson(content.json); assertThat(json.get("groupId").textValue()).isEqualTo("com.foo"); assertThat(json.get("artifactId").textValue()).isEqualTo("bar"); - JsonNode list = json.get("dependencies"); + JsonNode list = json.get("dependencies").get("values"); assertThat(list).hasSize(1); assertThat(list.get(0).textValue()).isEqualTo("web"); } @@ -113,7 +113,7 @@ class MainControllerStatsIntegrationTests StatsMockController.Content content = this.statsMockController.stats.get(0); JsonNode json = parseJson(content.json); - assertThat(json.get("requestIp").textValue()).as("Wrong requestIp") + assertThat(json.get("client").get("ip").textValue()).as("Wrong requestIp") .isEqualTo("10.0.0.123"); } @@ -160,10 +160,12 @@ class MainControllerStatsIntegrationTests JsonNode json = parseJson(content.json); assertThat(json.get("groupId").textValue()).isEqualTo("com.example"); assertThat(json.get("artifactId").textValue()).isEqualTo("demo"); - assertThat(json.get("invalid").booleanValue()).isEqualTo(true); - assertThat(json.get("invalidType").booleanValue()).isEqualTo(true); - assertThat(json.get("errorMessage")).isNotNull(); - assertThat(json.get("errorMessage").textValue()).contains("invalid-type"); + assertThat(json.has("errorState")).isTrue(); + JsonNode errorState = json.get("errorState"); + assertThat(errorState.get("invalid").booleanValue()).isEqualTo(true); + assertThat(errorState.get("type").booleanValue()).isEqualTo(true); + assertThat(errorState.get("message")).isNotNull(); + assertThat(errorState.get("message").textValue()).contains("invalid-type"); } @Test diff --git a/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectGenerationStatPublisherTests.java b/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectGenerationStatPublisherTests.java index cfb2a28c..28286063 100755 --- a/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectGenerationStatPublisherTests.java +++ b/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectGenerationStatPublisherTests.java @@ -16,27 +16,40 @@ package io.spring.initializr.actuate.stat; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; import java.util.Collections; import java.util.UUID; import io.spring.initializr.actuate.stat.StatsProperties.Elastic; import io.spring.initializr.generator.ProjectGeneratedEvent; import io.spring.initializr.generator.ProjectRequest; +import org.json.JSONException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.Customization; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.skyscreamer.jsonassert.comparator.CustomComparator; import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.core.io.ClassPathResource; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.mock.http.client.MockClientHttpRequest; import org.springframework.retry.policy.SimpleRetryPolicy; import org.springframework.retry.support.RetryTemplate; import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.client.RequestMatcher; +import org.springframework.util.StreamUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath; import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; @@ -127,13 +140,125 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests { @Test void publishDocument() { ProjectRequest request = createProjectRequest(); - request.setGroupId("com.example.foo"); - request.setArtifactId("my-project"); + request.setGroupId("com.example.acme"); + request.setArtifactId("project"); + request.setType("maven-project"); + request.setBootVersion("2.1.1.RELEASE"); + request.setDependencies(Arrays.asList("web", "data-jpa")); + request.setLanguage("java"); + request.getParameters().put("user-agent", "curl/1.2.4"); + request.getParameters().put("cf-connecting-ip", "10.0.0.42"); + request.getParameters().put("cf-ipcountry", "BE"); this.mockServer.expect(requestTo("http://example.com/elastic/initializr/request")) .andExpect(method(HttpMethod.POST)) - .andExpect(jsonPath("$.groupId").value("com.example.foo")) - .andExpect(jsonPath("$.artifactId").value("my-project")) + .andExpect(json("stat/request-simple.json")) + .andRespond(withStatus(HttpStatus.CREATED) + .body(mockResponse(UUID.randomUUID().toString(), true)) + .contentType(MediaType.APPLICATION_JSON)); + + this.statPublisher.handleEvent(new ProjectGeneratedEvent(request)); + this.mockServer.verify(); + } + + @Test + void publishDocumentWithNoClientInformation() { + ProjectRequest request = createProjectRequest(); + request.setGroupId("com.example.acme"); + request.setArtifactId("test"); + request.setType("gradle-project"); + request.setBootVersion("2.1.0.RELEASE"); + request.setDependencies(Arrays.asList("web", "data-jpa")); + request.setLanguage("java"); + + this.mockServer.expect(requestTo("http://example.com/elastic/initializr/request")) + .andExpect(method(HttpMethod.POST)) + .andExpect(json("stat/request-no-client.json")) + .andRespond(withStatus(HttpStatus.CREATED) + .body(mockResponse(UUID.randomUUID().toString(), true)) + .contentType(MediaType.APPLICATION_JSON)); + + this.statPublisher.handleEvent(new ProjectGeneratedEvent(request)); + this.mockServer.verify(); + } + + @Test + void publishDocumentWithInvalidType() { + ProjectRequest request = createProjectRequest(); + request.setGroupId("com.example.acme"); + request.setArtifactId("test"); + request.setType("not-a-type"); + request.setBootVersion("2.1.0.RELEASE"); + request.setDependencies(Arrays.asList("web", "data-jpa")); + request.setLanguage("java"); + + this.mockServer.expect(requestTo("http://example.com/elastic/initializr/request")) + .andExpect(method(HttpMethod.POST)) + .andExpect(json("stat/request-invalid-type.json")) + .andRespond(withStatus(HttpStatus.CREATED) + .body(mockResponse(UUID.randomUUID().toString(), true)) + .contentType(MediaType.APPLICATION_JSON)); + + this.statPublisher.handleEvent(new ProjectGeneratedEvent(request)); + this.mockServer.verify(); + } + + @Test + void publishDocumentWithInvalidLanguage() { + ProjectRequest request = createProjectRequest(); + request.setGroupId("com.example.acme"); + request.setArtifactId("test"); + request.setType("gradle-project"); + request.setBootVersion("2.1.0.RELEASE"); + request.setDependencies(Arrays.asList("web", "data-jpa")); + request.setLanguage("c"); + + this.mockServer.expect(requestTo("http://example.com/elastic/initializr/request")) + .andExpect(method(HttpMethod.POST)) + .andExpect(json("stat/request-invalid-language.json")) + .andRespond(withStatus(HttpStatus.CREATED) + .body(mockResponse(UUID.randomUUID().toString(), true)) + .contentType(MediaType.APPLICATION_JSON)); + + this.statPublisher.handleEvent(new ProjectGeneratedEvent(request)); + this.mockServer.verify(); + } + + @Test + void publishDocumentWithInvalidJavaVersion() { + ProjectRequest request = createProjectRequest(); + request.setGroupId("com.example.acme"); + request.setArtifactId("test"); + request.setType("gradle-project"); + request.setBootVersion("2.1.0.RELEASE"); + request.setDependencies(Arrays.asList("web", "data-jpa")); + request.setLanguage("java"); + request.setJavaVersion("1.2"); + + this.mockServer.expect(requestTo("http://example.com/elastic/initializr/request")) + .andExpect(method(HttpMethod.POST)) + .andExpect(json("stat/request-invalid-java-version.json")) + .andRespond(withStatus(HttpStatus.CREATED) + .body(mockResponse(UUID.randomUUID().toString(), true)) + .contentType(MediaType.APPLICATION_JSON)); + + this.statPublisher.handleEvent(new ProjectGeneratedEvent(request)); + this.mockServer.verify(); + } + + @Test + void publishDocumentWithInvalidDependencies() { + ProjectRequest request = createProjectRequest(); + request.setGroupId("com.example.acme"); + request.setArtifactId("test"); + request.setType("gradle-project"); + request.setBootVersion("2.1.0.RELEASE"); + request.setDependencies(Arrays.asList("invalid-2", "web", "invalid-1")); + request.setLanguage("java"); + + this.mockServer.expect(requestTo("http://example.com/elastic/initializr/request")) + .andExpect(method(HttpMethod.POST)) + .andExpect(json("stat/request-invalid-dependencies.json")) .andRespond(withStatus(HttpStatus.CREATED) .body(mockResponse(UUID.randomUUID().toString(), true)) .contentType(MediaType.APPLICATION_JSON)); @@ -196,4 +321,39 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests { return properties; } + private static RequestMatcher json(String location) { + return (request) -> { + MockClientHttpRequest mockRequest = (MockClientHttpRequest) request; + assertJsonContent(readJson(location), mockRequest.getBodyAsString()); + }; + } + + private static String readJson(String location) { + try { + try (InputStream in = new ClassPathResource(location).getInputStream()) { + return StreamUtils.copyToString(in, StandardCharsets.UTF_8); + } + } + catch (IOException ex) { + throw new IllegalStateException("Fail to read json from " + location, ex); + } + } + + private static void assertJsonContent(String expected, String actual) { + try { + JSONAssert.assertEquals(expected, actual, new CustomComparator( + JSONCompareMode.STRICT, + Customization.customization("generationTimestamp", (o1, o2) -> { + Instant timestamp = Instant.ofEpochMilli((long) o1); + return timestamp + .isAfter(Instant.now().minus(2, ChronoUnit.SECONDS)) + && timestamp.isBefore(Instant.now()); + }))); + } + catch (JSONException ex) { + throw new AssertionError( + "Failed to parse expected or actual JSON request content", ex); + } + } + } diff --git a/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactoryTests.java b/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactoryTests.java index 3f18ab6d..9ed123d3 100755 --- a/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactoryTests.java +++ b/initializr-actuator/src/test/java/io/spring/initializr/actuate/stat/ProjectRequestDocumentFactoryTests.java @@ -26,6 +26,8 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; /** + * Tests for {@link ProjectRequestDocumentFactory}. + * * @author Stephane Nicoll */ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { @@ -38,18 +40,23 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { ProjectRequest request = createProjectRequest(); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getGenerationTimestamp()).isEqualTo(event.getTimestamp()); - assertThat(document.getRequestIp()).isEqualTo(null); - assertThat(document.getGroupId()).isEqualTo("com.example"); assertThat(document.getArtifactId()).isEqualTo("demo"); - assertThat(document.getPackageName()).isEqualTo("com.example.demo"); - assertThat(document.getBootVersion()).isEqualTo("2.1.1.RELEASE"); + assertThat(document.getBuildSystem()).isEqualTo("maven"); + assertThat(document.getClient()).isNull(); + assertThat(document.getDependencies().getValues()).isEmpty(); + assertThat(document.getDependencies().getId()).isEqualTo("_none"); + assertThat(document.getDependencies().getCount()).isEqualTo(0); + assertThat(document.getErrorState()).isNull(); + assertThat(document.getGenerationTimestamp()).isEqualTo(event.getTimestamp()); + assertThat(document.getGroupId()).isEqualTo("com.example"); assertThat(document.getJavaVersion()).isEqualTo("1.8"); assertThat(document.getLanguage()).isEqualTo("java"); + assertThat(document.getPackageName()).isEqualTo("com.example.demo"); assertThat(document.getPackaging()).isEqualTo("jar"); assertThat(document.getType()).isEqualTo("maven-project"); - assertThat(document.getDependencies()).isEmpty(); - assertValid(document); + assertThat(document.getVersion().getId()).isEqualTo("2.1.1.RELEASE"); + assertThat(document.getVersion().getMajor()).isEqualTo("2"); + assertThat(document.getVersion().getMinor()).isEqualTo("2.1"); } @Test @@ -58,9 +65,8 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("x-forwarded-for", "10.0.0.123"); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getRequestIp()).isEqualTo("10.0.0.123"); - assertThat(document.getRequestIpv4()).isEqualTo("10.0.0.123"); - assertThat(document.getRequestCountry()).isNull(); + assertThat(document.getClient().getIp()).isEqualTo("10.0.0.123"); + assertThat(document.getClient().getCountry()).isNull(); } @Test @@ -69,9 +75,8 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("x-forwarded-for", "2001:db8:a0b:12f0::1"); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getRequestIp()).isEqualTo("2001:db8:a0b:12f0::1"); - assertThat(document.getRequestIpv4()).isNull(); - assertThat(document.getRequestCountry()).isNull(); + assertThat(document.getClient().getIp()).isEqualTo("2001:db8:a0b:12f0::1"); + assertThat(document.getClient().getCountry()).isNull(); } @Test @@ -81,9 +86,8 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("cf-ipcountry", "BE"); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getRequestIp()).isEqualTo("10.0.0.123"); - assertThat(document.getRequestIpv4()).isEqualTo("10.0.0.123"); - assertThat(document.getRequestCountry()).isEqualTo("BE"); + assertThat(document.getClient().getIp()).isEqualTo("10.0.0.123"); + assertThat(document.getClient().getCountry()).isEqualTo("BE"); } @Test @@ -92,9 +96,8 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("cf-connecting-ip", "2001:db8:a0b:12f0::1"); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getRequestIp()).isEqualTo("2001:db8:a0b:12f0::1"); - assertThat(document.getRequestIpv4()).isNull(); - assertThat(document.getRequestCountry()).isNull(); + assertThat(document.getClient().getIp()).isEqualTo("2001:db8:a0b:12f0::1"); + assertThat(document.getClient().getCountry()).isNull(); } @Test @@ -104,9 +107,8 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("x-forwarded-for", "192.168.1.101"); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getRequestIp()).isEqualTo("10.0.0.123"); - assertThat(document.getRequestIpv4()).isEqualTo("10.0.0.123"); - assertThat(document.getRequestCountry()).isNull(); + assertThat(document.getClient().getIp()).isEqualTo("10.0.0.123"); + assertThat(document.getClient().getCountry()).isNull(); } @Test @@ -115,7 +117,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("cf-connecting-ip", "Xx"); // case insensitive ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getRequestCountry()).isNull(); + assertThat(document.getClient().getCountry()).isNull(); } @Test @@ -124,8 +126,8 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("user-agent", "HTTPie/0.8.0"); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getClientId()).isEqualTo("httpie"); - assertThat(document.getClientVersion()).isEqualTo("0.8.0"); + assertThat(document.getClient().getId()).isEqualTo("httpie"); + assertThat(document.getClient().getVersion()).isEqualTo("0.8.0"); } @Test @@ -134,8 +136,8 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.getParameters().put("user-agent", "IntelliJ IDEA"); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getClientId()).isEqualTo("intellijidea"); - assertThat(document.getClientVersion()).isEqualTo(null); + assertThat(document.getClient().getId()).isEqualTo("intellijidea"); + assertThat(document.getClient().getVersion()).isNull(); } @Test @@ -145,8 +147,12 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); assertThat(document.getJavaVersion()).isEqualTo("1.2"); - assertThat(document.isInvalid()).isTrue(); - assertThat(document.isInvalidJavaVersion()).isTrue(); + assertThat(document.getErrorState().isInvalid()).isTrue(); + assertThat(document.getErrorState().getJavaVersion()).isTrue(); + assertThat(document.getErrorState().getLanguage()).isNull(); + assertThat(document.getErrorState().getPackaging()).isNull(); + assertThat(document.getErrorState().getType()).isNull(); + assertThat(document.getErrorState().getDependencies()).isNull(); } @Test @@ -156,8 +162,12 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); assertThat(document.getLanguage()).isEqualTo("c++"); - assertThat(document.isInvalid()).isTrue(); - assertThat(document.isInvalidLanguage()).isTrue(); + assertThat(document.getErrorState().isInvalid()).isTrue(); + assertThat(document.getErrorState().getJavaVersion()).isNull(); + assertThat(document.getErrorState().getLanguage()).isTrue(); + assertThat(document.getErrorState().getPackaging()).isNull(); + assertThat(document.getErrorState().getType()).isNull(); + assertThat(document.getErrorState().getDependencies()).isNull(); } @Test @@ -167,8 +177,12 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); assertThat(document.getPackaging()).isEqualTo("ear"); - assertThat(document.isInvalid()).isTrue(); - assertThat(document.isInvalidPackaging()).isTrue(); + assertThat(document.getErrorState().isInvalid()).isTrue(); + assertThat(document.getErrorState().getJavaVersion()).isNull(); + assertThat(document.getErrorState().getLanguage()).isNull(); + assertThat(document.getErrorState().getPackaging()).isTrue(); + assertThat(document.getErrorState().getType()).isNull(); + assertThat(document.getErrorState().getDependencies()).isNull(); } @Test @@ -178,8 +192,12 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); assertThat(document.getType()).isEqualTo("ant-project"); - assertThat(document.isInvalid()).isTrue(); - assertThat(document.isInvalidType()).isTrue(); + assertThat(document.getErrorState().isInvalid()).isTrue(); + assertThat(document.getErrorState().getJavaVersion()).isNull(); + assertThat(document.getErrorState().getLanguage()).isNull(); + assertThat(document.getErrorState().getPackaging()).isNull(); + assertThat(document.getErrorState().getType()).isTrue(); + assertThat(document.getErrorState().getDependencies()).isNull(); } @Test @@ -188,13 +206,17 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { request.setDependencies(Arrays.asList("web", "invalid", "data-jpa", "invalid-2")); ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.getDependencies().get(0)).isEqualTo("web"); - assertThat(document.getDependencies().get(1)).isEqualTo("data-jpa"); - assertThat(document.getDependencies()).hasSize(2); - assertThat(document.isInvalid()).isTrue(); - assertThat(document.getInvalidDependencies().get(0)).isEqualTo("invalid"); - assertThat(document.getInvalidDependencies().get(1)).isEqualTo("invalid-2"); - assertThat(document.getInvalidDependencies()).hasSize(2); + assertThat(document.getDependencies().getValues()).containsExactly("web", + "data-jpa"); + assertThat(document.getErrorState().isInvalid()).isTrue(); + assertThat(document.getErrorState().getJavaVersion()).isNull(); + assertThat(document.getErrorState().getLanguage()).isNull(); + assertThat(document.getErrorState().getPackaging()).isNull(); + assertThat(document.getErrorState().getType()).isNull(); + assertThat(document.getErrorState().getDependencies()).isNotNull(); + assertThat(document.getErrorState().getDependencies().isInvalid()).isTrue(); + assertThat(document.getErrorState().getDependencies().getValues()) + .containsExactly("invalid", "invalid-2"); } @Test @@ -203,16 +225,13 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests { ProjectFailedEvent event = new ProjectFailedEvent(request, new IllegalStateException("my test message")); ProjectRequestDocument document = this.factory.createDocument(event); - assertThat(document.isInvalid()).isTrue(); - assertThat(document.getErrorMessage()).isEqualTo("my test message"); - } - - private static void assertValid(ProjectRequestDocument document) { - assertThat(document.isInvalid()).isFalse(); - assertThat(document.isInvalidJavaVersion()).isFalse(); - assertThat(document.isInvalidLanguage()).isFalse(); - assertThat(document.isInvalidPackaging()).isFalse(); - assertThat(document.getInvalidDependencies()).isEmpty(); + assertThat(document.getErrorState().isInvalid()).isTrue(); + assertThat(document.getErrorState().getJavaVersion()).isNull(); + assertThat(document.getErrorState().getLanguage()).isNull(); + assertThat(document.getErrorState().getPackaging()).isNull(); + assertThat(document.getErrorState().getType()).isNull(); + assertThat(document.getErrorState().getDependencies()).isNull(); + assertThat(document.getErrorState().getMessage()).isEqualTo("my test message"); } } diff --git a/initializr-actuator/src/test/resources/stat/request-invalid-dependencies.json b/initializr-actuator/src/test/resources/stat/request-invalid-dependencies.json new file mode 100644 index 00000000..ae1b5e8c --- /dev/null +++ b/initializr-actuator/src/test/resources/stat/request-invalid-dependencies.json @@ -0,0 +1,33 @@ +{ + "generationTimestamp": 0, + "type": "gradle-project", + "buildSystem": "gradle", + "groupId": "com.example.acme", + "artifactId": "test", + "javaVersion": "1.8", + "language": "java", + "packaging": "jar", + "packageName": "com.example.acme.test", + "version": { + "id": "2.1.0.RELEASE", + "major": "2", + "minor": "2.1" + }, + "dependencies": { + "id": "web", + "values": [ + "web" + ], + "count": 1 + }, + "errorState": { + "invalid": true, + "dependencies": { + "invalid": true, + "values": [ + "invalid-2", + "invalid-1" + ] + } + } +} \ No newline at end of file diff --git a/initializr-actuator/src/test/resources/stat/request-invalid-java-version.json b/initializr-actuator/src/test/resources/stat/request-invalid-java-version.json new file mode 100644 index 00000000..8f3174b3 --- /dev/null +++ b/initializr-actuator/src/test/resources/stat/request-invalid-java-version.json @@ -0,0 +1,28 @@ +{ + "generationTimestamp": 0, + "type": "gradle-project", + "buildSystem": "gradle", + "groupId": "com.example.acme", + "artifactId": "test", + "javaVersion": "1.2", + "language": "java", + "packaging": "jar", + "packageName": "com.example.acme.test", + "version": { + "id": "2.1.0.RELEASE", + "major": "2", + "minor": "2.1" + }, + "dependencies": { + "id": "data-jpa web", + "values": [ + "web", + "data-jpa" + ], + "count": 2 + }, + "errorState": { + "invalid": true, + "javaVersion": true + } +} \ No newline at end of file diff --git a/initializr-actuator/src/test/resources/stat/request-invalid-language.json b/initializr-actuator/src/test/resources/stat/request-invalid-language.json new file mode 100644 index 00000000..8e470834 --- /dev/null +++ b/initializr-actuator/src/test/resources/stat/request-invalid-language.json @@ -0,0 +1,28 @@ +{ + "generationTimestamp": 0, + "type": "gradle-project", + "buildSystem": "gradle", + "groupId": "com.example.acme", + "artifactId": "test", + "javaVersion": "1.8", + "language": "c", + "packaging": "jar", + "packageName": "com.example.acme.test", + "version": { + "id": "2.1.0.RELEASE", + "major": "2", + "minor": "2.1" + }, + "dependencies": { + "id": "data-jpa web", + "values": [ + "web", + "data-jpa" + ], + "count": 2 + }, + "errorState": { + "invalid": true, + "language": true + } +} \ No newline at end of file diff --git a/initializr-actuator/src/test/resources/stat/request-invalid-type.json b/initializr-actuator/src/test/resources/stat/request-invalid-type.json new file mode 100644 index 00000000..c023eb9a --- /dev/null +++ b/initializr-actuator/src/test/resources/stat/request-invalid-type.json @@ -0,0 +1,27 @@ +{ + "generationTimestamp": 0, + "type": "not-a-type", + "groupId": "com.example.acme", + "artifactId": "test", + "javaVersion": "1.8", + "language": "java", + "packaging": "jar", + "packageName": "com.example.acme.test", + "version": { + "id": "2.1.0.RELEASE", + "major": "2", + "minor": "2.1" + }, + "dependencies": { + "id": "data-jpa web", + "values": [ + "web", + "data-jpa" + ], + "count": 2 + }, + "errorState": { + "invalid": true, + "type": true + } +} \ No newline at end of file diff --git a/initializr-actuator/src/test/resources/stat/request-no-client.json b/initializr-actuator/src/test/resources/stat/request-no-client.json new file mode 100644 index 00000000..4a59c19a --- /dev/null +++ b/initializr-actuator/src/test/resources/stat/request-no-client.json @@ -0,0 +1,24 @@ +{ + "generationTimestamp": 0, + "type": "gradle-project", + "buildSystem": "gradle", + "groupId": "com.example.acme", + "artifactId": "test", + "javaVersion": "1.8", + "language": "java", + "packaging": "jar", + "packageName": "com.example.acme.test", + "version": { + "id": "2.1.0.RELEASE", + "major": "2", + "minor": "2.1" + }, + "dependencies": { + "id": "data-jpa web", + "values": [ + "web", + "data-jpa" + ], + "count": 2 + } +} \ No newline at end of file diff --git a/initializr-actuator/src/test/resources/stat/request-simple.json b/initializr-actuator/src/test/resources/stat/request-simple.json new file mode 100644 index 00000000..170d5e44 --- /dev/null +++ b/initializr-actuator/src/test/resources/stat/request-simple.json @@ -0,0 +1,30 @@ +{ + "generationTimestamp": 0, + "type": "maven-project", + "buildSystem": "maven", + "groupId": "com.example.acme", + "artifactId": "project", + "javaVersion": "1.8", + "language": "java", + "packaging": "jar", + "packageName": "com.example.acme.project", + "version": { + "id": "2.1.1.RELEASE", + "major": "2", + "minor": "2.1" + }, + "client": { + "id": "curl", + "version": "1.2.4", + "ip": "10.0.0.42", + "country": "BE" + }, + "dependencies": { + "id": "data-jpa web", + "values": [ + "web", + "data-jpa" + ], + "count": 2 + } +} \ No newline at end of file