| Index: webrtc/base/safe_minmax_unittest.cc | 
| diff --git a/webrtc/base/safe_minmax_unittest.cc b/webrtc/base/safe_minmax_unittest.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..6276478e63ef9a82774663ede68a9cbebc9d8a10 | 
| --- /dev/null | 
| +++ b/webrtc/base/safe_minmax_unittest.cc | 
| @@ -0,0 +1,141 @@ | 
| +/* | 
| + *  Copyright 2017 The WebRTC Project Authors. All rights reserved. | 
| + * | 
| + *  Use of this source code is governed by a BSD-style license | 
| + *  that can be found in the LICENSE file in the root of the source | 
| + *  tree. An additional intellectual property rights grant can be found | 
| + *  in the file PATENTS.  All contributing project authors may | 
| + *  be found in the AUTHORS file in the root of the source tree. | 
| + */ | 
| + | 
| +#include <algorithm> | 
| +#include <limits> | 
| + | 
| +#include "webrtc/base/safe_minmax.h" | 
| +#include "webrtc/test/gtest.h" | 
| + | 
| +namespace rtc { | 
| + | 
| +namespace { | 
| + | 
| +// Functions that check that SafeMin() and SafeMax() return the specified type. | 
| +// The functions that end in "R" use an explicitly given return type. | 
| + | 
| +template <typename T1, typename T2, typename Tmin, typename Tmax> | 
| +constexpr bool TypeCheckMinMax() { | 
| +  return std::is_same<decltype(SafeMin(std::declval<T1>(), std::declval<T2>())), | 
| +                      Tmin>::value && | 
| +         std::is_same<decltype(SafeMax(std::declval<T1>(), std::declval<T2>())), | 
| +                      Tmax>::value; | 
| +} | 
| + | 
| +template <typename T1, typename T2, typename R> | 
| +constexpr bool TypeCheckMinR() { | 
| +  return std::is_same< | 
| +      decltype(SafeMin<R>(std::declval<T1>(), std::declval<T2>())), R>::value; | 
| +} | 
| + | 
| +template <typename T1, typename T2, typename R> | 
| +constexpr bool TypeCheckMaxR() { | 
| +  return std::is_same< | 
| +      decltype(SafeMax<R>(std::declval<T1>(), std::declval<T2>())), R>::value; | 
| +} | 
| + | 
| +// clang-format off | 
| + | 
| +// SafeMin/SafeMax: Check that all combinations of signed/unsigned 8/64 bits | 
| +// give the correct default result type. | 
| +static_assert(TypeCheckMinMax<  int8_t,   int8_t,   int8_t,   int8_t>(), ""); | 
| +static_assert(TypeCheckMinMax<  int8_t,  uint8_t,   int8_t,  uint8_t>(), ""); | 
| +static_assert(TypeCheckMinMax<  int8_t,  int64_t,  int64_t,  int64_t>(), ""); | 
| +static_assert(TypeCheckMinMax<  int8_t, uint64_t,   int8_t, uint64_t>(), ""); | 
| +static_assert(TypeCheckMinMax< uint8_t,   int8_t,   int8_t,  uint8_t>(), ""); | 
| +static_assert(TypeCheckMinMax< uint8_t,  uint8_t,  uint8_t,  uint8_t>(), ""); | 
| +static_assert(TypeCheckMinMax< uint8_t,  int64_t,  int64_t,  int64_t>(), ""); | 
| +static_assert(TypeCheckMinMax< uint8_t, uint64_t,  uint8_t, uint64_t>(), ""); | 
| +static_assert(TypeCheckMinMax< int64_t,   int8_t,  int64_t,  int64_t>(), ""); | 
| +static_assert(TypeCheckMinMax< int64_t,  uint8_t,  int64_t,  int64_t>(), ""); | 
| +static_assert(TypeCheckMinMax< int64_t,  int64_t,  int64_t,  int64_t>(), ""); | 
| +static_assert(TypeCheckMinMax< int64_t, uint64_t,  int64_t, uint64_t>(), ""); | 
| +static_assert(TypeCheckMinMax<uint64_t,   int8_t,   int8_t, uint64_t>(), ""); | 
| +static_assert(TypeCheckMinMax<uint64_t,  uint8_t,  uint8_t, uint64_t>(), ""); | 
| +static_assert(TypeCheckMinMax<uint64_t,  int64_t,  int64_t, uint64_t>(), ""); | 
| +static_assert(TypeCheckMinMax<uint64_t, uint64_t, uint64_t, uint64_t>(), ""); | 
| + | 
| +using ld = long double; | 
| + | 
| +// SafeMin/SafeMax: Check that some floating-point combinations give the | 
| +// correct result type. | 
| +static_assert(TypeCheckMinMax<   int,    int,    int,    int>(), ""); | 
| +static_assert(TypeCheckMinMax<   int,  float,  float,  float>(), ""); | 
| +static_assert(TypeCheckMinMax<   int, double, double, double>(), ""); | 
| +static_assert(TypeCheckMinMax<   int,     ld,     ld,     ld>(), ""); | 
| +static_assert(TypeCheckMinMax< float,    int,  float,  float>(), ""); | 
| +static_assert(TypeCheckMinMax< float,  float,  float,  float>(), ""); | 
| +static_assert(TypeCheckMinMax< float, double, double, double>(), ""); | 
| +static_assert(TypeCheckMinMax< float,     ld,     ld,     ld>(), ""); | 
| +static_assert(TypeCheckMinMax<double,    int, double, double>(), ""); | 
| +static_assert(TypeCheckMinMax<double,  float, double, double>(), ""); | 
| +static_assert(TypeCheckMinMax<double, double, double, double>(), ""); | 
| +static_assert(TypeCheckMinMax<double,     ld,     ld,     ld>(), ""); | 
| +static_assert(TypeCheckMinMax<    ld,    int,     ld,     ld>(), ""); | 
| +static_assert(TypeCheckMinMax<    ld,  float,     ld,     ld>(), ""); | 
| +static_assert(TypeCheckMinMax<    ld, double,     ld,     ld>(), ""); | 
| +static_assert(TypeCheckMinMax<    ld,     ld,     ld,     ld>(), ""); | 
| + | 
| +// clang-format on | 
| + | 
| +// SafeMin/SafeMax: Check some cases of explicitly specified return type. The | 
| +// commented-out lines give compilation errors due to the requested return type | 
| +// being too small. | 
| +static_assert(TypeCheckMinR<int8_t, int8_t, int16_t>(), ""); | 
| +static_assert(TypeCheckMinR<int8_t, int8_t, float>(), ""); | 
| +static_assert(TypeCheckMinR<uint32_t, uint64_t, uint32_t>(), ""); | 
| +static_assert(TypeCheckMaxR<uint64_t, float, float>(), ""); | 
| +// static_assert(TypeCheckMaxR<uint64_t, double, float>(), ""); | 
| +static_assert(TypeCheckMaxR<uint32_t, int32_t, uint32_t>(), ""); | 
| +// static_assert(TypeCheckMaxR<uint32_t, int32_t, int32_t>(), ""); | 
| + | 
| +template <typename T1, typename T2, typename Tmin, typename Tmax> | 
| +constexpr bool CheckMinMax(T1 a, T2 b, Tmin min, Tmax max) { | 
| +  return TypeCheckMinMax<T1, T2, Tmin, Tmax>() && SafeMin(a, b) == min && | 
| +         SafeMax(a, b) == max; | 
| +} | 
| + | 
| +// SafeMin/SafeMax: Check a few values. | 
| +static_assert(CheckMinMax(int8_t{1}, int8_t{-1}, int8_t{-1}, int8_t{1}), ""); | 
| +static_assert(CheckMinMax(uint8_t{1}, int8_t{-1}, int8_t{-1}, uint8_t{1}), ""); | 
| +static_assert(CheckMinMax(uint8_t{5}, uint64_t{2}, uint8_t{2}, uint64_t{5}), | 
| +              ""); | 
| +static_assert(CheckMinMax(std::numeric_limits<int32_t>::min(), | 
| +                          std::numeric_limits<uint32_t>::max(), | 
| +                          std::numeric_limits<int32_t>::min(), | 
| +                          std::numeric_limits<uint32_t>::max()), | 
| +              ""); | 
| +static_assert(CheckMinMax(std::numeric_limits<int32_t>::min(), | 
| +                          std::numeric_limits<uint16_t>::max(), | 
| +                          std::numeric_limits<int32_t>::min(), | 
| +                          int32_t{std::numeric_limits<uint16_t>::max()}), | 
| +              ""); | 
| +static_assert(CheckMinMax(1.f, 2, 1.f, 2.f), ""); | 
| +static_assert(CheckMinMax(1.f, 0.0, 0.0, 1.0), ""); | 
| + | 
| +}  // namespace | 
| + | 
| +// clang-format off | 
| + | 
| +// These functions aren't used in the tests, but it's useful to look at the | 
| +// compiler output for them, and verify that (1) the same-signedness *Safe | 
| +// functions result in exactly the same code as their *Ref counterparts, and | 
| +// that (2) the mixed-signedness *Safe functions have just a few extra | 
| +// arithmetic and logic instructions (but no extra control flow instructions). | 
| +int32_t  TestMinRef(  int32_t a,  int32_t b) { return std::min(a, b); } | 
| +uint32_t TestMinRef( uint32_t a, uint32_t b) { return std::min(a, b); } | 
| +int32_t  TestMinSafe( int32_t a,  int32_t b) { return SafeMin(a, b); } | 
| +int32_t  TestMinSafe( int32_t a, uint32_t b) { return SafeMin(a, b); } | 
| +int32_t  TestMinSafe(uint32_t a,  int32_t b) { return SafeMin(a, b); } | 
| +uint32_t TestMinSafe(uint32_t a, uint32_t b) { return SafeMin(a, b); } | 
| + | 
| +// clang-format on | 
| + | 
| +}  // namespace rtc | 
|  |