diff options
author | Ruslan Bukin <br@FreeBSD.org> | 2023-03-27 15:14:10 +0000 |
---|---|---|
committer | Ruslan Bukin <br@FreeBSD.org> | 2023-03-27 15:23:28 +0000 |
commit | 974000f192f9f74654b8835361cf35e606a10a76 (patch) | |
tree | c3aabe2b3d219cca63f0b426a2098bcdf9e9ac65 /decoder/tests/source | |
parent | d7aa8d0a1f110421252d79f5acfb72d89187ad1f (diff) | |
download | src-vendor/opencsd.tar.gz src-vendor/opencsd.zip |
Update OpenCSD to v1.4.0.vendor/opencsd/v1.4.0vendor/opencsd
Sponsored by: UKRI
Diffstat (limited to 'decoder/tests/source')
-rw-r--r-- | decoder/tests/source/c_api_pkt_print_test.c | 140 | ||||
-rw-r--r-- | decoder/tests/source/frame_demux_test.cpp | 524 | ||||
-rw-r--r-- | decoder/tests/source/mem_buff_demo.cpp | 9 | ||||
-rw-r--r-- | decoder/tests/source/trc_pkt_lister.cpp | 80 |
4 files changed, 723 insertions, 30 deletions
diff --git a/decoder/tests/source/c_api_pkt_print_test.c b/decoder/tests/source/c_api_pkt_print_test.c index 02c589e4f275..b930e0544cbd 100644 --- a/decoder/tests/source/c_api_pkt_print_test.c +++ b/decoder/tests/source/c_api_pkt_print_test.c @@ -116,6 +116,12 @@ static int test_printstr = 0; /* test the library printer API */ static int test_lib_printers = 0; +/* test the last error / error code api */ +static int test_error_api = 0; + +/* log statistics */ +static int stats = 0; + /* Process command line options - choose the operation to use for the test. */ static int process_cmd_line(int argc, char *argv[]) { @@ -124,52 +130,52 @@ static int process_cmd_line(int argc, char *argv[]) while(idx < argc) { - if(strcmp(argv[idx],"-decode_only") == 0) + if (strcmp(argv[idx], "-decode_only") == 0) { op = TEST_PKT_DECODEONLY; } - else if(strcmp(argv[idx],"-decode") == 0) + else if (strcmp(argv[idx], "-decode") == 0) { op = TEST_PKT_DECODE; } - else if(strcmp(argv[idx],"-id") == 0) + else if (strcmp(argv[idx], "-id") == 0) { idx++; - if(idx < argc) + if (idx < argc) { - test_trc_id_override = (uint8_t)(strtoul(argv[idx],0,0)); - printf("ID override = 0x%02X\n",test_trc_id_override); + test_trc_id_override = (uint8_t)(strtoul(argv[idx], 0, 0)); + printf("ID override = 0x%02X\n", test_trc_id_override); } } - else if(strcmp(argv[idx],"-etmv3") == 0) + else if (strcmp(argv[idx], "-etmv3") == 0) { - test_protocol = OCSD_PROTOCOL_ETMV3; + test_protocol = OCSD_PROTOCOL_ETMV3; selected_snapshot = tc2_snapshot; mem_dump_address = mem_dump_address_tc2; } - else if(strcmp(argv[idx],"-ptm") == 0) + else if (strcmp(argv[idx], "-ptm") == 0) { - test_protocol = OCSD_PROTOCOL_PTM; + test_protocol = OCSD_PROTOCOL_PTM; selected_snapshot = tc2_snapshot; mem_dump_address = mem_dump_address_tc2; } - else if(strcmp(argv[idx],"-stm") == 0) + else if (strcmp(argv[idx], "-stm") == 0) { test_protocol = OCSD_PROTOCOL_STM; trace_data_filename = stmtrace_data_filename; } - else if(strcmp(argv[idx],"-test_cb") == 0) + else if (strcmp(argv[idx], "-test_cb") == 0) { using_mem_acc_cb = 1; use_region_file = 0; } else if (strcmp(argv[idx], "-test_cb_id") == 0) - { + { using_mem_acc_cb = 1; use_region_file = 0; using_mem_acc_cb_id = 1; } - else if(strcmp(argv[idx],"-test_region_file") == 0) + else if (strcmp(argv[idx], "-test_region_file") == 0) { use_region_file = 1; using_mem_acc_cb = 0; @@ -182,6 +188,10 @@ static int process_cmd_line(int argc, char *argv[]) { frame_raw_unpacked = 1; } + else if (strcmp(argv[idx], "-stats") == 0) + { + stats = 1; + } else if (strcmp(argv[idx], "-raw_packed") == 0) { frame_raw_packed = 1; @@ -194,10 +204,10 @@ static int process_cmd_line(int argc, char *argv[]) { test_lib_printers = 1; } - else if(strcmp(argv[idx],"-ss_path") == 0) + else if (strcmp(argv[idx], "-ss_path") == 0) { idx++; - if((idx >= argc) || (strlen(argv[idx]) == 0)) + if ((idx >= argc) || (strlen(argv[idx]) == 0)) { printf("-ss_path: Missing path parameter or zero length\n"); return -1; @@ -205,14 +215,18 @@ static int process_cmd_line(int argc, char *argv[]) else { len = strlen(argv[idx]); - if(len > (MAX_TRACE_FILE_PATH_LEN - 32)) + if (len > (MAX_TRACE_FILE_PATH_LEN - 32)) { printf("-ss_path: path too long\n"); return -1; } usr_snapshot_path = argv[idx]; } - + + } + else if (strcmp(argv[idx], "-test_err_api") == 0) + { + test_error_api = 1; } else if(strcmp(argv[idx],"-help") == 0) { @@ -641,6 +655,7 @@ static ocsd_err_t create_decoder_etmv4(dcd_tree_handle_t dcd_tree_h) { trace_config.reg_traceidr = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_config.reg_traceidr; /* remember what ID we actually used */ trace_config.reg_idr0 = 0x28000EA1; trace_config.reg_idr1 = 0x4100F403; @@ -676,6 +691,7 @@ static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) { trace_config_etmv3.reg_trc_id = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_config_etmv3.reg_trc_id; /* remember what ID we actually used */ /* create an ETMV3 decoder - no context needed as we have a single stream to a single handler. */ return create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_ETMV3,(void *)&trace_config_etmv3,0); @@ -701,6 +717,7 @@ static ocsd_err_t create_decoder_ptm(dcd_tree_handle_t dcd_tree_h) { trace_config_ptm.reg_trc_id = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_config_ptm.reg_trc_id; /* remember what ID we actually used */ /* create an PTM decoder - no context needed as we have a single stream to a single handler. */ return create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_PTM,(void *)&trace_config_ptm,0); @@ -747,6 +764,7 @@ static ocsd_err_t create_decoder_extern(dcd_tree_handle_t dcd_tree_h) { trace_cfg_ext.cs_id = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_cfg_ext.cs_id; /* create an external decoder - no context needed as we have a single stream to a single handler. */ return create_generic_decoder(dcd_tree_h, EXT_DCD_NAME, (void *)&trace_cfg_ext, 0); @@ -874,6 +892,28 @@ ocsd_err_t process_data_block(dcd_tree_handle_t dcd_tree_h, int block_index, uin return ret; } +void print_statistics(dcd_tree_handle_t dcdtree_handle) +{ + ocsd_decode_stats_t *p_stats = 0; + ocsd_err_t err; + + sprintf(packet_str, "\nReading packet decoder statistics for ID:0x%02x...\n", test_trc_id_override); + ocsd_def_errlog_msgout(packet_str); + + err = ocsd_dt_get_decode_stats(dcdtree_handle, test_trc_id_override, &p_stats); + if (!err && p_stats) + { + sprintf(packet_str, "Total Bytes %ld; Unsynced Bytes: %ld\nBad Header Errors: %d; Bad sequence errors: %d\n", (long)p_stats->channel_total, + (long)p_stats->channel_unsynced, p_stats->bad_header_errs, p_stats->bad_sequence_errs); + ocsd_dt_reset_decode_stats(dcdtree_handle, test_trc_id_override); + } + else + { + sprintf(packet_str, "Not available for this ID.\n"); + } + ocsd_def_errlog_msgout(packet_str); +} + int process_trace_data(FILE *pf) { ocsd_err_t ret = OCSD_OK; @@ -936,7 +976,9 @@ int process_trace_data(FILE *pf) if(ret == OCSD_OK) ocsd_dt_process_data(dcdtree_handle, OCSD_OP_EOT, 0,0,NULL,NULL); - + if (stats) { + print_statistics(dcdtree_handle); + } /* shut down the mem acc CB if in use. */ if(using_mem_acc_cb) { @@ -955,6 +997,57 @@ int process_trace_data(FILE *pf) return (int)ret; } +#define ERR_BUFFER_SIZE 256 +int test_err_api() +{ + dcd_tree_handle_t dcdtree_handle = C_API_INVALID_TREE_HANDLE; + ocsd_err_t ret = OCSD_OK, err_test; + ocsd_trc_index_t index = 0, err_index = 0; + uint8_t cs_id; + char err_buffer[ERR_BUFFER_SIZE]; + + /* Create a decode tree for this source data. + source data is frame formatted, memory aligned from an ETR (no frame syncs) so create tree accordingly + */ + dcdtree_handle = ocsd_create_dcd_tree(OCSD_TRC_SRC_SINGLE, OCSD_DFRMTR_FRAME_MEM_ALIGN); + + if (dcdtree_handle != C_API_INVALID_TREE_HANDLE) + { + + ret = create_decoder(dcdtree_handle); + if (ret == OCSD_OK) + { + /* attach the generic trace element output callback */ + if (test_lib_printers) + ret = ocsd_dt_set_gen_elem_printer(dcdtree_handle); + else + ret = ocsd_dt_set_gen_elem_outfn(dcdtree_handle, gen_trace_elem_print, 0); + } + + + /* raw print and str print cb options tested in their init functions */ + if (ret == OCSD_OK) + ret = test_printstr_cb(dcdtree_handle); + + if (ret == OCSD_OK) + ret = attach_raw_printers(dcdtree_handle); + + /* feed some duff data into a decoder to provoke an error! */ + uint8_t trace_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x60, 0x71 }; + + if (ret == OCSD_OK) + ret = process_data_block(dcdtree_handle, index, trace_data, sizeof(trace_data)); + + ocsd_err_str(ret, err_buffer, ERR_BUFFER_SIZE); + printf("testing error API for code %d: %s\n", ret, err_buffer); + err_test = ocsd_get_last_err(&err_index, &cs_id, err_buffer, ERR_BUFFER_SIZE); + printf("get last error:\ncode = 0x%02x; trace index %d; cs_id 0x%02x;\nstring: %s\n", err_test, err_index, cs_id, err_buffer); + + } + return ret; +} + int main(int argc, char *argv[]) { FILE *trace_data; @@ -1012,9 +1105,12 @@ int main(int argc, char *argv[]) ocsd_def_errlog_msgout(message); /* process the trace data */ - if(ret == 0) - ret = process_trace_data(trace_data); - + if (ret == 0) { + if (test_error_api) + ret = test_err_api(); + else + ret = process_trace_data(trace_data); + } /* close the data file */ fclose(trace_data); } diff --git a/decoder/tests/source/frame_demux_test.cpp b/decoder/tests/source/frame_demux_test.cpp new file mode 100644 index 000000000000..69856cc7118a --- /dev/null +++ b/decoder/tests/source/frame_demux_test.cpp @@ -0,0 +1,524 @@ +/* +* \file frame_demux_test.cpp +* \brief OpenCSD: Test the frame demux code for robustness with correct and invalid data. +* +* \copyright Copyright (c) 2022, ARM Limited. All Rights Reserved. +*/ + +/* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Runs sets of test data through the frame demuxer to ensure that it is robust for valid and + * invalid inputs + */ + +#include <cstdio> +#include <string> +#include <iostream> +#include <sstream> +#include <cstring> + +#include "opencsd.h" // the library + + /* Decode tree is the main decoder framework - contains the frame demuxer + and will have an output printer attached to the raw output */ +static DecodeTree* pDecoder = 0; +static const uint32_t base_cfg = OCSD_DFRMTR_FRAME_MEM_ALIGN | + OCSD_DFRMTR_PACKED_RAW_OUT | OCSD_DFRMTR_UNPACKED_RAW_OUT; +static ocsdDefaultErrorLogger err_log; +static ocsdMsgLogger logger; + +/* test data */ +#define ID_BYTE_ID(id) ((uint8_t)(id) << 1 | 0x01) +#define ID_BYTE_DATA(data) ((uint8_t)(data & 0xFE)) +#define FLAGS_BYTE(id0, id1, id2, id3, id4, id5, id6, id7) ((uint8_t) ( \ + ((id7 & 0x1) << 7) | ((id6 & 0x1) << 6) | ((id5 & 0x1) << 5) | ((id4 & 0x1) << 4) | \ + ((id3 & 0x1) << 3) | ((id2 & 0x1) << 2) | ((id1 & 0x1) << 1) | (id0 & 0x1) )) +#define HSYNC_BYTES() 0xff, 0x7f +#define FSYNC_BYTES() 0xff, 0xff, 0xff, 0x7f +#define DATASIZE(array) static const size_t array##_sz = sizeof(array) / sizeof(array[0]) + + +static const uint8_t buf_hsync_fsync[] = { + FSYNC_BYTES(), + ID_BYTE_ID(0x10), 0x01, ID_BYTE_DATA(0x2), 0x03, + HSYNC_BYTES(), ID_BYTE_ID(0x20), 0x4, ID_BYTE_DATA(0x5), 0x6, + ID_BYTE_DATA(0x7), 0x08, HSYNC_BYTES(), ID_BYTE_DATA(0x9), 0xA, + ID_BYTE_ID(0x10), 0x0B, ID_BYTE_DATA(0xC), + FLAGS_BYTE(0, 0, 0, 1, 1, 1, 1, 0), +}; +DATASIZE(buf_hsync_fsync); + +static const uint8_t buf_mem_align[] = { + ID_BYTE_ID(0x10), 0x01, ID_BYTE_DATA(0x02), 0x03, + ID_BYTE_DATA(0x04), 0x05, ID_BYTE_DATA(0x06), 0x07, + ID_BYTE_ID(0x20), 0x08, ID_BYTE_DATA(0x09), 0x0A, + ID_BYTE_DATA(0x0B), 0x0C, ID_BYTE_DATA(0x0D), + FLAGS_BYTE(0, 0, 0, 0, 0, 1, 1, 1), + ID_BYTE_DATA(0x0E), 0x0F, ID_BYTE_ID(0x30), 0x10, + ID_BYTE_DATA(0x11), 0x12, ID_BYTE_DATA(0x13), 0x14, + ID_BYTE_DATA(0x15), 0x16, ID_BYTE_ID(0x10), 0x17, + ID_BYTE_DATA(0x18), 0x19, ID_BYTE_DATA(0x20), + FLAGS_BYTE(0, 0, 1, 1, 1, 1, 0, 0), +}; +DATASIZE(buf_mem_align); + +static const uint8_t buf_mem_align_8id[] = { + ID_BYTE_ID(0x10), 0x01, ID_BYTE_DATA(0x02), 0x03, + ID_BYTE_DATA(0x04), 0x05, ID_BYTE_DATA(0x06), 0x07, + ID_BYTE_ID(0x20), 0x08, ID_BYTE_DATA(0x09), 0x0A, + ID_BYTE_DATA(0x0B), 0x0C, ID_BYTE_DATA(0x0D), + FLAGS_BYTE(0, 0, 0, 0, 0, 1, 1, 1), + // 8 IDs, all with prev flag + ID_BYTE_ID(0x01), 0x0E, ID_BYTE_ID(0x02), 0x0F, + ID_BYTE_ID(0x03), 0x10, ID_BYTE_ID(0x04), 0x11, + ID_BYTE_ID(0x05), 0x12, ID_BYTE_ID(0x06), 0x13, + ID_BYTE_ID(0x07), 0x14, ID_BYTE_DATA(0x50), + FLAGS_BYTE(1, 1, 1, 1, 1, 1, 1, 1), + ID_BYTE_DATA(0x15), 0x16, ID_BYTE_DATA(0x17), 0x18, + ID_BYTE_DATA(0x19), 0x1A, ID_BYTE_DATA(0x1B), 0x1C, + ID_BYTE_ID(0x20), 0x1D, ID_BYTE_DATA(0x1E), 0x1F, + ID_BYTE_DATA(0x20), 0x21, ID_BYTE_DATA(0x22), + FLAGS_BYTE(1, 1, 1, 1, 0, 0, 0, 0), +}; +DATASIZE(buf_mem_align_8id); + +static const uint8_t buf_mem_align_st_rst[] = { + FSYNC_BYTES(), FSYNC_BYTES(), FSYNC_BYTES(), FSYNC_BYTES(), + ID_BYTE_ID(0x10), 0x01, ID_BYTE_DATA(0x02), 0x03, + ID_BYTE_DATA(0x04), 0x05, ID_BYTE_DATA(0x06), 0x07, + ID_BYTE_ID(0x20), 0x08, ID_BYTE_DATA(0x09), 0x0A, + ID_BYTE_DATA(0x0B), 0x0C, ID_BYTE_DATA(0x0D), + FLAGS_BYTE(0, 0, 0, 0, 0, 1, 1, 1), + ID_BYTE_DATA(0x0E), 0x0F, ID_BYTE_ID(0x30), 0x10, + ID_BYTE_DATA(0x11), 0x12, ID_BYTE_DATA(0x13), 0x14, + ID_BYTE_DATA(0x15), 0x16, ID_BYTE_ID(0x10), 0x17, + ID_BYTE_DATA(0x18), 0x19, ID_BYTE_DATA(0x20), + FLAGS_BYTE(0, 0, 1, 1, 1, 1, 0, 0), +}; +DATASIZE(buf_mem_align_st_rst); + +static const uint8_t buf_mem_align_mid_rst[] = { + ID_BYTE_ID(0x10), 0x01, ID_BYTE_DATA(0x02), 0x03, + ID_BYTE_DATA(0x04), 0x05, ID_BYTE_DATA(0x06), 0x07, + ID_BYTE_ID(0x20), 0x08, ID_BYTE_DATA(0x09), 0x0A, + ID_BYTE_DATA(0x0B), 0x0C, ID_BYTE_DATA(0x0D), + FLAGS_BYTE(0, 0, 0, 0, 0, 1, 1, 1), + FSYNC_BYTES(), FSYNC_BYTES(), FSYNC_BYTES(), FSYNC_BYTES(), + ID_BYTE_DATA(0x0E), 0x0F, ID_BYTE_ID(0x30), 0x10, + ID_BYTE_DATA(0x11), 0x12, ID_BYTE_DATA(0x13), 0x14, + ID_BYTE_DATA(0x15), 0x16, ID_BYTE_ID(0x10), 0x17, + ID_BYTE_DATA(0x18), 0x19, ID_BYTE_DATA(0x20), + FLAGS_BYTE(0, 0, 1, 1, 1, 1, 0, 0), +}; +DATASIZE(buf_mem_align_mid_rst); + +static const uint8_t buf_mem_align_en_rst[] = { + ID_BYTE_ID(0x10), 0x01, ID_BYTE_DATA(0x02), 0x03, + ID_BYTE_DATA(0x04), 0x05, ID_BYTE_DATA(0x06), 0x07, + ID_BYTE_ID(0x20), 0x08, ID_BYTE_DATA(0x09), 0x0A, + ID_BYTE_DATA(0x0B), 0x0C, ID_BYTE_DATA(0x0D), + FLAGS_BYTE(0, 0, 0, 0, 0, 1, 1, 1), + ID_BYTE_DATA(0x0E), 0x0F, ID_BYTE_ID(0x30), 0x10, + ID_BYTE_DATA(0x11), 0x12, ID_BYTE_DATA(0x13), 0x14, + ID_BYTE_DATA(0x15), 0x16, ID_BYTE_ID(0x10), 0x17, + ID_BYTE_DATA(0x18), 0x19, ID_BYTE_DATA(0x20), + FLAGS_BYTE(0, 0, 1, 1, 1, 1, 0, 0), + FSYNC_BYTES(), FSYNC_BYTES(), FSYNC_BYTES(), FSYNC_BYTES(), +}; +DATASIZE(buf_mem_align_en_rst); + +static const uint8_t buf_bad_data[] = { +0xff, 0xff, 0xff, 0x7f, 0x30, 0xff, 0x53, 0x54, 0x4d, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0, 0x36, 0xff, 0xb1, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x2b, +0x36, 0x36, 0x3a, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, +0, 0x2c, 0, 0, 0, 0x32, 0x1, 0, +}; +DATASIZE(buf_bad_data); + +static ocsd_err_t initDecoder(int init_opts) +{ + pDecoder = DecodeTree::CreateDecodeTree(OCSD_TRC_SRC_FRAME_FORMATTED, init_opts); + if (!pDecoder) + return OCSD_ERR_MEM; + return OCSD_OK; +} + +static void destroyDecoder() +{ + delete pDecoder; + pDecoder = 0; +} + +static void printTestHeaderStr(const char* hdr_str) +{ + std::ostringstream oss; + + oss << "\n---------------------------------------------------------\n"; + oss << hdr_str; + oss << "\n---------------------------------------------------------\n"; + logger.LogMsg(oss.str()); +} + +static void printSubTestName(const int test_num, const char* name) +{ + std::ostringstream oss; + + oss << "\n..Sub Test " << test_num << " : " << name << "\n"; + logger.LogMsg(oss.str()); +} + +static ocsd_err_t setConfig(uint32_t flags) +{ + TraceFormatterFrameDecoder* pFmt = pDecoder->getFrameDeformatter(); + return pFmt->Configure(flags); + +} + +// fail and print on none RESP_CONT response. +static ocsd_datapath_resp_t checkDataPathValue(ocsd_datapath_resp_t resp, int& failed_count) +{ + if (resp == OCSD_RESP_CONT) + return resp; + + std::ostringstream oss; + oss << "\nTest Datapath error response: " << ocsdDataRespStr(resp).getStr() << "\n"; + logger.LogMsg(oss.str()); + failed_count++; + return resp; +} + +static void resetDecoder(int& failed) +{ + checkDataPathValue(pDecoder->TraceDataIn(OCSD_OP_RESET, 0, 0, 0, 0), failed); +} + + +static void checkInOutSizes(const char *test, size_t in, size_t out, int& failed) +{ + if (in != out) { + failed++; + std::ostringstream oss; + oss << test << " test failed - mismatch between processed and input sizes:"; + oss << " In=" << in << "; Out=" << out; + logger.LogMsg(oss.str()); + } +} + +static int checkResult(int failed) +{ + std::ostringstream oss; + oss << "\nTEST : " << ((failed) ? "FAIL" : "PASS") << "\n"; + logger.LogMsg(oss.str()); + return failed; +} +static int testDemuxInit() +{ + ocsd_err_t err; + std::ostringstream oss; + int failed = 0; + + printTestHeaderStr("Demux Init Tests - check bad input rejected"); + + // init with invalid no flags + oss.str(""); + oss << "\nCheck 0 flag error: "; + err = initDecoder(0); + if (err) { + err = err_log.GetLastError()->getErrorCode(); + } + if (err != OCSD_ERR_INVALID_PARAM_VAL) { + oss << "FAIL: expected error code not returned\n"; + failed++; + } + else + oss << "PASS\n"; + logger.LogMsg(oss.str()); + + // init with invalid unknown flags + oss.str(""); + oss << "\nCheck unknown flag error: "; + err = initDecoder(0x80 | OCSD_DFRMTR_FRAME_MEM_ALIGN); + if (err) { + err = err_log.GetLastError()->getErrorCode(); + } + if (err != OCSD_ERR_INVALID_PARAM_VAL) { + oss << "FAIL: expected error code not returned\n"; + failed++; + } + else + oss << "PASS\n"; + logger.LogMsg(oss.str()); + + // init with bad combo + oss.str(""); + oss << "\nCheck bad combination flag error: "; + err = initDecoder(OCSD_DFRMTR_FRAME_MEM_ALIGN | OCSD_DFRMTR_HAS_FSYNCS); + if (err) { + err = err_log.GetLastError()->getErrorCode(); + } + if (err != OCSD_ERR_INVALID_PARAM_VAL) { + oss << "FAIL: expected error code not returned\n"; + failed++; + } + else + oss << "PASS\n"; + logger.LogMsg(oss.str()); + + return failed; +} + +static int runDemuxBadDataTest() +{ + + int failed = 0; + uint32_t processed = 0; + std::ostringstream oss; + ocsd_datapath_resp_t resp; + + printTestHeaderStr("Demux Bad Data Test - arbitrary test data input"); + + setConfig(base_cfg | OCSD_DFRMTR_RESET_ON_4X_FSYNC); + + // reset the decoder. + resetDecoder(failed); + resp = checkDataPathValue(pDecoder->TraceDataIn(OCSD_OP_DATA, 0, buf_bad_data_sz, buf_bad_data, &processed), failed); + if ((resp == OCSD_RESP_FATAL_INVALID_DATA) && + (err_log.GetLastError()->getErrorCode() == OCSD_ERR_DFMTR_BAD_FHSYNC)) + { + failed--; // cancel the fail - we require that the error happens for bad input + oss << "Got correct error response for invalid input\n"; + } + else + { + oss << "Expected error code not returned\n"; + } + logger.LogMsg(oss.str()); + + setConfig(base_cfg); + return checkResult(failed); +} + +static int runHSyncFSyncTest() +{ + uint32_t cfg_flags = base_cfg; + uint32_t processed = 0, total = 0; + ocsd_trc_index_t index = 0; + int failed = 0; + ocsd_datapath_resp_t resp; + std::ostringstream oss; + + printTestHeaderStr("FSYNC & HSYNC tests: check hander code for TPIU captures works."); + + // set for hsync / fsync operation + cfg_flags &= ~OCSD_DFRMTR_FRAME_MEM_ALIGN; // clear mem align + cfg_flags |= OCSD_DFRMTR_HAS_HSYNCS | OCSD_DFRMTR_HAS_FSYNCS; + setConfig(cfg_flags); + + // straight frame test with fsync + hsync + printSubTestName(1, "HSyncFSync frame"); + resetDecoder(failed); + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, index, buf_hsync_fsync_sz, buf_hsync_fsync, &processed), + failed); + checkInOutSizes("HSyncFSync frame", buf_hsync_fsync_sz, processed, failed); + + // test fsync broken across 2 input blocks + printSubTestName(2, "HSyncFSync split frame"); + resetDecoder(failed); + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, index, 2, buf_hsync_fsync, &processed), + failed); + total += processed; + index += processed; + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, index, buf_hsync_fsync_sz - processed, buf_hsync_fsync + processed, &processed), + failed); + total += processed; + checkInOutSizes("HSyncFSync split frame", buf_hsync_fsync_sz, total, failed); + + // check bad input data is rejected. + printSubTestName(3, "HSyncFSync bad input data"); + resetDecoder(failed); + resp = checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, index, buf_bad_data_sz, buf_bad_data, &processed), + failed); + if ((resp == OCSD_RESP_FATAL_INVALID_DATA) && + (err_log.GetLastError()->getErrorCode() == OCSD_ERR_DFMTR_BAD_FHSYNC)) + { + failed--; // cancel the fail - we require that the error happens for bad input + oss << "Got correct error response for invalid input\n"; + } + else + { + oss << "Expected error code not returned\n"; + } + logger.LogMsg(oss.str()); + + + setConfig(base_cfg); + return checkResult(failed); +} + +static int runMemAlignTest() +{ + uint32_t processed = 0; + int failed = 0; + + printTestHeaderStr("MemAligned Buffer tests: exercise the 16 byte frame buffer handler"); + + // default decoder set to mem align so just run the test. + + // straight frame pair + printSubTestName(1, "MemAlignFrame"); + resetDecoder(failed); + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, 0, buf_mem_align_sz, buf_mem_align, &processed), + failed); + checkInOutSizes("MemAlignFrame", buf_mem_align_sz, processed, failed); + + // frame with 8 id test + printSubTestName(2, "MemAlignFrame-8-ID"); + resetDecoder(failed); + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, 0, buf_mem_align_8id_sz, buf_mem_align_8id, &processed), + failed); + checkInOutSizes("MemAlignFrame-8-ID", buf_mem_align_8id_sz, processed, failed); + + // check reset FSYNC frame handling + setConfig(base_cfg | OCSD_DFRMTR_RESET_ON_4X_FSYNC); + printSubTestName(3, "MemAlignFrame-rst_st"); + resetDecoder(failed); + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, 0, buf_mem_align_st_rst_sz, buf_mem_align_st_rst, &processed), + failed); + checkInOutSizes("MemAlignFrame-rst_st", buf_mem_align_st_rst_sz, processed, failed); + + printSubTestName(4, "MemAlignFrame-rst_mid"); + resetDecoder(failed); + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, 0, buf_mem_align_mid_rst_sz, buf_mem_align_mid_rst, &processed), + failed); + checkInOutSizes("MemAlignFrame-rst_mid", buf_mem_align_mid_rst_sz, processed, failed); + + printSubTestName(5, "MemAlignFrame-rst_en"); + resetDecoder(failed); + checkDataPathValue( + pDecoder->TraceDataIn(OCSD_OP_DATA, 0, buf_mem_align_en_rst_sz, buf_mem_align_en_rst, &processed), + failed); + checkInOutSizes("MemAlignFrame-rst_en", buf_mem_align_en_rst_sz, processed, failed); + + setConfig(base_cfg); + return checkResult(failed); +} + +int main(int argc, char* argv[]) +{ + int failed = 0; + ocsd_err_t err; + std::ostringstream moss; + RawFramePrinter* framePrinter = 0; + + /* initialise logger */ + + static const int logOpts = ocsdMsgLogger::OUT_STDOUT | ocsdMsgLogger::OUT_FILE; + + logger.setLogOpts(logOpts); + logger.setLogFileName("frame_demux_test.ppl"); + moss << "---------------------------------------------------------\n"; + moss << "Trace Demux Frame Test - check CoreSight frame processing\n"; + moss << "---------------------------------------------------------\n\n"; + moss << "** Library Version : " << ocsdVersion::vers_str() << "\n\n"; + logger.LogMsg(moss.str()); + + /* initialise error logger */ + err_log.initErrorLogger(OCSD_ERR_SEV_INFO); + err_log.setOutputLogger(&logger); + DecodeTree::setAlternateErrorLogger(&err_log); + + /* run the init tests */ + failed += testDemuxInit(); + + /* create a decoder for the remainder of the tests */ + err = initDecoder(base_cfg); + moss.str(""); + moss << "Creating Decoder for active Demux testing\n"; + if (!err && pDecoder) { + err = pDecoder->addRawFramePrinter(&framePrinter, OCSD_DFRMTR_PACKED_RAW_OUT | OCSD_DFRMTR_UNPACKED_RAW_OUT); + if (err) + moss << "Failed to add Frame printer\n"; + } + if (err || !pDecoder) { + + moss << "Failed to initialise decoder for remainder of the tests\nSkipping active demux tests\n"; + failed++; + } + + /* remainder of the tests that need an active decoder */ + if (!err) { + try { + failed += runMemAlignTest(); + failed += runHSyncFSyncTest(); + failed += runDemuxBadDataTest(); + } + catch (ocsdError& err) { + moss.str(""); + moss << "*** TEST ERROR: Unhandled error from tests. Aborting test run ***\n"; + moss << err.getErrorString(err) << "\n"; + logger.LogMsg(moss.str()); + failed++; + } + } + + /* testing done */ + moss.str(""); + moss << "\n\n---------------------------------------------------------\n"; + moss << "Trace Demux Testing Complete\n"; + if (failed) + moss << "FAILED: recorded " << failed << " errors or failures.\n"; + else + moss << "PASSED ALL tests\n"; + moss << "\n\n---------------------------------------------------------\n"; + + logger.LogMsg(moss.str()); + + if (pDecoder) + destroyDecoder(); + + return failed ? -1 : 0; +} diff --git a/decoder/tests/source/mem_buff_demo.cpp b/decoder/tests/source/mem_buff_demo.cpp index cacc227e941f..052870fd3e56 100644 --- a/decoder/tests/source/mem_buff_demo.cpp +++ b/decoder/tests/source/mem_buff_demo.cpp @@ -126,6 +126,7 @@ static int initDataBuffers() FILE *fp; std::string filename; long size; + size_t bytes_read; /* the file names to create the data buffers */ #ifdef _WIN32 @@ -158,8 +159,10 @@ static int initDataBuffers() return OCSD_ERR_MEM; } rewind(fp); - fread(input_trace_data, 1, input_trace_data_size, fp); + bytes_read = fread(input_trace_data, 1, input_trace_data_size, fp); fclose(fp); + if (bytes_read < (size_t)input_trace_data_size) + return OCSD_ERR_FILE_ERROR; /* load up a memory image */ filename = default_base_snapshot_path; @@ -178,8 +181,10 @@ static int initDataBuffers() return OCSD_ERR_MEM; } rewind(fp); - fread(program_image_buffer, 1, program_image_size, fp); + bytes_read = fread(program_image_buffer, 1, program_image_size, fp); fclose(fp); + if (bytes_read < (size_t)program_image_size) + return OCSD_ERR_FILE_ERROR; program_image_address = mem_dump_address; return OCSD_OK; } diff --git a/decoder/tests/source/trc_pkt_lister.cpp b/decoder/tests/source/trc_pkt_lister.cpp index 50260a5f8b9b..9760351c9c7b 100644 --- a/decoder/tests/source/trc_pkt_lister.cpp +++ b/decoder/tests/source/trc_pkt_lister.cpp @@ -73,6 +73,8 @@ static int test_waits = 0; static bool dstream_format = false; static bool tpiu_format = false; static bool has_hsync = false; +static bool src_addr_n = false; +static bool stats = false; int main(int argc, char* argv[]) { @@ -185,14 +187,16 @@ void print_help() oss << "\nDecode:\n\n"; oss << "-id <n> Set an ID to list (may be used multiple times) - default if no id set is for all IDs to be printed\n"; oss << "-src_name <name> List packets from a given snapshot source name (defaults to first source found)\n"; - oss << "-dstream_format Input is DSTREAM framed."; - oss << "-tpiu Input from TPIU - sync by FSYNC."; - oss << "-tpiu_hsync Input from TPIU - sync by FSYNC and HSYNC."; + oss << "-dstream_format Input is DSTREAM framed.\n"; + oss << "-tpiu Input from TPIU - sync by FSYNC.\n"; + oss << "-tpiu_hsync Input from TPIU - sync by FSYNC and HSYNC.\n"; oss << "-decode Full decode of the packets from the trace snapshot (default is to list undecoded packets only\n"; oss << "-decode_only Does not list the undecoded packets, just the trace decode.\n"; oss << "-o_raw_packed Output raw packed trace frames\n"; oss << "-o_raw_unpacked Output raw unpacked trace data per ID\n"; oss << "-test_waits <N> Force wait from packet printer for N packets - test the wait/flush mechanisms for the decoder\n"; + oss << "-src_addr_n ETE protocol: Split source address ranges on N atoms\n"; + oss << "-stats Output packet processing statistics (if available).\n"; oss << "\nOutput:\n"; oss << " Setting any of these options cancels the default output to file & stdout,\n using _only_ the options supplied.\n\n"; oss << "-logstdout Output to stdout -> console.\n"; @@ -390,6 +394,14 @@ bool process_cmd_line_opts(int argc, char* argv[]) no_undecoded_packets = true; decode = true; } + else if (strcmp(argv[optIdx], "-src_addr_n") == 0) + { + src_addr_n = true; + } + else if (strcmp(argv[optIdx], "-stats") == 0) + { + stats = true; + } else if((strcmp(argv[optIdx], "-help") == 0) || (strcmp(argv[optIdx], "--help") == 0) || (strcmp(argv[optIdx], "-h") == 0)) { print_help(); @@ -518,8 +530,9 @@ void ConfigureFrameDeMux(DecodeTree *dcd_tree, RawFramePrinter **framePrinter) if (!configFlags) { configFlags = OCSD_DFRMTR_FRAME_MEM_ALIGN; - pDeformatter->Configure(configFlags); } + pDeformatter->Configure(configFlags); + if (outRawPacked || outRawUnpacked) { if (outRawPacked) configFlags |= OCSD_DFRMTR_PACKED_RAW_OUT; @@ -529,13 +542,67 @@ void ConfigureFrameDeMux(DecodeTree *dcd_tree, RawFramePrinter **framePrinter) } } +void PrintDecodeStats(DecodeTree *dcd_tree) +{ + uint8_t elemID; + std::ostringstream oss; + ocsd_decode_stats_t *pStats = 0; + ocsd_err_t err; + bool gotDemuxStats = false; + ocsd_demux_stats_t demux_stats; + + oss << "\nReading packet decoder statistics....\n\n"; + logger.LogMsg(oss.str()); + + DecodeTreeElement *pElement = dcd_tree->getFirstElement(elemID); + while (pElement) + { + oss.str(""); + err = dcd_tree->getDecoderStats(elemID, &pStats); + if (!err && pStats) + { + oss << "Decode stats ID 0x" << std::hex << (uint32_t)elemID << "\n"; + oss << "Total Bytes: " << std::dec << pStats->channel_total << "; Unsynced Bytes: " << std::dec << pStats->channel_unsynced << "\n"; + oss << "Bad Header Errors: " << std::dec << pStats->bad_header_errs << "; Bad Sequence Errors: " << std::dec << pStats->bad_sequence_errs << "\n"; + + // demux stats same for all IDs - grab them at the first opportunity.. + if (!gotDemuxStats) { + memcpy(&demux_stats, &pStats->demux, sizeof(ocsd_demux_stats_t)); + gotDemuxStats = true; + } + + } + else + oss << "Decode stats unavailable on Trace ID 0x" << std::hex << (uint32_t)elemID << "\n"; + + + logger.LogMsg(oss.str()); + pElement = dcd_tree->getNextElement(elemID); + } + + // if we have copied over the stats and there is at least 1 frame byte (impossible for there to be 0 if demuxing) + if (gotDemuxStats && demux_stats.frame_bytes) { + uint64_t total = demux_stats.valid_id_bytes + demux_stats.no_id_bytes + demux_stats.unknown_id_bytes + + demux_stats.reserved_id_bytes + demux_stats.frame_bytes; + oss.str(""); + oss << "\nFrame Demux Stats\n"; + oss << "Trace data bytes sent to registered ID decoders: " << std::dec << demux_stats.valid_id_bytes << "\n"; + oss << "Trace data bytes without registered ID decoders: " << std::dec << demux_stats.no_id_bytes << "\n"; + oss << "Trace data bytes with unknown ID: " << std::dec << demux_stats.unknown_id_bytes << "\n"; + oss << "Trace data bytes with reserved ID: " << std::dec << demux_stats.reserved_id_bytes << "\n"; + oss << "Frame demux bytes, ID bytes and sync bytes: " << std::dec << demux_stats.frame_bytes << "\n"; + oss << "Total bytes processed by frame demux: " << std::dec << total << "\n\n"; + logger.LogMsg(oss.str()); + } +} + void ListTracePackets(ocsdDefaultErrorLogger &err_logger, SnapShotReader &reader, const std::string &trace_buffer_name) { CreateDcdTreeFromSnapShot tree_creator; tree_creator.initialise(&reader, &err_logger); - if(tree_creator.createDecodeTree(trace_buffer_name, (decode == false))) + if(tree_creator.createDecodeTree(trace_buffer_name, (decode == false), src_addr_n ? ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS : 0)) { DecodeTree *dcd_tree = tree_creator.getDecodeTree(); dcd_tree->setAlternateErrorLogger(&err_logger); @@ -672,7 +739,8 @@ void ListTracePackets(ocsdDefaultErrorLogger &err_logger, SnapShotReader &reader std::ostringstream oss; oss << "Trace Packet Lister : Trace buffer done, processed " << trace_index << " bytes.\n"; logger.LogMsg(oss.str()); - + if (stats) + PrintDecodeStats(dcd_tree); } else { |