1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 Uwe Hermann <uwe@hermann-uwe.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <check.h>
24 #include <libsigrok/libsigrok.h>
25 #include "lib.h"
26 
27 /* Test lots of triggers/stages/matches/channels */
28 #define NUM_TRIGGERS 70
29 #define NUM_STAGES 30
30 #define NUM_MATCHES 70
31 #define NUM_CHANNELS NUM_MATCHES
32 
33 /* Check whether creating/freeing triggers with valid names works. */
START_TEST(test_trigger_new_free)34 START_TEST(test_trigger_new_free)
35 {
36 	int i;
37 	struct sr_trigger *t[NUM_TRIGGERS];
38 	char name[10];
39 
40 	/* Create a few triggers with a valid name. */
41 	for (i = 0; i < NUM_TRIGGERS; i++) {
42 		sprintf((char *)&name, "T%d", i);
43 		t[i] = sr_trigger_new((const char *)&name);
44 		fail_unless(t[i] != NULL);
45 		fail_unless(!strcmp(t[i]->name, (const char *)&name));
46 		fail_unless(t[i]->stages == NULL);
47 	}
48 
49 	/* Free the triggers again (must not segfault). */
50 	for (i = 0; i < NUM_TRIGGERS; i++)
51 		sr_trigger_free(t[i]);
52 }
53 END_TEST
54 
55 /* Check whether creating/freeing triggers with NULL names works. */
START_TEST(test_trigger_new_free_null)56 START_TEST(test_trigger_new_free_null)
57 {
58 	int i;
59 	struct sr_trigger *t[NUM_TRIGGERS];
60 
61 	/* Create a few triggers with a NULL name (which is allowed). */
62 	for (i = 0; i < NUM_TRIGGERS; i++) {
63 		t[i] = sr_trigger_new(NULL);
64 		fail_unless(t[i] != NULL);
65 		fail_unless(t[i]->name == NULL);
66 		fail_unless(t[i]->stages == NULL);
67 	}
68 
69 	/* Free the triggers again (must not segfault). */
70 	for (i = 0; i < NUM_TRIGGERS; i++)
71 		sr_trigger_free(t[i]);
72 }
73 END_TEST
74 
75 /* Check whether sr_trigger_free(NULL) works without segfaulting. */
START_TEST(test_trigger_free_null)76 START_TEST(test_trigger_free_null)
77 {
78 	sr_trigger_free(NULL);
79 }
80 END_TEST
81 
82 /* Check whether creating/freeing triggers with stages works. */
START_TEST(test_trigger_stage_add)83 START_TEST(test_trigger_stage_add)
84 {
85 	int i, j;
86 	struct sr_trigger *t[NUM_TRIGGERS];
87 	struct sr_trigger_stage *s[NUM_STAGES];
88 
89 	/* Create a few triggers with a valid name. */
90 	for (i = 0; i < NUM_TRIGGERS; i++) {
91 		t[i] = sr_trigger_new("T");
92 
93 		/* Add a bunch of trigger stages to this trigger. */
94 		for (j = 0; j < NUM_STAGES; j++) {
95 			s[j] = sr_trigger_stage_add(t[i]);
96 			fail_unless(s[j] != NULL);
97 			fail_unless(t[i]->stages != NULL);
98 			fail_unless((int)g_slist_length(t[i]->stages) == (j + 1));
99 			fail_unless(s[j]->stage == j);
100 			fail_unless(s[j]->matches == NULL);
101 		}
102 	}
103 
104 	/* Free the triggers again (must not segfault). */
105 	for (i = 0; i < NUM_TRIGGERS; i++)
106 		sr_trigger_free(t[i]);
107 }
108 END_TEST
109 
110 /* Check whether creating NULL trigger stages fails (as it should). */
START_TEST(test_trigger_stage_add_null)111 START_TEST(test_trigger_stage_add_null)
112 {
113 	/* Should not segfault, but rather return NULL. */
114 	fail_unless(sr_trigger_stage_add(NULL) == NULL);
115 }
116 END_TEST
117 
118 /* Check whether creating/freeing triggers with matches works. */
START_TEST(test_trigger_match_add)119 START_TEST(test_trigger_match_add)
120 {
121 	int i, j, k, tm, ret;
122 	struct sr_trigger *t[NUM_TRIGGERS];
123 	struct sr_trigger_stage *s[NUM_STAGES];
124 	struct sr_channel *chl[NUM_CHANNELS];
125 	struct sr_channel *cha[NUM_CHANNELS];
126 	char name[10];
127 
128 	/* Create a bunch of logic and analog channels. */
129 	for (i = 0; i < NUM_CHANNELS; i++) {
130 		sprintf((char *)&name, "L%d", i);
131 		chl[i] = g_malloc0(sizeof(struct sr_channel));
132 		chl[i]->index = i;
133 		chl[i]->type = SR_CHANNEL_LOGIC;
134 		chl[i]->enabled = TRUE;
135 		chl[i]->name = g_strdup((const char *)&name);
136 
137 		sprintf((char *)&name, "A%d", i);
138 		cha[i] = g_malloc0(sizeof(struct sr_channel));
139 		cha[i]->index = i;
140 		cha[i]->type = SR_CHANNEL_ANALOG;
141 		cha[i]->enabled = TRUE;
142 		cha[i]->name = g_strdup((const char *)&name);
143 	}
144 
145 	/* Create a few triggers with a valid name. */
146 	for (i = 0; i < NUM_TRIGGERS; i++) {
147 		t[i] = sr_trigger_new("T");
148 
149 		/* Add a bunch of trigger stages to this trigger. */
150 		for (j = 0; j < NUM_STAGES; j++) {
151 			s[j] = sr_trigger_stage_add(t[i]);
152 
153 			/* Add a bunch of matches to this stage. */
154 			for (k = 0; k < NUM_MATCHES; k++) {
155 				/* Logic channel matches. */
156 				tm = 1 + (k % 5); /* *_ZERO .. *_EDGE */
157 				ret = sr_trigger_match_add(s[j], chl[k], tm, 0);
158 				fail_unless(ret == SR_OK);
159 
160 				/* Analog channel matches. */
161 				tm = 3 + (k % 4); /* *_RISING .. *_UNDER */
162 				ret = sr_trigger_match_add(s[j], cha[k],
163 					tm, ((rand() % 500) - 500) * 1.739);
164 				fail_unless(ret == SR_OK);
165 			}
166 		}
167 	}
168 
169 	/* Free the triggers again (must not segfault). */
170 	for (i = 0; i < NUM_TRIGGERS; i++)
171 		sr_trigger_free(t[i]);
172 
173 	/* Free the channels. */
174 	for (i = 0; i < NUM_CHANNELS; i++) {
175 		g_free(chl[i]->name);
176 		g_free(chl[i]);
177 		g_free(cha[i]->name);
178 		g_free(cha[i]);
179 	}
180 }
181 END_TEST
182 
183 /* Check whether trigger_match_add() copes well with incorrect input. */
START_TEST(test_trigger_match_add_bogus)184 START_TEST(test_trigger_match_add_bogus)
185 {
186 	int ret;
187 	struct sr_trigger *t;
188 	struct sr_trigger_stage *s, *sl;
189 	struct sr_channel *chl, *cha;
190 
191 	t = sr_trigger_new("T");
192 	s = sr_trigger_stage_add(t);
193 	chl = g_malloc0(sizeof(struct sr_channel));
194 	chl->index = 0;
195 	chl->type = SR_CHANNEL_LOGIC;
196 	chl->enabled = TRUE;
197 	chl->name = g_strdup("L0");
198 	cha = g_malloc0(sizeof(struct sr_channel));
199 	cha->index = 1;
200 	cha->type = SR_CHANNEL_ANALOG;
201 	cha->enabled = TRUE;
202 	cha->name = g_strdup("A0");
203 
204 	/* Initially we have no matches at all. */
205 	sl = t->stages->data;
206 	fail_unless(g_slist_length(sl->matches) == 0);
207 
208 	/* NULL stage */
209 	ret = sr_trigger_match_add(NULL, chl, SR_TRIGGER_ZERO, 0);
210 	fail_unless(ret == SR_ERR_ARG);
211 	fail_unless(g_slist_length(sl->matches) == 0);
212 
213 	/* NULL channel */
214 	ret = sr_trigger_match_add(s, NULL, SR_TRIGGER_ZERO, 0);
215 	fail_unless(ret == SR_ERR_ARG);
216 	fail_unless(g_slist_length(sl->matches) == 0);
217 
218 	/* Invalid trigger matches for logic channels. */
219 	ret = sr_trigger_match_add(s, chl, SR_TRIGGER_OVER, 0);
220 	fail_unless(ret == SR_ERR_ARG);
221 	fail_unless(g_slist_length(sl->matches) == 0);
222 	ret = sr_trigger_match_add(s, chl, SR_TRIGGER_UNDER, 0);
223 	fail_unless(ret == SR_ERR_ARG);
224 	fail_unless(g_slist_length(sl->matches) == 0);
225 
226 	/* Invalid trigger matches for analog channels. */
227 	ret = sr_trigger_match_add(s, cha, SR_TRIGGER_ZERO, 9.4);
228 	fail_unless(ret == SR_ERR_ARG);
229 	fail_unless(g_slist_length(sl->matches) == 0);
230 	ret = sr_trigger_match_add(s, cha, SR_TRIGGER_ONE, -9.4);
231 	fail_unless(ret == SR_ERR_ARG);
232 	fail_unless(g_slist_length(sl->matches) == 0);
233 
234 	/* Invalid channel type. */
235 	chl->type = -1;
236 	ret = sr_trigger_match_add(s, chl, SR_TRIGGER_ZERO, 0);
237 	fail_unless(ret == SR_ERR_ARG);
238 	fail_unless(g_slist_length(sl->matches) == 0);
239 	chl->type = 270;
240 	ret = sr_trigger_match_add(s, chl, SR_TRIGGER_ZERO, 0);
241 	fail_unless(ret == SR_ERR_ARG);
242 	fail_unless(g_slist_length(sl->matches) == 0);
243 
244 	sr_trigger_free(t);
245 	g_free(chl->name);
246 	g_free(chl);
247 	g_free(cha->name);
248 	g_free(cha);
249 }
250 END_TEST
251 
suite_trigger(void)252 Suite *suite_trigger(void)
253 {
254 	Suite *s;
255 	TCase *tc;
256 
257 	s = suite_create("trigger");
258 
259 	tc = tcase_create("new_free");
260 	tcase_add_checked_fixture(tc, srtest_setup, srtest_teardown);
261 	tcase_add_test(tc, test_trigger_new_free);
262 	tcase_add_test(tc, test_trigger_new_free_null);
263 	tcase_add_test(tc, test_trigger_free_null);
264 	suite_add_tcase(s, tc);
265 
266 	tc = tcase_create("stage");
267 	tcase_add_checked_fixture(tc, srtest_setup, srtest_teardown);
268 	tcase_add_test(tc, test_trigger_stage_add);
269 	tcase_add_test(tc, test_trigger_stage_add_null);
270 	suite_add_tcase(s, tc);
271 
272 	tc = tcase_create("match");
273 	tcase_set_timeout(tc, 0);
274 	tcase_add_checked_fixture(tc, srtest_setup, srtest_teardown);
275 	tcase_add_test(tc, test_trigger_match_add);
276 	tcase_add_test(tc, test_trigger_match_add_bogus);
277 	suite_add_tcase(s, tc);
278 
279 	return s;
280 }
281