1 /*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2017 Roman Lebedev
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "EndiannessTest.h"
22 #include "io/Endianness.h" // for getHostEndianness, Endianness, getByteSwa...
23 #include <cstring> // for memcpy, memcmp
24 #include <gtest/gtest.h> // for ParamIteratorInterface, Message, TestPart...
25 #include <iomanip> // for setfill, setw, _Setw, _Setfill
26 #include <iostream> // for hex, endl, ostream
27
28 using rawspeed::Endianness;
29 using rawspeed::getBE;
30 using rawspeed::getByteSwapped;
31 using rawspeed::getHostEndianness;
32 using rawspeed::getHostEndiannessRuntime;
33 using rawspeed::getLE;
34 using rawspeed::getU16BE;
35 using rawspeed::getU16LE;
36 using rawspeed::getU32BE;
37 using rawspeed::getU32LE;
38 using std::setfill;
39 using std::setw;
40
41 namespace rawspeed_test {
42
TEST(EndiannessTest,getHostEndiannessTests)43 TEST(EndiannessTest, getHostEndiannessTests) {
44 #if defined(__BYTE_ORDER__)
45 ASSERT_EQ(getHostEndiannessRuntime(), getHostEndianness());
46 #endif
47 }
48
49 /*
50 #!/bin/bash
51 d=16 # squared, how many samples
52 # B=2 # sizeof, bytes
53 b=x # print format
54 p="0x" # print prefix
55 function proc {
56 echo "$1" | od -A n --endian="$2" -t $3$B -N $B -w$B | tr -d ''
57 }
58 function pp {
59 v=$(proc "$1" "$2" "$b")
60 echo $p$v
61 }
62 for i in $(seq $d)
63 do
64 for j in $(seq $d);
65 do
66 v=$(dd if=/dev/urandom bs=$B conv=sparse count=1 status=none)
67 x=$(pp "$v" little);
68 y=$(pp "$v" big);
69 echo "{$x, $y},";
70 done;
71 done;
72 */
73
74 #define setupHex setfill('0') << setw(2 * sizeof(T)) << std::hex
75
76 template <typename T>
operator <<(::std::ostream & os,const intPair<T> & p)77 ::std::ostream& operator<<(::std::ostream& os, const intPair<T>& p) {
78 ::testing::Message msg;
79 msg << "(0x" << setupHex << p.first << ", 0x" << setupHex << p.second << ")";
80
81 return os << msg;
82 }
83
84 // no polymorphic lambda till c++14
85 struct HexEquals {
86 template <typename T>
operator ()rawspeed_test::HexEquals87 ::testing::AssertionResult operator()(const char* darg1, const char* darg2,
88 const T& arg1, const T& arg2) {
89 if (memcmp(&arg1, &arg2, sizeof(T)) == 0)
90 return ::testing::AssertionSuccess();
91
92 ::testing::Message msg;
93 msg << " Expected: " << darg1 << std::endl;
94 msg << " Which is: " << setupHex << arg1 << std::endl;
95 msg << "To be equal to: " << darg2 << std::endl;
96 msg << " Which is: " << setupHex << arg2;
97
98 return ::testing::AssertionFailure() << msg;
99 }
100 };
101
102 #undef setupHex
103
104 template <class T1, class T2>
105 class AbstractGetByteSwappedTest : public ::testing::TestWithParam<T1> {
106 protected:
107 AbstractGetByteSwappedTest() = default;
SetUp()108 virtual void SetUp() {
109 auto p = this->GetParam();
110 auto v = std::get<0>(p);
111
112 // swap them around? the test is symmetrical
113 if (std::get<1>(p)) {
114 memcpy(&in, &(v.first), sizeof(T2));
115 memcpy(&expected, &(v.second), sizeof(T2));
116 } else {
117 memcpy(&in, &(v.second), sizeof(T2));
118 memcpy(&expected, &(v.first), sizeof(T2));
119 }
120 }
getByteSwappedT(const void * data,bool bswap)121 T2 getByteSwappedT(const void* data, bool bswap) {
122 return getByteSwapped<T2>(data, bswap);
123 }
getBEt(const void * data)124 T2 getBEt(const void* data) { return getBE<T2>(data); }
getLEt(const void * data)125 T2 getLEt(const void* data) { return getLE<T2>(data); }
126
127 T2 in; // input
128 T2 expected; // expected output
129 };
130
131 /*
132 B=2 # sizeof, bytes
133 */
134 class ushort16Test
135 : public AbstractGetByteSwappedTest<ushort16TType, uint16_t> {};
136 INSTANTIATE_TEST_CASE_P(ushort16Test, ushort16Test,
137 ::testing::Combine(::testing::ValuesIn(ushort16Values),
138 ::testing::Bool()));
TEST_P(ushort16Test,swap)139 TEST_P(ushort16Test, swap) {
140 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwapped(in), expected);
141 }
TEST_P(ushort16Test,NOP)142 TEST_P(ushort16Test, NOP) {
143 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, false), in);
144 }
TEST_P(ushort16Test,typedSwap)145 TEST_P(ushort16Test, typedSwap) {
146 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, true), expected);
147 }
TEST_P(ushort16Test,get)148 TEST_P(ushort16Test, get) {
149 if (getHostEndianness() == Endianness::little) {
150 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), expected);
151 } else if (getHostEndianness() == Endianness::big) {
152 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), expected);
153 }
154 }
TEST_P(ushort16Test,getNOP)155 TEST_P(ushort16Test, getNOP) {
156 if (getHostEndianness() == Endianness::little) {
157 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), in);
158 } else if (getHostEndianness() == Endianness::big) {
159 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), in);
160 }
161 }
162
TEST_P(ushort16Test,getU16)163 TEST_P(ushort16Test, getU16) {
164 if (getHostEndianness() == Endianness::little) {
165 ASSERT_PRED_FORMAT2(HexEquals{}, getU16BE(&in), expected);
166 } else if (getHostEndianness() == Endianness::big) {
167 ASSERT_PRED_FORMAT2(HexEquals{}, getU16LE(&in), expected);
168 }
169 }
TEST_P(ushort16Test,getU16NOP)170 TEST_P(ushort16Test, getU16NOP) {
171 if (getHostEndianness() == Endianness::little) {
172 ASSERT_PRED_FORMAT2(HexEquals{}, getU16LE(&in), in);
173 } else if (getHostEndianness() == Endianness::big) {
174 ASSERT_PRED_FORMAT2(HexEquals{}, getU16BE(&in), in);
175 }
176 }
177
178 class short16Test : public AbstractGetByteSwappedTest<ushort16TType, int16_t> {
179 };
180 INSTANTIATE_TEST_CASE_P(short16Test, short16Test,
181 ::testing::Combine(::testing::ValuesIn(ushort16Values),
182 ::testing::Bool()));
TEST_P(short16Test,swap)183 TEST_P(short16Test, swap) {
184 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwapped(in), expected);
185 }
TEST_P(short16Test,NOP)186 TEST_P(short16Test, NOP) {
187 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, false), in);
188 }
TEST_P(short16Test,typedSwap)189 TEST_P(short16Test, typedSwap) {
190 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, true), expected);
191 }
TEST_P(short16Test,get)192 TEST_P(short16Test, get) {
193 if (getHostEndianness() == Endianness::little) {
194 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), expected);
195 } else if (getHostEndianness() == Endianness::big) {
196 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), expected);
197 }
198 }
TEST_P(short16Test,getNOP)199 TEST_P(short16Test, getNOP) {
200 if (getHostEndianness() == Endianness::little) {
201 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), in);
202 } else if (getHostEndianness() == Endianness::big) {
203 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), in);
204 }
205 }
206
207 /*
208 B=4 # sizeof, bytes
209 */
210 class uint32Test : public AbstractGetByteSwappedTest<uint32TType, uint32_t> {};
211 INSTANTIATE_TEST_CASE_P(uint32Test, uint32Test,
212 ::testing::Combine(::testing::ValuesIn(uint32Values),
213 ::testing::Bool()));
TEST_P(uint32Test,swap)214 TEST_P(uint32Test, swap) {
215 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwapped(in), expected);
216 }
TEST_P(uint32Test,NOP)217 TEST_P(uint32Test, NOP) {
218 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, false), in);
219 }
TEST_P(uint32Test,typedSwap)220 TEST_P(uint32Test, typedSwap) {
221 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, true), expected);
222 }
TEST_P(uint32Test,get)223 TEST_P(uint32Test, get) {
224 if (getHostEndianness() == Endianness::little) {
225 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), expected);
226 } else if (getHostEndianness() == Endianness::big) {
227 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), expected);
228 }
229 }
TEST_P(uint32Test,getNOP)230 TEST_P(uint32Test, getNOP) {
231 if (getHostEndianness() == Endianness::little) {
232 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), in);
233 } else if (getHostEndianness() == Endianness::big) {
234 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), in);
235 }
236 }
237
TEST_P(uint32Test,getU32)238 TEST_P(uint32Test, getU32) {
239 if (getHostEndianness() == Endianness::little) {
240 ASSERT_PRED_FORMAT2(HexEquals{}, getU32BE(&in), expected);
241 } else if (getHostEndianness() == Endianness::big) {
242 ASSERT_PRED_FORMAT2(HexEquals{}, getU32LE(&in), expected);
243 }
244 }
TEST_P(uint32Test,getU32NOP)245 TEST_P(uint32Test, getU32NOP) {
246 if (getHostEndianness() == Endianness::little) {
247 ASSERT_PRED_FORMAT2(HexEquals{}, getU32LE(&in), in);
248 } else if (getHostEndianness() == Endianness::big) {
249 ASSERT_PRED_FORMAT2(HexEquals{}, getU32BE(&in), in);
250 }
251 }
252
253 class int32Test : public AbstractGetByteSwappedTest<uint32TType, int32_t> {};
254 INSTANTIATE_TEST_CASE_P(int32Test, int32Test,
255 ::testing::Combine(::testing::ValuesIn(uint32Values),
256 ::testing::Bool()));
TEST_P(int32Test,swap)257 TEST_P(int32Test, swap) {
258 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwapped(in), expected);
259 }
TEST_P(int32Test,NOP)260 TEST_P(int32Test, NOP) {
261 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, false), in);
262 }
TEST_P(int32Test,typedSwap)263 TEST_P(int32Test, typedSwap) {
264 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, true), expected);
265 }
TEST_P(int32Test,get)266 TEST_P(int32Test, get) {
267 if (getHostEndianness() == Endianness::little) {
268 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), expected);
269 } else if (getHostEndianness() == Endianness::big) {
270 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), expected);
271 }
272 }
TEST_P(int32Test,getNOP)273 TEST_P(int32Test, getNOP) {
274 if (getHostEndianness() == Endianness::little) {
275 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), in);
276 } else if (getHostEndianness() == Endianness::big) {
277 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), in);
278 }
279 }
280
281 /*
282 B=8 # sizeof, bytes
283 */
284 class uint64Test : public AbstractGetByteSwappedTest<uint64TType, uint64_t> {};
285 INSTANTIATE_TEST_CASE_P(uint64Test, uint64Test,
286 ::testing::Combine(::testing::ValuesIn(uint64Values),
287 ::testing::Bool()));
TEST_P(uint64Test,swap)288 TEST_P(uint64Test, swap) {
289 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwapped(in), expected);
290 }
TEST_P(uint64Test,NOP)291 TEST_P(uint64Test, NOP) {
292 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, false), in);
293 }
TEST_P(uint64Test,typedSwap)294 TEST_P(uint64Test, typedSwap) {
295 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, true), expected);
296 }
TEST_P(uint64Test,get)297 TEST_P(uint64Test, get) {
298 if (getHostEndianness() == Endianness::little) {
299 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), expected);
300 } else if (getHostEndianness() == Endianness::big) {
301 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), expected);
302 }
303 }
TEST_P(uint64Test,getNOP)304 TEST_P(uint64Test, getNOP) {
305 if (getHostEndianness() == Endianness::little) {
306 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), in);
307 } else if (getHostEndianness() == Endianness::big) {
308 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), in);
309 }
310 }
311
312 class floatTest : public AbstractGetByteSwappedTest<uint32TType, float> {};
313 INSTANTIATE_TEST_CASE_P(floatTest, floatTest,
314 ::testing::Combine(::testing::ValuesIn(uint32Values),
315 ::testing::Bool()));
TEST_P(floatTest,swap)316 TEST_P(floatTest, swap) {
317 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwapped(in), expected);
318 }
TEST_P(floatTest,NOP)319 TEST_P(floatTest, NOP) {
320 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, false), in);
321 }
TEST_P(floatTest,typedSwap)322 TEST_P(floatTest, typedSwap) {
323 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, true), expected);
324 }
TEST_P(floatTest,get)325 TEST_P(floatTest, get) {
326 if (getHostEndianness() == Endianness::little) {
327 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), expected);
328 } else if (getHostEndianness() == Endianness::big) {
329 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), expected);
330 }
331 }
TEST_P(floatTest,getNOP)332 TEST_P(floatTest, getNOP) {
333 if (getHostEndianness() == Endianness::little) {
334 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), in);
335 } else if (getHostEndianness() == Endianness::big) {
336 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), in);
337 }
338 }
339
340 class doubleTest : public AbstractGetByteSwappedTest<uint64TType, double> {};
341 INSTANTIATE_TEST_CASE_P(doubleTest, doubleTest,
342 ::testing::Combine(::testing::ValuesIn(uint64Values),
343 ::testing::Bool()));
TEST_P(doubleTest,swap)344 TEST_P(doubleTest, swap) {
345 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwapped(in), expected);
346 }
TEST_P(doubleTest,NOP)347 TEST_P(doubleTest, NOP) {
348 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, false), in);
349 }
TEST_P(doubleTest,typedSwap)350 TEST_P(doubleTest, typedSwap) {
351 ASSERT_PRED_FORMAT2(HexEquals{}, getByteSwappedT(&in, true), expected);
352 }
TEST_P(doubleTest,get)353 TEST_P(doubleTest, get) {
354 if (getHostEndianness() == Endianness::little) {
355 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), expected);
356 } else if (getHostEndianness() == Endianness::big) {
357 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), expected);
358 }
359 }
TEST_P(doubleTest,getNOP)360 TEST_P(doubleTest, getNOP) {
361 if (getHostEndianness() == Endianness::little) {
362 ASSERT_PRED_FORMAT2(HexEquals{}, getLEt(&in), in);
363 } else if (getHostEndianness() == Endianness::big) {
364 ASSERT_PRED_FORMAT2(HexEquals{}, getBEt(&in), in);
365 }
366 }
367
368 } // namespace rawspeed_test
369