// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) #include #include #include #include "google/protobuf/testing/file.h" #include "google/protobuf/testing/file.h" #include "google/protobuf/compiler/command_line_interface.h" #include "google/protobuf/compiler/python/generator.h" #include "google/protobuf/testing/googletest.h" #include #include "absl/log/absl_check.h" #include "absl/strings/str_split.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { namespace compiler { namespace python { namespace { class TestGenerator : public CodeGenerator { public: TestGenerator() {} ~TestGenerator() override {} bool Generate(const FileDescriptor* file, const std::string& parameter, GeneratorContext* context, std::string* error) const override { TryInsert("test_pb2.py", "imports", context); TryInsert("test_pb2.py", "module_scope", context); TryInsert("test_pb2.py", "class_scope:foo.Bar", context); TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context); return true; } void TryInsert(const std::string& filename, const std::string& insertion_point, GeneratorContext* context) const { std::unique_ptr output( context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } }; // opposed to importlib) in the usual case where the .proto file paths do not // not contain any Python keywords. TEST(PythonPluginTest, ImportTest) { // Create files test1.proto and test2.proto with the former importing the // latter. ABSL_CHECK_OK( File::SetContents(absl::StrCat(TestTempDir(), "/test1.proto"), "syntax = \"proto3\";\n" "package foo;\n" "import \"test2.proto\";" "message Message1 {\n" " Message2 message_2 = 1;\n" "}\n", true)); ABSL_CHECK_OK( File::SetContents(absl::StrCat(TestTempDir(), "/test2.proto"), "syntax = \"proto3\";\n" "package foo;\n" "message Message2 {}\n", true)); compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); python::Generator python_generator; cli.RegisterGenerator("--python_out", &python_generator, ""); std::string proto_path = absl::StrCat("-I", TestTempDir()); std::string python_out = absl::StrCat("--python_out=", TestTempDir()); const char* argv[] = {"protoc", proto_path.c_str(), "-I.", python_out.c_str(), "test1.proto"}; ASSERT_EQ(0, cli.Run(5, argv)); // Loop over the lines of the generated code and verify that we find an // ordinary Python import but do not find the string "importlib". std::string output; ABSL_CHECK_OK( File::GetContents(absl::StrCat(TestTempDir(), "/test1_pb2.py"), &output, true)); std::vector lines = absl::StrSplit(output, '\n'); std::string expected_import = "import test2_pb2"; bool found_expected_import = false; for (absl::string_view line : lines) { if (absl::StrContains(line, expected_import)) { found_expected_import = true; } EXPECT_FALSE(absl::StrContains(line, "importlib")); } EXPECT_TRUE(found_expected_import); } } // namespace } // namespace python } // namespace compiler } // namespace protobuf } // namespace google