blob: 4a3c1b4726d6817187ae4e43f02514aeb3a96b38 [file] [log] [blame]
Max53777012014-06-04 19:07:41 +02001#include <inttypes.h>
Harald Welte712691d2011-09-01 14:47:31 +02002#include <stdio.h>
3#include <stdlib.h>
4#include <stdint.h>
5#include <string.h>
Max53777012014-06-04 19:07:41 +02006#include <time.h>
7#include <stdbool.h>
Harald Welte712691d2011-09-01 14:47:31 +02008
9#include <osmocom/core/utils.h>
10#include <osmocom/core/bits.h>
11
12static const uint8_t input[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
13static const uint8_t exp_out[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
Max53777012014-06-04 19:07:41 +020014static char s[18];
15
16enum END {LE, BE};
17
Sylvain Munaut26ea7062014-06-16 15:57:36 +020018static inline const char *
19end2str(enum END e)
20{
Max53777012014-06-04 19:07:41 +020021 if (e == LE) return "LE";
22 return "BE";
23}
24
25
26/* convenience wrappers */
27
Sylvain Munaut26ea7062014-06-16 15:57:36 +020028static inline uint64_t
29load64(enum END e, const uint8_t *buf, unsigned nbytes)
30{
Max53777012014-06-04 19:07:41 +020031 return (e == BE) ? osmo_load64be_ext(buf, nbytes) : osmo_load64le_ext(buf, nbytes);
32}
33
Sylvain Munaut26ea7062014-06-16 15:57:36 +020034static inline uint32_t
35load32(enum END e, const uint8_t *buf, unsigned nbytes)
36{
Max53777012014-06-04 19:07:41 +020037 return (e == BE) ? osmo_load32be_ext(buf, nbytes) : osmo_load32le_ext(buf, nbytes);
38}
39
Sylvain Munaut26ea7062014-06-16 15:57:36 +020040static inline uint16_t
41load16(enum END e, const uint8_t *buf)
42{
Max53777012014-06-04 19:07:41 +020043 return (e == BE) ? osmo_load16be(buf) : osmo_load16le(buf);
44}
45
Sylvain Munaut26ea7062014-06-16 15:57:36 +020046static inline void
47store64(enum END e, uint64_t t, uint8_t *buf, unsigned nbytes)
48{
Max53777012014-06-04 19:07:41 +020049 (e == BE) ? osmo_store64be_ext(t, buf, nbytes) : osmo_store64le_ext(t, buf, nbytes);
50}
51
Sylvain Munaut26ea7062014-06-16 15:57:36 +020052static inline void
53store32(enum END e, uint64_t t, uint8_t *buf, unsigned nbytes)
54{
Max53777012014-06-04 19:07:41 +020055 (e == BE) ? osmo_store32be_ext(t, buf, nbytes) : osmo_store32le_ext(t, buf, nbytes);
56}
57
Sylvain Munaut26ea7062014-06-16 15:57:36 +020058static inline void
59store16(enum END e, uint64_t t, uint8_t *buf)
60{
Max53777012014-06-04 19:07:41 +020061 (e == BE) ? osmo_store16be(t, buf) : osmo_store16le(t, buf);
62}
63
64
65/* helper functions */
66
Sylvain Munaut26ea7062014-06-16 15:57:36 +020067static inline bool
68printcheck(bool chk, unsigned nbytes, enum END e, bool b)
Max53777012014-06-04 19:07:41 +020069{
70 if (!chk) {
71 printf("%u %s FAILED", nbytes * 8, end2str(e));
72 return true;
73 }
74 printf("%u %s OK", nbytes * 8, end2str(e));
75 return b;
76}
77
Sylvain Munaut26ea7062014-06-16 15:57:36 +020078static inline bool
79dumpcheck(const char *dump, const char *s, unsigned nbytes, bool chk, enum END e, bool b)
Max53777012014-06-04 19:07:41 +020080{
81 bool x = printcheck(chk, nbytes, e, b);
82 if (!dump) return x;
83
84 int m = memcmp(s, dump, nbytes);
85 if (0 == m) {
86 printf(", storage OK");
87 return x;
88 }
89 printf(", [%d]", m);
90
91 return true;
92}
93
94
95/* printcheckXX(): load/store 'test' and check against 'expected' value, compare to 'dump' buffer if given and print if necessary */
96
Sylvain Munaut26ea7062014-06-16 15:57:36 +020097static inline void
98printcheck64(enum END e, unsigned nbytes, uint64_t test, uint64_t expected, const char *dump, bool print)
Max53777012014-06-04 19:07:41 +020099{
100 uint8_t buf[nbytes];
101
102 store64(e, test, buf, nbytes);
103
104 char *s = osmo_hexdump_nospc(buf, nbytes);
105 uint64_t result = load64(e, buf, nbytes);
106
107 print = dumpcheck(dump, s, nbytes, result == expected, e, print);
108
109 if (print)
110 printf(": buffer %s known buffer %s loaded %.16" PRIx64 " expected %.16" PRIx64, s, dump, result, expected);
111 printf("\n");
112}
113
Sylvain Munaut26ea7062014-06-16 15:57:36 +0200114static inline void
115printcheck32(enum END e, unsigned nbytes, uint32_t test, uint32_t expected, const char *dump, bool print)
Max53777012014-06-04 19:07:41 +0200116{
117 uint8_t buf[nbytes];
118
119 store32(e, test, buf, nbytes);
120
121 char *s = osmo_hexdump_nospc(buf, nbytes);
122 uint32_t result = load32(e, buf, nbytes);
123
124 print = dumpcheck(dump, s, nbytes, result == expected, e, print);
125
126 if (print)
127 printf(": buffer %s known buffer %s loaded %.8" PRIx32 " expected %.8" PRIx32, s, dump, result, expected);
128 printf("\n");
129}
130
Sylvain Munaut26ea7062014-06-16 15:57:36 +0200131static inline void
132printcheck16(enum END e, uint32_t test, uint32_t expected, const char *dump, bool print)
Max53777012014-06-04 19:07:41 +0200133{
134 uint8_t buf[2];
135
136 store16(e, test, buf);
137
138 char *s = osmo_hexdump_nospc(buf, 2);
139 uint16_t result = load16(e, buf);
140
141 print = dumpcheck(dump, s, 2, result == expected, e, print);
142
143 if (print)
144 printf(": buffer %s known buffer %s loaded %.4" PRIx16 " expected %.4" PRIx16, s, dump, result, expected);
145 printf("\n");
146}
147
148
149/* compute expected value - zero excessive bytes */
150
Sylvain Munaut26ea7062014-06-16 15:57:36 +0200151static inline uint64_t
152exp64(enum END e, unsigned nbytes, uint64_t value)
153{
Max53777012014-06-04 19:07:41 +0200154 uint8_t adj = 64 - nbytes * 8;
155 uint64_t v = value << adj;
156 return (e == LE) ? v >> adj : v;
157}
158
Sylvain Munaut26ea7062014-06-16 15:57:36 +0200159static inline uint32_t
160exp32(enum END e, unsigned nbytes, uint32_t value)
161{
Max53777012014-06-04 19:07:41 +0200162 uint8_t adj = 32 - nbytes * 8;
163 uint32_t v = value << adj;
164 return (e == LE) ? v >> adj : v;
165}
166
167
168/* run actual tests - if 'test' is 0 than generate random test value internally */
169
Sylvain Munaut26ea7062014-06-16 15:57:36 +0200170static inline void
171check64(uint64_t test, uint64_t expected, unsigned nbytes, enum END e)
Max53777012014-06-04 19:07:41 +0200172{
173 bool print = true;
174 if (0 == test && 0 == expected) {
175 test = ((uint64_t)rand() << 32) + rand();
176 expected = exp64(e, nbytes, test);
177 print = false;
178 }
179 snprintf(s, 17, "%.16" PRIx64, expected);
180 printcheck64(e, nbytes, test, expected, (BE == e) ? s : NULL, print);
181}
182
Sylvain Munaut26ea7062014-06-16 15:57:36 +0200183static inline void
184check32(uint32_t test, uint32_t expected, unsigned nbytes, enum END e)
Max53777012014-06-04 19:07:41 +0200185{
186 bool print = true;
187 if (0 == test && 0 == expected) {
188 test = rand();
189 expected = exp32(e, nbytes, test);
190 print = false;
191 }
192 snprintf(s, 17, "%.8" PRIx32, expected);
193 printcheck32(e, nbytes, test, expected, (BE == e) ? s : NULL, print);
194}
195
Sylvain Munaut26ea7062014-06-16 15:57:36 +0200196static inline void
197check16(uint16_t test, enum END e)
Max53777012014-06-04 19:07:41 +0200198{
199 bool print = true;
200 if (0 == test) {
201 test = (uint16_t)rand();
202 print = false;
203 }
204 snprintf(s, 17, "%.4" PRIx16, test);
205 printcheck16(e, test, test, (BE == e) ? s : NULL, print);
206}
207
Maxe0a7d9e2016-06-17 17:58:52 +0200208static void sh_chk(const uint8_t *in, uint8_t len, unsigned int nib, bool r)
209{
210 uint8_t x[len];
Neels Hofmeyr8319a672016-09-21 18:30:01 +0200211 int bytes = nib/2 + (nib & 1);
212 OSMO_ASSERT(len >= bytes);
213 memset(x, 0xcc, len);
Maxe0a7d9e2016-06-17 17:58:52 +0200214 if (r)
215 osmo_nibble_shift_right(x, in, nib);
216 else
217 osmo_nibble_shift_left_unal(x, in, nib);
218
219 printf("[%u] %s IN: %s, nibble %u:", len, r ? "R" : "L",
220 osmo_hexdump_nospc(in, len), nib);
221 /* do NOT combine those printfs: osmo_hexdump* use static buffer which
222 WILL screw things up in that case */
Neels Hofmeyr8319a672016-09-21 18:30:01 +0200223 printf("\n OUT: %s\n", osmo_hexdump_nospc(x, bytes));
Maxe0a7d9e2016-06-17 17:58:52 +0200224}
Harald Welte712691d2011-09-01 14:47:31 +0200225
226int main(int argc, char **argv)
227{
228 uint8_t out[ARRAY_SIZE(input)];
229 unsigned int offs;
230
Max53777012014-06-04 19:07:41 +0200231 srand(time(NULL));
232
Harald Welte712691d2011-09-01 14:47:31 +0200233 for (offs = 0; offs < sizeof(out); offs++) {
234 uint8_t *start = out + offs;
235 uint8_t len = sizeof(out) - offs;
236
237 memcpy(out, input, sizeof(out));
238
239 printf("INORDER: %s\n", osmo_hexdump(start, len));
240 osmo_revbytebits_buf(start, len);
241 printf("REVERSED: %s\n", osmo_hexdump(start, len));
242 if (memcmp(start, exp_out + offs, len)) {
243 printf("EXPECTED: %s\n", osmo_hexdump(exp_out+offs, len));
244 fprintf(stderr, "REVERSED != EXPECTED!\n");
245 exit(1);
246 }
247 printf("\n");
248 }
249
Max53777012014-06-04 19:07:41 +0200250 printf("checking byte packing...\n");
251
252 printf("running static tests...\n");
253
254 check64(0xDEADBEEFF00DCAFE, 0xDEADBEEFF00DCAFE, 8, BE);
255 check64(0xDEADBEEFF00DCAFE, 0xADBEEFF00DCAFE00, 7, BE);
256 check64(0xDEADBEEFF00DCAFE, 0xBEEFF00DCAFE0000, 6, BE);
257 check64(0xDEADBEEFF00DCAFE, 0xEFF00DCAFE000000, 5, BE);
258
259 check64(0xDEADBEEFF00DCAFE, 0xDEADBEEFF00DCAFE, 8, LE);
260 check64(0xDEADBEEFF00DCAFE, 0x00ADBEEFF00DCAFE, 7, LE);
261 check64(0xDEADBEEFF00DCAFE, 0x0000BEEFF00DCAFE, 6, LE);
262 check64(0xDEADBEEFF00DCAFE, 0x000000EFF00DCAFE, 5, LE);
263
264 check32(0xBABEFACE, 0xBABEFACE, 4, BE);
265 check32(0xBABEFACE, 0xBEFACE00, 3, BE);
266
267 check32(0xBABEFACE, 0xBABEFACE, 4, LE);
268 check32(0xBABEFACE, 0x00BEFACE, 3, LE);
269
270 check16(0xB00B, BE);
271 check16(0xB00B, LE);
272
273 printf("running random tests...\n");
274
275 check64(0, 0, 8, BE);
276 check64(0, 0, 7, BE);
277 check64(0, 0, 6, BE);
278 check64(0, 0, 5, BE);
279
280 check64(0, 0, 8, LE);
281 check64(0, 0, 7, LE);
282 check64(0, 0, 6, LE);
283 check64(0, 0, 5, LE);
284
285 check32(0, 0, 4, BE);
286 check32(0, 0, 3, BE);
287
288 check32(0, 0, 4, LE);
289 check32(0, 0, 3, LE);
290
291 check16(0, BE);
292 check16(0, LE);
293
Maxe0a7d9e2016-06-17 17:58:52 +0200294 printf("running nibble tests...\n");
295
296 const uint8_t in1[] = { 0xF0, 0x0D, 0xCA, 0xFE, 0xDE, 0xAD, 0xBE, 0xEF },
297 in2[] = { 0xB0, 0x0B, 0xBA, 0xBE, 0xFA, 0xCE };
298
299 for (offs = 0; offs < 13; offs++) {
300 sh_chk(in1, ARRAY_SIZE(in1), offs, true);
301 sh_chk(in1, ARRAY_SIZE(in1), offs, false);
Max4fd60232016-09-20 16:33:50 +0200302 /* in2 is too short to shift left 12 nibbles */
Pau Espin Pedrolc5c955c2018-05-16 17:07:27 +0200303 if (offs < 12) {
304 sh_chk(in2, ARRAY_SIZE(in2), offs, true);
Max4fd60232016-09-20 16:33:50 +0200305 sh_chk(in2, ARRAY_SIZE(in2), offs, false);
Pau Espin Pedrolc5c955c2018-05-16 17:07:27 +0200306 }
Maxe0a7d9e2016-06-17 17:58:52 +0200307 }
Harald Welte712691d2011-09-01 14:47:31 +0200308 return 0;
309}