#include #include #include #include #include #include #include "catch2/catch.hpp" #include "system/ubloxd/generated/glonass.h" typedef std::vector> string_data; #define IDLE_CHIP_IDX 0 #define STRING_NUMBER_IDX 1 // string data 1-5 #define HC_IDX 0 #define PAD1_IDX 1 #define SUPERFRAME_IDX 2 #define PAD2_IDX 3 #define FRAME_IDX 4 // Indexes for string number 1 #define ST1_NU_IDX 2 #define ST1_P1_IDX 3 #define ST1_T_K_IDX 4 #define ST1_X_VEL_S_IDX 5 #define ST1_X_VEL_V_IDX 6 #define ST1_X_ACCEL_S_IDX 7 #define ST1_X_ACCEL_V_IDX 8 #define ST1_X_S_IDX 9 #define ST1_X_V_IDX 10 #define ST1_HC_OFF 11 // Indexes for string number 2 #define ST2_BN_IDX 2 #define ST2_P2_IDX 3 #define ST2_TB_IDX 4 #define ST2_NU_IDX 5 #define ST2_Y_VEL_S_IDX 6 #define ST2_Y_VEL_V_IDX 7 #define ST2_Y_ACCEL_S_IDX 8 #define ST2_Y_ACCEL_V_IDX 9 #define ST2_Y_S_IDX 10 #define ST2_Y_V_IDX 11 #define ST2_HC_OFF 12 // Indexes for string number 3 #define ST3_P3_IDX 2 #define ST3_GAMMA_N_S_IDX 3 #define ST3_GAMMA_N_V_IDX 4 #define ST3_NU_1_IDX 5 #define ST3_P_IDX 6 #define ST3_L_N_IDX 7 #define ST3_Z_VEL_S_IDX 8 #define ST3_Z_VEL_V_IDX 9 #define ST3_Z_ACCEL_S_IDX 10 #define ST3_Z_ACCEL_V_IDX 11 #define ST3_Z_S_IDX 12 #define ST3_Z_V_IDX 13 #define ST3_HC_OFF 14 // Indexes for string number 4 #define ST4_TAU_N_S_IDX 2 #define ST4_TAU_N_V_IDX 3 #define ST4_DELTA_TAU_N_S_IDX 4 #define ST4_DELTA_TAU_N_V_IDX 5 #define ST4_E_N_IDX 6 #define ST4_NU_1_IDX 7 #define ST4_P4_IDX 8 #define ST4_F_T_IDX 9 #define ST4_NU_2_IDX 10 #define ST4_N_T_IDX 11 #define ST4_N_IDX 12 #define ST4_M_IDX 13 #define ST4_HC_OFF 14 // Indexes for string number 5 #define ST5_N_A_IDX 2 #define ST5_TAU_C_IDX 3 #define ST5_NU_IDX 4 #define ST5_N_4_IDX 5 #define ST5_TAU_GPS_IDX 6 #define ST5_L_N_IDX 7 #define ST5_HC_OFF 8 // Indexes for non immediate #define ST6_DATA_1_IDX 2 #define ST6_DATA_2_IDX 3 #define ST6_HC_OFF 4 std::string generate_inp_data(string_data& data) { std::string inp_data = ""; for (auto& [b, v] : data) { std::string tmp = std::bitset<64>(v).to_string(); inp_data += tmp.substr(64-b, b); } assert(inp_data.size() == 128); std::string string_data; string_data.reserve(16); for (int i = 0; i < 128; i+=8) { std::string substr = inp_data.substr(i, 8); string_data.push_back((uint8_t)std::stoi(substr.c_str(), 0, 2)); } return string_data; } string_data generate_string_data(uint8_t string_number) { srand((unsigned)time(0)); string_data data; // data.push_back({1, 0}); // idle chip data.push_back({4, string_number}); // string number if (string_number == 1) { data.push_back({2, 3}); // not_used data.push_back({2, 1}); // p1 data.push_back({12, 113}); // t_k data.push_back({1, rand() & 1}); // x_vel_sign data.push_back({23, 7122}); // x_vel_value data.push_back({1, rand() & 1}); // x_accel_sign data.push_back({4, 3}); // x_accel_value data.push_back({1, rand() & 1}); // x_sign data.push_back({26, 33554431}); // x_value } else if (string_number == 2) { data.push_back({3, 3}); // b_n data.push_back({1, 1}); // p2 data.push_back({7, 123}); // t_b data.push_back({5, 31}); // not_used data.push_back({1, rand() & 1}); // y_vel_sign data.push_back({23, 7422}); // y_vel_value data.push_back({1, rand() & 1}); // y_accel_sign data.push_back({4, 3}); // y_accel_value data.push_back({1, rand() & 1}); // y_sign data.push_back({26, 67108863}); // y_value } else if (string_number == 3) { data.push_back({1, 0}); // p3 data.push_back({1, 1}); // gamma_n_sign data.push_back({10, 123}); // gamma_n_value data.push_back({1, 0}); // not_used data.push_back({2, 2}); // p data.push_back({1, 1}); // l_n data.push_back({1, rand() & 1}); // z_vel_sign data.push_back({23, 1337}); // z_vel_value data.push_back({1, rand() & 1}); // z_accel_sign data.push_back({4, 9}); // z_accel_value data.push_back({1, rand() & 1}); // z_sign data.push_back({26, 100023}); // z_value } else if (string_number == 4) { data.push_back({1, rand() & 1}); // tau_n_sign data.push_back({21, 197152}); // tau_n_value data.push_back({1, rand() & 1}); // delta_tau_n_sign data.push_back({4, 4}); // delta_tau_n_value data.push_back({5, 0}); // e_n data.push_back({14, 2}); // not_used_1 data.push_back({1, 1}); // p4 data.push_back({4, 9}); // f_t data.push_back({3, 3}); // not_used_2 data.push_back({11, 2047}); // n_t data.push_back({5, 2}); // n data.push_back({2, 1}); // m } else if (string_number == 5) { data.push_back({11, 2047}); // n_a data.push_back({32, 4294767295}); // tau_c data.push_back({1, 0}); // not_used_1 data.push_back({5, 2}); // n_4 data.push_back({22, 4114304}); // tau_gps data.push_back({1, 0}); // l_n } else { // non-immediate data is not parsed data.push_back({64, rand()}); // data_1 data.push_back({8, 6}); // data_2 } data.push_back({8, rand() & 0xFF}); // hamming code data.push_back({11, rand() & 0x7FF}); // pad data.push_back({16, rand() & 0xFFFF}); // superframe data.push_back({8, rand() & 0xFF}); // pad data.push_back({8, rand() & 0xFF}); // frame return data; } TEST_CASE("parse_string_number_1"){ string_data data = generate_string_data(1); std::string inp_data = generate_inp_data(data); kaitai::kstream stream(inp_data); glonass_t gl_string(&stream); REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); REQUIRE(gl_string.hamming_code() == data[ST1_HC_OFF + HC_IDX].second); REQUIRE(gl_string.pad_1() == data[ST1_HC_OFF + PAD1_IDX].second); REQUIRE(gl_string.superframe_number() == data[ST1_HC_OFF + SUPERFRAME_IDX].second); REQUIRE(gl_string.pad_2() == data[ST1_HC_OFF + PAD2_IDX].second); REQUIRE(gl_string.frame_number() == data[ST1_HC_OFF + FRAME_IDX].second); kaitai::kstream str1(inp_data); glonass_t str1_data(&str1); glonass_t::string_1_t* s1 = static_cast(str1_data.data()); REQUIRE(s1->not_used() == data[ST1_NU_IDX].second); REQUIRE(s1->p1() == data[ST1_P1_IDX].second); REQUIRE(s1->t_k() == data[ST1_T_K_IDX].second); int mul = s1->x_vel_sign() ? (-1) : 1; REQUIRE(s1->x_vel() == (data[ST1_X_VEL_V_IDX].second * mul)); mul = s1->x_accel_sign() ? (-1) : 1; REQUIRE(s1->x_accel() == (data[ST1_X_ACCEL_V_IDX].second * mul)); mul = s1->x_sign() ? (-1) : 1; REQUIRE(s1->x() == (data[ST1_X_V_IDX].second * mul)); } TEST_CASE("parse_string_number_2"){ string_data data = generate_string_data(2); std::string inp_data = generate_inp_data(data); kaitai::kstream stream(inp_data); glonass_t gl_string(&stream); REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); REQUIRE(gl_string.hamming_code() == data[ST2_HC_OFF + HC_IDX].second); REQUIRE(gl_string.pad_1() == data[ST2_HC_OFF + PAD1_IDX].second); REQUIRE(gl_string.superframe_number() == data[ST2_HC_OFF + SUPERFRAME_IDX].second); REQUIRE(gl_string.pad_2() == data[ST2_HC_OFF + PAD2_IDX].second); REQUIRE(gl_string.frame_number() == data[ST2_HC_OFF + FRAME_IDX].second); kaitai::kstream str2(inp_data); glonass_t str2_data(&str2); glonass_t::string_2_t* s2 = static_cast(str2_data.data()); REQUIRE(s2->b_n() == data[ST2_BN_IDX].second); REQUIRE(s2->not_used() == data[ST2_NU_IDX].second); REQUIRE(s2->p2() == data[ST2_P2_IDX].second); REQUIRE(s2->t_b() == data[ST2_TB_IDX].second); int mul = s2->y_vel_sign() ? (-1) : 1; REQUIRE(s2->y_vel() == (data[ST2_Y_VEL_V_IDX].second * mul)); mul = s2->y_accel_sign() ? (-1) : 1; REQUIRE(s2->y_accel() == (data[ST2_Y_ACCEL_V_IDX].second * mul)); mul = s2->y_sign() ? (-1) : 1; REQUIRE(s2->y() == (data[ST2_Y_V_IDX].second * mul)); } TEST_CASE("parse_string_number_3"){ string_data data = generate_string_data(3); std::string inp_data = generate_inp_data(data); kaitai::kstream stream(inp_data); glonass_t gl_string(&stream); REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); REQUIRE(gl_string.hamming_code() == data[ST3_HC_OFF + HC_IDX].second); REQUIRE(gl_string.pad_1() == data[ST3_HC_OFF + PAD1_IDX].second); REQUIRE(gl_string.superframe_number() == data[ST3_HC_OFF + SUPERFRAME_IDX].second); REQUIRE(gl_string.pad_2() == data[ST3_HC_OFF + PAD2_IDX].second); REQUIRE(gl_string.frame_number() == data[ST3_HC_OFF + FRAME_IDX].second); kaitai::kstream str3(inp_data); glonass_t str3_data(&str3); glonass_t::string_3_t* s3 = static_cast(str3_data.data()); REQUIRE(s3->p3() == data[ST3_P3_IDX].second); int mul = s3->gamma_n_sign() ? (-1) : 1; REQUIRE(s3->gamma_n() == (data[ST3_GAMMA_N_V_IDX].second * mul)); REQUIRE(s3->not_used() == data[ST3_NU_1_IDX].second); REQUIRE(s3->p() == data[ST3_P_IDX].second); REQUIRE(s3->l_n() == data[ST3_L_N_IDX].second); mul = s3->z_vel_sign() ? (-1) : 1; REQUIRE(s3->z_vel() == (data[ST3_Z_VEL_V_IDX].second * mul)); mul = s3->z_accel_sign() ? (-1) : 1; REQUIRE(s3->z_accel() == (data[ST3_Z_ACCEL_V_IDX].second * mul)); mul = s3->z_sign() ? (-1) : 1; REQUIRE(s3->z() == (data[ST3_Z_V_IDX].second * mul)); } TEST_CASE("parse_string_number_4"){ string_data data = generate_string_data(4); std::string inp_data = generate_inp_data(data); kaitai::kstream stream(inp_data); glonass_t gl_string(&stream); REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); REQUIRE(gl_string.hamming_code() == data[ST4_HC_OFF + HC_IDX].second); REQUIRE(gl_string.pad_1() == data[ST4_HC_OFF + PAD1_IDX].second); REQUIRE(gl_string.superframe_number() == data[ST4_HC_OFF + SUPERFRAME_IDX].second); REQUIRE(gl_string.pad_2() == data[ST4_HC_OFF + PAD2_IDX].second); REQUIRE(gl_string.frame_number() == data[ST4_HC_OFF + FRAME_IDX].second); kaitai::kstream str4(inp_data); glonass_t str4_data(&str4); glonass_t::string_4_t* s4 = static_cast(str4_data.data()); int mul = s4->tau_n_sign() ? (-1) : 1; REQUIRE(s4->tau_n() == (data[ST4_TAU_N_V_IDX].second * mul)); mul = s4->delta_tau_n_sign() ? (-1) : 1; REQUIRE(s4->delta_tau_n() == (data[ST4_DELTA_TAU_N_V_IDX].second * mul)); REQUIRE(s4->e_n() == data[ST4_E_N_IDX].second); REQUIRE(s4->not_used_1() == data[ST4_NU_1_IDX].second); REQUIRE(s4->p4() == data[ST4_P4_IDX].second); REQUIRE(s4->f_t() == data[ST4_F_T_IDX].second); REQUIRE(s4->not_used_2() == data[ST4_NU_2_IDX].second); REQUIRE(s4->n_t() == data[ST4_N_T_IDX].second); REQUIRE(s4->n() == data[ST4_N_IDX].second); REQUIRE(s4->m() == data[ST4_M_IDX].second); } TEST_CASE("parse_string_number_5"){ string_data data = generate_string_data(5); std::string inp_data = generate_inp_data(data); kaitai::kstream stream(inp_data); glonass_t gl_string(&stream); REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); REQUIRE(gl_string.hamming_code() == data[ST5_HC_OFF + HC_IDX].second); REQUIRE(gl_string.pad_1() == data[ST5_HC_OFF + PAD1_IDX].second); REQUIRE(gl_string.superframe_number() == data[ST5_HC_OFF + SUPERFRAME_IDX].second); REQUIRE(gl_string.pad_2() == data[ST5_HC_OFF + PAD2_IDX].second); REQUIRE(gl_string.frame_number() == data[ST5_HC_OFF + FRAME_IDX].second); kaitai::kstream str5(inp_data); glonass_t str5_data(&str5); glonass_t::string_5_t* s5 = static_cast(str5_data.data()); REQUIRE(s5->n_a() == data[ST5_N_A_IDX].second); REQUIRE(s5->tau_c() == data[ST5_TAU_C_IDX].second); REQUIRE(s5->not_used() == data[ST5_NU_IDX].second); REQUIRE(s5->n_4() == data[ST5_N_4_IDX].second); REQUIRE(s5->tau_gps() == data[ST5_TAU_GPS_IDX].second); REQUIRE(s5->l_n() == data[ST5_L_N_IDX].second); } TEST_CASE("parse_string_number_NI"){ string_data data = generate_string_data((rand() % 10) + 6); std::string inp_data = generate_inp_data(data); kaitai::kstream stream(inp_data); glonass_t gl_string(&stream); REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); REQUIRE(gl_string.hamming_code() == data[ST6_HC_OFF + HC_IDX].second); REQUIRE(gl_string.pad_1() == data[ST6_HC_OFF + PAD1_IDX].second); REQUIRE(gl_string.superframe_number() == data[ST6_HC_OFF + SUPERFRAME_IDX].second); REQUIRE(gl_string.pad_2() == data[ST6_HC_OFF + PAD2_IDX].second); REQUIRE(gl_string.frame_number() == data[ST6_HC_OFF + FRAME_IDX].second); kaitai::kstream strni(inp_data); glonass_t strni_data(&strni); glonass_t::string_non_immediate_t* sni = static_cast(strni_data.data()); REQUIRE(sni->data_1() == data[ST6_DATA_1_IDX].second); REQUIRE(sni->data_2() == data[ST6_DATA_2_IDX].second); }