1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // This file defines a protocol for running the conformance test suite
33 // in-process. In other words, the suite itself will run in the same process as
34 // the code under test.
36 // For pros and cons of this approach, please see conformance.proto.
38 #ifndef CONFORMANCE_CONFORMANCE_TEST_H
39 #define CONFORMANCE_CONFORMANCE_TEST_H
44 #include <google/protobuf/descriptor.h>
45 #include <google/protobuf/stubs/common.h>
46 #include <google/protobuf/util/type_resolver.h>
47 #include <google/protobuf/wire_format_lite.h>
49 #include "conformance.pb.h"
51 namespace conformance {
52 class ConformanceRequest;
53 class ConformanceResponse;
54 } // namespace conformance
56 namespace protobuf_test_messages {
58 class TestAllTypesProto3;
60 } // namespace protobuf_test_messages
65 class ConformanceTestSuite;
67 class ConformanceTestRunner {
69 virtual ~ConformanceTestRunner() {}
71 // Call to run a single conformance test.
73 // "input" is a serialized conformance.ConformanceRequest.
74 // "output" should be set to a serialized conformance.ConformanceResponse.
76 // If there is any error in running the test itself, set "runtime_error" in
78 virtual void RunTest(const std::string& test_name,
79 const std::string& input,
80 std::string* output) = 0;
83 // Test runner that spawns the process being tested and communicates with it
85 class ForkPipeRunner : public ConformanceTestRunner {
87 // Note: Run() doesn't take ownership of the pointers inside suites.
88 static int Run(int argc, char *argv[],
89 const std::vector<ConformanceTestSuite*>& suites);
91 ForkPipeRunner(const std::string &executable)
92 : child_pid_(-1), executable_(executable) {}
94 virtual ~ForkPipeRunner() {}
96 void RunTest(const std::string& test_name,
97 const std::string& request,
98 std::string* response);
101 void SpawnTestProgram();
103 void CheckedWrite(int fd, const void *buf, size_t len);
104 bool TryRead(int fd, void *buf, size_t len);
105 void CheckedRead(int fd, void *buf, size_t len);
110 std::string executable_;
111 std::string current_test_name_;
114 // Class representing the test suite itself. To run it, implement your own
115 // class derived from ConformanceTestRunner, class derived from
116 // ConformanceTestSuite and then write code like:
118 // class MyConformanceTestSuite : public ConformanceTestSuite {
120 // void RunSuiteImpl() {
121 // // INSERT ACTURAL TESTS.
125 // class MyConformanceTestRunner : public ConformanceTestRunner {
127 // static int Run(int argc, char *argv[],
128 // ConformanceTestSuite* suite);
131 // virtual void RunTest(...) {
132 // // INSERT YOUR FRAMEWORK-SPECIFIC CODE HERE.
137 // MyConformanceTestSuite suite;
138 // MyConformanceTestRunner::Run(argc, argv, &suite);
141 class ConformanceTestSuite {
143 ConformanceTestSuite()
145 enforce_recommended_(false),
146 failure_list_flag_name_("--failure_list") {}
147 virtual ~ConformanceTestSuite() {}
149 void SetVerbose(bool verbose) { verbose_ = verbose; }
151 // Whether to require the testee to pass RECOMMENDED tests. By default failing
152 // a RECOMMENDED test case will not fail the entire suite but will only
153 // generated a warning. If this flag is set to true, RECOMMENDED tests will
154 // be treated the same way as REQUIRED tests and failing a RECOMMENDED test
155 // case will cause the entire test suite to fail as well. An implementation
156 // can enable this if it wants to be strictly conforming to protobuf spec.
157 // See the comments about ConformanceLevel below to learn more about the
158 // difference between REQUIRED and RECOMMENDED test cases.
159 void SetEnforceRecommended(bool value) {
160 enforce_recommended_ = value;
163 // Gets the flag name to the failure list file.
164 // By default, this would return --failure_list
165 string GetFailureListFlagName() {
166 return failure_list_flag_name_;
169 void SetFailureListFlagName(const std::string& failure_list_flag_name) {
170 failure_list_flag_name_ = failure_list_flag_name;
173 // Run all the conformance tests against the given test runner.
174 // Test output will be stored in "output".
176 // Returns true if the set of failing tests was exactly the same as the
178 // The filename here is *only* used to create/format useful error messages for
179 // how to update the failure list. We do NOT read this file at all.
180 bool RunSuite(ConformanceTestRunner* runner, std::string* output,
181 const std::string& filename,
182 conformance::FailureSet* failure_list);
185 // Test cases are classified into a few categories:
186 // REQUIRED: the test case must be passed for an implementation to be
187 // interoperable with other implementations. For example, a
188 // parser implementaiton must accept both packed and unpacked
189 // form of repeated primitive fields.
190 // RECOMMENDED: the test case is not required for the implementation to
191 // be interoperable with other implementations, but is
192 // recommended for best performance and compatibility. For
193 // example, a proto3 serializer should serialize repeated
194 // primitive fields in packed form, but an implementation
195 // failing to do so will still be able to communicate with
196 // other implementations.
197 enum ConformanceLevel {
202 class ConformanceRequestSetting {
204 ConformanceRequestSetting(
205 ConformanceLevel level,
206 conformance::WireFormat input_format,
207 conformance::WireFormat output_format,
208 conformance::TestCategory test_category,
209 const Message& prototype_message,
210 const string& test_name, const string& input);
211 virtual ~ConformanceRequestSetting() {}
213 Message* GetTestMessage() const;
215 string GetTestName() const;
217 const conformance::ConformanceRequest& GetRequest() const {
221 const ConformanceLevel GetLevel() const {
225 string ConformanceLevelToString(ConformanceLevel level) const;
227 void SetPrintUnknownFields(bool print_unknown_fields) {
228 request_.set_print_unknown_fields(true);
231 void SetPrototypeMessageForCompare(const Message& message) {
232 prototype_message_for_compare_.reset(message.New());
236 virtual string InputFormatString(conformance::WireFormat format) const;
237 virtual string OutputFormatString(conformance::WireFormat format) const;
238 conformance::ConformanceRequest request_;
241 ConformanceLevel level_;
242 ::conformance::WireFormat input_format_;
243 ::conformance::WireFormat output_format_;
244 const Message& prototype_message_;
245 std::unique_ptr<Message> prototype_message_for_compare_;
249 bool CheckSetEmpty(const std::set<string>& set_to_check,
250 const std::string& write_to_file, const std::string& msg);
251 string WireFormatToString(conformance::WireFormat wire_format);
253 // Parse payload in the response to the given message. Returns true on
255 virtual bool ParseResponse(
256 const conformance::ConformanceResponse& response,
257 const ConformanceRequestSetting& setting,
258 Message* test_message) = 0;
261 const ConformanceRequestSetting& setting,
262 const string& equivalent_wire_format,
263 const conformance::ConformanceResponse& response,
264 bool need_report_success);
266 void ReportSuccess(const std::string& test_name);
267 void ReportFailure(const string& test_name,
268 ConformanceLevel level,
269 const conformance::ConformanceRequest& request,
270 const conformance::ConformanceResponse& response,
271 const char* fmt, ...);
272 void ReportSkip(const string& test_name,
273 const conformance::ConformanceRequest& request,
274 const conformance::ConformanceResponse& response);
276 void RunValidInputTest(const ConformanceRequestSetting& setting,
277 const string& equivalent_text_format);
278 void RunValidBinaryInputTest(const ConformanceRequestSetting& setting,
279 const string& equivalent_wire_format);
281 void RunTest(const std::string& test_name,
282 const conformance::ConformanceRequest& request,
283 conformance::ConformanceResponse* response);
285 void AddExpectedFailedTest(const std::string& test_name);
287 virtual void RunSuiteImpl() = 0;
289 ConformanceTestRunner* runner_;
291 int expected_failures_;
293 bool enforce_recommended_;
295 std::string failure_list_flag_name_;
296 std::string failure_list_filename_;
298 // The set of test names that are expected to fail in this run, but haven't
300 std::set<std::string> expected_to_fail_;
302 // The set of test names that have been run. Used to ensure that there are no
303 // duplicate names in the suite.
304 std::set<std::string> test_names_;
306 // The set of tests that failed, but weren't expected to.
307 std::set<std::string> unexpected_failing_tests_;
309 // The set of tests that succeeded, but weren't expected to.
310 std::set<std::string> unexpected_succeeding_tests_;
312 // The set of tests that the testee opted out of;
313 std::set<std::string> skipped_;
316 } // namespace protobuf
317 } // namespace google
319 #endif // CONFORMANCE_CONFORMANCE_TEST_H