diff --git a/BUILD.bazel b/BUILD.bazel index ca61266dfd..11b2b84ce0 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -15,6 +15,7 @@ JAVA_SRCS = [ TEST_SRCS = [ "//src/test/java/com/google/api/generator/engine:engine_files", "//src/test/java/com/google/api/generator/gapic:gapic_files", + "//src/test/java/com/google/api/generator/test/framework:framework_files", ] # ============= Proto wrappers ================= diff --git a/dependencies.properties b/dependencies.properties index feeea4cce5..42eb51736a 100644 --- a/dependencies.properties +++ b/dependencies.properties @@ -20,6 +20,7 @@ maven.com_google_code_findbugs_jsr305=com.google.code.findbugs:jsr305:3.0.0 maven.com_google_auto_value_auto_value=com.google.auto.value:auto-value:1.7.2 maven.com_google_auto_value_auto_value_annotations=com.google.auto.value:auto-value-annotations:1.7.2 maven.com_google_protobuf_protobuf_java=com.google.protobuf:protobuf-java:3.12.2 +maven.io_github_java_diff_utils=io.github.java-diff-utils:java-diff-utils:4.0 maven.javax_annotation_api=javax.annotation:javax.annotation-api:1.3.2 maven.javax_validation_javax_validation_api=javax.validation:validation-api:2.0.1.Final diff --git a/src/test/java/com/google/api/generator/gapic/dummy/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/dummy/BUILD.bazel index 84e4febc7a..ace0cd26f4 100644 --- a/src/test/java/com/google/api/generator/gapic/dummy/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/dummy/BUILD.bazel @@ -12,10 +12,12 @@ filegroup( [java_test( name = test_name, srcs = ["{0}.java".format(test_name)], + data = ["//src/test/java/com/google/api/generator/gapic/dummy/goldens:goldens_files"], test_class = "com.google.api.generator.gapic.dummy.{0}".format(test_name), deps = [ "//src/main/java/com/google/api/generator/engine/ast", "//src/main/java/com/google/api/generator/engine/writer", + "//src/test/java/com/google/api/generator/test/framework", "@junit_junit//jar", ], ) for test_name in TESTS] diff --git a/src/test/java/com/google/api/generator/gapic/dummy/FileDiffInfraDummyTest.java b/src/test/java/com/google/api/generator/gapic/dummy/FileDiffInfraDummyTest.java index 9dcc0ce252..98f766cab5 100644 --- a/src/test/java/com/google/api/generator/gapic/dummy/FileDiffInfraDummyTest.java +++ b/src/test/java/com/google/api/generator/gapic/dummy/FileDiffInfraDummyTest.java @@ -14,14 +14,15 @@ package com.google.api.generator.gapic.dummy; -import static junit.framework.Assert.assertEquals; - import com.google.api.generator.engine.ast.BlockComment; import com.google.api.generator.engine.ast.ClassDefinition; import com.google.api.generator.engine.ast.CommentStatement; import com.google.api.generator.engine.ast.LineComment; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.writer.JavaWriterVisitor; +import com.google.api.generator.test.framework.Assert; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import org.junit.Test; @@ -33,6 +34,9 @@ public class FileDiffInfraDummyTest { // created. // // TODO(xiaozhenliu): remove this test class once the file-diff infra is in place and well-tested. + private static final String GOLDENFILES_DIRECTORY = + "src/test/java/com/google/api/generator/gapic/dummy/goldens/"; + @Test public void simpleClass() { ClassDefinition classDef = @@ -47,7 +51,9 @@ public void simpleClass() { .build(); JavaWriterVisitor visitor = new JavaWriterVisitor(); classDef.accept(visitor); - assertEquals(visitor.write(), EXPECTED_CLASS_STRING_SIMPLE); + Path goldenFilePath = + Paths.get(GOLDENFILES_DIRECTORY, "FileDiffInfraDummyTestSimpleClass.golden"); + Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test @@ -63,7 +69,18 @@ public void classWithHeader() { .build(); JavaWriterVisitor visitor = new JavaWriterVisitor(); classDef.accept(visitor); - assertEquals(visitor.write(), EXPECTED_CLASS_STRING_WITH_HEADER); + Path goldenFilePath = + Paths.get(GOLDENFILES_DIRECTORY, "FileDiffInfraDummyTestClassWithHeader.golden"); + Assert.assertCodeEquals(goldenFilePath, visitor.write()); + } + + // Add a simple test for two strings comparison. + @Test + public void simpleLineComment() { + JavaWriterVisitor visitor = new JavaWriterVisitor(); + LineComment lineComment = LineComment.withComment("test strings comparison."); + lineComment.accept(visitor); + Assert.assertCodeEquals("// test strings comparison.", visitor.write()); } private static final String APACHE_LICENSE_STRING = @@ -77,28 +94,4 @@ public void classWithHeader() { + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + "See the License for the specific language governing permissions and\n" + "limitations under the License."; - - private static final String EXPECTED_CLASS_STRING_SIMPLE = - "package com.google.showcase.v1beta1.stub;\n\n" - + "// This is a test class for file-diff infra\n" - + "public class EchoStubSettings {}\n"; - - private static final String EXPECTED_CLASS_STRING_WITH_HEADER = - "/*\n" - + " * Copyright 2020 Google LLC\n" - + " *\n" - + " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" - + " * you may not use this file except in compliance with the License.\n" - + " * You may obtain a copy of the License at\n" - + " *\n" - + " * https://www.apache.org/licenses/LICENSE-2.0\n" - + " *\n" - + " * Unless required by applicable law or agreed to in writing, software\n" - + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" - + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" - + " * See the License for the specific language governing permissions and\n" - + " * limitations under the License.\n" - + " */\n\n" - + "package com.google.showcase.v1beta1.stub;\n\n" - + "public class EchoStubSettings {}\n"; } diff --git a/src/test/java/com/google/api/generator/test/framework/Assert.java b/src/test/java/com/google/api/generator/test/framework/Assert.java new file mode 100644 index 0000000000..4ed6a932fd --- /dev/null +++ b/src/test/java/com/google/api/generator/test/framework/Assert.java @@ -0,0 +1,44 @@ +// Copyright 2020 Google LLC +// +// 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 com.google.api.generator.test.framework; + +import java.nio.file.Path; +import java.util.List; +import junit.framework.AssertionFailedError; + +public class Assert { + /** + * Assert that the generated code is identical with the content in corresponding golden file. The + * differences will be emitted to the test-logs if any. + * + * @param goldenPath the path of the golden file. + * @param codegen the generated source code. + */ + public static void assertCodeEquals(Path goldenPath, String codegen) { + List diffList = Differ.diff(goldenPath, codegen); + if (!diffList.isEmpty()) { + throw new AssertionFailedError("Differences found: \n" + String.join("\n", diffList)); + } + } + + // Assert that two strings are identical, else throw AssertionFailedError and emit the + // differences to the test-logs. + public static void assertCodeEquals(String expected, String codegen) { + List diffList = Differ.diff(expected, codegen); + if (!diffList.isEmpty()) { + throw new AssertionFailedError("Differences found: \n" + String.join("\n", diffList)); + } + } +} diff --git a/src/test/java/com/google/api/generator/test/framework/BUILD.bazel b/src/test/java/com/google/api/generator/test/framework/BUILD.bazel new file mode 100644 index 0000000000..8cdc676778 --- /dev/null +++ b/src/test/java/com/google/api/generator/test/framework/BUILD.bazel @@ -0,0 +1,17 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "framework_files", + srcs = glob(["*.java"]), +) + +java_library( + name = "framework", + srcs = [ + ":framework_files", + ], + deps = [ + "@io_github_java_diff_utils//jar", + "@junit_junit//jar", + ], +) diff --git a/src/test/java/com/google/api/generator/test/framework/Differ.java b/src/test/java/com/google/api/generator/test/framework/Differ.java new file mode 100644 index 0000000000..6a3c364d33 --- /dev/null +++ b/src/test/java/com/google/api/generator/test/framework/Differ.java @@ -0,0 +1,71 @@ +// Copyright 2020 Google LLC +// +// 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 com.google.api.generator.test.framework; + +import com.github.difflib.DiffUtils; +import com.github.difflib.UnifiedDiffUtils; +import com.github.difflib.algorithm.DiffException; +import com.github.difflib.patch.Patch; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +public class Differ { + private static final String LINE_SPLITTER = "\\r?\\n"; + + public static List diff(Path goldenFilePath, String codegen) { + List revised = Arrays.asList(codegen.split(LINE_SPLITTER)); + List original = null; + try { + original = Files.readAllLines(goldenFilePath); + } catch (IOException e) { + throw new GoldenFileReadException( + String.format("Error occurs when reading golden file %s", goldenFilePath)); + } + return diffTwoStringLists(original, revised); + } + + public static List diff(String expectedStr, String actualStr) { + List revised = Arrays.asList(actualStr.split(LINE_SPLITTER)); + List original = Arrays.asList(expectedStr.split(LINE_SPLITTER)); + return diffTwoStringLists(original, revised); + } + + private static List diffTwoStringLists(List original, List revised) { + Patch diff = null; + try { + diff = DiffUtils.diff(original, revised); + } catch (DiffException e) { + throw new ComputeDiffException("Could not compute the differences."); + } + List unifiedDiff = + UnifiedDiffUtils.generateUnifiedDiff("golden", "codegen", original, diff, 2); + return unifiedDiff; + } + + private static class GoldenFileReadException extends RuntimeException { + public GoldenFileReadException(String errorMessage) { + super(errorMessage); + } + } + + private static class ComputeDiffException extends RuntimeException { + public ComputeDiffException(String errorMessage) { + super(errorMessage); + } + } +}