| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2014-05-02 07:23:25 -07:00
										 |  |  |  Custom Google Test assertions. | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |  Copyright (c) 2012-2014, Victor Zverovich | 
					
						
							|  |  |  |  All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  1. Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |     list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  2. Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |     this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |     and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | 
					
						
							|  |  |  |  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
					
						
							|  |  |  |  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | 
					
						
							|  |  |  |  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
					
						
							|  |  |  |  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
					
						
							|  |  |  |  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
					
						
							|  |  |  |  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
					
						
							|  |  |  |  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 08:48:16 -07:00
										 |  |  | #ifndef FMT_GTEST_EXTRA_H_
 | 
					
						
							|  |  |  | #define FMT_GTEST_EXTRA_H_
 | 
					
						
							| 
									
										
										
										
											2014-05-02 07:23:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-03 11:26:46 -07:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2016-05-19 15:04:25 -07:00
										 |  |  | #include <gmock/gmock.h>
 | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 09:06:12 -07:00
										 |  |  | #include "fmt/format.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-09 08:33:48 -07:00
										 |  |  | #ifndef FMT_USE_FILE_DESCRIPTORS
 | 
					
						
							|  |  |  | # define FMT_USE_FILE_DESCRIPTORS 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if FMT_USE_FILE_DESCRIPTORS
 | 
					
						
							| 
									
										
										
										
											2016-04-24 09:06:12 -07:00
										 |  |  | # include "fmt/posix.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-09 08:33:48 -07:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  | #define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
 | 
					
						
							|  |  |  |   GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | 
					
						
							| 
									
										
										
										
											2014-05-02 06:33:21 -07:00
										 |  |  |   if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \ | 
					
						
							| 
									
										
										
										
											2014-05-05 08:20:01 -07:00
										 |  |  |     std::string gtest_expected_message = expected_message; \ | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  |     bool gtest_caught_expected = false; \ | 
					
						
							|  |  |  |     try { \ | 
					
						
							|  |  |  |       GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |     catch (expected_exception const& e) { \ | 
					
						
							| 
									
										
										
										
											2014-05-05 08:20:01 -07:00
										 |  |  |       if (gtest_expected_message != e.what()) { \ | 
					
						
							| 
									
										
										
										
											2014-05-02 07:07:55 -07:00
										 |  |  |         gtest_ar \ | 
					
						
							|  |  |  |           << #statement " throws an exception with a different message.\n" \ | 
					
						
							| 
									
										
										
										
											2014-05-05 08:20:01 -07:00
										 |  |  |           << "Expected: " << gtest_expected_message << "\n" \ | 
					
						
							| 
									
										
										
										
											2014-05-02 07:07:55 -07:00
										 |  |  |           << "  Actual: " << e.what(); \ | 
					
						
							| 
									
										
										
										
											2014-05-02 06:33:21 -07:00
										 |  |  |         goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | 
					
						
							|  |  |  |       } \ | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  |       gtest_caught_expected = true; \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |     catch (...) { \ | 
					
						
							| 
									
										
										
										
											2014-05-02 06:33:21 -07:00
										 |  |  |       gtest_ar << \ | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  |           "Expected: " #statement " throws an exception of type " \ | 
					
						
							|  |  |  |           #expected_exception ".\n  Actual: it throws a different type."; \
 | 
					
						
							|  |  |  |       goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |     if (!gtest_caught_expected) { \ | 
					
						
							| 
									
										
										
										
											2014-05-02 06:33:21 -07:00
										 |  |  |       gtest_ar << \ | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  |           "Expected: " #statement " throws an exception of type " \ | 
					
						
							|  |  |  |           #expected_exception ".\n  Actual: it throws nothing."; \
 | 
					
						
							|  |  |  |       goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |   } else \ | 
					
						
							|  |  |  |     GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ | 
					
						
							| 
									
										
										
										
											2014-05-02 06:33:21 -07:00
										 |  |  |       fail(gtest_ar.failure_message()) | 
					
						
							| 
									
										
										
										
											2014-05-01 16:49:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Tests that the statement throws the expected exception and the exception's
 | 
					
						
							|  |  |  | // what() method returns expected message.
 | 
					
						
							|  |  |  | #define EXPECT_THROW_MSG(statement, expected_exception, expected_message) \
 | 
					
						
							|  |  |  |   FMT_TEST_THROW_(statement, expected_exception, \ | 
					
						
							|  |  |  |       expected_message, GTEST_NONFATAL_FAILURE_) | 
					
						
							| 
									
										
										
										
											2014-05-02 07:23:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-27 15:09:05 -07:00
										 |  |  | std::string format_system_error(int error_code, fmt::StringRef message); | 
					
						
							| 
									
										
										
										
											2014-05-06 06:11:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define EXPECT_SYSTEM_ERROR(statement, error_code, message) \
 | 
					
						
							|  |  |  |   EXPECT_THROW_MSG(statement, fmt::SystemError, \ | 
					
						
							| 
									
										
										
										
											2014-07-27 15:09:05 -07:00
										 |  |  |       format_system_error(error_code, message)) | 
					
						
							| 
									
										
										
										
											2014-05-06 06:11:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | #if FMT_USE_FILE_DESCRIPTORS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-03 16:47:00 -07:00
										 |  |  | // Captures file output by redirecting it to a pipe.
 | 
					
						
							|  |  |  | // The output it can handle is limited by the pipe capacity.
 | 
					
						
							| 
									
										
										
										
											2014-05-04 06:44:50 -07:00
										 |  |  | class OutputRedirect { | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  |  private: | 
					
						
							| 
									
										
										
										
											2014-05-15 08:58:10 -07:00
										 |  |  |   FILE *file_; | 
					
						
							| 
									
										
										
										
											2014-06-09 09:07:27 -07:00
										 |  |  |   fmt::File original_;  // Original file passed to redirector.
 | 
					
						
							|  |  |  |   fmt::File read_end_;  // Read end of the pipe where the output is redirected.
 | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-04 06:44:50 -07:00
										 |  |  |   GTEST_DISALLOW_COPY_AND_ASSIGN_(OutputRedirect); | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-29 07:50:05 -07:00
										 |  |  |   void flush(); | 
					
						
							|  |  |  |   void restore(); | 
					
						
							| 
									
										
										
										
											2014-05-03 16:47:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  |  public: | 
					
						
							| 
									
										
										
										
											2014-05-15 08:58:10 -07:00
										 |  |  |   explicit OutputRedirect(FILE *file); | 
					
						
							| 
									
										
										
										
											2015-02-14 09:58:29 +08:00
										 |  |  |   ~OutputRedirect() FMT_NOEXCEPT; | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-03 16:47:00 -07:00
										 |  |  |   // Restores the original file, reads output from the pipe into a string
 | 
					
						
							|  |  |  |   // and returns it.
 | 
					
						
							| 
									
										
										
										
											2014-07-29 07:50:05 -07:00
										 |  |  |   std::string restore_and_read(); | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 08:35:59 -07:00
										 |  |  | #define FMT_TEST_WRITE_(statement, expected_output, file, fail) \
 | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  |   GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | 
					
						
							|  |  |  |   if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \ | 
					
						
							| 
									
										
										
										
											2014-05-05 08:20:01 -07:00
										 |  |  |     std::string gtest_expected_output = expected_output; \ | 
					
						
							|  |  |  |     OutputRedirect gtest_redir(file); \ | 
					
						
							|  |  |  |     GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | 
					
						
							| 
									
										
										
										
											2014-07-29 07:50:05 -07:00
										 |  |  |     std::string gtest_output = gtest_redir.restore_and_read(); \ | 
					
						
							| 
									
										
										
										
											2014-05-05 08:20:01 -07:00
										 |  |  |     if (gtest_output != gtest_expected_output) { \ | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  |       gtest_ar \ | 
					
						
							|  |  |  |         << #statement " produces different output.\n" \ | 
					
						
							| 
									
										
										
										
											2014-05-05 08:20:01 -07:00
										 |  |  |         << "Expected: " << gtest_expected_output << "\n" \ | 
					
						
							| 
									
										
										
										
											2014-05-04 10:08:29 -07:00
										 |  |  |         << "  Actual: " << gtest_output; \ | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  |       goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |   } else \ | 
					
						
							|  |  |  |     GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ | 
					
						
							|  |  |  |       fail(gtest_ar.failure_message()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 08:35:59 -07:00
										 |  |  | // Tests that the statement writes the expected output to file.
 | 
					
						
							|  |  |  | #define EXPECT_WRITE(file, statement, expected_output) \
 | 
					
						
							|  |  |  |     FMT_TEST_WRITE_(statement, expected_output, file, GTEST_NONFATAL_FAILURE_) | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-24 09:16:03 -07:00
										 |  |  | #ifdef _MSC_VER
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Suppresses Windows assertions on invalid file descriptors, making
 | 
					
						
							|  |  |  | // POSIX functions return proper error codes instead of crashing on Windows.
 | 
					
						
							|  |  |  | class SuppressAssert { | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   _invalid_parameter_handler original_handler_; | 
					
						
							|  |  |  |   int original_report_mode_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static void handle_invalid_parameter(const wchar_t *, | 
					
						
							|  |  |  |       const wchar_t *, const wchar_t *, unsigned , uintptr_t) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   SuppressAssert() | 
					
						
							|  |  |  |   : original_handler_(_set_invalid_parameter_handler(handle_invalid_parameter)), | 
					
						
							|  |  |  |     original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   ~SuppressAssert() { | 
					
						
							|  |  |  |     _set_invalid_parameter_handler(original_handler_); | 
					
						
							|  |  |  |     _CrtSetReportMode(_CRT_ASSERT, original_report_mode_); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # define SUPPRESS_ASSERT(statement) { SuppressAssert sa; statement; }
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define SUPPRESS_ASSERT(statement) statement
 | 
					
						
							|  |  |  | #endif  // _MSC_VER
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EXPECT_SYSTEM_ERROR_NOASSERT(statement, error_code, message) \
 | 
					
						
							|  |  |  |   EXPECT_SYSTEM_ERROR(SUPPRESS_ASSERT(statement), error_code, message) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Attempts to read count characters from a file.
 | 
					
						
							|  |  |  | std::string read(fmt::File &f, std::size_t count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EXPECT_READ(file, expected_content) \
 | 
					
						
							|  |  |  |   EXPECT_EQ(expected_content, read(file, std::strlen(expected_content))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-03 09:48:54 -07:00
										 |  |  | #endif  // FMT_USE_FILE_DESCRIPTORS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-19 15:04:25 -07:00
										 |  |  | template <typename Mock> | 
					
						
							|  |  |  | struct ScopedMock : testing::StrictMock<Mock> { | 
					
						
							|  |  |  |   ScopedMock() { Mock::instance = this; } | 
					
						
							|  |  |  |   ~ScopedMock() { Mock::instance = 0; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 08:48:16 -07:00
										 |  |  | #endif  // FMT_GTEST_EXTRA_H_
 |