1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda)
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Based on original Protocol Buffers design by
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Sanjay Ghemawat, Jeff Dean, and others.
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/types.h>
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/stat.h>
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <fcntl.h>
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _MSC_VER
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <io.h>
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <unistd.h>
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <vector>
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/descriptor.pb.h>
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/descriptor.h>
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/zero_copy_stream.h>
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/command_line_interface.h>
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/code_generator.h>
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/mock_code_generator.h>
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/printer.h>
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/unittest.pb.h>
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/file.h>
54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/strutil.h>
55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/substitute.h>
56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/googletest.h>
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <gtest/gtest.h>
59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google {
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf {
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace compiler {
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32)
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef STDIN_FILENO
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define STDIN_FILENO 0
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef STDOUT_FILENO
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define STDOUT_FILENO 1
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
71d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifndef F_OK
72d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#define F_OK 00  // not defined by MSVC for whatever reason
73d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace {
77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass CommandLineInterfaceTest : public testing::Test {
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville protected:
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  virtual void SetUp();
81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  virtual void TearDown();
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Runs the CommandLineInterface with the given command line.  The
84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // command is automatically split on spaces, and the string "$tmpdir"
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // is replaced with TestTempDir().
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void Run(const string& command);
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // -----------------------------------------------------------------
89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Methods to set up the test (called before Run()).
90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  class NullCodeGenerator;
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Normally plugins are allowed for all tests.  Call this to explicitly
94d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // disable them.
95d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void DisallowPlugins() { disallow_plugins_ = true; }
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create a temp file within temp_directory_ with the given name.
98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // The containing directory is also created if necessary.
99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void CreateTempFile(const string& name, const string& contents);
100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Create a subdirectory within temp_directory_.
102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void CreateTempDir(const string& name);
103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void SetInputsAreProtoPathRelative(bool enable) {
105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cli_.SetInputsAreProtoPathRelative(enable);
106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // -----------------------------------------------------------------
109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Methods to check the test results (called after Run()).
110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Checks that no text was written to stderr during Run(), and Run()
112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // returned 0.
113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectNoErrors();
114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Checks that Run() returned non-zero and the stderr output is exactly
116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // the text given.  expected_test may contain references to "$tmpdir",
117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // which will be replaced by the temporary directory path.
118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectErrorText(const string& expected_text);
119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Checks that Run() returned non-zero and the stderr contains the given
121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // substring.
122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectErrorSubstring(const string& expected_substring);
123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // does not fail otherwise.
126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool HasAlternateErrorSubstring(const string& expected_substring);
127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Checks that MockCodeGenerator::Generate() was called in the given
129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // context (or the generator in test_plugin.cc, which produces the same
130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // output).  That is, this tests if the generator with the given name
131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // was called with the given parameter and proto file and produced the
132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // given output file.  This is checked by reading the output file and
133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // checking that it contains the content that MockCodeGenerator would
134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // generate given these inputs.  message_name is the name of the first
135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // message that appeared in the proto file; this is just to make extra
136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // sure that the correct file was parsed.
137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectGenerated(const string& generator_name,
138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                       const string& parameter,
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                       const string& proto_name,
140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                       const string& message_name);
141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void ExpectGenerated(const string& generator_name,
142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                       const string& parameter,
143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                       const string& proto_name,
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                       const string& message_name,
145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                       const string& output_directory);
146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void ExpectGeneratedWithInsertions(const string& generator_name,
147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                     const string& parameter,
148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                     const string& insertions,
149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                     const string& proto_name,
150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                     const string& message_name);
151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void ExpectNullCodeGeneratorCalled(const string& parameter);
153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ReadDescriptorSet(const string& filename,
155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                         FileDescriptorSet* descriptor_set);
156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private:
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // The object we are testing.
159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CommandLineInterface cli_;
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Was DisallowPlugins() called?
162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  bool disallow_plugins_;
163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // We create a directory within TestTempDir() in order to add extra
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // protection against accidentally deleting user files (since we recursively
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // delete this directory during the test).  This is the full path of that
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // directory.
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string temp_directory_;
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // The result of Run().
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int return_code_;
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // The captured stderr output.
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string error_text_;
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Pointers which need to be deleted later.
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vector<CodeGenerator*> mock_generators_to_delete_;
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
179d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  NullCodeGenerator* null_generator_;
180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville};
181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator {
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public:
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  NullCodeGenerator() : called_(false) {}
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ~NullCodeGenerator() {}
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  mutable bool called_;
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  mutable string parameter_;
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // implements CodeGenerator ----------------------------------------
191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool Generate(const FileDescriptor* file,
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                const string& parameter,
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                OutputDirectory* output_directory,
194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                string* error) const {
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    called_ = true;
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    parameter_ = parameter;
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return true;
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville};
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::SetUp() {
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Most of these tests were written before this option was added, so we
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // run with the option on (which used to be the only way) except in certain
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // tests where we turn it off.
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cli_.SetInputsAreProtoPathRelative(true);
208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  temp_directory_ = TestTempDir() + "/proto2_cli_test_temp";
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // If the temp directory already exists, it must be left over from a
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // previous run.  Delete it.
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (File::Exists(temp_directory_)) {
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    File::DeleteRecursively(temp_directory_, NULL, NULL);
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create the temp directory.
218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE));
219d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
220d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Register generators.
221d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CodeGenerator* generator = new MockCodeGenerator("test_generator");
222d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  mock_generators_to_delete_.push_back(generator);
223d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cli_.RegisterGenerator("--test_out", generator, "Test output.");
224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cli_.RegisterGenerator("-t", generator, "Test output.");
225d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
226d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  generator = new MockCodeGenerator("alt_generator");
227d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  mock_generators_to_delete_.push_back(generator);
228d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cli_.RegisterGenerator("--alt_out", generator, "Alt output.");
229d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
230d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  generator = null_generator_ = new NullCodeGenerator();
231d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  mock_generators_to_delete_.push_back(generator);
232d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cli_.RegisterGenerator("--null_out", generator, "Null output.");
233d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
234d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  disallow_plugins_ = false;
235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::TearDown() {
238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Delete the temp directory.
239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  File::DeleteRecursively(temp_directory_, NULL, NULL);
240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Delete all the MockCodeGenerators.
242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < mock_generators_to_delete_.size(); i++) {
243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    delete mock_generators_to_delete_[i];
244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  mock_generators_to_delete_.clear();
246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::Run(const string& command) {
249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vector<string> args;
250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  SplitStringUsing(command, " ", &args);
251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
252d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!disallow_plugins_) {
253d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cli_.AllowPlugins("prefix-");
254d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
255d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const char* possible_paths[] = {
256d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // When building with shared libraries, libtool hides the real executable
257d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // in .libs and puts a fake wrapper in the current directory.
258d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program
259d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // wrapped in this way (e.g. protobuf-tests.exe) tries to execute another
260d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // program wrapped in this way (e.g. test_plugin.exe), the latter fails
261d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // with error code 127 and no explanation message.  Presumably the problem
262d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // is that the wrapper for protobuf-tests.exe set some environment
263d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // variables that confuse the wrapper for test_plugin.exe.  Luckily, it
264d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // turns out that if we simply invoke the wrapped test_plugin.exe
265d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // directly, it works -- I guess the environment variables set by the
266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // protobuf-tests.exe wrapper happen to be correct for it too.  So we do
267d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // that.
268d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      ".libs/test_plugin.exe",  // Win32 w/autotool (Cygwin / MinGW)
269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "test_plugin.exe",        // Other Win32 (MSVC)
270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "test_plugin",            // Unix
271d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    };
272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    string plugin_path;
274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) {
276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (access(possible_paths[i], F_OK) == 0) {
277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        plugin_path = possible_paths[i];
278d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        break;
279d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
280d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
281d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
282d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (plugin_path.empty()) {
283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      GOOGLE_LOG(ERROR)
284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          << "Plugin executable not found.  Plugin tests are likely to fail.";
285d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    } else {
286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      args.push_back("--plugin=prefix-gen-plug=" + plugin_path);
287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
288d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
289d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  scoped_array<const char*> argv(new const char*[args.size()]);
291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < args.size(); i++) {
293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    argv[i] = args[i].c_str();
295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CaptureTestStderr();
298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return_code_ = cli_.Run(args.size(), argv.get());
300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  error_text_ = GetCapturedTestStderr();
302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// -------------------------------------------------------------------
305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::CreateTempFile(
307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& name,
308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& contents) {
309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create parent directory, if necessary.
310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string::size_type slash_pos = name.find_last_of('/');
311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (slash_pos != string::npos) {
312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    string dir = name.substr(0, slash_pos);
313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    File::RecursivelyCreateDir(temp_directory_ + "/" + dir, 0777);
314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Write file.
317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string full_name = temp_directory_ + "/" + name;
318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  File::WriteStringToFileOrDie(contents, full_name);
319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
321d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid CommandLineInterfaceTest::CreateTempDir(const string& name) {
322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777);
323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// -------------------------------------------------------------------
326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::ExpectNoErrors() {
328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(0, return_code_);
329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ("", error_text_);
330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::ExpectErrorText(const string& expected_text) {
333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_NE(0, return_code_);
334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(StringReplace(expected_text, "$tmpdir", temp_directory_, true),
335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville            error_text_);
336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::ExpectErrorSubstring(
339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& expected_substring) {
340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_NE(0, return_code_);
341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterfaceTest::HasAlternateErrorSubstring(
345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& expected_substring) {
346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_NE(0, return_code_);
347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return error_text_.find(expected_substring) != string::npos;
348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::ExpectGenerated(
351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& generator_name,
352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& parameter,
353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& proto_name,
354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& message_name) {
355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  MockCodeGenerator::ExpectGenerated(
356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      generator_name, parameter, "", proto_name, message_name, temp_directory_);
357d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
358d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
359d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid CommandLineInterfaceTest::ExpectGenerated(
360d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& generator_name,
361d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& parameter,
362d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& proto_name,
363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& message_name,
364d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& output_directory) {
365d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  MockCodeGenerator::ExpectGenerated(
366d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      generator_name, parameter, "", proto_name, message_name,
367d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      temp_directory_ + "/" + output_directory);
368d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
370d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
371d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& generator_name,
372d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& parameter,
373d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& insertions,
374d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& proto_name,
375d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& message_name) {
376d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  MockCodeGenerator::ExpectGenerated(
377d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      generator_name, parameter, insertions, proto_name, message_name,
378d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      temp_directory_);
379d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
380d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
381d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
382d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string& parameter) {
383d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  EXPECT_TRUE(null_generator_->called_);
384d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  EXPECT_EQ(parameter, null_generator_->parameter_);
385fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
386fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
387fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterfaceTest::ReadDescriptorSet(
388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const string& filename, FileDescriptorSet* descriptor_set) {
389fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string path = temp_directory_ + "/" + filename;
390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string file_contents;
391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (!File::ReadFileToString(path, &file_contents)) {
392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    FAIL() << "File not found: " << path;
393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (!descriptor_set->ParseFromString(file_contents)) {
395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    FAIL() << "Could not parse file contents: " << path;
396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
399fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
400fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
401d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, BasicOutput) {
402d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test that the common case works.
403fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
404d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("foo.proto",
405d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
406d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message Foo {}\n");
407fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
408d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --test_out=$tmpdir "
409d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
410fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
411d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectNoErrors();
412d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
414fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
415d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, BasicPlugin) {
416d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test that basic plugins work.
417fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
418d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("foo.proto",
419d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
420d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message Foo {}\n");
421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
422d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --plug_out=$tmpdir "
423d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
424d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
425d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectNoErrors();
426d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
427d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
428d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
429d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
430d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Invoke a generator and a plugin at the same time.
431fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
432fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
433fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
434fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
435fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
436d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
437fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
438fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
439fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
440d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
441d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
442fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
443fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
444fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, MultipleInputs) {
445fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test parsing multiple input files.
446fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
447fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
449fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
450fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("bar.proto",
451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
452fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Bar {}\n");
453fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
454d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
455fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto bar.proto");
456fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
457fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
458d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
459d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "bar.proto", "Bar");
460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, CreateDirectory) {
463fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that when we output to a sub-directory, it is created.
464fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
465d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("bar/baz/foo.proto",
466fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
467fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
468d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempDir("out");
469d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempDir("plugout");
470fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
471d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout "
472d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir bar/baz/foo.proto");
473fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
474fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
475d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "bar/baz/foo.proto", "Foo", "out");
476d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_plugin", "", "bar/baz/foo.proto", "Foo", "plugout");
477fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
478fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
479fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, GeneratorParameters) {
480fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that generator parameters are correctly parsed from the command line.
481fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
482fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
483fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
484fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
485fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
486fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=TestParameter:$tmpdir "
487d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plug_out=TestPluginParameter:$tmpdir "
488fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
489fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
490fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
491d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "TestParameter", "foo.proto", "Foo");
492d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
493d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
494d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
495d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, Insert) {
496d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test running a generator that inserts code into another's output.
497d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
498d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("foo.proto",
499d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
500d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message Foo {}\n");
501d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
502d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler "
503d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--test_out=TestParameter:$tmpdir "
504d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plug_out=TestPluginParameter:$tmpdir "
505d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--test_out=insert=test_generator,test_plugin:$tmpdir "
506d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plug_out=insert=test_generator,test_plugin:$tmpdir "
507d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
508d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
509d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectNoErrors();
510d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGeneratedWithInsertions(
511d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "test_generator", "TestParameter", "test_generator,test_plugin",
512d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "foo.proto", "Foo");
513d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGeneratedWithInsertions(
514d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "test_plugin", "TestPluginParameter", "test_generator,test_plugin",
515d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "foo.proto", "Foo");
516fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
517fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
518fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32) || defined(__CYGWIN__)
519fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
520fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
521fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that the output path can be a Windows-style path.
522fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
523fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
524fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n");
525fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
526d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --null_out=C:\\ "
527fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
528fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
529fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
530d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectNullCodeGeneratorCalled("");
531fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
532fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
533fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) {
534fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that we can have a windows-style output path and a parameter.
535fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
536fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
537fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n");
538fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
539d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --null_out=bar:C:\\ "
540fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
541fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
542fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
543d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectNullCodeGeneratorCalled("bar");
544fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
545fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
546fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, TrailingBackslash) {
547fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that the directories can end in backslashes.  Some users claim this
548fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // doesn't work on their system.
549fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
550fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
551fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
552fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
553fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
554fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir\\ "
555fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir\\ foo.proto");
556fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
557fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
558d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
559fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
560fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
561fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif  // defined(_WIN32) || defined(__CYGWIN__)
562fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
563fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, PathLookup) {
564fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that specifying multiple directories in the proto search path works.
565fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
566fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("b/bar.proto",
567fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Bar {}\n");
569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("a/foo.proto",
570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "import \"bar.proto\";\n"
572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {\n"
573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  optional Bar a = 1;\n"
574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "}\n");
575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("b/foo.proto", "this should not be parsed\n");
576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto");
579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
581d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Same as PathLookup, but we provide the proto_path in a single flag.
586fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
587fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("b/bar.proto",
588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
589fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Bar {}\n");
590fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("a/foo.proto",
591fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "import \"bar.proto\";\n"
593fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {\n"
594fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  optional Bar a = 1;\n"
595fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "}\n");
596fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("b/foo.proto", "this should not be parsed\n");
597fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
598fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#undef PATH_SEPARATOR
599fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32)
600fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define PATH_SEPARATOR ";"
601fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
602fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define PATH_SEPARATOR ":"
603fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
604fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
605fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
606fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir/a"PATH_SEPARATOR"$tmpdir/b foo.proto");
607fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
608fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#undef PATH_SEPARATOR
609fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
610fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
611d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
612fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
613fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
614fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, NonRootMapping) {
615fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test setting up a search path mapping a directory to a non-root location.
616fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
617fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
618fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
619fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
620fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
621fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
622fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=bar=$tmpdir bar/foo.proto");
623fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
624fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
625d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo");
626fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
627fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
628fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, MultipleGenerators) {
629fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that we can have multiple generators and use both in one invocation,
630fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // each with a different output directory.
631fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
632fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
634fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
635fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create the "a" and "b" sub-directories.
636d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempDir("a");
637d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempDir("b");
638fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
639fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler "
640d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--test_out=$tmpdir/a "
641d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--alt_out=$tmpdir/b "
642fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
643fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
644fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
645d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo", "a");
646d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("alt_generator", "", "foo.proto", "Foo", "b");
647fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
648fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
649fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
650fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that --disallow_services doesn't cause a problem when there are no
651fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // services.
652fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
653fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
654fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
655fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
656fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
657fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --disallow_services --test_out=$tmpdir "
658fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
661d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
662fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
663fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
664fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
665fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that --disallow_services produces an error when there are services.
666fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
667fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
668fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
669fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n"
670fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "service Bar {}\n");
671fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
672fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --disallow_services --test_out=$tmpdir "
673fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
674fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
675fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorSubstring("foo.proto: This file contains services");
676fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
677fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
678fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
679fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that services work fine as long as --disallow_services is not used.
680fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
681fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
682fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
683fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n"
684fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "service Bar {}\n");
685fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
686fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
687fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
688fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
689fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
690d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
691fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
692fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
693fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that we can accept working-directory-relative input files.
695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
696fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  SetInputsAreProtoPathRelative(false);
697fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
702fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
703fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir $tmpdir/foo.proto");
704fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
705fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
706d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
707fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
708fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
709fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
710fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
711fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
712fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
713fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("bar.proto",
714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "import \"foo.proto\";\n"
716fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Bar {\n"
717fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  optional Foo foo = 1;\n"
718fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "}\n");
719fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
720fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
721fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir bar.proto");
722fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
723fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
724fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
725fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  FileDescriptorSet descriptor_set;
726fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadDescriptorSet("descriptor_set", &descriptor_set);
727fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasFatalFailure()) return;
728fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ASSERT_EQ(1, descriptor_set.file_size());
729fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
730fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
731fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
732fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
733fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
734fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
735fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
736fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("bar.proto",
737fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
738fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "import \"foo.proto\";\n"
739fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Bar {\n"
740fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  optional Foo foo = 1;\n"
741fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "}\n");
742fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
743fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
744fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--include_imports --proto_path=$tmpdir bar.proto");
745fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
746fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
747fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
748fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  FileDescriptorSet descriptor_set;
749fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadDescriptorSet("descriptor_set", &descriptor_set);
750fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasFatalFailure()) return;
751fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ASSERT_EQ(2, descriptor_set.file_size());
752fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (descriptor_set.file(0).name() == "bar.proto") {
753d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    std::swap(descriptor_set.mutable_file()->mutable_data()[0],
754d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville              descriptor_set.mutable_file()->mutable_data()[1]);
755fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
756fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
757fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
758fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
759fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
760fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// -------------------------------------------------------------------
761fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
762fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, ParseErrors) {
763fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that parse errors are reported.
764fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
765fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
766fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
767fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "badsyntax\n");
768fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
769fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
770fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
771fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
772fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
773fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
774fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
775fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
776fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
777fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that parse errors are reported from multiple files.
778fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
779fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // We set up files such that foo.proto actually depends on bar.proto in
780fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // two ways:  Directly and through baz.proto.  bar.proto's errors should
781fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // only be reported once.
782fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("bar.proto",
783fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
784fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "badsyntax\n");
785fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("baz.proto",
786fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
787fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "import \"bar.proto\";\n");
788fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
789fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
790fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "import \"bar.proto\";\n"
791fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "import \"baz.proto\";\n");
792fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
793fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
794fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
795fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
796fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
797fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n"
798fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "baz.proto: Import \"bar.proto\" was not found or had errors.\n"
799fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "foo.proto: Import \"bar.proto\" was not found or had errors.\n"
800fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "foo.proto: Import \"baz.proto\" was not found or had errors.\n");
801fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
802fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
803fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, InputNotFoundError) {
804fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test what happens if the input file is not found.
805fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
806fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
807fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
808fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
809fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
810fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "foo.proto: File not found.\n");
811fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
812fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
813fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
814fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test what happens when a working-directory-relative input file is not
815fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // found.
816fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
817fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  SetInputsAreProtoPathRelative(false);
818fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
819fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
820fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir $tmpdir/foo.proto");
821fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
822fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
823fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "$tmpdir/foo.proto: No such file or directory\n");
824fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
825fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
826fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) {
827fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test what happens when a working-directory-relative input file is not
828fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // mapped to a virtual path.
829fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
830fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  SetInputsAreProtoPathRelative(false);
831fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
832fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
833fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
834fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
835fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
836fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create a directory called "bar" so that we can point --proto_path at it.
837fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("bar/dummy", "");
838fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
839fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
840fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
841fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
842fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
843fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "$tmpdir/foo.proto: File does not reside within any path "
844fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "specified using --proto_path (or -I).  You must specify a "
845d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path which encompasses this file.  Note that the "
846d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "proto_path must be an exact prefix of the .proto file "
847d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "names -- protoc is too dumb to figure out when two paths "
848d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "(e.g. absolute and relative) are equivalent (it's harder "
849d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "than you think).\n");
850fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
851fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
852fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) {
853fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Check what happens if the input file is not found *and* is not mapped
854fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // in the proto_path.
855fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
856fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  SetInputsAreProtoPathRelative(false);
857fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
858fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create a directory called "bar" so that we can point --proto_path at it.
859fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("bar/dummy", "");
860fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
861fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
862fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
863fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
864fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
865fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "$tmpdir/foo.proto: No such file or directory\n");
866fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
867fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
868fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
869fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test what happens when a working-directory-relative input file is shadowed
870fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // by another file in the virtual path.
871fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
872fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  SetInputsAreProtoPathRelative(false);
873fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
874fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo/foo.proto",
875fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
876fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
877fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("bar/foo.proto",
878fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
879fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Bar {}\n");
880fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
881fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
882fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir/foo --proto_path=$tmpdir/bar "
883fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "$tmpdir/bar/foo.proto");
884fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
885fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
886fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path "
887fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "by \"$tmpdir/foo/foo.proto\".  Either use the latter "
888fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "file as your input or reorder the --proto_path so that the "
889fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "former file's location comes first.\n");
890fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
891fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
892fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
893fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test what happens if the input file is not found.
894fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
895fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
896fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir/foo foo.proto");
897fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
898fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
899fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "$tmpdir/foo: warning: directory does not exist.\n"
900fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "foo.proto: File not found.\n");
901fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
902fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
903fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, MissingInputError) {
904fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that we get an error if no inputs are given.
905fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
906fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
907fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir");
908fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
909fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText("Missing input file.\n");
910fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
911fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
912fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, MissingOutputError) {
913fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
914fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
915fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
916fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
917fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --proto_path=$tmpdir foo.proto");
918fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
919fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText("Missing output directives.\n");
920fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
921fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
922fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, OutputWriteError) {
923fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
924fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
925fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
926fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
927d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string output_file =
928d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto");
929d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
930fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create a directory blocking our output location.
931d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempDir(output_file);
932fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
933fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
934fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
935fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
936d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // MockCodeGenerator no longer detects an error because we actually write to
937d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // an in-memory location first, then dump to disk at the end.  This is no
938d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // big deal.
939d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  //   ExpectErrorSubstring("MockCodeGenerator detected write error.");
940d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
941fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32) && !defined(__CYGWIN__)
942fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
943d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
944fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return;
945fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
946fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
947fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
948d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(output_file + ": Is a directory");
949fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
950fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
951d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, PluginOutputWriteError) {
952d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("foo.proto",
953d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
954d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message Foo {}\n");
955d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
956d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string output_file =
957d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto");
958d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
959d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Create a directory blocking our output location.
960d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempDir(output_file);
961d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
962d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --plug_out=$tmpdir "
963d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
964d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
965d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#if defined(_WIN32) && !defined(__CYGWIN__)
966d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
967d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
968d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return;
969d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
970d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
971fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
972d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(output_file + ": Is a directory");
973d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
974d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
975d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
976fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
977fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
978fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
979fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
980fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir/nosuchdir "
981fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
982fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
983d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring("nosuchdir/: No such file or directory");
984fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
985fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
986d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) {
987d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("foo.proto",
988d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
989d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message Foo {}\n");
990d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
991d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --plug_out=$tmpdir/nosuchdir "
992d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
993fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
994d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring("nosuchdir/: No such file or directory");
995d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
996d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
997d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
998fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
999fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1000fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
1001fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1002fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir/foo.proto "
1003fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
1004fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1005fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32) && !defined(__CYGWIN__)
1006fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Windows with MSVCRT.dll produces EINVAL instead of ENOTDIR.
1007fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasAlternateErrorSubstring("foo.proto/: Invalid argument")) {
1008fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return;
1009fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1010fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
1011fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1012fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorSubstring("foo.proto/: Not a directory");
1013fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1014fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1015fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, GeneratorError) {
1016d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("foo.proto",
1017d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
1018d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message MockCodeGenerator_Error {}\n");
1019d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1020d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --test_out=$tmpdir "
1021d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
1022d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1023d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1024d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--test_out: foo.proto: Saw message type MockCodeGenerator_Error.");
1025d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
1026d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1027d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, GeneratorPluginError) {
1028d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test a generator plugin that returns an error.
1029fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1030fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1031fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1032d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message MockCodeGenerator_Error {}\n");
1033fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1034d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
1035fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
1036fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1037d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1038d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error.");
1039fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1040fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1041d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, GeneratorPluginFail) {
1042d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test a generator plugin that exits with an error code.
1043fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1044fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1045fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1046d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message MockCodeGenerator_Exit {}\n");
1047d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1048d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
1049d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
1050d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1051d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring("Saw message type MockCodeGenerator_Exit.");
1052d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1053d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plug_out: prefix-gen-plug: Plugin failed with status code 123.");
1054d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
1055d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1056d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) {
1057d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test a generator plugin that crashes.
1058d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1059d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("foo.proto",
1060d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
1061d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message MockCodeGenerator_Abort {}\n");
1062d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1063d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
1064d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir foo.proto");
1065d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1066d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring("Saw message type MockCodeGenerator_Abort.");
1067d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1068d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifdef _WIN32
1069d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Windows doesn't have signals.  It looks like abort()ing causes the process
1070d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // to exit with status code 3, but let's not depend on the exact number here.
1071d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1072d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plug_out: prefix-gen-plug: Plugin failed with status code");
1073d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#else
1074d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Don't depend on the exact signal number.
1075d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1076d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plug_out: prefix-gen-plug: Plugin killed by signal");
1077d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
1078d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
1079d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1080d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
1081d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test what happens if the plugin isn't found.
1082d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1083d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("error.proto",
1084d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
1085d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "message Foo {}\n");
1086d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1087d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --badplug_out=TestParameter:$tmpdir "
1088d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--plugin=prefix-gen-badplug=no_such_file "
1089d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir error.proto");
1090d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1091d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifdef _WIN32
1092d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1093d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--badplug_out: prefix-gen-badplug: The system cannot find the file "
1094d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        "specified.");
1095d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#else
1096d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Error written to stdout by child process after exec() fails.
1097d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1098d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "no_such_file: program not found or is not executable");
1099d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Error written by parent process when child fails.
1101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring(
1102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1.");
1103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
1104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
1105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
1107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Test what happens if plugins aren't allowed.
1108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CreateTempFile("error.proto",
1110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "syntax = \"proto2\";\n"
1111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
1112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  DisallowPlugins();
1114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
1115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "--proto_path=$tmpdir error.proto");
1116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring("Unknown flag: --plug_out");
1118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
1119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleTEST_F(CommandLineInterfaceTest, HelpText) {
1121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("test_exec_name --help");
1122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorSubstring("Usage: test_exec_name ");
1124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorSubstring("--test_out=OUT_DIR");
1125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorSubstring("Test output.");
1126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring("--alt_out=OUT_DIR");
1127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectErrorSubstring("Alt output.");
1128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, GccFormatErrors) {
1131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test --error_format=gcc (which is the default, but we want to verify
1132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // that it can be set explicitly).
1133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "badsyntax\n");
1137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
1139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir --error_format=gcc foo.proto");
1140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
1142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
1143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
1146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test --error_format=msvs
1147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "badsyntax\n");
1151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
1153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir --error_format=msvs foo.proto");
1154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
1156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "foo.proto(2) : error in column=1: Expected top-level statement "
1157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "(e.g. \"message\").\n");
1158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
1161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test --error_format=msvs
1162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "badsyntax\n");
1166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out=$tmpdir "
1168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir --error_format=invalid foo.proto");
1169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText(
1171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "Unknown error format: invalid\n");
1172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// -------------------------------------------------------------------
1175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Flag parsing tests
1176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
1178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that a single-character flag works.
1179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
1183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler -t$tmpdir "
1185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
1186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
1188d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
1189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
1192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that separating the flag value with a space works.
1193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
1197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out $tmpdir "
1199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
1200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
1202d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
1203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
1206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that separating the flag value with a space works for
1207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // single-character flags.
1208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  CreateTempFile("foo.proto",
1210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "syntax = \"proto2\";\n"
1211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "message Foo {}\n");
1212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler -t $tmpdir "
1214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "--proto_path=$tmpdir foo.proto");
1215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectNoErrors();
1217d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
1218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, MissingValueError) {
1221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that we get an error if a flag is missing its value.
1222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out --proto_path=$tmpdir foo.proto");
1224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText("Missing value for flag: --test_out\n");
1226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
1229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test that we get an error if the last argument is a flag requiring a
1230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // value.
1231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Run("protocol_compiler --test_out");
1233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectErrorText("Missing value for flag: --test_out\n");
1235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
1238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Test for --encode and --decode.  Note that it would be easier to do this
1240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// test as a shell script, but we'd like to be able to run the test on
1241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// platforms that don't have a Bourne-compatible shell available (especially
1242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Windows/MSVC).
1243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass EncodeDecodeTest : public testing::Test {
1244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville protected:
1245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  virtual void SetUp() {
1246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    duped_stdin_ = dup(STDIN_FILENO);
1247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  virtual void TearDown() {
1250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    dup2(duped_stdin_, STDIN_FILENO);
1251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    close(duped_stdin_);
1252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void RedirectStdinFromText(const string& input) {
1255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    string filename = TestTempDir() + "/test_stdin";
1256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    File::WriteStringToFileOrDie(input, filename);
1257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GOOGLE_CHECK(RedirectStdinFromFile(filename));
1258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool RedirectStdinFromFile(const string& filename) {
1261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int fd = open(filename.c_str(), O_RDONLY);
1262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (fd < 0) return false;
1263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    dup2(fd, STDIN_FILENO);
1264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    close(fd);
1265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return true;
1266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Remove '\r' characters from text.
1269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string StripCR(const string& text) {
1270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    string result;
1271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int i = 0; i < text.size(); i++) {
1273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if (text[i] != '\r') {
1274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        result.push_back(text[i]);
1275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
1276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return result;
1279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  enum Type { TEXT, BINARY };
1282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  enum ReturnCode { SUCCESS, ERROR };
1283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool Run(const string& command) {
1285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vector<string> args;
1286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    args.push_back("protoc");
1287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    SplitStringUsing(command, " ", &args);
1288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    args.push_back("--proto_path=" + TestSourceDir());
1289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    scoped_array<const char*> argv(new const char*[args.size()]);
1291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int i = 0; i < args.size(); i++) {
1292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      argv[i] = args[i].c_str();
1293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    CommandLineInterface cli;
1296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cli.SetInputsAreProtoPathRelative(true);
1297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    CaptureTestStdout();
1299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    CaptureTestStderr();
1300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int result = cli.Run(args.size(), argv.get());
1302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    captured_stdout_ = GetCapturedTestStdout();
1304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    captured_stderr_ = GetCapturedTestStderr();
1305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return result == 0;
1307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectStdoutMatchesBinaryFile(const string& filename) {
1310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    string expected_output;
1311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ASSERT_TRUE(File::ReadFileToString(filename, &expected_output));
1312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Don't use EXPECT_EQ because we don't want to print raw binary data to
1314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // stdout on failure.
1315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    EXPECT_TRUE(captured_stdout_ == expected_output);
1316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectStdoutMatchesTextFile(const string& filename) {
1319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    string expected_output;
1320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ASSERT_TRUE(File::ReadFileToString(filename, &expected_output));
1321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1322fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ExpectStdoutMatchesText(expected_output);
1323fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectStdoutMatchesText(const string& expected_text) {
1326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_));
1327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ExpectStderrMatchesText(const string& expected_text) {
1330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    EXPECT_EQ(StripCR(expected_text), StripCR(captured_stderr_));
1331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private:
1334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int duped_stdin_;
1335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string captured_stdout_;
1336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string captured_stderr_;
1337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville};
1338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(EncodeDecodeTest, Encode) {
1340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  RedirectStdinFromFile(TestSourceDir() +
1341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "/google/protobuf/testdata/text_format_unittest_data.txt");
1342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(Run("google/protobuf/unittest.proto "
1343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                  "--encode=protobuf_unittest.TestAllTypes"));
1344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStdoutMatchesBinaryFile(TestSourceDir() +
1345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "/google/protobuf/testdata/golden_message");
1346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStderrMatchesText("");
1347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(EncodeDecodeTest, Decode) {
1350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  RedirectStdinFromFile(TestSourceDir() +
1351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "/google/protobuf/testdata/golden_message");
1352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(Run("google/protobuf/unittest.proto "
1353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                  "--decode=protobuf_unittest.TestAllTypes"));
1354fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStdoutMatchesTextFile(TestSourceDir() +
1355fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "/google/protobuf/testdata/text_format_unittest_data.txt");
1356fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStderrMatchesText("");
1357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(EncodeDecodeTest, Partial) {
1360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  RedirectStdinFromText("");
1361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(Run("google/protobuf/unittest.proto "
1362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                  "--encode=protobuf_unittest.TestRequired"));
1363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStdoutMatchesText("");
1364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStderrMatchesText(
1365fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "warning:  Input message is missing required fields:  a, b, c\n");
1366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1367fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1368fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(EncodeDecodeTest, DecodeRaw) {
1369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  protobuf_unittest::TestAllTypes message;
1370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  message.set_optional_int32(123);
1371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  message.set_optional_string("foo");
1372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string data;
1373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  message.SerializeToString(&data);
1374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1375fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  RedirectStdinFromText(data);
1376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(Run("--decode_raw"));
1377fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStdoutMatchesText("1: 123\n"
1378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                          "14: \"foo\"\n");
1379fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStderrMatchesText("");
1380fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1381fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1382fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(EncodeDecodeTest, UnknownType) {
1383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_FALSE(Run("google/protobuf/unittest.proto "
1384fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                   "--encode=NoSuchType"));
1385fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStdoutMatchesText("");
1386fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStderrMatchesText("Type not defined: NoSuchType\n");
1387fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1389fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(EncodeDecodeTest, ProtoParseError) {
1390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_FALSE(Run("google/protobuf/no_such_file.proto "
1391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                   "--encode=NoSuchType"));
1392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStdoutMatchesText("");
1393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ExpectStderrMatchesText(
1394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "google/protobuf/no_such_file.proto: File not found.\n");
1395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // anonymous namespace
1398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1399fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace compiler
1400fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace protobuf
1401fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace google
1402