googletest.cc 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  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.
  30. // Author: kenton@google.com (Kenton Varda)
  31. // emulates google3/testing/base/public/googletest.cc
  32. #include <google/protobuf/testing/googletest.h>
  33. #include <google/protobuf/testing/file.h>
  34. #include <google/protobuf/stubs/io_win32.h>
  35. #include <google/protobuf/stubs/strutil.h>
  36. #include <sys/stat.h>
  37. #include <sys/types.h>
  38. #include <errno.h>
  39. #include <stdlib.h>
  40. #ifdef _MSC_VER
  41. // #include <direct.h>
  42. #else
  43. #include <unistd.h>
  44. #endif
  45. #include <stdio.h>
  46. #include <fcntl.h>
  47. #include <iostream>
  48. #include <fstream>
  49. namespace google {
  50. namespace protobuf {
  51. #ifdef _WIN32
  52. // DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
  53. // them like we do below.
  54. using google::protobuf::internal::win32::close;
  55. using google::protobuf::internal::win32::dup2;
  56. using google::protobuf::internal::win32::dup;
  57. using google::protobuf::internal::win32::mkdir;
  58. using google::protobuf::internal::win32::open;
  59. #endif
  60. #ifndef O_BINARY
  61. #ifdef _O_BINARY
  62. #define O_BINARY _O_BINARY
  63. #else
  64. #define O_BINARY 0 // If this isn't defined, the platform doesn't need it.
  65. #endif
  66. #endif
  67. string TestSourceDir() {
  68. #ifndef GOOGLE_THIRD_PARTY_PROTOBUF
  69. #ifdef GOOGLE_PROTOBUF_TEST_SOURCE_PATH
  70. return GOOGLE_PROTOBUF_TEST_SOURCE_PATH;
  71. #else
  72. #ifndef _MSC_VER
  73. // automake sets the "srcdir" environment variable.
  74. char* result = getenv("srcdir");
  75. if (result != NULL) {
  76. return result;
  77. }
  78. #endif // _MSC_VER
  79. // Look for the "src" directory.
  80. string prefix = ".";
  81. while (!File::Exists(prefix + "/src/google/protobuf")) {
  82. if (!File::Exists(prefix)) {
  83. GOOGLE_LOG(FATAL)
  84. << "Could not find protobuf source code. Please run tests from "
  85. "somewhere within the protobuf source package.";
  86. }
  87. prefix += "/..";
  88. }
  89. return prefix + "/src";
  90. #endif // GOOGLE_PROTOBUF_TEST_SOURCE_PATH
  91. #else
  92. return "third_party/protobuf/src";
  93. #endif // GOOGLE_THIRD_PARTY_PROTOBUF
  94. }
  95. namespace {
  96. string GetTemporaryDirectoryName() {
  97. // Tests run under Bazel "should not" use /tmp. Bazel sets this environment
  98. // variable for tests to use instead.
  99. char *from_environment = getenv("TEST_TMPDIR");
  100. if (from_environment != NULL && from_environment[0] != '\0') {
  101. return string(from_environment) + "/protobuf_tmpdir";
  102. }
  103. // tmpnam() is generally not considered safe but we're only using it for
  104. // testing. We cannot use tmpfile() or mkstemp() since we're creating a
  105. // directory.
  106. char b[L_tmpnam + 1]; // HPUX multithread return 0 if s is 0
  107. string result = tmpnam(b);
  108. #ifdef _WIN32
  109. // Avoid a trailing dot by changing it to an underscore. On Win32 the names of
  110. // files and directories can, but should not, end with dot.
  111. //
  112. // In MS-DOS and FAT16 filesystem the filenames were 8dot3 style so it didn't
  113. // make sense to have a name ending in dot without an extension, so the shell
  114. // silently ignored trailing dots. To this day the Win32 API still maintains
  115. // this behavior and silently ignores trailing dots in path arguments of
  116. // functions such as CreateFile{A,W}. Even POSIX API function implementations
  117. // seem to wrap the Win32 API functions (e.g. CreateDirectoryA) and behave
  118. // this way.
  119. // It's possible to avoid this behavior and create files / directories with
  120. // trailing dots (using CreateFileW / CreateDirectoryW and prefixing the path
  121. // with "\\?\") but these will be degenerate in the sense that you cannot
  122. // chdir into such directories (or navigate into them with Windows Explorer)
  123. // nor can you open such files with some programs (e.g. Notepad).
  124. if (result[result.size() - 1] == '.') {
  125. result[result.size() - 1] = '_';
  126. }
  127. // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed
  128. // to be used in the current working directory. WTF?
  129. if (HasPrefixString(result, "\\")) {
  130. result.erase(0, 1);
  131. }
  132. // The Win32 API accepts forward slashes as a path delimiter as long as the
  133. // path doesn't use the "\\?\" prefix.
  134. // Let's avoid confusion and use only forward slashes.
  135. result = StringReplace(result, "\\", "/", true);
  136. #endif // _WIN32
  137. return result;
  138. }
  139. // Creates a temporary directory on demand and deletes it when the process
  140. // quits.
  141. class TempDirDeleter {
  142. public:
  143. TempDirDeleter() {}
  144. ~TempDirDeleter() {
  145. if (!name_.empty()) {
  146. File::DeleteRecursively(name_, NULL, NULL);
  147. }
  148. }
  149. string GetTempDir() {
  150. if (name_.empty()) {
  151. name_ = GetTemporaryDirectoryName();
  152. GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno);
  153. // Stick a file in the directory that tells people what this is, in case
  154. // we abort and don't get a chance to delete it.
  155. File::WriteStringToFileOrDie("", name_ + "/TEMP_DIR_FOR_PROTOBUF_TESTS");
  156. }
  157. return name_;
  158. }
  159. private:
  160. string name_;
  161. };
  162. TempDirDeleter temp_dir_deleter_;
  163. } // namespace
  164. string TestTempDir() {
  165. return temp_dir_deleter_.GetTempDir();
  166. }
  167. // TODO(kenton): Share duplicated code below. Too busy/lazy for now.
  168. static string stdout_capture_filename_;
  169. static string stderr_capture_filename_;
  170. static int original_stdout_ = -1;
  171. static int original_stderr_ = -1;
  172. void CaptureTestStdout() {
  173. GOOGLE_CHECK_EQ(original_stdout_, -1) << "Already capturing.";
  174. stdout_capture_filename_ = TestTempDir() + "/captured_stdout";
  175. int fd = open(stdout_capture_filename_.c_str(),
  176. O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
  177. GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno);
  178. original_stdout_ = dup(1);
  179. close(1);
  180. dup2(fd, 1);
  181. close(fd);
  182. }
  183. void CaptureTestStderr() {
  184. GOOGLE_CHECK_EQ(original_stderr_, -1) << "Already capturing.";
  185. stderr_capture_filename_ = TestTempDir() + "/captured_stderr";
  186. int fd = open(stderr_capture_filename_.c_str(),
  187. O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
  188. GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno);
  189. original_stderr_ = dup(2);
  190. close(2);
  191. dup2(fd, 2);
  192. close(fd);
  193. }
  194. string GetCapturedTestStdout() {
  195. GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing.";
  196. close(1);
  197. dup2(original_stdout_, 1);
  198. original_stdout_ = -1;
  199. string result;
  200. File::ReadFileToStringOrDie(stdout_capture_filename_, &result);
  201. remove(stdout_capture_filename_.c_str());
  202. return result;
  203. }
  204. string GetCapturedTestStderr() {
  205. GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing.";
  206. close(2);
  207. dup2(original_stderr_, 2);
  208. original_stderr_ = -1;
  209. string result;
  210. File::ReadFileToStringOrDie(stderr_capture_filename_, &result);
  211. remove(stderr_capture_filename_.c_str());
  212. return result;
  213. }
  214. ScopedMemoryLog* ScopedMemoryLog::active_log_ = NULL;
  215. ScopedMemoryLog::ScopedMemoryLog() {
  216. GOOGLE_CHECK(active_log_ == NULL);
  217. active_log_ = this;
  218. old_handler_ = SetLogHandler(&HandleLog);
  219. }
  220. ScopedMemoryLog::~ScopedMemoryLog() {
  221. SetLogHandler(old_handler_);
  222. active_log_ = NULL;
  223. }
  224. const std::vector<string>& ScopedMemoryLog::GetMessages(LogLevel level) {
  225. GOOGLE_CHECK(level == ERROR ||
  226. level == WARNING);
  227. return messages_[level];
  228. }
  229. void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename,
  230. int line, const string& message) {
  231. GOOGLE_CHECK(active_log_ != NULL);
  232. if (level == ERROR || level == WARNING) {
  233. active_log_->messages_[level].push_back(message);
  234. }
  235. }
  236. namespace {
  237. // Force shutdown at process exit so that we can test for memory leaks. To
  238. // actually check for leaks, I suggest using the heap checker included with
  239. // google-perftools. Set it to "draconian" mode to ensure that every last
  240. // call to malloc() has a corresponding free().
  241. struct ForceShutdown {
  242. ~ForceShutdown() {
  243. ShutdownProtobufLibrary();
  244. // Test to shutdown the library twice, which should succeed.
  245. ShutdownProtobufLibrary();
  246. }
  247. } force_shutdown;
  248. } // namespace
  249. } // namespace protobuf
  250. } // namespace google