1 #define _USE_MATH_DEFINES 1
2 #undef __STRICT_ANSI__
3 #include <math.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <pb_decode.h>
7 #include <pb_encode.h>
8 #include "doublemsg.pb.h"
9 #include "unittests.h"
10 
11 /* This message mimics how DoubleMsg would appear on e.g. AVR. */
12 typedef struct {
13     float value;
14 } FloatMsg;
15 PB_BIND(DoubleMsg, FloatMsg, AUTO)
16 
17 static const double testvalues[] = {
18            0.0,        -0.0,         0.1,         -0.1,
19           M_PI,       -M_PI,  123456.789,  -123456.789,
20 #if defined(NAN) && defined(INFINITY)
21       INFINITY,   -INFINITY,         NAN, INFINITY - INFINITY,
22 #endif
23           1e38,       -1e38,        1e39,        -1e39,
24          1e-38,      -1e-38,       1e-39,       -1e-39,
25    3.14159e-37,-3.14159e-37, 3.14159e-43, -3.14159e-43,
26          1e-60,      -1e-60,       1e-45,       -1e-45,
27     0.99999999999999, -0.99999999999999, 127.999999999999, -127.999999999999
28 };
29 
30 #define TESTVALUES_COUNT (sizeof(testvalues)/sizeof(testvalues[0]))
31 
main()32 int main()
33 {
34     uint8_t buf[16];
35     size_t msglen;
36     int status = 0;
37     int i;
38     for (i = 0; i < TESTVALUES_COUNT; i++)
39     {
40         double orig_double = testvalues[i];
41         float expected_float = (float)orig_double;
42         double expected_double = (double)expected_float;
43 
44         printf("\n---- Testcase: %f ----\n", expected_float);
45 
46         {
47             /* Encode the original double */
48             pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));
49             DoubleMsg msg = { 0.0 };
50             msg.value = orig_double;
51             TEST(pb_encode(&stream, &DoubleMsg_msg, &msg));
52             msglen = stream.bytes_written;
53             TEST(msglen == 9);
54         }
55 
56         {
57             /* Decode as float */
58             pb_ostream_t ostream;
59             pb_istream_t stream = pb_istream_from_buffer(buf, msglen);
60             FloatMsg msg = { 0.0f };
61             TEST(pb_decode(&stream, &FloatMsg_msg, &msg));
62             TEST(memcmp(&msg.value, &expected_float, sizeof(float)) == 0);
63 
64             /* Re-encode */
65             ostream = pb_ostream_from_buffer(buf, sizeof(buf));
66             TEST(pb_encode(&ostream, &FloatMsg_msg, &msg));
67             msglen = ostream.bytes_written;
68             TEST(msglen == 9);
69         }
70 
71         {
72             /* Decode as double */
73             pb_istream_t stream = pb_istream_from_buffer(buf, msglen);
74             DoubleMsg msg = { 0.0 };
75             TEST(pb_decode(&stream, &DoubleMsg_msg, &msg));
76 
77             if (isnan(expected_double))
78             {
79                 /* Bottom bits of NAN converted to double can vary */
80                 TEST(isnan(msg.value));
81             }
82             else
83             {
84                 TEST(memcmp(&msg.value, &expected_double, sizeof(double)) == 0);
85             }
86         }
87     }
88 
89     return status;
90 }
91