| /* | |
| * Copyright 2026 WebAssembly Community Group participants | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include <cstdint> | |
| #include <limits> | |
| #include <sstream> | |
| #include <vector> | |
| #include "support/iu64.h" | |
| #include "gtest/gtest.h" | |
| using namespace wasm; | |
| TEST(IU64Test, DefaultConstruct) { | |
| IU64 x; | |
| EXPECT_EQ(x.value, 0u); | |
| EXPECT_FALSE(x.negative); | |
| EXPECT_EQ(x, IU64(0)); | |
| } | |
| TEST(IU64Test, ConstructFromUnsigned32) { | |
| uint32_t zero = 0; | |
| uint32_t one = 1; | |
| uint32_t mid = 12345678; | |
| uint32_t maxU32 = std::numeric_limits<uint32_t>::max(); | |
| IU64 iZero(zero); | |
| EXPECT_EQ(iZero.value, 0u); | |
| EXPECT_FALSE(iZero.negative); | |
| IU64 iOne(one); | |
| EXPECT_EQ(iOne.value, 1u); | |
| EXPECT_FALSE(iOne.negative); | |
| IU64 iMid(mid); | |
| EXPECT_EQ(iMid.value, mid); | |
| EXPECT_FALSE(iMid.negative); | |
| IU64 iMax(maxU32); | |
| EXPECT_EQ(iMax.value, uint64_t(maxU32)); | |
| EXPECT_FALSE(iMax.negative); | |
| } | |
| TEST(IU64Test, ConstructFromSigned32) { | |
| int32_t zero = 0; | |
| int32_t one = 1; | |
| int32_t maxI32 = std::numeric_limits<int32_t>::max(); | |
| int32_t negOne = -1; | |
| int32_t negMid = -12345678; | |
| int32_t minI32 = std::numeric_limits<int32_t>::min(); | |
| IU64 iZero(zero); | |
| EXPECT_EQ(iZero.value, 0u); | |
| EXPECT_FALSE(iZero.negative); | |
| IU64 iOne(one); | |
| EXPECT_EQ(iOne.value, 1u); | |
| EXPECT_FALSE(iOne.negative); | |
| IU64 iMax(maxI32); | |
| EXPECT_EQ(iMax.value, uint64_t(maxI32)); | |
| EXPECT_FALSE(iMax.negative); | |
| IU64 iNegOne(negOne); | |
| EXPECT_EQ(iNegOne.value, 1u); | |
| EXPECT_TRUE(iNegOne.negative); | |
| IU64 iNegMid(negMid); | |
| EXPECT_EQ(iNegMid.value, 12345678u); | |
| EXPECT_TRUE(iNegMid.negative); | |
| IU64 iMin(minI32); | |
| EXPECT_EQ(iMin.value, 2147483648ULL); | |
| EXPECT_TRUE(iMin.negative); | |
| } | |
| TEST(IU64Test, ConstructFromUnsigned64) { | |
| uint64_t zero = 0; | |
| uint64_t one = 1; | |
| uint64_t maxU32 = std::numeric_limits<uint32_t>::max(); | |
| uint64_t maxI64 = std::numeric_limits<int64_t>::max(); | |
| uint64_t highBitOnly = uint64_t(1) << 63; | |
| uint64_t maxU64 = std::numeric_limits<uint64_t>::max(); | |
| IU64 iZero(zero); | |
| EXPECT_EQ(iZero.value, 0u); | |
| EXPECT_FALSE(iZero.negative); | |
| IU64 iOne(one); | |
| EXPECT_EQ(iOne.value, 1u); | |
| EXPECT_FALSE(iOne.negative); | |
| IU64 iMaxU32(maxU32); | |
| EXPECT_EQ(iMaxU32.value, maxU32); | |
| EXPECT_FALSE(iMaxU32.negative); | |
| IU64 iMaxI64(maxI64); | |
| EXPECT_EQ(iMaxI64.value, maxI64); | |
| EXPECT_FALSE(iMaxI64.negative); | |
| IU64 iHighBit(highBitOnly); | |
| EXPECT_EQ(iHighBit.value, highBitOnly); | |
| EXPECT_FALSE(iHighBit.negative); | |
| IU64 iMaxU64(maxU64); | |
| EXPECT_EQ(iMaxU64.value, maxU64); | |
| EXPECT_FALSE(iMaxU64.negative); | |
| } | |
| TEST(IU64Test, ConstructFromSigned64) { | |
| int64_t zero = 0; | |
| int64_t one = 1; | |
| int64_t maxI64 = std::numeric_limits<int64_t>::max(); | |
| int64_t negOne = -1; | |
| int64_t minI64 = std::numeric_limits<int64_t>::min(); | |
| int64_t minI64PlusOne = std::numeric_limits<int64_t>::min() + 1; | |
| IU64 iZero(zero); | |
| EXPECT_EQ(iZero.value, 0u); | |
| EXPECT_FALSE(iZero.negative); | |
| IU64 iOne(one); | |
| EXPECT_EQ(iOne.value, 1u); | |
| EXPECT_FALSE(iOne.negative); | |
| IU64 iMax(maxI64); | |
| EXPECT_EQ(iMax.value, uint64_t(maxI64)); | |
| EXPECT_FALSE(iMax.negative); | |
| IU64 iNegOne(negOne); | |
| EXPECT_EQ(iNegOne.value, 1u); | |
| EXPECT_TRUE(iNegOne.negative); | |
| IU64 iMin(minI64); | |
| EXPECT_EQ(iMin.value, uint64_t(1) << 63); | |
| EXPECT_TRUE(iMin.negative); | |
| IU64 iMinPlusOne(minI64PlusOne); | |
| EXPECT_EQ(iMinPlusOne.value, uint64_t(std::numeric_limits<int64_t>::max())); | |
| EXPECT_TRUE(iMinPlusOne.negative); | |
| } | |
| TEST(IU64Test, EqualityAndInequality) { | |
| EXPECT_EQ(IU64(int32_t(0)), IU64(uint32_t(0))); | |
| EXPECT_EQ(IU64(int32_t(0)), IU64(int64_t(0))); | |
| EXPECT_EQ(IU64(int32_t(0)), IU64(uint64_t(0))); | |
| EXPECT_EQ(IU64(int32_t(42)), IU64(uint32_t(42))); | |
| EXPECT_EQ(IU64(int32_t(42)), IU64(int64_t(42))); | |
| EXPECT_EQ(IU64(int32_t(42)), IU64(uint64_t(42))); | |
| EXPECT_EQ(IU64(int32_t(-42)), IU64(int64_t(-42))); | |
| EXPECT_EQ(IU64(std::numeric_limits<int32_t>::min()), | |
| IU64(int64_t(std::numeric_limits<int32_t>::min()))); | |
| EXPECT_NE(IU64(int32_t(1)), IU64(int32_t(-1))); | |
| EXPECT_NE(IU64(uint64_t(0xffffffffffffffffULL)), IU64(int64_t(-1))); | |
| EXPECT_NE(IU64(std::numeric_limits<int64_t>::min()), IU64(uint64_t(1) << 63)); | |
| } | |
| TEST(IU64Test, TotalOrdering) { | |
| std::vector<IU64> sortedValues = { | |
| IU64(std::numeric_limits<int64_t>::min()), | |
| IU64(std::numeric_limits<int64_t>::min() + 1), | |
| IU64(int64_t(-0x100000000LL)), | |
| IU64(std::numeric_limits<int32_t>::min()), | |
| IU64(int32_t(-12345)), | |
| IU64(int64_t(-2)), | |
| IU64(int64_t(-1)), | |
| IU64(0), | |
| IU64(1), | |
| IU64(2), | |
| IU64(int32_t(12345)), | |
| IU64(std::numeric_limits<int32_t>::max()), | |
| IU64(uint64_t(std::numeric_limits<int32_t>::max()) + 1), | |
| IU64(std::numeric_limits<uint32_t>::max()), | |
| IU64(uint64_t(std::numeric_limits<uint32_t>::max()) + 1), | |
| IU64(std::numeric_limits<int64_t>::max() - 1), | |
| IU64(std::numeric_limits<int64_t>::max()), | |
| IU64(uint64_t(std::numeric_limits<int64_t>::max()) + 1), | |
| IU64(std::numeric_limits<uint64_t>::max() - 1), | |
| IU64(std::numeric_limits<uint64_t>::max()), | |
| }; | |
| for (size_t i = 0; i < sortedValues.size(); ++i) { | |
| for (size_t j = 0; j < sortedValues.size(); ++j) { | |
| const auto& a = sortedValues[i]; | |
| const auto& b = sortedValues[j]; | |
| if (i < j) { | |
| EXPECT_LT(a, b); | |
| EXPECT_LE(a, b); | |
| EXPECT_GT(b, a); | |
| EXPECT_GE(b, a); | |
| EXPECT_NE(a, b); | |
| EXPECT_FALSE(a == b); | |
| EXPECT_FALSE(b < a); | |
| } else if (i == j) { | |
| EXPECT_EQ(a, b); | |
| EXPECT_LE(a, b); | |
| EXPECT_GE(a, b); | |
| EXPECT_FALSE(a < b); | |
| EXPECT_FALSE(a > b); | |
| EXPECT_FALSE(a != b); | |
| } else { | |
| EXPECT_GT(a, b); | |
| EXPECT_GE(a, b); | |
| EXPECT_LT(b, a); | |
| EXPECT_LE(b, a); | |
| EXPECT_NE(a, b); | |
| EXPECT_FALSE(a == b); | |
| EXPECT_FALSE(a < b); | |
| } | |
| } | |
| } | |
| } | |
| TEST(IU64Test, NumericLimits) { | |
| EXPECT_TRUE(std::numeric_limits<IU64>::is_specialized); | |
| EXPECT_TRUE(std::numeric_limits<IU64>::is_signed); | |
| EXPECT_TRUE(std::numeric_limits<IU64>::is_integer); | |
| EXPECT_EQ(std::numeric_limits<IU64>::min(), | |
| IU64(std::numeric_limits<int64_t>::min())); | |
| EXPECT_EQ(std::numeric_limits<IU64>::lowest(), | |
| IU64(std::numeric_limits<int64_t>::min())); | |
| EXPECT_EQ(std::numeric_limits<IU64>::max(), | |
| IU64(std::numeric_limits<uint64_t>::max())); | |
| } | |
| TEST(IU64Test, StreamOutput) { | |
| auto toString = [](const IU64& x) { | |
| std::ostringstream ss; | |
| ss << x; | |
| return ss.str(); | |
| }; | |
| EXPECT_EQ(toString(IU64(0)), "0"); | |
| EXPECT_EQ(toString(IU64(42)), "42"); | |
| EXPECT_EQ(toString(IU64(-42)), "-42"); | |
| EXPECT_EQ(toString(IU64(std::numeric_limits<int64_t>::min())), | |
| "-9223372036854775808"); | |
| EXPECT_EQ(toString(IU64(std::numeric_limits<uint64_t>::max())), | |
| "18446744073709551615"); | |
| } |