merged the trunk r8735:8766, r8769, r8777:8780, r8790 and r8800:8811
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -96,13 +96,13 @@ def query_yes_no(stdout, question, default="yes"):
|
||||
else:
|
||||
stdout.write("Please respond with 'yes' or 'no' "\
|
||||
"(or 'y' or 'n').\n")
|
||||
|
||||
|
||||
def getRunningProcessExePathByName_win32(name):
|
||||
from ctypes import windll, POINTER, pointer, Structure, sizeof
|
||||
from ctypes import c_long , c_int , c_uint , c_char , c_ubyte , c_char_p , c_void_p
|
||||
|
||||
|
||||
class PROCESSENTRY32(Structure):
|
||||
_fields_ = [ ( 'dwSize' , c_uint ) ,
|
||||
_fields_ = [ ( 'dwSize' , c_uint ) ,
|
||||
( 'cntUsage' , c_uint) ,
|
||||
( 'th32ProcessID' , c_uint) ,
|
||||
( 'th32DefaultHeapID' , c_uint) ,
|
||||
@@ -111,25 +111,25 @@ def getRunningProcessExePathByName_win32(name):
|
||||
( 'th32ParentProcessID' , c_uint) ,
|
||||
( 'pcPriClassBase' , c_long) ,
|
||||
( 'dwFlags' , c_uint) ,
|
||||
( 'szExeFile' , c_char * 260 ) ,
|
||||
( 'szExeFile' , c_char * 260 ) ,
|
||||
( 'th32MemoryBase' , c_long) ,
|
||||
( 'th32AccessKey' , c_long ) ]
|
||||
|
||||
|
||||
class MODULEENTRY32(Structure):
|
||||
_fields_ = [ ( 'dwSize' , c_long ) ,
|
||||
_fields_ = [ ( 'dwSize' , c_long ) ,
|
||||
( 'th32ModuleID' , c_long ),
|
||||
( 'th32ProcessID' , c_long ),
|
||||
( 'GlblcntUsage' , c_long ),
|
||||
( 'ProccntUsage' , c_long ) ,
|
||||
( 'modBaseAddr' , c_long ) ,
|
||||
( 'modBaseSize' , c_long ) ,
|
||||
( 'modBaseSize' , c_long ) ,
|
||||
( 'hModule' , c_void_p ) ,
|
||||
( 'szModule' , c_char * 256 ),
|
||||
( 'szExePath' , c_char * 260 ) ]
|
||||
|
||||
|
||||
TH32CS_SNAPPROCESS = 2
|
||||
TH32CS_SNAPMODULE = 0x00000008
|
||||
|
||||
|
||||
## CreateToolhelp32Snapshot
|
||||
CreateToolhelp32Snapshot= windll.kernel32.CreateToolhelp32Snapshot
|
||||
CreateToolhelp32Snapshot.reltype = c_long
|
||||
@@ -150,7 +150,7 @@ def getRunningProcessExePathByName_win32(name):
|
||||
Module32First = windll.kernel32.Module32First
|
||||
Module32First.argtypes = [ c_void_p , POINTER(MODULEENTRY32) ]
|
||||
Module32First.rettype = c_int
|
||||
|
||||
|
||||
hProcessSnap = c_void_p(0)
|
||||
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 )
|
||||
|
||||
@@ -180,7 +180,7 @@ def getRunningProcessExePathByName_posix(name):
|
||||
for pid in pids:
|
||||
try:
|
||||
path = os.readlink(os.path.join('/proc', pid, 'exe'))
|
||||
if path and path.endswith(name):
|
||||
if path and path.endswith(name):
|
||||
return path
|
||||
except:
|
||||
pass
|
||||
@@ -195,7 +195,7 @@ def getRunningProcessExePathByName(name):
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
class RunInfo(object):
|
||||
def setCallback(self, name, callback):
|
||||
setattr(self, name, callback)
|
||||
@@ -224,7 +224,7 @@ class RunInfo(object):
|
||||
except:
|
||||
pass
|
||||
cachefile.close()
|
||||
|
||||
|
||||
# fix empty tests dir
|
||||
if not self.tests_dir:
|
||||
self.tests_dir = self.path
|
||||
@@ -236,12 +236,12 @@ class RunInfo(object):
|
||||
else:
|
||||
self.adb = None
|
||||
|
||||
# detect target platform
|
||||
# detect target platform
|
||||
if self.android_executable or self.android_abi or self.ndk_path:
|
||||
self.targetos = "android"
|
||||
else:
|
||||
self.targetos = hostos
|
||||
|
||||
|
||||
if self.targetos == "android":
|
||||
# fix adb tool location
|
||||
if not self.adb:
|
||||
@@ -250,7 +250,7 @@ class RunInfo(object):
|
||||
self.adb = "adb"
|
||||
if options.adb_serial:
|
||||
self.adb = [self.adb, "-s", options.adb_serial]
|
||||
else:
|
||||
else:
|
||||
self.adb = [self.adb]
|
||||
try:
|
||||
output = Popen(self.adb + ["shell", "ls"], stdout=PIPE, stderr=PIPE).communicate()
|
||||
@@ -317,23 +317,23 @@ class RunInfo(object):
|
||||
self.targetarch = "x86"
|
||||
else:
|
||||
self.targetarch = "unknown"
|
||||
|
||||
|
||||
# fix CUDA attributes
|
||||
self.with_cuda = self.with_cuda == "ON"
|
||||
if self.cuda_library and self.cuda_library.endswith("-NOTFOUND"):
|
||||
self.cuda_library = None
|
||||
self.has_cuda = self.with_cuda and self.cuda_library and self.targetarch in ["x86", "x64"]
|
||||
|
||||
|
||||
self.hardware = None
|
||||
|
||||
|
||||
self.getSvnVersion(self.cmake_home, "cmake_home_svn")
|
||||
if self.opencv_home == self.cmake_home:
|
||||
self.opencv_home_svn = self.cmake_home_svn
|
||||
else:
|
||||
self.getSvnVersion(self.opencv_home, "opencv_home_svn")
|
||||
|
||||
|
||||
self.tests = self.getAvailableTestApps()
|
||||
|
||||
|
||||
def getSvnVersion(self, path, name):
|
||||
if not path:
|
||||
setattr(self, name, None)
|
||||
@@ -352,7 +352,7 @@ class RunInfo(object):
|
||||
setattr(self, name, None)
|
||||
except OSError:
|
||||
setattr(self, name, None)
|
||||
|
||||
|
||||
def tryGetSvnVersionWithTortoise(self, path, name):
|
||||
try:
|
||||
wcrev = "SubWCRev.exe"
|
||||
@@ -377,7 +377,7 @@ class RunInfo(object):
|
||||
if dir:
|
||||
import shutil
|
||||
shutil.rmtree(dir)
|
||||
|
||||
|
||||
def isTest(self, fullpath):
|
||||
if not os.path.isfile(fullpath):
|
||||
return False
|
||||
@@ -388,14 +388,14 @@ class RunInfo(object):
|
||||
if self.targetos == "android" and fullpath.endswith(".apk"):
|
||||
return True
|
||||
return True
|
||||
|
||||
|
||||
def getAvailableTestApps(self):
|
||||
if self.tests_dir and os.path.isdir(self.tests_dir):
|
||||
files = glob.glob(os.path.join(self.tests_dir, self.nameprefix + "*"))
|
||||
files = [f for f in files if self.isTest(f)]
|
||||
return files
|
||||
return []
|
||||
|
||||
|
||||
def getLogName(self, app, timestamp):
|
||||
app = os.path.basename(app)
|
||||
if app.endswith(".exe"):
|
||||
@@ -508,17 +508,17 @@ class RunInfo(object):
|
||||
hw = ""
|
||||
tstamp = timestamp.strftime("%Y-%m-%d--%H-%M-%S")
|
||||
return "%s_%s_%s_%s%s%s.xml" % (app, self.targetos, self.targetarch, hw, rev, tstamp)
|
||||
|
||||
|
||||
def getTest(self, name):
|
||||
# full path
|
||||
if self.isTest(name):
|
||||
return name
|
||||
|
||||
|
||||
# name only
|
||||
fullname = os.path.join(self.tests_dir, name)
|
||||
if self.isTest(fullname):
|
||||
return fullname
|
||||
|
||||
|
||||
# name without extension
|
||||
fullname += ".exe"
|
||||
if self.isTest(fullname):
|
||||
@@ -527,7 +527,7 @@ class RunInfo(object):
|
||||
fullname += ".apk"
|
||||
if self.isTest(fullname):
|
||||
return fullname
|
||||
|
||||
|
||||
# short name for OpenCV tests
|
||||
for t in self.tests:
|
||||
if t == name:
|
||||
@@ -547,7 +547,7 @@ class RunInfo(object):
|
||||
if fname == name:
|
||||
return t
|
||||
return None
|
||||
|
||||
|
||||
def runAdb(self, *args):
|
||||
cmd = self.adb[:]
|
||||
cmd.extend(args)
|
||||
@@ -559,7 +559,7 @@ class RunInfo(object):
|
||||
except OSError:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def isRunnable(self):
|
||||
if self.error:
|
||||
return False
|
||||
@@ -585,7 +585,7 @@ class RunInfo(object):
|
||||
if hw:
|
||||
self.hardware = hw.groups()[0].strip()
|
||||
return True
|
||||
|
||||
|
||||
def runTest(self, path, workingDir, _stdout, _stderr, args = []):
|
||||
if self.error:
|
||||
return
|
||||
@@ -593,13 +593,13 @@ class RunInfo(object):
|
||||
timestamp = datetime.datetime.now()
|
||||
logfile = self.getLogName(path, timestamp)
|
||||
exe = os.path.abspath(path)
|
||||
|
||||
|
||||
userlog = [a for a in args if a.startswith("--gtest_output=")]
|
||||
if len(userlog) == 0:
|
||||
args.append("--gtest_output=xml:" + logfile)
|
||||
else:
|
||||
logfile = userlog[0][userlog[0].find(":")+1:]
|
||||
|
||||
|
||||
if self.targetos == "android" and exe.endswith(".apk"):
|
||||
print "running java tests:", exe
|
||||
try:
|
||||
@@ -653,10 +653,11 @@ class RunInfo(object):
|
||||
elif self.targetos == "android":
|
||||
hostlogpath = ""
|
||||
usercolor = [a for a in args if a.startswith("--gtest_color=")]
|
||||
if len(userlog) == 0 and _stdout.isatty() and hostos != "nt":
|
||||
if len(usercolor) == 0 and _stdout.isatty() and hostos != "nt":
|
||||
args.append("--gtest_color=yes")
|
||||
try:
|
||||
andoidcwd = "/data/bin/" + getpass.getuser().replace(" ","") + "_" + self.options.mode +"/"
|
||||
tempdir = "/data/local/tmp/"
|
||||
andoidcwd = tempdir + getpass.getuser().replace(" ","") + "_" + self.options.mode +"/"
|
||||
exename = os.path.basename(exe)
|
||||
androidexe = andoidcwd + exename
|
||||
#upload
|
||||
@@ -692,6 +693,9 @@ class RunInfo(object):
|
||||
return
|
||||
#rm log
|
||||
Popen(self.adb + ["shell", "rm " + andoidcwd + logfile], stdout=_stdout, stderr=_stderr).wait()
|
||||
|
||||
# clean temporary files
|
||||
Popen(self.adb + ["shell", "rm " + tempdir + "__opencv_temp.*"], stdout=_stdout, stderr=_stderr).wait()
|
||||
except OSError:
|
||||
pass
|
||||
if os.path.isfile(hostlogpath):
|
||||
@@ -704,16 +708,27 @@ class RunInfo(object):
|
||||
else:
|
||||
cmd.extend(args)
|
||||
print >> _stderr, "Running:", " ".join(cmd)
|
||||
try:
|
||||
try:
|
||||
Popen(cmd, stdout=_stdout, stderr=_stderr, cwd = workingDir).wait()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
# clean temporary files
|
||||
temp_path = os.environ.get('OPENCV_TEMP_PATH')
|
||||
if not temp_path:
|
||||
if hostos == "nt":
|
||||
temp_path = tempfile.gettempdir()
|
||||
else:
|
||||
temp_path = "/tmp"
|
||||
|
||||
for filename in glob.glob(os.path.join(temp_path, "__opencv_temp.*")) :
|
||||
os.remove( filename )
|
||||
|
||||
logpath = os.path.join(workingDir, logfile)
|
||||
if os.path.isfile(logpath):
|
||||
return logpath
|
||||
return None
|
||||
|
||||
|
||||
def runTests(self, tests, _stdout, _stderr, workingDir, args = []):
|
||||
if self.error:
|
||||
return []
|
||||
@@ -747,10 +762,10 @@ def getRunArgs(args):
|
||||
if __name__ == "__main__":
|
||||
test_args = [a for a in sys.argv if a.startswith("--perf_") or a.startswith("--gtest_")]
|
||||
argv = [a for a in sys.argv if not(a.startswith("--perf_") or a.startswith("--gtest_"))]
|
||||
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option("-t", "--tests", dest="tests", help="comma-separated list of modules to test", metavar="SUITS", default="")
|
||||
|
||||
|
||||
parser.add_option("-w", "--cwd", dest="cwd", help="working directory for tests", metavar="PATH", default=".")
|
||||
parser.add_option("-a", "--accuracy", dest="accuracy", help="look for accuracy tests instead of performance tests", action="store_true", default=False)
|
||||
parser.add_option("-l", "--longname", dest="useLongNames", action="store_true", help="generate log files with long names", default=False)
|
||||
@@ -759,26 +774,26 @@ if __name__ == "__main__":
|
||||
parser.add_option("", "--serial", dest="adb_serial", help="Android: directs command to the USB device or emulator with the given serial number", metavar="serial number", default="")
|
||||
parser.add_option("", "--package", dest="junit_package", help="Android: run jUnit tests for specified package", metavar="package", default="")
|
||||
parser.add_option("", "--help-tests", dest="help", help="Show help for test executable", action="store_true", default=False)
|
||||
|
||||
|
||||
(options, args) = parser.parse_args(argv)
|
||||
|
||||
if options.accuracy:
|
||||
options.mode = "test"
|
||||
else:
|
||||
options.mode = "perf"
|
||||
|
||||
|
||||
run_args = getRunArgs(args[1:] or ['.'])
|
||||
|
||||
|
||||
if len(run_args) == 0:
|
||||
print >> sys.stderr, "Usage:\n", os.path.basename(sys.argv[0]), "<build_path>"
|
||||
exit(1)
|
||||
|
||||
|
||||
tests = [s.strip() for s in options.tests.split(",") if s]
|
||||
|
||||
|
||||
if len(tests) != 1 or len(run_args) != 1:
|
||||
#remove --gtest_output from params
|
||||
test_args = [a for a in test_args if not a.startswith("--gtest_output=")]
|
||||
|
||||
|
||||
logs = []
|
||||
for path in run_args:
|
||||
info = RunInfo(path, options)
|
||||
@@ -789,5 +804,5 @@ if __name__ == "__main__":
|
||||
info.test_data_path = options.test_data_path
|
||||
logs.extend(info.runTests(tests, sys.stdout, sys.stderr, options.cwd, test_args))
|
||||
|
||||
if logs:
|
||||
if logs:
|
||||
print >> sys.stderr, "Collected:", " ".join(logs)
|
||||
|
@@ -40,6 +40,7 @@
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
// The following lines pull in the real gtest *.cc files.
|
||||
@@ -300,7 +301,7 @@ class GTEST_API_ SingleFailureChecker {
|
||||
(substr));\
|
||||
{\
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\
|
||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
||||
>est_failures);\
|
||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||
}\
|
||||
@@ -313,6 +314,7 @@ class GTEST_API_ SingleFailureChecker {
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
@@ -514,6 +516,12 @@ GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
|
||||
// Formats the given time in milliseconds as seconds.
|
||||
GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
|
||||
|
||||
// Converts the given time in milliseconds to a date string in the ISO 8601
|
||||
// format, without the timezone information. N.B.: due to the use the
|
||||
// non-reentrant localtime() function, this function is not thread safe. Do
|
||||
// not use it in any code that can be called from multiple threads.
|
||||
GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
|
||||
|
||||
// Parses a string for an Int32 flag, in the form of "--flag=value".
|
||||
//
|
||||
// On success, stores the value of the flag in *value, and returns
|
||||
@@ -592,6 +600,7 @@ class GTestFlagSaver {
|
||||
GTEST_FLAG(stream_result_to) = stream_result_to_;
|
||||
GTEST_FLAG(throw_on_failure) = throw_on_failure_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Fields for saving the original values of flags.
|
||||
bool also_run_disabled_tests_;
|
||||
@@ -834,8 +843,11 @@ class OsStackTraceGetterInterface {
|
||||
class OsStackTraceGetter : public OsStackTraceGetterInterface {
|
||||
public:
|
||||
OsStackTraceGetter() : caller_frame_(NULL) {}
|
||||
virtual String CurrentStackTrace(int max_depth, int skip_count);
|
||||
virtual void UponLeavingGTest();
|
||||
|
||||
virtual String CurrentStackTrace(int max_depth, int skip_count)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
// This string is inserted in place of stack frames that are part of
|
||||
// Google Test's implementation.
|
||||
@@ -950,6 +962,10 @@ class GTEST_API_ UnitTestImpl {
|
||||
// Gets the number of tests that should run.
|
||||
int test_to_run_count() const;
|
||||
|
||||
// Gets the time of the test program start, in ms from the start of the
|
||||
// UNIX epoch.
|
||||
TimeInMillis start_timestamp() const { return start_timestamp_; }
|
||||
|
||||
// Gets the elapsed time, in milliseconds.
|
||||
TimeInMillis elapsed_time() const { return elapsed_time_; }
|
||||
|
||||
@@ -1008,7 +1024,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
// For example, if Foo() calls Bar(), which in turn calls
|
||||
// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
|
||||
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
||||
String CurrentOsStackTraceExceptTop(int skip_count);
|
||||
String CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
|
||||
|
||||
// Finds and returns a TestCase with the given name. If one doesn't
|
||||
// exist, creates one and returns it.
|
||||
@@ -1282,6 +1298,10 @@ class GTEST_API_ UnitTestImpl {
|
||||
// Our random number generator.
|
||||
internal::Random random_;
|
||||
|
||||
// The time of the test program start, in ms from the start of the
|
||||
// UNIX epoch.
|
||||
TimeInMillis start_timestamp_;
|
||||
|
||||
// How long the test took to run, in milliseconds.
|
||||
TimeInMillis elapsed_time_;
|
||||
|
||||
@@ -1613,7 +1633,7 @@ UInt32 Random::Generate(UInt32 range) {
|
||||
// Test. g_init_gtest_count is set to the number of times
|
||||
// InitGoogleTest() has been called. We don't protect this variable
|
||||
// under a mutex as it is only accessed in the main thread.
|
||||
int g_init_gtest_count = 0;
|
||||
GTEST_API_ int g_init_gtest_count = 0;
|
||||
static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
|
||||
|
||||
// Iterates over a vector of TestCases, keeping a running sum of the
|
||||
@@ -1668,7 +1688,7 @@ void AssertHelper::operator=(const Message& message) const {
|
||||
}
|
||||
|
||||
// Mutex for linked pointers.
|
||||
GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||
GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||
|
||||
// Application pathname gotten in InitGoogleTest.
|
||||
String g_executable_path;
|
||||
@@ -2125,17 +2145,6 @@ TimeInMillis GetTimeInMillis() {
|
||||
|
||||
// class String
|
||||
|
||||
// Returns the input enclosed in double quotes if it's not NULL;
|
||||
// otherwise returns "(null)". For example, "\"Hello\"" is returned
|
||||
// for input "Hello".
|
||||
//
|
||||
// This is useful for printing a C string in the syntax of a literal.
|
||||
//
|
||||
// Known issue: escape sequences are not handled yet.
|
||||
String String::ShowCStringQuoted(const char* c_str) {
|
||||
return c_str ? String::Format("\"%s\"", c_str) : String("(null)");
|
||||
}
|
||||
|
||||
// Copies at most length characters from str into a newly-allocated
|
||||
// piece of memory of size length+1. The memory is allocated with new[].
|
||||
// A terminating null byte is written to the memory, and a pointer to it
|
||||
@@ -2476,8 +2485,8 @@ AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
|
||||
return EqFailure(expected_expression,
|
||||
actual_expression,
|
||||
String::ShowCStringQuoted(expected),
|
||||
String::ShowCStringQuoted(actual),
|
||||
PrintToString(expected),
|
||||
PrintToString(actual),
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -2492,8 +2501,8 @@ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
|
||||
|
||||
return EqFailure(expected_expression,
|
||||
actual_expression,
|
||||
String::ShowCStringQuoted(expected),
|
||||
String::ShowCStringQuoted(actual),
|
||||
PrintToString(expected),
|
||||
PrintToString(actual),
|
||||
true);
|
||||
}
|
||||
|
||||
@@ -2841,15 +2850,6 @@ String String::ShowWideCString(const wchar_t * wide_c_str) {
|
||||
return String(internal::WideStringToUtf8(wide_c_str, -1).c_str());
|
||||
}
|
||||
|
||||
// Similar to ShowWideCString(), except that this function encloses
|
||||
// the converted string in double quotes.
|
||||
String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) {
|
||||
if (wide_c_str == NULL) return String("(null)");
|
||||
|
||||
return String::Format("L\"%s\"",
|
||||
String::ShowWideCString(wide_c_str).c_str());
|
||||
}
|
||||
|
||||
// Compares two wide C strings. Returns true iff they have the same
|
||||
// content.
|
||||
//
|
||||
@@ -2875,8 +2875,8 @@ AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
|
||||
return EqFailure(expected_expression,
|
||||
actual_expression,
|
||||
String::ShowWideCStringQuoted(expected),
|
||||
String::ShowWideCStringQuoted(actual),
|
||||
PrintToString(expected),
|
||||
PrintToString(actual),
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -2891,8 +2891,8 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
|
||||
return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
|
||||
<< s2_expression << "), actual: "
|
||||
<< String::ShowWideCStringQuoted(s1)
|
||||
<< " vs " << String::ShowWideCStringQuoted(s2);
|
||||
<< PrintToString(s1)
|
||||
<< " vs " << PrintToString(s2);
|
||||
}
|
||||
|
||||
// Compares two C strings, ignoring case. Returns true iff they have
|
||||
@@ -4015,8 +4015,6 @@ class PrettyUnitTestResultPrinter : public TestEventListener {
|
||||
|
||||
private:
|
||||
static void PrintFailedTests(const UnitTest& unit_test);
|
||||
|
||||
internal::String test_case_name_;
|
||||
};
|
||||
|
||||
// Fired before each iteration of tests starts.
|
||||
@@ -4063,11 +4061,10 @@ void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
|
||||
}
|
||||
|
||||
void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
|
||||
test_case_name_ = test_case.name();
|
||||
const internal::String counts =
|
||||
FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
|
||||
ColoredPrintf(COLOR_GREEN, "[----------] ");
|
||||
printf("%s from %s", counts.c_str(), test_case_name_.c_str());
|
||||
printf("%s from %s", counts.c_str(), test_case.name());
|
||||
if (test_case.type_param() == NULL) {
|
||||
printf("\n");
|
||||
} else {
|
||||
@@ -4078,7 +4075,7 @@ void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
|
||||
|
||||
void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
|
||||
ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
|
||||
PrintTestName(test_case_name_.c_str(), test_info.name());
|
||||
PrintTestName(test_info.test_case_name(), test_info.name());
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -4101,7 +4098,7 @@ void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
|
||||
} else {
|
||||
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
|
||||
}
|
||||
PrintTestName(test_case_name_.c_str(), test_info.name());
|
||||
PrintTestName(test_info.test_case_name(), test_info.name());
|
||||
if (test_info.result()->Failed())
|
||||
PrintFullTestCommentIfPresent(test_info);
|
||||
|
||||
@@ -4117,12 +4114,11 @@ void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
|
||||
void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
|
||||
if (!GTEST_FLAG(print_time)) return;
|
||||
|
||||
test_case_name_ = test_case.name();
|
||||
const internal::String counts =
|
||||
FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
|
||||
ColoredPrintf(COLOR_GREEN, "[----------] ");
|
||||
printf("%s from %s (%s ms total)\n\n",
|
||||
counts.c_str(), test_case_name_.c_str(),
|
||||
counts.c_str(), test_case.name(),
|
||||
internal::StreamableToString(test_case.elapsed_time()).c_str());
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -4507,6 +4503,32 @@ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Converts the given epoch time in milliseconds to a date string in the ISO
|
||||
// 8601 format, without the timezone information.
|
||||
std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
|
||||
// Using non-reentrant version as localtime_r is not portable.
|
||||
time_t seconds = static_cast<time_t>(ms / 1000);
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push) // Saves the current warning state.
|
||||
# pragma warning(disable:4996) // Temporarily disables warning 4996
|
||||
// (function or variable may be unsafe).
|
||||
const struct tm* const time_struct = localtime(&seconds); // NOLINT
|
||||
# pragma warning(pop) // Restores the warning state again.
|
||||
#else
|
||||
const struct tm* const time_struct = localtime(&seconds); // NOLINT
|
||||
#endif
|
||||
if (time_struct == NULL)
|
||||
return ""; // Invalid ms value
|
||||
|
||||
return String::Format("%d-%02d-%02dT%02d:%02d:%02d", // YYYY-MM-DDThh:mm:ss
|
||||
time_struct->tm_year + 1900,
|
||||
time_struct->tm_mon + 1,
|
||||
time_struct->tm_mday,
|
||||
time_struct->tm_hour,
|
||||
time_struct->tm_min,
|
||||
time_struct->tm_sec);
|
||||
}
|
||||
|
||||
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
|
||||
void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
|
||||
const char* data) {
|
||||
@@ -4556,16 +4578,17 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
|
||||
for (int i = 0; i < result.total_part_count(); ++i) {
|
||||
const TestPartResult& part = result.GetTestPartResult(i);
|
||||
if (part.failed()) {
|
||||
if (++failures == 1)
|
||||
if (++failures == 1) {
|
||||
*stream << ">\n";
|
||||
*stream << " <failure message=\""
|
||||
<< EscapeXmlAttribute(part.summary()).c_str()
|
||||
<< "\" type=\"\">";
|
||||
}
|
||||
const string location = internal::FormatCompilerIndependentFileLocation(
|
||||
part.file_name(), part.line_number());
|
||||
const string message = location + "\n" + part.message();
|
||||
OutputXmlCDataSection(stream,
|
||||
RemoveInvalidXmlCharacters(message).c_str());
|
||||
const string summary = location + "\n" + part.summary();
|
||||
*stream << " <failure message=\""
|
||||
<< EscapeXmlAttribute(summary.c_str())
|
||||
<< "\" type=\"\">";
|
||||
const string detail = location + "\n" + part.message();
|
||||
OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
|
||||
*stream << "</failure>\n";
|
||||
}
|
||||
}
|
||||
@@ -4603,10 +4626,11 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
|
||||
fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
fprintf(out,
|
||||
"<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
|
||||
"errors=\"0\" time=\"%s\" ",
|
||||
"errors=\"0\" timestamp=\"%s\" time=\"%s\" ",
|
||||
unit_test.total_test_count(),
|
||||
unit_test.failed_test_count(),
|
||||
unit_test.disabled_test_count(),
|
||||
FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()).c_str(),
|
||||
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
|
||||
if (GTEST_FLAG(shuffle)) {
|
||||
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
|
||||
@@ -4812,8 +4836,8 @@ void StreamingListener::MakeConnection() {
|
||||
|
||||
// Pushes the given source file location and message onto a per-thread
|
||||
// trace stack maintained by Google Test.
|
||||
// L < UnitTest::mutex_
|
||||
ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
|
||||
ScopedTrace::ScopedTrace(const char* file, int line, const Message& message)
|
||||
GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
|
||||
TraceInfo trace;
|
||||
trace.file = file;
|
||||
trace.line = line;
|
||||
@@ -4823,8 +4847,8 @@ ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
|
||||
}
|
||||
|
||||
// Pops the info pushed by the c'tor.
|
||||
// L < UnitTest::mutex_
|
||||
ScopedTrace::~ScopedTrace() {
|
||||
ScopedTrace::~ScopedTrace()
|
||||
GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
|
||||
UnitTest::GetInstance()->PopGTestTrace();
|
||||
}
|
||||
|
||||
@@ -4838,14 +4862,14 @@ ScopedTrace::~ScopedTrace() {
|
||||
// skip_count - the number of top frames to be skipped; doesn't count
|
||||
// against max_depth.
|
||||
//
|
||||
// L < mutex_
|
||||
// We use "L < mutex_" to denote that the function may acquire mutex_.
|
||||
String OsStackTraceGetter::CurrentStackTrace(int, int) {
|
||||
String OsStackTraceGetter::CurrentStackTrace(int /* max_depth */,
|
||||
int /* skip_count */)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
return String("");
|
||||
}
|
||||
|
||||
// L < mutex_
|
||||
void OsStackTraceGetter::UponLeavingGTest() {
|
||||
void OsStackTraceGetter::UponLeavingGTest()
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
}
|
||||
|
||||
const char* const
|
||||
@@ -4999,6 +5023,12 @@ int UnitTest::total_test_count() const { return impl()->total_test_count(); }
|
||||
// Gets the number of tests that should run.
|
||||
int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
|
||||
|
||||
// Gets the time of the test program start, in ms from the start of the
|
||||
// UNIX epoch.
|
||||
internal::TimeInMillis UnitTest::start_timestamp() const {
|
||||
return impl()->start_timestamp();
|
||||
}
|
||||
|
||||
// Gets the elapsed time, in milliseconds.
|
||||
internal::TimeInMillis UnitTest::elapsed_time() const {
|
||||
return impl()->elapsed_time();
|
||||
@@ -5052,12 +5082,13 @@ Environment* UnitTest::AddEnvironment(Environment* env) {
|
||||
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
|
||||
// this to report their results. The user code should use the
|
||||
// assertion macros instead of calling this directly.
|
||||
// L < mutex_
|
||||
void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
|
||||
const char* file_name,
|
||||
int line_number,
|
||||
const internal::String& message,
|
||||
const internal::String& os_stack_trace) {
|
||||
void UnitTest::AddTestPartResult(
|
||||
TestPartResult::Type result_type,
|
||||
const char* file_name,
|
||||
int line_number,
|
||||
const internal::String& message,
|
||||
const internal::String& os_stack_trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
Message msg;
|
||||
msg << message;
|
||||
|
||||
@@ -5141,7 +5172,6 @@ int UnitTest::Run() {
|
||||
// process. In either case the user does not want to see pop-up dialogs
|
||||
// about crashes - they are expected.
|
||||
if (impl()->catch_exceptions() || in_death_test_child_process) {
|
||||
|
||||
# if !GTEST_OS_WINDOWS_MOBILE
|
||||
// SetErrorMode doesn't exist on CE.
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
|
||||
@@ -5172,7 +5202,6 @@ int UnitTest::Run() {
|
||||
0x0, // Clear the following flags:
|
||||
_WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
|
||||
# endif
|
||||
|
||||
}
|
||||
#endif // GTEST_HAS_SEH
|
||||
|
||||
@@ -5190,16 +5219,16 @@ const char* UnitTest::original_working_dir() const {
|
||||
|
||||
// Returns the TestCase object for the test that's currently running,
|
||||
// or NULL if no test is running.
|
||||
// L < mutex_
|
||||
const TestCase* UnitTest::current_test_case() const {
|
||||
const TestCase* UnitTest::current_test_case() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
return impl_->current_test_case();
|
||||
}
|
||||
|
||||
// Returns the TestInfo object for the test that's currently running,
|
||||
// or NULL if no test is running.
|
||||
// L < mutex_
|
||||
const TestInfo* UnitTest::current_test_info() const {
|
||||
const TestInfo* UnitTest::current_test_info() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
return impl_->current_test_info();
|
||||
}
|
||||
@@ -5210,9 +5239,9 @@ int UnitTest::random_seed() const { return impl_->random_seed(); }
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
// Returns ParameterizedTestCaseRegistry object used to keep track of
|
||||
// value-parameterized tests and instantiate and register them.
|
||||
// L < mutex_
|
||||
internal::ParameterizedTestCaseRegistry&
|
||||
UnitTest::parameterized_test_registry() {
|
||||
UnitTest::parameterized_test_registry()
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
return impl_->parameterized_test_registry();
|
||||
}
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
@@ -5229,15 +5258,15 @@ UnitTest::~UnitTest() {
|
||||
|
||||
// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
|
||||
// Google Test trace stack.
|
||||
// L < mutex_
|
||||
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) {
|
||||
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
impl_->gtest_trace_stack().push_back(trace);
|
||||
}
|
||||
|
||||
// Pops a trace from the per-thread Google Test trace stack.
|
||||
// L < mutex_
|
||||
void UnitTest::PopGTestTrace() {
|
||||
void UnitTest::PopGTestTrace()
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
impl_->gtest_trace_stack().pop_back();
|
||||
}
|
||||
@@ -5273,6 +5302,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
|
||||
post_flag_parse_init_performed_(false),
|
||||
random_seed_(0), // Will be overridden by the flag before first use.
|
||||
random_(0), // Will be reseeded before first use.
|
||||
start_timestamp_(0),
|
||||
elapsed_time_(0),
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
internal_run_death_test_flag_(NULL),
|
||||
@@ -5504,6 +5534,7 @@ bool UnitTestImpl::RunAllTests() {
|
||||
|
||||
TestEventListener* repeater = listeners()->repeater();
|
||||
|
||||
start_timestamp_ = GetTimeInMillis();
|
||||
repeater->OnTestProgramStart(*parent_);
|
||||
|
||||
// How many times to repeat the tests? We don't want to repeat them
|
||||
@@ -5865,7 +5896,7 @@ bool SkipPrefix(const char* prefix, const char** pstr) {
|
||||
// part can be omitted.
|
||||
//
|
||||
// Returns the value of the flag, or NULL if the parsing failed.
|
||||
static const char* ParseFlagValue(const char* str,
|
||||
const char* ParseFlagValue(const char* str,
|
||||
const char* flag,
|
||||
bool def_optional) {
|
||||
// str and flag must not be NULL.
|
||||
@@ -6240,13 +6271,18 @@ void InitGoogleTest(int* argc, wchar_t** argv) {
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
# if GTEST_OS_MAC && !GTEST_OS_MAC_IOS
|
||||
# if GTEST_OS_MAC
|
||||
# include <crt_externs.h>
|
||||
# endif // GTEST_OS_MAC
|
||||
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <limits.h>
|
||||
|
||||
# if GTEST_OS_LINUX
|
||||
# include <signal.h>
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
# include <stdarg.h>
|
||||
|
||||
# if GTEST_OS_WINDOWS
|
||||
@@ -6256,6 +6292,10 @@ void InitGoogleTest(int* argc, wchar_t** argv) {
|
||||
# include <sys/wait.h>
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
# if GTEST_OS_QNX
|
||||
# include <spawn.h>
|
||||
# endif // GTEST_OS_QNX
|
||||
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
|
||||
@@ -6301,13 +6341,42 @@ GTEST_DEFINE_string_(
|
||||
"Indicates the file, line number, temporal index of "
|
||||
"the single death test to run, and a file descriptor to "
|
||||
"which a success code may be sent, all separated by "
|
||||
"colons. This flag is specified if and only if the current "
|
||||
"the '|' characters. This flag is specified if and only if the current "
|
||||
"process is a sub-process launched for running a thread-safe "
|
||||
"death test. FOR INTERNAL USE ONLY.");
|
||||
} // namespace internal
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Valid only for fast death tests. Indicates the code is running in the
|
||||
// child process of a fast style death test.
|
||||
static bool g_in_fast_death_test_child = false;
|
||||
|
||||
// Returns a Boolean value indicating whether the caller is currently
|
||||
// executing in the context of the death test child process. Tools such as
|
||||
// Valgrind heap checkers may need this to modify their behavior in death
|
||||
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
||||
// implementation of death tests. User code MUST NOT use it.
|
||||
bool InDeathTestChild() {
|
||||
# if GTEST_OS_WINDOWS
|
||||
|
||||
// On Windows, death tests are thread-safe regardless of the value of the
|
||||
// death_test_style flag.
|
||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
||||
|
||||
# else
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe")
|
||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
||||
else
|
||||
return g_in_fast_death_test_child;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// ExitedWithCode constructor.
|
||||
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
|
||||
}
|
||||
@@ -7017,6 +7086,7 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
|
||||
// Event forwarding to the listeners of event listener API mush be shut
|
||||
// down in death test subprocesses.
|
||||
GetUnitTestImpl()->listeners()->SuppressEventForwarding();
|
||||
g_in_fast_death_test_child = true;
|
||||
return EXECUTE_TEST;
|
||||
} else {
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
||||
@@ -7036,6 +7106,11 @@ class ExecDeathTest : public ForkingDeathTest {
|
||||
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
|
||||
virtual TestRole AssumeRole();
|
||||
private:
|
||||
static ::std::vector<testing::internal::string>
|
||||
GetArgvsForDeathTestChildProcess() {
|
||||
::std::vector<testing::internal::string> args = GetInjectableArgvs();
|
||||
return args;
|
||||
}
|
||||
// The name of the file in which the death test is located.
|
||||
const char* const file_;
|
||||
// The line number on which the death test is located.
|
||||
@@ -7070,6 +7145,7 @@ class Arguments {
|
||||
char* const* Argv() {
|
||||
return &args_[0];
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char*> args_;
|
||||
};
|
||||
@@ -7081,7 +7157,7 @@ struct ExecDeathTestArgs {
|
||||
int close_fd; // File descriptor to close; the read end of a pipe
|
||||
};
|
||||
|
||||
# if GTEST_OS_MAC && !GTEST_OS_MAC_IOS
|
||||
# if GTEST_OS_MAC
|
||||
inline char** GetEnviron() {
|
||||
// When Google Test is built as a framework on MacOS X, the environ variable
|
||||
// is unavailable. Apple's documentation (man environ) recommends using
|
||||
@@ -7095,6 +7171,7 @@ extern "C" char** environ;
|
||||
inline char** GetEnviron() { return environ; }
|
||||
# endif // GTEST_OS_MAC
|
||||
|
||||
# if !GTEST_OS_QNX
|
||||
// The main function for a threadsafe-style death test child process.
|
||||
// This function is called in a clone()-ed process and thus must avoid
|
||||
// any potentially unsafe operations like malloc or libc functions.
|
||||
@@ -7127,6 +7204,7 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||
GetLastErrnoDescription().c_str()));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
# endif // !GTEST_OS_QNX
|
||||
|
||||
// Two utility routines that together determine the direction the stack
|
||||
// grows.
|
||||
@@ -7137,25 +7215,76 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
|
||||
// StackLowerThanAddress into StackGrowsDown, which then doesn't give
|
||||
// correct answer.
|
||||
bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
|
||||
bool StackLowerThanAddress(const void* ptr) {
|
||||
void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
|
||||
void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||
int dummy;
|
||||
return &dummy < ptr;
|
||||
*result = (&dummy < ptr);
|
||||
}
|
||||
|
||||
static bool StackGrowsDown() {
|
||||
int dummy;
|
||||
return StackLowerThanAddress(&dummy);
|
||||
bool result;
|
||||
StackLowerThanAddress(&dummy, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A threadsafe implementation of fork(2) for threadsafe-style death tests
|
||||
// that uses clone(2). It dies with an error message if anything goes
|
||||
// wrong.
|
||||
static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
||||
// Spawns a child process with the same executable as the current process in
|
||||
// a thread-safe manner and instructs it to run the death test. The
|
||||
// implementation uses fork(2) + exec. On systems where clone(2) is
|
||||
// available, it is used instead, being slightly more thread-safe. On QNX,
|
||||
// fork supports only single-threaded environments, so this function uses
|
||||
// spawn(2) there instead. The function dies with an error message if
|
||||
// anything goes wrong.
|
||||
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||
ExecDeathTestArgs args = { argv, close_fd };
|
||||
pid_t child_pid = -1;
|
||||
|
||||
# if GTEST_HAS_CLONE
|
||||
# if GTEST_OS_QNX
|
||||
// Obtains the current directory and sets it to be closed in the child
|
||||
// process.
|
||||
const int cwd_fd = open(".", O_RDONLY);
|
||||
GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
|
||||
// We need to execute the test program in the same environment where
|
||||
// it was originally invoked. Therefore we change to the original
|
||||
// working directory first.
|
||||
const char* const original_dir =
|
||||
UnitTest::GetInstance()->original_working_dir();
|
||||
// We can safely call chdir() as it's a direct system call.
|
||||
if (chdir(original_dir) != 0) {
|
||||
DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
|
||||
original_dir,
|
||||
GetLastErrnoDescription().c_str()));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int fd_flags;
|
||||
// Set close_fd to be closed after spawn.
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
|
||||
fd_flags | FD_CLOEXEC));
|
||||
struct inheritance inherit = {0};
|
||||
// spawn is a system call.
|
||||
child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
|
||||
// Restores the current working directory.
|
||||
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||
|
||||
# else // GTEST_OS_QNX
|
||||
# if GTEST_OS_LINUX
|
||||
// When a SIGPROF signal is received while fork() or clone() are executing,
|
||||
// the process may hang. To avoid this, we ignore SIGPROF here and re-enable
|
||||
// it after the call to fork()/clone() is complete.
|
||||
struct sigaction saved_sigprof_action;
|
||||
struct sigaction ignore_sigprof_action;
|
||||
memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
|
||||
sigemptyset(&ignore_sigprof_action.sa_mask);
|
||||
ignore_sigprof_action.sa_handler = SIG_IGN;
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
|
||||
SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
# if GTEST_HAS_CLONE
|
||||
const bool use_fork = GTEST_FLAG(death_test_use_fork);
|
||||
|
||||
if (!use_fork) {
|
||||
@@ -7172,14 +7301,19 @@ static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
||||
}
|
||||
# else
|
||||
# else
|
||||
const bool use_fork = true;
|
||||
# endif // GTEST_HAS_CLONE
|
||||
# endif // GTEST_HAS_CLONE
|
||||
|
||||
if (use_fork && (child_pid = fork()) == 0) {
|
||||
ExecDeathTestChildMain(&args);
|
||||
_exit(0);
|
||||
}
|
||||
# endif // GTEST_OS_QNX
|
||||
# if GTEST_OS_LINUX
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||
sigaction(SIGPROF, &saved_sigprof_action, NULL));
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||
return child_pid;
|
||||
@@ -7216,7 +7350,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||
GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag,
|
||||
file_, line_, death_test_index, pipe_fd[1]);
|
||||
Arguments args;
|
||||
args.AddArguments(GetArgvs());
|
||||
args.AddArguments(GetArgvsForDeathTestChildProcess());
|
||||
args.AddArgument(filter_flag.c_str());
|
||||
args.AddArgument(internal_flag.c_str());
|
||||
|
||||
@@ -7227,7 +7361,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||
// is necessary.
|
||||
FlushInfoLog();
|
||||
|
||||
const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
|
||||
const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
||||
set_child_pid(child_pid);
|
||||
set_read_fd(pipe_fd[0]);
|
||||
@@ -7862,6 +7996,11 @@ void FilePath::Normalize() {
|
||||
# include <mach/vm_map.h>
|
||||
#endif // GTEST_OS_MAC
|
||||
|
||||
#if GTEST_OS_QNX
|
||||
# include <devctl.h>
|
||||
# include <sys/procfs.h>
|
||||
#endif // GTEST_OS_QNX
|
||||
|
||||
|
||||
// Indicates that this translation unit is part of Google Test's
|
||||
// implementation. It must come before gtest-internal-inl.h is
|
||||
@@ -7904,6 +8043,26 @@ size_t GetThreadCount() {
|
||||
}
|
||||
}
|
||||
|
||||
#elif GTEST_OS_QNX
|
||||
|
||||
// Returns the number of threads running in the process, or 0 to indicate that
|
||||
// we cannot detect it.
|
||||
size_t GetThreadCount() {
|
||||
const int fd = open("/proc/self/as", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return 0;
|
||||
}
|
||||
procfs_info process_info;
|
||||
const int status =
|
||||
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
|
||||
close(fd);
|
||||
if (status == EOK) {
|
||||
return static_cast<size_t>(process_info.num_threads);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
size_t GetThreadCount() {
|
||||
@@ -8295,7 +8454,6 @@ class CapturedStream {
|
||||
public:
|
||||
// The ctor redirects the stream to a temporary file.
|
||||
CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
|
||||
|
||||
# if GTEST_OS_WINDOWS
|
||||
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||
@@ -8312,10 +8470,15 @@ class CapturedStream {
|
||||
<< temp_file_path;
|
||||
filename_ = temp_file_path;
|
||||
# else
|
||||
// There's no guarantee that a test has write access to the
|
||||
// current directory, so we create the temporary file in the /tmp
|
||||
// directory instead.
|
||||
// There's no guarantee that a test has write access to the current
|
||||
// directory, so we create the temporary file in the /tmp directory instead.
|
||||
// We use /tmp on most systems, and /mnt/sdcard on Android. That's because
|
||||
// Android doesn't have /tmp.
|
||||
# if GTEST_OS_LINUX_ANDROID
|
||||
char name_template[] = "/mnt/sdcard/gtest_captured_stream.XXXXXX";
|
||||
# else
|
||||
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
||||
# endif // GTEST_OS_LINUX_ANDROID
|
||||
const int captured_fd = mkstemp(name_template);
|
||||
filename_ = name_template;
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
@@ -8434,11 +8597,23 @@ String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
// A copy of all command line arguments. Set by InitGoogleTest().
|
||||
::std::vector<String> g_argvs;
|
||||
::std::vector<testing::internal::string> g_argvs;
|
||||
|
||||
// Returns the command line as a vector of strings.
|
||||
const ::std::vector<String>& GetArgvs() { return g_argvs; }
|
||||
static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
|
||||
NULL; // Owned.
|
||||
|
||||
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
|
||||
if (g_injected_test_argvs != argvs)
|
||||
delete g_injected_test_argvs;
|
||||
g_injected_test_argvs = argvs;
|
||||
}
|
||||
|
||||
const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
|
||||
if (g_injected_test_argvs != NULL) {
|
||||
return *g_injected_test_argvs;
|
||||
}
|
||||
return g_argvs;
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
@@ -8605,14 +8780,6 @@ namespace {
|
||||
|
||||
using ::std::ostream;
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s.
|
||||
# define snprintf _snprintf
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf.
|
||||
# define snprintf _snprintf_s
|
||||
#elif defined(_MSC_VER) && _MSC_VER
|
||||
# define snprintf _snprintf
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
// Prints a segment of bytes in the given object.
|
||||
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||
size_t count, ostream* os) {
|
||||
@@ -8627,7 +8794,7 @@ void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||
else
|
||||
*os << '-';
|
||||
}
|
||||
snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
|
||||
GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
|
||||
*os << text;
|
||||
}
|
||||
}
|
||||
@@ -8741,9 +8908,9 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||
return kSpecialEscape;
|
||||
}
|
||||
|
||||
// Prints a char c as if it's part of a string literal, escaping it when
|
||||
// Prints a wchar_t c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
|
||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
switch (c) {
|
||||
case L'\'':
|
||||
*os << "'";
|
||||
@@ -8758,8 +8925,9 @@ static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
|
||||
|
||||
// Prints a char c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
|
||||
return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
|
||||
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(
|
||||
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
|
||||
}
|
||||
|
||||
// Prints a wide or narrow character c and its code. '\0' is printed
|
||||
@@ -8805,48 +8973,63 @@ void PrintTo(wchar_t wc, ostream* os) {
|
||||
PrintCharAndCodeTo<wchar_t>(wc, os);
|
||||
}
|
||||
|
||||
// Prints the given array of characters to the ostream.
|
||||
// The array starts at *begin, the length is len, it may include '\0' characters
|
||||
// and may not be null-terminated.
|
||||
static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
|
||||
*os << "\"";
|
||||
// Prints the given array of characters to the ostream. CharType must be either
|
||||
// char or wchar_t.
|
||||
// The array starts at begin, the length is len, it may include '\0' characters
|
||||
// and may not be NUL-terminated.
|
||||
template <typename CharType>
|
||||
static void PrintCharsAsStringTo(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
||||
*os << kQuoteBegin;
|
||||
bool is_previous_hex = false;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
const char cur = begin[index];
|
||||
const CharType cur = begin[index];
|
||||
if (is_previous_hex && IsXDigit(cur)) {
|
||||
// Previous character is of '\x..' form and this character can be
|
||||
// interpreted as another hexadecimal digit in its number. Break string to
|
||||
// disambiguate.
|
||||
*os << "\" \"";
|
||||
*os << "\" " << kQuoteBegin;
|
||||
}
|
||||
is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
|
||||
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
||||
}
|
||||
*os << "\"";
|
||||
}
|
||||
|
||||
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
||||
// 'begin'. CharType must be either char or wchar_t.
|
||||
template <typename CharType>
|
||||
static void UniversalPrintCharArray(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
// The code
|
||||
// const char kFoo[] = "foo";
|
||||
// generates an array of 4, not 3, elements, with the last one being '\0'.
|
||||
//
|
||||
// Therefore when printing a char array, we don't print the last element if
|
||||
// it's '\0', such that the output matches the string literal as it's
|
||||
// written in the source code.
|
||||
if (len > 0 && begin[len - 1] == '\0') {
|
||||
PrintCharsAsStringTo(begin, len - 1, os);
|
||||
return;
|
||||
}
|
||||
|
||||
// If, however, the last element in the array is not '\0', e.g.
|
||||
// const char kFoo[] = { 'f', 'o', 'o' };
|
||||
// we must print the entire array. We also print a message to indicate
|
||||
// that the array is not NUL-terminated.
|
||||
PrintCharsAsStringTo(begin, len, os);
|
||||
*os << " (no terminating NUL)";
|
||||
}
|
||||
|
||||
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
|
||||
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
||||
PrintCharsAsStringTo(begin, len, os);
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints the given array of wide characters to the ostream.
|
||||
// The array starts at *begin, the length is len, it may include L'\0'
|
||||
// characters and may not be null-terminated.
|
||||
static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
|
||||
ostream* os) {
|
||||
*os << "L\"";
|
||||
bool is_previous_hex = false;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
const wchar_t cur = begin[index];
|
||||
if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) {
|
||||
// Previous character is of '\x..' form and this character can be
|
||||
// interpreted as another hexadecimal digit in its number. Break string to
|
||||
// disambiguate.
|
||||
*os << "\" L\"";
|
||||
}
|
||||
is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
|
||||
}
|
||||
*os << "\"";
|
||||
// Prints a (const) wchar_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints the given C string to the ostream.
|
||||
@@ -8872,7 +9055,7 @@ void PrintTo(const wchar_t* s, ostream* os) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintWideCharsAsStringTo(s, wcslen(s), os);
|
||||
PrintCharsAsStringTo(s, wcslen(s), os);
|
||||
}
|
||||
}
|
||||
#endif // wchar_t is native
|
||||
@@ -8891,13 +9074,13 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||
// Prints a ::wstring object.
|
||||
#if GTEST_HAS_GLOBAL_WSTRING
|
||||
void PrintWideStringTo(const ::wstring& s, ostream* os) {
|
||||
PrintWideCharsAsStringTo(s.data(), s.size(), os);
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||
PrintWideCharsAsStringTo(s.data(), s.size(), os);
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
|
Reference in New Issue
Block a user