#include "ble/ByteBuffer.h" #include #include #define BOOST_TEST_MODULE "ByteBuffer" #include using namespace std; static void checkBuffer(const ByteBuffer& buffer, size_t size, size_t position) { if (false) { cout << "size=" << buffer.getSize() << ", position=" << buffer.getPosition(); } BOOST_CHECK_EQUAL(buffer.getSize(), size); BOOST_CHECK_EQUAL(buffer.getPosition(), position); } class Bytes { public: explicit Bytes(size_t size) : capacity(size), secret(new uint8_t[size + 0x100]) { auto tmp = (uint8_t *) (((uint64_t) &secret[0x100]) & 0xffffffffffffff00); for (int i = 0; i < size; i++) { tmp[i] = (uint8_t) i; } bytes = tmp; } ~Bytes() { delete[] secret; } uint8_t* bytes; size_t capacity; uint8_t* secret; }; BOOST_AUTO_TEST_CASE(empty_buffer) { Bytes b(0); ByteBuffer buffer(b.bytes, b.capacity); checkBuffer(buffer, 0, 0); try { buffer.read8(); BOOST_FAIL("Expected exception"); } catch (ByteBufferException &e) { } } BOOST_AUTO_TEST_CASE(basic) { Bytes b(1000); ByteBuffer buffer(b.bytes, 1000); checkBuffer(buffer, 1000, 0); BOOST_CHECK_EQUAL(buffer.read8(), 0); checkBuffer(buffer, 1000, 1); for (int i = 1; i < b.capacity; i++) { BOOST_CHECK_EQUAL(buffer.read8(), b.bytes[i]); } } BOOST_AUTO_TEST_CASE(setCursor) { Bytes b(1000); ByteBuffer buffer(b.bytes, 1000); checkBuffer(buffer, 1000, 0); BOOST_CHECK_EQUAL(buffer.read8(), 0); checkBuffer(buffer, 1000, 1); buffer.setCursor(0); checkBuffer(buffer, 1000, 0); BOOST_CHECK_EQUAL(buffer.read8(), 0); checkBuffer(buffer, 1000, 1); buffer.setCursor(9); checkBuffer(buffer, 1000, 9); } BOOST_AUTO_TEST_CASE(view) { Bytes b(1000); ByteBuffer buffer(b.bytes, b.capacity); BOOST_CHECK_EQUAL(buffer.read8(), 0); ByteBuffer view1 = buffer.viewCursorToEnd(); checkBuffer(view1, 999, 0); BOOST_CHECK_EQUAL(view1.read8(), 1); BOOST_CHECK_EQUAL(view1.read8(), 2); ByteBuffer view2 = view1.viewCursorToEnd(); checkBuffer(view2, 997, 0); BOOST_CHECK_EQUAL(view1.read8(), 3); } BOOST_AUTO_TEST_CASE(ieee_11073_20601_float_1_0d) { Bytes b(1000); ByteBuffer buffer(b.bytes, b.capacity); buffer.writeFLOAT(1.0); buffer.setCursor(0); BOOST_CHECK_EQUAL(buffer.readFLOAT(), 1.0); } BOOST_AUTO_TEST_CASE(ieee_11073_20601_float_nan) { Bytes b(1000); ByteBuffer buffer(b.bytes, b.capacity); BOOST_CHECK_EQUAL(std::isnan(stof("NaN")), true); buffer.writeFLOAT(stof("NaN")); buffer.setCursor(0); BOOST_CHECK_EQUAL(std::isnan(buffer.readFLOAT()), true); } void c(double input, uint32_t hx, double sigma = 0.00001) { Bytes b(1000); ByteBuffer buffer(b.bytes, b.capacity); buffer.writeFLOAT(input); buffer.setCursor(0); double output = buffer.readFLOAT(); stringstream str; auto actual_hex = ((uint32_t *) b.bytes)[0]; str << "input=" << setw(20) << setprecision(10) << input << ", output=" << setw(20) << setprecision(10) << output << ", diff=" << setw(20) << setprecision(10) << fabs(input - output) << ", expected=" << setw(8) << setfill('0') << hex << hx << ", actual=" << setw(8) << setfill('0') << hex << actual_hex; if (std::isnan(input) || std::isnan(output)) { BOOST_CHECK_EQUAL(std::isnan(input), std::isnan(output)); } else if (input >= FLOAT::max) { BOOST_CHECK_EQUAL(INFINITY, output); } else if (input <= FLOAT::min) { BOOST_CHECK_EQUAL(-INFINITY, output); } else { BOOST_CHECK_MESSAGE(fabs(input - output) < sigma, str.str()); } } BOOST_AUTO_TEST_CASE(ieee_11073_20601_float_lots) { c(36.4, 0xFF00016C); c(1, 0xFF000270); c(62.4, 0xFF000270); c(25.8, 0xFF000102); c(-0.2, 0xFFFFFFFE); c(0.03, 0xFE000003); c(15000000.0, 0x0116e360); c(15000000.1, 0x0116e360, 0.11); c(1500000.1, 0x0016e360, 0.11); c(1499999.99, 0x0016e360, 0.02); c(NAN, 0x007FFFFF); c(1e300, 0x007FFFFE); c(-1e300, 0x00800002); }