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

Side by Side Diff: webrtc/base/optional.h

Issue 2704483002: Add a PrintTo function for rtc::Optional to aid with testing. (Closed)
Patch Set: Reworked PrintTo so that it's always implemented, or gtest will print out uninitialized bytes. 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 unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/base/optional.cc » ('j') | webrtc/base/optional.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #ifndef WEBRTC_BASE_OPTIONAL_H_ 11 #ifndef WEBRTC_BASE_OPTIONAL_H_
12 #define WEBRTC_BASE_OPTIONAL_H_ 12 #define WEBRTC_BASE_OPTIONAL_H_
13 13
14 #include <algorithm> 14 #include <algorithm>
15 #include <memory> 15 #include <memory>
16 #include <ostream>
16 #include <utility> 17 #include <utility>
17 18
18 #include "webrtc/base/array_view.h" 19 #include "webrtc/base/array_view.h"
19 #include "webrtc/base/checks.h" 20 #include "webrtc/base/checks.h"
20 #include "webrtc/base/sanitizer.h" 21 #include "webrtc/base/sanitizer.h"
21 22
22 namespace rtc { 23 namespace rtc {
23 24
24 namespace optional_internal { 25 namespace optional_internal {
25 26
26 #if RTC_HAS_ASAN 27 #if RTC_HAS_ASAN
27 28
28 // This is a non-inlined function. The optimizer can't see inside it. 29 // This is a non-inlined function. The optimizer can't see inside it. It
30 // prevents the compiler from generating optimized code that reads value_ even
31 // if it is unset. Although safe, this causes memory sanitizers to complain.
29 void* FunctionThatDoesNothingImpl(void*); 32 void* FunctionThatDoesNothingImpl(void*);
30 33
31 template <typename T> 34 template <typename T>
32 inline T* FunctionThatDoesNothing(T* x) { 35 inline T* FunctionThatDoesNothing(T* x) {
33 return reinterpret_cast<T*>( 36 return reinterpret_cast<T*>(
34 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x))); 37 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x)));
35 } 38 }
36 39
40 template <typename T>
41 inline const T* FunctionThatDoesNothing(const T* x) {
42 return const_cast<const T*>(reinterpret_cast<T*>(
43 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(const_cast<T*>(x)))));
44 }
kwiberg-webrtc 2017/02/17 13:50:17 Hmm. Wouldn't it be more general to just have one
ossu 2017/02/17 14:02:19 Nope, the problem was that the compiler disallowed
45
37 #else 46 #else
38 47
39 template <typename T> 48 template <typename T>
40 inline T* FunctionThatDoesNothing(T* x) { return x; } 49 inline T* FunctionThatDoesNothing(T* x) { return x; }
41 50
42 #endif 51 #endif
43 52
44 } // namespace optional_internal 53 } // namespace optional_internal
45 54
46 // Simple std::optional-wannabe. It either contains a T or not. 55 // Simple std::optional-wannabe. It either contains a T or not.
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 char empty_; 298 char empty_;
290 // By placing value_ in a union, we get to manage its construction and 299 // By placing value_ in a union, we get to manage its construction and
291 // destruction manually: the Optional constructors won't automatically 300 // destruction manually: the Optional constructors won't automatically
292 // construct it, and the Optional destructor won't automatically destroy 301 // construct it, and the Optional destructor won't automatically destroy
293 // it. Basically, this just allocates a properly sized and aligned block of 302 // it. Basically, this just allocates a properly sized and aligned block of
294 // memory in which we can manually put a T with placement new. 303 // memory in which we can manually put a T with placement new.
295 T value_; 304 T value_;
296 }; 305 };
297 }; 306 };
298 307
308 namespace optional_internal {
309
310 // Checks if there's a valid PrintTo(const T&, std::ostream*) call for T.
311 template <typename T>
312 struct HasPrintTo {
313 private:
314 struct No {};
315
316 template <typename T2>
317 static auto Test(const T2& obj)
318 -> decltype(PrintTo(obj, std::declval<std::ostream*>()));
319
320 template <typename>
321 static No Test(...);
322
323 public:
324 static constexpr bool value =
325 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
326 };
327
328 // Checks if there's a valid operator<<(std::ostream&, const T&) call for T.
329 template <typename T>
330 struct HasOstreamOperator {
331 private:
332 struct No {};
333
334 template <typename T2>
335 static auto Test(const T2& obj)
336 -> decltype(std::declval<std::ostream&>() << obj);
337
338 template <typename>
339 static No Test(...);
340
341 public:
342 static constexpr bool value =
343 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
344 };
345
346 // Prefer using PrintTo to print the object.
347 template <typename T>
348 typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper(
349 const T& value,
350 std::ostream* os) {
351 PrintTo(value, os);
352 }
353
354 // Fall back to operator<<(std::ostream&, ...) if it exists.
355 template <typename T>
356 typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
357 void>::type
358 OptionalPrintToHelper(const T& value, std::ostream* os) {
359 *os << value;
360 }
361
362 void OptionalPrintObjectBytes(const unsigned char* bytes,
363 size_t size,
kwiberg-webrtc 2017/02/17 13:50:17 ArrayView?
ossu 2017/02/17 14:02:20 Not certain the extra dependency is worth it, hone
364 std::ostream* os);
365
366 // As a final back-up, just print the contents of the objcets byte-wise.
367 template <typename T>
368 typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
369 void>::type
370 OptionalPrintToHelper(const T& value, std::ostream* os) {
371 OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value),
372 sizeof(value), os);
373 }
374
375 } // namespace optional_internal
376
377 // PrintTo is used by gtest to print out the results of tests. We want to ensure
378 // the object contained in an Optional can be printed out if it's set, while
379 // avoiding touching the object's storage if it is undefined.
380 template <typename T>
381 void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) {
382 if (opt) {
383 optional_internal::OptionalPrintToHelper(*opt, os);
384 } else {
385 *os << "<empty optional>";
386 }
387 }
388
299 } // namespace rtc 389 } // namespace rtc
300 390
301 #endif // WEBRTC_BASE_OPTIONAL_H_ 391 #endif // WEBRTC_BASE_OPTIONAL_H_
OLDNEW
« 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