aboutsummaryrefslogtreecommitdiff
path: root/decoder/tests/source
diff options
context:
space:
mode:
Diffstat (limited to 'decoder/tests/source')
-rw-r--r--decoder/tests/source/c_api_pkt_print_test.c140
-rw-r--r--decoder/tests/source/frame_demux_test.cpp524
-rw-r--r--decoder/tests/source/mem_buff_demo.cpp9
-rw-r--r--decoder/tests/source/trc_pkt_lister.cpp80
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
{