• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2015 Samsung Electronics Co., Ltd
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
26 #include "config.h"
27 
28 #include "zuc_collector.h"
29 
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #include <libweston/zalloc.h>
36 #include "zuc_event_listener.h"
37 #include "zunitc/zunitc_impl.h"
38 
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 
43 /**
44  * @file
45  * General handling of collecting events during testing to pass back to
46  * main tracking of fork()'d tests.
47  *
48  * @note implementation of zuc_process_message() is included here so that
49  * all child->parent IPC is in a single source file for easier maintenance
50  * and updating.
51  */
52 
53 /**
54  * Internal data struct for processing.
55  */
56 struct collector_data
57 {
58 	int *fd;		/**< file descriptor to output to. */
59 	struct zuc_test *test;	/**< current test, or NULL. */
60 };
61 
62 /**
63  * Stores an int32_t into the given buffer.
64  *
65  * @param ptr the buffer to store to.
66  * @param val the value to store.
67  * @return a pointer to the position in the buffer after the stored value.
68  */
69 static char *
70 pack_int32(char *ptr, int32_t val);
71 
72 /**
73  * Stores an intptr_t into the given buffer.
74  *
75  * @param ptr the buffer to store to.
76  * @param val the value to store.
77  * @return a pointer to the position in the buffer after the stored value.
78  */
79 static char *
80 pack_intptr_t(char *ptr, intptr_t val);
81 
82 /**
83  * Extracts a int32_t from the given buffer.
84  *
85  * @param ptr the buffer to extract from.
86  * @param val the value to set.
87  * @return a pointer to the position in the buffer after the extracted
88  * value.
89  */
90 static char const *
91 unpack_int32(char const *ptr, int32_t *val);
92 
93 /**
94  * Extracts a intptr_t from the given buffer.
95  *
96  * @param ptr the buffer to extract from.
97  * @param val the value to set.
98  * @return a pointer to the position in the buffer after the extracted
99  * value.
100  */
101 static char const *
102 unpack_intptr_t(char const *ptr, intptr_t *val);
103 
104 /**
105  * Extracts a length-prefixed string from the given buffer.
106  *
107  * @param ptr the buffer to extract from.
108  * @param str the value to set.
109  * @return a pointer to the position in the buffer after the extracted
110  * value.
111  */
112 static char const *
113 unpack_string(char const *ptr, char **str);
114 
115 /**
116  * Extracts an event from the given buffer.
117  *
118  * @param ptr the buffer to extract from.
119  * @param len the length of the given buffer.
120  * @return an event that was packed in the buffer
121  */
122 static struct zuc_event *
123 unpack_event(char const *ptr, int32_t len);
124 
125 /**
126  * Handles an event by either attaching it directly or sending it over IPC
127  * as needed.
128  */
129 static void
130 store_event(struct collector_data *cdata,
131 	    enum zuc_event_type event_type, char const *file, int line,
132 	    enum zuc_fail_state state, enum zuc_check_op op,
133 	    enum zuc_check_valtype valtype,
134 	    intptr_t val1, intptr_t val2, const char *expr1, const char *expr2);
135 
136 static void
137 destroy(void *data);
138 
139 static void
140 test_started(void *data, struct zuc_test *test);
141 
142 static void
143 test_ended(void *data, struct zuc_test *test);
144 
145 static void
146 check_triggered(void *data, char const *file, int line,
147 		enum zuc_fail_state state, enum zuc_check_op op,
148 		enum zuc_check_valtype valtype,
149 		intptr_t val1, intptr_t val2,
150 		const char *expr1, const char *expr2);
151 
152 static void
153 collect_event(void *data, char const *file, int line, const char *expr1);
154 
155 struct zuc_event_listener *
zuc_collector_create(int * pipe_fd)156 zuc_collector_create(int *pipe_fd)
157 {
158 	struct zuc_event_listener *listener =
159 		zalloc(sizeof(struct zuc_event_listener));
160 
161 	listener->data = zalloc(sizeof(struct collector_data));
162 	((struct collector_data *)listener->data)->fd = pipe_fd;
163 	listener->destroy = destroy;
164 	listener->test_started = test_started;
165 	listener->test_ended = test_ended;
166 	listener->check_triggered = check_triggered;
167 	listener->collect_event = collect_event;
168 
169 	return listener;
170 }
171 
172 char *
pack_int32(char * ptr,int32_t val)173 pack_int32(char *ptr, int32_t val)
174 {
175 	memcpy(ptr, &val, sizeof(val));
176 	return ptr + sizeof(val);
177 }
178 
179 char *
pack_intptr_t(char * ptr,intptr_t val)180 pack_intptr_t(char *ptr, intptr_t val)
181 {
182 	memcpy(ptr, &val, sizeof(val));
183 	return ptr + sizeof(val);
184 }
185 
186 static char *
pack_cstr(char * ptr,intptr_t val,int len)187 pack_cstr(char *ptr, intptr_t val, int len)
188 {
189 	if (val == 0) { /* a null pointer */
190 		ptr = pack_int32(ptr, -1);
191 	} else {
192 		ptr = pack_int32(ptr, len);
193 		memcpy(ptr, (const char *)val, len);
194 		ptr += len;
195 	}
196 	return ptr;
197 }
198 
199 void
destroy(void * data)200 destroy(void *data)
201 {
202 	free(data);
203 }
204 
205 void
test_started(void * data,struct zuc_test * test)206 test_started(void *data, struct zuc_test *test)
207 {
208 	struct collector_data *cdata = data;
209 	cdata->test = test;
210 }
211 
212 void
test_ended(void * data,struct zuc_test * test)213 test_ended(void *data, struct zuc_test *test)
214 {
215 	struct collector_data *cdata = data;
216 	cdata->test = NULL;
217 }
218 
219 void
check_triggered(void * data,char const * file,int line,enum zuc_fail_state state,enum zuc_check_op op,enum zuc_check_valtype valtype,intptr_t val1,intptr_t val2,const char * expr1,const char * expr2)220 check_triggered(void *data, char const *file, int line,
221 		enum zuc_fail_state state, enum zuc_check_op op,
222 		enum zuc_check_valtype valtype,
223 		intptr_t val1, intptr_t val2,
224 		const char *expr1, const char *expr2)
225 {
226 	struct collector_data *cdata = data;
227 	if (op != ZUC_OP_TRACEPOINT)
228 		store_event(cdata, ZUC_EVENT_IMMEDIATE, file, line, state, op,
229 			    valtype,
230 			    val1, val2, expr1, expr2);
231 }
232 
233 void
collect_event(void * data,char const * file,int line,const char * expr1)234 collect_event(void *data, char const *file, int line, const char *expr1)
235 {
236 	struct collector_data *cdata = data;
237 	store_event(cdata, ZUC_EVENT_DEFERRED, file, line, ZUC_CHECK_OK,
238 		    ZUC_OP_TRACEPOINT, ZUC_VAL_INT,
239 		    0, 0, expr1, "");
240 }
241 
242 void
store_event(struct collector_data * cdata,enum zuc_event_type event_type,char const * file,int line,enum zuc_fail_state state,enum zuc_check_op op,enum zuc_check_valtype valtype,intptr_t val1,intptr_t val2,const char * expr1,const char * expr2)243 store_event(struct collector_data *cdata,
244 	    enum zuc_event_type event_type, char const *file, int line,
245 	    enum zuc_fail_state state, enum zuc_check_op op,
246 	    enum zuc_check_valtype valtype,
247 	    intptr_t val1, intptr_t val2, const char *expr1, const char *expr2)
248 {
249 	struct zuc_event *event = zalloc(sizeof(*event));
250 	event->file = strdup(file);
251 	event->line = line;
252 	event->state = state;
253 	event->op = op;
254 	event->valtype = valtype;
255 	event->val1 = val1;
256 	event->val2 = val2;
257 	if (valtype == ZUC_VAL_CSTR) {
258 		if (val1)
259 			event->val1 = (intptr_t)strdup((const char *)val1);
260 		if (val2)
261 			event->val2 = (intptr_t)strdup((const char *)val2);
262 	}
263 	event->expr1 = strdup(expr1);
264 	event->expr2 = strdup(expr2);
265 
266 	zuc_attach_event(cdata->test, event, event_type, false);
267 
268 	if (*cdata->fd == -1) {
269 	} else {
270 		/* Need to pass it back */
271 		int sent;
272 		int count;
273 		int expr1_len = strlen(expr1);
274 		int expr2_len = strlen(expr2);
275 		int val1_len =
276 			((valtype == ZUC_VAL_CSTR) && val1) ?
277 			strlen((char *)val1) : 0;
278 		int val2_len =
279 			((valtype == ZUC_VAL_CSTR) && val2) ?
280 			strlen((char *)val2) : 0;
281 		int file_len = strlen(file);
282 		int len = (sizeof(int32_t) * 9) + file_len
283 			+ (sizeof(intptr_t) * 2)
284 			+ ((valtype == ZUC_VAL_CSTR) ?
285 			   (sizeof(int32_t) * 2) + val1_len + val2_len : 0)
286 			+ expr1_len + expr2_len;
287 		char *buf = zalloc(len);
288 
289 		char *ptr = pack_int32(buf, len - 4);
290 		ptr = pack_int32(ptr, event_type);
291 		ptr = pack_int32(ptr, file_len);
292 		memcpy(ptr, file, file_len);
293 		ptr += file_len;
294 		ptr = pack_int32(ptr, line);
295 		ptr = pack_int32(ptr, state);
296 		ptr = pack_int32(ptr, op);
297 		ptr = pack_int32(ptr, valtype);
298 		if (valtype == ZUC_VAL_CSTR) {
299 			ptr = pack_cstr(ptr, val1, val1_len);
300 			ptr = pack_cstr(ptr, val2, val2_len);
301 		} else {
302 			ptr = pack_intptr_t(ptr, val1);
303 			ptr = pack_intptr_t(ptr, val2);
304 		}
305 
306 		ptr = pack_int32(ptr, expr1_len);
307 		if (expr1_len) {
308 			memcpy(ptr, expr1, expr1_len);
309 			ptr += expr1_len;
310 		}
311 		ptr = pack_int32(ptr, expr2_len);
312 		if (expr2_len) {
313 			memcpy(ptr, expr2, expr2_len);
314 			ptr += expr2_len;
315 		}
316 
317 
318 		sent = 0;
319 		while (sent < len) {
320 			count = write(*cdata->fd, buf, len);
321 			if (count == -1)
322 				break;
323 			sent += count;
324 		}
325 
326 		free(buf);
327 	}
328 }
329 
330 char const *
unpack_int32(char const * ptr,int32_t * val)331 unpack_int32(char const *ptr, int32_t *val)
332 {
333 	memcpy(val, ptr, sizeof(*val));
334 	return ptr + sizeof(*val);
335 }
336 
337 char const *
unpack_intptr_t(char const * ptr,intptr_t * val)338 unpack_intptr_t(char const *ptr, intptr_t *val)
339 {
340 	memcpy(val, ptr, sizeof(*val));
341 	return ptr + sizeof(*val);
342 }
343 
344 char const *
unpack_string(char const * ptr,char ** str)345 unpack_string(char const *ptr, char **str)
346 {
347 	int32_t len = 0;
348 	ptr = unpack_int32(ptr, &len);
349 	*str = zalloc(len + 1);
350 	if (len)
351 		memcpy(*str, ptr, len);
352 	ptr += len;
353 	return ptr;
354 }
355 
356 static char const *
unpack_cstr(char const * ptr,char ** str)357 unpack_cstr(char const *ptr, char **str)
358 {
359 	int32_t len = 0;
360 	ptr = unpack_int32(ptr, &len);
361 	if (len < 0) {
362 		*str = NULL;
363 	} else {
364 		*str = zalloc(len + 1);
365 		if (len)
366 			memcpy(*str, ptr, len);
367 		ptr += len;
368 	}
369 	return ptr;
370 }
371 
372 struct zuc_event *
unpack_event(char const * ptr,int32_t len)373 unpack_event(char const *ptr, int32_t len)
374 {
375 	int32_t val = 0;
376 	struct zuc_event *evt = zalloc(sizeof(*evt));
377 	char const *tmp = unpack_string(ptr, &evt->file);
378 	tmp = unpack_int32(tmp, &evt->line);
379 
380 	tmp = unpack_int32(tmp, &val);
381 	evt->state = val;
382 	tmp = unpack_int32(tmp, &val);
383 	evt->op = val;
384 	tmp = unpack_int32(tmp, &val);
385 	evt->valtype = val;
386 
387 	if (evt->valtype == ZUC_VAL_CSTR) {
388 		char *ptr = NULL;
389 		tmp = unpack_cstr(tmp, &ptr);
390 		evt->val1 = (intptr_t)ptr;
391 		tmp = unpack_cstr(tmp, &ptr);
392 		evt->val2 = (intptr_t)ptr;
393 	} else {
394 		tmp = unpack_intptr_t(tmp, &evt->val1);
395 		tmp = unpack_intptr_t(tmp, &evt->val2);
396 	}
397 
398 	tmp = unpack_string(tmp, &evt->expr1);
399 	tmp = unpack_string(tmp, &evt->expr2);
400 
401 	return evt;
402 }
403 
404 int
zuc_process_message(struct zuc_test * test,int fd)405 zuc_process_message(struct zuc_test *test, int fd)
406 {
407 	char buf[4] = {};
408 	int got = read(fd, buf, 4);
409 	if (got == 4) {
410 		enum zuc_event_type event_type = ZUC_EVENT_IMMEDIATE;
411 		int32_t val = 0;
412 		int32_t len = 0;
413 		const char *tmp = NULL;
414 		char *raw = NULL;
415 		unpack_int32(buf, &len);
416 		raw = zalloc(len);
417 		got = read(fd, raw, len);
418 
419 		tmp = unpack_int32(raw, &val);
420 		event_type = val;
421 
422 		struct zuc_event *evt = unpack_event(tmp, len - (tmp - raw));
423 		zuc_attach_event(test, evt, event_type, true);
424 		free(raw);
425 	}
426 	return got;
427 }
428