2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-04 07:55:18 +00:00

[#2830] static cast enum to int

This commit is contained in:
Razvan Becheriu
2023-06-08 20:52:02 +03:00
parent ff6eaacd1b
commit 753f6d03c4
12 changed files with 88 additions and 57 deletions

View File

@@ -375,7 +375,11 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
} else if (optarg_text == "multi") { } else if (optarg_text == "multi") {
single_thread_mode_ = false; single_thread_mode_ = false;
} else { } else {
isc_throw(InvalidParameter, "value of thread mode (-g) '" << optarg << "' is wrong - should be '-g single' or '-g multi'"); if (optarg) {
isc_throw(InvalidParameter, "value of thread mode (-g) '" << optarg << "' is wrong - should be '-g single' or '-g multi'");
} else {
isc_throw(InvalidParameter, "value of thread mode (-g) is wrong - should be '-g single' or '-g multi'");
}
} }
break; break;
} }

View File

@@ -1641,15 +1641,14 @@ TestControl::sendRequest6(const std::vector<uint8_t>& template_buf,
} }
} }
// Set IA_NA // Set IA_NA
boost::shared_ptr<Option6IA> opt_ia_na_advertise = OptionPtr opt_ia_na_advertise = advertise_pkt6->getOption(D6O_IA_NA);
boost::static_pointer_cast<Option6IA>(advertise_pkt6->getOption(D6O_IA_NA));
if (!opt_ia_na_advertise) { if (!opt_ia_na_advertise) {
isc_throw(Unexpected, "DHCPv6 IA_NA option not found in received " isc_throw(Unexpected, "DHCPv6 IA_NA option not found in received "
"packet"); "packet");
} }
size_t addr_offset = getRequestedIpOffset(); size_t addr_offset = getRequestedIpOffset();
boost::shared_ptr<LocalizedOption> boost::shared_ptr<LocalizedOption>
opt_ia_na(new LocalizedOption(opt_ia_na_advertise, addr_offset)); opt_ia_na(new LocalizedOption(Option::V6, D6O_IA_NA, opt_ia_na_advertise->getData(), addr_offset));
if (!opt_ia_na->valid()) { if (!opt_ia_na->valid()) {
isc_throw(BadValue, "Option IA_NA in advertise packet is invalid"); isc_throw(BadValue, "Option IA_NA in advertise packet is invalid");
} }

View File

