• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_TESTER_H__
9 #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_TESTER_H__
10 
11 #include <fcntl.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 #ifndef _MSC_VER
21 #include <unistd.h>
22 #endif
23 
24 #include <gtest/gtest.h>
25 #include "absl/strings/string_view.h"
26 #include "google/protobuf/compiler/code_generator.h"
27 #include "google/protobuf/compiler/command_line_interface.h"
28 
29 // Must be included last.
30 #include "google/protobuf/port_def.inc"
31 
32 namespace google {
33 namespace protobuf {
34 namespace compiler {
35 
36 // Provide a base class for testing the protoc CLI and plugins.
37 class CommandLineInterfaceTester : public testing::Test {
38  protected:
39   CommandLineInterfaceTester();
40   ~CommandLineInterfaceTester() override;
41 
42   // Runs the CommandLineInterface with the given command line.  The
43   // command is automatically split on spaces, and the string "$tmpdir"
44   // is replaced with TestTempDir().
45   void RunProtoc(absl::string_view command);
46   void RunProtocWithArgs(std::vector<std::string> args);
47 
48   // -----------------------------------------------------------------
49   // Methods to set up the test (called before Run()).
50 
51   // Returns the temporary directory created for testing.
temp_directory()52   std::string temp_directory() { return temp_directory_; }
53 
AllowPlugins(const std::string & prefix)54   void AllowPlugins(const std::string& prefix) { cli_.AllowPlugins(prefix); }
55 
RegisterGenerator(const std::string & flag_name,std::unique_ptr<CodeGenerator> generator,const std::string & help_text)56   void RegisterGenerator(const std::string& flag_name,
57                          std::unique_ptr<CodeGenerator> generator,
58                          const std::string& help_text) {
59     generators_.emplace_back(std::move(generator));
60     cli_.RegisterGenerator(flag_name, generators_.back().get(), help_text);
61   }
62 
RegisterGenerator(const std::string & flag_name,const std::string & option_flag_name,std::unique_ptr<CodeGenerator> generator,const std::string & help_text)63   void RegisterGenerator(const std::string& flag_name,
64                          const std::string& option_flag_name,
65                          std::unique_ptr<CodeGenerator> generator,
66                          const std::string& help_text) {
67     generators_.emplace_back(std::move(generator));
68     cli_.RegisterGenerator(flag_name, option_flag_name,
69                            generators_.back().get(), help_text);
70   }
71 
72   // Creates a temp file within temp_directory_ with the given name.
73   // The containing directory is also created if necessary.
74   void CreateTempFile(absl::string_view name, absl::string_view contents);
75 
76   // Creates a subdirectory within temp_directory_.
77   void CreateTempDir(absl::string_view name);
78 
79 #ifdef PROTOBUF_OPENSOURCE
80   // Changes working directory to temp directory.
SwitchToTempDirectory()81   void SwitchToTempDirectory() {
82     File::ChangeWorkingDirectory(temp_directory_);
83   }
84 #endif  // !PROTOBUF_OPENSOURCE
85 
86   // -----------------------------------------------------------------
87   // Methods to check the test results (called after Run()).
88 
89   // Checks that no text was written to stderr during Run(), and Run()
90   // returned 0.
91   void ExpectNoErrors();
92 
93   // Checks that Run() returned non-zero and the stderr output is exactly
94   // the text given.  expected_test may contain references to "$tmpdir",
95   // which will be replaced by the temporary directory path.
96   void ExpectErrorText(absl::string_view expected_text);
97 
98   // Checks that Run() returned non-zero and the stderr contains the given
99   // substring.
100   void ExpectErrorSubstring(absl::string_view expected_substring);
101 
102   // Checks that Run() returned zero and the stderr contains the given
103   // substring.
104   void ExpectWarningSubstring(absl::string_view expected_substring);
105 
106   // Checks that the captured stdout is the same as the expected_text.
107   void ExpectCapturedStdout(absl::string_view expected_text);
108 
109   // Checks that Run() returned zero and the stdout contains the given
110   // substring.
111   void ExpectCapturedStdoutSubstringWithZeroReturnCode(
112       absl::string_view expected_substring);
113 
114   // Checks that Run() returned zero and the stderr contains the given
115   // substring.
116   void ExpectCapturedStderrSubstringWithZeroReturnCode(
117       absl::string_view expected_substring);
118 
119 #if defined(_WIN32) && !defined(__CYGWIN__)
120   // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
121   // does not fail otherwise.
122   bool HasAlternateErrorSubstring(const std::string& expected_substring);
123 #endif  // _WIN32 && !__CYGWIN__
124 
125   void ExpectFileContent(absl::string_view filename, absl::string_view content);
126 
127  private:
128   // The object we are testing.
129   CommandLineInterface cli_;
130 
131   // We create a directory within TestTempDir() in order to add extra
132   // protection against accidentally deleting user files (since we recursively
133   // delete this directory during the test).  This is the full path of that
134   // directory.
135   std::string temp_directory_;
136 
137   // The result of Run().
138   int return_code_;
139 
140   // The captured stderr output.
141   std::string error_text_;
142 
143   // The captured stdout.
144   std::string captured_stdout_;
145 
146   std::vector<std::unique_ptr<CodeGenerator>> generators_;
147 };
148 
149 }  // namespace compiler
150 }  // namespace protobuf
151 }  // namespace google
152 
153 #include "google/protobuf/port_undef.inc"
154 
155 #endif  // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_TEST_UTIL_H__
156