From: Parichay Kapoor Date: Tue, 9 Apr 2019 02:59:54 +0000 (+0900) Subject: [IIO] Added more test cases with corresponding bug fixes X-Git-Tag: accepted/tizen/unified/20190425.014439~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=96a1097a00e416282a3fed25f097d818ba96e577;p=platform%2Fupstream%2Fnnstreamer.git [IIO] Added more test cases with corresponding bug fixes 1. Added test cases for - caps verification - default restoration - setting trigger with number - using generic scan element type - auto enable channels 2. Corresponding bug fixes Signed-off-by: Parichay Kapoor --- diff --git a/gst/nnstreamer/tensor_source/tensor_src_iio.c b/gst/nnstreamer/tensor_source/tensor_src_iio.c index c7833f7..fc3206c 100644 --- a/gst/nnstreamer/tensor_source/tensor_src_iio.c +++ b/gst/nnstreamer/tensor_source/tensor_src_iio.c @@ -1282,9 +1282,12 @@ gst_tensor_set_all_channels (GstTensorSrcIIO * self, const gint contents) for (ch_list = self->channels; ch_list != NULL; ch_list = ch_list->next) { channel_prop = (GstTensorSrcIIOChannelProperties *) ch_list->data; filename = g_strdup_printf ("%s%s", channel_prop->name, EN_SUFFIX); - ret &= - gst_tensor_write_sysfs_int (self, filename, channel_prop->base_dir, - contents); + if (gst_tensor_write_sysfs_int (self, filename, channel_prop->base_dir, + contents)) { + channel_prop->enabled = TRUE; + } else { + ret = FALSE; + } g_free (filename); } @@ -1921,22 +1924,9 @@ gst_tensor_src_iio_query (GstBaseSrc * src, GstQuery * query) static gboolean gst_tensor_src_iio_set_caps (GstBaseSrc * src, GstCaps * caps) { - GstTensorSrcIIO *self; GstPad *pad; - self = GST_TENSOR_SRC_IIO (src); pad = src->srcpad; - - if (DBG) { - GstCaps *cur_caps = gst_pad_get_current_caps (pad); - if (cur_caps != NULL && !gst_caps_is_subset (caps, cur_caps)) { - silent_debug ("Setting caps in source mismatch"); - silent_debug ("caps = %" GST_PTR_FORMAT, caps); - silent_debug ("cur_caps = %" GST_PTR_FORMAT, cur_caps); - gst_caps_unref (cur_caps); - } - } - if (!gst_pad_set_caps (pad, caps)) { return FALSE; } diff --git a/tests/nnstreamer_source/unittest_src_iio.cpp b/tests/nnstreamer_source/unittest_src_iio.cpp index af08996..ccb63de 100644 --- a/tests/nnstreamer_source/unittest_src_iio.cpp +++ b/tests/nnstreamer_source/unittest_src_iio.cpp @@ -6,12 +6,14 @@ * @author Parichay Kapoor * @bug No known bugs. */ +#include #include #include #include #include #include #include +#include /** * @brief element name to be tested @@ -113,6 +115,7 @@ typedef struct _iio_dev_dir_struct gchar *scan_el_time_en; gchar *scan_el_time_index; gchar *scan_el_time_type; + gchar *scan_el_type_generic; gchar *dev_dir; gchar *dev_device_dir; @@ -204,7 +207,10 @@ make_iio_dev_structure (int num) g_build_filename (iio_dev->scan_el, "timestamp_index", NULL); iio_dev->scan_el_time_type = g_build_filename (iio_dev->scan_el, "timestamp_type", NULL); + iio_dev->scan_el_type_generic = + g_build_filename (iio_dev->scan_el, "in_voltage_type", NULL); + iio_dev->log_file = NULL; iio_dev->dev_dir = g_build_filename (iio_dev->base_dir, "dev", NULL); iio_dev->dev_device_dir = g_build_filename (iio_dev->dev_dir, device_folder_name, NULL); @@ -429,7 +435,7 @@ static gint build_dev_dir_samp_freq_avail (const iio_dev_dir_struct * iio_dev) { gint status = 0; - gchar *samp_freq_avail_string = g_strjoinv (",", (char **) samp_freq_avail); + gchar *samp_freq_avail_string = g_strjoinv (" ", (char **) samp_freq_avail); status += write_file_string (iio_dev->samp_freq_avail, samp_freq_avail_string); @@ -665,6 +671,7 @@ clean_iio_dev_structure (iio_dev_dir_struct * iio_dev) g_free (iio_dev->scan_el_time_en); g_free (iio_dev->scan_el_time_index); g_free (iio_dev->scan_el_time_type); + g_free (iio_dev->scan_el_type_generic); for (int idx = 0; idx < iio_dev->num_scan_elements; idx++) { g_free (iio_dev->scan_el_en[idx]); @@ -732,6 +739,7 @@ destroy_dev_dir (const iio_dev_dir_struct * iio_dev) status += safe_remove (iio_dev->scan_el_time_en); status += safe_remove (iio_dev->scan_el_time_index); status += safe_remove (iio_dev->scan_el_time_type); + status += safe_remove (iio_dev->scan_el_type_generic); status += safe_rmdir (iio_dev->scan_el); status += safe_remove (iio_dev->buf_en); @@ -760,7 +768,9 @@ destroy_dev_dir (const iio_dev_dir_struct * iio_dev) close (iio_dev->dev_device_dir_fd_read); status += safe_remove (iio_dev->dev_device_dir); status += safe_rmdir (iio_dev->dev_dir); - status += safe_remove (iio_dev->log_file); + if (iio_dev->log_file != NULL) { + status += safe_remove (iio_dev->log_file); + } status += safe_rmdir (iio_dev->base_dir); return status; @@ -1025,7 +1035,8 @@ TEST (test_tensor_src_iio, start_stop) /** * @brief tests tensor source IIO data without trigger */ \ -TEST (test_tensor_src_iio, data_verify_no_trigger_bits##DATA_BITS##_alternate##SKIP) \ +TEST (test_tensor_src_iio, \ + data_verify_no_trigger_bits##DATA_BITS##_alternate##SKIP) \ { \ iio_dev_dir_struct *dev0; \ GstElement *src_iio_pipeline; \ @@ -1050,14 +1061,15 @@ TEST (test_tensor_src_iio, data_verify_no_trigger_bits##DATA_BITS##_alternate##S /** setup */ \ samp_freq = g_ascii_strtoll (samp_freq_avail[0], NULL, 10); \ dev0->log_file = g_build_filename (dev0->base_dir, "temp.log", NULL); \ - parse_launch = \ - g_strdup_printf ("%s device=%s silent=FALSE ! multifilesink location=%s", \ + parse_launch = g_strdup_printf ( \ + "%s device=%s silent=FALSE ! multifilesink location=%s", \ ELEMENT_NAME, DEVICE_NAME, dev0->log_file); \ src_iio_pipeline = gst_parse_launch (parse_launch, NULL); \ /** state transition test upwards */ \ status = gst_element_set_state (src_iio_pipeline, GST_STATE_PLAYING); \ EXPECT_EQ (status, GST_STATE_CHANGE_ASYNC); \ - status = gst_element_get_state (src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); \ + status = gst_element_get_state (\ + src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); \ EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); \ EXPECT_EQ (state, GST_STATE_PLAYING); \ /** \ @@ -1073,14 +1085,16 @@ TEST (test_tensor_src_iio, data_verify_no_trigger_bits##DATA_BITS##_alternate##S if (stat_ret == 0 && stat_buf.st_size != 0) { \ /** verify playing state has been maintained */ \ status = \ - gst_element_get_state (src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); \ + gst_element_get_state ( \ + src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); \ EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); \ EXPECT_EQ (state, GST_STATE_PLAYING); \ /** state transition test downwards */ \ status = gst_element_set_state (src_iio_pipeline, GST_STATE_NULL); \ EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); \ status = \ - gst_element_get_state (src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); \ + gst_element_get_state ( \ + src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); \ EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); \ EXPECT_EQ (state, GST_STATE_NULL); \ break; \ @@ -1132,11 +1146,13 @@ GENERATE_TESTS_TO_VERIFY_DATA_WO_TRIGGER (DATA, 64, 2); /** * @brief tests tensor source IIO data with trigger * @note verifies that no frames have been lost as well + * @note verifies caps for the src pad as well */ TEST (test_tensor_src_iio, data_verify_trigger) { iio_dev_dir_struct *dev0; GstElement *src_iio_pipeline; + GstElement *src_iio; GstStateChangeReturn status; GstState state; gchar *parse_launch; @@ -1152,23 +1168,54 @@ TEST (test_tensor_src_iio, data_verify_trigger) gint stat_ret; data_value = DATA; data_bits = 16; + GstCaps *caps; + GstPad *src_pad; + GstStructure *structure; + GstTensorConfig config; + gint num_scan_elements; /** Make device */ dev0 = make_full_device (data_value, data_bits); ASSERT_NE (dev0, nullptr); /** setup */ + num_scan_elements = dev0->num_scan_elements; samp_freq = g_ascii_strtoll (samp_freq_avail[0], NULL, 10); dev0->log_file = g_build_filename (dev0->base_dir, "temp.log", NULL); parse_launch = g_strdup_printf - ("%s device-number=%d trigger=%s silent=FALSE ! multifilesink location=%s", + ("%s device-number=%d trigger=%s silent=FALSE " + "name=my-src-iio ! multifilesink location=%s", ELEMENT_NAME, 0, TRIGGER_NAME, dev0->log_file); src_iio_pipeline = gst_parse_launch (parse_launch, NULL); /** state transition test upwards */ status = gst_element_set_state (src_iio_pipeline, GST_STATE_PLAYING); EXPECT_EQ (status, GST_STATE_CHANGE_ASYNC); - status = gst_element_get_state (src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + status = + gst_element_get_state (src_iio_pipeline, &state, NULL, + GST_CLOCK_TIME_NONE); EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); EXPECT_EQ (state, GST_STATE_PLAYING); + + /** get and verify the caps */ + src_iio = gst_bin_get_by_name (GST_BIN (src_iio_pipeline), "my-src-iio"); + ASSERT_NE (src_iio, nullptr); + src_pad = gst_element_get_static_pad (src_iio, "src"); + ASSERT_NE (src_pad, nullptr); + caps = gst_pad_get_current_caps (src_pad); + ASSERT_NE (caps, nullptr); + structure = gst_caps_get_structure (caps, 0); + ASSERT_NE (structure, nullptr); + + /** Default has merge channels enabled */ + EXPECT_STREQ (gst_structure_get_name (structure), "other/tensor"); + EXPECT_EQ (gst_tensor_config_from_structure (&config, structure), TRUE); + EXPECT_EQ (config.rate_n, samp_freq); + EXPECT_EQ (config.rate_d, 1); + EXPECT_EQ (config.info.type, _NNS_FLOAT32); + EXPECT_EQ (config.info.dimension[0], num_scan_elements); + EXPECT_EQ (config.info.dimension[1], 1); + EXPECT_EQ (config.info.dimension[2], 1); + EXPECT_EQ (config.info.dimension[3], 1); + /** let a few frames transfer */ for (int idx = 0; idx < NUM_FRAMES; idx++) { /** wait for filter to process the frame and multifilesink to write it */ @@ -1206,13 +1253,17 @@ TEST (test_tensor_src_iio, data_verify_trigger) } /** verify playing state has been maintained */ - status = gst_element_get_state (src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + status = + gst_element_get_state (src_iio_pipeline, &state, NULL, + GST_CLOCK_TIME_NONE); EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); EXPECT_EQ (state, GST_STATE_PLAYING); /** state transition test downwards */ status = gst_element_set_state (src_iio_pipeline, GST_STATE_NULL); EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); - status = gst_element_get_state (src_iio_pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + status = + gst_element_get_state (src_iio_pipeline, &state, NULL, + GST_CLOCK_TIME_NONE); EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); EXPECT_EQ (state, GST_STATE_NULL); @@ -1224,6 +1275,146 @@ TEST (test_tensor_src_iio, data_verify_trigger) } /** + * @brief tests tensor source IIO data with set frequency + * @note verifies restoration of default values + * @note verifies setting trigger using trigger number + * @note verifies setting frequency manually + * @note verifies enabling of channels automatically + * @note verifies using generic type information for channels + */ +TEST (test_tensor_src_iio, data_verify_freq_generic_type) +{ + iio_dev_dir_struct *dev0; + GstElement *src_iio_pipeline; + GstStateChangeReturn status; + GstState state; + gchar *parse_launch; + gint samp_freq; + gint data_value; + guint data_bits; + gint fd, bytes_to_read, bytes_read; + gchar *data_buffer; + gfloat expect_val, actual_val; + guint64 expect_val_mask; + gchar *expect_val_char, *actual_val_char; + struct stat stat_buf; + gint stat_ret; + data_value = DATA; + data_bits = 16; + gint samp_freq_idx = 1; + gint num_scan_elements; + gchar *ret_string = NULL; + const gchar *buffer_length_char = "3"; + /** Make device */ + dev0 = make_full_device (data_value, data_bits); + ASSERT_NE (dev0, nullptr); + /** setup */ + num_scan_elements = dev0->num_scan_elements; + samp_freq = g_ascii_strtoll (samp_freq_avail[samp_freq_idx], NULL, 10); + dev0->log_file = g_build_filename (dev0->base_dir, "temp.log", NULL); + parse_launch = + g_strdup_printf + ("%s device-number=%d trigger-number=%d silent=FALSE frequency=%d " + "name=my-src-iio ! multifilesink location=%s", + ELEMENT_NAME, 0, 0, samp_freq, dev0->log_file); + src_iio_pipeline = gst_parse_launch (parse_launch, NULL); + + /** move channel specific type for channel 1 to generic */ + g_rename (dev0->scan_el_type[1], dev0->scan_el_type_generic); + /** disable all/some channels */ + for (int idx = 0; idx < num_scan_elements; idx++) { + write_file_int (dev0->scan_el_en[idx], 0); + } + /** set default sampling frequency and verify reset after closure */ + write_file_string (dev0->samp_freq, samp_freq_avail[samp_freq_idx + 1]); + /** set default sampling frequency and verify reset after closure */ + write_file_string (dev0->buf_length, buffer_length_char); + + /** state transition test upwards */ + status = gst_element_set_state (src_iio_pipeline, GST_STATE_PLAYING); + EXPECT_EQ (status, GST_STATE_CHANGE_ASYNC); + status = + gst_element_get_state (src_iio_pipeline, &state, NULL, + GST_CLOCK_TIME_NONE); + EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); + EXPECT_EQ (state, GST_STATE_PLAYING); + + /** let a few frames transfer */ + for (int idx = 0; idx < NUM_FRAMES; idx++) { + /** wait for filter to process the frame and multifilesink to write it */ + while (TRUE) { + if (g_file_test (dev0->log_file, G_FILE_TEST_IS_REGULAR)) { + stat_ret = stat (dev0->log_file, &stat_buf); + if (stat_ret == 0 && stat_buf.st_size != 0) { + break; + } + } + g_usleep (MAX (1, 1000000 / samp_freq)); + } + + /** verify correctness of data */ + fd = open (dev0->log_file, O_RDONLY); + bytes_to_read = sizeof (float) * BUF_LENGTH * dev0->num_scan_elements; + data_buffer = (gchar *) malloc (bytes_to_read); + bytes_read = read (fd, data_buffer, bytes_to_read); + EXPECT_EQ (bytes_read, bytes_to_read); + expect_val_mask = G_MAXUINT64 >> (64 - data_bits); + expect_val = ((data_value & expect_val_mask) + OFFSET) * SCALE; + expect_val_char = g_strdup_printf ("%.2f", expect_val); + for (int idx = 0; idx < bytes_to_read; idx += sizeof (float)) { + actual_val = *((gfloat *) data_buffer); + actual_val_char = g_strdup_printf ("%.2f", actual_val); + EXPECT_STREQ (expect_val_char, actual_val_char); + g_free (actual_val_char); + } + close (fd); + ASSERT_EQ (safe_remove (dev0->log_file), 0); + /** update data value to check data updates */ + data_value += 1; + ASSERT_EQ (build_dev_dir_scan_elements (dev0, data_bits, data_value, + data_value), 0); + } + + /** verify playing state has been maintained */ + status = + gst_element_get_state (src_iio_pipeline, &state, NULL, + GST_CLOCK_TIME_NONE); + EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); + EXPECT_EQ (state, GST_STATE_PLAYING); + /** state transition test downwards */ + status = gst_element_set_state (src_iio_pipeline, GST_STATE_NULL); + EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); + status = + gst_element_get_state (src_iio_pipeline, &state, NULL, + GST_CLOCK_TIME_NONE); + EXPECT_EQ (status, GST_STATE_CHANGE_SUCCESS); + EXPECT_EQ (state, GST_STATE_NULL); + + /** Verify default values */ + EXPECT_EQ (g_file_get_contents (dev0->samp_freq, &ret_string, NULL, NULL), + TRUE); + EXPECT_STREQ (ret_string, samp_freq_avail[samp_freq_idx + 1]); + g_free (ret_string); + EXPECT_EQ (g_file_get_contents (dev0->buf_length, &ret_string, NULL, NULL), + TRUE); + EXPECT_STREQ (ret_string, buffer_length_char); + g_free (ret_string); + for (int idx = 0; idx < num_scan_elements; idx++) { + EXPECT_EQ (g_file_get_contents (dev0->scan_el_en[idx], &ret_string, NULL, + NULL), TRUE); + EXPECT_STREQ (ret_string, "0"); + g_free (ret_string); + } + + /** delete device structure */ + gst_object_unref (src_iio_pipeline); + ASSERT_EQ (destroy_dev_dir (dev0), 0); + g_free (dev0->log_file); + clean_iio_dev_structure (dev0); +} + + +/** * @brief Main function for unit test. */ int