test/fmw/gtest/src/gtest-death-test.cc
author iveresov
Mon, 19 Dec 2016 22:50:28 +0000
changeset 42879 ccdff4493787
parent 37967 8dd54c3bf02a
child 54913 9cfbe22bcdf8
permissions -rw-r--r--
Merge
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37967
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     1
// Copyright 2005, Google Inc.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     2
// All rights reserved.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     3
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     4
// Redistribution and use in source and binary forms, with or without
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     5
// modification, are permitted provided that the following conditions are
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     6
// met:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     7
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     8
//     * Redistributions of source code must retain the above copyright
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
     9
// notice, this list of conditions and the following disclaimer.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    10
//     * Redistributions in binary form must reproduce the above
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    11
// copyright notice, this list of conditions and the following disclaimer
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    12
// in the documentation and/or other materials provided with the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    13
// distribution.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    14
//     * Neither the name of Google Inc. nor the names of its
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    15
// contributors may be used to endorse or promote products derived from
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    16
// this software without specific prior written permission.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    17
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    29
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    30
// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    31
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    32
// This file implements death tests.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    33
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    34
#include "gtest/gtest-death-test.h"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    35
#include "gtest/internal/gtest-port.h"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    36
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    37
#if GTEST_HAS_DEATH_TEST
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    38
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    39
# if GTEST_OS_MAC
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    40
#  include <crt_externs.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    41
# endif  // GTEST_OS_MAC
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    42
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    43
# include <errno.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    44
# include <fcntl.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    45
# include <limits.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    46
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    47
# if GTEST_OS_LINUX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    48
#  include <signal.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    49
# endif  // GTEST_OS_LINUX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    50
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    51
# include <stdarg.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    52
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    53
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    54
#  include <windows.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    55
# else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    56
#  include <sys/mman.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    57
#  include <sys/wait.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    58
# endif  // GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    59
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    60
# if GTEST_OS_QNX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    61
#  include <spawn.h>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    62
# endif  // GTEST_OS_QNX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    63
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    64
#endif  // GTEST_HAS_DEATH_TEST
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    65
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    66
#include "gtest/gtest-message.h"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    67
#include "gtest/internal/gtest-string.h"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    68
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    69
// Indicates that this translation unit is part of Google Test's
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    70
// implementation.  It must come before gtest-internal-inl.h is
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    71
// included, or there will be a compiler error.  This trick is to
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    72
// prevent a user from accidentally including gtest-internal-inl.h in
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    73
// his code.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    74
#define GTEST_IMPLEMENTATION_ 1
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    75
#include "src/gtest-internal-inl.h"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    76
#undef GTEST_IMPLEMENTATION_
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    77
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    78
namespace testing {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    79
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    80
// Constants.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    81
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    82
// The default death test style.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    83
static const char kDefaultDeathTestStyle[] = "fast";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    84
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    85
GTEST_DEFINE_string_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    86
    death_test_style,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    87
    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    88
    "Indicates how to run a death test in a forked child process: "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    89
    "\"threadsafe\" (child process re-executes the test binary "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    90
    "from the beginning, running only the specific death test) or "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    91
    "\"fast\" (child process runs the death test immediately "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    92
    "after forking).");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    93
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    94
GTEST_DEFINE_bool_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    95
    death_test_use_fork,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    96
    internal::BoolFromGTestEnv("death_test_use_fork", false),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    97
    "Instructs to use fork()/_exit() instead of clone() in death tests. "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    98
    "Ignored and always uses fork() on POSIX systems where clone() is not "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
    99
    "implemented. Useful when running under valgrind or similar tools if "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   100
    "those do not support clone(). Valgrind 3.3.1 will just fail if "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   101
    "it sees an unsupported combination of clone() flags. "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   102
    "It is not recommended to use this flag w/o valgrind though it will "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   103
    "work in 99% of the cases. Once valgrind is fixed, this flag will "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   104
    "most likely be removed.");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   105
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   106
namespace internal {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   107
GTEST_DEFINE_string_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   108
    internal_run_death_test, "",
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   109
    "Indicates the file, line number, temporal index of "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   110
    "the single death test to run, and a file descriptor to "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   111
    "which a success code may be sent, all separated by "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   112
    "the '|' characters.  This flag is specified if and only if the current "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   113
    "process is a sub-process launched for running a thread-safe "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   114
    "death test.  FOR INTERNAL USE ONLY.");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   115
}  // namespace internal
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   116
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   117
#if GTEST_HAS_DEATH_TEST
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   118
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   119
namespace internal {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   120
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   121
// Valid only for fast death tests. Indicates the code is running in the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   122
// child process of a fast style death test.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   123
static bool g_in_fast_death_test_child = false;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   124
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   125
// Returns a Boolean value indicating whether the caller is currently
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   126
// executing in the context of the death test child process.  Tools such as
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   127
// Valgrind heap checkers may need this to modify their behavior in death
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   128
// tests.  IMPORTANT: This is an internal utility.  Using it may break the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   129
// implementation of death tests.  User code MUST NOT use it.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   130
bool InDeathTestChild() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   131
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   132
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   133
  // On Windows, death tests are thread-safe regardless of the value of the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   134
  // death_test_style flag.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   135
  return !GTEST_FLAG(internal_run_death_test).empty();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   136
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   137
# else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   138
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   139
  if (GTEST_FLAG(death_test_style) == "threadsafe")
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   140
    return !GTEST_FLAG(internal_run_death_test).empty();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   141
  else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   142
    return g_in_fast_death_test_child;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   143
#endif
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   144
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   145
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   146
}  // namespace internal
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   147
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   148
// ExitedWithCode constructor.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   149
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   150
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   151
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   152
// ExitedWithCode function-call operator.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   153
bool ExitedWithCode::operator()(int exit_status) const {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   154
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   155
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   156
  return exit_status == exit_code_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   157
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   158
# else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   159
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   160
  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   161
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   162
# endif  // GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   163
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   164
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   165
# if !GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   166
// KilledBySignal constructor.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   167
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   168
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   169
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   170
// KilledBySignal function-call operator.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   171
bool KilledBySignal::operator()(int exit_status) const {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   172
  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   173
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   174
# endif  // !GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   175
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   176
namespace internal {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   177
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   178
// Utilities needed for death tests.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   179
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   180
// Generates a textual description of a given exit code, in the format
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   181
// specified by wait(2).
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   182
static std::string ExitSummary(int exit_code) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   183
  Message m;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   184
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   185
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   186
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   187
  m << "Exited with exit status " << exit_code;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   188
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   189
# else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   190
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   191
  if (WIFEXITED(exit_code)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   192
    m << "Exited with exit status " << WEXITSTATUS(exit_code);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   193
  } else if (WIFSIGNALED(exit_code)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   194
    m << "Terminated by signal " << WTERMSIG(exit_code);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   195
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   196
#  ifdef WCOREDUMP
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   197
  if (WCOREDUMP(exit_code)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   198
    m << " (core dumped)";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   199
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   200
#  endif
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   201
# endif  // GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   202
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   203
  return m.GetString();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   204
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   205
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   206
// Returns true if exit_status describes a process that was terminated
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   207
// by a signal, or exited normally with a nonzero exit code.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   208
bool ExitedUnsuccessfully(int exit_status) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   209
  return !ExitedWithCode(0)(exit_status);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   210
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   211
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   212
# if !GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   213
// Generates a textual failure message when a death test finds more than
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   214
// one thread running, or cannot determine the number of threads, prior
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   215
// to executing the given statement.  It is the responsibility of the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   216
// caller not to pass a thread_count of 1.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   217
static std::string DeathTestThreadWarning(size_t thread_count) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   218
  Message msg;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   219
  msg << "Death tests use fork(), which is unsafe particularly"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   220
      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   221
  if (thread_count == 0)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   222
    msg << "couldn't detect the number of threads.";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   223
  else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   224
    msg << "detected " << thread_count << " threads.";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   225
  return msg.GetString();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   226
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   227
# endif  // !GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   228
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   229
// Flag characters for reporting a death test that did not die.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   230
static const char kDeathTestLived = 'L';
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   231
static const char kDeathTestReturned = 'R';
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   232
static const char kDeathTestThrew = 'T';
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   233
static const char kDeathTestInternalError = 'I';
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   234
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   235
// An enumeration describing all of the possible ways that a death test can
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   236
// conclude.  DIED means that the process died while executing the test
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   237
// code; LIVED means that process lived beyond the end of the test code;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   238
// RETURNED means that the test statement attempted to execute a return
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   239
// statement, which is not allowed; THREW means that the test statement
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   240
// returned control by throwing an exception.  IN_PROGRESS means the test
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   241
// has not yet concluded.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   242
// TODO(vladl@google.com): Unify names and possibly values for
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   243
// AbortReason, DeathTestOutcome, and flag characters above.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   244
enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   245
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   246
// Routine for aborting the program which is safe to call from an
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   247
// exec-style death test child process, in which case the error
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   248
// message is propagated back to the parent process.  Otherwise, the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   249
// message is simply printed to stderr.  In either case, the program
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   250
// then exits with status 1.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   251
void DeathTestAbort(const std::string& message) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   252
  // On a POSIX system, this function may be called from a threadsafe-style
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   253
  // death test child process, which operates on a very small stack.  Use
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   254
  // the heap for any additional non-minuscule memory requirements.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   255
  const InternalRunDeathTestFlag* const flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   256
      GetUnitTestImpl()->internal_run_death_test_flag();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   257
  if (flag != NULL) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   258
    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   259
    fputc(kDeathTestInternalError, parent);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   260
    fprintf(parent, "%s", message.c_str());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   261
    fflush(parent);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   262
    _exit(1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   263
  } else {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   264
    fprintf(stderr, "%s", message.c_str());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   265
    fflush(stderr);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   266
    posix::Abort();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   267
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   268
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   269
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   270
// A replacement for CHECK that calls DeathTestAbort if the assertion
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   271
// fails.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   272
# define GTEST_DEATH_TEST_CHECK_(expression) \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   273
  do { \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   274
    if (!::testing::internal::IsTrue(expression)) { \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   275
      DeathTestAbort( \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   276
          ::std::string("CHECK failed: File ") + __FILE__ +  ", line " \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   277
          + ::testing::internal::StreamableToString(__LINE__) + ": " \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   278
          + #expression); \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   279
    } \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   280
  } while (::testing::internal::AlwaysFalse())
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   281
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   282
// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   283
// evaluating any system call that fulfills two conditions: it must return
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   284
// -1 on failure, and set errno to EINTR when it is interrupted and
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   285
// should be tried again.  The macro expands to a loop that repeatedly
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   286
// evaluates the expression as long as it evaluates to -1 and sets
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   287
// errno to EINTR.  If the expression evaluates to -1 but errno is
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   288
// something other than EINTR, DeathTestAbort is called.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   289
# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   290
  do { \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   291
    int gtest_retval; \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   292
    do { \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   293
      gtest_retval = (expression); \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   294
    } while (gtest_retval == -1 && errno == EINTR); \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   295
    if (gtest_retval == -1) { \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   296
      DeathTestAbort( \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   297
          ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   298
          + ::testing::internal::StreamableToString(__LINE__) + ": " \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   299
          + #expression + " != -1"); \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   300
    } \
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   301
  } while (::testing::internal::AlwaysFalse())
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   302
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   303
// Returns the message describing the last system error in errno.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   304
std::string GetLastErrnoDescription() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   305
    return errno == 0 ? "" : posix::StrError(errno);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   306
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   307
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   308
// This is called from a death test parent process to read a failure
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   309
// message from the death test child process and log it with the FATAL
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   310
// severity. On Windows, the message is read from a pipe handle. On other
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   311
// platforms, it is read from a file descriptor.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   312
static void FailFromInternalError(int fd) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   313
  Message error;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   314
  char buffer[256];
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   315
  int num_read;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   316
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   317
  do {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   318
    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   319
      buffer[num_read] = '\0';
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   320
      error << buffer;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   321
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   322
  } while (num_read == -1 && errno == EINTR);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   323
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   324
  if (num_read == 0) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   325
    GTEST_LOG_(FATAL) << error.GetString();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   326
  } else {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   327
    const int last_error = errno;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   328
    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   329
                      << GetLastErrnoDescription() << " [" << last_error << "]";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   330
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   331
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   332
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   333
// Death test constructor.  Increments the running death test count
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   334
// for the current test.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   335
DeathTest::DeathTest() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   336
  TestInfo* const info = GetUnitTestImpl()->current_test_info();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   337
  if (info == NULL) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   338
    DeathTestAbort("Cannot run a death test outside of a TEST or "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   339
                   "TEST_F construct");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   340
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   341
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   342
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   343
// Creates and returns a death test by dispatching to the current
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   344
// death test factory.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   345
bool DeathTest::Create(const char* statement, const RE* regex,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   346
                       const char* file, int line, DeathTest** test) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   347
  return GetUnitTestImpl()->death_test_factory()->Create(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   348
      statement, regex, file, line, test);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   349
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   350
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   351
const char* DeathTest::LastMessage() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   352
  return last_death_test_message_.c_str();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   353
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   354
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   355
void DeathTest::set_last_death_test_message(const std::string& message) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   356
  last_death_test_message_ = message;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   357
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   358
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   359
std::string DeathTest::last_death_test_message_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   360
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   361
// Provides cross platform implementation for some death functionality.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   362
class DeathTestImpl : public DeathTest {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   363
 protected:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   364
  DeathTestImpl(const char* a_statement, const RE* a_regex)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   365
      : statement_(a_statement),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   366
        regex_(a_regex),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   367
        spawned_(false),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   368
        status_(-1),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   369
        outcome_(IN_PROGRESS),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   370
        read_fd_(-1),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   371
        write_fd_(-1) {}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   372
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   373
  // read_fd_ is expected to be closed and cleared by a derived class.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   374
  ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   375
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   376
  void Abort(AbortReason reason);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   377
  virtual bool Passed(bool status_ok);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   378
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   379
  const char* statement() const { return statement_; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   380
  const RE* regex() const { return regex_; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   381
  bool spawned() const { return spawned_; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   382
  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   383
  int status() const { return status_; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   384
  void set_status(int a_status) { status_ = a_status; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   385
  DeathTestOutcome outcome() const { return outcome_; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   386
  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   387
  int read_fd() const { return read_fd_; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   388
  void set_read_fd(int fd) { read_fd_ = fd; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   389
  int write_fd() const { return write_fd_; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   390
  void set_write_fd(int fd) { write_fd_ = fd; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   391
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   392
  // Called in the parent process only. Reads the result code of the death
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   393
  // test child process via a pipe, interprets it to set the outcome_
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   394
  // member, and closes read_fd_.  Outputs diagnostics and terminates in
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   395
  // case of unexpected codes.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   396
  void ReadAndInterpretStatusByte();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   397
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   398
 private:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   399
  // The textual content of the code this object is testing.  This class
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   400
  // doesn't own this string and should not attempt to delete it.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   401
  const char* const statement_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   402
  // The regular expression which test output must match.  DeathTestImpl
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   403
  // doesn't own this object and should not attempt to delete it.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   404
  const RE* const regex_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   405
  // True if the death test child process has been successfully spawned.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   406
  bool spawned_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   407
  // The exit status of the child process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   408
  int status_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   409
  // How the death test concluded.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   410
  DeathTestOutcome outcome_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   411
  // Descriptor to the read end of the pipe to the child process.  It is
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   412
  // always -1 in the child process.  The child keeps its write end of the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   413
  // pipe in write_fd_.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   414
  int read_fd_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   415
  // Descriptor to the child's write end of the pipe to the parent process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   416
  // It is always -1 in the parent process.  The parent keeps its end of the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   417
  // pipe in read_fd_.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   418
  int write_fd_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   419
};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   420
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   421
// Called in the parent process only. Reads the result code of the death
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   422
// test child process via a pipe, interprets it to set the outcome_
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   423
// member, and closes read_fd_.  Outputs diagnostics and terminates in
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   424
// case of unexpected codes.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   425
void DeathTestImpl::ReadAndInterpretStatusByte() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   426
  char flag;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   427
  int bytes_read;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   428
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   429
  // The read() here blocks until data is available (signifying the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   430
  // failure of the death test) or until the pipe is closed (signifying
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   431
  // its success), so it's okay to call this in the parent before
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   432
  // the child process has exited.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   433
  do {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   434
    bytes_read = posix::Read(read_fd(), &flag, 1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   435
  } while (bytes_read == -1 && errno == EINTR);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   436
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   437
  if (bytes_read == 0) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   438
    set_outcome(DIED);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   439
  } else if (bytes_read == 1) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   440
    switch (flag) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   441
      case kDeathTestReturned:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   442
        set_outcome(RETURNED);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   443
        break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   444
      case kDeathTestThrew:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   445
        set_outcome(THREW);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   446
        break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   447
      case kDeathTestLived:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   448
        set_outcome(LIVED);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   449
        break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   450
      case kDeathTestInternalError:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   451
        FailFromInternalError(read_fd());  // Does not return.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   452
        break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   453
      default:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   454
        GTEST_LOG_(FATAL) << "Death test child process reported "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   455
                          << "unexpected status byte ("
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   456
                          << static_cast<unsigned int>(flag) << ")";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   457
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   458
  } else {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   459
    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   460
                      << GetLastErrnoDescription();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   461
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   462
  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   463
  set_read_fd(-1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   464
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   465
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   466
// Signals that the death test code which should have exited, didn't.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   467
// Should be called only in a death test child process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   468
// Writes a status byte to the child's status file descriptor, then
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   469
// calls _exit(1).
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   470
void DeathTestImpl::Abort(AbortReason reason) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   471
  // The parent process considers the death test to be a failure if
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   472
  // it finds any data in our pipe.  So, here we write a single flag byte
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   473
  // to the pipe, then exit.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   474
  const char status_ch =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   475
      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   476
      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   477
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   478
  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   479
  // We are leaking the descriptor here because on some platforms (i.e.,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   480
  // when built as Windows DLL), destructors of global objects will still
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   481
  // run after calling _exit(). On such systems, write_fd_ will be
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   482
  // indirectly closed from the destructor of UnitTestImpl, causing double
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   483
  // close if it is also closed here. On debug configurations, double close
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   484
  // may assert. As there are no in-process buffers to flush here, we are
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   485
  // relying on the OS to close the descriptor after the process terminates
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   486
  // when the destructors are not run.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   487
  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   488
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   489
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   490
// Returns an indented copy of stderr output for a death test.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   491
// This makes distinguishing death test output lines from regular log lines
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   492
// much easier.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   493
static ::std::string FormatDeathTestOutput(const ::std::string& output) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   494
  ::std::string ret;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   495
  for (size_t at = 0; ; ) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   496
    const size_t line_end = output.find('\n', at);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   497
    ret += "[  DEATH   ] ";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   498
    if (line_end == ::std::string::npos) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   499
      ret += output.substr(at);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   500
      break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   501
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   502
    ret += output.substr(at, line_end + 1 - at);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   503
    at = line_end + 1;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   504
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   505
  return ret;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   506
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   507
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   508
// Assesses the success or failure of a death test, using both private
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   509
// members which have previously been set, and one argument:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   510
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   511
// Private data members:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   512
//   outcome:  An enumeration describing how the death test
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   513
//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   514
//             fails in the latter three cases.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   515
//   status:   The exit status of the child process. On *nix, it is in the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   516
//             in the format specified by wait(2). On Windows, this is the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   517
//             value supplied to the ExitProcess() API or a numeric code
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   518
//             of the exception that terminated the program.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   519
//   regex:    A regular expression object to be applied to
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   520
//             the test's captured standard error output; the death test
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   521
//             fails if it does not match.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   522
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   523
// Argument:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   524
//   status_ok: true if exit_status is acceptable in the context of
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   525
//              this particular death test, which fails if it is false
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   526
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   527
// Returns true iff all of the above conditions are met.  Otherwise, the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   528
// first failing condition, in the order given above, is the one that is
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   529
// reported. Also sets the last death test message string.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   530
bool DeathTestImpl::Passed(bool status_ok) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   531
  if (!spawned())
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   532
    return false;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   533
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   534
  const std::string error_message = GetCapturedStderr();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   535
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   536
  bool success = false;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   537
  Message buffer;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   538
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   539
  buffer << "Death test: " << statement() << "\n";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   540
  switch (outcome()) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   541
    case LIVED:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   542
      buffer << "    Result: failed to die.\n"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   543
             << " Error msg:\n" << FormatDeathTestOutput(error_message);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   544
      break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   545
    case THREW:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   546
      buffer << "    Result: threw an exception.\n"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   547
             << " Error msg:\n" << FormatDeathTestOutput(error_message);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   548
      break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   549
    case RETURNED:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   550
      buffer << "    Result: illegal return in test statement.\n"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   551
             << " Error msg:\n" << FormatDeathTestOutput(error_message);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   552
      break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   553
    case DIED:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   554
      if (status_ok) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   555
        const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   556
        if (matched) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   557
          success = true;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   558
        } else {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   559
          buffer << "    Result: died but not with expected error.\n"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   560
                 << "  Expected: " << regex()->pattern() << "\n"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   561
                 << "Actual msg:\n" << FormatDeathTestOutput(error_message);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   562
        }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   563
      } else {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   564
        buffer << "    Result: died but not with expected exit code:\n"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   565
               << "            " << ExitSummary(status()) << "\n"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   566
               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   567
      }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   568
      break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   569
    case IN_PROGRESS:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   570
    default:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   571
      GTEST_LOG_(FATAL)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   572
          << "DeathTest::Passed somehow called before conclusion of test";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   573
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   574
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   575
  DeathTest::set_last_death_test_message(buffer.GetString());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   576
  return success;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   577
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   578
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   579
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   580
// WindowsDeathTest implements death tests on Windows. Due to the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   581
// specifics of starting new processes on Windows, death tests there are
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   582
// always threadsafe, and Google Test considers the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   583
// --gtest_death_test_style=fast setting to be equivalent to
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   584
// --gtest_death_test_style=threadsafe there.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   585
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   586
// A few implementation notes:  Like the Linux version, the Windows
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   587
// implementation uses pipes for child-to-parent communication. But due to
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   588
// the specifics of pipes on Windows, some extra steps are required:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   589
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   590
// 1. The parent creates a communication pipe and stores handles to both
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   591
//    ends of it.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   592
// 2. The parent starts the child and provides it with the information
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   593
//    necessary to acquire the handle to the write end of the pipe.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   594
// 3. The child acquires the write end of the pipe and signals the parent
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   595
//    using a Windows event.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   596
// 4. Now the parent can release the write end of the pipe on its side. If
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   597
//    this is done before step 3, the object's reference count goes down to
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   598
//    0 and it is destroyed, preventing the child from acquiring it. The
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   599
//    parent now has to release it, or read operations on the read end of
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   600
//    the pipe will not return when the child terminates.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   601
// 5. The parent reads child's output through the pipe (outcome code and
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   602
//    any possible error messages) from the pipe, and its stderr and then
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   603
//    determines whether to fail the test.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   604
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   605
// Note: to distinguish Win32 API calls from the local method and function
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   606
// calls, the former are explicitly resolved in the global namespace.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   607
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   608
class WindowsDeathTest : public DeathTestImpl {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   609
 public:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   610
  WindowsDeathTest(const char* a_statement,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   611
                   const RE* a_regex,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   612
                   const char* file,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   613
                   int line)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   614
      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   615
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   616
  // All of these virtual functions are inherited from DeathTest.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   617
  virtual int Wait();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   618
  virtual TestRole AssumeRole();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   619
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   620
 private:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   621
  // The name of the file in which the death test is located.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   622
  const char* const file_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   623
  // The line number on which the death test is located.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   624
  const int line_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   625
  // Handle to the write end of the pipe to the child process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   626
  AutoHandle write_handle_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   627
  // Child process handle.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   628
  AutoHandle child_handle_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   629
  // Event the child process uses to signal the parent that it has
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   630
  // acquired the handle to the write end of the pipe. After seeing this
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   631
  // event the parent can release its own handles to make sure its
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   632
  // ReadFile() calls return when the child terminates.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   633
  AutoHandle event_handle_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   634
};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   635
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   636
// Waits for the child in a death test to exit, returning its exit
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   637
// status, or 0 if no child process exists.  As a side effect, sets the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   638
// outcome data member.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   639
int WindowsDeathTest::Wait() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   640
  if (!spawned())
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   641
    return 0;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   642
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   643
  // Wait until the child either signals that it has acquired the write end
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   644
  // of the pipe or it dies.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   645
  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   646
  switch (::WaitForMultipleObjects(2,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   647
                                   wait_handles,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   648
                                   FALSE,  // Waits for any of the handles.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   649
                                   INFINITE)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   650
    case WAIT_OBJECT_0:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   651
    case WAIT_OBJECT_0 + 1:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   652
      break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   653
    default:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   654
      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   655
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   656
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   657
  // The child has acquired the write end of the pipe or exited.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   658
  // We release the handle on our side and continue.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   659
  write_handle_.Reset();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   660
  event_handle_.Reset();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   661
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   662
  ReadAndInterpretStatusByte();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   663
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   664
  // Waits for the child process to exit if it haven't already. This
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   665
  // returns immediately if the child has already exited, regardless of
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   666
  // whether previous calls to WaitForMultipleObjects synchronized on this
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   667
  // handle or not.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   668
  GTEST_DEATH_TEST_CHECK_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   669
      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   670
                                             INFINITE));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   671
  DWORD status_code;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   672
  GTEST_DEATH_TEST_CHECK_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   673
      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   674
  child_handle_.Reset();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   675
  set_status(static_cast<int>(status_code));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   676
  return status();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   677
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   678
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   679
// The AssumeRole process for a Windows death test.  It creates a child
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   680
// process with the same executable as the current process to run the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   681
// death test.  The child process is given the --gtest_filter and
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   682
// --gtest_internal_run_death_test flags such that it knows to run the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   683
// current death test only.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   684
DeathTest::TestRole WindowsDeathTest::AssumeRole() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   685
  const UnitTestImpl* const impl = GetUnitTestImpl();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   686
  const InternalRunDeathTestFlag* const flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   687
      impl->internal_run_death_test_flag();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   688
  const TestInfo* const info = impl->current_test_info();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   689
  const int death_test_index = info->result()->death_test_count();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   690
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   691
  if (flag != NULL) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   692
    // ParseInternalRunDeathTestFlag() has performed all the necessary
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   693
    // processing.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   694
    set_write_fd(flag->write_fd());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   695
    return EXECUTE_TEST;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   696
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   697
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   698
  // WindowsDeathTest uses an anonymous pipe to communicate results of
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   699
  // a death test.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   700
  SECURITY_ATTRIBUTES handles_are_inheritable = {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   701
    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   702
  HANDLE read_handle, write_handle;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   703
  GTEST_DEATH_TEST_CHECK_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   704
      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   705
                   0)  // Default buffer size.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   706
      != FALSE);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   707
  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   708
                                O_RDONLY));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   709
  write_handle_.Reset(write_handle);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   710
  event_handle_.Reset(::CreateEvent(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   711
      &handles_are_inheritable,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   712
      TRUE,    // The event will automatically reset to non-signaled state.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   713
      FALSE,   // The initial state is non-signalled.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   714
      NULL));  // The even is unnamed.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   715
  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   716
  const std::string filter_flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   717
      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   718
      info->test_case_name() + "." + info->name();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   719
  const std::string internal_flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   720
      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   721
      "=" + file_ + "|" + StreamableToString(line_) + "|" +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   722
      StreamableToString(death_test_index) + "|" +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   723
      StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   724
      // size_t has the same width as pointers on both 32-bit and 64-bit
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   725
      // Windows platforms.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   726
      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   727
      "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   728
      "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   729
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   730
  char executable_path[_MAX_PATH + 1];  // NOLINT
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   731
  GTEST_DEATH_TEST_CHECK_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   732
      _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   733
                                            executable_path,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   734
                                            _MAX_PATH));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   735
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   736
  std::string command_line =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   737
      std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   738
      internal_flag + "\"";
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   739
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   740
  DeathTest::set_last_death_test_message("");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   741
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   742
  CaptureStderr();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   743
  // Flush the log buffers since the log streams are shared with the child.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   744
  FlushInfoLog();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   745
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   746
  // The child process will share the standard handles with the parent.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   747
  STARTUPINFOA startup_info;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   748
  memset(&startup_info, 0, sizeof(STARTUPINFO));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   749
  startup_info.dwFlags = STARTF_USESTDHANDLES;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   750
  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   751
  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   752
  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   753
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   754
  PROCESS_INFORMATION process_info;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   755
  GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   756
      executable_path,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   757
      const_cast<char*>(command_line.c_str()),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   758
      NULL,   // Retuned process handle is not inheritable.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   759
      NULL,   // Retuned thread handle is not inheritable.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   760
      TRUE,   // Child inherits all inheritable handles (for write_handle_).
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   761
      0x0,    // Default creation flags.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   762
      NULL,   // Inherit the parent's environment.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   763
      UnitTest::GetInstance()->original_working_dir(),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   764
      &startup_info,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   765
      &process_info) != FALSE);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   766
  child_handle_.Reset(process_info.hProcess);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   767
  ::CloseHandle(process_info.hThread);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   768
  set_spawned(true);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   769
  return OVERSEE_TEST;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   770
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   771
# else  // We are not on Windows.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   772
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   773
// ForkingDeathTest provides implementations for most of the abstract
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   774
// methods of the DeathTest interface.  Only the AssumeRole method is
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   775
// left undefined.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   776
class ForkingDeathTest : public DeathTestImpl {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   777
 public:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   778
  ForkingDeathTest(const char* statement, const RE* regex);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   779
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   780
  // All of these virtual functions are inherited from DeathTest.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   781
  virtual int Wait();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   782
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   783
 protected:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   784
  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   785
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   786
 private:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   787
  // PID of child process during death test; 0 in the child process itself.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   788
  pid_t child_pid_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   789
};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   790
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   791
// Constructs a ForkingDeathTest.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   792
ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   793
    : DeathTestImpl(a_statement, a_regex),
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   794
      child_pid_(-1) {}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   795
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   796
// Waits for the child in a death test to exit, returning its exit
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   797
// status, or 0 if no child process exists.  As a side effect, sets the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   798
// outcome data member.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   799
int ForkingDeathTest::Wait() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   800
  if (!spawned())
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   801
    return 0;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   802
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   803
  ReadAndInterpretStatusByte();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   804
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   805
  int status_value;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   806
  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   807
  set_status(status_value);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   808
  return status_value;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   809
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   810
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   811
// A concrete death test class that forks, then immediately runs the test
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   812
// in the child process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   813
class NoExecDeathTest : public ForkingDeathTest {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   814
 public:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   815
  NoExecDeathTest(const char* a_statement, const RE* a_regex) :
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   816
      ForkingDeathTest(a_statement, a_regex) { }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   817
  virtual TestRole AssumeRole();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   818
};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   819
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   820
// The AssumeRole process for a fork-and-run death test.  It implements a
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   821
// straightforward fork, with a simple pipe to transmit the status byte.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   822
DeathTest::TestRole NoExecDeathTest::AssumeRole() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   823
  const size_t thread_count = GetThreadCount();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   824
  if (thread_count != 1) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   825
    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   826
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   827
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   828
  int pipe_fd[2];
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   829
  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   830
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   831
  DeathTest::set_last_death_test_message("");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   832
  CaptureStderr();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   833
  // When we fork the process below, the log file buffers are copied, but the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   834
  // file descriptors are shared.  We flush all log files here so that closing
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   835
  // the file descriptors in the child process doesn't throw off the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   836
  // synchronization between descriptors and buffers in the parent process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   837
  // This is as close to the fork as possible to avoid a race condition in case
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   838
  // there are multiple threads running before the death test, and another
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   839
  // thread writes to the log file.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   840
  FlushInfoLog();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   841
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   842
  const pid_t child_pid = fork();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   843
  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   844
  set_child_pid(child_pid);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   845
  if (child_pid == 0) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   846
    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   847
    set_write_fd(pipe_fd[1]);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   848
    // Redirects all logging to stderr in the child process to prevent
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   849
    // concurrent writes to the log files.  We capture stderr in the parent
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   850
    // process and append the child process' output to a log.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   851
    LogToStderr();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   852
    // Event forwarding to the listeners of event listener API mush be shut
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   853
    // down in death test subprocesses.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   854
    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   855
    g_in_fast_death_test_child = true;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   856
    return EXECUTE_TEST;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   857
  } else {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   858
    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   859
    set_read_fd(pipe_fd[0]);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   860
    set_spawned(true);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   861
    return OVERSEE_TEST;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   862
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   863
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   864
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   865
// A concrete death test class that forks and re-executes the main
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   866
// program from the beginning, with command-line flags set that cause
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   867
// only this specific death test to be run.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   868
class ExecDeathTest : public ForkingDeathTest {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   869
 public:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   870
  ExecDeathTest(const char* a_statement, const RE* a_regex,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   871
                const char* file, int line) :
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   872
      ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   873
  virtual TestRole AssumeRole();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   874
 private:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   875
  static ::std::vector<testing::internal::string>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   876
  GetArgvsForDeathTestChildProcess() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   877
    ::std::vector<testing::internal::string> args = GetInjectableArgvs();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   878
    return args;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   879
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   880
  // The name of the file in which the death test is located.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   881
  const char* const file_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   882
  // The line number on which the death test is located.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   883
  const int line_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   884
};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   885
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   886
// Utility class for accumulating command-line arguments.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   887
class Arguments {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   888
 public:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   889
  Arguments() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   890
    args_.push_back(NULL);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   891
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   892
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   893
  ~Arguments() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   894
    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   895
         ++i) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   896
      free(*i);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   897
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   898
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   899
  void AddArgument(const char* argument) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   900
    args_.insert(args_.end() - 1, posix::StrDup(argument));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   901
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   902
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   903
  template <typename Str>
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   904
  void AddArguments(const ::std::vector<Str>& arguments) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   905
    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   906
         i != arguments.end();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   907
         ++i) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   908
      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   909
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   910
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   911
  char* const* Argv() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   912
    return &args_[0];
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   913
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   914
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   915
 private:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   916
  std::vector<char*> args_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   917
};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   918
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   919
// A struct that encompasses the arguments to the child process of a
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   920
// threadsafe-style death test process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   921
struct ExecDeathTestArgs {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   922
  char* const* argv;  // Command-line arguments for the child's call to exec
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   923
  int close_fd;       // File descriptor to close; the read end of a pipe
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   924
};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   925
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   926
#  if GTEST_OS_MAC
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   927
inline char** GetEnviron() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   928
  // When Google Test is built as a framework on MacOS X, the environ variable
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   929
  // is unavailable. Apple's documentation (man environ) recommends using
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   930
  // _NSGetEnviron() instead.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   931
  return *_NSGetEnviron();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   932
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   933
#  else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   934
// Some POSIX platforms expect you to declare environ. extern "C" makes
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   935
// it reside in the global namespace.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   936
extern "C" char** environ;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   937
inline char** GetEnviron() { return environ; }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   938
#  endif  // GTEST_OS_MAC
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   939
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   940
#  if !GTEST_OS_QNX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   941
// The main function for a threadsafe-style death test child process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   942
// This function is called in a clone()-ed process and thus must avoid
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   943
// any potentially unsafe operations like malloc or libc functions.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   944
static int ExecDeathTestChildMain(void* child_arg) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   945
  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   946
  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   947
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   948
  // We need to execute the test program in the same environment where
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   949
  // it was originally invoked.  Therefore we change to the original
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   950
  // working directory first.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   951
  const char* const original_dir =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   952
      UnitTest::GetInstance()->original_working_dir();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   953
  // We can safely call chdir() as it's a direct system call.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   954
  if (chdir(original_dir) != 0) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   955
    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   956
                   GetLastErrnoDescription());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   957
    return EXIT_FAILURE;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   958
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   959
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   960
  // We can safely call execve() as it's a direct system call.  We
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   961
  // cannot use execvp() as it's a libc function and thus potentially
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   962
  // unsafe.  Since execve() doesn't search the PATH, the user must
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   963
  // invoke the test program via a valid path that contains at least
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   964
  // one path separator.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   965
  execve(args->argv[0], args->argv, GetEnviron());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   966
  DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   967
                 original_dir + " failed: " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   968
                 GetLastErrnoDescription());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   969
  return EXIT_FAILURE;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   970
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   971
#  endif  // !GTEST_OS_QNX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   972
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   973
// Two utility routines that together determine the direction the stack
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   974
// grows.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   975
// This could be accomplished more elegantly by a single recursive
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   976
// function, but we want to guard against the unlikely possibility of
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   977
// a smart compiler optimizing the recursion away.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   978
//
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   979
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   980
// StackLowerThanAddress into StackGrowsDown, which then doesn't give
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   981
// correct answer.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   982
void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   983
void StackLowerThanAddress(const void* ptr, bool* result) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   984
  int dummy;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   985
  *result = (&dummy < ptr);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   986
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   987
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   988
bool StackGrowsDown() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   989
  int dummy;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   990
  bool result;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   991
  StackLowerThanAddress(&dummy, &result);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   992
  return result;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   993
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   994
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   995
// Spawns a child process with the same executable as the current process in
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   996
// a thread-safe manner and instructs it to run the death test.  The
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   997
// implementation uses fork(2) + exec.  On systems where clone(2) is
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   998
// available, it is used instead, being slightly more thread-safe.  On QNX,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
   999
// fork supports only single-threaded environments, so this function uses
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1000
// spawn(2) there instead.  The function dies with an error message if
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1001
// anything goes wrong.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1002
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1003
  ExecDeathTestArgs args = { argv, close_fd };
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1004
  pid_t child_pid = -1;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1005
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1006
#  if GTEST_OS_QNX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1007
  // Obtains the current directory and sets it to be closed in the child
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1008
  // process.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1009
  const int cwd_fd = open(".", O_RDONLY);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1010
  GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1011
  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1012
  // We need to execute the test program in the same environment where
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1013
  // it was originally invoked.  Therefore we change to the original
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1014
  // working directory first.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1015
  const char* const original_dir =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1016
      UnitTest::GetInstance()->original_working_dir();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1017
  // We can safely call chdir() as it's a direct system call.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1018
  if (chdir(original_dir) != 0) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1019
    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1020
                   GetLastErrnoDescription());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1021
    return EXIT_FAILURE;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1022
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1023
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1024
  int fd_flags;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1025
  // Set close_fd to be closed after spawn.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1026
  GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1027
  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1028
                                        fd_flags | FD_CLOEXEC));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1029
  struct inheritance inherit = {0};
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1030
  // spawn is a system call.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1031
  child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1032
  // Restores the current working directory.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1033
  GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1034
  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1035
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1036
#  else   // GTEST_OS_QNX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1037
#   if GTEST_OS_LINUX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1038
  // When a SIGPROF signal is received while fork() or clone() are executing,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1039
  // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1040
  // it after the call to fork()/clone() is complete.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1041
  struct sigaction saved_sigprof_action;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1042
  struct sigaction ignore_sigprof_action;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1043
  memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1044
  sigemptyset(&ignore_sigprof_action.sa_mask);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1045
  ignore_sigprof_action.sa_handler = SIG_IGN;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1046
  GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1047
      SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1048
#   endif  // GTEST_OS_LINUX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1049
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1050
#   if GTEST_HAS_CLONE
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1051
  const bool use_fork = GTEST_FLAG(death_test_use_fork);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1052
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1053
  if (!use_fork) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1054
    static const bool stack_grows_down = StackGrowsDown();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1055
    const size_t stack_size = getpagesize();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1056
    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1057
    void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1058
                             MAP_ANON | MAP_PRIVATE, -1, 0);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1059
    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1060
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1061
    // Maximum stack alignment in bytes:  For a downward-growing stack, this
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1062
    // amount is subtracted from size of the stack space to get an address
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1063
    // that is within the stack space and is aligned on all systems we care
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1064
    // about.  As far as I know there is no ABI with stack alignment greater
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1065
    // than 64.  We assume stack and stack_size already have alignment of
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1066
    // kMaxStackAlignment.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1067
    const size_t kMaxStackAlignment = 64;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1068
    void* const stack_top =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1069
        static_cast<char*>(stack) +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1070
            (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1071
    GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment &&
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1072
        reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1073
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1074
    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1075
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1076
    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1077
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1078
#   else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1079
  const bool use_fork = true;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1080
#   endif  // GTEST_HAS_CLONE
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1081
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1082
  if (use_fork && (child_pid = fork()) == 0) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1083
      ExecDeathTestChildMain(&args);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1084
      _exit(0);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1085
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1086
#  endif  // GTEST_OS_QNX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1087
#  if GTEST_OS_LINUX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1088
  GTEST_DEATH_TEST_CHECK_SYSCALL_(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1089
      sigaction(SIGPROF, &saved_sigprof_action, NULL));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1090
#  endif  // GTEST_OS_LINUX
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1091
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1092
  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1093
  return child_pid;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1094
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1095
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1096
// The AssumeRole process for a fork-and-exec death test.  It re-executes the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1097
// main program from the beginning, setting the --gtest_filter
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1098
// and --gtest_internal_run_death_test flags to cause only the current
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1099
// death test to be re-run.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1100
DeathTest::TestRole ExecDeathTest::AssumeRole() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1101
  const UnitTestImpl* const impl = GetUnitTestImpl();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1102
  const InternalRunDeathTestFlag* const flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1103
      impl->internal_run_death_test_flag();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1104
  const TestInfo* const info = impl->current_test_info();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1105
  const int death_test_index = info->result()->death_test_count();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1106
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1107
  if (flag != NULL) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1108
    set_write_fd(flag->write_fd());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1109
    return EXECUTE_TEST;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1110
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1111
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1112
  int pipe_fd[2];
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1113
  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1114
  // Clear the close-on-exec flag on the write end of the pipe, lest
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1115
  // it be closed when the child process does an exec:
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1116
  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1117
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1118
  const std::string filter_flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1119
      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1120
      + info->test_case_name() + "." + info->name();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1121
  const std::string internal_flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1122
      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1123
      + file_ + "|" + StreamableToString(line_) + "|"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1124
      + StreamableToString(death_test_index) + "|"
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1125
      + StreamableToString(pipe_fd[1]);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1126
  Arguments args;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1127
  args.AddArguments(GetArgvsForDeathTestChildProcess());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1128
  args.AddArgument(filter_flag.c_str());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1129
  args.AddArgument(internal_flag.c_str());
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1130
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1131
  DeathTest::set_last_death_test_message("");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1132
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1133
  CaptureStderr();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1134
  // See the comment in NoExecDeathTest::AssumeRole for why the next line
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1135
  // is necessary.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1136
  FlushInfoLog();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1137
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1138
  const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1139
  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1140
  set_child_pid(child_pid);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1141
  set_read_fd(pipe_fd[0]);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1142
  set_spawned(true);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1143
  return OVERSEE_TEST;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1144
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1145
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1146
# endif  // !GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1147
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1148
// Creates a concrete DeathTest-derived class that depends on the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1149
// --gtest_death_test_style flag, and sets the pointer pointed to
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1150
// by the "test" argument to its address.  If the test should be
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1151
// skipped, sets that pointer to NULL.  Returns true, unless the
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1152
// flag is set to an invalid value.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1153
bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1154
                                     const char* file, int line,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1155
                                     DeathTest** test) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1156
  UnitTestImpl* const impl = GetUnitTestImpl();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1157
  const InternalRunDeathTestFlag* const flag =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1158
      impl->internal_run_death_test_flag();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1159
  const int death_test_index = impl->current_test_info()
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1160
      ->increment_death_test_count();
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1161
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1162
  if (flag != NULL) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1163
    if (death_test_index > flag->index()) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1164
      DeathTest::set_last_death_test_message(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1165
          "Death test count (" + StreamableToString(death_test_index)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1166
          + ") somehow exceeded expected maximum ("
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1167
          + StreamableToString(flag->index()) + ")");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1168
      return false;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1169
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1170
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1171
    if (!(flag->file() == file && flag->line() == line &&
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1172
          flag->index() == death_test_index)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1173
      *test = NULL;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1174
      return true;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1175
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1176
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1177
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1178
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1179
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1180
  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1181
      GTEST_FLAG(death_test_style) == "fast") {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1182
    *test = new WindowsDeathTest(statement, regex, file, line);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1183
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1184
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1185
# else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1186
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1187
  if (GTEST_FLAG(death_test_style) == "threadsafe") {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1188
    *test = new ExecDeathTest(statement, regex, file, line);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1189
  } else if (GTEST_FLAG(death_test_style) == "fast") {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1190
    *test = new NoExecDeathTest(statement, regex);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1191
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1192
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1193
# endif  // GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1194
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1195
  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1196
    DeathTest::set_last_death_test_message(
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1197
        "Unknown death test style \"" + GTEST_FLAG(death_test_style)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1198
        + "\" encountered");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1199
    return false;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1200
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1201
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1202
  return true;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1203
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1204
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1205
// Splits a given string on a given delimiter, populating a given
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1206
// vector with the fields.  GTEST_HAS_DEATH_TEST implies that we have
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1207
// ::std::string, so we can use it here.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1208
static void SplitString(const ::std::string& str, char delimiter,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1209
                        ::std::vector< ::std::string>* dest) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1210
  ::std::vector< ::std::string> parsed;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1211
  ::std::string::size_type pos = 0;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1212
  while (::testing::internal::AlwaysTrue()) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1213
    const ::std::string::size_type colon = str.find(delimiter, pos);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1214
    if (colon == ::std::string::npos) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1215
      parsed.push_back(str.substr(pos));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1216
      break;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1217
    } else {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1218
      parsed.push_back(str.substr(pos, colon - pos));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1219
      pos = colon + 1;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1220
    }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1221
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1222
  dest->swap(parsed);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1223
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1224
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1225
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1226
// Recreates the pipe and event handles from the provided parameters,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1227
// signals the event, and returns a file descriptor wrapped around the pipe
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1228
// handle. This function is called in the child process only.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1229
int GetStatusFileDescriptor(unsigned int parent_process_id,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1230
                            size_t write_handle_as_size_t,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1231
                            size_t event_handle_as_size_t) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1232
  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1233
                                                   FALSE,  // Non-inheritable.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1234
                                                   parent_process_id));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1235
  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1236
    DeathTestAbort("Unable to open parent process " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1237
                   StreamableToString(parent_process_id));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1238
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1239
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1240
  // TODO(vladl@google.com): Replace the following check with a
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1241
  // compile-time assertion when available.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1242
  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1243
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1244
  const HANDLE write_handle =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1245
      reinterpret_cast<HANDLE>(write_handle_as_size_t);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1246
  HANDLE dup_write_handle;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1247
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1248
  // The newly initialized handle is accessible only in in the parent
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1249
  // process. To obtain one accessible within the child, we need to use
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1250
  // DuplicateHandle.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1251
  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1252
                         ::GetCurrentProcess(), &dup_write_handle,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1253
                         0x0,    // Requested privileges ignored since
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1254
                                 // DUPLICATE_SAME_ACCESS is used.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1255
                         FALSE,  // Request non-inheritable handler.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1256
                         DUPLICATE_SAME_ACCESS)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1257
    DeathTestAbort("Unable to duplicate the pipe handle " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1258
                   StreamableToString(write_handle_as_size_t) +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1259
                   " from the parent process " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1260
                   StreamableToString(parent_process_id));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1261
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1262
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1263
  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1264
  HANDLE dup_event_handle;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1265
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1266
  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1267
                         ::GetCurrentProcess(), &dup_event_handle,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1268
                         0x0,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1269
                         FALSE,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1270
                         DUPLICATE_SAME_ACCESS)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1271
    DeathTestAbort("Unable to duplicate the event handle " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1272
                   StreamableToString(event_handle_as_size_t) +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1273
                   " from the parent process " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1274
                   StreamableToString(parent_process_id));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1275
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1276
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1277
  const int write_fd =
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1278
      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1279
  if (write_fd == -1) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1280
    DeathTestAbort("Unable to convert pipe handle " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1281
                   StreamableToString(write_handle_as_size_t) +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1282
                   " to a file descriptor");
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1283
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1284
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1285
  // Signals the parent that the write end of the pipe has been acquired
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1286
  // so the parent can release its own write end.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1287
  ::SetEvent(dup_event_handle);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1288
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1289
  return write_fd;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1290
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1291
# endif  // GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1292
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1293
// Returns a newly created InternalRunDeathTestFlag object with fields
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1294
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1295
// the flag is specified; otherwise returns NULL.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1296
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1297
  if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1298
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1299
  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1300
  // can use it here.
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1301
  int line = -1;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1302
  int index = -1;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1303
  ::std::vector< ::std::string> fields;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1304
  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1305
  int write_fd = -1;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1306
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1307
# if GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1308
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1309
  unsigned int parent_process_id = 0;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1310
  size_t write_handle_as_size_t = 0;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1311
  size_t event_handle_as_size_t = 0;
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1312
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1313
  if (fields.size() != 6
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1314
      || !ParseNaturalNumber(fields[1], &line)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1315
      || !ParseNaturalNumber(fields[2], &index)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1316
      || !ParseNaturalNumber(fields[3], &parent_process_id)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1317
      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1318
      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1319
    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1320
                   GTEST_FLAG(internal_run_death_test));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1321
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1322
  write_fd = GetStatusFileDescriptor(parent_process_id,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1323
                                     write_handle_as_size_t,
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1324
                                     event_handle_as_size_t);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1325
# else
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1326
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1327
  if (fields.size() != 4
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1328
      || !ParseNaturalNumber(fields[1], &line)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1329
      || !ParseNaturalNumber(fields[2], &index)
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1330
      || !ParseNaturalNumber(fields[3], &write_fd)) {
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1331
    DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1332
        + GTEST_FLAG(internal_run_death_test));
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1333
  }
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1334
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1335
# endif  // GTEST_OS_WINDOWS
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1336
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1337
  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1338
}
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1339
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1340
}  // namespace internal
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1341
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1342
#endif  // GTEST_HAS_DEATH_TEST
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1343
8dd54c3bf02a 8148244: Finalize and integrate GTest implementation
iignatyev
parents:
diff changeset
  1344
}  // namespace testing