Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
b8a03c80
Commit
b8a03c80
authored
Oct 28, 2018
by
Jerry Turcios
Browse files
Merge branch 'master' of
https://github.com/google/googletest
parents
299d098d
2e308484
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
107 additions
and
51 deletions
+107
-51
googletest/src/gtest-death-test.cc
googletest/src/gtest-death-test.cc
+107
-51
No files found.
googletest/src/gtest-death-test.cc
View file @
b8a03c80
...
@@ -64,6 +64,10 @@
...
@@ -64,6 +64,10 @@
# if GTEST_OS_FUCHSIA
# if GTEST_OS_FUCHSIA
# include <lib/fdio/io.h>
# include <lib/fdio/io.h>
# include <lib/fdio/spawn.h>
# include <lib/fdio/spawn.h>
# include <lib/fdio/util.h>
# include <lib/zx/socket.h>
# include <lib/zx/port.h>
# include <lib/zx/process.h>
# include <zircon/processargs.h>
# include <zircon/processargs.h>
# include <zircon/syscalls.h>
# include <zircon/syscalls.h>
# include <zircon/syscalls/port.h>
# include <zircon/syscalls/port.h>
...
@@ -422,6 +426,9 @@ class DeathTestImpl : public DeathTest {
...
@@ -422,6 +426,9 @@ class DeathTestImpl : public DeathTest {
// case of unexpected codes.
// case of unexpected codes.
void
ReadAndInterpretStatusByte
();
void
ReadAndInterpretStatusByte
();
// Returns stderr output from the child process.
virtual
std
::
string
GetErrorLogs
();
private:
private:
// The textual content of the code this object is testing. This class
// The textual content of the code this object is testing. This class
// doesn't own this string and should not attempt to delete it.
// doesn't own this string and should not attempt to delete it.
...
@@ -490,6 +497,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
...
@@ -490,6 +497,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
set_read_fd
(
-
1
);
set_read_fd
(
-
1
);
}
}
std
::
string
DeathTestImpl
::
GetErrorLogs
()
{
return
GetCapturedStderr
();
}
// Signals that the death test code which should have exited, didn't.
// Signals that the death test code which should have exited, didn't.
// Should be called only in a death test child process.
// Should be called only in a death test child process.
// Writes a status byte to the child's status file descriptor, then
// Writes a status byte to the child's status file descriptor, then
...
@@ -558,7 +569,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
...
@@ -558,7 +569,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
if
(
!
spawned
())
if
(
!
spawned
())
return
false
;
return
false
;
const
std
::
string
error_message
=
Get
CapturedStderr
();
const
std
::
string
error_message
=
Get
ErrorLogs
();
bool
success
=
false
;
bool
success
=
false
;
Message
buffer
;
Message
buffer
;
...
@@ -810,12 +821,6 @@ class FuchsiaDeathTest : public DeathTestImpl {
...
@@ -810,12 +821,6 @@ class FuchsiaDeathTest : public DeathTestImpl {
const
char
*
file
,
const
char
*
file
,
int
line
)
int
line
)
:
DeathTestImpl
(
a_statement
,
a_regex
),
file_
(
file
),
line_
(
line
)
{}
:
DeathTestImpl
(
a_statement
,
a_regex
),
file_
(
file
),
line_
(
line
)
{}
virtual
~
FuchsiaDeathTest
()
{
zx_status_t
status
=
zx_handle_close
(
child_process_
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
status
=
zx_handle_close
(
port_
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
}
// All of these virtual functions are inherited from DeathTest.
// All of these virtual functions are inherited from DeathTest.
virtual
int
Wait
();
virtual
int
Wait
();
...
@@ -826,9 +831,12 @@ class FuchsiaDeathTest : public DeathTestImpl {
...
@@ -826,9 +831,12 @@ class FuchsiaDeathTest : public DeathTestImpl {
const
char
*
const
file_
;
const
char
*
const
file_
;
// The line number on which the death test is located.
// The line number on which the death test is located.
const
int
line_
;
const
int
line_
;
// The stderr data captured by the child process.
std
::
string
captured_stderr_
;
zx_handle_t
child_process_
=
ZX_HANDLE_INVALID
;
zx
::
process
child_process_
;
zx_handle_t
port_
=
ZX_HANDLE_INVALID
;
zx
::
port
port_
;
zx
::
socket
stderr_socket_
;
};
};
// Utility class for accumulating command-line arguments.
// Utility class for accumulating command-line arguments.
...
@@ -872,51 +880,74 @@ class Arguments {
...
@@ -872,51 +880,74 @@ class Arguments {
// status, or 0 if no child process exists. As a side effect, sets the
// status, or 0 if no child process exists. As a side effect, sets the
// outcome data member.
// outcome data member.
int
FuchsiaDeathTest
::
Wait
()
{
int
FuchsiaDeathTest
::
Wait
()
{
const
int
kProcessKey
=
0
;
const
int
kSocketKey
=
1
;
if
(
!
spawned
())
if
(
!
spawned
())
return
0
;
return
0
;
// Register to wait for the child process to terminate.
// Register to wait for the child process to terminate.
zx_status_t
status_zx
;
zx_status_t
status_zx
;
status_zx
=
zx_object_wait_async
(
child_process_
,
status_zx
=
child_process_
.
wait_async
(
port_
,
port_
,
kProcessKey
,
ZX_PROCESS_TERMINATED
,
ZX_WAIT_ASYNC_ONCE
);
0
/* key */
,
ZX_PROCESS_TERMINATED
,
ZX_WAIT_ASYNC_ONCE
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
// Register to wait for the socket to be readable or closed.
// Wait for it to terminate, or an exception to be received.
status_zx
=
stderr_socket_
.
wait_async
(
zx_
port_
packet_t
packet
;
port_
,
kSocketKey
,
ZX_SOCKET_READABLE
|
ZX_SOCKET_PEER_CLOSED
,
status_zx
=
zx_port_wait
(
port_
,
ZX_TIME_INFINITE
,
&
packet
);
ZX_WAIT_ASYNC_REPEATING
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
if
(
ZX_PKT_IS_EXCEPTION
(
packet
.
type
))
{
bool
process_terminated
=
false
;
// Process encountered an exception. Kill it directly rather than letting
bool
socket_closed
=
false
;
// other handlers process the event.
do
{
status_zx
=
zx_task_kill
(
child_process_
);
zx_port_packet_t
packet
=
{};
status_zx
=
port_
.
wait
(
zx
::
time
::
infinite
(),
&
packet
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
// Now wait for |child_process_| to terminate.
if
(
packet
.
key
==
kProcessKey
)
{
zx_signals_t
signals
=
0
;
if
(
ZX_PKT_IS_EXCEPTION
(
packet
.
type
))
{
status_zx
=
zx_object_wait_one
(
// Process encountered an exception. Kill it directly rather than
child_process_
,
ZX_PROCESS_TERMINATED
,
ZX_TIME_INFINITE
,
&
signals
);
// letting other handlers process the event. We will get a second
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
// kProcessKey event when the process actually terminates.
GTEST_DEATH_TEST_CHECK_
(
signals
&
ZX_PROCESS_TERMINATED
);
status_zx
=
child_process_
.
kill
();
}
else
{
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
// Process terminated.
}
else
{
GTEST_DEATH_TEST_CHECK_
(
ZX_PKT_IS_SIGNAL_ONE
(
packet
.
type
));
// Process terminated.
GTEST_DEATH_TEST_CHECK_
(
packet
.
signal
.
observed
&
ZX_PROCESS_TERMINATED
);
GTEST_DEATH_TEST_CHECK_
(
ZX_PKT_IS_SIGNAL_ONE
(
packet
.
type
));
}
GTEST_DEATH_TEST_CHECK_
(
packet
.
signal
.
observed
&
ZX_PROCESS_TERMINATED
);
process_terminated
=
true
;
}
}
else
if
(
packet
.
key
==
kSocketKey
)
{
GTEST_DEATH_TEST_CHECK_
(
ZX_PKT_IS_SIGNAL_REP
(
packet
.
type
));
if
(
packet
.
signal
.
observed
&
ZX_SOCKET_READABLE
)
{
// Read data from the socket.
constexpr
size_t
kBufferSize
=
1024
;
do
{
size_t
old_length
=
captured_stderr_
.
length
();
size_t
bytes_read
=
0
;
captured_stderr_
.
resize
(
old_length
+
kBufferSize
);
status_zx
=
stderr_socket_
.
read
(
0
,
&
captured_stderr_
.
front
()
+
old_length
,
kBufferSize
,
&
bytes_read
);
captured_stderr_
.
resize
(
old_length
+
bytes_read
);
}
while
(
status_zx
==
ZX_OK
);
if
(
status_zx
==
ZX_ERR_PEER_CLOSED
)
{
socket_closed
=
true
;
}
else
{
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_ERR_SHOULD_WAIT
);
}
}
else
{
GTEST_DEATH_TEST_CHECK_
(
packet
.
signal
.
observed
&
ZX_SOCKET_PEER_CLOSED
);
socket_closed
=
true
;
}
}
}
while
(
!
process_terminated
&&
!
socket_closed
);
ReadAndInterpretStatusByte
();
ReadAndInterpretStatusByte
();
zx_info_process_t
buffer
;
zx_info_process_t
buffer
;
status_zx
=
zx_object_get_info
(
status_zx
=
child_process_
.
get_info
(
child_process_
,
ZX_INFO_PROCESS
,
&
buffer
,
sizeof
(
buffer
),
nullptr
,
nullptr
);
ZX_INFO_PROCESS
,
&
buffer
,
sizeof
(
buffer
),
nullptr
,
nullptr
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
status_zx
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
buffer
.
exited
);
GTEST_DEATH_TEST_CHECK_
(
buffer
.
exited
);
...
@@ -943,7 +974,6 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
...
@@ -943,7 +974,6 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
return
EXECUTE_TEST
;
return
EXECUTE_TEST
;
}
}
CaptureStderr
();
// Flush the log buffers since the log streams are shared with the child.
// Flush the log buffers since the log streams are shared with the child.
FlushInfoLog
();
FlushInfoLog
();
...
@@ -970,29 +1000,55 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
...
@@ -970,29 +1000,55 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
set_read_fd
(
status
);
set_read_fd
(
status
);
// Set the pipe handle for the child.
// Set the pipe handle for the child.
fdio_spawn_action_t
add_handle_action
=
{};
fdio_spawn_action_t
spawn_actions
[
2
]
=
{};
add_handle_action
.
action
=
FDIO_SPAWN_ACTION_ADD_HANDLE
;
fdio_spawn_action_t
*
add_handle_action
=
&
spawn_actions
[
0
];
add_handle_action
.
h
.
id
=
PA_HND
(
type
,
kFuchsiaReadPipeFd
);
add_handle_action
->
action
=
FDIO_SPAWN_ACTION_ADD_HANDLE
;
add_handle_action
.
h
.
handle
=
child_pipe_handle
;
add_handle_action
->
h
.
id
=
PA_HND
(
type
,
kFuchsiaReadPipeFd
);
add_handle_action
->
h
.
handle
=
child_pipe_handle
;
// Create a socket pair will be used to receive the child process' stderr.
zx
::
socket
stderr_producer_socket
;
status
=
zx
::
socket
::
create
(
0
,
&
stderr_producer_socket
,
&
stderr_socket_
);
GTEST_DEATH_TEST_CHECK_
(
status
>=
0
);
int
stderr_producer_fd
=
-
1
;
zx_handle_t
producer_handle
[
1
]
=
{
stderr_producer_socket
.
release
()
};
uint32_t
producer_handle_type
[
1
]
=
{
PA_FDIO_SOCKET
};
status
=
fdio_create_fd
(
producer_handle
,
producer_handle_type
,
1
,
&
stderr_producer_fd
);
GTEST_DEATH_TEST_CHECK_
(
status
>=
0
);
// Make the stderr socket nonblocking.
GTEST_DEATH_TEST_CHECK_
(
fcntl
(
stderr_producer_fd
,
F_SETFL
,
0
)
==
0
);
fdio_spawn_action_t
*
add_stderr_action
=
&
spawn_actions
[
1
];
add_stderr_action
->
action
=
FDIO_SPAWN_ACTION_CLONE_FD
;
add_stderr_action
->
fd
.
local_fd
=
stderr_producer_fd
;
add_stderr_action
->
fd
.
target_fd
=
STDERR_FILENO
;
// Spawn the child process.
// Spawn the child process.
status
=
fdio_spawn_etc
(
ZX_HANDLE_INVALID
,
FDIO_SPAWN_CLONE_ALL
,
status
=
fdio_spawn_etc
(
args
.
Argv
()[
0
],
args
.
Argv
(),
nullptr
,
1
,
ZX_HANDLE_INVALID
,
FDIO_SPAWN_CLONE_ALL
,
args
.
Argv
()[
0
],
args
.
Argv
(),
&
add_handle_action
,
&
child_process_
,
nullptr
);
nullptr
,
2
,
spawn_actions
,
child_process_
.
reset_and_get_address
(),
nullptr
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
// Create an exception port and attach it to the |child_process_|, to allow
// Create an exception port and attach it to the |child_process_|, to allow
// us to suppress the system default exception handler from firing.
// us to suppress the system default exception handler from firing.
status
=
zx
_
port
_
create
(
0
,
&
port_
);
status
=
zx
::
port
::
create
(
0
,
&
port_
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
status
=
zx_task_
bind_exception_port
(
status
=
child_process_
.
bind_exception_port
(
child_process_
,
port_
,
0
/* key */
,
0
/*options */
);
port_
,
0
/* key */
,
0
/*options */
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
GTEST_DEATH_TEST_CHECK_
(
status
==
ZX_OK
);
set_spawned
(
true
);
set_spawned
(
true
);
return
OVERSEE_TEST
;
return
OVERSEE_TEST
;
}
}
std
::
string
FuchsiaDeathTest
::
GetErrorLogs
()
{
return
captured_stderr_
;
}
#else // We are neither on Windows, nor on Fuchsia.
#else // We are neither on Windows, nor on Fuchsia.
// ForkingDeathTest provides implementations for most of the abstract
// ForkingDeathTest provides implementations for most of the abstract
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment