#define _USE_MATH_DEFINES 1 #undef __STRICT_ANSI__ #include #include #include #include #include #include "doublemsg.pb.h" #include "unittests.h" /* This message mimics how DoubleMsg would appear on e.g. AVR. */ typedef struct { float value; } FloatMsg; PB_BIND(DoubleMsg, FloatMsg, AUTO) static const double testvalues[] = { 0.0, -0.0, 0.1, -0.1, M_PI, -M_PI, 123456.789, -123456.789, #if defined(NAN) && defined(INFINITY) INFINITY, -INFINITY, NAN, INFINITY - INFINITY, #endif 1e38, -1e38, 1e39, -1e39, 1e-38, -1e-38, 1e-39, -1e-39, 3.14159e-37,-3.14159e-37, 3.14159e-43, -3.14159e-43, 1e-60, -1e-60, 1e-45, -1e-45, 0.99999999999999, -0.99999999999999, 127.999999999999, -127.999999999999 }; #define TESTVALUES_COUNT (sizeof(testvalues)/sizeof(testvalues[0])) int main() { uint8_t buf[16]; size_t msglen; int status = 0; int i; for (i = 0; i < TESTVALUES_COUNT; i++) { double orig_double = testvalues[i]; float expected_float = (float)orig_double; double expected_double = (double)expected_float; printf("\n---- Testcase: %f ----\n", expected_float); { /* Encode the original double */ pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf)); DoubleMsg msg = { 0.0 }; msg.value = orig_double; TEST(pb_encode(&stream, &DoubleMsg_msg, &msg)); msglen = stream.bytes_written; TEST(msglen == 9); } { /* Decode as float */ pb_ostream_t ostream; pb_istream_t stream = pb_istream_from_buffer(buf, msglen); FloatMsg msg = { 0.0f }; TEST(pb_decode(&stream, &FloatMsg_msg, &msg)); TEST(memcmp(&msg.value, &expected_float, sizeof(float)) == 0); /* Re-encode */ ostream = pb_ostream_from_buffer(buf, sizeof(buf)); TEST(pb_encode(&ostream, &FloatMsg_msg, &msg)); msglen = ostream.bytes_written; TEST(msglen == 9); } { /* Decode as double */ pb_istream_t stream = pb_istream_from_buffer(buf, msglen); DoubleMsg msg = { 0.0 }; TEST(pb_decode(&stream, &DoubleMsg_msg, &msg)); if (isnan(expected_double)) { /* Bottom bits of NAN converted to double can vary */ TEST(isnan(msg.value)); } else { TEST(memcmp(&msg.value, &expected_double, sizeof(double)) == 0); } } } return status; }