diff --git a/README.md b/README.md index f62e4f4..9a18c43 100644 --- a/README.md +++ b/README.md @@ -321,9 +321,14 @@ Adding a new validator implementation is relatively straight forward and very we The unit test class needs to content. See other implementations for examples. Ensure tests pass! 5. Register your new Implementation type in [Implementations.java](src/main/java/org/creekservice/kafka/test/perf/implementations/Implementations.java). -6. Run `./gradlew` to format your code, perform static analysis and run the tests. + This will ensure the new implementation is included in the docs and included in the functional test +6. Manually add appropriate benchmark methods to [JsonSerdeBenchmark.java](src/main/java/org/creekservice/kafka/test/perf/JsonSerdeBenchmark.java) + and [JsonValidateBenchmark.java](src/main/java/org/creekservice/kafka/test/perf/JsonValidateBenchmark.java). + This is currently manual as JMH library does provide a way to generate these automatically. + There should be one test per supported draft version. See the other methods in these classes for examples. +7. Run `./gradlew` to format your code, perform static analysis and run the tests. Ensure this passes! -7. Raise a PR with your changes. +8. Raise a PR with your changes. [1]: https://github.com/eclipse-vertx/vertx-json-schema diff --git a/build.gradle.kts b/build.gradle.kts index 56aaa57..44a59db 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -134,7 +134,7 @@ tasks.register("runBenchmarks") { dependsOn(pullTask) } -val benchmarkSmokeTest = tasks.register("runBenchmarkSmokeTest") { +val runBenchmarkSmokeTest = tasks.register("runBenchmarkSmokeTest") { classpath = sourceSets.main.get().runtimeClasspath mainClass.set("org.creekservice.kafka.test.perf.BenchmarkRunner") args(listOf( @@ -152,8 +152,8 @@ val benchmarkSmokeTest = tasks.register("runBenchmarkSmokeTest") { dependsOn(pullTask) } -tasks.test { - dependsOn(runFunctionalTests, benchmarkSmokeTest) +tasks.check { + dependsOn(runFunctionalTests, runBenchmarkSmokeTest) } // Dummy / empty tasks required to allow the repo to use the same standard GitHub workflows as other Creek repos: diff --git a/src/main/java/org/creekservice/kafka/test/perf/ImplementationsMain.java b/src/main/java/org/creekservice/kafka/test/perf/ImplementationsMain.java new file mode 100644 index 0000000..5047a9a --- /dev/null +++ b/src/main/java/org/creekservice/kafka/test/perf/ImplementationsMain.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Creek Contributors (https://github.com/creek-service) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.creekservice.kafka.test.perf; + +import org.creekservice.kafka.test.perf.util.ImplsJsonFormatter; + +/** Main entry point for getting information about the implementations under test */ +public final class ImplementationsMain { + + private ImplementationsMain() {} + + public static void main(final String[] args) { + System.out.println(ImplsJsonFormatter.implDetailsAsJson()); + } +} diff --git a/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java b/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java index 67c6a52..18c41a6 100644 --- a/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java +++ b/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java @@ -18,7 +18,9 @@ import static java.util.Objects.requireNonNull; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Set; +import java.util.TreeSet; import org.creekservice.kafka.test.perf.model.TestModel; import org.creekservice.kafka.test.perf.testsuite.AdditionalSchemas; import org.creekservice.kafka.test.perf.testsuite.SchemaSpec; @@ -56,9 +58,9 @@ interface JsonValidator { } class MetaData { - public final String longName; - public final String shortName; - public final Set supported; + private final String longName; + private final String shortName; + private final Set supported; /** * @param longName a more expressive name. @@ -80,6 +82,21 @@ public MetaData( } } + @JsonProperty("longName") + public String longName() { + return longName; + } + + @JsonProperty("shortName") + public String shortName() { + return shortName; + } + + @JsonProperty("supported") + public Set supported() { + return new TreeSet<>(supported); + } + // Final, empty finalize method stops spotbugs CT_CONSTRUCTOR_THROW // Can be moved to base type after https://github.com/spotbugs/spotbugs/issues/2665 @Override @@ -99,7 +116,7 @@ protected final void finalize() {} * @return {@code true} if the impl supports the supplied {@code spec}. */ default boolean supports(final SchemaSpec spec) { - return metadata().supported.contains(spec); + return metadata().supported().contains(spec); } /** diff --git a/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/PerDraftSummary.java b/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/PerDraftSummary.java index 8d793b7..5250bed 100644 --- a/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/PerDraftSummary.java +++ b/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/PerDraftSummary.java @@ -69,7 +69,7 @@ private Stream> buildResults( results.visit( (spec, result) -> { output.computeIfAbsent( - new Key(spec, impl.metadata().shortName), k -> new Builder()) + new Key(spec, impl.metadata().shortName()), k -> new Builder()) .add(result, spec); }); return output.entrySet().stream(); diff --git a/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/Summary.java b/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/Summary.java index 3123ef5..a7b52c2 100644 --- a/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/Summary.java +++ b/src/main/java/org/creekservice/kafka/test/perf/testsuite/output/Summary.java @@ -80,7 +80,7 @@ private static Map> buildCounts( results.entrySet().stream() .collect( toMap( - e -> e.getKey().metadata().shortName, + e -> e.getKey().metadata().shortName(), e -> resultCounts(e.getValue()))); counts.values() diff --git a/src/main/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatter.java b/src/main/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatter.java new file mode 100644 index 0000000..ff44359 --- /dev/null +++ b/src/main/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatter.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Creek Contributors (https://github.com/creek-service) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.creekservice.kafka.test.perf.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import java.util.List; +import java.util.stream.Collectors; +import org.creekservice.kafka.test.perf.implementations.Implementation; +import org.creekservice.kafka.test.perf.implementations.Implementations; + +public final class ImplsJsonFormatter { + + public static String implDetailsAsJson() { + return implDetailsAsJson(Implementations.all()); + } + + static String implDetailsAsJson(final List impls) { + final ObjectMapper mapper = JsonMapper.builder().build(); + + final List metadata = + impls.stream().map(Implementation::metadata).collect(Collectors.toList()); + + try { + return mapper.writeValueAsString(metadata); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private ImplsJsonFormatter() {} +} diff --git a/src/test/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatterTest.java b/src/test/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatterTest.java new file mode 100644 index 0000000..2371d47 --- /dev/null +++ b/src/test/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatterTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2023 Creek Contributors (https://github.com/creek-service) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.creekservice.kafka.test.perf.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Set; +import org.creekservice.kafka.test.perf.implementations.Implementation; +import org.creekservice.kafka.test.perf.testsuite.SchemaSpec; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ImplsJsonFormatterTest { + + private static final Implementation.MetaData MD_A = + new Implementation.MetaData( + "Implementation A", + "Impl_A", + Set.of(SchemaSpec.DRAFT_2019_09, SchemaSpec.DRAFT_04)); + + private static final Implementation.MetaData MD_B = + new Implementation.MetaData("Implementation B", "Impl_B", Set.of(SchemaSpec.DRAFT_07)); + + @Mock private Implementation implA; + + @Mock private Implementation implB; + + @BeforeEach + void setUp() { + when(implA.metadata()).thenReturn(MD_A); + when(implB.metadata()).thenReturn(MD_B); + } + + @Test + void shouldFormatAsJson() { + // Given: + + // When: + final String json = ImplsJsonFormatter.implDetailsAsJson(List.of(implA, implB)); + + // Then: + assertThat( + json, + is( + "[{\"longName\":\"Implementation" + + " A\",\"shortName\":\"Impl_A\",\"supported\":[\"DRAFT_04\",\"DRAFT_2019_09\"]},{\"longName\":\"Implementation" + + " B\",\"shortName\":\"Impl_B\",\"supported\":[\"DRAFT_07\"]}]")); + } +}