1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson// https://developers.google.com/protocol-buffers/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda)
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// emulates google3/testing/base/public/googletest.cc
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/googletest.h>
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/file.h>
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/strutil.h>
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/stat.h>
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/types.h>
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <errno.h>
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stdlib.h>
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _MSC_VER
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <io.h>
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <direct.h>
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <unistd.h>
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stdio.h>
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <fcntl.h>
49d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <iostream>
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <fstream>
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google {
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf {
54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32
56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define mkdir(name, mode) mkdir(name)
57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef O_BINARY
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _O_BINARY
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define O_BINARY _O_BINARY
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define O_BINARY 0     // If this isn't defined, the platform doesn't need it.
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring TestSourceDir() {
68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef _MSC_VER
70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // automake sets the "srcdir" environment variable.
71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char* result = getenv("srcdir");
72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (result != NULL) {
73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return result;
74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif  // _MSC_VER
76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Look for the "src" directory.
78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string prefix = ".";
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  while (!File::Exists(prefix + "/src/google/protobuf")) {
81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (!File::Exists(prefix)) {
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      GOOGLE_LOG(FATAL)
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        << "Could not find protobuf source code.  Please run tests from "
84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville           "somewhere within the protobuf source package.";
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    prefix += "/..";
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return prefix + "/src";
89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return "third_party/protobuf/src";
91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace {
95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring GetTemporaryDirectoryName() {
97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Tests run under Bazel "should not" use /tmp. Bazel sets this environment
98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // variable for tests to use instead.
99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *from_environment = getenv("TEST_TMPDIR");
100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (from_environment != NULL && from_environment[0] != '\0') {
101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return string(from_environment) + "/protobuf_tmpdir";
102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // tmpnam() is generally not considered safe but we're only using it for
105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // testing.  We cannot use tmpfile() or mkstemp() since we're creating a
106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // directory.
107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  char b[L_tmpnam + 1];     // HPUX multithread return 0 if s is 0
108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string result = tmpnam(b);
109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32
110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed
111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // to be used in the current working directory.  WTF?
112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasPrefixString(result, "\\")) {
113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    result.erase(0, 1);
114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // The Win32 API accepts forward slashes as a path delimiter even though
116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // backslashes are standard.  Let's avoid confusion and use only forward
117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // slashes.
118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  result = StringReplace(result, "\\", "/", true);
119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif  // _WIN32
120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Creates a temporary directory on demand and deletes it when the process
124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// quits.
125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass TempDirDeleter {
126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public:
127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  TempDirDeleter() {}
128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ~TempDirDeleter() {
129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (!name_.empty()) {
130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      File::DeleteRecursively(name_, NULL, NULL);
131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string GetTempDir() {
135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (name_.empty()) {
136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      name_ = GetTemporaryDirectoryName();
137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno);
138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Stick a file in the directory that tells people what this is, in case
140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // we abort and don't get a chance to delete it.
141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      File::WriteStringToFileOrDie("", name_ + "/TEMP_DIR_FOR_PROTOBUF_TESTS");
142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return name_;
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private:
147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string name_;
148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville};
149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTempDirDeleter temp_dir_deleter_;
151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace
153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring TestTempDir() {
155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return temp_dir_deleter_.GetTempDir();
156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// TODO(kenton):  Share duplicated code below.  Too busy/lazy for now.
159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic string stdout_capture_filename_;
161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic string stderr_capture_filename_;
162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic int original_stdout_ = -1;
163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic int original_stderr_ = -1;
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CaptureTestStdout() {
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK_EQ(original_stdout_, -1) << "Already capturing.";
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  stdout_capture_filename_ = TestTempDir() + "/captured_stdout";
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int fd = open(stdout_capture_filename_.c_str(),
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno);
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  original_stdout_ = dup(1);
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  close(1);
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  dup2(fd, 1);
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  close(fd);
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CaptureTestStderr() {
181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK_EQ(original_stderr_, -1) << "Already capturing.";
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  stderr_capture_filename_ = TestTempDir() + "/captured_stderr";
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int fd = open(stderr_capture_filename_.c_str(),
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno);
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  original_stderr_ = dup(2);
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  close(2);
191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  dup2(fd, 2);
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  close(fd);
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring GetCapturedTestStdout() {
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing.";
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  close(1);
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  dup2(original_stdout_, 1);
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  original_stdout_ = -1;
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string result;
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  File::ReadFileToStringOrDie(stdout_capture_filename_, &result);
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  remove(stdout_capture_filename_.c_str());
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring GetCapturedTestStderr() {
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing.";
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  close(2);
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  dup2(original_stderr_, 2);
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  original_stderr_ = -1;
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string result;
218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  File::ReadFileToStringOrDie(stderr_capture_filename_, &result);
219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  remove(stderr_capture_filename_.c_str());
221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleScopedMemoryLog* ScopedMemoryLog::active_log_ = NULL;
226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleScopedMemoryLog::ScopedMemoryLog() {
228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(active_log_ == NULL);
229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  active_log_ = this;
230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  old_handler_ = SetLogHandler(&HandleLog);
231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleScopedMemoryLog::~ScopedMemoryLog() {
234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  SetLogHandler(old_handler_);
235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  active_log_ = NULL;
236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
238a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonconst vector<string>& ScopedMemoryLog::GetMessages(LogLevel level) {
239a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  GOOGLE_CHECK(level == ERROR ||
240a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson               level == WARNING);
241a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  return messages_[level];
242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid ScopedMemoryLog::HandleLog(LogLevel level, const char* filename,
245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                                int line, const string& message) {
246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(active_log_ != NULL);
247a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  if (level == ERROR || level == WARNING) {
248a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    active_log_->messages_[level].push_back(message);
249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace {
253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Force shutdown at process exit so that we can test for memory leaks.  To
255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// actually check for leaks, I suggest using the heap checker included with
256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// google-perftools.  Set it to "draconian" mode to ensure that every last
257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// call to malloc() has a corresponding free().
258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestruct ForceShutdown {
259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ~ForceShutdown() {
260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ShutdownProtobufLibrary();
261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} force_shutdown;
263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace
265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace protobuf
267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace google
268