Let RTC_[D]CHECK_op accept arguments of different signedness
With this change, instead of
RTC_DCHECK_GE(unsigned_var, 17u);
we can simply write
RTC_DCHECK_GE(unsigned_var, 17);
or even
RTC_DCHECK_GE(unsigned_var, -17); // Always true.
and the mathematically sensible thing will happen.
Perhaps more importantly, we can replace checks like
// index is size_t, num_channels is int.
RTC_DCHECK(num_channels >= 0
&& index < static_cast<size_t>(num_channels));
or, even worse, just
// Surely num_channels isn't negative. That would be absurd!
RTC_DCHECK_LT(index, static_cast<size_t>(num_channels));
with simply
RTC_DCHECK_LT(index, num_channels);
In short, you no longer have to keep track of the signedness of the arguments, because the sensible thing will happen.
BUG=webrtc:6645
Review-Url: https://codereview.webrtc.org/2459793002
Cr-Commit-Position: refs/heads/master@{#14878}
This commit is contained in:
@ -437,6 +437,7 @@ if (rtc_include_tests) {
|
||||
"base/rollingaccumulator_unittest.cc",
|
||||
"base/rtccertificate_unittest.cc",
|
||||
"base/rtccertificategenerator_unittest.cc",
|
||||
"base/safe_compare_unittest.cc",
|
||||
"base/scopedptrcollection_unittest.cc",
|
||||
"base/sequenced_task_checker_unittest.cc",
|
||||
"base/sha1digest_unittest.cc",
|
||||
|
||||
@ -159,6 +159,7 @@ rtc_static_library("rtc_base_approved") {
|
||||
"ratetracker.h",
|
||||
"refcount.h",
|
||||
"refcountedobject.h",
|
||||
"safe_compare.h",
|
||||
"safe_conversions.h",
|
||||
"safe_conversions_impl.h",
|
||||
"sanitizer.h",
|
||||
|
||||
@ -36,6 +36,8 @@ NO_RETURN void rtc_FatalMessage(const char* file, int line, const char* msg);
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/base/safe_compare.h"
|
||||
|
||||
// The macros here print a message to stderr and abort under various
|
||||
// conditions. All will accept additional stream messages. For example:
|
||||
// RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar.";
|
||||
@ -97,9 +99,7 @@ namespace rtc {
|
||||
// values of the same types as |a| and |b| can't be compared with the given
|
||||
// operation, and that would evaluate |a| and |b| if evaluated.
|
||||
#define RTC_EAT_STREAM_PARAMETERS_OP(op, a, b) \
|
||||
RTC_EAT_STREAM_PARAMETERS(((void)sizeof(std::declval<decltype(a)>() \
|
||||
op std::declval<decltype(b)>()), \
|
||||
(void)(a), (void)(b)))
|
||||
RTC_EAT_STREAM_PARAMETERS(((void)rtc::safe_cmp::op(a, b)))
|
||||
|
||||
// RTC_CHECK dies with a fatal error if condition is not true. It is *not*
|
||||
// controlled by NDEBUG or anything else, so the check will be executed
|
||||
@ -158,35 +158,35 @@ std::string* MakeCheckOpString<std::string, std::string>(
|
||||
// The (int, int) specialization works around the issue that the compiler
|
||||
// will not instantiate the template version of the function on values of
|
||||
// unnamed enum type - see comment below.
|
||||
#define DEFINE_RTC_CHECK_OP_IMPL(name, op) \
|
||||
#define DEFINE_RTC_CHECK_OP_IMPL(name) \
|
||||
template <class t1, class t2> \
|
||||
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
|
||||
const char* names) { \
|
||||
if (v1 op v2) \
|
||||
if (rtc::safe_cmp::name(v1, v2)) \
|
||||
return NULL; \
|
||||
else \
|
||||
return rtc::MakeCheckOpString(v1, v2, names); \
|
||||
} \
|
||||
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
|
||||
if (v1 op v2) \
|
||||
if (rtc::safe_cmp::name(v1, v2)) \
|
||||
return NULL; \
|
||||
else \
|
||||
return rtc::MakeCheckOpString(v1, v2, names); \
|
||||
}
|
||||
DEFINE_RTC_CHECK_OP_IMPL(EQ, ==)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(NE, !=)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(LE, <=)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(LT, < )
|
||||
DEFINE_RTC_CHECK_OP_IMPL(GE, >=)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(GT, > )
|
||||
DEFINE_RTC_CHECK_OP_IMPL(Eq)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(Ne)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(Le)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(Lt)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(Ge)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(Gt)
|
||||
#undef DEFINE_RTC_CHECK_OP_IMPL
|
||||
|
||||
#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(EQ, ==, val1, val2)
|
||||
#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(NE, !=, val1, val2)
|
||||
#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(LE, <=, val1, val2)
|
||||
#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(LT, < , val1, val2)
|
||||
#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(GE, >=, val1, val2)
|
||||
#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(GT, > , val1, val2)
|
||||
#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(Eq, ==, val1, val2)
|
||||
#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(Ne, !=, val1, val2)
|
||||
#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(Le, <=, val1, val2)
|
||||
#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(Lt, <, val1, val2)
|
||||
#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(Ge, >=, val1, val2)
|
||||
#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(Gt, >, val1, val2)
|
||||
|
||||
// The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates
|
||||
// code in debug builds. It does reference the condition parameter in all cases,
|
||||
@ -201,12 +201,12 @@ DEFINE_RTC_CHECK_OP_IMPL(GT, > )
|
||||
#define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2)
|
||||
#else
|
||||
#define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition)
|
||||
#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(==, v1, v2)
|
||||
#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(!=, v1, v2)
|
||||
#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(<=, v1, v2)
|
||||
#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(<, v1, v2)
|
||||
#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(>=, v1, v2)
|
||||
#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(>, v1, v2)
|
||||
#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Eq, v1, v2)
|
||||
#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ne, v1, v2)
|
||||
#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Le, v1, v2)
|
||||
#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Lt, v1, v2)
|
||||
#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ge, v1, v2)
|
||||
#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Gt, v1, v2)
|
||||
#endif
|
||||
|
||||
// This is identical to LogMessageVoidify but in name.
|
||||
|
||||
180
webrtc/base/safe_compare.h
Normal file
180
webrtc/base/safe_compare.h
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
// This file defines six functions:
|
||||
//
|
||||
// rtc::safe_cmp::Eq // ==
|
||||
// rtc::safe_cmp::Ne // !=
|
||||
// rtc::safe_cmp::Lt // <
|
||||
// rtc::safe_cmp::Le // <=
|
||||
// rtc::safe_cmp::Gt // >
|
||||
// rtc::safe_cmp::Ge // >=
|
||||
//
|
||||
// They each accept two arguments of arbitrary types, and in almost all cases,
|
||||
// they simply call the appropriate comparison operator. However, if both
|
||||
// arguments are integers, they don't compare them using C++'s quirky rules,
|
||||
// but instead adhere to the true mathematical definitions. It is as if the
|
||||
// arguments were first converted to infinite-range signed integers, and then
|
||||
// compared, although of course nothing expensive like that actually takes
|
||||
// place. In practice, for signed/signed and unsigned/unsigned comparisons and
|
||||
// some mixed-signed comparisons with a compile-time constant, the overhead is
|
||||
// zero; in the remaining cases, it is just a few machine instructions (no
|
||||
// branches).
|
||||
|
||||
#ifndef WEBRTC_BASE_SAFE_COMPARE_H_
|
||||
#define WEBRTC_BASE_SAFE_COMPARE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace rtc {
|
||||
namespace safe_cmp {
|
||||
|
||||
namespace safe_cmp_impl {
|
||||
|
||||
template <size_t N>
|
||||
struct LargerIntImpl : std::false_type {};
|
||||
template <>
|
||||
struct LargerIntImpl<sizeof(int8_t)> : std::true_type {
|
||||
using type = int16_t;
|
||||
};
|
||||
template <>
|
||||
struct LargerIntImpl<sizeof(int16_t)> : std::true_type {
|
||||
using type = int32_t;
|
||||
};
|
||||
template <>
|
||||
struct LargerIntImpl<sizeof(int32_t)> : std::true_type {
|
||||
using type = int64_t;
|
||||
};
|
||||
|
||||
// LargerInt<T1, T2>::value is true iff there's a signed type that's larger
|
||||
// than T1 (and no larger than the larger of T2 and int*, for performance
|
||||
// reasons); and if there is such a type, LargerInt<T1, T2>::type is an alias
|
||||
// for it.
|
||||
template <typename T1, typename T2>
|
||||
struct LargerInt
|
||||
: LargerIntImpl<sizeof(T1) < sizeof(T2) || sizeof(T1) < sizeof(int*)
|
||||
? sizeof(T1)
|
||||
: 0> {};
|
||||
|
||||
template <typename T>
|
||||
inline typename std::make_unsigned<T>::type MakeUnsigned(T a) {
|
||||
return static_cast<typename std::make_unsigned<T>::type>(a);
|
||||
}
|
||||
|
||||
// Overload for when both T1 and T2 have the same signedness.
|
||||
template <typename Op,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename std::enable_if<std::is_signed<T1>::value ==
|
||||
std::is_signed<T2>::value>::type* = nullptr>
|
||||
inline bool Cmp(T1 a, T2 b) {
|
||||
return Op::Op(a, b);
|
||||
}
|
||||
|
||||
// Overload for signed - unsigned comparison that can be promoted to a bigger
|
||||
// signed type.
|
||||
template <typename Op,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename std::enable_if<std::is_signed<T1>::value &&
|
||||
std::is_unsigned<T2>::value &&
|
||||
LargerInt<T2, T1>::value>::type* = nullptr>
|
||||
inline bool Cmp(T1 a, T2 b) {
|
||||
return Op::Op(a, static_cast<typename LargerInt<T2, T1>::type>(b));
|
||||
}
|
||||
|
||||
// Overload for unsigned - signed comparison that can be promoted to a bigger
|
||||
// signed type.
|
||||
template <typename Op,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename std::enable_if<std::is_unsigned<T1>::value &&
|
||||
std::is_signed<T2>::value &&
|
||||
LargerInt<T1, T2>::value>::type* = nullptr>
|
||||
inline bool Cmp(T1 a, T2 b) {
|
||||
return Op::Op(static_cast<typename LargerInt<T1, T2>::type>(a), b);
|
||||
}
|
||||
|
||||
// Overload for signed - unsigned comparison that can't be promoted to a bigger
|
||||
// signed type.
|
||||
template <typename Op,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename std::enable_if<std::is_signed<T1>::value &&
|
||||
std::is_unsigned<T2>::value &&
|
||||
!LargerInt<T2, T1>::value>::type* = nullptr>
|
||||
inline bool Cmp(T1 a, T2 b) {
|
||||
return a < 0 ? Op::Op(-1, 0) : Op::Op(safe_cmp_impl::MakeUnsigned(a), b);
|
||||
}
|
||||
|
||||
// Overload for unsigned - signed comparison that can't be promoted to a bigger
|
||||
// signed type.
|
||||
template <typename Op,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename std::enable_if<std::is_unsigned<T1>::value &&
|
||||
std::is_signed<T2>::value &&
|
||||
!LargerInt<T1, T2>::value>::type* = nullptr>
|
||||
inline bool Cmp(T1 a, T2 b) {
|
||||
return b < 0 ? Op::Op(0, -1) : Op::Op(a, safe_cmp_impl::MakeUnsigned(b));
|
||||
}
|
||||
|
||||
#define RTC_SAFECMP_MAKE_OP(name, op) \
|
||||
struct name { \
|
||||
template <typename T1, typename T2> \
|
||||
static constexpr bool Op(T1 a, T2 b) { \
|
||||
return a op b; \
|
||||
} \
|
||||
};
|
||||
RTC_SAFECMP_MAKE_OP(EqOp, ==)
|
||||
RTC_SAFECMP_MAKE_OP(NeOp, !=)
|
||||
RTC_SAFECMP_MAKE_OP(LtOp, <)
|
||||
RTC_SAFECMP_MAKE_OP(LeOp, <=)
|
||||
RTC_SAFECMP_MAKE_OP(GtOp, >)
|
||||
RTC_SAFECMP_MAKE_OP(GeOp, >=)
|
||||
#undef RTC_SAFECMP_MAKE_OP
|
||||
|
||||
} // namespace safe_cmp_impl
|
||||
|
||||
#define RTC_SAFECMP_MAKE_FUN(name) \
|
||||
template < \
|
||||
typename T1, typename T2, \
|
||||
typename std::enable_if< \
|
||||
std::is_integral<typename std::remove_reference<T1>::type>::value && \
|
||||
std::is_integral<typename std::remove_reference<T2>::type>::value>:: \
|
||||
type* = nullptr> \
|
||||
inline bool name(T1 a, T2 b) { \
|
||||
return safe_cmp_impl::Cmp<safe_cmp_impl::name##Op>(a, b); \
|
||||
} \
|
||||
template <typename T1, typename T2, \
|
||||
typename std::enable_if< \
|
||||
!std::is_integral< \
|
||||
typename std::remove_reference<T1>::type>::value || \
|
||||
!std::is_integral<typename std::remove_reference<T2>::type>:: \
|
||||
value>::type* = nullptr> \
|
||||
inline bool name(T1&& a, T2&& b) { \
|
||||
return safe_cmp_impl::name##Op::Op(a, b); \
|
||||
}
|
||||
RTC_SAFECMP_MAKE_FUN(Eq)
|
||||
RTC_SAFECMP_MAKE_FUN(Ne)
|
||||
RTC_SAFECMP_MAKE_FUN(Lt)
|
||||
RTC_SAFECMP_MAKE_FUN(Le)
|
||||
RTC_SAFECMP_MAKE_FUN(Gt)
|
||||
RTC_SAFECMP_MAKE_FUN(Ge)
|
||||
#undef RTC_SAFECMP_MAKE_FUN
|
||||
|
||||
} // namespace safe_cmp
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_SAFE_COMPARE_H_
|
||||
379
webrtc/base/safe_compare_unittest.cc
Normal file
379
webrtc/base/safe_compare_unittest.cc
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright 2016 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 <limits>
|
||||
|
||||
#include "webrtc/base/safe_compare.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::uintmax_t umax = std::numeric_limits<std::uintmax_t>::max();
|
||||
constexpr std::intmax_t imin = std::numeric_limits<std::intmax_t>::min();
|
||||
constexpr std::intmax_t m1 = -1;
|
||||
|
||||
// m1 and umax have the same representation because we use 2's complement
|
||||
// arithmetic, so naive casting will confuse them.
|
||||
static_assert(static_cast<std::uintmax_t>(m1) == umax, "");
|
||||
static_assert(m1 == static_cast<std::intmax_t>(umax), "");
|
||||
|
||||
std::pair<int, int> p1(1, 1);
|
||||
std::pair<int, int> p2(1, 2);
|
||||
|
||||
} // 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).
|
||||
bool TestLessThanRef( int a, int b) { return a < b; }
|
||||
bool TestLessThanRef( unsigned a, unsigned b) { return a < b; }
|
||||
bool TestLessThanSafe( int a, int b) { return safe_cmp::Lt(a, b); }
|
||||
bool TestLessThanSafe(unsigned a, unsigned b) { return safe_cmp::Lt(a, b); }
|
||||
bool TestLessThanSafe(unsigned a, int b) { return safe_cmp::Lt(a, b); }
|
||||
bool TestLessThanSafe( int a, unsigned b) { return safe_cmp::Lt(a, b); }
|
||||
|
||||
// For these, we expect the *Ref and *Safe functions to result in identical
|
||||
// code, except for the ones that compare a signed variable with an unsigned
|
||||
// constant; in that case, the *Ref function does an unsigned comparison (fast
|
||||
// but incorrect) and the *Safe function spends a few extra instructions on
|
||||
// doing it right.
|
||||
bool TestLessThan17Ref( int a) { return a < 17; }
|
||||
bool TestLessThan17Ref( unsigned a) { return a < 17; }
|
||||
bool TestLessThan17uRef( int a) { return static_cast<unsigned>(a) < 17u; }
|
||||
bool TestLessThan17uRef( unsigned a) { return a < 17u; }
|
||||
bool TestLessThan17Safe( int a) { return safe_cmp::Lt(a, 17); }
|
||||
bool TestLessThan17Safe( unsigned a) { return safe_cmp::Lt(a, 17); }
|
||||
bool TestLessThan17uSafe( int a) { return safe_cmp::Lt(a, 17u); }
|
||||
bool TestLessThan17uSafe(unsigned a) { return safe_cmp::Lt(a, 17u); }
|
||||
|
||||
// Cases where we can't convert to a larger signed type.
|
||||
bool TestLessThanMax( intmax_t a, uintmax_t b) { return safe_cmp::Lt(a, b); }
|
||||
bool TestLessThanMax(uintmax_t a, intmax_t b) { return safe_cmp::Lt(a, b); }
|
||||
bool TestLessThanMax17u( intmax_t a) { return safe_cmp::Lt(a, uintmax_t{17}); }
|
||||
bool TestLessThanMax17( uintmax_t a) { return safe_cmp::Lt(a, intmax_t{17}); }
|
||||
|
||||
// Cases where the compiler should be able to compute the result at compile
|
||||
// time.
|
||||
bool TestLessThanConst1() { return safe_cmp::Lt( -1, 1); }
|
||||
bool TestLessThanConst2() { return safe_cmp::Lt( m1, umax); }
|
||||
bool TestLessThanConst3() { return safe_cmp::Lt(umax, imin); }
|
||||
bool TestLessThanConst4(unsigned a) { return safe_cmp::Lt( a, -1); }
|
||||
bool TestLessThanConst5(unsigned a) { return safe_cmp::Lt(-1, a); }
|
||||
bool TestLessThanConst6(unsigned a) { return safe_cmp::Lt( a, a); }
|
||||
|
||||
// clang-format on
|
||||
|
||||
TEST(SafeCmpTest, Eq) {
|
||||
EXPECT_FALSE(safe_cmp::Eq(-1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Eq(-1, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2, -1));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2u, -1));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Eq(1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Eq(1, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Eq(1u, 2));
|
||||
EXPECT_FALSE(safe_cmp::Eq(1u, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2, 1));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2, 1u));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2u, 1));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2u, 1u));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Eq(2, 2));
|
||||
EXPECT_TRUE(safe_cmp::Eq(2, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Eq(2u, 2));
|
||||
EXPECT_TRUE(safe_cmp::Eq(2u, 2u));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Eq(imin, imin));
|
||||
EXPECT_FALSE(safe_cmp::Eq(imin, umax));
|
||||
EXPECT_FALSE(safe_cmp::Eq(umax, imin));
|
||||
EXPECT_TRUE(safe_cmp::Eq(umax, umax));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Eq(m1, m1));
|
||||
EXPECT_FALSE(safe_cmp::Eq(m1, umax));
|
||||
EXPECT_FALSE(safe_cmp::Eq(umax, m1));
|
||||
EXPECT_TRUE(safe_cmp::Eq(umax, umax));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Eq(1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Eq(1, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Eq(1.0, 2));
|
||||
EXPECT_FALSE(safe_cmp::Eq(1.0, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2, 1));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2, 1.0));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2.0, 1));
|
||||
EXPECT_FALSE(safe_cmp::Eq(2.0, 1.0));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Eq(2, 2));
|
||||
EXPECT_TRUE(safe_cmp::Eq(2, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Eq(2.0, 2));
|
||||
EXPECT_TRUE(safe_cmp::Eq(2.0, 2.0));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Eq(p1, p1));
|
||||
EXPECT_FALSE(safe_cmp::Eq(p1, p2));
|
||||
EXPECT_FALSE(safe_cmp::Eq(p2, p1));
|
||||
EXPECT_TRUE(safe_cmp::Eq(p2, p2));
|
||||
}
|
||||
|
||||
TEST(SafeCmpTest, Ne) {
|
||||
EXPECT_TRUE(safe_cmp::Ne(-1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ne(-1, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2, -1));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2u, -1));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Ne(1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ne(1, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Ne(1u, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ne(1u, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2, 1u));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2u, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2u, 1u));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Ne(2, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ne(2, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Ne(2u, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ne(2u, 2u));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Ne(imin, imin));
|
||||
EXPECT_TRUE(safe_cmp::Ne(imin, umax));
|
||||
EXPECT_TRUE(safe_cmp::Ne(umax, imin));
|
||||
EXPECT_FALSE(safe_cmp::Ne(umax, umax));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Ne(m1, m1));
|
||||
EXPECT_TRUE(safe_cmp::Ne(m1, umax));
|
||||
EXPECT_TRUE(safe_cmp::Ne(umax, m1));
|
||||
EXPECT_FALSE(safe_cmp::Ne(umax, umax));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Ne(1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ne(1, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Ne(1.0, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ne(1.0, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2, 1.0));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2.0, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ne(2.0, 1.0));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Ne(2, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ne(2, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Ne(2.0, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ne(2.0, 2.0));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Ne(p1, p1));
|
||||
EXPECT_TRUE(safe_cmp::Ne(p1, p2));
|
||||
EXPECT_TRUE(safe_cmp::Ne(p2, p1));
|
||||
EXPECT_FALSE(safe_cmp::Ne(p2, p2));
|
||||
}
|
||||
|
||||
TEST(SafeCmpTest, Lt) {
|
||||
EXPECT_TRUE(safe_cmp::Lt(-1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Lt(-1, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, -1));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2u, -1));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Lt(1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Lt(1, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Lt(1u, 2));
|
||||
EXPECT_TRUE(safe_cmp::Lt(1u, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 1));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 1u));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2u, 1));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2u, 1u));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 2));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2u, 2));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2u, 2u));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Lt(imin, imin));
|
||||
EXPECT_TRUE(safe_cmp::Lt(imin, umax));
|
||||
EXPECT_FALSE(safe_cmp::Lt(umax, imin));
|
||||
EXPECT_FALSE(safe_cmp::Lt(umax, umax));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Lt(m1, m1));
|
||||
EXPECT_TRUE(safe_cmp::Lt(m1, umax));
|
||||
EXPECT_FALSE(safe_cmp::Lt(umax, m1));
|
||||
EXPECT_FALSE(safe_cmp::Lt(umax, umax));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Lt(1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Lt(1, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Lt(1.0, 2));
|
||||
EXPECT_TRUE(safe_cmp::Lt(1.0, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 1));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 1.0));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2.0, 1));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2.0, 1.0));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 2));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2.0, 2));
|
||||
EXPECT_FALSE(safe_cmp::Lt(2.0, 2.0));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Lt(p1, p1));
|
||||
EXPECT_TRUE(safe_cmp::Lt(p1, p2));
|
||||
EXPECT_FALSE(safe_cmp::Lt(p2, p1));
|
||||
EXPECT_FALSE(safe_cmp::Lt(p2, p2));
|
||||
}
|
||||
|
||||
TEST(SafeCmpTest, Le) {
|
||||
EXPECT_TRUE(safe_cmp::Le(-1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(-1, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Le(2, -1));
|
||||
EXPECT_FALSE(safe_cmp::Le(2u, -1));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Le(1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(1, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Le(1u, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(1u, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Le(2, 1));
|
||||
EXPECT_FALSE(safe_cmp::Le(2, 1u));
|
||||
EXPECT_FALSE(safe_cmp::Le(2u, 1));
|
||||
EXPECT_FALSE(safe_cmp::Le(2u, 1u));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Le(2, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(2, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Le(2u, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(2u, 2u));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Le(imin, imin));
|
||||
EXPECT_TRUE(safe_cmp::Le(imin, umax));
|
||||
EXPECT_FALSE(safe_cmp::Le(umax, imin));
|
||||
EXPECT_TRUE(safe_cmp::Le(umax, umax));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Le(m1, m1));
|
||||
EXPECT_TRUE(safe_cmp::Le(m1, umax));
|
||||
EXPECT_FALSE(safe_cmp::Le(umax, m1));
|
||||
EXPECT_TRUE(safe_cmp::Le(umax, umax));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Le(1, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(1, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Le(1.0, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(1.0, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Le(2, 1));
|
||||
EXPECT_FALSE(safe_cmp::Le(2, 1.0));
|
||||
EXPECT_FALSE(safe_cmp::Le(2.0, 1));
|
||||
EXPECT_FALSE(safe_cmp::Le(2.0, 1.0));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Le(2, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(2, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Le(2.0, 2));
|
||||
EXPECT_TRUE(safe_cmp::Le(2.0, 2.0));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Le(p1, p1));
|
||||
EXPECT_TRUE(safe_cmp::Le(p1, p2));
|
||||
EXPECT_FALSE(safe_cmp::Le(p2, p1));
|
||||
EXPECT_TRUE(safe_cmp::Le(p2, p2));
|
||||
}
|
||||
|
||||
TEST(SafeCmpTest, Gt) {
|
||||
EXPECT_FALSE(safe_cmp::Gt(-1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(-1, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2, -1));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2u, -1));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Gt(1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(1, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Gt(1u, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(1u, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2, 1));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2, 1u));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2u, 1));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2u, 1u));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Gt(2, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(2, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Gt(2u, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(2u, 2u));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Gt(imin, imin));
|
||||
EXPECT_FALSE(safe_cmp::Gt(imin, umax));
|
||||
EXPECT_TRUE(safe_cmp::Gt(umax, imin));
|
||||
EXPECT_FALSE(safe_cmp::Gt(umax, umax));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Gt(m1, m1));
|
||||
EXPECT_FALSE(safe_cmp::Gt(m1, umax));
|
||||
EXPECT_TRUE(safe_cmp::Gt(umax, m1));
|
||||
EXPECT_FALSE(safe_cmp::Gt(umax, umax));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Gt(1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(1, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Gt(1.0, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(1.0, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2, 1));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2, 1.0));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2.0, 1));
|
||||
EXPECT_TRUE(safe_cmp::Gt(2.0, 1.0));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Gt(2, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(2, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Gt(2.0, 2));
|
||||
EXPECT_FALSE(safe_cmp::Gt(2.0, 2.0));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Gt(p1, p1));
|
||||
EXPECT_FALSE(safe_cmp::Gt(p1, p2));
|
||||
EXPECT_TRUE(safe_cmp::Gt(p2, p1));
|
||||
EXPECT_FALSE(safe_cmp::Gt(p2, p2));
|
||||
}
|
||||
|
||||
TEST(SafeCmpTest, Ge) {
|
||||
EXPECT_FALSE(safe_cmp::Ge(-1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ge(-1, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, -1));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2u, -1));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Ge(1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ge(1, 2u));
|
||||
EXPECT_FALSE(safe_cmp::Ge(1u, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ge(1u, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 1u));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2u, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2u, 1u));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 2u));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2u, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2u, 2u));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Ge(imin, imin));
|
||||
EXPECT_FALSE(safe_cmp::Ge(imin, umax));
|
||||
EXPECT_TRUE(safe_cmp::Ge(umax, imin));
|
||||
EXPECT_TRUE(safe_cmp::Ge(umax, umax));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Ge(m1, m1));
|
||||
EXPECT_FALSE(safe_cmp::Ge(m1, umax));
|
||||
EXPECT_TRUE(safe_cmp::Ge(umax, m1));
|
||||
EXPECT_TRUE(safe_cmp::Ge(umax, umax));
|
||||
|
||||
EXPECT_FALSE(safe_cmp::Ge(1, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ge(1, 2.0));
|
||||
EXPECT_FALSE(safe_cmp::Ge(1.0, 2));
|
||||
EXPECT_FALSE(safe_cmp::Ge(1.0, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 1.0));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2.0, 1));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2.0, 1.0));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2, 2.0));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2.0, 2));
|
||||
EXPECT_TRUE(safe_cmp::Ge(2.0, 2.0));
|
||||
|
||||
EXPECT_TRUE(safe_cmp::Ge(p1, p1));
|
||||
EXPECT_FALSE(safe_cmp::Ge(p1, p2));
|
||||
EXPECT_TRUE(safe_cmp::Ge(p2, p1));
|
||||
EXPECT_TRUE(safe_cmp::Ge(p2, p2));
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
@ -134,7 +134,7 @@ int DtmfToneGenerator::Init(int fs, int event, int attenuation) {
|
||||
}
|
||||
|
||||
// Look up oscillator coefficient for low and high frequencies.
|
||||
RTC_DCHECK_LE(0u, fs_index);
|
||||
RTC_DCHECK_LE(0, fs_index);
|
||||
RTC_DCHECK_GT(arraysize(kCoeff1), fs_index);
|
||||
RTC_DCHECK_GT(arraysize(kCoeff2), fs_index);
|
||||
RTC_DCHECK_LE(0, event);
|
||||
@ -149,7 +149,7 @@ int DtmfToneGenerator::Init(int fs, int event, int attenuation) {
|
||||
amplitude_ = kAmplitude[attenuation];
|
||||
|
||||
// Initialize sample history.
|
||||
RTC_DCHECK_LE(0u, fs_index);
|
||||
RTC_DCHECK_LE(0, fs_index);
|
||||
RTC_DCHECK_GT(arraysize(kInitValue1), fs_index);
|
||||
RTC_DCHECK_GT(arraysize(kInitValue2), fs_index);
|
||||
RTC_DCHECK_LE(0, event);
|
||||
|
||||
Reference in New Issue
Block a user