Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
googletest
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
googletest
Commits
07d4a6e9
Commit
07d4a6e9
authored
Jun 05, 2020
by
Gennadiy Rozental
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2742 from kuzkry:c++17-type-printers
PiperOrigin-RevId: 314593695
parents
210aab09
eb3953f8
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
209 additions
and
39 deletions
+209
-39
BUILD.bazel
BUILD.bazel
+1
-0
gtest-printers.h
googletest/include/gtest/gtest-printers.h
+48
-12
gtest-port.h
googletest/include/gtest/internal/gtest-port.h
+96
-0
gtest-type-util.h
googletest/include/gtest/internal/gtest-type-util.h
+21
-17
googletest-printers-test.cc
googletest/test/googletest-printers-test.cc
+43
-10
No files found.
BUILD.bazel
View file @
07d4a6e9
...
@@ -103,6 +103,7 @@ cc_library(
...
@@ -103,6 +103,7 @@ cc_library(
"@com_google_absl//absl/debugging:stacktrace",
"@com_google_absl//absl/debugging:stacktrace",
"@com_google_absl//absl/debugging:symbolize",
"@com_google_absl//absl/debugging:symbolize",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:any",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:variant",
"@com_google_absl//absl/types:variant",
],
],
...
...
googletest/include/gtest/gtest-printers.h
View file @
07d4a6e9
...
@@ -113,8 +113,6 @@
...
@@ -113,8 +113,6 @@
#if GTEST_HAS_ABSL
#if GTEST_HAS_ABSL
#include "absl/strings/string_view.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/variant.h"
#endif // GTEST_HAS_ABSL
#endif // GTEST_HAS_ABSL
namespace
testing
{
namespace
testing
{
...
@@ -596,14 +594,42 @@ class UniversalPrinter {
...
@@ -596,14 +594,42 @@ class UniversalPrinter {
GTEST_DISABLE_MSC_WARNINGS_POP_
()
GTEST_DISABLE_MSC_WARNINGS_POP_
()
};
};
#if GTEST_HAS_ABSL
#if GTEST_INTERNAL_HAS_ANY
// Printer for std::any / absl::any
// Printer for absl::optional
template
<>
class
UniversalPrinter
<
Any
>
{
public
:
static
void
Print
(
const
Any
&
value
,
::
std
::
ostream
*
os
)
{
if
(
value
.
has_value
())
{
*
os
<<
"value of type "
<<
GetTypeName
(
value
);
}
else
{
*
os
<<
"no value"
;
}
}
private
:
static
std
::
string
GetTypeName
(
const
Any
&
value
)
{
#if GTEST_HAS_RTTI
return
internal
::
GetTypeName
(
value
.
type
());
#else
static_cast
<
void
>
(
value
);
// possibly unused
return
"<unknown_type>"
;
#endif // GTEST_HAS_RTTI
}
};
#endif // GTEST_INTERNAL_HAS_ANY
#if GTEST_INTERNAL_HAS_OPTIONAL
// Printer for std::optional / absl::optional
template
<
typename
T
>
template
<
typename
T
>
class
UniversalPrinter
<
::
absl
::
o
ptional
<
T
>>
{
class
UniversalPrinter
<
O
ptional
<
T
>>
{
public
:
public
:
static
void
Print
(
const
::
absl
::
o
ptional
<
T
>&
value
,
::
std
::
ostream
*
os
)
{
static
void
Print
(
const
O
ptional
<
T
>&
value
,
::
std
::
ostream
*
os
)
{
*
os
<<
'('
;
*
os
<<
'('
;
if
(
!
value
)
{
if
(
!
value
)
{
*
os
<<
"nullopt"
;
*
os
<<
"nullopt"
;
...
@@ -614,14 +640,22 @@ class UniversalPrinter<::absl::optional<T>> {
...
@@ -614,14 +640,22 @@ class UniversalPrinter<::absl::optional<T>> {
}
}
};
};
// Printer for absl::variant
#endif // GTEST_INTERNAL_HAS_OPTIONAL
#if GTEST_INTERNAL_HAS_VARIANT
// Printer for std::variant / absl::variant
template
<
typename
...
T
>
template
<
typename
...
T
>
class
UniversalPrinter
<
::
absl
::
v
ariant
<
T
...
>>
{
class
UniversalPrinter
<
V
ariant
<
T
...
>>
{
public
:
public
:
static
void
Print
(
const
::
absl
::
v
ariant
<
T
...
>&
value
,
::
std
::
ostream
*
os
)
{
static
void
Print
(
const
V
ariant
<
T
...
>&
value
,
::
std
::
ostream
*
os
)
{
*
os
<<
'('
;
*
os
<<
'('
;
absl
::
visit
(
Visitor
{
os
},
value
);
#if GTEST_HAS_ABSL
absl
::
visit
(
Visitor
{
os
,
value
.
index
()},
value
);
#else
std
::
visit
(
Visitor
{
os
,
value
.
index
()},
value
);
#endif // GTEST_HAS_ABSL
*
os
<<
')'
;
*
os
<<
')'
;
}
}
...
@@ -629,14 +663,16 @@ class UniversalPrinter<::absl::variant<T...>> {
...
@@ -629,14 +663,16 @@ class UniversalPrinter<::absl::variant<T...>> {
struct
Visitor
{
struct
Visitor
{
template
<
typename
U
>
template
<
typename
U
>
void
operator
()(
const
U
&
u
)
const
{
void
operator
()(
const
U
&
u
)
const
{
*
os
<<
"'"
<<
GetTypeName
<
U
>
()
<<
"' with value "
;
*
os
<<
"'"
<<
GetTypeName
<
U
>
()
<<
"(index = "
<<
index
<<
")' with value "
;
UniversalPrint
(
u
,
os
);
UniversalPrint
(
u
,
os
);
}
}
::
std
::
ostream
*
os
;
::
std
::
ostream
*
os
;
std
::
size_t
index
;
};
};
};
};
#endif // GTEST_
HAS_ABSL
#endif // GTEST_
INTERNAL_HAS_VARIANT
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'.
// elements, starting at address 'begin'.
...
...
googletest/include/gtest/internal/gtest-port.h
View file @
07d4a6e9
...
@@ -199,9 +199,18 @@
...
@@ -199,9 +199,18 @@
// suppressed (constant conditional).
// suppressed (constant conditional).
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
// is suppressed.
// is suppressed.
// GTEST_INTERNAL_HAS_ANY - for enabling UniversalPrinter<std::any> or
// UniversalPrinter<absl::any> specializations.
// GTEST_INTERNAL_HAS_OPTIONAL - for enabling UniversalPrinter<std::optional>
// or
// UniversalPrinter<absl::optional>
// specializations.
// GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
// GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
// Matcher<absl::string_view>
// Matcher<absl::string_view>
// specializations.
// specializations.
// GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter<std::variant> or
// UniversalPrinter<absl::variant>
// specializations.
//
//
// Synchronization:
// Synchronization:
// Mutex, MutexLock, ThreadLocal, GetThreadCount()
// Mutex, MutexLock, ThreadLocal, GetThreadCount()
...
@@ -2244,6 +2253,64 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
...
@@ -2244,6 +2253,64 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
#endif // !defined(GTEST_INTERNAL_DEPRECATED)
#endif // !defined(GTEST_INTERNAL_DEPRECATED)
#if GTEST_HAS_ABSL
#if GTEST_HAS_ABSL
// Always use absl::any for UniversalPrinter<> specializations if googletest
// is built with absl support.
#define GTEST_INTERNAL_HAS_ANY 1
#include "absl/types/any.h"
namespace
testing
{
namespace
internal
{
using
Any
=
::
absl
::
any
;
}
// namespace internal
}
// namespace testing
#else
#ifdef __has_include
#if __has_include(<any>) && __cplusplus >= 201703L
// Otherwise for C++17 and higher use std::any for UniversalPrinter<>
// specializations.
#define GTEST_INTERNAL_HAS_ANY 1
#include <any>
namespace
testing
{
namespace
internal
{
using
Any
=
::
std
::
any
;
}
// namespace internal
}
// namespace testing
// The case where absl is configured NOT to alias std::any is not
// supported.
#endif // __has_include(<any>) && __cplusplus >= 201703L
#endif // __has_include
#endif // GTEST_HAS_ABSL
#if GTEST_HAS_ABSL
// Always use absl::optional for UniversalPrinter<> specializations if
// googletest is built with absl support.
#define GTEST_INTERNAL_HAS_OPTIONAL 1
#include "absl/types/optional.h"
namespace
testing
{
namespace
internal
{
template
<
typename
T
>
using
Optional
=
::
absl
::
optional
<
T
>
;
}
// namespace internal
}
// namespace testing
#else
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
// Otherwise for C++17 and higher use std::optional for UniversalPrinter<>
// specializations.
#define GTEST_INTERNAL_HAS_OPTIONAL 1
#include <optional>
namespace
testing
{
namespace
internal
{
template
<
typename
T
>
using
Optional
=
::
std
::
optional
<
T
>
;
}
// namespace internal
}
// namespace testing
// The case where absl is configured NOT to alias std::optional is not
// supported.
#endif // __has_include(<optional>) && __cplusplus >= 201703L
#endif // __has_include
#endif // GTEST_HAS_ABSL
#if GTEST_HAS_ABSL
// Always use absl::string_view for Matcher<> specializations if googletest
// Always use absl::string_view for Matcher<> specializations if googletest
// is built with absl support.
// is built with absl support.
# define GTEST_INTERNAL_HAS_STRING_VIEW 1
# define GTEST_INTERNAL_HAS_STRING_VIEW 1
...
@@ -2271,4 +2338,33 @@ using StringView = ::std::string_view;
...
@@ -2271,4 +2338,33 @@ using StringView = ::std::string_view;
# endif // __has_include
# endif // __has_include
#endif // GTEST_HAS_ABSL
#endif // GTEST_HAS_ABSL
#if GTEST_HAS_ABSL
// Always use absl::variant for UniversalPrinter<> specializations if googletest
// is built with absl support.
#define GTEST_INTERNAL_HAS_VARIANT 1
#include "absl/types/variant.h"
namespace
testing
{
namespace
internal
{
template
<
typename
...
T
>
using
Variant
=
::
absl
::
variant
<
T
...
>
;
}
// namespace internal
}
// namespace testing
#else
#ifdef __has_include
#if __has_include(<variant>) && __cplusplus >= 201703L
// Otherwise for C++17 and higher use std::variant for UniversalPrinter<>
// specializations.
#define GTEST_INTERNAL_HAS_VARIANT 1
#include <variant>
namespace
testing
{
namespace
internal
{
template
<
typename
...
T
>
using
Variant
=
::
std
::
variant
<
T
...
>
;
}
// namespace internal
}
// namespace testing
// The case where absl is configured NOT to alias std::variant is not supported.
#endif // __has_include(<variant>) && __cplusplus >= 201703L
#endif // __has_include
#endif // GTEST_HAS_ABSL
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
googletest/include/gtest/internal/gtest-type-util.h
View file @
07d4a6e9
...
@@ -64,34 +64,38 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) {
...
@@ -64,34 +64,38 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) {
return
s
;
return
s
;
}
}
// GetTypeName<T>() returns a human-readable name of type T.
#if GTEST_HAS_RTTI
// NB: This function is also used in Google Mock, so don't move it inside of
// GetTypeName(const std::type_info&) returns a human-readable name of type T.
// the typed-test-only section below.
inline
std
::
string
GetTypeName
(
const
std
::
type_info
&
type
)
{
template
<
typename
T
>
const
char
*
const
name
=
type
.
name
();
std
::
string
GetTypeName
()
{
#if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
# if GTEST_HAS_RTTI
const
char
*
const
name
=
typeid
(
T
).
name
();
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
int
status
=
0
;
int
status
=
0
;
// gcc's implementation of typeid(T).name() mangles the type name,
// gcc's implementation of typeid(T).name() mangles the type name,
// so we have to demangle it.
// so we have to demangle it.
#
if GTEST_HAS_CXXABI_H_
#if GTEST_HAS_CXXABI_H_
using
abi
::
__cxa_demangle
;
using
abi
::
__cxa_demangle
;
#
endif // GTEST_HAS_CXXABI_H_
#endif // GTEST_HAS_CXXABI_H_
char
*
const
readable_name
=
__cxa_demangle
(
name
,
nullptr
,
nullptr
,
&
status
);
char
*
const
readable_name
=
__cxa_demangle
(
name
,
nullptr
,
nullptr
,
&
status
);
const
std
::
string
name_str
(
status
==
0
?
readable_name
:
name
);
const
std
::
string
name_str
(
status
==
0
?
readable_name
:
name
);
free
(
readable_name
);
free
(
readable_name
);
return
CanonicalizeForStdLibVersioning
(
name_str
);
return
CanonicalizeForStdLibVersioning
(
name_str
);
#
else
#else
return
name
;
return
name
;
#
endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
#endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
}
#
else
#
endif // GTEST_HAS_RTTI
// GetTypeName<T>() returns a human-readable name of type T if and only if
// RTTI is enabled, otherwise it returns a dummy type name.
// NB: This function is also used in Google Mock, so don't move it inside of
// the typed-test-only section below.
template
<
typename
T
>
std
::
string
GetTypeName
()
{
#if GTEST_HAS_RTTI
return
GetTypeName
(
typeid
(
T
));
#else
return
"<type>"
;
return
"<type>"
;
#endif // GTEST_HAS_RTTI
# endif // GTEST_HAS_RTTI
}
}
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
...
...
googletest/test/googletest-printers-test.cc
View file @
07d4a6e9
...
@@ -1531,32 +1531,65 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
...
@@ -1531,32 +1531,65 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
EXPECT_EQ
(
"
\"
a
\"
"
,
result
[
1
]);
EXPECT_EQ
(
"
\"
a
\"
"
,
result
[
1
]);
}
}
#if GTEST_HAS_ABSL
#if GTEST_INTERNAL_HAS_ANY
class
PrintAnyTest
:
public
::
testing
::
Test
{
protected
:
template
<
typename
T
>
static
std
::
string
ExpectedTypeName
()
{
#if GTEST_HAS_RTTI
return
internal
::
GetTypeName
<
T
>
();
#else
return
"<unknown_type>"
;
#endif // GTEST_HAS_RTTI
}
};
TEST_F
(
PrintAnyTest
,
Empty
)
{
internal
::
Any
any
;
EXPECT_EQ
(
"no value"
,
PrintToString
(
any
));
}
TEST_F
(
PrintAnyTest
,
NonEmpty
)
{
internal
::
Any
any
;
constexpr
int
val1
=
10
;
const
std
::
string
val2
=
"content"
;
any
=
val1
;
EXPECT_EQ
(
"value of type "
+
ExpectedTypeName
<
int
>
(),
PrintToString
(
any
));
any
=
val2
;
EXPECT_EQ
(
"value of type "
+
ExpectedTypeName
<
std
::
string
>
(),
PrintToString
(
any
));
}
#endif // GTEST_INTERNAL_HAS_ANY
#if GTEST_INTERNAL_HAS_OPTIONAL
TEST
(
PrintOptionalTest
,
Basic
)
{
TEST
(
PrintOptionalTest
,
Basic
)
{
absl
::
o
ptional
<
int
>
value
;
internal
::
O
ptional
<
int
>
value
;
EXPECT_EQ
(
"(nullopt)"
,
PrintToString
(
value
));
EXPECT_EQ
(
"(nullopt)"
,
PrintToString
(
value
));
value
=
{
7
};
value
=
{
7
};
EXPECT_EQ
(
"(7)"
,
PrintToString
(
value
));
EXPECT_EQ
(
"(7)"
,
PrintToString
(
value
));
EXPECT_EQ
(
"(1.1)"
,
PrintToString
(
absl
::
o
ptional
<
double
>
{
1.1
}));
EXPECT_EQ
(
"(1.1)"
,
PrintToString
(
internal
::
O
ptional
<
double
>
{
1.1
}));
EXPECT_EQ
(
"(
\"
A
\"
)"
,
PrintToString
(
absl
::
o
ptional
<
std
::
string
>
{
"A"
}));
EXPECT_EQ
(
"(
\"
A
\"
)"
,
PrintToString
(
internal
::
O
ptional
<
std
::
string
>
{
"A"
}));
}
}
#endif // GTEST_INTERNAL_HAS_OPTIONAL
#if GTEST_INTERNAL_HAS_VARIANT
struct
NonPrintable
{
struct
NonPrintable
{
unsigned
char
contents
=
17
;
unsigned
char
contents
=
17
;
};
};
TEST
(
PrintOneofTest
,
Basic
)
{
TEST
(
PrintOneofTest
,
Basic
)
{
using
Type
=
absl
::
v
ariant
<
int
,
StreamableInGlobal
,
NonPrintable
>
;
using
Type
=
internal
::
V
ariant
<
int
,
StreamableInGlobal
,
NonPrintable
>
;
EXPECT_EQ
(
"('int' with value 7)"
,
PrintToString
(
Type
(
7
)));
EXPECT_EQ
(
"('int
(index = 0)
' with value 7)"
,
PrintToString
(
Type
(
7
)));
EXPECT_EQ
(
"('StreamableInGlobal' with value StreamableInGlobal)"
,
EXPECT_EQ
(
"('StreamableInGlobal
(index = 1)
' with value StreamableInGlobal)"
,
PrintToString
(
Type
(
StreamableInGlobal
{})));
PrintToString
(
Type
(
StreamableInGlobal
{})));
EXPECT_EQ
(
EXPECT_EQ
(
"('testing::gtest_printers_test::NonPrintable
' with value 1-byte object
"
"('testing::gtest_printers_test::NonPrintable
(index = 2)' with value
"
"<11>)"
,
"
1-byte object
<11>)"
,
PrintToString
(
Type
(
NonPrintable
{})));
PrintToString
(
Type
(
NonPrintable
{})));
}
}
#endif // GTEST_
HAS_ABSL
#endif // GTEST_
INTERNAL_HAS_VARIANT
namespace
{
namespace
{
class
string_ref
;
class
string_ref
;
...
...
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