1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "mozilla/Assertions.h"
8 #include "mozilla/EndianUtils.h"
9 
10 #include <stddef.h>
11 
12 using mozilla::BigEndian;
13 using mozilla::LittleEndian;
14 using mozilla::NativeEndian;
15 
16 template<typename T>
17 void
TestSingleSwap(T aValue,T aSwappedValue)18 TestSingleSwap(T aValue, T aSwappedValue)
19 {
20 #if MOZ_LITTLE_ENDIAN
21   MOZ_RELEASE_ASSERT(NativeEndian::swapToBigEndian(aValue) == aSwappedValue);
22   MOZ_RELEASE_ASSERT(NativeEndian::swapFromBigEndian(aValue) == aSwappedValue);
23   MOZ_RELEASE_ASSERT(NativeEndian::swapToNetworkOrder(aValue) == aSwappedValue);
24   MOZ_RELEASE_ASSERT(NativeEndian::swapFromNetworkOrder(aValue) ==
25                      aSwappedValue);
26 #else
27   MOZ_RELEASE_ASSERT(NativeEndian::swapToLittleEndian(aValue) == aSwappedValue);
28   MOZ_RELEASE_ASSERT(NativeEndian::swapFromLittleEndian(aValue) ==
29                      aSwappedValue);
30 #endif
31 }
32 
33 template<typename T>
34 void
TestSingleNoSwap(T aValue,T aUnswappedValue)35 TestSingleNoSwap(T aValue, T aUnswappedValue)
36 {
37 #if MOZ_LITTLE_ENDIAN
38   MOZ_RELEASE_ASSERT(NativeEndian::swapToLittleEndian(aValue) ==
39                      aUnswappedValue);
40   MOZ_RELEASE_ASSERT(NativeEndian::swapFromLittleEndian(aValue) ==
41                      aUnswappedValue);
42 #else
43   MOZ_RELEASE_ASSERT(NativeEndian::swapToBigEndian(aValue) == aUnswappedValue);
44   MOZ_RELEASE_ASSERT(NativeEndian::swapFromBigEndian(aValue) == aUnswappedValue);
45   MOZ_RELEASE_ASSERT(NativeEndian::swapToNetworkOrder(aValue) ==
46                      aUnswappedValue);
47   MOZ_RELEASE_ASSERT(NativeEndian::swapFromNetworkOrder(aValue) ==
48                      aUnswappedValue);
49 #endif
50 }
51 
52 // EndianUtils.h functions are declared as protected in a base class and
53 // then re-exported as public in public derived classes.  The
54 // standardese around explicit instantiation of templates is not clear
55 // in such cases.  Provide these wrappers to make things more explicit.
56 // For your own enlightenment, you may wish to peruse:
57 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56152 and subsequently
58 // http://j.mp/XosS6S .
59 #define WRAP_COPYTO(NAME)                                       \
60   template<typename T>                                          \
61   void                                                          \
62   NAME(void* aDst, const T* aSrc, size_t aCount)                \
63   {                                                             \
64     NativeEndian::NAME<T>(aDst, aSrc, aCount);                  \
65   }
66 
67 WRAP_COPYTO(copyAndSwapToLittleEndian)
68 WRAP_COPYTO(copyAndSwapToBigEndian)
69 WRAP_COPYTO(copyAndSwapToNetworkOrder)
70 
71 #define WRAP_COPYFROM(NAME)                                     \
72   template<typename T>                                          \
73   void                                                          \
74   NAME(T* aDst, const void* aSrc, size_t aCount)                \
75   {                                                             \
76     NativeEndian::NAME<T>(aDst, aSrc, aCount);                  \
77   }
78 
79 WRAP_COPYFROM(copyAndSwapFromLittleEndian)
80 WRAP_COPYFROM(copyAndSwapFromBigEndian)
81 WRAP_COPYFROM(copyAndSwapFromNetworkOrder)
82 
83 #define WRAP_IN_PLACE(NAME)                                     \
84   template<typename T>                                          \
85   void                                                          \
86   NAME(T* aP, size_t aCount)                                    \
87   {                                                             \
88     NativeEndian::NAME<T>(aP, aCount);                          \
89   }
90 WRAP_IN_PLACE(swapToLittleEndianInPlace)
91 WRAP_IN_PLACE(swapFromLittleEndianInPlace)
92 WRAP_IN_PLACE(swapToBigEndianInPlace)
93 WRAP_IN_PLACE(swapFromBigEndianInPlace)
94 WRAP_IN_PLACE(swapToNetworkOrderInPlace)
95 WRAP_IN_PLACE(swapFromNetworkOrderInPlace)
96 
97 enum SwapExpectation
98 {
99   Swap,
100   NoSwap
101 };
102 
103 template<typename T, size_t Count>
104 void
TestBulkSwapToSub(enum SwapExpectation aExpectSwap,const T (& aValues)[Count],void (* aSwapperFunc)(void *,const T *,size_t),T (* aReaderFunc)(const void *))105 TestBulkSwapToSub(enum SwapExpectation aExpectSwap,
106                   const T (&aValues)[Count],
107                   void (*aSwapperFunc)(void*, const T*, size_t),
108                   T (*aReaderFunc)(const void*))
109 {
110   const size_t arraySize = 2 * Count;
111   const size_t bufferSize = arraySize * sizeof(T);
112   static uint8_t buffer[bufferSize];
113   const uint8_t fillValue = 0xa5;
114   static uint8_t checkBuffer[bufferSize];
115 
116   MOZ_RELEASE_ASSERT(bufferSize > 2 * sizeof(T));
117 
118   memset(checkBuffer, fillValue, bufferSize);
119 
120   for (size_t startPosition = 0; startPosition < sizeof(T); ++startPosition) {
121     for (size_t nValues = 0; nValues < Count; ++nValues) {
122       memset(buffer, fillValue, bufferSize);
123       aSwapperFunc(buffer + startPosition, aValues, nValues);
124 
125       MOZ_RELEASE_ASSERT(memcmp(buffer, checkBuffer, startPosition) == 0);
126       size_t valuesEndPosition = startPosition + sizeof(T) * nValues;
127       MOZ_RELEASE_ASSERT(memcmp(buffer + valuesEndPosition,
128                          checkBuffer + valuesEndPosition,
129                          bufferSize - valuesEndPosition) == 0);
130       if (aExpectSwap == NoSwap) {
131         MOZ_RELEASE_ASSERT(memcmp(buffer + startPosition, aValues,
132                            nValues * sizeof(T)) == 0);
133       }
134       for (size_t i = 0; i < nValues; ++i) {
135         MOZ_RELEASE_ASSERT(
136           aReaderFunc(buffer + startPosition + sizeof(T) * i) == aValues[i]);
137       }
138     }
139   }
140 }
141 
142 template<typename T, size_t Count>
143 void
TestBulkSwapFromSub(enum SwapExpectation aExpectSwap,const T (& aValues)[Count],void (* aSwapperFunc)(T *,const void *,size_t),T (* aReaderFunc)(const void *))144 TestBulkSwapFromSub(enum SwapExpectation aExpectSwap,
145                     const T (&aValues)[Count],
146                     void (*aSwapperFunc)(T*, const void*, size_t),
147                     T (*aReaderFunc)(const void*))
148 {
149   const size_t arraySize = 2 * Count;
150   const size_t bufferSize = arraySize * sizeof(T);
151   static T buffer[arraySize];
152   const uint8_t fillValue = 0xa5;
153   static T checkBuffer[arraySize];
154 
155   memset(checkBuffer, fillValue, bufferSize);
156 
157   for (size_t startPosition = 0; startPosition < Count; ++startPosition) {
158     for (size_t nValues = 0; nValues < (Count - startPosition); ++nValues) {
159       memset(buffer, fillValue, bufferSize);
160       aSwapperFunc(buffer + startPosition, aValues, nValues);
161 
162       MOZ_RELEASE_ASSERT(
163         memcmp(buffer, checkBuffer, startPosition * sizeof(T)) == 0);
164       size_t valuesEndPosition = startPosition + nValues;
165       MOZ_RELEASE_ASSERT(memcmp(buffer + valuesEndPosition,
166                         checkBuffer + valuesEndPosition,
167                         (arraySize - valuesEndPosition) * sizeof(T)) == 0);
168       if (aExpectSwap == NoSwap) {
169         MOZ_RELEASE_ASSERT(memcmp(buffer + startPosition, aValues,
170                           nValues * sizeof(T)) == 0);
171       }
172       for (size_t i = 0; i < nValues; ++i) {
173         MOZ_RELEASE_ASSERT(aReaderFunc(buffer + startPosition + i) == aValues[i]);
174       }
175     }
176   }
177 }
178 
179 
180 template<typename T, size_t Count>
181 void
TestBulkInPlaceSub(enum SwapExpectation aExpectSwap,const T (& aValues)[Count],void (* aSwapperFunc)(T *,size_t),T (* aReaderFunc)(const void *))182 TestBulkInPlaceSub(enum SwapExpectation aExpectSwap,
183                    const T (&aValues)[Count],
184                    void (*aSwapperFunc)(T*, size_t),
185                    T (*aReaderFunc)(const void*))
186 {
187   const size_t bufferCount = 4 * Count;
188   const size_t bufferSize = bufferCount * sizeof(T);
189   static T buffer[bufferCount];
190   const T fillValue = 0xa5;
191   static T checkBuffer[bufferCount];
192 
193   MOZ_RELEASE_ASSERT(bufferSize > 2 * sizeof(T));
194 
195   memset(checkBuffer, fillValue, bufferSize);
196 
197   for (size_t startPosition = 0; startPosition < Count; ++startPosition) {
198     for (size_t nValues = 0; nValues < Count; ++nValues) {
199       memset(buffer, fillValue, bufferSize);
200       memcpy(buffer + startPosition, aValues, nValues * sizeof(T));
201       aSwapperFunc(buffer + startPosition, nValues);
202 
203       MOZ_RELEASE_ASSERT(
204         memcmp(buffer, checkBuffer, startPosition * sizeof(T)) == 0);
205       size_t valuesEndPosition = startPosition + nValues;
206       MOZ_RELEASE_ASSERT(memcmp(buffer + valuesEndPosition,
207                          checkBuffer + valuesEndPosition,
208                          bufferSize - valuesEndPosition * sizeof(T)) == 0);
209       if (aExpectSwap == NoSwap) {
210         MOZ_RELEASE_ASSERT(memcmp(buffer + startPosition, aValues,
211                            nValues * sizeof(T)) == 0);
212       }
213       for (size_t i = 0; i < nValues; ++i) {
214         MOZ_RELEASE_ASSERT(aReaderFunc(buffer + startPosition + i) == aValues[i]);
215       }
216     }
217   }
218 }
219 
220 template<typename T>
221 struct Reader
222 {
223 };
224 
225 #define SPECIALIZE_READER(TYPE, READ_FUNC)                                    \
226   template<>                                                                  \
227   struct Reader<TYPE>                                                         \
228   {                                                                           \
229     static TYPE readLE(const void* aP) { return LittleEndian::READ_FUNC(aP); }\
230     static TYPE readBE(const void* aP) { return BigEndian::READ_FUNC(aP); }   \
231   };
232 
SPECIALIZE_READER(uint16_t,readUint16)233 SPECIALIZE_READER(uint16_t, readUint16)
234 SPECIALIZE_READER(uint32_t, readUint32)
235 SPECIALIZE_READER(uint64_t, readUint64)
236 SPECIALIZE_READER(int16_t, readInt16)
237 SPECIALIZE_READER(int32_t, readInt32)
238 SPECIALIZE_READER(int64_t, readInt64)
239 
240 template<typename T, size_t Count>
241 void
242 TestBulkSwap(const T (&aBytes)[Count])
243 {
244 #if MOZ_LITTLE_ENDIAN
245   TestBulkSwapToSub(Swap, aBytes, copyAndSwapToBigEndian<T>,
246                     Reader<T>::readBE);
247   TestBulkSwapFromSub(Swap, aBytes, copyAndSwapFromBigEndian<T>,
248                       Reader<T>::readBE);
249   TestBulkSwapToSub(Swap, aBytes, copyAndSwapToNetworkOrder<T>,
250                     Reader<T>::readBE);
251   TestBulkSwapFromSub(Swap, aBytes, copyAndSwapFromNetworkOrder<T>,
252                       Reader<T>::readBE);
253 #else
254   TestBulkSwapToSub(Swap, aBytes, copyAndSwapToLittleEndian<T>,
255                     Reader<T>::readLE);
256   TestBulkSwapFromSub(Swap, aBytes, copyAndSwapFromLittleEndian<T>,
257                       Reader<T>::readLE);
258 #endif
259 }
260 
261 template<typename T, size_t Count>
262 void
TestBulkNoSwap(const T (& aBytes)[Count])263 TestBulkNoSwap(const T (&aBytes)[Count])
264 {
265 #if MOZ_LITTLE_ENDIAN
266   TestBulkSwapToSub(NoSwap, aBytes, copyAndSwapToLittleEndian<T>,
267                     Reader<T>::readLE);
268   TestBulkSwapFromSub(NoSwap, aBytes, copyAndSwapFromLittleEndian<T>,
269                       Reader<T>::readLE);
270 #else
271   TestBulkSwapToSub(NoSwap, aBytes, copyAndSwapToBigEndian<T>,
272                     Reader<T>::readBE);
273   TestBulkSwapFromSub(NoSwap, aBytes, copyAndSwapFromBigEndian<T>,
274                       Reader<T>::readBE);
275   TestBulkSwapToSub(NoSwap, aBytes, copyAndSwapToNetworkOrder<T>,
276                     Reader<T>::readBE);
277   TestBulkSwapFromSub(NoSwap, aBytes, copyAndSwapFromNetworkOrder<T>,
278                       Reader<T>::readBE);
279 #endif
280 }
281 
282 template<typename T, size_t Count>
283 void
TestBulkInPlaceSwap(const T (& aBytes)[Count])284 TestBulkInPlaceSwap(const T (&aBytes)[Count])
285 {
286 #if MOZ_LITTLE_ENDIAN
287   TestBulkInPlaceSub(Swap, aBytes, swapToBigEndianInPlace<T>,
288                      Reader<T>::readBE);
289   TestBulkInPlaceSub(Swap, aBytes, swapFromBigEndianInPlace<T>,
290                      Reader<T>::readBE);
291   TestBulkInPlaceSub(Swap, aBytes, swapToNetworkOrderInPlace<T>,
292                      Reader<T>::readBE);
293   TestBulkInPlaceSub(Swap, aBytes, swapFromNetworkOrderInPlace<T>,
294                      Reader<T>::readBE);
295 #else
296   TestBulkInPlaceSub(Swap, aBytes, swapToLittleEndianInPlace<T>,
297                      Reader<T>::readLE);
298   TestBulkInPlaceSub(Swap, aBytes, swapFromLittleEndianInPlace<T>,
299                      Reader<T>::readLE);
300 #endif
301 }
302 
303 template<typename T, size_t Count>
304 void
TestBulkInPlaceNoSwap(const T (& aBytes)[Count])305 TestBulkInPlaceNoSwap(const T (&aBytes)[Count])
306 {
307 #if MOZ_LITTLE_ENDIAN
308   TestBulkInPlaceSub(NoSwap, aBytes, swapToLittleEndianInPlace<T>,
309                      Reader<T>::readLE);
310   TestBulkInPlaceSub(NoSwap, aBytes, swapFromLittleEndianInPlace<T>,
311                      Reader<T>::readLE);
312 #else
313   TestBulkInPlaceSub(NoSwap, aBytes, swapToBigEndianInPlace<T>,
314                      Reader<T>::readBE);
315   TestBulkInPlaceSub(NoSwap, aBytes, swapFromBigEndianInPlace<T>,
316                      Reader<T>::readBE);
317   TestBulkInPlaceSub(NoSwap, aBytes, swapToNetworkOrderInPlace<T>,
318                      Reader<T>::readBE);
319   TestBulkInPlaceSub(NoSwap, aBytes, swapFromNetworkOrderInPlace<T>,
320                      Reader<T>::readBE);
321 #endif
322 }
323 
324 int
main()325 main()
326 {
327   static const uint8_t unsigned_bytes[16] = {
328     0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
329     0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8
330   };
331   static const int8_t signed_bytes[16] = {
332     -0x0f, -0x0e, -0x0d, -0x0c, -0x0b, -0x0a, -0x09, -0x08,
333     -0x0f, -0x0e, -0x0d, -0x0c, -0x0b, -0x0a, -0x09, -0x08
334   };
335   static const uint16_t uint16_values[8] = {
336     0x102, 0x304, 0x506, 0x708, 0x102, 0x304, 0x506, 0x708
337   };
338   static const int16_t int16_values[8] = {
339     int16_t(0xf1f2), int16_t(0xf3f4), int16_t(0xf5f6), int16_t(0xf7f8),
340     int16_t(0xf1f2), int16_t(0xf3f4), int16_t(0xf5f6), int16_t(0xf7f8)
341   };
342   static const uint32_t uint32_values[4] = {
343     0x1020304, 0x5060708, 0x1020304, 0x5060708
344   };
345   static const int32_t int32_values[4] = {
346     int32_t(0xf1f2f3f4), int32_t(0xf5f6f7f8),
347     int32_t(0xf1f2f3f4), int32_t(0xf5f6f7f8)
348   };
349   static const uint64_t uint64_values[2] = {
350     0x102030405060708, 0x102030405060708
351   };
352   static const int64_t int64_values[2] = {
353     int64_t(0xf1f2f3f4f5f6f7f8), int64_t(0xf1f2f3f4f5f6f7f8)
354   };
355   uint8_t buffer[8];
356 
357   MOZ_RELEASE_ASSERT(LittleEndian::readUint16(&unsigned_bytes[0]) == 0x201);
358   MOZ_RELEASE_ASSERT(BigEndian::readUint16(&unsigned_bytes[0]) == 0x102);
359 
360   MOZ_RELEASE_ASSERT(
361     LittleEndian::readUint32(&unsigned_bytes[0]) == 0x4030201U);
362   MOZ_RELEASE_ASSERT(
363     BigEndian::readUint32(&unsigned_bytes[0]) == 0x1020304U);
364 
365   MOZ_RELEASE_ASSERT(
366     LittleEndian::readUint64(&unsigned_bytes[0]) == 0x807060504030201ULL);
367   MOZ_RELEASE_ASSERT(
368     BigEndian::readUint64(&unsigned_bytes[0]) == 0x102030405060708ULL);
369 
370   LittleEndian::writeUint16(&buffer[0], 0x201);
371   MOZ_RELEASE_ASSERT(
372     memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint16_t)) == 0);
373   BigEndian::writeUint16(&buffer[0], 0x102);
374   MOZ_RELEASE_ASSERT(
375     memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint16_t)) == 0);
376 
377   LittleEndian::writeUint32(&buffer[0], 0x4030201U);
378   MOZ_RELEASE_ASSERT(
379     memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint32_t)) == 0);
380   BigEndian::writeUint32(&buffer[0], 0x1020304U);
381   MOZ_RELEASE_ASSERT(
382     memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint32_t)) == 0);
383 
384   LittleEndian::writeUint64(&buffer[0], 0x807060504030201ULL);
385   MOZ_RELEASE_ASSERT(
386     memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint64_t)) == 0);
387   BigEndian::writeUint64(&buffer[0], 0x102030405060708ULL);
388   MOZ_RELEASE_ASSERT(
389     memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint64_t)) == 0);
390 
391   MOZ_RELEASE_ASSERT(
392     LittleEndian::readInt16(&signed_bytes[0]) == int16_t(0xf2f1));
393   MOZ_RELEASE_ASSERT(
394     BigEndian::readInt16(&signed_bytes[0]) == int16_t(0xf1f2));
395 
396   MOZ_RELEASE_ASSERT(
397     LittleEndian::readInt32(&signed_bytes[0]) == int32_t(0xf4f3f2f1));
398   MOZ_RELEASE_ASSERT(
399     BigEndian::readInt32(&signed_bytes[0]) == int32_t(0xf1f2f3f4));
400 
401   MOZ_RELEASE_ASSERT(
402     LittleEndian::readInt64(&signed_bytes[0]) == int64_t(0xf8f7f6f5f4f3f2f1LL));
403   MOZ_RELEASE_ASSERT(
404     BigEndian::readInt64(&signed_bytes[0]) == int64_t(0xf1f2f3f4f5f6f7f8LL));
405 
406   LittleEndian::writeInt16(&buffer[0], int16_t(0xf2f1));
407   MOZ_RELEASE_ASSERT(
408     memcmp(&signed_bytes[0], &buffer[0], sizeof(int16_t)) == 0);
409   BigEndian::writeInt16(&buffer[0], int16_t(0xf1f2));
410   MOZ_RELEASE_ASSERT(
411     memcmp(&signed_bytes[0], &buffer[0], sizeof(int16_t)) == 0);
412 
413   LittleEndian::writeInt32(&buffer[0], 0xf4f3f2f1);
414   MOZ_RELEASE_ASSERT(
415     memcmp(&signed_bytes[0], &buffer[0], sizeof(int32_t)) == 0);
416   BigEndian::writeInt32(&buffer[0], 0xf1f2f3f4);
417   MOZ_RELEASE_ASSERT(
418     memcmp(&signed_bytes[0], &buffer[0], sizeof(int32_t)) == 0);
419 
420   LittleEndian::writeInt64(&buffer[0], 0xf8f7f6f5f4f3f2f1LL);
421   MOZ_RELEASE_ASSERT(
422     memcmp(&signed_bytes[0], &buffer[0], sizeof(int64_t)) == 0);
423   BigEndian::writeInt64(&buffer[0], 0xf1f2f3f4f5f6f7f8LL);
424   MOZ_RELEASE_ASSERT(
425     memcmp(&signed_bytes[0], &buffer[0], sizeof(int64_t)) == 0);
426 
427   TestSingleSwap(uint16_t(0xf2f1), uint16_t(0xf1f2));
428   TestSingleSwap(uint32_t(0xf4f3f2f1), uint32_t(0xf1f2f3f4));
429   TestSingleSwap(uint64_t(0xf8f7f6f5f4f3f2f1), uint64_t(0xf1f2f3f4f5f6f7f8));
430 
431   TestSingleSwap(int16_t(0xf2f1), int16_t(0xf1f2));
432   TestSingleSwap(int32_t(0xf4f3f2f1), int32_t(0xf1f2f3f4));
433   TestSingleSwap(int64_t(0xf8f7f6f5f4f3f2f1), int64_t(0xf1f2f3f4f5f6f7f8));
434 
435   TestSingleNoSwap(uint16_t(0xf2f1), uint16_t(0xf2f1));
436   TestSingleNoSwap(uint32_t(0xf4f3f2f1), uint32_t(0xf4f3f2f1));
437   TestSingleNoSwap(uint64_t(0xf8f7f6f5f4f3f2f1), uint64_t(0xf8f7f6f5f4f3f2f1));
438 
439   TestSingleNoSwap(int16_t(0xf2f1), int16_t(0xf2f1));
440   TestSingleNoSwap(int32_t(0xf4f3f2f1), int32_t(0xf4f3f2f1));
441   TestSingleNoSwap(int64_t(0xf8f7f6f5f4f3f2f1), int64_t(0xf8f7f6f5f4f3f2f1));
442 
443   TestBulkSwap(uint16_values);
444   TestBulkSwap(int16_values);
445   TestBulkSwap(uint32_values);
446   TestBulkSwap(int32_values);
447   TestBulkSwap(uint64_values);
448   TestBulkSwap(int64_values);
449 
450   TestBulkNoSwap(uint16_values);
451   TestBulkNoSwap(int16_values);
452   TestBulkNoSwap(uint32_values);
453   TestBulkNoSwap(int32_values);
454   TestBulkNoSwap(uint64_values);
455   TestBulkNoSwap(int64_values);
456 
457   TestBulkInPlaceSwap(uint16_values);
458   TestBulkInPlaceSwap(int16_values);
459   TestBulkInPlaceSwap(uint32_values);
460   TestBulkInPlaceSwap(int32_values);
461   TestBulkInPlaceSwap(uint64_values);
462   TestBulkInPlaceSwap(int64_values);
463 
464   TestBulkInPlaceNoSwap(uint16_values);
465   TestBulkInPlaceNoSwap(int16_values);
466   TestBulkInPlaceNoSwap(uint32_values);
467   TestBulkInPlaceNoSwap(int32_values);
468   TestBulkInPlaceNoSwap(uint64_values);
469   TestBulkInPlaceNoSwap(int64_values);
470 
471   return 0;
472 }
473