Add support for streaming results on Windows (fixes #3935).

This commit is contained in:
David Matson 2022-08-29 12:40:04 -07:00 committed by David Matson
parent b479e7a3c1
commit 9b0b00a104
14 changed files with 143 additions and 11 deletions

View File

@ -75,7 +75,7 @@ macro(config_compiler_and_linker)
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J")
set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN -DNOMINMAX")
set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
set(cxx_no_exception_flags "-EHs-c- -D_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-GR-")

View File

@ -708,7 +708,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#if defined(GTEST_OS_LINUX) || defined(GTEST_OS_GNU_KFREEBSD) || \
defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) || \
defined(GTEST_OS_NETBSD) || defined(GTEST_OS_OPENBSD) || \
defined(GTEST_OS_GNU_HURD) || defined(GTEST_OS_MAC)
defined(GTEST_OS_GNU_HURD) || defined(GTEST_OS_MAC) || \
defined(GTEST_OS_WINDOWS)
#define GTEST_CAN_STREAM_RESULTS_ 1
#else
#define GTEST_CAN_STREAM_RESULTS_ 0

View File

@ -62,6 +62,12 @@
#ifdef GTEST_OS_WINDOWS
#include <windows.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#else
#include <sys/mman.h>
#include <sys/wait.h>

View File

@ -38,6 +38,12 @@
#include "gtest/internal/gtest-port.h"
#ifdef GTEST_OS_WINDOWS_MOBILE
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#elif defined(GTEST_OS_WINDOWS)
#include <direct.h>

View File

