* @author Parichay Kapoor <pk.kapoor@samsung.com>
* @bug No known bugs.
*/
+#include <glib/gstdio.h>
#include <gtest/gtest.h>
#include <gst/gst.h>
#include <gst/check/gstharness.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
+#include <tensor_common.h>
/**
* @brief element name to be tested
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;
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);
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);
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]);
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);
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;
/**
* @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; \
/** 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); \
/** \
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; \
/**
* @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;
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 */
}
/** 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);
}
/**
+ * @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