temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 2 | // Copyright 2008 Google Inc. All rights reserved. |
Feng Xiao | e428862 | 2014-10-01 16:26:23 -0700 | [diff] [blame] | 3 | // https://developers.google.com/protocol-buffers/ |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 4 | // |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 5 | // Redistribution and use in source and binary forms, with or without |
| 6 | // modification, are permitted provided that the following conditions are |
| 7 | // met: |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 8 | // |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 9 | // * Redistributions of source code must retain the above copyright |
| 10 | // notice, this list of conditions and the following disclaimer. |
| 11 | // * Redistributions in binary form must reproduce the above |
| 12 | // copyright notice, this list of conditions and the following disclaimer |
| 13 | // in the documentation and/or other materials provided with the |
| 14 | // distribution. |
| 15 | // * Neither the name of Google Inc. nor the names of its |
| 16 | // contributors may be used to endorse or promote products derived from |
| 17 | // this software without specific prior written permission. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 18 | // |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 30 | |
| 31 | // Author: kenton@google.com (Kenton Varda) |
| 32 | // Based on original Protocol Buffers design by |
| 33 | // Sanjay Ghemawat, Jeff Dean, and others. |
| 34 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 35 | #include <sys/types.h> |
| 36 | #include <sys/stat.h> |
| 37 | #include <fcntl.h> |
| 38 | #ifdef _MSC_VER |
| 39 | #include <io.h> |
| 40 | #else |
| 41 | #include <unistd.h> |
| 42 | #endif |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 43 | #include <memory> |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 44 | #ifndef _SHARED_PTR_H |
| 45 | #include <google/protobuf/stubs/shared_ptr.h> |
| 46 | #endif |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 47 | #include <vector> |
| 48 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 49 | #include <google/protobuf/descriptor.pb.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 50 | #include <google/protobuf/descriptor.h> |
| 51 | #include <google/protobuf/io/zero_copy_stream.h> |
| 52 | #include <google/protobuf/compiler/command_line_interface.h> |
| 53 | #include <google/protobuf/compiler/code_generator.h> |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 54 | #include <google/protobuf/testing/file.h> |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 55 | #include <google/protobuf/compiler/mock_code_generator.h> |
liujisi@google.com | 57014ff | 2010-12-21 05:56:35 +0000 | [diff] [blame] | 56 | #include <google/protobuf/compiler/subprocess.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 57 | #include <google/protobuf/io/printer.h> |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 58 | #include <google/protobuf/unittest.pb.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 59 | #include <google/protobuf/testing/file.h> |
| 60 | #include <google/protobuf/stubs/strutil.h> |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 61 | #include <google/protobuf/stubs/substitute.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 62 | |
| 63 | #include <google/protobuf/testing/googletest.h> |
| 64 | #include <gtest/gtest.h> |
| 65 | |
Feng Xiao | c5147e3 | 2015-12-28 16:40:39 -0800 | [diff] [blame] | 66 | namespace google { |
| 67 | namespace protobuf { |
| 68 | namespace compiler { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 69 | |
Jisi Liu | 7a00a1e | 2015-02-21 17:28:51 -0800 | [diff] [blame] | 70 | // Disable the whole test when we use tcmalloc for "draconian" heap checks, in |
| 71 | // which case tcmalloc will print warnings that fail the plugin tests. |
| 72 | #if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 73 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 74 | #if defined(_WIN32) |
| 75 | #ifndef STDIN_FILENO |
| 76 | #define STDIN_FILENO 0 |
| 77 | #endif |
| 78 | #ifndef STDOUT_FILENO |
| 79 | #define STDOUT_FILENO 1 |
| 80 | #endif |
kenton@google.com | c0ee4d2 | 2009-12-22 02:05:33 +0000 | [diff] [blame] | 81 | #ifndef F_OK |
| 82 | #define F_OK 00 // not defined by MSVC for whatever reason |
| 83 | #endif |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 84 | #endif |
| 85 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 86 | namespace { |
| 87 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 88 | bool FileExists(const string& path) { |
| 89 | return File::Exists(path); |
| 90 | } |
| 91 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 92 | class CommandLineInterfaceTest : public testing::Test { |
| 93 | protected: |
| 94 | virtual void SetUp(); |
| 95 | virtual void TearDown(); |
| 96 | |
| 97 | // Runs the CommandLineInterface with the given command line. The |
| 98 | // command is automatically split on spaces, and the string "$tmpdir" |
| 99 | // is replaced with TestTempDir(). |
jieluo@google.com | 8d6f04a | 2014-08-06 20:49:30 +0000 | [diff] [blame] | 100 | void Run(const string& command); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 101 | |
| 102 | // ----------------------------------------------------------------- |
| 103 | // Methods to set up the test (called before Run()). |
| 104 | |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 105 | class NullCodeGenerator; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 106 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 107 | // Normally plugins are allowed for all tests. Call this to explicitly |
| 108 | // disable them. |
| 109 | void DisallowPlugins() { disallow_plugins_ = true; } |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 110 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 111 | // Create a temp file within temp_directory_ with the given name. |
| 112 | // The containing directory is also created if necessary. |
| 113 | void CreateTempFile(const string& name, const string& contents); |
| 114 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 115 | // Create a subdirectory within temp_directory_. |
| 116 | void CreateTempDir(const string& name); |
| 117 | |
Bo Yang | 5db2173 | 2015-05-21 14:28:59 -0700 | [diff] [blame] | 118 | #ifdef PROTOBUF_OPENSOURCE |
Bo Yang | a1b351c | 2015-02-04 10:20:20 -0800 | [diff] [blame] | 119 | // Change working directory to temp directory. |
| 120 | void SwitchToTempDirectory() { |
| 121 | File::ChangeWorkingDirectory(temp_directory_); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 122 | } |
Bo Yang | 5db2173 | 2015-05-21 14:28:59 -0700 | [diff] [blame] | 123 | #else // !PROTOBUF_OPENSOURCE |
| 124 | // TODO(teboring): Figure out how to change and get working directory in |
| 125 | // google3. |
| 126 | #endif // !PROTOBUF_OPENSOURCE |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 127 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 128 | void SetInputsAreProtoPathRelative(bool enable) { |
| 129 | cli_.SetInputsAreProtoPathRelative(enable); |
| 130 | } |
| 131 | |
| 132 | // ----------------------------------------------------------------- |
| 133 | // Methods to check the test results (called after Run()). |
| 134 | |
| 135 | // Checks that no text was written to stderr during Run(), and Run() |
| 136 | // returned 0. |
| 137 | void ExpectNoErrors(); |
| 138 | |
| 139 | // Checks that Run() returned non-zero and the stderr output is exactly |
| 140 | // the text given. expected_test may contain references to "$tmpdir", |
| 141 | // which will be replaced by the temporary directory path. |
| 142 | void ExpectErrorText(const string& expected_text); |
| 143 | |
| 144 | // Checks that Run() returned non-zero and the stderr contains the given |
| 145 | // substring. |
| 146 | void ExpectErrorSubstring(const string& expected_substring); |
| 147 | |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 148 | // Like ExpectErrorSubstring, but checks that Run() returned zero. |
| 149 | void ExpectErrorSubstringWithZeroReturnCode( |
| 150 | const string& expected_substring); |
| 151 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 152 | // Checks that the captured stdout is the same as the expected_text. |
| 153 | void ExpectCapturedStdout(const string& expected_text); |
| 154 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 155 | // Returns true if ExpectErrorSubstring(expected_substring) would pass, but |
| 156 | // does not fail otherwise. |
| 157 | bool HasAlternateErrorSubstring(const string& expected_substring); |
| 158 | |
| 159 | // Checks that MockCodeGenerator::Generate() was called in the given |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 160 | // context (or the generator in test_plugin.cc, which produces the same |
| 161 | // output). That is, this tests if the generator with the given name |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 162 | // was called with the given parameter and proto file and produced the |
| 163 | // given output file. This is checked by reading the output file and |
| 164 | // checking that it contains the content that MockCodeGenerator would |
| 165 | // generate given these inputs. message_name is the name of the first |
| 166 | // message that appeared in the proto file; this is just to make extra |
| 167 | // sure that the correct file was parsed. |
| 168 | void ExpectGenerated(const string& generator_name, |
| 169 | const string& parameter, |
| 170 | const string& proto_name, |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 171 | const string& message_name); |
| 172 | void ExpectGenerated(const string& generator_name, |
| 173 | const string& parameter, |
| 174 | const string& proto_name, |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 175 | const string& message_name, |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 176 | const string& output_directory); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 177 | void ExpectGeneratedWithMultipleInputs(const string& generator_name, |
| 178 | const string& all_proto_names, |
| 179 | const string& proto_name, |
| 180 | const string& message_name); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 181 | void ExpectGeneratedWithInsertions(const string& generator_name, |
| 182 | const string& parameter, |
| 183 | const string& insertions, |
| 184 | const string& proto_name, |
| 185 | const string& message_name); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 186 | |
kenton@google.com | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 187 | void ExpectNullCodeGeneratorCalled(const string& parameter); |
| 188 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 189 | void ReadDescriptorSet(const string& filename, |
| 190 | FileDescriptorSet* descriptor_set); |
| 191 | |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 192 | void ExpectFileContent(const string& filename, |
| 193 | const string& content); |
| 194 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 195 | private: |
| 196 | // The object we are testing. |
| 197 | CommandLineInterface cli_; |
| 198 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 199 | // Was DisallowPlugins() called? |
| 200 | bool disallow_plugins_; |
| 201 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 202 | // We create a directory within TestTempDir() in order to add extra |
| 203 | // protection against accidentally deleting user files (since we recursively |
| 204 | // delete this directory during the test). This is the full path of that |
| 205 | // directory. |
| 206 | string temp_directory_; |
| 207 | |
| 208 | // The result of Run(). |
| 209 | int return_code_; |
| 210 | |
| 211 | // The captured stderr output. |
| 212 | string error_text_; |
| 213 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 214 | // The captured stdout. |
| 215 | string captured_stdout_; |
| 216 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 217 | // Pointers which need to be deleted later. |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 218 | vector<CodeGenerator*> mock_generators_to_delete_; |
kenton@google.com | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 219 | |
| 220 | NullCodeGenerator* null_generator_; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 221 | }; |
| 222 | |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 223 | class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator { |
| 224 | public: |
| 225 | NullCodeGenerator() : called_(false) {} |
| 226 | ~NullCodeGenerator() {} |
| 227 | |
| 228 | mutable bool called_; |
| 229 | mutable string parameter_; |
| 230 | |
| 231 | // implements CodeGenerator ---------------------------------------- |
| 232 | bool Generate(const FileDescriptor* file, |
| 233 | const string& parameter, |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 234 | GeneratorContext* context, |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 235 | string* error) const { |
| 236 | called_ = true; |
| 237 | parameter_ = parameter; |
| 238 | return true; |
| 239 | } |
| 240 | }; |
| 241 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 242 | // =================================================================== |
| 243 | |
| 244 | void CommandLineInterfaceTest::SetUp() { |
| 245 | // Most of these tests were written before this option was added, so we |
| 246 | // run with the option on (which used to be the only way) except in certain |
| 247 | // tests where we turn it off. |
| 248 | cli_.SetInputsAreProtoPathRelative(true); |
| 249 | |
| 250 | temp_directory_ = TestTempDir() + "/proto2_cli_test_temp"; |
| 251 | |
| 252 | // If the temp directory already exists, it must be left over from a |
| 253 | // previous run. Delete it. |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 254 | if (FileExists(temp_directory_)) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 255 | File::DeleteRecursively(temp_directory_, NULL, NULL); |
| 256 | } |
| 257 | |
| 258 | // Create the temp directory. |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 259 | GOOGLE_CHECK_OK(File::CreateDir(temp_directory_, 0777)); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 260 | |
| 261 | // Register generators. |
| 262 | CodeGenerator* generator = new MockCodeGenerator("test_generator"); |
| 263 | mock_generators_to_delete_.push_back(generator); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 264 | cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output."); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 265 | cli_.RegisterGenerator("-t", generator, "Test output."); |
| 266 | |
| 267 | generator = new MockCodeGenerator("alt_generator"); |
| 268 | mock_generators_to_delete_.push_back(generator); |
| 269 | cli_.RegisterGenerator("--alt_out", generator, "Alt output."); |
| 270 | |
kenton@google.com | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 271 | generator = null_generator_ = new NullCodeGenerator(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 272 | mock_generators_to_delete_.push_back(generator); |
| 273 | cli_.RegisterGenerator("--null_out", generator, "Null output."); |
| 274 | |
| 275 | disallow_plugins_ = false; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 276 | } |
| 277 | |
| 278 | void CommandLineInterfaceTest::TearDown() { |
| 279 | // Delete the temp directory. |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 280 | if (FileExists(temp_directory_)) { |
Feng Xiao | baca1a8 | 2014-11-07 14:09:18 -0500 | [diff] [blame] | 281 | File::DeleteRecursively(temp_directory_, NULL, NULL); |
| 282 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 283 | |
| 284 | // Delete all the MockCodeGenerators. |
| 285 | for (int i = 0; i < mock_generators_to_delete_.size(); i++) { |
| 286 | delete mock_generators_to_delete_[i]; |
| 287 | } |
| 288 | mock_generators_to_delete_.clear(); |
| 289 | } |
| 290 | |
jieluo@google.com | 8d6f04a | 2014-08-06 20:49:30 +0000 | [diff] [blame] | 291 | void CommandLineInterfaceTest::Run(const string& command) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 292 | vector<string> args = Split(command, " ", true); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 293 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 294 | if (!disallow_plugins_) { |
| 295 | cli_.AllowPlugins("prefix-"); |
Bo Yang | 46bd60b | 2015-04-27 17:44:45 -0700 | [diff] [blame] | 296 | #ifndef GOOGLE_THIRD_PARTY_PROTOBUF |
Konstantin Podsvirov | e301946 | 2015-09-17 12:08:47 +0300 | [diff] [blame] | 297 | string plugin_path; |
| 298 | #ifdef GOOGLE_PROTOBUF_TEST_PLUGIN_PATH |
| 299 | plugin_path = GOOGLE_PROTOBUF_TEST_PLUGIN_PATH; |
| 300 | #else |
kenton@google.com | c0ee4d2 | 2009-12-22 02:05:33 +0000 | [diff] [blame] | 301 | const char* possible_paths[] = { |
| 302 | // When building with shared libraries, libtool hides the real executable |
| 303 | // in .libs and puts a fake wrapper in the current directory. |
| 304 | // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program |
| 305 | // wrapped in this way (e.g. protobuf-tests.exe) tries to execute another |
| 306 | // program wrapped in this way (e.g. test_plugin.exe), the latter fails |
| 307 | // with error code 127 and no explanation message. Presumably the problem |
| 308 | // is that the wrapper for protobuf-tests.exe set some environment |
| 309 | // variables that confuse the wrapper for test_plugin.exe. Luckily, it |
| 310 | // turns out that if we simply invoke the wrapped test_plugin.exe |
| 311 | // directly, it works -- I guess the environment variables set by the |
| 312 | // protobuf-tests.exe wrapper happen to be correct for it too. So we do |
| 313 | // that. |
| 314 | ".libs/test_plugin.exe", // Win32 w/autotool (Cygwin / MinGW) |
| 315 | "test_plugin.exe", // Other Win32 (MSVC) |
| 316 | "test_plugin", // Unix |
| 317 | }; |
kenton@google.com | c0ee4d2 | 2009-12-22 02:05:33 +0000 | [diff] [blame] | 318 | for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) { |
| 319 | if (access(possible_paths[i], F_OK) == 0) { |
| 320 | plugin_path = possible_paths[i]; |
| 321 | break; |
| 322 | } |
| 323 | } |
Konstantin Podsvirov | 2fa0439 | 2015-09-15 15:01:05 +0300 | [diff] [blame] | 324 | #endif |
kenton@google.com | c0ee4d2 | 2009-12-22 02:05:33 +0000 | [diff] [blame] | 325 | |
| 326 | if (plugin_path.empty()) { |
Bo Yang | 46bd60b | 2015-04-27 17:44:45 -0700 | [diff] [blame] | 327 | #else |
| 328 | string plugin_path = "third_party/protobuf/test_plugin"; |
| 329 | |
| 330 | if (access(plugin_path.c_str(), F_OK) != 0) { |
| 331 | #endif // GOOGLE_THIRD_PARTY_PROTOBUF |
kenton@google.com | c0ee4d2 | 2009-12-22 02:05:33 +0000 | [diff] [blame] | 332 | GOOGLE_LOG(ERROR) |
| 333 | << "Plugin executable not found. Plugin tests are likely to fail."; |
| 334 | } else { |
| 335 | args.push_back("--plugin=prefix-gen-plug=" + plugin_path); |
| 336 | } |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 337 | } |
| 338 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 339 | google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 340 | |
| 341 | for (int i = 0; i < args.size(); i++) { |
| 342 | args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true); |
| 343 | argv[i] = args[i].c_str(); |
| 344 | } |
| 345 | |
jieluo@google.com | 8d6f04a | 2014-08-06 20:49:30 +0000 | [diff] [blame] | 346 | // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and |
| 347 | // stdout at the same time. Need to figure out why and add this capture back |
| 348 | // for Cygwin. |
| 349 | #if !defined(__CYGWIN__) |
| 350 | CaptureTestStdout(); |
| 351 | #endif |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 352 | CaptureTestStderr(); |
| 353 | |
| 354 | return_code_ = cli_.Run(args.size(), argv.get()); |
| 355 | |
| 356 | error_text_ = GetCapturedTestStderr(); |
jieluo@google.com | 8d6f04a | 2014-08-06 20:49:30 +0000 | [diff] [blame] | 357 | #if !defined(__CYGWIN__) |
| 358 | captured_stdout_ = GetCapturedTestStdout(); |
| 359 | #endif |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 360 | } |
| 361 | |
| 362 | // ------------------------------------------------------------------- |
| 363 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 364 | void CommandLineInterfaceTest::CreateTempFile( |
| 365 | const string& name, |
| 366 | const string& contents) { |
| 367 | // Create parent directory, if necessary. |
| 368 | string::size_type slash_pos = name.find_last_of('/'); |
| 369 | if (slash_pos != string::npos) { |
| 370 | string dir = name.substr(0, slash_pos); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 371 | if (!FileExists(temp_directory_ + "/" + dir)) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 372 | GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir, |
| 373 | 0777)); |
| 374 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 375 | } |
| 376 | |
| 377 | // Write file. |
| 378 | string full_name = temp_directory_ + "/" + name; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 379 | GOOGLE_CHECK_OK(File::SetContents(full_name, contents, true)); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 380 | } |
| 381 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 382 | void CommandLineInterfaceTest::CreateTempDir(const string& name) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 383 | GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name, |
| 384 | 0777)); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 385 | } |
| 386 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 387 | // ------------------------------------------------------------------- |
| 388 | |
| 389 | void CommandLineInterfaceTest::ExpectNoErrors() { |
| 390 | EXPECT_EQ(0, return_code_); |
| 391 | EXPECT_EQ("", error_text_); |
| 392 | } |
| 393 | |
| 394 | void CommandLineInterfaceTest::ExpectErrorText(const string& expected_text) { |
| 395 | EXPECT_NE(0, return_code_); |
| 396 | EXPECT_EQ(StringReplace(expected_text, "$tmpdir", temp_directory_, true), |
| 397 | error_text_); |
| 398 | } |
| 399 | |
| 400 | void CommandLineInterfaceTest::ExpectErrorSubstring( |
| 401 | const string& expected_substring) { |
| 402 | EXPECT_NE(0, return_code_); |
| 403 | EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); |
| 404 | } |
| 405 | |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 406 | void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode( |
| 407 | const string& expected_substring) { |
| 408 | EXPECT_EQ(0, return_code_); |
| 409 | EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); |
| 410 | } |
| 411 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 412 | bool CommandLineInterfaceTest::HasAlternateErrorSubstring( |
| 413 | const string& expected_substring) { |
| 414 | EXPECT_NE(0, return_code_); |
| 415 | return error_text_.find(expected_substring) != string::npos; |
| 416 | } |
| 417 | |
| 418 | void CommandLineInterfaceTest::ExpectGenerated( |
| 419 | const string& generator_name, |
| 420 | const string& parameter, |
| 421 | const string& proto_name, |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 422 | const string& message_name) { |
| 423 | MockCodeGenerator::ExpectGenerated( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 424 | generator_name, parameter, "", proto_name, message_name, proto_name, |
| 425 | temp_directory_); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 426 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 427 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 428 | void CommandLineInterfaceTest::ExpectGenerated( |
| 429 | const string& generator_name, |
| 430 | const string& parameter, |
| 431 | const string& proto_name, |
| 432 | const string& message_name, |
| 433 | const string& output_directory) { |
| 434 | MockCodeGenerator::ExpectGenerated( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 435 | generator_name, parameter, "", proto_name, message_name, proto_name, |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 436 | temp_directory_ + "/" + output_directory); |
| 437 | } |
| 438 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 439 | void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs( |
| 440 | const string& generator_name, |
| 441 | const string& all_proto_names, |
| 442 | const string& proto_name, |
| 443 | const string& message_name) { |
| 444 | MockCodeGenerator::ExpectGenerated( |
| 445 | generator_name, "", "", proto_name, message_name, |
| 446 | all_proto_names, |
| 447 | temp_directory_); |
| 448 | } |
| 449 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 450 | void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( |
| 451 | const string& generator_name, |
| 452 | const string& parameter, |
| 453 | const string& insertions, |
| 454 | const string& proto_name, |
| 455 | const string& message_name) { |
| 456 | MockCodeGenerator::ExpectGenerated( |
| 457 | generator_name, parameter, insertions, proto_name, message_name, |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 458 | proto_name, temp_directory_); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 459 | } |
| 460 | |
kenton@google.com | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 461 | void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled( |
| 462 | const string& parameter) { |
| 463 | EXPECT_TRUE(null_generator_->called_); |
| 464 | EXPECT_EQ(parameter, null_generator_->parameter_); |
| 465 | } |
| 466 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 467 | void CommandLineInterfaceTest::ReadDescriptorSet( |
| 468 | const string& filename, FileDescriptorSet* descriptor_set) { |
| 469 | string path = temp_directory_ + "/" + filename; |
| 470 | string file_contents; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 471 | GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); |
| 472 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 473 | if (!descriptor_set->ParseFromString(file_contents)) { |
| 474 | FAIL() << "Could not parse file contents: " << path; |
| 475 | } |
| 476 | } |
| 477 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 478 | void CommandLineInterfaceTest::ExpectCapturedStdout( |
| 479 | const string& expected_text) { |
| 480 | EXPECT_EQ(expected_text, captured_stdout_); |
| 481 | } |
| 482 | |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 483 | |
| 484 | void CommandLineInterfaceTest::ExpectFileContent( |
| 485 | const string& filename, const string& content) { |
| 486 | string path = temp_directory_ + "/" + filename; |
| 487 | string file_contents; |
| 488 | GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); |
| 489 | |
| 490 | EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true), |
| 491 | file_contents); |
| 492 | } |
| 493 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 494 | // =================================================================== |
| 495 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 496 | TEST_F(CommandLineInterfaceTest, BasicOutput) { |
| 497 | // Test that the common case works. |
| 498 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 499 | CreateTempFile("foo.proto", |
| 500 | "syntax = \"proto2\";\n" |
| 501 | "message Foo {}\n"); |
| 502 | |
| 503 | Run("protocol_compiler --test_out=$tmpdir " |
| 504 | "--proto_path=$tmpdir foo.proto"); |
| 505 | |
| 506 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 507 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
| 508 | } |
| 509 | |
| 510 | TEST_F(CommandLineInterfaceTest, BasicPlugin) { |
| 511 | // Test that basic plugins work. |
| 512 | |
| 513 | CreateTempFile("foo.proto", |
| 514 | "syntax = \"proto2\";\n" |
| 515 | "message Foo {}\n"); |
| 516 | |
| 517 | Run("protocol_compiler --plug_out=$tmpdir " |
| 518 | "--proto_path=$tmpdir foo.proto"); |
| 519 | |
| 520 | ExpectNoErrors(); |
| 521 | ExpectGenerated("test_plugin", "", "foo.proto", "Foo"); |
| 522 | } |
| 523 | |
| 524 | TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) { |
| 525 | // Invoke a generator and a plugin at the same time. |
| 526 | |
| 527 | CreateTempFile("foo.proto", |
| 528 | "syntax = \"proto2\";\n" |
| 529 | "message Foo {}\n"); |
| 530 | |
| 531 | Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " |
| 532 | "--proto_path=$tmpdir foo.proto"); |
| 533 | |
| 534 | ExpectNoErrors(); |
| 535 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
| 536 | ExpectGenerated("test_plugin", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 537 | } |
| 538 | |
| 539 | TEST_F(CommandLineInterfaceTest, MultipleInputs) { |
| 540 | // Test parsing multiple input files. |
| 541 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 542 | CreateTempFile("foo.proto", |
| 543 | "syntax = \"proto2\";\n" |
| 544 | "message Foo {}\n"); |
| 545 | CreateTempFile("bar.proto", |
| 546 | "syntax = \"proto2\";\n" |
| 547 | "message Bar {}\n"); |
| 548 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 549 | Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 550 | "--proto_path=$tmpdir foo.proto bar.proto"); |
| 551 | |
| 552 | ExpectNoErrors(); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 553 | ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", |
| 554 | "foo.proto", "Foo"); |
| 555 | ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", |
| 556 | "bar.proto", "Bar"); |
| 557 | ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", |
| 558 | "foo.proto", "Foo"); |
| 559 | ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", |
| 560 | "bar.proto", "Bar"); |
| 561 | } |
| 562 | |
| 563 | TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) { |
| 564 | // Test parsing multiple input files with an import of a separate file. |
| 565 | |
| 566 | CreateTempFile("foo.proto", |
| 567 | "syntax = \"proto2\";\n" |
| 568 | "message Foo {}\n"); |
| 569 | CreateTempFile("bar.proto", |
| 570 | "syntax = \"proto2\";\n" |
| 571 | "import \"baz.proto\";\n" |
| 572 | "message Bar {\n" |
| 573 | " optional Baz a = 1;\n" |
| 574 | "}\n"); |
| 575 | CreateTempFile("baz.proto", |
| 576 | "syntax = \"proto2\";\n" |
| 577 | "message Baz {}\n"); |
| 578 | |
| 579 | Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " |
| 580 | "--proto_path=$tmpdir foo.proto bar.proto"); |
| 581 | |
| 582 | ExpectNoErrors(); |
| 583 | ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", |
| 584 | "foo.proto", "Foo"); |
| 585 | ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", |
| 586 | "bar.proto", "Bar"); |
| 587 | ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", |
| 588 | "foo.proto", "Foo"); |
| 589 | ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", |
| 590 | "bar.proto", "Bar"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 591 | } |
| 592 | |
| 593 | TEST_F(CommandLineInterfaceTest, CreateDirectory) { |
| 594 | // Test that when we output to a sub-directory, it is created. |
| 595 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 596 | CreateTempFile("bar/baz/foo.proto", |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 597 | "syntax = \"proto2\";\n" |
| 598 | "message Foo {}\n"); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 599 | CreateTempDir("out"); |
| 600 | CreateTempDir("plugout"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 601 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 602 | Run("protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout " |
| 603 | "--proto_path=$tmpdir bar/baz/foo.proto"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 604 | |
| 605 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 606 | ExpectGenerated("test_generator", "", "bar/baz/foo.proto", "Foo", "out"); |
| 607 | ExpectGenerated("test_plugin", "", "bar/baz/foo.proto", "Foo", "plugout"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 608 | } |
| 609 | |
| 610 | TEST_F(CommandLineInterfaceTest, GeneratorParameters) { |
| 611 | // Test that generator parameters are correctly parsed from the command line. |
| 612 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 613 | CreateTempFile("foo.proto", |
| 614 | "syntax = \"proto2\";\n" |
| 615 | "message Foo {}\n"); |
| 616 | |
| 617 | Run("protocol_compiler --test_out=TestParameter:$tmpdir " |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 618 | "--plug_out=TestPluginParameter:$tmpdir " |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 619 | "--proto_path=$tmpdir foo.proto"); |
| 620 | |
| 621 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 622 | ExpectGenerated("test_generator", "TestParameter", "foo.proto", "Foo"); |
| 623 | ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo"); |
| 624 | } |
| 625 | |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 626 | TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) { |
| 627 | // Test that generator parameters specified with the option flag are |
| 628 | // correctly passed to the code generator. |
| 629 | |
| 630 | CreateTempFile("foo.proto", |
| 631 | "syntax = \"proto2\";\n" |
| 632 | "message Foo {}\n"); |
| 633 | // Create the "a" and "b" sub-directories. |
| 634 | CreateTempDir("a"); |
| 635 | CreateTempDir("b"); |
| 636 | |
| 637 | Run("protocol_compiler " |
| 638 | "--test_opt=foo1 " |
| 639 | "--test_out=bar:$tmpdir/a " |
| 640 | "--test_opt=foo2 " |
| 641 | "--test_out=baz:$tmpdir/b " |
| 642 | "--test_opt=foo3 " |
| 643 | "--proto_path=$tmpdir foo.proto"); |
| 644 | |
| 645 | ExpectNoErrors(); |
| 646 | ExpectGenerated( |
| 647 | "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a"); |
| 648 | ExpectGenerated( |
| 649 | "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b"); |
| 650 | } |
| 651 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 652 | TEST_F(CommandLineInterfaceTest, Insert) { |
| 653 | // Test running a generator that inserts code into another's output. |
| 654 | |
| 655 | CreateTempFile("foo.proto", |
| 656 | "syntax = \"proto2\";\n" |
| 657 | "message Foo {}\n"); |
| 658 | |
| 659 | Run("protocol_compiler " |
| 660 | "--test_out=TestParameter:$tmpdir " |
| 661 | "--plug_out=TestPluginParameter:$tmpdir " |
| 662 | "--test_out=insert=test_generator,test_plugin:$tmpdir " |
| 663 | "--plug_out=insert=test_generator,test_plugin:$tmpdir " |
| 664 | "--proto_path=$tmpdir foo.proto"); |
| 665 | |
| 666 | ExpectNoErrors(); |
| 667 | ExpectGeneratedWithInsertions( |
| 668 | "test_generator", "TestParameter", "test_generator,test_plugin", |
| 669 | "foo.proto", "Foo"); |
| 670 | ExpectGeneratedWithInsertions( |
| 671 | "test_plugin", "TestPluginParameter", "test_generator,test_plugin", |
| 672 | "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 673 | } |
| 674 | |
liujisi@google.com | 9b7f6c5 | 2010-12-08 03:45:27 +0000 | [diff] [blame] | 675 | #if defined(_WIN32) |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 676 | |
| 677 | TEST_F(CommandLineInterfaceTest, WindowsOutputPath) { |
| 678 | // Test that the output path can be a Windows-style path. |
| 679 | |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 680 | CreateTempFile("foo.proto", |
| 681 | "syntax = \"proto2\";\n"); |
| 682 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 683 | Run("protocol_compiler --null_out=C:\\ " |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 684 | "--proto_path=$tmpdir foo.proto"); |
| 685 | |
| 686 | ExpectNoErrors(); |
kenton@google.com | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 687 | ExpectNullCodeGeneratorCalled(""); |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 688 | } |
| 689 | |
| 690 | TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) { |
| 691 | // Test that we can have a windows-style output path and a parameter. |
| 692 | |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 693 | CreateTempFile("foo.proto", |
| 694 | "syntax = \"proto2\";\n"); |
| 695 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 696 | Run("protocol_compiler --null_out=bar:C:\\ " |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 697 | "--proto_path=$tmpdir foo.proto"); |
| 698 | |
| 699 | ExpectNoErrors(); |
kenton@google.com | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 700 | ExpectNullCodeGeneratorCalled("bar"); |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 701 | } |
| 702 | |
kenton@google.com | ef3730c | 2009-04-28 00:49:36 +0000 | [diff] [blame] | 703 | TEST_F(CommandLineInterfaceTest, TrailingBackslash) { |
| 704 | // Test that the directories can end in backslashes. Some users claim this |
| 705 | // doesn't work on their system. |
| 706 | |
kenton@google.com | ef3730c | 2009-04-28 00:49:36 +0000 | [diff] [blame] | 707 | CreateTempFile("foo.proto", |
| 708 | "syntax = \"proto2\";\n" |
| 709 | "message Foo {}\n"); |
| 710 | |
| 711 | Run("protocol_compiler --test_out=$tmpdir\\ " |
| 712 | "--proto_path=$tmpdir\\ foo.proto"); |
| 713 | |
| 714 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 715 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
kenton@google.com | ef3730c | 2009-04-28 00:49:36 +0000 | [diff] [blame] | 716 | } |
| 717 | |
temporal | cc93043 | 2008-07-21 20:28:30 +0000 | [diff] [blame] | 718 | #endif // defined(_WIN32) || defined(__CYGWIN__) |
| 719 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 720 | TEST_F(CommandLineInterfaceTest, PathLookup) { |
| 721 | // Test that specifying multiple directories in the proto search path works. |
| 722 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 723 | CreateTempFile("b/bar.proto", |
| 724 | "syntax = \"proto2\";\n" |
| 725 | "message Bar {}\n"); |
| 726 | CreateTempFile("a/foo.proto", |
| 727 | "syntax = \"proto2\";\n" |
| 728 | "import \"bar.proto\";\n" |
| 729 | "message Foo {\n" |
| 730 | " optional Bar a = 1;\n" |
| 731 | "}\n"); |
| 732 | CreateTempFile("b/foo.proto", "this should not be parsed\n"); |
| 733 | |
| 734 | Run("protocol_compiler --test_out=$tmpdir " |
| 735 | "--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto"); |
| 736 | |
| 737 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 738 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 739 | } |
| 740 | |
| 741 | TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) { |
| 742 | // Same as PathLookup, but we provide the proto_path in a single flag. |
| 743 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 744 | CreateTempFile("b/bar.proto", |
| 745 | "syntax = \"proto2\";\n" |
| 746 | "message Bar {}\n"); |
| 747 | CreateTempFile("a/foo.proto", |
| 748 | "syntax = \"proto2\";\n" |
| 749 | "import \"bar.proto\";\n" |
| 750 | "message Foo {\n" |
| 751 | " optional Bar a = 1;\n" |
| 752 | "}\n"); |
| 753 | CreateTempFile("b/foo.proto", "this should not be parsed\n"); |
| 754 | |
| 755 | #undef PATH_SEPARATOR |
| 756 | #if defined(_WIN32) |
| 757 | #define PATH_SEPARATOR ";" |
| 758 | #else |
| 759 | #define PATH_SEPARATOR ":" |
| 760 | #endif |
| 761 | |
| 762 | Run("protocol_compiler --test_out=$tmpdir " |
Nobuaki Sukegawa | 8ba0e35 | 2014-11-30 19:42:51 +0900 | [diff] [blame] | 763 | "--proto_path=$tmpdir/a" PATH_SEPARATOR "$tmpdir/b foo.proto"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 764 | |
| 765 | #undef PATH_SEPARATOR |
| 766 | |
| 767 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 768 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 769 | } |
| 770 | |
| 771 | TEST_F(CommandLineInterfaceTest, NonRootMapping) { |
| 772 | // Test setting up a search path mapping a directory to a non-root location. |
| 773 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 774 | CreateTempFile("foo.proto", |
| 775 | "syntax = \"proto2\";\n" |
| 776 | "message Foo {}\n"); |
| 777 | |
| 778 | Run("protocol_compiler --test_out=$tmpdir " |
| 779 | "--proto_path=bar=$tmpdir bar/foo.proto"); |
| 780 | |
| 781 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 782 | ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 783 | } |
| 784 | |
| 785 | TEST_F(CommandLineInterfaceTest, MultipleGenerators) { |
| 786 | // Test that we can have multiple generators and use both in one invocation, |
| 787 | // each with a different output directory. |
| 788 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 789 | CreateTempFile("foo.proto", |
| 790 | "syntax = \"proto2\";\n" |
| 791 | "message Foo {}\n"); |
| 792 | // Create the "a" and "b" sub-directories. |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 793 | CreateTempDir("a"); |
| 794 | CreateTempDir("b"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 795 | |
| 796 | Run("protocol_compiler " |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 797 | "--test_out=$tmpdir/a " |
| 798 | "--alt_out=$tmpdir/b " |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 799 | "--proto_path=$tmpdir foo.proto"); |
| 800 | |
| 801 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 802 | ExpectGenerated("test_generator", "", "foo.proto", "Foo", "a"); |
| 803 | ExpectGenerated("alt_generator", "", "foo.proto", "Foo", "b"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 804 | } |
| 805 | |
| 806 | TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) { |
| 807 | // Test that --disallow_services doesn't cause a problem when there are no |
| 808 | // services. |
| 809 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 810 | CreateTempFile("foo.proto", |
| 811 | "syntax = \"proto2\";\n" |
| 812 | "message Foo {}\n"); |
| 813 | |
| 814 | Run("protocol_compiler --disallow_services --test_out=$tmpdir " |
| 815 | "--proto_path=$tmpdir foo.proto"); |
| 816 | |
| 817 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 818 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 819 | } |
| 820 | |
| 821 | TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) { |
| 822 | // Test that --disallow_services produces an error when there are services. |
| 823 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 824 | CreateTempFile("foo.proto", |
| 825 | "syntax = \"proto2\";\n" |
| 826 | "message Foo {}\n" |
| 827 | "service Bar {}\n"); |
| 828 | |
| 829 | Run("protocol_compiler --disallow_services --test_out=$tmpdir " |
| 830 | "--proto_path=$tmpdir foo.proto"); |
| 831 | |
| 832 | ExpectErrorSubstring("foo.proto: This file contains services"); |
| 833 | } |
| 834 | |
| 835 | TEST_F(CommandLineInterfaceTest, AllowServicesHasService) { |
| 836 | // Test that services work fine as long as --disallow_services is not used. |
| 837 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 838 | CreateTempFile("foo.proto", |
| 839 | "syntax = \"proto2\";\n" |
| 840 | "message Foo {}\n" |
| 841 | "service Bar {}\n"); |
| 842 | |
| 843 | Run("protocol_compiler --test_out=$tmpdir " |
| 844 | "--proto_path=$tmpdir foo.proto"); |
| 845 | |
| 846 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 847 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 848 | } |
| 849 | |
| 850 | TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) { |
| 851 | // Test that we can accept working-directory-relative input files. |
| 852 | |
| 853 | SetInputsAreProtoPathRelative(false); |
| 854 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 855 | CreateTempFile("foo.proto", |
| 856 | "syntax = \"proto2\";\n" |
| 857 | "message Foo {}\n"); |
| 858 | |
| 859 | Run("protocol_compiler --test_out=$tmpdir " |
| 860 | "--proto_path=$tmpdir $tmpdir/foo.proto"); |
| 861 | |
| 862 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 863 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 864 | } |
| 865 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 866 | TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { |
| 867 | CreateTempFile("foo.proto", |
| 868 | "syntax = \"proto2\";\n" |
| 869 | "message Foo {}\n"); |
| 870 | CreateTempFile("bar.proto", |
| 871 | "syntax = \"proto2\";\n" |
| 872 | "import \"foo.proto\";\n" |
| 873 | "message Bar {\n" |
| 874 | " optional Foo foo = 1;\n" |
| 875 | "}\n"); |
| 876 | |
| 877 | Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " |
| 878 | "--proto_path=$tmpdir bar.proto"); |
| 879 | |
| 880 | ExpectNoErrors(); |
| 881 | |
| 882 | FileDescriptorSet descriptor_set; |
| 883 | ReadDescriptorSet("descriptor_set", &descriptor_set); |
| 884 | if (HasFatalFailure()) return; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 885 | EXPECT_EQ(1, descriptor_set.file_size()); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 886 | EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 887 | // Descriptor set should not have source code info. |
| 888 | EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 889 | // Descriptor set should have json_name. |
| 890 | EXPECT_EQ("Bar", descriptor_set.file(0).message_type(0).name()); |
| 891 | EXPECT_EQ("foo", descriptor_set.file(0).message_type(0).field(0).name()); |
| 892 | EXPECT_TRUE(descriptor_set.file(0).message_type(0).field(0).has_json_name()); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 893 | } |
| 894 | |
Feng Xiao | eee38b0 | 2015-08-22 18:25:48 -0700 | [diff] [blame] | 895 | TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) { |
| 896 | CreateTempFile("foo.proto", |
| 897 | "syntax = \"proto2\";\n" |
| 898 | "message Foo {}\n"); |
| 899 | CreateTempFile("bar.proto", |
| 900 | "syntax = \"proto2\";\n" |
| 901 | "import \"foo.proto\";\n" |
| 902 | "message Bar {\n" |
| 903 | " optional Foo foo = 1;\n" |
| 904 | "}\n"); |
| 905 | CreateTempFile("baz.proto", |
| 906 | "syntax = \"proto2\";\n" |
| 907 | "import \"foo.proto\";\n" |
| 908 | "message Baz {\n" |
| 909 | " optional Foo foo = 1;\n" |
| 910 | "}\n"); |
| 911 | |
| 912 | Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " |
| 913 | "--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto"); |
| 914 | |
| 915 | ExpectNoErrors(); |
| 916 | |
| 917 | FileDescriptorSet descriptor_set; |
| 918 | ReadDescriptorSet("descriptor_set", &descriptor_set); |
| 919 | if (HasFatalFailure()) return; |
| 920 | EXPECT_EQ(3, descriptor_set.file_size()); |
| 921 | EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); |
| 922 | EXPECT_EQ("foo.proto", descriptor_set.file(1).name()); |
| 923 | EXPECT_EQ("baz.proto", descriptor_set.file(2).name()); |
| 924 | // Descriptor set should not have source code info. |
| 925 | EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 926 | // Descriptor set should have json_name. |
| 927 | EXPECT_EQ("Bar", descriptor_set.file(0).message_type(0).name()); |
| 928 | EXPECT_EQ("foo", descriptor_set.file(0).message_type(0).field(0).name()); |
| 929 | EXPECT_TRUE(descriptor_set.file(0).message_type(0).field(0).has_json_name()); |
Feng Xiao | eee38b0 | 2015-08-22 18:25:48 -0700 | [diff] [blame] | 930 | } |
| 931 | |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 932 | TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { |
| 933 | CreateTempFile("foo.proto", |
| 934 | "syntax = \"proto2\";\n" |
| 935 | "message Foo {}\n"); |
| 936 | CreateTempFile("bar.proto", |
| 937 | "syntax = \"proto2\";\n" |
| 938 | "import \"foo.proto\";\n" |
| 939 | "message Bar {\n" |
| 940 | " optional Foo foo = 1;\n" |
| 941 | "}\n"); |
| 942 | |
| 943 | Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " |
| 944 | "--include_source_info --proto_path=$tmpdir bar.proto"); |
| 945 | |
| 946 | ExpectNoErrors(); |
| 947 | |
| 948 | FileDescriptorSet descriptor_set; |
| 949 | ReadDescriptorSet("descriptor_set", &descriptor_set); |
| 950 | if (HasFatalFailure()) return; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 951 | EXPECT_EQ(1, descriptor_set.file_size()); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 952 | EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); |
| 953 | // Source code info included. |
| 954 | EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 955 | } |
| 956 | |
| 957 | TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { |
| 958 | CreateTempFile("foo.proto", |
| 959 | "syntax = \"proto2\";\n" |
| 960 | "message Foo {}\n"); |
| 961 | CreateTempFile("bar.proto", |
| 962 | "syntax = \"proto2\";\n" |
| 963 | "import \"foo.proto\";\n" |
| 964 | "message Bar {\n" |
| 965 | " optional Foo foo = 1;\n" |
| 966 | "}\n"); |
| 967 | |
| 968 | Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " |
| 969 | "--include_imports --proto_path=$tmpdir bar.proto"); |
| 970 | |
| 971 | ExpectNoErrors(); |
| 972 | |
| 973 | FileDescriptorSet descriptor_set; |
| 974 | ReadDescriptorSet("descriptor_set", &descriptor_set); |
| 975 | if (HasFatalFailure()) return; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 976 | EXPECT_EQ(2, descriptor_set.file_size()); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 977 | if (descriptor_set.file(0).name() == "bar.proto") { |
kenton@google.com | 7fb9ae9 | 2009-09-02 02:42:56 +0000 | [diff] [blame] | 978 | std::swap(descriptor_set.mutable_file()->mutable_data()[0], |
| 979 | descriptor_set.mutable_file()->mutable_data()[1]); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 980 | } |
| 981 | EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); |
| 982 | EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 983 | // Descriptor set should not have source code info. |
| 984 | EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); |
| 985 | EXPECT_FALSE(descriptor_set.file(1).has_source_code_info()); |
| 986 | } |
| 987 | |
| 988 | TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { |
| 989 | CreateTempFile("foo.proto", |
| 990 | "syntax = \"proto2\";\n" |
| 991 | "message Foo {}\n"); |
| 992 | CreateTempFile("bar.proto", |
| 993 | "syntax = \"proto2\";\n" |
| 994 | "import \"foo.proto\";\n" |
| 995 | "message Bar {\n" |
| 996 | " optional Foo foo = 1;\n" |
| 997 | "}\n"); |
| 998 | |
| 999 | Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " |
| 1000 | "--include_imports --include_source_info --proto_path=$tmpdir bar.proto"); |
| 1001 | |
| 1002 | ExpectNoErrors(); |
| 1003 | |
| 1004 | FileDescriptorSet descriptor_set; |
| 1005 | ReadDescriptorSet("descriptor_set", &descriptor_set); |
| 1006 | if (HasFatalFailure()) return; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1007 | EXPECT_EQ(2, descriptor_set.file_size()); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1008 | if (descriptor_set.file(0).name() == "bar.proto") { |
| 1009 | std::swap(descriptor_set.mutable_file()->mutable_data()[0], |
| 1010 | descriptor_set.mutable_file()->mutable_data()[1]); |
| 1011 | } |
| 1012 | EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); |
| 1013 | EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); |
| 1014 | // Source code info included. |
| 1015 | EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); |
| 1016 | EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1017 | } |
| 1018 | |
Bo Yang | cf603a9 | 2015-05-24 22:28:04 -0700 | [diff] [blame] | 1019 | #ifdef _WIN32 |
| 1020 | // TODO(teboring): Figure out how to write test on windows. |
| 1021 | #else |
Bo Yang | e2555e2 | 2015-02-07 15:28:54 -0800 | [diff] [blame] | 1022 | TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { |
| 1023 | CreateTempFile("foo.proto", |
| 1024 | "syntax = \"proto2\";\n" |
| 1025 | "message Foo {}\n"); |
| 1026 | CreateTempFile("bar.proto", |
| 1027 | "syntax = \"proto2\";\n" |
| 1028 | "import \"foo.proto\";\n" |
| 1029 | "message Bar {\n" |
| 1030 | " optional Foo foo = 1;\n" |
| 1031 | "}\n"); |
| 1032 | |
| 1033 | Run("protocol_compiler --dependency_out=$tmpdir/manifest " |
| 1034 | "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto"); |
| 1035 | |
| 1036 | ExpectErrorText( |
| 1037 | "Can only process one input file when using --dependency_out=FILE.\n"); |
| 1038 | } |
| 1039 | |
Bo Yang | 5db2173 | 2015-05-21 14:28:59 -0700 | [diff] [blame] | 1040 | #ifdef PROTOBUF_OPENSOURCE |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1041 | TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { |
| 1042 | CreateTempFile("foo.proto", |
| 1043 | "syntax = \"proto2\";\n" |
| 1044 | "message Foo {}\n"); |
| 1045 | CreateTempFile("bar.proto", |
| 1046 | "syntax = \"proto2\";\n" |
| 1047 | "import \"foo.proto\";\n" |
| 1048 | "message Bar {\n" |
| 1049 | " optional Foo foo = 1;\n" |
| 1050 | "}\n"); |
| 1051 | |
Tamir Duberstein | ed71504 | 2015-03-18 00:43:34 -0700 | [diff] [blame] | 1052 | string current_working_directory = getcwd(NULL, 0); |
Bo Yang | eb2ce02 | 2015-02-09 11:57:41 -0800 | [diff] [blame] | 1053 | SwitchToTempDirectory(); |
| 1054 | |
| 1055 | Run("protocol_compiler --dependency_out=manifest --test_out=. " |
| 1056 | "bar.proto"); |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1057 | |
| 1058 | ExpectNoErrors(); |
| 1059 | |
| 1060 | ExpectFileContent("manifest", |
Bo Yang | eb2ce02 | 2015-02-09 11:57:41 -0800 | [diff] [blame] | 1061 | "bar.proto.MockCodeGenerator.test_generator: " |
| 1062 | "foo.proto\\\n bar.proto"); |
| 1063 | |
| 1064 | File::ChangeWorkingDirectory(current_working_directory); |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1065 | } |
Bo Yang | 5db2173 | 2015-05-21 14:28:59 -0700 | [diff] [blame] | 1066 | #else // !PROTOBUF_OPENSOURCE |
| 1067 | // TODO(teboring): Figure out how to change and get working directory in |
| 1068 | // google3. |
| 1069 | #endif // !PROTOBUF_OPENSOURCE |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1070 | |
Bo Yang | eb2ce02 | 2015-02-09 11:57:41 -0800 | [diff] [blame] | 1071 | TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1072 | CreateTempFile("foo.proto", |
| 1073 | "syntax = \"proto2\";\n" |
| 1074 | "message Foo {}\n"); |
| 1075 | CreateTempFile("bar.proto", |
| 1076 | "syntax = \"proto2\";\n" |
| 1077 | "import \"foo.proto\";\n" |
| 1078 | "message Bar {\n" |
| 1079 | " optional Foo foo = 1;\n" |
| 1080 | "}\n"); |
| 1081 | |
Bo Yang | eb2ce02 | 2015-02-09 11:57:41 -0800 | [diff] [blame] | 1082 | Run("protocol_compiler --dependency_out=$tmpdir/manifest " |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1083 | "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); |
| 1084 | |
| 1085 | ExpectNoErrors(); |
| 1086 | |
| 1087 | ExpectFileContent("manifest", |
Bo Yang | e2555e2 | 2015-02-07 15:28:54 -0800 | [diff] [blame] | 1088 | "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " |
| 1089 | "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1090 | } |
Bo Yang | cf603a9 | 2015-05-24 22:28:04 -0700 | [diff] [blame] | 1091 | #endif // !_WIN32 |
Bo Yang | 5914ce7 | 2015-02-03 21:35:50 -0800 | [diff] [blame] | 1092 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1093 | // ------------------------------------------------------------------- |
| 1094 | |
| 1095 | TEST_F(CommandLineInterfaceTest, ParseErrors) { |
| 1096 | // Test that parse errors are reported. |
| 1097 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1098 | CreateTempFile("foo.proto", |
| 1099 | "syntax = \"proto2\";\n" |
| 1100 | "badsyntax\n"); |
| 1101 | |
| 1102 | Run("protocol_compiler --test_out=$tmpdir " |
| 1103 | "--proto_path=$tmpdir foo.proto"); |
| 1104 | |
| 1105 | ExpectErrorText( |
| 1106 | "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); |
| 1107 | } |
| 1108 | |
| 1109 | TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) { |
| 1110 | // Test that parse errors are reported from multiple files. |
| 1111 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1112 | // We set up files such that foo.proto actually depends on bar.proto in |
| 1113 | // two ways: Directly and through baz.proto. bar.proto's errors should |
| 1114 | // only be reported once. |
| 1115 | CreateTempFile("bar.proto", |
| 1116 | "syntax = \"proto2\";\n" |
| 1117 | "badsyntax\n"); |
| 1118 | CreateTempFile("baz.proto", |
| 1119 | "syntax = \"proto2\";\n" |
| 1120 | "import \"bar.proto\";\n"); |
| 1121 | CreateTempFile("foo.proto", |
| 1122 | "syntax = \"proto2\";\n" |
| 1123 | "import \"bar.proto\";\n" |
| 1124 | "import \"baz.proto\";\n"); |
| 1125 | |
| 1126 | Run("protocol_compiler --test_out=$tmpdir " |
| 1127 | "--proto_path=$tmpdir foo.proto"); |
| 1128 | |
| 1129 | ExpectErrorText( |
| 1130 | "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n" |
| 1131 | "baz.proto: Import \"bar.proto\" was not found or had errors.\n" |
| 1132 | "foo.proto: Import \"bar.proto\" was not found or had errors.\n" |
| 1133 | "foo.proto: Import \"baz.proto\" was not found or had errors.\n"); |
| 1134 | } |
| 1135 | |
| 1136 | TEST_F(CommandLineInterfaceTest, InputNotFoundError) { |
| 1137 | // Test what happens if the input file is not found. |
| 1138 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1139 | Run("protocol_compiler --test_out=$tmpdir " |
| 1140 | "--proto_path=$tmpdir foo.proto"); |
| 1141 | |
| 1142 | ExpectErrorText( |
| 1143 | "foo.proto: File not found.\n"); |
| 1144 | } |
| 1145 | |
| 1146 | TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) { |
| 1147 | // Test what happens when a working-directory-relative input file is not |
| 1148 | // found. |
| 1149 | |
| 1150 | SetInputsAreProtoPathRelative(false); |
| 1151 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1152 | Run("protocol_compiler --test_out=$tmpdir " |
| 1153 | "--proto_path=$tmpdir $tmpdir/foo.proto"); |
| 1154 | |
| 1155 | ExpectErrorText( |
| 1156 | "$tmpdir/foo.proto: No such file or directory\n"); |
| 1157 | } |
| 1158 | |
| 1159 | TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) { |
| 1160 | // Test what happens when a working-directory-relative input file is not |
| 1161 | // mapped to a virtual path. |
| 1162 | |
| 1163 | SetInputsAreProtoPathRelative(false); |
| 1164 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1165 | CreateTempFile("foo.proto", |
| 1166 | "syntax = \"proto2\";\n" |
| 1167 | "message Foo {}\n"); |
| 1168 | |
| 1169 | // Create a directory called "bar" so that we can point --proto_path at it. |
| 1170 | CreateTempFile("bar/dummy", ""); |
| 1171 | |
| 1172 | Run("protocol_compiler --test_out=$tmpdir " |
| 1173 | "--proto_path=$tmpdir/bar $tmpdir/foo.proto"); |
| 1174 | |
| 1175 | ExpectErrorText( |
| 1176 | "$tmpdir/foo.proto: File does not reside within any path " |
| 1177 | "specified using --proto_path (or -I). You must specify a " |
kenton@google.com | 477f799 | 2009-10-07 21:38:11 +0000 | [diff] [blame] | 1178 | "--proto_path which encompasses this file. Note that the " |
| 1179 | "proto_path must be an exact prefix of the .proto file " |
| 1180 | "names -- protoc is too dumb to figure out when two paths " |
| 1181 | "(e.g. absolute and relative) are equivalent (it's harder " |
| 1182 | "than you think).\n"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1183 | } |
| 1184 | |
| 1185 | TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) { |
| 1186 | // Check what happens if the input file is not found *and* is not mapped |
| 1187 | // in the proto_path. |
| 1188 | |
| 1189 | SetInputsAreProtoPathRelative(false); |
| 1190 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1191 | // Create a directory called "bar" so that we can point --proto_path at it. |
| 1192 | CreateTempFile("bar/dummy", ""); |
| 1193 | |
| 1194 | Run("protocol_compiler --test_out=$tmpdir " |
| 1195 | "--proto_path=$tmpdir/bar $tmpdir/foo.proto"); |
| 1196 | |
| 1197 | ExpectErrorText( |
| 1198 | "$tmpdir/foo.proto: No such file or directory\n"); |
| 1199 | } |
| 1200 | |
| 1201 | TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) { |
| 1202 | // Test what happens when a working-directory-relative input file is shadowed |
| 1203 | // by another file in the virtual path. |
| 1204 | |
| 1205 | SetInputsAreProtoPathRelative(false); |
| 1206 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1207 | CreateTempFile("foo/foo.proto", |
| 1208 | "syntax = \"proto2\";\n" |
| 1209 | "message Foo {}\n"); |
| 1210 | CreateTempFile("bar/foo.proto", |
| 1211 | "syntax = \"proto2\";\n" |
| 1212 | "message Bar {}\n"); |
| 1213 | |
| 1214 | Run("protocol_compiler --test_out=$tmpdir " |
| 1215 | "--proto_path=$tmpdir/foo --proto_path=$tmpdir/bar " |
| 1216 | "$tmpdir/bar/foo.proto"); |
| 1217 | |
| 1218 | ExpectErrorText( |
| 1219 | "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path " |
| 1220 | "by \"$tmpdir/foo/foo.proto\". Either use the latter " |
| 1221 | "file as your input or reorder the --proto_path so that the " |
| 1222 | "former file's location comes first.\n"); |
| 1223 | } |
| 1224 | |
| 1225 | TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) { |
| 1226 | // Test what happens if the input file is not found. |
| 1227 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1228 | Run("protocol_compiler --test_out=$tmpdir " |
| 1229 | "--proto_path=$tmpdir/foo foo.proto"); |
| 1230 | |
| 1231 | ExpectErrorText( |
| 1232 | "$tmpdir/foo: warning: directory does not exist.\n" |
| 1233 | "foo.proto: File not found.\n"); |
| 1234 | } |
| 1235 | |
| 1236 | TEST_F(CommandLineInterfaceTest, MissingInputError) { |
| 1237 | // Test that we get an error if no inputs are given. |
| 1238 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1239 | Run("protocol_compiler --test_out=$tmpdir " |
| 1240 | "--proto_path=$tmpdir"); |
| 1241 | |
| 1242 | ExpectErrorText("Missing input file.\n"); |
| 1243 | } |
| 1244 | |
| 1245 | TEST_F(CommandLineInterfaceTest, MissingOutputError) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1246 | CreateTempFile("foo.proto", |
| 1247 | "syntax = \"proto2\";\n" |
| 1248 | "message Foo {}\n"); |
| 1249 | |
| 1250 | Run("protocol_compiler --proto_path=$tmpdir foo.proto"); |
| 1251 | |
| 1252 | ExpectErrorText("Missing output directives.\n"); |
| 1253 | } |
| 1254 | |
| 1255 | TEST_F(CommandLineInterfaceTest, OutputWriteError) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1256 | CreateTempFile("foo.proto", |
| 1257 | "syntax = \"proto2\";\n" |
| 1258 | "message Foo {}\n"); |
| 1259 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1260 | string output_file = |
| 1261 | MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto"); |
| 1262 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1263 | // Create a directory blocking our output location. |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1264 | CreateTempDir(output_file); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1265 | |
| 1266 | Run("protocol_compiler --test_out=$tmpdir " |
| 1267 | "--proto_path=$tmpdir foo.proto"); |
| 1268 | |
kenton@google.com | 5f12164 | 2009-12-23 07:03:06 +0000 | [diff] [blame] | 1269 | // MockCodeGenerator no longer detects an error because we actually write to |
| 1270 | // an in-memory location first, then dump to disk at the end. This is no |
| 1271 | // big deal. |
| 1272 | // ExpectErrorSubstring("MockCodeGenerator detected write error."); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1273 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1274 | #if defined(_WIN32) && !defined(__CYGWIN__) |
| 1275 | // Windows with MSVCRT.dll produces EPERM instead of EISDIR. |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1276 | if (HasAlternateErrorSubstring(output_file + ": Permission denied")) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1277 | return; |
| 1278 | } |
| 1279 | #endif |
| 1280 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1281 | ExpectErrorSubstring(output_file + ": Is a directory"); |
| 1282 | } |
| 1283 | |
| 1284 | TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) { |
| 1285 | CreateTempFile("foo.proto", |
| 1286 | "syntax = \"proto2\";\n" |
| 1287 | "message Foo {}\n"); |
| 1288 | |
| 1289 | string output_file = |
| 1290 | MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto"); |
| 1291 | |
| 1292 | // Create a directory blocking our output location. |
| 1293 | CreateTempDir(output_file); |
| 1294 | |
| 1295 | Run("protocol_compiler --plug_out=$tmpdir " |
| 1296 | "--proto_path=$tmpdir foo.proto"); |
| 1297 | |
| 1298 | #if defined(_WIN32) && !defined(__CYGWIN__) |
| 1299 | // Windows with MSVCRT.dll produces EPERM instead of EISDIR. |
| 1300 | if (HasAlternateErrorSubstring(output_file + ": Permission denied")) { |
| 1301 | return; |
| 1302 | } |
| 1303 | #endif |
| 1304 | |
| 1305 | ExpectErrorSubstring(output_file + ": Is a directory"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1306 | } |
| 1307 | |
| 1308 | TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1309 | CreateTempFile("foo.proto", |
| 1310 | "syntax = \"proto2\";\n" |
| 1311 | "message Foo {}\n"); |
| 1312 | |
| 1313 | Run("protocol_compiler --test_out=$tmpdir/nosuchdir " |
| 1314 | "--proto_path=$tmpdir foo.proto"); |
| 1315 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1316 | ExpectErrorSubstring("nosuchdir/: No such file or directory"); |
| 1317 | } |
| 1318 | |
| 1319 | TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) { |
| 1320 | CreateTempFile("foo.proto", |
| 1321 | "syntax = \"proto2\";\n" |
| 1322 | "message Foo {}\n"); |
| 1323 | |
| 1324 | Run("protocol_compiler --plug_out=$tmpdir/nosuchdir " |
| 1325 | "--proto_path=$tmpdir foo.proto"); |
| 1326 | |
| 1327 | ExpectErrorSubstring("nosuchdir/: No such file or directory"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1328 | } |
| 1329 | |
| 1330 | TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1331 | CreateTempFile("foo.proto", |
| 1332 | "syntax = \"proto2\";\n" |
| 1333 | "message Foo {}\n"); |
| 1334 | |
| 1335 | Run("protocol_compiler --test_out=$tmpdir/foo.proto " |
| 1336 | "--proto_path=$tmpdir foo.proto"); |
| 1337 | |
| 1338 | #if defined(_WIN32) && !defined(__CYGWIN__) |
| 1339 | // Windows with MSVCRT.dll produces EINVAL instead of ENOTDIR. |
| 1340 | if (HasAlternateErrorSubstring("foo.proto/: Invalid argument")) { |
| 1341 | return; |
| 1342 | } |
| 1343 | #endif |
| 1344 | |
| 1345 | ExpectErrorSubstring("foo.proto/: Not a directory"); |
| 1346 | } |
| 1347 | |
| 1348 | TEST_F(CommandLineInterfaceTest, GeneratorError) { |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1349 | CreateTempFile("foo.proto", |
| 1350 | "syntax = \"proto2\";\n" |
| 1351 | "message MockCodeGenerator_Error {}\n"); |
| 1352 | |
| 1353 | Run("protocol_compiler --test_out=$tmpdir " |
| 1354 | "--proto_path=$tmpdir foo.proto"); |
| 1355 | |
| 1356 | ExpectErrorSubstring( |
| 1357 | "--test_out: foo.proto: Saw message type MockCodeGenerator_Error."); |
| 1358 | } |
| 1359 | |
| 1360 | TEST_F(CommandLineInterfaceTest, GeneratorPluginError) { |
| 1361 | // Test a generator plugin that returns an error. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1362 | |
| 1363 | CreateTempFile("foo.proto", |
| 1364 | "syntax = \"proto2\";\n" |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1365 | "message MockCodeGenerator_Error {}\n"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1366 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1367 | Run("protocol_compiler --plug_out=TestParameter:$tmpdir " |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1368 | "--proto_path=$tmpdir foo.proto"); |
| 1369 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1370 | ExpectErrorSubstring( |
| 1371 | "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error."); |
| 1372 | } |
| 1373 | |
| 1374 | TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) { |
| 1375 | // Test a generator plugin that exits with an error code. |
| 1376 | |
| 1377 | CreateTempFile("foo.proto", |
| 1378 | "syntax = \"proto2\";\n" |
| 1379 | "message MockCodeGenerator_Exit {}\n"); |
| 1380 | |
| 1381 | Run("protocol_compiler --plug_out=TestParameter:$tmpdir " |
| 1382 | "--proto_path=$tmpdir foo.proto"); |
| 1383 | |
| 1384 | ExpectErrorSubstring("Saw message type MockCodeGenerator_Exit."); |
| 1385 | ExpectErrorSubstring( |
| 1386 | "--plug_out: prefix-gen-plug: Plugin failed with status code 123."); |
| 1387 | } |
| 1388 | |
| 1389 | TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) { |
| 1390 | // Test a generator plugin that crashes. |
| 1391 | |
| 1392 | CreateTempFile("foo.proto", |
| 1393 | "syntax = \"proto2\";\n" |
| 1394 | "message MockCodeGenerator_Abort {}\n"); |
| 1395 | |
| 1396 | Run("protocol_compiler --plug_out=TestParameter:$tmpdir " |
| 1397 | "--proto_path=$tmpdir foo.proto"); |
| 1398 | |
| 1399 | ExpectErrorSubstring("Saw message type MockCodeGenerator_Abort."); |
| 1400 | |
kenton@google.com | 684d45b | 2009-12-19 04:50:00 +0000 | [diff] [blame] | 1401 | #ifdef _WIN32 |
| 1402 | // Windows doesn't have signals. It looks like abort()ing causes the process |
| 1403 | // to exit with status code 3, but let's not depend on the exact number here. |
| 1404 | ExpectErrorSubstring( |
| 1405 | "--plug_out: prefix-gen-plug: Plugin failed with status code"); |
| 1406 | #else |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1407 | // Don't depend on the exact signal number. |
| 1408 | ExpectErrorSubstring( |
| 1409 | "--plug_out: prefix-gen-plug: Plugin killed by signal"); |
kenton@google.com | 684d45b | 2009-12-19 04:50:00 +0000 | [diff] [blame] | 1410 | #endif |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1411 | } |
| 1412 | |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1413 | TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) { |
| 1414 | CreateTempFile("foo.proto", |
| 1415 | "syntax = \"proto2\";\n" |
| 1416 | "message MockCodeGenerator_HasSourceCodeInfo {}\n"); |
| 1417 | |
| 1418 | Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); |
| 1419 | |
| 1420 | ExpectErrorSubstring( |
| 1421 | "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1."); |
| 1422 | } |
| 1423 | |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 1424 | TEST_F(CommandLineInterfaceTest, PluginReceivesJsonName) { |
| 1425 | CreateTempFile("foo.proto", |
| 1426 | "syntax = \"proto2\";\n" |
| 1427 | "message MockCodeGenerator_HasJsonName {\n" |
| 1428 | " optional int32 value = 1;\n" |
| 1429 | "}\n"); |
| 1430 | |
| 1431 | Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); |
| 1432 | |
| 1433 | ExpectErrorSubstring("Saw json_name: 1"); |
| 1434 | } |
| 1435 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1436 | TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { |
| 1437 | // Test what happens if the plugin isn't found. |
| 1438 | |
| 1439 | CreateTempFile("error.proto", |
| 1440 | "syntax = \"proto2\";\n" |
| 1441 | "message Foo {}\n"); |
| 1442 | |
| 1443 | Run("protocol_compiler --badplug_out=TestParameter:$tmpdir " |
| 1444 | "--plugin=prefix-gen-badplug=no_such_file " |
| 1445 | "--proto_path=$tmpdir error.proto"); |
| 1446 | |
kenton@google.com | 684d45b | 2009-12-19 04:50:00 +0000 | [diff] [blame] | 1447 | #ifdef _WIN32 |
liujisi@google.com | 57014ff | 2010-12-21 05:56:35 +0000 | [diff] [blame] | 1448 | ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " + |
| 1449 | Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); |
kenton@google.com | 684d45b | 2009-12-19 04:50:00 +0000 | [diff] [blame] | 1450 | #else |
| 1451 | // Error written to stdout by child process after exec() fails. |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1452 | ExpectErrorSubstring( |
| 1453 | "no_such_file: program not found or is not executable"); |
| 1454 | |
kenton@google.com | 684d45b | 2009-12-19 04:50:00 +0000 | [diff] [blame] | 1455 | // Error written by parent process when child fails. |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1456 | ExpectErrorSubstring( |
| 1457 | "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1."); |
kenton@google.com | 684d45b | 2009-12-19 04:50:00 +0000 | [diff] [blame] | 1458 | #endif |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1459 | } |
| 1460 | |
| 1461 | TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) { |
| 1462 | // Test what happens if plugins aren't allowed. |
| 1463 | |
| 1464 | CreateTempFile("error.proto", |
| 1465 | "syntax = \"proto2\";\n" |
| 1466 | "message Foo {}\n"); |
| 1467 | |
| 1468 | DisallowPlugins(); |
| 1469 | Run("protocol_compiler --plug_out=TestParameter:$tmpdir " |
| 1470 | "--proto_path=$tmpdir error.proto"); |
| 1471 | |
| 1472 | ExpectErrorSubstring("Unknown flag: --plug_out"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1473 | } |
| 1474 | |
| 1475 | TEST_F(CommandLineInterfaceTest, HelpText) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1476 | Run("test_exec_name --help"); |
| 1477 | |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1478 | ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name "); |
| 1479 | ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR"); |
| 1480 | ExpectErrorSubstringWithZeroReturnCode("Test output."); |
| 1481 | ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR"); |
| 1482 | ExpectErrorSubstringWithZeroReturnCode("Alt output."); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1483 | } |
| 1484 | |
kenton@google.com | f663b16 | 2009-04-15 19:50:54 +0000 | [diff] [blame] | 1485 | TEST_F(CommandLineInterfaceTest, GccFormatErrors) { |
| 1486 | // Test --error_format=gcc (which is the default, but we want to verify |
| 1487 | // that it can be set explicitly). |
| 1488 | |
kenton@google.com | f663b16 | 2009-04-15 19:50:54 +0000 | [diff] [blame] | 1489 | CreateTempFile("foo.proto", |
| 1490 | "syntax = \"proto2\";\n" |
| 1491 | "badsyntax\n"); |
| 1492 | |
| 1493 | Run("protocol_compiler --test_out=$tmpdir " |
| 1494 | "--proto_path=$tmpdir --error_format=gcc foo.proto"); |
| 1495 | |
| 1496 | ExpectErrorText( |
| 1497 | "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); |
| 1498 | } |
| 1499 | |
| 1500 | TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) { |
| 1501 | // Test --error_format=msvs |
| 1502 | |
kenton@google.com | f663b16 | 2009-04-15 19:50:54 +0000 | [diff] [blame] | 1503 | CreateTempFile("foo.proto", |
| 1504 | "syntax = \"proto2\";\n" |
| 1505 | "badsyntax\n"); |
| 1506 | |
| 1507 | Run("protocol_compiler --test_out=$tmpdir " |
| 1508 | "--proto_path=$tmpdir --error_format=msvs foo.proto"); |
| 1509 | |
| 1510 | ExpectErrorText( |
kenton@google.com | 6793c1a | 2010-04-05 21:45:45 +0000 | [diff] [blame] | 1511 | "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement " |
kenton@google.com | f663b16 | 2009-04-15 19:50:54 +0000 | [diff] [blame] | 1512 | "(e.g. \"message\").\n"); |
| 1513 | } |
| 1514 | |
| 1515 | TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) { |
| 1516 | // Test --error_format=msvs |
| 1517 | |
kenton@google.com | f663b16 | 2009-04-15 19:50:54 +0000 | [diff] [blame] | 1518 | CreateTempFile("foo.proto", |
| 1519 | "syntax = \"proto2\";\n" |
| 1520 | "badsyntax\n"); |
| 1521 | |
| 1522 | Run("protocol_compiler --test_out=$tmpdir " |
| 1523 | "--proto_path=$tmpdir --error_format=invalid foo.proto"); |
| 1524 | |
| 1525 | ExpectErrorText( |
| 1526 | "Unknown error format: invalid\n"); |
| 1527 | } |
| 1528 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1529 | // ------------------------------------------------------------------- |
| 1530 | // Flag parsing tests |
| 1531 | |
| 1532 | TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) { |
| 1533 | // Test that a single-character flag works. |
| 1534 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1535 | CreateTempFile("foo.proto", |
| 1536 | "syntax = \"proto2\";\n" |
| 1537 | "message Foo {}\n"); |
| 1538 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1539 | Run("protocol_compiler -t$tmpdir " |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1540 | "--proto_path=$tmpdir foo.proto"); |
| 1541 | |
| 1542 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1543 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1544 | } |
| 1545 | |
| 1546 | TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) { |
| 1547 | // Test that separating the flag value with a space works. |
| 1548 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1549 | CreateTempFile("foo.proto", |
| 1550 | "syntax = \"proto2\";\n" |
| 1551 | "message Foo {}\n"); |
| 1552 | |
| 1553 | Run("protocol_compiler --test_out $tmpdir " |
| 1554 | "--proto_path=$tmpdir foo.proto"); |
| 1555 | |
| 1556 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1557 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1558 | } |
| 1559 | |
| 1560 | TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) { |
| 1561 | // Test that separating the flag value with a space works for |
| 1562 | // single-character flags. |
| 1563 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1564 | CreateTempFile("foo.proto", |
| 1565 | "syntax = \"proto2\";\n" |
| 1566 | "message Foo {}\n"); |
| 1567 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1568 | Run("protocol_compiler -t $tmpdir " |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1569 | "--proto_path=$tmpdir foo.proto"); |
| 1570 | |
| 1571 | ExpectNoErrors(); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1572 | ExpectGenerated("test_generator", "", "foo.proto", "Foo"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1573 | } |
| 1574 | |
| 1575 | TEST_F(CommandLineInterfaceTest, MissingValueError) { |
| 1576 | // Test that we get an error if a flag is missing its value. |
| 1577 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1578 | Run("protocol_compiler --test_out --proto_path=$tmpdir foo.proto"); |
| 1579 | |
| 1580 | ExpectErrorText("Missing value for flag: --test_out\n"); |
| 1581 | } |
| 1582 | |
| 1583 | TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) { |
| 1584 | // Test that we get an error if the last argument is a flag requiring a |
| 1585 | // value. |
| 1586 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1587 | Run("protocol_compiler --test_out"); |
| 1588 | |
| 1589 | ExpectErrorText("Missing value for flag: --test_out\n"); |
| 1590 | } |
| 1591 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1592 | TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) { |
| 1593 | CreateTempFile( |
| 1594 | "foo.proto", |
| 1595 | "syntax = \"proto2\";\n" |
| 1596 | "package foo;\n" |
| 1597 | "message Foo {\n" |
| 1598 | " optional int32 a = 2;\n" |
| 1599 | " optional string b = 4;\n" |
| 1600 | " optional string c = 5;\n" |
| 1601 | " optional int64 d = 8;\n" |
| 1602 | " optional double e = 10;\n" |
| 1603 | "}\n"); |
| 1604 | CreateTempFile( |
| 1605 | "bar.proto", |
| 1606 | "syntax = \"proto2\";\n" |
| 1607 | "message Bar {\n" |
| 1608 | " optional int32 a = 2;\n" |
| 1609 | " extensions 4 to 5;\n" |
| 1610 | " optional int64 d = 8;\n" |
| 1611 | " extensions 10;\n" |
| 1612 | "}\n"); |
| 1613 | CreateTempFile( |
| 1614 | "baz.proto", |
| 1615 | "syntax = \"proto2\";\n" |
| 1616 | "message Baz {\n" |
| 1617 | " optional int32 a = 2;\n" |
| 1618 | " optional int64 d = 8;\n" |
| 1619 | " extensions 15 to max;\n" // unordered. |
| 1620 | " extensions 13;\n" |
| 1621 | " extensions 10 to 12;\n" |
| 1622 | " extensions 5;\n" |
| 1623 | " extensions 4;\n" |
| 1624 | "}\n"); |
| 1625 | CreateTempFile( |
| 1626 | "quz.proto", |
| 1627 | "syntax = \"proto2\";\n" |
| 1628 | "message Quz {\n" |
| 1629 | " message Foo {}\n" // nested message |
| 1630 | " optional int32 a = 2;\n" |
| 1631 | " optional group C = 4 {\n" |
| 1632 | " optional int32 d = 5;\n" |
| 1633 | " }\n" |
| 1634 | " extensions 8 to 10;\n" |
| 1635 | " optional group E = 11 {\n" |
| 1636 | " optional int32 f = 9;\n" // explicitly reuse extension range 8-10 |
| 1637 | " optional group G = 15 {\n" // nested group |
| 1638 | " message Foo {}\n" // nested message inside nested group |
| 1639 | " }\n" |
| 1640 | " }\n" |
| 1641 | "}\n"); |
| 1642 | |
| 1643 | Run("protocol_compiler --print_free_field_numbers --proto_path=$tmpdir " |
jieluo@google.com | 8d6f04a | 2014-08-06 20:49:30 +0000 | [diff] [blame] | 1644 | "foo.proto bar.proto baz.proto quz.proto"); |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1645 | |
| 1646 | ExpectNoErrors(); |
jieluo@google.com | 8d6f04a | 2014-08-06 20:49:30 +0000 | [diff] [blame] | 1647 | |
| 1648 | // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and |
| 1649 | // stdout at the same time. Need to figure out why and add this test back |
| 1650 | // for Cygwin. |
| 1651 | #if !defined(__CYGWIN__) |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1652 | ExpectCapturedStdout( |
| 1653 | "foo.Foo free: 1 3 6-7 9 11-INF\n" |
| 1654 | "Bar free: 1 3 6-7 9 11-INF\n" |
| 1655 | "Baz free: 1 3 6-7 9 14\n" |
| 1656 | "Quz.Foo free: 1-INF\n" |
| 1657 | "Quz.E.G.Foo free: 1-INF\n" |
| 1658 | "Quz free: 1 3 6-7 12-14 16-INF\n"); |
jieluo@google.com | 8d6f04a | 2014-08-06 20:49:30 +0000 | [diff] [blame] | 1659 | #endif |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1660 | } |
| 1661 | |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1662 | // =================================================================== |
| 1663 | |
| 1664 | // Test for --encode and --decode. Note that it would be easier to do this |
| 1665 | // test as a shell script, but we'd like to be able to run the test on |
| 1666 | // platforms that don't have a Bourne-compatible shell available (especially |
| 1667 | // Windows/MSVC). |
| 1668 | class EncodeDecodeTest : public testing::Test { |
| 1669 | protected: |
| 1670 | virtual void SetUp() { |
| 1671 | duped_stdin_ = dup(STDIN_FILENO); |
| 1672 | } |
| 1673 | |
| 1674 | virtual void TearDown() { |
| 1675 | dup2(duped_stdin_, STDIN_FILENO); |
| 1676 | close(duped_stdin_); |
| 1677 | } |
| 1678 | |
| 1679 | void RedirectStdinFromText(const string& input) { |
| 1680 | string filename = TestTempDir() + "/test_stdin"; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1681 | GOOGLE_CHECK_OK(File::SetContents(filename, input, true)); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1682 | GOOGLE_CHECK(RedirectStdinFromFile(filename)); |
| 1683 | } |
| 1684 | |
| 1685 | bool RedirectStdinFromFile(const string& filename) { |
| 1686 | int fd = open(filename.c_str(), O_RDONLY); |
| 1687 | if (fd < 0) return false; |
| 1688 | dup2(fd, STDIN_FILENO); |
| 1689 | close(fd); |
| 1690 | return true; |
| 1691 | } |
| 1692 | |
| 1693 | // Remove '\r' characters from text. |
| 1694 | string StripCR(const string& text) { |
| 1695 | string result; |
| 1696 | |
| 1697 | for (int i = 0; i < text.size(); i++) { |
| 1698 | if (text[i] != '\r') { |
| 1699 | result.push_back(text[i]); |
| 1700 | } |
| 1701 | } |
| 1702 | |
| 1703 | return result; |
| 1704 | } |
| 1705 | |
| 1706 | enum Type { TEXT, BINARY }; |
| 1707 | enum ReturnCode { SUCCESS, ERROR }; |
| 1708 | |
| 1709 | bool Run(const string& command) { |
| 1710 | vector<string> args; |
| 1711 | args.push_back("protoc"); |
| 1712 | SplitStringUsing(command, " ", &args); |
| 1713 | args.push_back("--proto_path=" + TestSourceDir()); |
| 1714 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1715 | google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1716 | for (int i = 0; i < args.size(); i++) { |
| 1717 | argv[i] = args[i].c_str(); |
| 1718 | } |
| 1719 | |
| 1720 | CommandLineInterface cli; |
| 1721 | cli.SetInputsAreProtoPathRelative(true); |
| 1722 | |
| 1723 | CaptureTestStdout(); |
| 1724 | CaptureTestStderr(); |
| 1725 | |
| 1726 | int result = cli.Run(args.size(), argv.get()); |
| 1727 | |
| 1728 | captured_stdout_ = GetCapturedTestStdout(); |
| 1729 | captured_stderr_ = GetCapturedTestStderr(); |
| 1730 | |
| 1731 | return result == 0; |
| 1732 | } |
| 1733 | |
| 1734 | void ExpectStdoutMatchesBinaryFile(const string& filename) { |
| 1735 | string expected_output; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1736 | GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1737 | |
| 1738 | // Don't use EXPECT_EQ because we don't want to print raw binary data to |
| 1739 | // stdout on failure. |
| 1740 | EXPECT_TRUE(captured_stdout_ == expected_output); |
| 1741 | } |
| 1742 | |
| 1743 | void ExpectStdoutMatchesTextFile(const string& filename) { |
| 1744 | string expected_output; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1745 | GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1746 | |
| 1747 | ExpectStdoutMatchesText(expected_output); |
| 1748 | } |
| 1749 | |
| 1750 | void ExpectStdoutMatchesText(const string& expected_text) { |
| 1751 | EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_)); |
| 1752 | } |
| 1753 | |
| 1754 | void ExpectStderrMatchesText(const string& expected_text) { |
| 1755 | EXPECT_EQ(StripCR(expected_text), StripCR(captured_stderr_)); |
| 1756 | } |
| 1757 | |
| 1758 | private: |
| 1759 | int duped_stdin_; |
| 1760 | string captured_stdout_; |
| 1761 | string captured_stderr_; |
| 1762 | }; |
| 1763 | |
| 1764 | TEST_F(EncodeDecodeTest, Encode) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1765 | RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/" |
| 1766 | "testdata/text_format_unittest_data_oneof_implemented.txt"); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1767 | EXPECT_TRUE(Run("google/protobuf/unittest.proto " |
| 1768 | "--encode=protobuf_unittest.TestAllTypes")); |
| 1769 | ExpectStdoutMatchesBinaryFile(TestSourceDir() + |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1770 | "/google/protobuf/testdata/golden_message_oneof_implemented"); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1771 | ExpectStderrMatchesText(""); |
| 1772 | } |
| 1773 | |
| 1774 | TEST_F(EncodeDecodeTest, Decode) { |
| 1775 | RedirectStdinFromFile(TestSourceDir() + |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1776 | "/google/protobuf/testdata/golden_message_oneof_implemented"); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1777 | EXPECT_TRUE(Run("google/protobuf/unittest.proto " |
| 1778 | "--decode=protobuf_unittest.TestAllTypes")); |
| 1779 | ExpectStdoutMatchesTextFile(TestSourceDir() + |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1780 | "/google/protobuf/" |
| 1781 | "testdata/text_format_unittest_data_oneof_implemented.txt"); |
temporal | 779f61c | 2008-08-13 03:15:00 +0000 | [diff] [blame] | 1782 | ExpectStderrMatchesText(""); |
| 1783 | } |
| 1784 | |
| 1785 | TEST_F(EncodeDecodeTest, Partial) { |
| 1786 | RedirectStdinFromText(""); |
| 1787 | EXPECT_TRUE(Run("google/protobuf/unittest.proto " |
| 1788 | "--encode=protobuf_unittest.TestRequired")); |
| 1789 | ExpectStdoutMatchesText(""); |
| 1790 | ExpectStderrMatchesText( |
| 1791 | "warning: Input message is missing required fields: a, b, c\n"); |
| 1792 | } |
| 1793 | |
| 1794 | TEST_F(EncodeDecodeTest, DecodeRaw) { |
| 1795 | protobuf_unittest::TestAllTypes message; |
| 1796 | message.set_optional_int32(123); |
| 1797 | message.set_optional_string("foo"); |
| 1798 | string data; |
| 1799 | message.SerializeToString(&data); |
| 1800 | |
| 1801 | RedirectStdinFromText(data); |
| 1802 | EXPECT_TRUE(Run("--decode_raw")); |
| 1803 | ExpectStdoutMatchesText("1: 123\n" |
| 1804 | "14: \"foo\"\n"); |
| 1805 | ExpectStderrMatchesText(""); |
| 1806 | } |
| 1807 | |
| 1808 | TEST_F(EncodeDecodeTest, UnknownType) { |
| 1809 | EXPECT_FALSE(Run("google/protobuf/unittest.proto " |
| 1810 | "--encode=NoSuchType")); |
| 1811 | ExpectStdoutMatchesText(""); |
| 1812 | ExpectStderrMatchesText("Type not defined: NoSuchType\n"); |
| 1813 | } |
| 1814 | |
| 1815 | TEST_F(EncodeDecodeTest, ProtoParseError) { |
| 1816 | EXPECT_FALSE(Run("google/protobuf/no_such_file.proto " |
| 1817 | "--encode=NoSuchType")); |
| 1818 | ExpectStdoutMatchesText(""); |
| 1819 | ExpectStderrMatchesText( |
| 1820 | "google/protobuf/no_such_file.proto: File not found.\n"); |
| 1821 | } |
| 1822 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1823 | } // anonymous namespace |
| 1824 | |
Feng Xiao | c5147e3 | 2015-12-28 16:40:39 -0800 | [diff] [blame] | 1825 | #endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN |
| 1826 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1827 | } // namespace compiler |
| 1828 | } // namespace protobuf |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame] | 1829 | } // namespace google |