@ -52,11 +52,22 @@
#include "gtest/internal/gtest-port.h"
#if GTEST_CAN_STREAM_RESULTS_
#if GTEST_OS_WINDOWS
#include <WinSock2.h> // NOLINT
#pragma comment(lib, "Ws2_32.lib")
#else
#include <arpa/inet.h> // NOLINT
#include <netdb.h> // NOLINT
#endif
#endif
#ifdef GTEST_OS_WINDOWS
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // NOLINT
#endif // GTEST_OS_WINDOWS
@ -1071,7 +1082,7 @@ class TestResultAccessor {
#if GTEST_CAN_STREAM_RESULTS_
// Streams test results to the given port on the given host machine.
class StreamingListener : public EmptyTestEventListener {
class GTEST_API_ StreamingListener : public EmptyTestEventListener {
public:
// Abstract base class for writing strings to a socket.
class AbstractSocketWriter {
@ -1092,24 +1103,44 @@ class StreamingListener : public EmptyTestEventListener {
class SocketWriter : public AbstractSocketWriter {
public:
SocketWriter(const std::string& host, const std::string& port)
#if GTEST_OS_WINDOWS
: sockfd_(INVALID_SOCKET), host_name_(host), port_num_(port) {
#else
: sockfd_(-1), host_name_(host), port_num_(port) {
#endif
MakeConnection();
}
~SocketWriter() override {
#if GTEST_OS_WINDOWS
if (sockfd_ != INVALID_SOCKET) CloseConnection();
#else
if (sockfd_ != -1) CloseConnection();
#endif
}
// Sends a string to the socket.
void Send(const std::string& message) override {
#if GTEST_OS_WINDOWS
GTEST_CHECK_(sockfd_ != INVALID_SOCKET)
#else
GTEST_CHECK_(sockfd_ != -1)
#endif
<< "Send() can be called only when there is a connection.";
#if GTEST_OS_WINDOWS
const auto len = static_cast<int>(message.length());
if (send(sockfd_, message.c_str(), len, 0) != len) {
GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to "
<< host_name_ << ":" << port_num_;
}
#else
const auto len = static_cast<size_t>(message.length());
if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to "
<< host_name_ << ":" << port_num_;
}
#endif
}
private:
@ -1118,14 +1149,27 @@ class StreamingListener : public EmptyTestEventListener {
// Closes the socket.
void CloseConnection() override {
#if GTEST_OS_WINDOWS
GTEST_CHECK_(sockfd_ != INVALID_SOCKET)
#else
GTEST_CHECK_(sockfd_ != -1)
#endif
<< "CloseConnection() can be called only when there is a connection.";
#if GTEST_OS_WINDOWS
closesocket(sockfd_);
sockfd_ = INVALID_SOCKET;
#else
close(sockfd_);
sockfd_ = -1;
#endif
}
int sockfd_; // socket file descriptor
#if GTEST_OS_WINDOWS
SOCKET sockfd_; // socket file descriptor
#else
int sockfd_; // socket file descriptor
#endif
const std::string host_name_;
const std::string port_num_;

View File

@ -45,6 +45,12 @@
#ifdef GTEST_OS_WINDOWS
#include <io.h>
#include <sys/stat.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <map> // Used in ThreadLocal.

View File

@ -88,13 +88,23 @@
#elif defined(GTEST_OS_WINDOWS_MOBILE) // We are on Windows CE.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // NOLINT
#undef min
#elif defined(GTEST_OS_WINDOWS) // We are on Windows proper.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // NOLINT
#undef min
#ifdef _MSC_VER
#include <crtdbg.h> // NOLINT
@ -123,11 +133,17 @@
#endif
#if GTEST_CAN_STREAM_RESULTS_
#if GTEST_OS_WINDOWS
#include <WinSock2.h> // NOLINT
#include <ws2tcpip.h> // NOLINT
#pragma comment(lib, "Ws2_32.lib")
#else
#include <arpa/inet.h> // NOLINT
#include <netdb.h> // NOLINT
#include <sys/socket.h> // NOLINT
#include <sys/types.h> // NOLINT
#endif
#endif
#include "src/gtest-internal-inl.h"
@ -4940,6 +4956,21 @@ void StreamingListener::SocketWriter::MakeConnection() {
GTEST_CHECK_(sockfd_ == -1)
<< "MakeConnection() can't be called when there is already a connection.";
#if GTEST_OS_WINDOWS
WSADATA winsockVersion{};
int startupError{ WSAStartup(MAKEWORD(2, 2), &winsockVersion) };
if (startupError)
{
return;
}
if (LOBYTE(winsockVersion.wVersion) != 2 || HIBYTE(winsockVersion.wVersion) != 2)
{
return;
}
#endif
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses.
@ -4960,6 +4991,15 @@ void StreamingListener::SocketWriter::MakeConnection() {
cur_addr = cur_addr->ai_next) {
sockfd_ = socket(cur_addr->ai_family, cur_addr->ai_socktype,
cur_addr->ai_protocol);
#if GTEST_OS_WINDOWS
if (sockfd_ != INVALID_SOCKET) {
// Connect the client socket to the server socket.
if (connect(sockfd_, cur_addr->ai_addr, static_cast<int>(cur_addr->ai_addrlen)) == -1) {
closesocket(sockfd_);
sockfd_ = INVALID_SOCKET;
}
}
#else
if (sockfd_ != -1) {
// Connect the client socket to the server socket.
if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
@ -4967,6 +5007,7 @@ void StreamingListener::SocketWriter::MakeConnection() {
sockfd_ = -1;
}
}
#endif
}
freeaddrinfo(servinfo); // all done with this structure

View File

@ -41,6 +41,12 @@
#ifdef GTEST_OS_WINDOWS
#include <stdlib.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#endif

View File

@ -38,6 +38,12 @@
#include "gtest/gtest.h"
#if GTEST_HAS_SEH
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#endif

View File

@ -1217,10 +1217,8 @@ typedef unsigned long long BiggestParsable;
typedef signed long long BiggestSignedParsable;
#endif // GTEST_OS_WINDOWS
// We cannot use std::numeric_limits<T>::max() as it clashes with the
// max() macro defined by <windows.h>.
const BiggestParsable kBiggestParsableMax = ULLONG_MAX;
const BiggestSignedParsable kBiggestSignedParsableMax = LLONG_MAX;
const BiggestParsable kBiggestParsableMax = std::numeric_limits<unsigned long long>::max();
const BiggestSignedParsable kBiggestSignedParsableMax = std::numeric_limits<long long>::max();
TEST(ParseNaturalNumberTest, RejectsInvalidFormat) {
BiggestParsable result = 0;

View File

@ -36,6 +36,12 @@
#ifdef GTEST_HAS_DEATH_TEST
#if GTEST_HAS_SEH
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // For RaiseException().
#endif

View File

@ -42,6 +42,12 @@
#include "src/gtest-internal-inl.h"
#ifdef GTEST_OS_WINDOWS_MOBILE
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // NOLINT
#elif defined(GTEST_OS_WINDOWS)
#include <direct.h> // NOLINT

View File

@ -41,6 +41,12 @@
#include "gtest/gtest.h"
#ifdef GTEST_OS_WINDOWS_MOBILE
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#elif defined(GTEST_OS_WINDOWS)
#include <direct.h>

View File

@ -144,7 +144,7 @@ class GTestHelpTest(gtest_test_utils.TestCase):
self.assertTrue(HELP_REGEX.search(output), output)
if IS_DARWIN or IS_LINUX or IS_GNUHURD or is_bsd_based_os():
if IS_DARWIN or IS_LINUX or IS_GNUHURD or is_bsd_based_os() or IS_WINDOWS:
self.assertIn(STREAM_RESULT_TO_FLAG, output)
else:
self.assertNotIn(STREAM_RESULT_TO_FLAG, output)