Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2523)

Unified Diff: webrtc/base/optional.h

Issue 2704483002: Add a PrintTo function for rtc::Optional to aid with testing. (Closed)
Patch Set: Moved OptionalPrintObjectBytes into optional.h, added an #ifdef UNIT_TEST. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | webrtc/base/optional.cc » ('j') | webrtc/base/optional.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/base/optional.h
diff --git a/webrtc/base/optional.h b/webrtc/base/optional.h
index f5354ee0f25fdb6eabcf6fa367e3db64152681ee..c80d5a4d4eeac633fd01c5732f6531697122d405 100644
--- a/webrtc/base/optional.h
+++ b/webrtc/base/optional.h
@@ -15,6 +15,11 @@
#include <memory>
#include <utility>
+#ifdef UNIT_TEST
kwiberg-webrtc 2017/02/18 18:50:47 Who defines this? I couldn't find it in our tree.
kjellander_webrtc 2017/02/19 09:29:19 It comes from gtest: https://cs.chromium.org/chrom
kwiberg-webrtc 2017/02/19 13:14:15 Aha. Excellent!
kjellander_webrtc 2017/02/20 07:24:20 I don't have time to put in more work than this fo
+#include <iomanip>
+#include <ostream>
+#endif // UNIT_TEST
+
#include "webrtc/base/array_view.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/sanitizer.h"
@@ -25,7 +30,9 @@ namespace optional_internal {
#if RTC_HAS_ASAN
-// This is a non-inlined function. The optimizer can't see inside it.
+// This is a non-inlined function. The optimizer can't see inside it. It
+// prevents the compiler from generating optimized code that reads value_ even
+// if it is unset. Although safe, this causes memory sanitizers to complain.
void* FunctionThatDoesNothingImpl(void*);
template <typename T>
@@ -34,6 +41,12 @@ inline T* FunctionThatDoesNothing(T* x) {
FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x)));
}
+template <typename T>
+inline const T* FunctionThatDoesNothing(const T* x) {
+ return const_cast<const T*>(reinterpret_cast<T*>(
+ FunctionThatDoesNothingImpl(reinterpret_cast<void*>(const_cast<T*>(x)))));
kwiberg-webrtc 2017/02/18 18:50:47 The outermost const_cast is unnecessary.
ossu 2017/02/20 11:02:24 That is true. But also, I think the whole function
kwiberg-webrtc 2017/02/20 11:45:31 Acknowledged.
+}
+
#else
template <typename T>
@@ -296,6 +309,98 @@ class Optional final {
};
};
+#ifdef UNIT_TEST
+namespace optional_internal {
+
+// Checks if there's a valid PrintTo(const T&, std::ostream*) call for T.
+template <typename T>
+struct HasPrintTo {
+ private:
+ struct No {};
+
+ template <typename T2>
+ static auto Test(const T2& obj)
+ -> decltype(PrintTo(obj, std::declval<std::ostream*>()));
+
+ template <typename>
+ static No Test(...);
+
+ public:
+ static constexpr bool value =
+ !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
+};
+
+// Checks if there's a valid operator<<(std::ostream&, const T&) call for T.
+template <typename T>
+struct HasOstreamOperator {
+ private:
+ struct No {};
+
+ template <typename T2>
+ static auto Test(const T2& obj)
+ -> decltype(std::declval<std::ostream&>() << obj);
+
+ template <typename>
+ static No Test(...);
+
+ public:
+ static constexpr bool value =
+ !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
+};
+
+// Prefer using PrintTo to print the object.
+template <typename T>
+typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper(
+ const T& value,
+ std::ostream* os) {
+ PrintTo(value, os);
+}
+
+// Fall back to operator<<(std::ostream&, ...) if it exists.
+template <typename T>
+typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
+ void>::type
+OptionalPrintToHelper(const T& value, std::ostream* os) {
+ *os << value;
+}
+
+inline void OptionalPrintObjectBytes(const unsigned char* bytes,
+ size_t size,
+ std::ostream* os) {
+ *os << "<optional with " << size << "-byte object [";
+ for (size_t i = 0; i != size; ++i) {
+ *os << (i == 0 ? "" : ((i & 1) ? "-" : " "));
+ *os << std::hex << std::setw(2) << std::setfill('0')
+ << static_cast<int>(bytes[i]);
+ }
+ *os << "]>";
+}
+
+// As a final back-up, just print the contents of the objcets byte-wise.
+template <typename T>
+typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
+ void>::type
+OptionalPrintToHelper(const T& value, std::ostream* os) {
+ OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value),
+ sizeof(value), os);
+}
+
+} // namespace optional_internal
+
+// PrintTo is used by gtest to print out the results of tests. We want to ensure
+// the object contained in an Optional can be printed out if it's set, while
+// avoiding touching the object's storage if it is undefined.
+template <typename T>
+void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) {
+ if (opt) {
+ optional_internal::OptionalPrintToHelper(*opt, os);
+ } else {
+ *os << "<empty optional>";
+ }
+}
+
+#endif // UNIT_TEST
+
} // namespace rtc
#endif // WEBRTC_BASE_OPTIONAL_H_
« no previous file with comments | « no previous file | webrtc/base/optional.cc » ('j') | webrtc/base/optional.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698