mfbt/tests/TestEndian.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "mozilla/Assertions.h"
     6 #include "mozilla/Endian.h"
     8 #include <stddef.h>
    10 using mozilla::BigEndian;
    11 using mozilla::LittleEndian;
    12 using mozilla::NativeEndian;
    14 template<typename T>
    15 void
    16 TestSingleSwap(T value, T swappedValue)
    17 {
    18 #if MOZ_LITTLE_ENDIAN
    19   MOZ_RELEASE_ASSERT(NativeEndian::swapToBigEndian(value) == swappedValue);
    20   MOZ_RELEASE_ASSERT(NativeEndian::swapFromBigEndian(value) == swappedValue);
    21   MOZ_RELEASE_ASSERT(NativeEndian::swapToNetworkOrder(value) == swappedValue);
    22   MOZ_RELEASE_ASSERT(NativeEndian::swapFromNetworkOrder(value) == swappedValue);
    23 #else
    24   MOZ_RELEASE_ASSERT(NativeEndian::swapToLittleEndian(value) == swappedValue);
    25   MOZ_RELEASE_ASSERT(NativeEndian::swapFromLittleEndian(value) == swappedValue);
    26 #endif
    27 }
    29 template<typename T>
    30 void
    31 TestSingleNoSwap(T value, T notSwappedValue)
    32 {
    33 #if MOZ_LITTLE_ENDIAN
    34   MOZ_RELEASE_ASSERT(NativeEndian::swapToLittleEndian(value) == notSwappedValue);
    35   MOZ_RELEASE_ASSERT(NativeEndian::swapFromLittleEndian(value) == notSwappedValue);
    36 #else
    37   MOZ_RELEASE_ASSERT(NativeEndian::swapToBigEndian(value) == notSwappedValue);
    38   MOZ_RELEASE_ASSERT(NativeEndian::swapFromBigEndian(value) == notSwappedValue);
    39   MOZ_RELEASE_ASSERT(NativeEndian::swapToNetworkOrder(value) == notSwappedValue);
    40   MOZ_RELEASE_ASSERT(NativeEndian::swapFromNetworkOrder(value) == notSwappedValue);
    41 #endif
    42 }
    44 // Endian.h functions are declared as protected in an base class and
    45 // then re-exported as public in public derived classes.  The
    46 // standardese around explicit instantiation of templates is not clear
    47 // in such cases.  Provide these wrappers to make things more explicit.
    48 // For your own enlightenment, you may wish to peruse:
    49 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56152 and subsequently
    50 // http://j.mp/XosS6S .
    51 #define WRAP_COPYTO(NAME)                                       \
    52   template<typename T>                                          \
    53   void                                                          \
    54   NAME(void* dst, const T* src, size_t count)                   \
    55   {                                                             \
    56     NativeEndian::NAME<T>(dst, src, count);                     \
    57   }
    59 WRAP_COPYTO(copyAndSwapToLittleEndian)
    60 WRAP_COPYTO(copyAndSwapToBigEndian)
    61 WRAP_COPYTO(copyAndSwapToNetworkOrder)
    63 #define WRAP_COPYFROM(NAME)                                     \
    64   template<typename T>                                          \
    65   void                                                          \
    66   NAME(T* dst, const void* src, size_t count)                   \
    67   {                                                             \
    68     NativeEndian::NAME<T>(dst, src, count);                     \
    69   }
    71 WRAP_COPYFROM(copyAndSwapFromLittleEndian)
    72 WRAP_COPYFROM(copyAndSwapFromBigEndian)
    73 WRAP_COPYFROM(copyAndSwapFromNetworkOrder)
    75 #define WRAP_IN_PLACE(NAME)                                     \
    76   template<typename T>                                          \
    77   void                                                          \
    78   NAME(T* p, size_t count)                                      \
    79   {                                                             \
    80     NativeEndian::NAME<T>(p, count);                            \
    81   }
    82 WRAP_IN_PLACE(swapToLittleEndianInPlace)
    83 WRAP_IN_PLACE(swapFromLittleEndianInPlace)
    84 WRAP_IN_PLACE(swapToBigEndianInPlace)
    85 WRAP_IN_PLACE(swapFromBigEndianInPlace)
    86 WRAP_IN_PLACE(swapToNetworkOrderInPlace)
    87 WRAP_IN_PLACE(swapFromNetworkOrderInPlace)
    89 enum SwapExpectation {
    90   Swap,
    91   NoSwap
    92 };
    94 template<typename T, size_t Count>
    95 void
    96 TestBulkSwapToSub(enum SwapExpectation expectSwap,
    97                   const T (&values)[Count],
    98                   void (*swapperFunc)(void*, const T*, size_t),
    99                   T (*readerFunc)(const void*))
   100 {
   101   const size_t arraySize = 2 * Count;
   102   const size_t bufferSize = arraySize * sizeof(T);
   103   static uint8_t buffer[bufferSize];
   104   const uint8_t fillValue = 0xa5;
   105   static uint8_t checkBuffer[bufferSize];
   107   MOZ_RELEASE_ASSERT(bufferSize > 2 * sizeof(T));
   109   memset(checkBuffer, fillValue, bufferSize);
   111   for (size_t startPosition = 0; startPosition < sizeof(T); ++startPosition) {
   112     for (size_t nValues = 0; nValues < Count; ++nValues) {
   113       memset(buffer, fillValue, bufferSize);
   114       swapperFunc(buffer + startPosition, values, nValues);
   116       MOZ_RELEASE_ASSERT(memcmp(buffer, checkBuffer, startPosition) == 0);
   117       size_t valuesEndPosition = startPosition + sizeof(T) * nValues;
   118       MOZ_RELEASE_ASSERT(memcmp(buffer + valuesEndPosition,
   119                         checkBuffer + valuesEndPosition,
   120                         bufferSize - valuesEndPosition) == 0);
   121       if (expectSwap == NoSwap) {
   122         MOZ_RELEASE_ASSERT(memcmp(buffer + startPosition, values,
   123                           nValues * sizeof(T)) == 0);
   124       }
   125       for (size_t i = 0; i < nValues; ++i) {
   126         MOZ_RELEASE_ASSERT(readerFunc(buffer + startPosition + sizeof(T) * i) ==
   127                    values[i]);
   128       }
   129     }
   130   }
   131 }
   133 template<typename T, size_t Count>
   134 void
   135 TestBulkSwapFromSub(enum SwapExpectation expectSwap,
   136                     const T (&values)[Count],
   137                     void (*swapperFunc)(T*, const void*, size_t),
   138                     T (*readerFunc)(const void*))
   139 {
   140   const size_t arraySize = 2 * Count;
   141   const size_t bufferSize = arraySize * sizeof(T);
   142   static T buffer[arraySize];
   143   const uint8_t fillValue = 0xa5;
   144   static T checkBuffer[arraySize];
   146   memset(checkBuffer, fillValue, bufferSize);
   148   for (size_t startPosition = 0; startPosition < Count; ++startPosition) {
   149     for (size_t nValues = 0; nValues < (Count - startPosition); ++nValues) {
   150       memset(buffer, fillValue, bufferSize);
   151       swapperFunc(buffer + startPosition, values, nValues);
   153       MOZ_RELEASE_ASSERT(memcmp(buffer, checkBuffer, startPosition * sizeof(T)) == 0);
   154       size_t valuesEndPosition = startPosition + nValues;
   155       MOZ_RELEASE_ASSERT(memcmp(buffer + valuesEndPosition,
   156                         checkBuffer + valuesEndPosition,
   157                         (arraySize - valuesEndPosition) * sizeof(T)) == 0);
   158       if (expectSwap == NoSwap) {
   159         MOZ_RELEASE_ASSERT(memcmp(buffer + startPosition, values,
   160                           nValues * sizeof(T)) == 0);
   161       }
   162       for (size_t i = 0; i < nValues; ++i)
   163         MOZ_RELEASE_ASSERT(readerFunc(buffer + startPosition + i) == values[i]);
   164     }
   165   }
   166 }
   169 template<typename T, size_t Count>
   170 void
   171 TestBulkInPlaceSub(enum SwapExpectation expectSwap,
   172                    const T (&values)[Count],
   173                    void (*swapperFunc)(T* p, size_t),
   174                    T (*readerFunc)(const void*))
   175 {
   176   const size_t bufferCount = 4 * Count;
   177   const size_t bufferSize = bufferCount * sizeof(T);
   178   static T buffer[bufferCount];
   179   const T fillValue = 0xa5;
   180   static T checkBuffer[bufferCount];
   182   MOZ_RELEASE_ASSERT(bufferSize > 2 * sizeof(T));
   184   memset(checkBuffer, fillValue, bufferSize);
   186   for (size_t startPosition = 0; startPosition < Count; ++startPosition) {
   187     for (size_t nValues = 0; nValues < Count; ++nValues) {
   188       memset(buffer, fillValue, bufferSize);
   189       memcpy(buffer + startPosition, values, nValues * sizeof(T));
   190       swapperFunc(buffer + startPosition, nValues);
   192       MOZ_RELEASE_ASSERT(memcmp(buffer, checkBuffer, startPosition * sizeof(T)) == 0);
   193       size_t valuesEndPosition = startPosition + nValues;
   194       MOZ_RELEASE_ASSERT(memcmp(buffer + valuesEndPosition,
   195                         checkBuffer + valuesEndPosition,
   196                         bufferSize - valuesEndPosition * sizeof(T)) == 0);
   197       if (expectSwap == NoSwap) {
   198         MOZ_RELEASE_ASSERT(memcmp(buffer + startPosition, values,
   199                           nValues * sizeof(T)) == 0);
   200       }
   201       for (size_t i = 0; i < nValues; ++i)
   202         MOZ_RELEASE_ASSERT(readerFunc(buffer + startPosition + i) == values[i]);
   203     }
   204   }
   205 }
   207 template<typename T>
   208 struct Reader
   209 {
   210 };
   212 #define SPECIALIZE_READER(TYPE, READ_FUNC)                              \
   213   template<>                                                            \
   214   struct Reader<TYPE>                                                   \
   215   {                                                                     \
   216     static TYPE readLE(const void* p) { return LittleEndian::READ_FUNC(p); }    \
   217     static TYPE readBE(const void* p) { return BigEndian::READ_FUNC(p); } \
   218   };
   220 SPECIALIZE_READER(uint16_t, readUint16)
   221 SPECIALIZE_READER(uint32_t, readUint32)
   222 SPECIALIZE_READER(uint64_t, readUint64)
   223 SPECIALIZE_READER(int16_t, readInt16)
   224 SPECIALIZE_READER(int32_t, readInt32)
   225 SPECIALIZE_READER(int64_t, readInt64)
   227 template<typename T, size_t Count>
   228 void
   229 TestBulkSwap(const T (&bytes)[Count])
   230 {
   231 #if MOZ_LITTLE_ENDIAN
   232   TestBulkSwapToSub(Swap, bytes, copyAndSwapToBigEndian<T>, Reader<T>::readBE);
   233   TestBulkSwapFromSub(Swap, bytes, copyAndSwapFromBigEndian<T>, Reader<T>::readBE);
   234   TestBulkSwapToSub(Swap, bytes, copyAndSwapToNetworkOrder<T>, Reader<T>::readBE);
   235   TestBulkSwapFromSub(Swap, bytes, copyAndSwapFromNetworkOrder<T>, Reader<T>::readBE);
   236 #else
   237   TestBulkSwapToSub(Swap, bytes, copyAndSwapToLittleEndian<T>, Reader<T>::readLE);
   238   TestBulkSwapFromSub(Swap, bytes, copyAndSwapFromLittleEndian<T>, Reader<T>::readLE);
   239 #endif
   240 }
   242 template<typename T, size_t Count>
   243 void
   244 TestBulkNoSwap(const T (&bytes)[Count])
   245 {
   246 #if MOZ_LITTLE_ENDIAN
   247   TestBulkSwapToSub(NoSwap, bytes, copyAndSwapToLittleEndian<T>, Reader<T>::readLE);
   248   TestBulkSwapFromSub(NoSwap, bytes, copyAndSwapFromLittleEndian<T>, Reader<T>::readLE);
   249 #else
   250   TestBulkSwapToSub(NoSwap, bytes, copyAndSwapToBigEndian<T>, Reader<T>::readBE);
   251   TestBulkSwapFromSub(NoSwap, bytes, copyAndSwapFromBigEndian<T>, Reader<T>::readBE);
   252   TestBulkSwapToSub(NoSwap, bytes, copyAndSwapToNetworkOrder<T>, Reader<T>::readBE);
   253   TestBulkSwapFromSub(NoSwap, bytes, copyAndSwapFromNetworkOrder<T>, Reader<T>::readBE);
   254 #endif
   255 }
   257 template<typename T, size_t Count>
   258 void
   259 TestBulkInPlaceSwap(const T (&bytes)[Count])
   260 {
   261 #if MOZ_LITTLE_ENDIAN
   262   TestBulkInPlaceSub(Swap, bytes, swapToBigEndianInPlace<T>, Reader<T>::readBE);
   263   TestBulkInPlaceSub(Swap, bytes, swapFromBigEndianInPlace<T>, Reader<T>::readBE);
   264   TestBulkInPlaceSub(Swap, bytes, swapToNetworkOrderInPlace<T>, Reader<T>::readBE);
   265   TestBulkInPlaceSub(Swap, bytes, swapFromNetworkOrderInPlace<T>, Reader<T>::readBE);
   266 #else
   267   TestBulkInPlaceSub(Swap, bytes, swapToLittleEndianInPlace<T>, Reader<T>::readLE);
   268   TestBulkInPlaceSub(Swap, bytes, swapFromLittleEndianInPlace<T>, Reader<T>::readLE);
   269 #endif
   270 }
   272 template<typename T, size_t Count>
   273 void
   274 TestBulkInPlaceNoSwap(const T (&bytes)[Count])
   275 {
   276 #if MOZ_LITTLE_ENDIAN
   277   TestBulkInPlaceSub(NoSwap, bytes, swapToLittleEndianInPlace<T>, Reader<T>::readLE);
   278   TestBulkInPlaceSub(NoSwap, bytes, swapFromLittleEndianInPlace<T>, Reader<T>::readLE);
   279 #else
   280   TestBulkInPlaceSub(NoSwap, bytes, swapToBigEndianInPlace<T>, Reader<T>::readBE);
   281   TestBulkInPlaceSub(NoSwap, bytes, swapFromBigEndianInPlace<T>, Reader<T>::readBE);
   282   TestBulkInPlaceSub(NoSwap, bytes, swapToNetworkOrderInPlace<T>, Reader<T>::readBE);
   283   TestBulkInPlaceSub(NoSwap, bytes, swapFromNetworkOrderInPlace<T>, Reader<T>::readBE);
   284 #endif
   285 }
   287 int
   288 main()
   289 {
   290   static const uint8_t unsigned_bytes[16] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
   291                                               0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };
   292   static const int8_t signed_bytes[16] = { -0x0f, -0x0e, -0x0d, -0x0c, -0x0b, -0x0a, -0x09, -0x08,
   293                                            -0x0f, -0x0e, -0x0d, -0x0c, -0x0b, -0x0a, -0x09, -0x08 };
   294   static const uint16_t uint16_values[8] = { 0x102, 0x304, 0x506, 0x708, 0x102, 0x304, 0x506, 0x708 };
   295   static const int16_t int16_values[8] = { int16_t(0xf1f2), int16_t(0xf3f4), int16_t(0xf5f6), int16_t(0xf7f8),
   296                                            int16_t(0xf1f2), int16_t(0xf3f4), int16_t(0xf5f6), int16_t(0xf7f8) };
   297   static const uint32_t uint32_values[4] = { 0x1020304, 0x5060708, 0x1020304, 0x5060708 };
   298   static const int32_t int32_values[4] = { int32_t(0xf1f2f3f4), int32_t(0xf5f6f7f8),
   299                                            int32_t(0xf1f2f3f4), int32_t(0xf5f6f7f8) };
   300   static const uint64_t uint64_values[2] = { 0x102030405060708, 0x102030405060708 };
   301   static const int64_t int64_values[2] = { int64_t(0xf1f2f3f4f5f6f7f8),
   302                                            int64_t(0xf1f2f3f4f5f6f7f8) };
   303   uint8_t buffer[8];
   305   MOZ_RELEASE_ASSERT(LittleEndian::readUint16(&unsigned_bytes[0]) == 0x201);
   306   MOZ_RELEASE_ASSERT(BigEndian::readUint16(&unsigned_bytes[0]) == 0x102);
   308   MOZ_RELEASE_ASSERT(LittleEndian::readUint32(&unsigned_bytes[0]) == 0x4030201U);
   309   MOZ_RELEASE_ASSERT(BigEndian::readUint32(&unsigned_bytes[0]) == 0x1020304U);
   311   MOZ_RELEASE_ASSERT(LittleEndian::readUint64(&unsigned_bytes[0]) == 0x807060504030201ULL);
   312   MOZ_RELEASE_ASSERT(BigEndian::readUint64(&unsigned_bytes[0]) == 0x102030405060708ULL);
   314   LittleEndian::writeUint16(&buffer[0], 0x201);
   315   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint16_t)) == 0);
   316   BigEndian::writeUint16(&buffer[0], 0x102);
   317   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint16_t)) == 0);
   319   LittleEndian::writeUint32(&buffer[0], 0x4030201U);
   320   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint32_t)) == 0);
   321   BigEndian::writeUint32(&buffer[0], 0x1020304U);
   322   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint32_t)) == 0);
   324   LittleEndian::writeUint64(&buffer[0], 0x807060504030201ULL);
   325   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint64_t)) == 0);
   326   BigEndian::writeUint64(&buffer[0], 0x102030405060708ULL);
   327   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint64_t)) == 0);
   329   MOZ_RELEASE_ASSERT(LittleEndian::readInt16(&signed_bytes[0]) == int16_t(0xf2f1));
   330   MOZ_RELEASE_ASSERT(BigEndian::readInt16(&signed_bytes[0]) == int16_t(0xf1f2));
   332   MOZ_RELEASE_ASSERT(LittleEndian::readInt32(&signed_bytes[0]) == int32_t(0xf4f3f2f1));
   333   MOZ_RELEASE_ASSERT(BigEndian::readInt32(&signed_bytes[0]) == int32_t(0xf1f2f3f4));
   335   MOZ_RELEASE_ASSERT(LittleEndian::readInt64(&signed_bytes[0]) == int64_t(0xf8f7f6f5f4f3f2f1LL));
   336   MOZ_RELEASE_ASSERT(BigEndian::readInt64(&signed_bytes[0]) == int64_t(0xf1f2f3f4f5f6f7f8LL));
   338   LittleEndian::writeInt16(&buffer[0], 0xf2f1);
   339   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int16_t)) == 0);
   340   BigEndian::writeInt16(&buffer[0], 0xf1f2);
   341   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int16_t)) == 0);
   343   LittleEndian::writeInt32(&buffer[0], 0xf4f3f2f1);
   344   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int32_t)) == 0);
   345   BigEndian::writeInt32(&buffer[0], 0xf1f2f3f4);
   346   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int32_t)) == 0);
   348   LittleEndian::writeInt64(&buffer[0], 0xf8f7f6f5f4f3f2f1LL);
   349   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int64_t)) == 0);
   350   BigEndian::writeInt64(&buffer[0], 0xf1f2f3f4f5f6f7f8LL);
   351   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int64_t)) == 0);
   353   TestSingleSwap(uint16_t(0xf2f1), uint16_t(0xf1f2));
   354   TestSingleSwap(uint32_t(0xf4f3f2f1), uint32_t(0xf1f2f3f4));
   355   TestSingleSwap(uint64_t(0xf8f7f6f5f4f3f2f1), uint64_t(0xf1f2f3f4f5f6f7f8));
   357   TestSingleSwap(int16_t(0xf2f1), int16_t(0xf1f2));
   358   TestSingleSwap(int32_t(0xf4f3f2f1), int32_t(0xf1f2f3f4));
   359   TestSingleSwap(int64_t(0xf8f7f6f5f4f3f2f1), int64_t(0xf1f2f3f4f5f6f7f8));
   361   TestSingleNoSwap(uint16_t(0xf2f1), uint16_t(0xf2f1));
   362   TestSingleNoSwap(uint32_t(0xf4f3f2f1), uint32_t(0xf4f3f2f1));
   363   TestSingleNoSwap(uint64_t(0xf8f7f6f5f4f3f2f1), uint64_t(0xf8f7f6f5f4f3f2f1));
   365   TestSingleNoSwap(int16_t(0xf2f1), int16_t(0xf2f1));
   366   TestSingleNoSwap(int32_t(0xf4f3f2f1), int32_t(0xf4f3f2f1));
   367   TestSingleNoSwap(int64_t(0xf8f7f6f5f4f3f2f1), int64_t(0xf8f7f6f5f4f3f2f1));
   369   TestBulkSwap(uint16_values);
   370   TestBulkSwap(int16_values);
   371   TestBulkSwap(uint32_values);
   372   TestBulkSwap(int32_values);
   373   TestBulkSwap(uint64_values);
   374   TestBulkSwap(int64_values);
   376   TestBulkNoSwap(uint16_values);
   377   TestBulkNoSwap(int16_values);
   378   TestBulkNoSwap(uint32_values);
   379   TestBulkNoSwap(int32_values);
   380   TestBulkNoSwap(uint64_values);
   381   TestBulkNoSwap(int64_values);
   383   TestBulkInPlaceSwap(uint16_values);
   384   TestBulkInPlaceSwap(int16_values);
   385   TestBulkInPlaceSwap(uint32_values);
   386   TestBulkInPlaceSwap(int32_values);
   387   TestBulkInPlaceSwap(uint64_values);
   388   TestBulkInPlaceSwap(int64_values);
   390   TestBulkInPlaceNoSwap(uint16_values);
   391   TestBulkInPlaceNoSwap(int16_values);
   392   TestBulkInPlaceNoSwap(uint32_values);
   393   TestBulkInPlaceNoSwap(int32_values);
   394   TestBulkInPlaceNoSwap(uint64_values);
   395   TestBulkInPlaceNoSwap(int64_values);
   397   return 0;
   398 }

mercurial