endian_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/base/internal/endian.h"
00016 
00017 #include <algorithm>
00018 #include <cstdint>
00019 #include <limits>
00020 #include <random>
00021 #include <vector>
00022 
00023 #include "gtest/gtest.h"
00024 #include "absl/base/config.h"
00025 
00026 namespace absl {
00027 namespace {
00028 
00029 const uint64_t kInitialNumber{0x0123456789abcdef};
00030 const uint64_t k64Value{kInitialNumber};
00031 const uint32_t k32Value{0x01234567};
00032 const uint16_t k16Value{0x0123};
00033 const int kNumValuesToTest = 1000000;
00034 const int kRandomSeed = 12345;
00035 
00036 #if defined(ABSL_IS_BIG_ENDIAN)
00037 const uint64_t kInitialInNetworkOrder{kInitialNumber};
00038 const uint64_t k64ValueLE{0xefcdab8967452301};
00039 const uint32_t k32ValueLE{0x67452301};
00040 const uint16_t k16ValueLE{0x2301};
00041 
00042 const uint64_t k64ValueBE{kInitialNumber};
00043 const uint32_t k32ValueBE{k32Value};
00044 const uint16_t k16ValueBE{k16Value};
00045 #elif defined(ABSL_IS_LITTLE_ENDIAN)
00046 const uint64_t kInitialInNetworkOrder{0xefcdab8967452301};
00047 const uint64_t k64ValueLE{kInitialNumber};
00048 const uint32_t k32ValueLE{k32Value};
00049 const uint16_t k16ValueLE{k16Value};
00050 
00051 const uint64_t k64ValueBE{0xefcdab8967452301};
00052 const uint32_t k32ValueBE{0x67452301};
00053 const uint16_t k16ValueBE{0x2301};
00054 #endif
00055 
00056 template<typename T>
00057 std::vector<T> GenerateAllValuesForType() {
00058   std::vector<T> result;
00059   T next = std::numeric_limits<T>::min();
00060   while (true) {
00061     result.push_back(next);
00062     if (next == std::numeric_limits<T>::max()) {
00063       return result;
00064     }
00065     ++next;
00066   }
00067 }
00068 
00069 template<typename T>
00070 std::vector<T> GenerateRandomIntegers(size_t numValuesToTest) {
00071   std::vector<T> result;
00072   std::mt19937_64 rng(kRandomSeed);
00073   for (size_t i = 0; i < numValuesToTest; ++i) {
00074     result.push_back(rng());
00075   }
00076   return result;
00077 }
00078 
00079 void ManualByteSwap(char* bytes, int length) {
00080   if (length == 1)
00081     return;
00082 
00083   EXPECT_EQ(0, length % 2);
00084   for (int i = 0; i < length / 2; ++i) {
00085     int j = (length - 1) - i;
00086     using std::swap;
00087     swap(bytes[i], bytes[j]);
00088   }
00089 }
00090 
00091 template<typename T>
00092 inline T UnalignedLoad(const char* p) {
00093   static_assert(
00094       sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,
00095       "Unexpected type size");
00096 
00097   switch (sizeof(T)) {
00098     case 1: return *reinterpret_cast<const T*>(p);
00099     case 2:
00100       return ABSL_INTERNAL_UNALIGNED_LOAD16(p);
00101     case 4:
00102       return ABSL_INTERNAL_UNALIGNED_LOAD32(p);
00103     case 8:
00104       return ABSL_INTERNAL_UNALIGNED_LOAD64(p);
00105     default:
00106       // Suppresses invalid "not all control paths return a value" on MSVC
00107       return {};
00108   }
00109 }
00110 
00111 template <typename T, typename ByteSwapper>
00112 static void GBSwapHelper(const std::vector<T>& host_values_to_test,
00113                          const ByteSwapper& byte_swapper) {
00114   // Test byte_swapper against a manual byte swap.
00115   for (typename std::vector<T>::const_iterator it = host_values_to_test.begin();
00116        it != host_values_to_test.end(); ++it) {
00117     T host_value = *it;
00118 
00119     char actual_value[sizeof(host_value)];
00120     memcpy(actual_value, &host_value, sizeof(host_value));
00121     byte_swapper(actual_value);
00122 
00123     char expected_value[sizeof(host_value)];
00124     memcpy(expected_value, &host_value, sizeof(host_value));
00125     ManualByteSwap(expected_value, sizeof(host_value));
00126 
00127     ASSERT_EQ(0, memcmp(actual_value, expected_value, sizeof(host_value)))
00128         << "Swap output for 0x" << std::hex << host_value << " does not match. "
00129         << "Expected: 0x" << UnalignedLoad<T>(expected_value) << "; "
00130         << "actual: 0x" <<  UnalignedLoad<T>(actual_value);
00131   }
00132 }
00133 
00134 void Swap16(char* bytes) {
00135   ABSL_INTERNAL_UNALIGNED_STORE16(
00136       bytes, gbswap_16(ABSL_INTERNAL_UNALIGNED_LOAD16(bytes)));
00137 }
00138 
00139 void Swap32(char* bytes) {
00140   ABSL_INTERNAL_UNALIGNED_STORE32(
00141       bytes, gbswap_32(ABSL_INTERNAL_UNALIGNED_LOAD32(bytes)));
00142 }
00143 
00144 void Swap64(char* bytes) {
00145   ABSL_INTERNAL_UNALIGNED_STORE64(
00146       bytes, gbswap_64(ABSL_INTERNAL_UNALIGNED_LOAD64(bytes)));
00147 }
00148 
00149 TEST(EndianessTest, Uint16) {
00150   GBSwapHelper(GenerateAllValuesForType<uint16_t>(), &Swap16);
00151 }
00152 
00153 TEST(EndianessTest, Uint32) {
00154   GBSwapHelper(GenerateRandomIntegers<uint32_t>(kNumValuesToTest), &Swap32);
00155 }
00156 
00157 TEST(EndianessTest, Uint64) {
00158   GBSwapHelper(GenerateRandomIntegers<uint64_t>(kNumValuesToTest), &Swap64);
00159 }
00160 
00161 TEST(EndianessTest, ghtonll_gntohll) {
00162   // Test that absl::ghtonl compiles correctly
00163   uint32_t test = 0x01234567;
00164   EXPECT_EQ(absl::gntohl(absl::ghtonl(test)), test);
00165 
00166   uint64_t comp = absl::ghtonll(kInitialNumber);
00167   EXPECT_EQ(comp, kInitialInNetworkOrder);
00168   comp = absl::gntohll(kInitialInNetworkOrder);
00169   EXPECT_EQ(comp, kInitialNumber);
00170 
00171   // Test that htonll and ntohll are each others' inverse functions on a
00172   // somewhat assorted batch of numbers. 37 is chosen to not be anything
00173   // particularly nice base 2.
00174   uint64_t value = 1;
00175   for (int i = 0; i < 100; ++i) {
00176     comp = absl::ghtonll(absl::gntohll(value));
00177     EXPECT_EQ(value, comp);
00178     comp = absl::gntohll(absl::ghtonll(value));
00179     EXPECT_EQ(value, comp);
00180     value *= 37;
00181   }
00182 }
00183 
00184 TEST(EndianessTest, little_endian) {
00185   // Check little_endian uint16_t.
00186   uint64_t comp = little_endian::FromHost16(k16Value);
00187   EXPECT_EQ(comp, k16ValueLE);
00188   comp = little_endian::ToHost16(k16ValueLE);
00189   EXPECT_EQ(comp, k16Value);
00190 
00191   // Check little_endian uint32_t.
00192   comp = little_endian::FromHost32(k32Value);
00193   EXPECT_EQ(comp, k32ValueLE);
00194   comp = little_endian::ToHost32(k32ValueLE);
00195   EXPECT_EQ(comp, k32Value);
00196 
00197   // Check little_endian uint64_t.
00198   comp = little_endian::FromHost64(k64Value);
00199   EXPECT_EQ(comp, k64ValueLE);
00200   comp = little_endian::ToHost64(k64ValueLE);
00201   EXPECT_EQ(comp, k64Value);
00202 
00203   // Check little-endian Load and store functions.
00204   uint16_t u16Buf;
00205   uint32_t u32Buf;
00206   uint64_t u64Buf;
00207 
00208   little_endian::Store16(&u16Buf, k16Value);
00209   EXPECT_EQ(u16Buf, k16ValueLE);
00210   comp = little_endian::Load16(&u16Buf);
00211   EXPECT_EQ(comp, k16Value);
00212 
00213   little_endian::Store32(&u32Buf, k32Value);
00214   EXPECT_EQ(u32Buf, k32ValueLE);
00215   comp = little_endian::Load32(&u32Buf);
00216   EXPECT_EQ(comp, k32Value);
00217 
00218   little_endian::Store64(&u64Buf, k64Value);
00219   EXPECT_EQ(u64Buf, k64ValueLE);
00220   comp = little_endian::Load64(&u64Buf);
00221   EXPECT_EQ(comp, k64Value);
00222 }
00223 
00224 TEST(EndianessTest, big_endian) {
00225   // Check big-endian Load and store functions.
00226   uint16_t u16Buf;
00227   uint32_t u32Buf;
00228   uint64_t u64Buf;
00229 
00230   unsigned char buffer[10];
00231   big_endian::Store16(&u16Buf, k16Value);
00232   EXPECT_EQ(u16Buf, k16ValueBE);
00233   uint64_t comp = big_endian::Load16(&u16Buf);
00234   EXPECT_EQ(comp, k16Value);
00235 
00236   big_endian::Store32(&u32Buf, k32Value);
00237   EXPECT_EQ(u32Buf, k32ValueBE);
00238   comp = big_endian::Load32(&u32Buf);
00239   EXPECT_EQ(comp, k32Value);
00240 
00241   big_endian::Store64(&u64Buf, k64Value);
00242   EXPECT_EQ(u64Buf, k64ValueBE);
00243   comp = big_endian::Load64(&u64Buf);
00244   EXPECT_EQ(comp, k64Value);
00245 
00246   big_endian::Store16(buffer + 1, k16Value);
00247   EXPECT_EQ(u16Buf, k16ValueBE);
00248   comp = big_endian::Load16(buffer + 1);
00249   EXPECT_EQ(comp, k16Value);
00250 
00251   big_endian::Store32(buffer + 1, k32Value);
00252   EXPECT_EQ(u32Buf, k32ValueBE);
00253   comp = big_endian::Load32(buffer + 1);
00254   EXPECT_EQ(comp, k32Value);
00255 
00256   big_endian::Store64(buffer + 1, k64Value);
00257   EXPECT_EQ(u64Buf, k64ValueBE);
00258   comp = big_endian::Load64(buffer + 1);
00259   EXPECT_EQ(comp, k64Value);
00260 }
00261 
00262 }  // namespace
00263 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14