From c1f00de32a1ccd3dceb7b7ca6e3ccf2a61b0526d Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 28 Aug 2022 10:52:03 +0200 Subject: [PATCH] #336: Add provides tags for ServiceLoader --- .../specobject/src/main/java/module-info.java | 7 +- .../markdown/src/main/java/module-info.java | 7 +- .../specobject/src/main/java/module-info.java | 11 +- importer/tag/src/main/java/module-info.java | 6 +- importer/zip/src/main/java/module-info.java | 8 +- .../TestAllServicesAvailable.java | 132 ++++++++++++++++++ reporter/aspec/src/main/java/module-info.java | 7 +- reporter/html/src/main/java/module-info.java | 9 +- .../plaintext/src/main/java/module-info.java | 7 +- 9 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 product/src/test/java/org/itsallcode/openfasttrace/TestAllServicesAvailable.java diff --git a/exporter/specobject/src/main/java/module-info.java b/exporter/specobject/src/main/java/module-info.java index 8eaff6ff..1bbbb17a 100644 --- a/exporter/specobject/src/main/java/module-info.java +++ b/exporter/specobject/src/main/java/module-info.java @@ -1,12 +1,15 @@ /** * This provides an exporter for the SpecObject XML format. + * + * @provides org.itsallcode.openfasttrace.api.exporter.ExporterFactory */ module org.itsallcode.openfasttrace.exporter.specobject { - exports org.itsallcode.openfasttrace.exporter.specobject; - requires java.logging; requires java.xml; requires org.itsallcode.openfasttrace.api; requires org.itsallcode.openfasttrace.exporter.common; + + provides org.itsallcode.openfasttrace.api.exporter.ExporterFactory + with org.itsallcode.openfasttrace.exporter.specobject.SpecobjectExporterFactory; } diff --git a/importer/markdown/src/main/java/module-info.java b/importer/markdown/src/main/java/module-info.java index 68d2c02f..a4c289dd 100644 --- a/importer/markdown/src/main/java/module-info.java +++ b/importer/markdown/src/main/java/module-info.java @@ -1,10 +1,13 @@ /** * This provides an importer for the MarkDown format. + * + * @provides org.itsallcode.openfasttrace.api.importer.ImporterFactory */ module org.itsallcode.openfasttrace.importer.markdown { - exports org.itsallcode.openfasttrace.importer.markdown; - requires java.logging; requires transitive org.itsallcode.openfasttrace.api; + + provides org.itsallcode.openfasttrace.api.importer.ImporterFactory + with org.itsallcode.openfasttrace.importer.markdown.MarkdownImporterFactory; } diff --git a/importer/specobject/src/main/java/module-info.java b/importer/specobject/src/main/java/module-info.java index 9100acd2..650bf26b 100644 --- a/importer/specobject/src/main/java/module-info.java +++ b/importer/specobject/src/main/java/module-info.java @@ -1,15 +1,14 @@ /** * This provides an importer for the SpecObject XML format. + * + * @provides org.itsallcode.openfasttrace.api.importer.ImporterFactory */ module org.itsallcode.openfasttrace.importer.specobject { - exports org.itsallcode.openfasttrace.importer.specobject; - exports org.itsallcode.openfasttrace.importer.specobject.handler; - exports org.itsallcode.openfasttrace.importer.specobject.xml; - exports org.itsallcode.openfasttrace.importer.specobject.xml.tree; - exports org.itsallcode.openfasttrace.importer.specobject.xml.event; - requires java.logging; requires transitive java.xml; requires transitive org.itsallcode.openfasttrace.api; + + provides org.itsallcode.openfasttrace.api.importer.ImporterFactory + with org.itsallcode.openfasttrace.importer.specobject.SpecobjectImporterFactory; } diff --git a/importer/tag/src/main/java/module-info.java b/importer/tag/src/main/java/module-info.java index 4c9f9537..9f813098 100644 --- a/importer/tag/src/main/java/module-info.java +++ b/importer/tag/src/main/java/module-info.java @@ -1,10 +1,14 @@ /** * This provides an importer for coverage tags. + * + * @provides org.itsallcode.openfasttrace.api.importer.ImporterFactory */ module org.itsallcode.openfasttrace.importer.tag { - exports org.itsallcode.openfasttrace.importer.tag; requires java.logging; requires transitive org.itsallcode.openfasttrace.api; + + provides org.itsallcode.openfasttrace.api.importer.ImporterFactory + with org.itsallcode.openfasttrace.importer.tag.TagImporterFactory; } diff --git a/importer/zip/src/main/java/module-info.java b/importer/zip/src/main/java/module-info.java index 26cf618a..46e48463 100644 --- a/importer/zip/src/main/java/module-info.java +++ b/importer/zip/src/main/java/module-info.java @@ -1,10 +1,12 @@ /** * This provides an importer for the ZIP files. + * + * @provides org.itsallcode.openfasttrace.api.importer.ImporterFactory */ module org.itsallcode.openfasttrace.importer.zip { - exports org.itsallcode.openfasttrace.importer.zip; - exports org.itsallcode.openfasttrace.importer.zip.input; - requires transitive org.itsallcode.openfasttrace.api; + + provides org.itsallcode.openfasttrace.api.importer.ImporterFactory + with org.itsallcode.openfasttrace.importer.zip.ZipFileImporterFactory; } diff --git a/product/src/test/java/org/itsallcode/openfasttrace/TestAllServicesAvailable.java b/product/src/test/java/org/itsallcode/openfasttrace/TestAllServicesAvailable.java new file mode 100644 index 00000000..7284d65c --- /dev/null +++ b/product/src/test/java/org/itsallcode/openfasttrace/TestAllServicesAvailable.java @@ -0,0 +1,132 @@ +package org.itsallcode.openfasttrace; + +import static java.util.stream.Collectors.toList; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.withSettings; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.ServiceLoader; +import java.util.stream.Stream; + +import org.itsallcode.openfasttrace.api.core.Newline; +import org.itsallcode.openfasttrace.api.core.Trace; +import org.itsallcode.openfasttrace.api.exporter.Exporter; +import org.itsallcode.openfasttrace.api.exporter.ExporterContext; +import org.itsallcode.openfasttrace.api.exporter.ExporterFactory; +import org.itsallcode.openfasttrace.api.importer.ImportEventListener; +import org.itsallcode.openfasttrace.api.importer.Importer; +import org.itsallcode.openfasttrace.api.importer.ImporterContext; +import org.itsallcode.openfasttrace.api.importer.ImporterFactory; +import org.itsallcode.openfasttrace.api.importer.input.InputFile; +import org.itsallcode.openfasttrace.api.importer.input.RealFileInput; +import org.itsallcode.openfasttrace.api.report.Reportable; +import org.itsallcode.openfasttrace.api.report.ReporterContext; +import org.itsallcode.openfasttrace.api.report.ReporterFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.Answers; + +class TestAllServicesAvailable +{ + private static List importerFactories; + private static List exporterFactories; + private static List reporterFactories; + + @BeforeAll + static void loadFactories() + { + importerFactories = loadImporterFactories(); + exporterFactories = loadExporterFactories(); + reporterFactories = loadReporterFactories(); + } + + private static List loadImporterFactories() + { + final ServiceLoader loader = ServiceLoader.load(ImporterFactory.class); + final ImporterContext contextMock = mock(ImporterContext.class, + withSettings().defaultAnswer(Answers.RETURNS_DEEP_STUBS)); + final List importerFactories = loader.stream() // + .map(ServiceLoader.Provider::get).collect(toList()); + importerFactories.forEach(factory -> factory.init(contextMock)); + return importerFactories; + } + + private static List loadExporterFactories() + { + final ServiceLoader loader = ServiceLoader.load(ExporterFactory.class); + final ExporterContext contextMock = mock(ExporterContext.class, + withSettings().defaultAnswer(Answers.RETURNS_DEEP_STUBS)); + final List exporterFactories = loader.stream() // + .map(ServiceLoader.Provider::get).collect(toList()); + exporterFactories.forEach(factory -> factory.init(contextMock)); + return exporterFactories; + } + + private static List loadReporterFactories() + { + final ServiceLoader loader = ServiceLoader.load(ReporterFactory.class); + final ReporterContext contextMock = mock(ReporterContext.class, + withSettings().defaultAnswer(Answers.RETURNS_DEEP_STUBS)); + final List reporterFactories = loader.stream() // + .map(ServiceLoader.Provider::get).collect(toList()); + reporterFactories.forEach(factory -> factory.init(contextMock)); + return reporterFactories; + } + + @ParameterizedTest + @CsvSource( + { "md", "oreqm", "java", "zip" }) + void importerAvailable(final String suffix) + { + final InputFile file = RealFileInput.forPath(Paths.get("file." + suffix)); + final Optional factory = importerFactories.stream() // + .filter(f -> f.supportsFile(file)) // + .findAny(); + if (factory.isEmpty()) + { + fail("No importer found for file name suffix '" + suffix + "'"); + } + final Importer importer = factory.get().createImporter(file, mock(ImportEventListener.class)); + assertNotNull(importer); + } + + @ParameterizedTest + @CsvSource( + { "specobject" }) + void exporterAvailable(final String format) + { + final Optional factory = exporterFactories.stream() // + .filter(f -> f.supportsFormat(format)) // + .findAny(); + if (factory.isEmpty()) + { + fail("No exporter found for format '" + format + "'"); + } + final Exporter exporter = factory.get().createExporter(Path.of("file"), format, StandardCharsets.UTF_8, + Newline.UNIX, Stream.empty()); + assertNotNull(exporter); + } + + @ParameterizedTest + @CsvSource( + { "aspec", "html", "plain" }) + void reporterAvailable(final String format) + { + final Optional factory = reporterFactories.stream() // + .filter(f -> f.supportsFormat(format)) // + .findAny(); + if (factory.isEmpty()) + { + fail("No reporter found for format '" + format + "'"); + } + final Reportable reportable = factory.get().createImporter(Trace.builder().build()); + assertNotNull(reportable); + } +} diff --git a/reporter/aspec/src/main/java/module-info.java b/reporter/aspec/src/main/java/module-info.java index d3a0d6be..83565455 100644 --- a/reporter/aspec/src/main/java/module-info.java +++ b/reporter/aspec/src/main/java/module-info.java @@ -1,12 +1,15 @@ /** * This provides an report generator for the Aspec format. + * + * @provides org.itsallcode.openfasttrace.api.report.ReporterFactory */ module org.itsallcode.openfasttrace.report.aspec { - exports org.itsallcode.openfasttrace.report.aspec; - requires java.xml; requires java.logging; requires org.itsallcode.openfasttrace.api; requires org.itsallcode.openfasttrace.exporter.common; + + provides org.itsallcode.openfasttrace.api.report.ReporterFactory + with org.itsallcode.openfasttrace.report.aspec.ASpecReporterFactory; } diff --git a/reporter/html/src/main/java/module-info.java b/reporter/html/src/main/java/module-info.java index f4087a14..c27dad5c 100644 --- a/reporter/html/src/main/java/module-info.java +++ b/reporter/html/src/main/java/module-info.java @@ -1,11 +1,12 @@ /** * This provides an report generator for the HTML format. + * + * @provides org.itsallcode.openfasttrace.api.report.ReporterFactory */ module org.itsallcode.openfasttrace.report.html { - exports org.itsallcode.openfasttrace.report.html; - exports org.itsallcode.openfasttrace.report.html.view; - exports org.itsallcode.openfasttrace.report.html.view.html; - requires transitive org.itsallcode.openfasttrace.api; + + provides org.itsallcode.openfasttrace.api.report.ReporterFactory + with org.itsallcode.openfasttrace.report.html.HtmlReporterFactory; } diff --git a/reporter/plaintext/src/main/java/module-info.java b/reporter/plaintext/src/main/java/module-info.java index 3cf71adb..03b67636 100644 --- a/reporter/plaintext/src/main/java/module-info.java +++ b/reporter/plaintext/src/main/java/module-info.java @@ -1,9 +1,12 @@ /** * This provides an report generator for the plain text format. + * + * @provides org.itsallcode.openfasttrace.api.report.ReporterFactory */ module org.itsallcode.openfasttrace.report.plaintext { - exports org.itsallcode.openfasttrace.report.plaintext; - requires transitive org.itsallcode.openfasttrace.api; + + provides org.itsallcode.openfasttrace.api.report.ReporterFactory + with org.itsallcode.openfasttrace.report.plaintext.PlaintextReporterFactory; }