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
07d4a6e9
Commit
07d4a6e9
authored
Jun 05, 2020
by
Gennadiy Rozental
Browse files
Merge pull request #2742 from kuzkry:c++17-type-printers
PiperOrigin-RevId: 314593695
parents
210aab09
eb3953f8
Changes
5
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
googletest/include/gtest/gtest-printers.h
googletest/include/gtest/gtest-printers.h
+48
-12
googletest/include/gtest/internal/gtest-port.h
googletest/include/gtest/internal/gtest-port.h
+96
-0
googletest/include/gtest/internal/gtest-type-util.h
googletest/include/gtest/internal/gtest-type-util.h
+21
-17
googletest/test/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(
"@com_google_absl//absl/debugging:stacktrace"
,
"@com_google_absl//absl/debugging:symbolize"
,
"@com_google_absl//absl/strings"
,
"@com_google_absl//absl/types:any"
,
"@com_google_absl//absl/types:optional"
,
"@com_google_absl//absl/types:variant"
,
],
...
...
googletest/include/gtest/gtest-printers.h
View file @
07d4a6e9
...
...
@@ -113,8 +113,6 @@
#if GTEST_HAS_ABSL
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/variant.h"
#endif // GTEST_HAS_ABSL
namespace
testing
{
...
...
@@ -596,14 +594,42 @@ class UniversalPrinter {
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
>
class
UniversalPrinter
<
::
absl
::
o
ptional
<
T
>>
{
class
UniversalPrinter
<
O
ptional
<
T
>>
{
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
<<
'('
;
if
(
!
value
)
{
*
os
<<
"nullopt"
;
...
...
@@ -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
>
class
UniversalPrinter
<
::
absl
::
v
ariant
<
T
...
>>
{
class
UniversalPrinter
<
V
ariant
<
T
...
>>
{
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
<<
'('
;
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
<<
')'
;
}
...
...
@@ -629,14 +663,16 @@ class UniversalPrinter<::absl::variant<T...>> {
struct
Visitor
{
template
<
typename
U
>
void
operator
()(
const
U
&
u
)
const
{
*
os
<<
"'"
<<
GetTypeName
<
U
>
()
<<
"' with value "
;
*
os
<<
"'"
<<
GetTypeName
<
U
>
()
<<
"(index = "
<<
index
<<
")' with value "
;
UniversalPrint
(
u
,
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'
// elements, starting at address 'begin'.
...
...
googletest/include/gtest/internal/gtest-port.h
View file @
07d4a6e9
...
...
@@ -199,9 +199,18 @@
// suppressed (constant conditional).
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
// 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
// Matcher<absl::string_view>
// specializations.
// GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter<std::variant> or
// UniversalPrinter<absl::variant>
// specializations.
//
// Synchronization:
// Mutex, MutexLock, ThreadLocal, GetThreadCount()
...
...
@@ -2243,6 +2252,64 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
#endif // !defined(GTEST_INTERNAL_DEPRECATED)
#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
// is built with absl support.
...
...
@@ -2271,4 +2338,33 @@ using StringView = ::std::string_view;
# endif // __has_include
#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_
googletest/include/gtest/internal/gtest-type-util.h
View file @
07d4a6e9
...
...
@@ -64,34 +64,38 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) {
return
s
;
}
// GetTypeName<T>() returns a human-readable name of type T.
// 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
const
char
*
const
name
=
typeid
(
T
).
name
();
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
#if GTEST_HAS_RTTI
// GetTypeName(const std::type_info&) returns a human-readable name of type T.
inline
std
::
string
GetTypeName
(
const
std
::
type_info
&
type
)
{
const
char
*
const
name
=
type
.
name
();
#if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
int
status
=
0
;
// gcc's implementation of typeid(T).name() mangles the type name,
// so we have to demangle it.
#
if GTEST_HAS_CXXABI_H_
#if GTEST_HAS_CXXABI_H_
using
abi
::
__cxa_demangle
;
#
endif // GTEST_HAS_CXXABI_H_
#endif // GTEST_HAS_CXXABI_H_
char
*
const
readable_name
=
__cxa_demangle
(
name
,
nullptr
,
nullptr
,
&
status
);
const
std
::
string
name_str
(
status
==
0
?
readable_name
:
name
);
free
(
readable_name
);
return
CanonicalizeForStdLibVersioning
(
name_str
);
#
else
#else
return
name
;
#
endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
#
else
#endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
}
#
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>"
;
# endif // GTEST_HAS_RTTI
#endif // GTEST_HAS_RTTI
}
#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) {
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
)
{
abs
l
::
o
ptional
<
int
>
value
;
interna
l
::
O
ptional
<
int
>
value
;
EXPECT_EQ
(
"(nullopt)"
,
PrintToString
(
value
));
value
=
{
7
};
EXPECT_EQ
(
"(7)"
,
PrintToString
(
value
));
EXPECT_EQ
(
"(1.1)"
,
PrintToString
(
abs
l
::
o
ptional
<
double
>
{
1.1
}));
EXPECT_EQ
(
"(
\"
A
\"
)"
,
PrintToString
(
abs
l
::
o
ptional
<
std
::
string
>
{
"A"
}));
EXPECT_EQ
(
"(1.1)"
,
PrintToString
(
interna
l
::
O
ptional
<
double
>
{
1.1
}));
EXPECT_EQ
(
"(
\"
A
\"
)"
,
PrintToString
(
interna
l
::
O
ptional
<
std
::
string
>
{
"A"
}));
}
#endif // GTEST_INTERNAL_HAS_OPTIONAL
#if GTEST_INTERNAL_HAS_VARIANT
struct
NonPrintable
{
unsigned
char
contents
=
17
;
};
TEST
(
PrintOneofTest
,
Basic
)
{
using
Type
=
abs
l
::
v
ariant
<
int
,
StreamableInGlobal
,
NonPrintable
>
;
EXPECT_EQ
(
"('int' with value 7)"
,
PrintToString
(
Type
(
7
)));
EXPECT_EQ
(
"('StreamableInGlobal' with value StreamableInGlobal)"
,
using
Type
=
interna
l
::
V
ariant
<
int
,
StreamableInGlobal
,
NonPrintable
>
;
EXPECT_EQ
(
"('int
(index = 0)
' with value 7)"
,
PrintToString
(
Type
(
7
)));
EXPECT_EQ
(
"('StreamableInGlobal
(index = 1)
' with value StreamableInGlobal)"
,
PrintToString
(
Type
(
StreamableInGlobal
{})));
EXPECT_EQ
(
"('testing::gtest_printers_test::NonPrintable' with value
1-byte object
"
"<11>)"
,
"('testing::gtest_printers_test::NonPrintable
(index = 2)
' with value "
"
1-byte object
<11>)"
,
PrintToString
(
Type
(
NonPrintable
{})));
}
#endif // GTEST_
HAS_ABSL
#endif // GTEST_
INTERNAL_HAS_VARIANT
namespace
{
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