/* * This file is part of the libsigrok project. * * Copyright (C) 2014 Uwe Hermann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "../include/libsigrok/libsigrok.h" #include "lib.h" /* Test lots of triggers/stages/matches/channels */ #define NUM_TRIGGERS 70 #define NUM_STAGES 30 #define NUM_MATCHES 70 #define NUM_CHANNELS NUM_MATCHES /* Check whether creating/freeing triggers with valid names works. */ START_TEST(test_trigger_new_free) { int i; struct sr_trigger *t[NUM_TRIGGERS]; char name[10]; /* Create a few triggers with a valid name. */ for (i = 0; i < NUM_TRIGGERS; i++) { sprintf((char *)&name, "T%d", i); t[i] = sr_trigger_new((const char *)&name); fail_unless(t[i] != NULL); fail_unless(!strcmp(t[i]->name, (const char *)&name)); fail_unless(t[i]->stages == NULL); } /* Free the triggers again (must not segfault). */ for (i = 0; i < NUM_TRIGGERS; i++) sr_trigger_free(t[i]); } END_TEST /* Check whether creating/freeing triggers with NULL names works. */ START_TEST(test_trigger_new_free_null) { int i; struct sr_trigger *t[NUM_TRIGGERS]; /* Create a few triggers with a NULL name (which is allowed). */ for (i = 0; i < NUM_TRIGGERS; i++) { t[i] = sr_trigger_new(NULL); fail_unless(t[i] != NULL); fail_unless(t[i]->name == NULL); fail_unless(t[i]->stages == NULL); } /* Free the triggers again (must not segfault). */ for (i = 0; i < NUM_TRIGGERS; i++) sr_trigger_free(t[i]); } END_TEST /* Check whether sr_trigger_free(NULL) works without segfaulting. */ START_TEST(test_trigger_free_null) { sr_trigger_free(NULL); } END_TEST /* Check whether creating/freeing triggers with stages works. */ START_TEST(test_trigger_stage_add) { int i, j; struct sr_trigger *t[NUM_TRIGGERS]; struct sr_trigger_stage *s[NUM_STAGES]; /* Create a few triggers with a valid name. */ for (i = 0; i < NUM_TRIGGERS; i++) { t[i] = sr_trigger_new("T"); /* Add a bunch of trigger stages to this trigger. */ for (j = 0; j < NUM_STAGES; j++) { s[j] = sr_trigger_stage_add(t[i]); fail_unless(s[j] != NULL); fail_unless(t[i]->stages != NULL); fail_unless((int)g_slist_length(t[i]->stages) == (j + 1)); fail_unless(s[j]->stage == j); fail_unless(s[j]->matches == NULL); } } /* Free the triggers again (must not segfault). */ for (i = 0; i < NUM_TRIGGERS; i++) sr_trigger_free(t[i]); } END_TEST /* Check whether creating NULL trigger stages fails (as it should). */ START_TEST(test_trigger_stage_add_null) { /* Should not segfault, but rather return NULL. */ fail_unless(sr_trigger_stage_add(NULL) == NULL); } END_TEST /* Check whether creating/freeing triggers with matches works. */ START_TEST(test_trigger_match_add) { int i, j, k, tm, ret; struct sr_trigger *t[NUM_TRIGGERS]; struct sr_trigger_stage *s[NUM_STAGES]; struct sr_channel *chl[NUM_CHANNELS]; struct sr_channel *cha[NUM_CHANNELS]; char name[10]; /* Create a bunch of logic and analog channels. */ for (i = 0; i < NUM_CHANNELS; i++) { sprintf((char *)&name, "L%d", i); chl[i] = g_malloc0(sizeof(struct sr_channel)); chl[i]->index = i; chl[i]->type = SR_CHANNEL_LOGIC; chl[i]->enabled = TRUE; chl[i]->name = g_strdup((const char *)&name); sprintf((char *)&name, "A%d", i); cha[i] = g_malloc0(sizeof(struct sr_channel)); cha[i]->index = i; cha[i]->type = SR_CHANNEL_ANALOG; cha[i]->enabled = TRUE; cha[i]->name = g_strdup((const char *)&name); } /* Create a few triggers with a valid name. */ for (i = 0; i < NUM_TRIGGERS; i++) { t[i] = sr_trigger_new("T"); /* Add a bunch of trigger stages to this trigger. */ for (j = 0; j < NUM_STAGES; j++) { s[j] = sr_trigger_stage_add(t[i]); /* Add a bunch of matches to this stage. */ for (k = 0; k < NUM_MATCHES; k++) { /* Logic channel matches. */ tm = 1 + (k % 5); /* *_ZERO .. *_EDGE */ ret = sr_trigger_match_add(s[j], chl[k], tm, 0); fail_unless(ret == SR_OK); /* Analog channel matches. */ tm = 3 + (k % 4); /* *_RISING .. *_UNDER */ ret = sr_trigger_match_add(s[j], cha[k], tm, ((rand() % 500) - 500) * 1.739); fail_unless(ret == SR_OK); } } } /* Free the triggers again (must not segfault). */ for (i = 0; i < NUM_TRIGGERS; i++) sr_trigger_free(t[i]); /* Free the channels. */ for (i = 0; i < NUM_CHANNELS; i++) { g_free(chl[i]->name); g_free(chl[i]); g_free(cha[i]->name); g_free(cha[i]); } } END_TEST /* Check whether trigger_match_add() copes well with incorrect input. */ START_TEST(test_trigger_match_add_bogus) { int ret; struct sr_trigger *t; struct sr_trigger_stage *s, *sl; struct sr_channel *chl, *cha; t = sr_trigger_new("T"); s = sr_trigger_stage_add(t); chl = g_malloc0(sizeof(struct sr_channel)); chl->index = 0; chl->type = SR_CHANNEL_LOGIC; chl->enabled = TRUE; chl->name = g_strdup("L0"); cha = g_malloc0(sizeof(struct sr_channel)); cha->index = 1; cha->type = SR_CHANNEL_ANALOG; cha->enabled = TRUE; cha->name = g_strdup("A0"); /* Initially we have no matches at all. */ sl = t->stages->data; fail_unless(g_slist_length(sl->matches) == 0); /* NULL stage */ ret = sr_trigger_match_add(NULL, chl, SR_TRIGGER_ZERO, 0); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); /* NULL channel */ ret = sr_trigger_match_add(s, NULL, SR_TRIGGER_ZERO, 0); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); /* Invalid trigger matches for logic channels. */ ret = sr_trigger_match_add(s, chl, SR_TRIGGER_OVER, 0); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); ret = sr_trigger_match_add(s, chl, SR_TRIGGER_UNDER, 0); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); /* Invalid trigger matches for analog channels. */ ret = sr_trigger_match_add(s, cha, SR_TRIGGER_ZERO, 9.4); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); ret = sr_trigger_match_add(s, cha, SR_TRIGGER_ONE, -9.4); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); /* Invalid channel type. */ chl->type = -1; ret = sr_trigger_match_add(s, chl, SR_TRIGGER_ZERO, 0); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); chl->type = 270; ret = sr_trigger_match_add(s, chl, SR_TRIGGER_ZERO, 0); fail_unless(ret == SR_ERR_ARG); fail_unless(g_slist_length(sl->matches) == 0); sr_trigger_free(t); g_free(chl->name); g_free(chl); g_free(cha->name); g_free(cha); } END_TEST Suite *suite_trigger(void) { Suite *s; TCase *tc; s = suite_create("trigger"); tc = tcase_create("new_free"); tcase_add_checked_fixture(tc, srtest_setup, srtest_teardown); tcase_add_test(tc, test_trigger_new_free); tcase_add_test(tc, test_trigger_new_free_null); tcase_add_test(tc, test_trigger_free_null); suite_add_tcase(s, tc); tc = tcase_create("stage"); tcase_add_checked_fixture(tc, srtest_setup, srtest_teardown); tcase_add_test(tc, test_trigger_stage_add); tcase_add_test(tc, test_trigger_stage_add_null); suite_add_tcase(s, tc); tc = tcase_create("match"); tcase_set_timeout(tc, 0); tcase_add_checked_fixture(tc, srtest_setup, srtest_teardown); tcase_add_test(tc, test_trigger_match_add); tcase_add_test(tc, test_trigger_match_add_bogus); suite_add_tcase(s, tc); return s; }