| #include <stdint.h> |
| #include <string.h> |
| |
| #include "rlc.h" |
| #include "gprs_debug.h" |
| #include <gprs_rlcmac.h> |
| #include "egprs_rlc_compression.h" |
| |
| extern "C" { |
| #include <osmocom/core/logging.h> |
| #include <osmocom/core/bitvec.h> |
| #include <osmocom/core/utils.h> |
| #include <osmocom/core/application.h> |
| } |
| |
| #define NEW 1 |
| #define MASK(n) (0xFF << (8-n)) |
| #define MAX_CRBB_LEN 23 |
| #define MAX_URBB_LEN 40 |
| #define CEIL_DIV_8(x) (((x) + 7)/8) |
| #define _LOG(fmt, args...) \ |
| fprintf(stderr, fmt, ## args) |
| |
| void *tall_pcu_ctx; |
| |
| struct test_data { |
| int8_t crbb_len; |
| uint8_t cc; |
| uint8_t crbb_data[MAX_CRBB_LEN]; /* compressed data */ |
| uint8_t ucmp_data[MAX_URBB_LEN]; /* uncompressed data */ |
| int ucmp_len; |
| int expect_rc; |
| } test[] = { |
| { .crbb_len = 67, .cc = 1, |
| .crbb_data = { |
| 0x02, 0x0c, 0xa0, 0x30, 0xcb, 0x1a, 0x0c, 0xe3, 0x6c |
| }, |
| .ucmp_data = { |
| 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xff, 0xff, |
| 0xff, 0xf8, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, |
| 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0 |
| }, |
| .ucmp_len = 194, |
| .expect_rc = 0, |
| }, |
| { .crbb_len = 40, .cc = 1, |
| .crbb_data = { |
| 0x53, 0x06, 0xc5, 0x40, 0x6d |
| }, |
| .ucmp_data = { |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, |
| 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, |
| 0x00, 0x00, 0x00, 0x00, 0x00 |
| }, |
| .ucmp_len = 182, |
| .expect_rc = 0, |
| }, |
| { .crbb_len = 8, .cc = 1, |
| .crbb_data = {0x02}, |
| .ucmp_data = {0xff, 0xff, 0xff, 0xf8}, |
| .ucmp_len = 29, |
| .expect_rc = 0, |
| }, |
| { .crbb_len = 103, .cc = 1, |
| .crbb_data = { |
| 0x02, 0x0c, 0xe0, 0x41, 0xa0, 0x0c, 0x36, 0x0d, 0x03, |
| 0x71, 0xb0, 0x6e, 0x24 |
| }, |
| .ucmp_data = { |
| 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xff, |
| 0xf8, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, |
| 0x0f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, |
| 0xff, 0xff, 0x80, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff |
| }, |
| .ucmp_len = 288, |
| .expect_rc = 0, |
| }, |
| /* Test vector from libosmocore test */ |
| { .crbb_len = 35, .cc = 0, |
| .crbb_data = {0xde, 0x88, 0x75, 0x65, 0x80}, |
| .ucmp_data = {0x37, 0x47, 0x81, 0xf0}, |
| .ucmp_len = 28, |
| .expect_rc = 0, |
| }, |
| { .crbb_len = 18, .cc = 1, |
| .crbb_data = {0xdd, 0x41, 0x00}, |
| .ucmp_data = { |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0x00, 0x00 |
| }, |
| .ucmp_len = 90, |
| .expect_rc = 0, |
| }, |
| /* Invalid inputs */ |
| { .crbb_len = 18, .cc = 1, |
| .crbb_data = {0x1E, 0x70, 0xc0}, |
| .ucmp_data = {0xb0, 0x00, 0x00}, |
| .ucmp_len = 19, |
| .expect_rc = -1, |
| }, |
| { .crbb_len = 14, .cc = 1, |
| .crbb_data = {0x00, 0x1E, 0x7c}, |
| .ucmp_data = {0x0}, |
| .ucmp_len = 0, |
| .expect_rc = -1, |
| }, |
| { .crbb_len = 24, .cc = 0, |
| .crbb_data = {0x00, 0x00, 0x00}, |
| .ucmp_data = {0x0}, |
| .ucmp_len = 0, |
| .expect_rc = -1, |
| } |
| }; |
| |
| bool result_matches(const bitvec &bits, const uint8_t *exp_data, unsigned int exp_len) |
| { |
| if (bits.cur_bit != exp_len) |
| return false; |
| return (memcmp(exp_data, bits.data, CEIL_DIV_8(exp_len)) == 0); |
| } |
| |
| /* To test decoding of compressed bitmap by Tree based method |
| * and to verify the result with expected result |
| * for invalid input verfication is suppressed |
| */ |
| static void test_EPDAN_decode_tree(void) |
| { |
| bitvec dest; |
| unsigned int itr; |
| int rc; |
| uint8_t bits_data[RLC_EGPRS_MAX_WS/8]; |
| |
| printf("=== start %s ===\n", __func__); |
| |
| for (itr = 0 ; itr < (sizeof(test) / sizeof(test_data)) ; itr++) { |
| memset(bits_data, 0, sizeof(bits_data)); |
| dest.data = bits_data; |
| dest.data_len = sizeof(bits_data); |
| dest.cur_bit = 0; |
| _LOG("\nTest:%d\n" |
| "Tree based decoding:\n" |
| "compressed data = %s\n" |
| "len = %d\n", |
| itr + 1, |
| osmo_hexdump(test[itr].crbb_data, |
| CEIL_DIV_8(test[itr].crbb_len)), |
| test[itr].crbb_len); |
| rc = egprs_compress::decompress_crbb(test[itr].crbb_len, |
| test[itr].cc, test[itr].crbb_data, &dest); |
| _LOG("rc = %d\n", rc); |
| OSMO_ASSERT(test[itr].expect_rc == rc); |
| if (rc < 0) { |
| _LOG("Failed to decode CRBB: length %d, data %s\n", |
| test[itr].crbb_len, |
| osmo_hexdump(test[itr].crbb_data, |
| CEIL_DIV_8(test[itr].crbb_len))); |
| continue; |
| } |
| if (!result_matches(dest, test[itr].ucmp_data, |
| test[itr].ucmp_len)) { |
| _LOG("\nTree based decoding: Error\n" |
| "expected data = %s\n" |
| "expected len = %d\n", |
| osmo_hexdump(test[itr].ucmp_data, |
| CEIL_DIV_8(test[itr].ucmp_len)), |
| test[itr].ucmp_len); |
| _LOG("decoded data = %s\n" |
| "decoded len = %d\n", |
| osmo_hexdump(dest.data, |
| CEIL_DIV_8(dest.cur_bit)), |
| dest.cur_bit); |
| OSMO_ASSERT(0); |
| } |
| _LOG("\nexpected data = %s\n" |
| "expected len = %d\n", |
| osmo_hexdump(test[itr].ucmp_data, |
| CEIL_DIV_8(test[itr].ucmp_len)), |
| test[itr].ucmp_len); |
| _LOG("decoded data = %s\n" |
| "decoded len = %d\n", |
| osmo_hexdump(dest.data, CEIL_DIV_8(dest.cur_bit)), |
| dest.cur_bit); |
| } |
| |
| printf("=== end %s ===\n", __func__); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| tall_pcu_ctx = talloc_named_const(NULL, 1, "moiji-mobile bitcompTest context"); |
| if (!tall_pcu_ctx) |
| abort(); |
| |
| osmo_init_logging2(tall_pcu_ctx, &gprs_log_info); |
| log_set_use_color(osmo_stderr_target, 0); |
| log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); |
| log_set_print_category(osmo_stderr_target, 0); |
| log_set_print_category_hex(osmo_stderr_target, 0); |
| log_parse_category_mask(osmo_stderr_target, "DRLCMACUL,1"); |
| |
| test_EPDAN_decode_tree(); |
| |
| if (getenv("TALLOC_REPORT_FULL")) |
| talloc_report_full(tall_pcu_ctx, stderr); |
| talloc_free(tall_pcu_ctx); |
| return EXIT_SUCCESS; |
| } |
| |
| /* |
| * stubs that should not be reached |
| */ |
| extern "C" { |
| void l1if_pdch_req() { abort(); } |
| void l1if_connect_pdch() { abort(); } |
| void l1if_close_pdch() { abort(); } |
| void l1if_open_pdch() { abort(); } |
| } |