@@ -74,7 +74,7 @@ TEST(Element, TypeNameConversion) {
EXPECT_EQ("map", Element::typeToName(Element::map)); EXPECT_EQ("map", Element::typeToName(Element::map));
EXPECT_EQ("null", Element::typeToName(Element::null)); EXPECT_EQ("null", Element::typeToName(Element::null));
EXPECT_EQ("any", Element::typeToName(Element::any)); EXPECT_EQ("any", Element::typeToName(Element::any));
EXPECT_EQ("unknown", Element::typeToName((Element::types)123)); EXPECT_EQ("unknown", Element::typeToName(static_cast<Element::types>(123)));
} }
TEST(Element, from_and_to_json) { TEST(Element, from_and_to_json) {

View File

@@ -215,7 +215,7 @@ public:
BackendSelector::UNSPEC(), BackendSelector::UNSPEC(),
const ServerSelector& server_selector = const ServerSelector& server_selector =
ServerSelector::ALL()) const { ServerSelector::ALL()) const {
int property; int property = 0;
// If the selector is specified, this method will pick the appropriate // If the selector is specified, this method will pick the appropriate
// backend and will call getProperty method on this backend. If the // backend and will call getProperty method on this backend. If the
@@ -247,7 +247,8 @@ public:
BackendSelector::UNSPEC(), BackendSelector::UNSPEC(),
const ServerSelector& server_selector = const ServerSelector& server_selector =
ServerSelector::ALL()) const { ServerSelector::ALL()) const {
int property; int property = 0;
getPropertyPtrConst<int, const std::string&, int> getPropertyPtrConst<int, const std::string&, int>
(&TestConfigBackend::getProperty, backend_selector, server_selector, (&TestConfigBackend::getProperty, backend_selector, server_selector,
property, property_name, property_value); property, property_name, property_value);

View File

@@ -52,7 +52,11 @@ IPRangePermutation::next(bool& done) {
// addresses between the cursor and the end of the range have been already // addresses between the cursor and the end of the range have been already
// returned by this function. Therefore we focus on the remaining cursor-1 // returned by this function. Therefore we focus on the remaining cursor-1
// addresses. Let's get random address from this sub-range. // addresses. Let's get random address from this sub-range.
std::uniform_int_distribution<uint64_t> dist(0, static_cast<uint64_t>(cursor_ - 1)); uint64_t max_limit = std::numeric_limits<uint64_t>::max();
if ((cursor_ - 1) < isc::util::int128_t(max_limit)) {
max_limit = static_cast<uint64_t>(cursor_ - 1);
}
std::uniform_int_distribution<uint64_t> dist(0, max_limit);
auto next_loc = dist(generator_); auto next_loc = dist(generator_);
IOAddress next_loc_address = IOAddress::IPV4_ZERO_ADDRESS(); IOAddress next_loc_address = IOAddress::IPV4_ZERO_ADDRESS();

View File

@@ -412,7 +412,7 @@ Message::setHeaderFlag(const HeaderFlag flag, const bool on) {
if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) { if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) {
isc_throw(InvalidParameter, isc_throw(InvalidParameter,
"Message::getHeaderFlag:: Invalid flag is specified: " << "Message::getHeaderFlag:: Invalid flag is specified: " <<
"0x" << std::hex << flag); "0x" << std::hex << static_cast<int>(flag));
} }
if (on) { if (on) {
impl_->flags_ |= flag; impl_->flags_ |= flag;
@@ -997,7 +997,7 @@ Message::clear(Mode mode) {
void void
Message::appendSection(const Section section, const Message& source) { Message::appendSection(const Section section, const Message& source) {
if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) { if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
isc_throw(OutOfRange, "Invalid message section: " << section); isc_throw(OutOfRange, "Invalid message section: " << static_cast<int>(section));
} }
if (section == SECTION_QUESTION) { if (section == SECTION_QUESTION) {
@@ -1145,7 +1145,7 @@ Message::endQuestion() const {
const SectionIterator<RRsetPtr> const SectionIterator<RRsetPtr>
Message::beginSection(const Section section) const { Message::beginSection(const Section section) const {
if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) { if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
isc_throw(OutOfRange, "Invalid message section: " << section); isc_throw(OutOfRange, "Invalid message section: " << static_cast<int>(section));
} }
if (section == SECTION_QUESTION) { if (section == SECTION_QUESTION) {
isc_throw(InvalidMessageSection, isc_throw(InvalidMessageSection,

View File

@@ -1694,7 +1694,7 @@ TEST_F(TokenTest, pkt4Fields) {
// Unknown field fails // Unknown field fails
clearStack(); clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::FieldType(100)))); ASSERT_NO_THROW(t_.reset(new TokenPkt4(static_cast<TokenPkt4::FieldType>(100))));
EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError); EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
// Check that the debug output was correct. Add the strings // Check that the debug output was correct. Add the strings
@@ -1739,7 +1739,7 @@ TEST_F(TokenTest, pkt6Fields) {
// Unknown field fails // Unknown field fails
clearStack(); clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::FieldType(100)))); ASSERT_NO_THROW(t_.reset(new TokenPkt6(static_cast<TokenPkt6::FieldType>(100))));
EXPECT_THROW(t_->evaluate(*pkt6_, values_), EvalTypeError); EXPECT_THROW(t_->evaluate(*pkt6_, values_), EvalTypeError);
// Check that the debug output was correct. Add the strings // Check that the debug output was correct. Add the strings

View File

@@ -162,7 +162,7 @@ TokenInt8ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
} }
stringstream tmp; stringstream tmp;
tmp << static_cast<int32_t>(*(reinterpret_cast<int8_t*>(const_cast<char*>(op.data())))); tmp << static_cast<int32_t>(*(reinterpret_cast<int8_t*>(op.data())));
op = tmp.str(); op = tmp.str();
values.push(op); values.push(op);
@@ -191,8 +191,7 @@ TokenInt16ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
} }
stringstream tmp; stringstream tmp;
int16_t value = 0; int16_t value = static_cast<int16_t>(readUint16(const_cast<const char*>(op.data()), size));
memcpy(&value, op.data(), size);
tmp << value; tmp << value;
op = tmp.str(); op = tmp.str();
values.push(op); values.push(op);
@@ -222,8 +221,7 @@ TokenInt32ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
} }
stringstream tmp; stringstream tmp;
int32_t value = 0; int32_t value = static_cast<int32_t>(readUint32(const_cast<const char*>(op.data()), size));
memcpy(&value, op.data(), size);
tmp << value; tmp << value;
op = tmp.str(); op = tmp.str();
values.push(op); values.push(op);
@@ -253,7 +251,7 @@ TokenUInt8ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
} }
stringstream tmp; stringstream tmp;
tmp << static_cast<uint32_t>(*(reinterpret_cast<uint8_t*>(const_cast<char*>(op.data())))); tmp << static_cast<uint32_t>(*(reinterpret_cast<uint8_t*>(op.data())));
op = tmp.str(); op = tmp.str();
values.push(op); values.push(op);
@@ -282,8 +280,7 @@ TokenUInt16ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
} }
stringstream tmp; stringstream tmp;
uint16_t value = 0; uint16_t value = readUint16(const_cast<const char*>(op.data()), size);
memcpy(&value, op.data(), size);
tmp << value; tmp << value;
op = tmp.str(); op = tmp.str();
values.push(op); values.push(op);
@@ -313,8 +310,7 @@ TokenUInt32ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
} }
stringstream tmp; stringstream tmp;
uint32_t value = 0; uint32_t value = readUint32(const_cast<const char*>(op.data()), size);
memcpy(&value, op.data(), size);
tmp << value; tmp << value;
op = tmp.str(); op = tmp.str();
values.push(op); values.push(op);
@@ -379,7 +375,7 @@ TokenOption::pushFailure(ValueStack& values) {
TokenRelay4Option::TokenRelay4Option(const uint16_t option_code, TokenRelay4Option::TokenRelay4Option(const uint16_t option_code,
const RepresentationType& rep_type) const RepresentationType& rep_type)
:TokenOption(option_code, rep_type) { : TokenOption(option_code, rep_type) {
} }
OptionPtr TokenRelay4Option::getOption(Pkt& pkt) { OptionPtr TokenRelay4Option::getOption(Pkt& pkt) {
@@ -461,8 +457,7 @@ TokenPkt::evaluate(Pkt& pkt, ValueStack& values) {
break; break;
default: default:
isc_throw(EvalTypeError, "Bad meta data specified: " isc_throw(EvalTypeError, "Bad meta data specified: " << static_cast<int>(type_));
<< static_cast<int>(type_) );
} }
if (is_binary) { if (is_binary) {
@@ -538,8 +533,7 @@ TokenPkt4::evaluate(Pkt& pkt, ValueStack& values) {
type_str = "transid"; type_str = "transid";
break; break;
default: default:
isc_throw(EvalTypeError, "Bad field specified: " isc_throw(EvalTypeError, "Bad field specified: " << static_cast<int>(type_));
<< static_cast<int>(type_) );
} }
} catch (const std::bad_cast&) { } catch (const std::bad_cast&) {
@@ -582,8 +576,7 @@ TokenPkt6::evaluate(Pkt& pkt, ValueStack& values) {
break; break;
} }
default: default:
isc_throw(EvalTypeError, "Bad field specified: " isc_throw(EvalTypeError, "Bad field specified: " << static_cast<int>(type_));
<< static_cast<int>(type_) );
} }
} catch (const std::bad_cast&) { } catch (const std::bad_cast&) {
@@ -1043,13 +1036,13 @@ TokenMember::evaluate(Pkt& pkt, ValueStack& values) {
TokenVendor::TokenVendor(Option::Universe u, uint32_t vendor_id, RepresentationType repr, TokenVendor::TokenVendor(Option::Universe u, uint32_t vendor_id, RepresentationType repr,
uint16_t option_code) uint16_t option_code)
:TokenOption(option_code, repr), universe_(u), vendor_id_(vendor_id), : TokenOption(option_code, repr), universe_(u), vendor_id_(vendor_id),
field_(option_code ? SUBOPTION : EXISTS) { field_(option_code ? SUBOPTION : EXISTS) {
} }
TokenVendor::TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field) TokenVendor::TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field)
:TokenOption(0, TokenOption::HEXADECIMAL), universe_(u), vendor_id_(vendor_id), : TokenOption(0, TokenOption::HEXADECIMAL), universe_(u), vendor_id_(vendor_id),
field_(field) { field_(field) {
if (field_ == EXISTS) { if (field_ == EXISTS) {
representation_type_ = TokenOption::EXISTS; representation_type_ = TokenOption::EXISTS;
} }
@@ -1155,12 +1148,12 @@ OptionPtr TokenVendor::getOption(Pkt& pkt) {
TokenVendorClass::TokenVendorClass(Option::Universe u, uint32_t vendor_id, TokenVendorClass::TokenVendorClass(Option::Universe u, uint32_t vendor_id,
RepresentationType repr) RepresentationType repr)
:TokenVendor(u, vendor_id, repr, 0), index_(0) { : TokenVendor(u, vendor_id, repr, 0), index_(0) {
} }
TokenVendorClass::TokenVendorClass(Option::Universe u, uint32_t vendor_id, TokenVendorClass::TokenVendorClass(Option::Universe u, uint32_t vendor_id,
FieldType field, uint16_t index) FieldType field, uint16_t index)
:TokenVendor(u, vendor_id, TokenOption::HEXADECIMAL, 0), index_(index) { : TokenVendor(u, vendor_id, TokenOption::HEXADECIMAL, 0), index_(index) {
field_ = field; field_ = field;
} }
@@ -1261,7 +1254,7 @@ void TokenVendorClass::evaluate(Pkt& pkt, ValueStack& values) {
} }
TokenInteger::TokenInteger(const uint32_t value) TokenInteger::TokenInteger(const uint32_t value)
:TokenString(EvalContext::fromUint32(value)), int_value_(value) { : TokenString(EvalContext::fromUint32(value)), int_value_(value) {
} }
OptionPtr OptionPtr

View File

@@ -117,7 +117,7 @@ public:
/// ///
/// @param str constant string to be represented. /// @param str constant string to be represented.
TokenString(const std::string& str) TokenString(const std::string& str)
:value_(str){ : value_(str){
} }
/// @brief Token evaluation (puts value of the constant string on the stack) /// @brief Token evaluation (puts value of the constant string on the stack)
@@ -474,7 +474,7 @@ public:
/// @param rep_type Token representation type. /// @param rep_type Token representation type.
TokenRelay6Option(const int8_t nest_level, const uint16_t option_code, TokenRelay6Option(const int8_t nest_level, const uint16_t option_code,
const RepresentationType& rep_type) const RepresentationType& rep_type)
:TokenOption(option_code, rep_type), nest_level_(nest_level) {} : TokenOption(option_code, rep_type), nest_level_(nest_level) {}
/// @brief Returns nest-level /// @brief Returns nest-level
/// ///
@@ -676,7 +676,7 @@ public:
/// @param nest_level the nesting level for which relay to examine. /// @param nest_level the nesting level for which relay to examine.
/// @param type which field to extract. /// @param type which field to extract.
TokenRelay6Field(const int8_t nest_level, const FieldType type) TokenRelay6Field(const int8_t nest_level, const FieldType type)
: nest_level_(nest_level), type_(type) {} : nest_level_(nest_level), type_(type) {}
/// @brief Extracts the specified field from the requested relay /// @brief Extracts the specified field from the requested relay
/// ///
@@ -1017,7 +1017,7 @@ public:
/// ///
/// @param client_class client class name /// @param client_class client class name
TokenMember(const std::string& client_class) TokenMember(const std::string& client_class)
:client_class_(client_class){ : client_class_(client_class){
} }
/// @brief Token evaluation (check if client_class_ was added to /// @brief Token evaluation (check if client_class_ was added to

View File

@@ -65,6 +65,7 @@ TcpConnection::TcpConnection(asiolink::IOService& io_service,
connection_pool_(connection_pool), connection_pool_(connection_pool),
acceptor_callback_(acceptor_callback), acceptor_callback_(acceptor_callback),
connection_filter_(connection_filter), connection_filter_(connection_filter),
read_max_(read_max),
input_buf_(read_max) { input_buf_(read_max) {
if (!tls_context) { if (!tls_context) {
tcp_socket_.reset(new asiolink::TCPSocket<SocketCallback>(io_service)); tcp_socket_.reset(new asiolink::TCPSocket<SocketCallback>(io_service));

View File

@@ -76,7 +76,7 @@ writeUint16(uint16_t value, void* buffer, size_t length) {
/// ///
/// \return Value of 32-bit unsigned integer /// \return Value of 32-bit unsigned integer
inline uint32_t inline uint32_t
readUint32(const uint8_t* buffer, size_t length) { readUint32(const void* buffer, size_t length) {
if (length < sizeof(uint32_t)) { if (length < sizeof(uint32_t)) {
isc_throw(isc::OutOfRange, isc_throw(isc::OutOfRange,
"Length (" << length << ") of buffer is insufficient " << "Length (" << length << ") of buffer is insufficient " <<
@@ -93,6 +93,32 @@ readUint32(const uint8_t* buffer, size_t length) {
return (result); return (result);
} }
/// \brief Write Unsigned 32-Bit Integer to Buffer
///
/// \param value 32-bit value to convert
/// \param buffer Data buffer at least four bytes long into which the 32-bit
/// value is written in network-byte order.
/// \param length Length of the data buffer.
///
/// \return pointer to the next byte after stored value
inline uint8_t*
writeUint32(uint32_t value, void* buffer, size_t length) {
if (length < sizeof(uint32_t)) {
isc_throw(isc::OutOfRange,
"Length (" << length << ") of buffer is insufficient " <<
"to write a uint32_t");
}
uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
byte_buffer[0] = static_cast<uint8_t>((value & 0xff000000U) >> 24);
byte_buffer[1] = static_cast<uint8_t>((value & 0x00ff0000U) >> 16);
byte_buffer[2] = static_cast<uint8_t>((value & 0x0000ff00U) >> 8);
byte_buffer[3] = static_cast<uint8_t>((value & 0x000000ffU));
return (byte_buffer + sizeof(uint32_t));
}
/// \brief Read Unsigned 64-Bit Integer from Buffer /// \brief Read Unsigned 64-Bit Integer from Buffer
/// ///
/// \param buffer Data buffer at least four bytes long of which the first four /// \param buffer Data buffer at least four bytes long of which the first four
@@ -102,7 +128,7 @@ readUint32(const uint8_t* buffer, size_t length) {
/// ///
/// \return Value of 64-bit unsigned integer /// \return Value of 64-bit unsigned integer
inline uint64_t inline uint64_t
readUint64(const uint8_t* buffer, size_t length) { readUint64(const void* buffer, size_t length) {
if (length < sizeof(uint64_t)) { if (length < sizeof(uint64_t)) {
isc_throw(isc::OutOfRange, isc_throw(isc::OutOfRange,
"Length (" << length << ") of buffer is insufficient " << "Length (" << length << ") of buffer is insufficient " <<
@@ -120,34 +146,37 @@ readUint64(const uint8_t* buffer, size_t length) {
result |= (static_cast<uint64_t>(byte_buffer[6])) << 8; result |= (static_cast<uint64_t>(byte_buffer[6])) << 8;
result |= (static_cast<uint64_t>(byte_buffer[7])); result |= (static_cast<uint64_t>(byte_buffer[7]));
return (result); return (result);
} }
/// \brief Write Unsigned 32-Bit Integer to Buffer /// \brief Write Unsigned 64-Bit Integer to Buffer
/// ///
/// \param value 32-bit value to convert /// \param value 64-bit value to convert
/// \param buffer Data buffer at least four bytes long into which the 32-bit /// \param buffer Data buffer at least four bytes long into which the 64-bit
/// value is written in network-byte order. /// value is written in network-byte order.
/// \param length Length of the data buffer. /// \param length Length of the data buffer.
/// ///
/// \return pointer to the next byte after stored value /// \return pointer to the next byte after stored value
inline uint8_t* inline uint8_t*
writeUint32(uint32_t value, uint8_t* buffer, size_t length) { writeUint64(uint64_t value, void* buffer, size_t length) {
if (length < sizeof(uint32_t)) { if (length < sizeof(uint64_t)) {
isc_throw(isc::OutOfRange, isc_throw(isc::OutOfRange,
"Length (" << length << ") of buffer is insufficient " << "Length (" << length << ") of buffer is insufficient " <<
"to write a uint32_t"); "to write a uint64_t");
} }
uint8_t* byte_buffer = static_cast<uint8_t*>(buffer); uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
byte_buffer[0] = static_cast<uint8_t>((value & 0xff000000U) >> 24); byte_buffer[0] = static_cast<uint8_t>((value & 0xff00000000000000UL) >> 56);
byte_buffer[1] = static_cast<uint8_t>((value & 0x00ff0000U) >> 16); byte_buffer[1] = static_cast<uint8_t>((value & 0x00ff000000000000UL) >> 48);
byte_buffer[2] = static_cast<uint8_t>((value & 0x0000ff00U) >> 8); byte_buffer[2] = static_cast<uint8_t>((value & 0x0000ff0000000000UL) >> 40);
byte_buffer[3] = static_cast<uint8_t>((value & 0x000000ffU)); byte_buffer[3] = static_cast<uint8_t>((value & 0x000000ff00000000UL) >> 32);
byte_buffer[4] = static_cast<uint8_t>((value & 0x00000000ff000000UL) >> 24);
byte_buffer[5] = static_cast<uint8_t>((value & 0x0000000000ff0000UL) >> 16);
byte_buffer[6] = static_cast<uint8_t>((value & 0x000000000000ff00UL) >> 8);
byte_buffer[7] = static_cast<uint8_t>((value & 0x00000000000000ffUL));
return (byte_buffer + sizeof(uint32_t)); return (byte_buffer + sizeof(uint64_t));
} }
} // namespace util } // namespace util

View File

@@ -37,7 +37,7 @@ TEST(BigintTest, int128) {
EXPECT_EQ(16, int128_t(65) / int128_t(4)); EXPECT_EQ(16, int128_t(65) / int128_t(4));
// Check that dividing by zero throws. // Check that dividing by zero throws.
EXPECT_THROW_MSG(int128_t(1) / 0, std::overflow_error, "Integer Division by zero."); EXPECT_THROW(int128_t(1) / 0, std::overflow_error);
// Check that underflowing results in a negative number for int128_t. // Check that underflowing results in a negative number for int128_t.
EXPECT_EQ(-1, int128_t(0) - 1); EXPECT_EQ(-1, int128_t(0) - 1);
@@ -73,7 +73,7 @@ TEST(BigintTest, uint128) {
EXPECT_EQ(16, uint128_t(65) / uint128_t(4)); EXPECT_EQ(16, uint128_t(65) / uint128_t(4));
// Check that dividing by zero throws. // Check that dividing by zero throws.
EXPECT_THROW_MSG(uint128_t(1) / 0, std::overflow_error, "Integer Division by zero."); EXPECT_THROW(uint128_t(1) / 0, std::overflow_error);
// Check that underflowing results in a positive number for uint128_t. // Check that underflowing results in a positive number for uint128_t.
EXPECT_LT(0, uint128_t(0) - 1); EXPECT_LT(0, uint128_t(0) - 1);