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 31 // Author: kenton (at) google.com (Kenton Varda) 32 // emulates google3/testing/base/public/googletest.cc 33 34 #include <google/protobuf/testing/googletest.h> 35 #include <google/protobuf/testing/file.h> 36 #include <google/protobuf/stubs/strutil.h> 37 #include <sys/stat.h> 38 #include <sys/types.h> 39 #include <errno.h> 40 #include <stdlib.h> 41 #ifdef _MSC_VER 42 #include <io.h> 43 #include <direct.h> 44 #else 45 #include <unistd.h> 46 #endif 47 #include <stdio.h> 48 #include <fcntl.h> 49 #include <iostream> 50 #include <fstream> 51 52 namespace google { 53 namespace protobuf { 54 55 #ifdef _WIN32 56 #define mkdir(name, mode) mkdir(name) 57 #endif 58 59 #ifndef O_BINARY 60 #ifdef _O_BINARY 61 #define O_BINARY _O_BINARY 62 #else 63 #define O_BINARY 0 // If this isn't defined, the platform doesn't need it. 64 #endif 65 #endif 66 67 string TestSourceDir() { 68 #ifndef GOOGLE_THIRD_PARTY_PROTOBUF 69 #ifndef _MSC_VER 70 // automake sets the "srcdir" environment variable. 71 char* result = getenv("srcdir"); 72 if (result != NULL) { 73 return result; 74 } 75 #endif // _MSC_VER 76 77 // Look for the "src" directory. 78 string prefix = "."; 79 80 while (!File::Exists(prefix + "/src/google/protobuf")) { 81 if (!File::Exists(prefix)) { 82 GOOGLE_LOG(FATAL) 83 << "Could not find protobuf source code. Please run tests from " 84 "somewhere within the protobuf source package."; 85 } 86 prefix += "/.."; 87 } 88 return prefix + "/src"; 89 #else 90 return "third_party/protobuf/src"; 91 #endif // GOOGLE_THIRD_PARTY_PROTOBUF 92 } 93 94 namespace { 95 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 104 // tmpnam() is generally not considered safe but we're only using it for 105 // testing. We cannot use tmpfile() or mkstemp() since we're creating a 106 // directory. 107 char b[L_tmpnam + 1]; // HPUX multithread return 0 if s is 0 108 string result = tmpnam(b); 109 #ifdef _WIN32 110 // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed 111 // to be used in the current working directory. WTF? 112 if (HasPrefixString(result, "\\")) { 113 result.erase(0, 1); 114 } 115 // The Win32 API accepts forward slashes as a path delimiter even though 116 // backslashes are standard. Let's avoid confusion and use only forward 117 // slashes. 118 result = StringReplace(result, "\\", "/", true); 119 #endif // _WIN32 120 return result; 121 } 122 123 // Creates a temporary directory on demand and deletes it when the process 124 // quits. 125 class TempDirDeleter { 126 public: 127 TempDirDeleter() {} 128 ~TempDirDeleter() { 129 if (!name_.empty()) { 130 File::DeleteRecursively(name_, NULL, NULL); 131 } 132 } 133 134 string GetTempDir() { 135 if (name_.empty()) { 136 name_ = GetTemporaryDirectoryName(); 137 GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno); 138 139 // Stick a file in the directory that tells people what this is, in case 140 // we abort and don't get a chance to delete it. 141 File::WriteStringToFileOrDie("", name_ + "/TEMP_DIR_FOR_PROTOBUF_TESTS"); 142 } 143 return name_; 144 } 145 146 private: 147 string name_; 148 }; 149 150 TempDirDeleter temp_dir_deleter_; 151 152 } // namespace 153 154 string TestTempDir() { 155 return temp_dir_deleter_.GetTempDir(); 156 } 157 158 // TODO(kenton): Share duplicated code below. Too busy/lazy for now. 159 160 static string stdout_capture_filename_; 161 static string stderr_capture_filename_; 162 static int original_stdout_ = -1; 163 static int original_stderr_ = -1; 164 165 void CaptureTestStdout() { 166 GOOGLE_CHECK_EQ(original_stdout_, -1) << "Already capturing."; 167 168 stdout_capture_filename_ = TestTempDir() + "/captured_stdout"; 169 170 int fd = open(stdout_capture_filename_.c_str(), 171 O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777); 172 GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno); 173 174 original_stdout_ = dup(1); 175 close(1); 176 dup2(fd, 1); 177 close(fd); 178 } 179 180 void CaptureTestStderr() { 181 GOOGLE_CHECK_EQ(original_stderr_, -1) << "Already capturing."; 182 183 stderr_capture_filename_ = TestTempDir() + "/captured_stderr"; 184 185 int fd = open(stderr_capture_filename_.c_str(), 186 O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777); 187 GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno); 188 189 original_stderr_ = dup(2); 190 close(2); 191 dup2(fd, 2); 192 close(fd); 193 } 194 195 string GetCapturedTestStdout() { 196 GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing."; 197 198 close(1); 199 dup2(original_stdout_, 1); 200 original_stdout_ = -1; 201 202 string result; 203 File::ReadFileToStringOrDie(stdout_capture_filename_, &result); 204 205 remove(stdout_capture_filename_.c_str()); 206 207 return result; 208 } 209 210 string GetCapturedTestStderr() { 211 GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing."; 212 213 close(2); 214 dup2(original_stderr_, 2); 215 original_stderr_ = -1; 216 217 string result; 218 File::ReadFileToStringOrDie(stderr_capture_filename_, &result); 219 220 remove(stderr_capture_filename_.c_str()); 221 222 return result; 223 } 224 225 ScopedMemoryLog* ScopedMemoryLog::active_log_ = NULL; 226 227 ScopedMemoryLog::ScopedMemoryLog() { 228 GOOGLE_CHECK(active_log_ == NULL); 229 active_log_ = this; 230 old_handler_ = SetLogHandler(&HandleLog); 231 } 232 233 ScopedMemoryLog::~ScopedMemoryLog() { 234 SetLogHandler(old_handler_); 235 active_log_ = NULL; 236 } 237 238 const vector<string>& ScopedMemoryLog::GetMessages(LogLevel level) { 239 GOOGLE_CHECK(level == ERROR || 240 level == WARNING); 241 return messages_[level]; 242 } 243 244 void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, 245 int line, const string& message) { 246 GOOGLE_CHECK(active_log_ != NULL); 247 if (level == ERROR || level == WARNING) { 248 active_log_->messages_[level].push_back(message); 249 } 250 } 251 252 namespace { 253 254 // Force shutdown at process exit so that we can test for memory leaks. To 255 // actually check for leaks, I suggest using the heap checker included with 256 // google-perftools. Set it to "draconian" mode to ensure that every last 257 // call to malloc() has a corresponding free(). 258 struct ForceShutdown { 259 ~ForceShutdown() { 260 ShutdownProtobufLibrary(); 261 } 262 } force_shutdown; 263 264 } // namespace 265 266 } // namespace protobuf 267 } // namespace google 268