diff --git a/README.md b/README.md index 6739c9d..6af6b6d 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,15 @@ buildscript { ``` +## Testing the plugin + +The plugin is tested using integration tests that exercise example packages +in the `examples` directory. Failure cases are placed in `examples/failure-cases`. +Integration tests are executed with Gradle using the `it` task. Note that this +task requires publishing the Smithy Gradle plugin to your Maven local +repository. + + ## License This library is licensed under the Apache 2.0 License. diff --git a/build.gradle.kts b/build.gradle.kts index 8eb7658..d87c9e5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { testRuntime("org.junit.jupiter:junit-jupiter-engine:5.4.0") testImplementation("org.junit.jupiter:junit-jupiter-params:5.4.0") testImplementation("org.hamcrest:hamcrest:2.1") + testImplementation("commons-io:commons-io:2.6") } /* @@ -78,8 +79,26 @@ tasks.jar { } } -// Always run javadoc after build. -tasks["build"].finalizedBy(tasks["javadoc"]) +sourceSets { + create("it") { + java.srcDir("src/it/java") + resources.srcDir("src/it/resources") + compileClasspath += sourceSets["main"].output + configurations["testRuntimeClasspath"] + runtimeClasspath += output + compileClasspath + sourceSets["test"].runtimeClasspath + } +} + +tasks.register("it") { + useJUnitPlatform() + testClassesDirs = sourceSets["it"].output.classesDirs + classpath = sourceSets["it"].compileClasspath + sourceSets["it"].runtimeClasspath + maxParallelForks = Runtime.getRuntime().availableProcessors() / 2 +} + +tasks["it"].dependsOn("publishToMavenLocal") + +// Always run javadoc and integration tests after build. +tasks["build"].finalizedBy(tasks["javadoc"]).finalizedBy(tasks["it"]) /* * Maven @@ -115,6 +134,7 @@ publishing { */ tasks["checkstyleTest"].enabled = false +tasks["checkstyleIt"].enabled = false /* * Code coverage @@ -144,6 +164,7 @@ tasks.jacocoTestReport { // We don't need to lint tests. tasks["spotbugsTest"].enabled = false +tasks["spotbugsIt"].enabled = false // Configure the bug filter for spotbugs. tasks.withType(com.github.spotbugs.SpotBugsTask::class) { diff --git a/examples/disable-jar/build.gradle.kts b/examples/disable-jar/build.gradle.kts new file mode 100644 index 0000000..e30392d --- /dev/null +++ b/examples/disable-jar/build.gradle.kts @@ -0,0 +1,27 @@ +// This example builds Smithy models but does not create a JAR. + +plugins { + java +} + +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath("software.amazon.smithy:smithy-gradle-plugin:0.0.1") + } +} + +apply(plugin = "software.amazon.smithy") + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:0.4.1") +} + +tasks["jar"].enabled = false diff --git a/examples/disable-jar/model/main.smithy b/examples/disable-jar/model/main.smithy new file mode 100644 index 0000000..36da160 --- /dev/null +++ b/examples/disable-jar/model/main.smithy @@ -0,0 +1,5 @@ +namespace smithy.example + +structure Example { + foo: String +} diff --git a/examples/disable-jar/settings.gradle.kts b/examples/disable-jar/settings.gradle.kts new file mode 100644 index 0000000..0ecb3b8 --- /dev/null +++ b/examples/disable-jar/settings.gradle.kts @@ -0,0 +1,7 @@ +rootProject.name = "disable-jar" + +pluginManagement { + repositories { + mavenLocal() + } +} diff --git a/examples/disable-jar/smithy-build.json b/examples/disable-jar/smithy-build.json new file mode 100644 index 0000000..703ffb7 --- /dev/null +++ b/examples/disable-jar/smithy-build.json @@ -0,0 +1,3 @@ +{ + "version": "1.0" +} diff --git a/examples/failure-cases/invalid-projection/build.gradle.kts b/examples/failure-cases/invalid-projection/build.gradle.kts new file mode 100644 index 0000000..ffe4327 --- /dev/null +++ b/examples/failure-cases/invalid-projection/build.gradle.kts @@ -0,0 +1,29 @@ +// This example attempts to use an invalid projection. The build will fail. + +plugins { + java +} + +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath("software.amazon.smithy:smithy-gradle-plugin:0.0.1") + } +} + +apply(plugin = "software.amazon.smithy") + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:0.4.1") +} + +configure { + projection = "invalid" +} diff --git a/examples/failure-cases/invalid-projection/model/main.smithy b/examples/failure-cases/invalid-projection/model/main.smithy new file mode 100644 index 0000000..d4b3bee --- /dev/null +++ b/examples/failure-cases/invalid-projection/model/main.smithy @@ -0,0 +1,5 @@ +namespace smithy.example + +structure Foo { + foo: String +} diff --git a/test-kotlin/settings.gradle.kts b/examples/failure-cases/invalid-projection/settings.gradle.kts similarity index 68% rename from test-kotlin/settings.gradle.kts rename to examples/failure-cases/invalid-projection/settings.gradle.kts index a0f06a9..9672e10 100644 --- a/test-kotlin/settings.gradle.kts +++ b/examples/failure-cases/invalid-projection/settings.gradle.kts @@ -1,4 +1,4 @@ -rootProject.name = "test" +rootProject.name = "projection" pluginManagement { repositories { diff --git a/test-kotlin/smithy-build.json b/examples/failure-cases/invalid-projection/smithy-build.json similarity index 72% rename from test-kotlin/smithy-build.json rename to examples/failure-cases/invalid-projection/smithy-build.json index d9e773b..556e923 100644 --- a/test-kotlin/smithy-build.json +++ b/examples/failure-cases/invalid-projection/smithy-build.json @@ -1,6 +1,6 @@ { "version": "1.0", "projections": { - "trimmed": {} + "foo": {} } } diff --git a/examples/failure-cases/missing-runtime-dependency/build.gradle.kts b/examples/failure-cases/missing-runtime-dependency/build.gradle.kts new file mode 100644 index 0000000..15658ae --- /dev/null +++ b/examples/failure-cases/missing-runtime-dependency/build.gradle.kts @@ -0,0 +1,39 @@ +// This example creates a projected version of the model, but because the +// projected model references traits from another package and that package +// is not part of the runtime dependencies, the build will fail when the +// plugin validates the JAR with Smithy model discovery. + +plugins { + java +} + +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath("software.amazon.smithy:smithy-gradle-plugin:0.0.1") + + // This dependency is required to build the model. + classpath("software.amazon.smithy:smithy-aws-traits:0.4.1") + } +} + +apply(plugin = "software.amazon.smithy") + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:0.4.1") + + // This dependency is used in the projected model, so it's required here too. + // This should fail to build since this is missing. + //implementation("software.amazon.smithy:smithy-aws-traits:0.4.1") +} + +configure { + projection = "foo" +} diff --git a/test-kotlin/src/main/smithy/baz.smithy b/examples/failure-cases/missing-runtime-dependency/model/main.smithy similarity index 100% rename from test-kotlin/src/main/smithy/baz.smithy rename to examples/failure-cases/missing-runtime-dependency/model/main.smithy diff --git a/examples/failure-cases/missing-runtime-dependency/settings.gradle.kts b/examples/failure-cases/missing-runtime-dependency/settings.gradle.kts new file mode 100644 index 0000000..9672e10 --- /dev/null +++ b/examples/failure-cases/missing-runtime-dependency/settings.gradle.kts @@ -0,0 +1,7 @@ +rootProject.name = "projection" + +pluginManagement { + repositories { + mavenLocal() + } +} diff --git a/examples/failure-cases/missing-runtime-dependency/smithy-build.json b/examples/failure-cases/missing-runtime-dependency/smithy-build.json new file mode 100644 index 0000000..556e923 --- /dev/null +++ b/examples/failure-cases/missing-runtime-dependency/smithy-build.json @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "projections": { + "foo": {} + } +} diff --git a/examples/multiple-sources/build.gradle.kts b/examples/multiple-sources/build.gradle.kts new file mode 100644 index 0000000..29da6f8 --- /dev/null +++ b/examples/multiple-sources/build.gradle.kts @@ -0,0 +1,28 @@ +// This example pulls Smithy models from the following locations: +// - model/ +// - src/main/smithy/ +// - src/main/resources/META-INF/smithy + +plugins { + java +} + +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath("software.amazon.smithy:smithy-gradle-plugin:0.0.1") + } +} + +apply(plugin = "software.amazon.smithy") + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:0.4.1") +} diff --git a/examples/multiple-sources/model/a.smithy b/examples/multiple-sources/model/a.smithy new file mode 100644 index 0000000..7753e40 --- /dev/null +++ b/examples/multiple-sources/model/a.smithy @@ -0,0 +1,3 @@ +namespace smithy.example + +structure A {} diff --git a/examples/multiple-sources/settings.gradle.kts b/examples/multiple-sources/settings.gradle.kts new file mode 100644 index 0000000..d6753cc --- /dev/null +++ b/examples/multiple-sources/settings.gradle.kts @@ -0,0 +1,7 @@ +rootProject.name = "multiple-sources" + +pluginManagement { + repositories { + mavenLocal() + } +} diff --git a/examples/multiple-sources/src/main/resources/META-INF/smithy/c.smithy b/examples/multiple-sources/src/main/resources/META-INF/smithy/c.smithy new file mode 100644 index 0000000..1a8ed35 --- /dev/null +++ b/examples/multiple-sources/src/main/resources/META-INF/smithy/c.smithy @@ -0,0 +1,5 @@ +namespace smithy.example + +structure C { + foo: String +} diff --git a/examples/multiple-sources/src/main/smithy/b.smithy b/examples/multiple-sources/src/main/smithy/b.smithy new file mode 100644 index 0000000..a52c9d6 --- /dev/null +++ b/examples/multiple-sources/src/main/smithy/b.smithy @@ -0,0 +1,5 @@ +namespace smithy.example + +structure B { + foo: String +} diff --git a/examples/projection/build.gradle.kts b/examples/projection/build.gradle.kts new file mode 100644 index 0000000..6e072f0 --- /dev/null +++ b/examples/projection/build.gradle.kts @@ -0,0 +1,35 @@ +// This example places a projected version of the model into the JAR. + +plugins { + java +} + +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath("software.amazon.smithy:smithy-gradle-plugin:0.0.1") + + // This dependency is required to build the model. + classpath("software.amazon.smithy:smithy-aws-traits:0.4.1") + } +} + +apply(plugin = "software.amazon.smithy") + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:0.4.1") + + // This dependency is used in the projected model, so it's requird here too. + implementation("software.amazon.smithy:smithy-aws-traits:0.4.1") +} + +configure { + projection = "foo" +} diff --git a/examples/projection/model/main.smithy b/examples/projection/model/main.smithy new file mode 100644 index 0000000..225fc26 --- /dev/null +++ b/examples/projection/model/main.smithy @@ -0,0 +1,8 @@ +namespace smithy.example + +structure Baz { + foo: String +} + +@aws.api#unsignedPayload +operation Foo() diff --git a/examples/projection/settings.gradle.kts b/examples/projection/settings.gradle.kts new file mode 100644 index 0000000..9672e10 --- /dev/null +++ b/examples/projection/settings.gradle.kts @@ -0,0 +1,7 @@ +rootProject.name = "projection" + +pluginManagement { + repositories { + mavenLocal() + } +} diff --git a/examples/projection/smithy-build.json b/examples/projection/smithy-build.json new file mode 100644 index 0000000..556e923 --- /dev/null +++ b/examples/projection/smithy-build.json @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "projections": { + "foo": {} + } +} diff --git a/test-kotlin/build.gradle.kts b/examples/source-projection/build.gradle.kts similarity index 85% rename from test-kotlin/build.gradle.kts rename to examples/source-projection/build.gradle.kts index 64d1d92..b591072 100644 --- a/test-kotlin/build.gradle.kts +++ b/examples/source-projection/build.gradle.kts @@ -1,3 +1,5 @@ +// This example builds the model and places it in the JAR. + plugins { java } @@ -8,7 +10,6 @@ buildscript { } dependencies { classpath("software.amazon.smithy:smithy-gradle-plugin:0.0.1") - //classpath("software.amazon.smithy:smithy-aws-traits:0.4.1") } } @@ -16,6 +17,7 @@ apply(plugin = "software.amazon.smithy") repositories { mavenLocal() + mavenCentral() } dependencies { @@ -25,7 +27,7 @@ dependencies { configure { // Uncomment this to use a custom projection when building the JAR. - // projection = "trimmed" + // projection = "foo" } // Uncomment to disable creating a JAR. diff --git a/examples/source-projection/model/main.smithy b/examples/source-projection/model/main.smithy new file mode 100644 index 0000000..225fc26 --- /dev/null +++ b/examples/source-projection/model/main.smithy @@ -0,0 +1,8 @@ +namespace smithy.example + +structure Baz { + foo: String +} + +@aws.api#unsignedPayload +operation Foo() diff --git a/examples/source-projection/settings.gradle.kts b/examples/source-projection/settings.gradle.kts new file mode 100644 index 0000000..2d646e3 --- /dev/null +++ b/examples/source-projection/settings.gradle.kts @@ -0,0 +1,7 @@ +rootProject.name = "source-projection" + +pluginManagement { + repositories { + mavenLocal() + } +} diff --git a/examples/source-projection/smithy-build.json b/examples/source-projection/smithy-build.json new file mode 100644 index 0000000..556e923 --- /dev/null +++ b/examples/source-projection/smithy-build.json @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "projections": { + "foo": {} + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..f97ebb7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +org.gradle.parallel=true diff --git a/src/it/java/software/amazon/smithy/gradle/DisableJarTest.java b/src/it/java/software/amazon/smithy/gradle/DisableJarTest.java new file mode 100644 index 0000000..501022e --- /dev/null +++ b/src/it/java/software/amazon/smithy/gradle/DisableJarTest.java @@ -0,0 +1,26 @@ +package software.amazon.smithy.gradle; + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.Test; + +public class DisableJarTest { + @Test + public void testProjection() { + Utils.withCopy("disable-jar", buildDir -> { + BuildResult result = GradleRunner.create() + .withProjectDir(buildDir) + .withArguments("build") + .build(); + + Utils.assertSmithyBuildRan(result); + Utils.assertValidationDidNotRun(result); + Utils.assertArtifactsCreated(buildDir, + "build/smithyprojections/disable-jar/source/build-info/smithy-build-info.json", + "build/smithyprojections/disable-jar/source/model/model.json", + "build/smithyprojections/disable-jar/source/sources/main.smithy", + "build/smithyprojections/disable-jar/source/sources/manifest"); + Utils.assertArtifactsNotCreated(buildDir, "build/libs/disable-jar.jar"); + }); + } +} diff --git a/src/it/java/software/amazon/smithy/gradle/InvalidProjectionTest.java b/src/it/java/software/amazon/smithy/gradle/InvalidProjectionTest.java new file mode 100644 index 0000000..aee5080 --- /dev/null +++ b/src/it/java/software/amazon/smithy/gradle/InvalidProjectionTest.java @@ -0,0 +1,21 @@ +package software.amazon.smithy.gradle; + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class InvalidProjectionTest { + @Test + public void testProjection() { + Utils.withCopy("failure-cases/invalid-projection", buildDir -> { + BuildResult result = GradleRunner.create() + .withProjectDir(buildDir) + .withArguments("build") + .buildAndFail(); + + Assertions.assertTrue(result.getOutput().contains("Smithy projection `invalid` not found")); + Utils.assertArtifactsNotCreated(buildDir, "build/libs/invalid-projection.jar"); + }); + } +} diff --git a/src/it/java/software/amazon/smithy/gradle/MissingRuntimeDependencyTest.java b/src/it/java/software/amazon/smithy/gradle/MissingRuntimeDependencyTest.java new file mode 100644 index 0000000..88b7022 --- /dev/null +++ b/src/it/java/software/amazon/smithy/gradle/MissingRuntimeDependencyTest.java @@ -0,0 +1,20 @@ +package software.amazon.smithy.gradle; + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class MissingRuntimeDependencyTest { + @Test + public void testProjection() { + Utils.withCopy("failure-cases/missing-runtime-dependency", buildDir -> { + BuildResult result = GradleRunner.create() + .withProjectDir(buildDir) + .withArguments("build") + .buildAndFail(); + + Assertions.assertTrue(result.getOutput().contains("Unable to resolve trait")); + }); + } +} diff --git a/src/it/java/software/amazon/smithy/gradle/MultipleSourcesTest.java b/src/it/java/software/amazon/smithy/gradle/MultipleSourcesTest.java new file mode 100644 index 0000000..885a4eb --- /dev/null +++ b/src/it/java/software/amazon/smithy/gradle/MultipleSourcesTest.java @@ -0,0 +1,34 @@ +package software.amazon.smithy.gradle; + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.Test; + +public class MultipleSourcesTest { + @Test + public void testProjection() { + Utils.withCopy("multiple-sources", buildDir -> { + BuildResult result = GradleRunner.create() + .withProjectDir(buildDir) + .withArguments("build") + .build(); + + Utils.assertSmithyBuildRan(result); + Utils.assertValidationRan(result); + Utils.assertArtifactsCreated(buildDir, + "build/smithyprojections/multiple-sources/source/build-info/smithy-build-info.json", + "build/smithyprojections/multiple-sources/source/model/model.json", + "build/smithyprojections/multiple-sources/source/sources/a.smithy", + "build/smithyprojections/multiple-sources/source/sources/b.smithy", + "build/smithyprojections/multiple-sources/source/sources/c.smithy", + "build/smithyprojections/multiple-sources/source/sources/manifest", + "build/libs/multiple-sources.jar"); + Utils.assertJarContains(buildDir, + "build/libs/multiple-sources.jar", + "META-INF/smithy/manifest", + "META-INF/smithy/a.smithy", + "META-INF/smithy/b.smithy", + "META-INF/smithy/c.smithy"); + }); + } +} diff --git a/src/it/java/software/amazon/smithy/gradle/ProjectionTest.java b/src/it/java/software/amazon/smithy/gradle/ProjectionTest.java new file mode 100644 index 0000000..f20b7d3 --- /dev/null +++ b/src/it/java/software/amazon/smithy/gradle/ProjectionTest.java @@ -0,0 +1,47 @@ +package software.amazon.smithy.gradle;/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.Test; + +public class ProjectionTest { + @Test + public void testProjection() { + Utils.withCopy("projection", buildDir -> { + BuildResult result = GradleRunner.create() + .withProjectDir(buildDir) + .withArguments("build") + .build(); + + Utils.assertSmithyBuildRan(result); + Utils.assertValidationRan(result); + Utils.assertArtifactsCreated(buildDir, + "build/smithyprojections/projection/source/build-info/smithy-build-info.json", + "build/smithyprojections/projection/source/model/model.json", + "build/smithyprojections/projection/source/sources/main.smithy", + "build/smithyprojections/projection/source/sources/manifest", + "build/smithyprojections/projection/foo/build-info/smithy-build-info.json", + "build/smithyprojections/projection/foo/model/model.json", + "build/smithyprojections/projection/foo/sources/manifest", + "build/smithyprojections/projection/foo/sources/model.json", + "build/libs/projection.jar"); + Utils.assertJarContains(buildDir, + "build/libs/projection.jar", + "META-INF/smithy/manifest", + "META-INF/smithy/model.json"); + }); + } +} diff --git a/src/it/java/software/amazon/smithy/gradle/SourceProjectionTest.java b/src/it/java/software/amazon/smithy/gradle/SourceProjectionTest.java new file mode 100644 index 0000000..5a61aeb --- /dev/null +++ b/src/it/java/software/amazon/smithy/gradle/SourceProjectionTest.java @@ -0,0 +1,46 @@ +package software.amazon.smithy.gradle;/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.Test; + +public class SourceProjectionTest { + @Test + public void testSourceProjection() { + Utils.withCopy("source-projection", buildDir -> { + BuildResult result = GradleRunner.create() + .withProjectDir(buildDir) + .withArguments("build") + .build(); + + Utils.assertSmithyBuildRan(result); + Utils.assertValidationRan(result); + Utils.assertArtifactsCreated(buildDir, + "build/smithyprojections/source-projection/source/build-info/smithy-build-info.json", + "build/smithyprojections/source-projection/source/model/model.json", + "build/smithyprojections/source-projection/source/sources/main.smithy", + "build/smithyprojections/source-projection/source/sources/manifest", + "build/smithyprojections/source-projection/foo/build-info/smithy-build-info.json", + "build/smithyprojections/source-projection/foo/model/model.json", + "build/smithyprojections/source-projection/foo/sources/manifest", + "build/smithyprojections/source-projection/foo/sources/model.json", + "build/libs/source-projection.jar"); + Utils.assertJarContains(buildDir, "build/libs/source-projection.jar", + "META-INF/smithy/manifest", + "META-INF/smithy/main.smithy"); + }); + } +} diff --git a/src/it/java/software/amazon/smithy/gradle/Utils.java b/src/it/java/software/amazon/smithy/gradle/Utils.java new file mode 100644 index 0000000..9a2855e --- /dev/null +++ b/src/it/java/software/amazon/smithy/gradle/Utils.java @@ -0,0 +1,132 @@ +package software.amazon.smithy.gradle;/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.Comparator; +import java.util.function.Consumer; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import org.apache.commons.io.FileUtils; +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.TaskOutcome; +import org.junit.jupiter.api.Assertions; + +public final class Utils { + private Utils() {} + + public static Path createTempDir(String name) { + try { + return Files.createTempDirectory(name.replace("/", "_")); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static void deleteTempDir(Path dir) { + try { + Files.walk(dir).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static void deleteTempDir(File dir) { + deleteTempDir(dir.toPath()); + } + + public static void copyProject(String name, File dest) { + File source = getProjectDir(name).toFile(); + + try { + FileUtils.deleteQuietly(dest); + FileUtils.copyDirectory(source, dest, f -> { + // Don't copy the build dir. + if (f.toString().endsWith("build") || f.toString().endsWith(".gradle")) { + return false; + } + + // Skip hidden files. + return !f.getName().startsWith("."); + }); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static void withCopy(String projectName, Consumer consumer) { + File buildDir = Utils.createTempDir(projectName).toFile(); + try { + copyProject(projectName, buildDir); + consumer.accept(buildDir); + } finally { + Utils.deleteTempDir(buildDir); + } + } + + public static Path getProjectDir(String name) { + return Paths.get(".").resolve("examples").resolve(name); + } + + public static void assertSmithyBuildRan(BuildResult result) { + Assertions.assertTrue(result.task(":smithyBuild").getOutcome() == TaskOutcome.SUCCESS); + } + + public static void assertValidationRan(BuildResult result) { + Assertions.assertTrue(result.getOutput().contains("Smithy validation complete")); + } + + public static void assertValidationDidNotRun(BuildResult result) { + Assertions.assertFalse(result.getOutput().contains("Smithy validation complete")); + } + + public static void assertArtifactsCreated(File projectDir, String... paths) { + Path base = projectDir.toPath(); + for (String file : paths) { + Assertions.assertTrue(Files.exists(base.resolve(file)), () -> file + + " does not exist. The following files exist:\n" + + FileUtils.listFiles(projectDir, null, true).stream() + .map(File::toString) + .collect(Collectors.joining("\n"))); + } + } + + public static void assertArtifactsNotCreated(File projectDir, String... paths) { + Path base = projectDir.toPath(); + for (String file : paths) { + Assertions.assertFalse(Files.exists(base.resolve(file)), () -> file + " should not exist"); + } + } + + public static void assertJarContains(File projectDir, String jarPath, String... jarEntries) { + try (JarFile jar = new JarFile(new File(projectDir, jarPath))) { + for (String jarEntry : jarEntries) { + Assertions.assertNotNull(jar.getEntry(jarEntry), "JAR entry `" + jarEntry + "` does not exist in `" + + jarPath + "`. This JAR contains the following entries:\n" + + Collections.list(jar.entries()).stream() + .map(JarEntry::getName) + .collect(Collectors.joining("\n"))); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/src/main/java/software/amazon/smithy/gradle/tasks/SmithyBuildJar.java b/src/main/java/software/amazon/smithy/gradle/tasks/SmithyBuildJar.java index 839ec1a..e7da4c6 100644 --- a/src/main/java/software/amazon/smithy/gradle/tasks/SmithyBuildJar.java +++ b/src/main/java/software/amazon/smithy/gradle/tasks/SmithyBuildJar.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; +import org.gradle.api.GradleException; import org.gradle.api.file.FileCollection; import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.TaskAction; @@ -126,6 +127,12 @@ private List getDirectories(Path path) throws IOException { // Copy the "sources" plugin output to the generated resources directory. private void copyModelsToStaging() throws IOException { Path sources = SmithyUtils.getProjectionPluginPath(getProject(), getProjection(), "sources"); + + if (!Files.isDirectory(sources)) { + throw new GradleException("Smithy projection `" + getProjection() + "` not found. " + + "Is this projection defined in your smithy-build.json file?"); + } + FileUtils.copyDirectory(sources.toFile(), SmithyUtils.getSmithyResourceTempDir(getProject())); } diff --git a/src/test/java/software/amazon/smithy/gradle/SmithyExtensionTest.java b/src/test/java/software/amazon/smithy/gradle/SmithyExtensionTest.java new file mode 100644 index 0000000..9f2bc38 --- /dev/null +++ b/src/test/java/software/amazon/smithy/gradle/SmithyExtensionTest.java @@ -0,0 +1,17 @@ +package software.amazon.smithy.gradle; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import org.junit.jupiter.api.Test; + +public class SmithyExtensionTest { + @Test + public void projectionDefaultsToSource() { + SmithyExtension extension = new SmithyExtension(); + + assertThat(extension.getProjection(), equalTo("source")); + extension.setProjection("foo"); + assertThat(extension.getProjection(), equalTo("foo")); + } +} diff --git a/src/test/java/software/amazon/smithy/gradle/SmithyPluginTest.java b/src/test/java/software/amazon/smithy/gradle/SmithyPluginTest.java deleted file mode 100644 index 5a6d264..0000000 --- a/src/test/java/software/amazon/smithy/gradle/SmithyPluginTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package software.amazon.smithy.gradle; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -public class SmithyPluginTest { - @Test - public void testSomeLibraryMethod() { - assertTrue(true); - } -} diff --git a/test-kotlin/model/test.smithy b/test-kotlin/model/test.smithy deleted file mode 100644 index a6080d2..0000000 --- a/test-kotlin/model/test.smithy +++ /dev/null @@ -1,5 +0,0 @@ -namespace foo.baz - -list MyList { - member: String -}