]>
Commit | Line | Data |
---|---|---|
f730f6c5 VB |
1 | /* -*- mode: c; c-file-style: "openbsd" -*- */ |
2 | /* | |
3 | * Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx> | |
4 | * | |
5 | * Permission to use, copy, modify, and/or distribute this software for any | |
6 | * purpose with or without fee is hereby granted, provided that the above | |
7 | * copyright notice and this permission notice appear in all copies. | |
8 | * | |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
16 | */ | |
17 | ||
18 | #include <check.h> | |
19 | #include <stdlib.h> | |
20 | ||
21 | #include "../src/lib/fixedpoint.h" | |
22 | ||
23 | #ifdef ENABLE_LLDPMED | |
24 | ||
25 | START_TEST(test_string_parsing_suffix) { | |
26 | char *end; | |
27 | fp_strtofp("4541T", &end, 14, 8); | |
28 | ck_assert_int_eq(*end, 'T'); | |
29 | fp_strtofp("4541.U", &end, 14, 8); | |
30 | ck_assert_int_eq(*end, 'U'); | |
31 | fp_strtofp("4541.676V", &end, 14, 8); | |
32 | ck_assert_int_eq(*end, 'V'); | |
33 | } | |
34 | END_TEST | |
35 | ||
36 | START_TEST(test_string_parsing_positive_int) { | |
37 | struct fp_number fp = fp_strtofp("4541T", NULL, 14, 8); | |
38 | ck_assert_int_eq(fp.integer.bits, 14); | |
39 | ck_assert_int_eq(fp.integer.value, 4541); | |
40 | ck_assert_int_eq(fp.fraction.bits, 8); | |
41 | ck_assert_int_eq(fp.fraction.value, 0); | |
42 | ck_assert_int_eq(fp.fraction.precision, 0); | |
43 | } | |
44 | END_TEST | |
45 | ||
46 | START_TEST(test_string_parsing_negative_int) { | |
47 | struct fp_number fp = fp_strtofp("-4214N", NULL, 14, 8); | |
48 | ck_assert_int_eq(fp.integer.bits, 14); | |
49 | ck_assert_int_eq(fp.integer.value, -4214); | |
50 | ck_assert_int_eq(fp.fraction.bits, 8); | |
51 | ck_assert_int_eq(fp.fraction.value, 0); | |
52 | ck_assert_int_eq(fp.fraction.precision, 0); | |
53 | } | |
54 | END_TEST | |
55 | ||
56 | START_TEST(test_string_parsing_positive_int_overflow) { | |
57 | struct fp_number fp1 = fp_strtofp("4098", NULL, 13, 8); | |
58 | struct fp_number fp2 = fp_strtofp("4096", NULL, 13, 8); | |
59 | struct fp_number fp3 = fp_strtofp("4095", NULL, 13, 8); | |
60 | struct fp_number fp4 = fp_strtofp("4094", NULL, 13, 8); | |
61 | ck_assert_int_eq(fp1.integer.value, 4095); | |
62 | ck_assert_int_eq(fp2.integer.value, 4095); | |
63 | ck_assert_int_eq(fp3.integer.value, 4095); | |
64 | ck_assert_int_eq(fp4.integer.value, 4094); | |
65 | } | |
66 | END_TEST | |
67 | ||
68 | START_TEST(test_string_parsing_negative_int_overflow) { | |
69 | struct fp_number fp1 = fp_strtofp("-4097", NULL, 13, 8); | |
70 | struct fp_number fp2 = fp_strtofp("-4096", NULL, 13, 8); | |
71 | struct fp_number fp3 = fp_strtofp("-4095", NULL, 13, 8); | |
72 | struct fp_number fp4 = fp_strtofp("-4094", NULL, 13, 8); | |
73 | ck_assert_int_eq(fp1.integer.value, -4096); | |
74 | ck_assert_int_eq(fp2.integer.value, -4096); | |
75 | ck_assert_int_eq(fp3.integer.value, -4095); | |
76 | ck_assert_int_eq(fp4.integer.value, -4094); | |
77 | } | |
78 | END_TEST | |
79 | ||
80 | START_TEST(test_string_parsing_positive_float) { | |
81 | struct fp_number fp1 = fp_strtofp("1542.6250E", NULL, 13, 20); | |
82 | ck_assert_int_eq(fp1.integer.value, 1542); | |
83 | ck_assert_int_eq(fp1.fraction.precision, 14); | |
84 | ck_assert_int_eq((fp1.fraction.value * 10000) >> fp1.fraction.bits, 6250); | |
85 | ||
86 | struct fp_number fp2 = fp_strtofp("1542.06250E", NULL, 13, 4); | |
87 | ck_assert_int_eq(fp2.integer.value, 1542); | |
88 | ck_assert_int_eq(fp2.fraction.precision, 4); | |
89 | ck_assert_int_eq((fp2.fraction.value * 10000) >> fp2.fraction.bits, 625); | |
90 | } | |
91 | END_TEST | |
92 | ||
93 | START_TEST(test_string_parsing_negative_float) { | |
94 | struct fp_number fp = fp_strtofp("-11542.6250N", NULL, 15, 4); | |
95 | ck_assert_int_eq(fp.integer.value, -11542); | |
96 | ck_assert_int_eq(fp.fraction.precision, 4); | |
97 | ck_assert_int_eq((fp.fraction.value * 10000) >> fp.fraction.bits, 6250); | |
98 | } | |
99 | END_TEST | |
100 | ||
101 | START_TEST(test_string_parsing_no_fract_part) { | |
102 | struct fp_number fp = fp_strtofp("11542.", NULL, 15, 4); | |
103 | ck_assert_int_eq(fp.integer.value, 11542); | |
104 | ck_assert_int_eq(fp.fraction.value, 0); | |
105 | ck_assert_int_eq(fp.fraction.precision, 1); | |
106 | } | |
107 | END_TEST | |
108 | ||
109 | START_TEST(test_string_parsing_no_int_part) { | |
110 | struct fp_number fp = fp_strtofp(".6250E", NULL, 13, 4); | |
111 | ck_assert_int_eq(fp.integer.value, 0); | |
112 | ck_assert_int_eq(fp.fraction.precision, 4); | |
113 | ck_assert_int_eq((fp.fraction.value * 10000) >> fp.fraction.bits, 6250); | |
114 | } | |
115 | END_TEST | |
116 | ||
117 | ||
118 | START_TEST(test_string_representation_positive_int) { | |
119 | struct fp_number fp1 = fp_strtofp("214", NULL, 9, 9); | |
120 | struct fp_number fp2 = fp_strtofp("11178.0000", NULL, 15, 9); | |
121 | ck_assert_str_eq(fp_fptostr(fp1, NULL), "214"); | |
122 | ck_assert_str_eq(fp_fptostr(fp2, NULL), "11178"); | |
123 | ck_assert_str_eq(fp_fptostr(fp2, "ES"), "11178E"); | |
124 | } | |
125 | END_TEST | |
126 | ||
127 | START_TEST(test_string_representation_negative_int) { | |
128 | struct fp_number fp1 = fp_strtofp("-214", NULL, 9, 9); | |
129 | struct fp_number fp2 = fp_strtofp("-11178.0000", NULL, 15, 9); | |
130 | ck_assert_str_eq(fp_fptostr(fp1, NULL), "-214"); | |
131 | ck_assert_str_eq(fp_fptostr(fp2, NULL), "-11178"); | |
132 | ck_assert_str_eq(fp_fptostr(fp2, "ES"), "11178S"); | |
133 | } | |
134 | END_TEST | |
135 | ||
136 | START_TEST(test_string_representation_positive_float) { | |
137 | struct fp_number fp = fp_strtofp("214.6250", NULL, 9, 20); | |
138 | ck_assert_str_eq(fp_fptostr(fp, NULL), "214.6250"); | |
139 | ck_assert_str_eq(fp_fptostr(fp, "ES"), "214.6250E"); | |
140 | } | |
141 | END_TEST | |
142 | ||
143 | START_TEST(test_string_representation_positive_float_with_leading_zero) { | |
144 | struct fp_number fp = fp_strtofp("214.06250", NULL, 9, 24); | |
145 | ck_assert_str_eq(fp_fptostr(fp, NULL), "214.06250"); | |
146 | ck_assert_str_eq(fp_fptostr(fp, "ES"), "214.06250E"); | |
147 | } | |
148 | END_TEST | |
149 | ||
150 | START_TEST(test_string_representation_negative_float) { | |
151 | struct fp_number fp1 = fp_strtofp("-214.625", NULL, 22, 10); | |
152 | struct fp_number fp2 = fp_strtofp("-415.5", NULL, 22, 4); | |
153 | ck_assert_str_eq(fp_fptostr(fp1, NULL), "-214.625"); | |
154 | ck_assert_str_eq(fp_fptostr(fp2, NULL), "-415.5"); | |
155 | ck_assert_str_eq(fp_fptostr(fp2, "ES"), "415.5S"); | |
156 | } | |
157 | END_TEST | |
158 | ||
159 | START_TEST(test_buffer_representation_positive_float) { | |
160 | unsigned char buffer[5] = {}; | |
161 | unsigned char expected[] = { 0x21 << 2, 47 << 1, 0x68, 0x00, 0x00 }; | |
162 | /* 47.2031250 = 47 + 2**-3 + 2**-4 + 2**-6, precision = 9+24 */ | |
163 | struct fp_number fp = fp_strtofp("47.2031250", NULL, 9, 25); | |
164 | fp_fptobuf(fp, buffer, 0); | |
165 | fail_unless(memcmp(buffer, expected, sizeof(expected)) == 0); | |
166 | } | |
167 | END_TEST | |
168 | ||
169 | START_TEST(test_buffer_representation_negative_float) { | |
170 | unsigned char buffer[5] = {}; | |
171 | unsigned char expected[] = { (0x21 << 2) | 3, 0xa1, 0x98, 0x00, 0x00 }; | |
172 | /* 47.2031250 = 000101111.0011010000000000000000000 */ | |
173 | /* -47.2031250 = 111010000.1100101111111111111111111 + 1 */ | |
174 | /* -47.2031250 = 111010000.1100110000000000000000000 */ | |
175 | struct fp_number fp = fp_strtofp("-47.2031250", NULL, 9, 25); | |
176 | fp_fptobuf(fp, buffer, 0); | |
177 | fail_unless(memcmp(buffer, expected, sizeof(expected)) == 0); | |
178 | } | |
179 | END_TEST | |
180 | ||
181 | START_TEST(test_buffer_representation_with_shift) { | |
182 | unsigned char buffer[] = { 0x77, 0xc6, 0x0, 0x0, 0x0, 0x0, 0xc7 }; | |
183 | unsigned char expected[] = { 0x77, 0xc8, 0x45, 0xe6, 0x80, 0x00, 0x07 }; | |
184 | struct fp_number fp = fp_strtofp("47.2031250", NULL, 9, 25); | |
185 | fp_fptobuf(fp, buffer, 12); | |
186 | fail_unless(memcmp(buffer, expected, sizeof(buffer)) == 0); | |
187 | } | |
188 | END_TEST | |
189 | ||
190 | START_TEST(test_buffer_representation_altitude) { | |
191 | unsigned char buffer[5] = {}; | |
192 | unsigned char expected[] = { (22 + 4) << 2, 0, 0, 14 << 4 | 1 << 3, 0 }; | |
193 | struct fp_number fp = fp_strtofp("14.5", NULL, 22, 8); | |
194 | fp_fptobuf(fp, buffer, 0); | |
195 | fail_unless(memcmp(buffer, expected, sizeof(buffer)) == 0); | |
196 | } | |
197 | END_TEST | |
198 | ||
199 | START_TEST(test_buffer_parsing_positive_float) { | |
200 | unsigned char buffer[] = { 0x21 << 2, 47 << 1, 0x68, 0x00, 0x00 }; | |
201 | struct fp_number fp = fp_buftofp(buffer, 9, 25, 0); | |
202 | ck_assert_int_eq(fp.integer.value, 47); | |
203 | ck_assert_int_eq(fp.integer.bits, 9); | |
204 | ck_assert_int_eq((fp.fraction.value * 10000000) >> fp.fraction.bits, 2031250); | |
205 | ck_assert_int_eq(fp.fraction.bits, 25); | |
206 | ck_assert_int_eq(fp.fraction.precision, 24); | |
207 | } | |
208 | END_TEST | |
209 | ||
210 | START_TEST(test_buffer_parsing_negative_float) { | |
211 | unsigned char buffer[] = { (0x21 << 2) | 3, 0xa1, 0x98, 0x00, 0x00 }; | |
212 | struct fp_number fp = fp_buftofp(buffer, 9, 25, 0); | |
213 | ck_assert_int_eq(fp.integer.value, -47); | |
214 | ck_assert_int_eq(fp.integer.bits, 9); | |
215 | ck_assert_int_eq((fp.fraction.value * 10000000) >> fp.fraction.bits, 2031250); | |
216 | ck_assert_int_eq(fp.fraction.bits, 25); | |
217 | ck_assert_int_eq(fp.fraction.precision, 24); | |
218 | } | |
219 | END_TEST | |
220 | ||
221 | /* This is some corner case */ | |
222 | START_TEST(test_buffer_parsing_positive_float_2) { | |
223 | unsigned char buffer[] = { 0x40, 0x9c, 0x80, 0x00, 0x00 }; | |
224 | struct fp_number fp = fp_buftofp(buffer, 9, 25, 0); | |
225 | ck_assert_int_eq(fp.integer.value, 78); | |
226 | } | |
227 | END_TEST | |
228 | ||
229 | START_TEST(test_buffer_parsing_positive_float_with_shift) { | |
230 | unsigned char buffer[] = { 0x77, 0xc8, 0x45, 0xe6, 0x80, 0x00, 0x07 }; | |
231 | struct fp_number fp = fp_buftofp(buffer, 9, 25, 12); | |
232 | ck_assert_int_eq(fp.integer.value, 47); | |
233 | ck_assert_int_eq(fp.integer.bits, 9); | |
234 | ck_assert_int_eq((fp.fraction.value * 10000000) >> fp.fraction.bits, 2031250); | |
235 | ck_assert_int_eq(fp.fraction.bits, 25); | |
236 | ck_assert_int_eq(fp.fraction.precision, 24); | |
237 | } | |
238 | END_TEST | |
239 | ||
240 | START_TEST(test_buffer_parsing_negative_float_with_shift) { | |
241 | unsigned char buffer[] = { 0x00, 0xff, (0x21 << 2) | 3, 0xa1, 0x98, 0x00, 0x00 }; | |
242 | struct fp_number fp = fp_buftofp(buffer, 9, 25, 16); | |
243 | ck_assert_int_eq(fp.integer.value, -47); | |
244 | ck_assert_int_eq(fp.integer.bits, 9); | |
245 | ck_assert_int_eq((fp.fraction.value * 10000000) >> fp.fraction.bits, 2031250); | |
246 | ck_assert_int_eq(fp.fraction.bits, 25); | |
247 | ck_assert_int_eq(fp.fraction.precision, 24); | |
248 | } | |
249 | END_TEST | |
250 | ||
251 | START_TEST(test_negate_positive) { | |
252 | struct fp_number fp = fp_strtofp("14.5", NULL, 9, 25); | |
253 | struct fp_number nfp = fp_negate(fp); | |
254 | ck_assert_int_eq(nfp.integer.value, -14); | |
255 | ck_assert_int_eq(fp.fraction.value, nfp.fraction.value); | |
256 | ck_assert_str_eq(fp_fptostr(nfp, NULL), "-14.5"); | |
257 | } | |
258 | END_TEST | |
259 | ||
260 | START_TEST(test_negate_negative) { | |
261 | struct fp_number fp = fp_strtofp("-14.5", NULL, 9, 25); | |
262 | struct fp_number nfp = fp_negate(fp); | |
263 | ck_assert_int_eq(nfp.integer.value, 14); | |
264 | ck_assert_int_eq(fp.fraction.value, nfp.fraction.value); | |
265 | ck_assert_str_eq(fp_fptostr(nfp, NULL), "14.5"); | |
266 | } | |
267 | END_TEST | |
268 | ||
269 | #endif | |
270 | ||
271 | Suite * | |
272 | fixedpoint_suite(void) | |
273 | { | |
274 | Suite *s = suite_create("Fixed point representation"); | |
275 | ||
276 | #ifdef ENABLE_LLDPMED | |
277 | TCase *tc_fp = tcase_create("Fixed point representation"); | |
278 | tcase_add_test(tc_fp, test_string_parsing_suffix); | |
279 | tcase_add_test(tc_fp, test_string_parsing_positive_int); | |
280 | tcase_add_test(tc_fp, test_string_parsing_negative_int); | |
281 | tcase_add_test(tc_fp, test_string_parsing_no_fract_part); | |
282 | tcase_add_test(tc_fp, test_string_parsing_no_int_part); | |
283 | tcase_add_test(tc_fp, test_string_parsing_positive_int_overflow); | |
284 | tcase_add_test(tc_fp, test_string_parsing_negative_int_overflow); | |
285 | tcase_add_test(tc_fp, test_string_parsing_positive_float); | |
286 | tcase_add_test(tc_fp, test_string_parsing_negative_float); | |
287 | tcase_add_test(tc_fp, test_string_representation_positive_int); | |
288 | tcase_add_test(tc_fp, test_string_representation_negative_int); | |
289 | tcase_add_test(tc_fp, test_string_representation_positive_float); | |
290 | tcase_add_test(tc_fp, test_string_representation_positive_float_with_leading_zero); | |
291 | tcase_add_test(tc_fp, test_string_representation_negative_float); | |
292 | tcase_add_test(tc_fp, test_buffer_representation_positive_float); | |
293 | tcase_add_test(tc_fp, test_buffer_representation_negative_float); | |
294 | tcase_add_test(tc_fp, test_buffer_representation_with_shift); | |
295 | tcase_add_test(tc_fp, test_buffer_representation_altitude); | |
296 | tcase_add_test(tc_fp, test_buffer_parsing_positive_float); | |
297 | tcase_add_test(tc_fp, test_buffer_parsing_positive_float_2); | |
298 | tcase_add_test(tc_fp, test_buffer_parsing_negative_float); | |
299 | tcase_add_test(tc_fp, test_buffer_parsing_positive_float_with_shift); | |
300 | tcase_add_test(tc_fp, test_buffer_parsing_negative_float_with_shift); | |
301 | tcase_add_test(tc_fp, test_negate_positive); | |
302 | tcase_add_test(tc_fp, test_negate_negative); | |
303 | suite_add_tcase(s, tc_fp); | |
304 | #endif | |
305 | ||
306 | return s; | |
307 | } | |
308 | ||
9997f8e4 VB |
309 | /* Disable leak detection sanitizer */ |
310 | int __lsan_is_turned_off() { | |
311 | return 1; | |
312 | } | |
313 | ||
f730f6c5 VB |
314 | int |
315 | main() | |
316 | { | |
317 | int number_failed; | |
318 | Suite *s = fixedpoint_suite(); | |
319 | SRunner *sr = srunner_create(s); | |
320 | srunner_run_all(sr, CK_ENV); | |
321 | number_failed = srunner_ntests_failed(sr); | |
322 | srunner_free(sr); | |
323 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; | |
324 | } |