blob: e17231cd8d127aff074e8518a26fea6b33e8db35 [file] [log] [blame]
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001/*
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 "shared/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 */
56struct 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 */
69static char *
70pack_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 */
79static char *
80pack_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 */
90static char const *
91unpack_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 */
101static char const *
102unpack_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 */
112static char const *
113unpack_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 */
122static struct zuc_event *
123unpack_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 */
129static void
130store_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
136static void
137destroy(void *data);
138
139static void
140test_started(void *data, struct zuc_test *test);
141
142static void
143test_ended(void *data, struct zuc_test *test);
144
145static void
146check_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
152static void
153collect_event(void *data, char const *file, int line, const char *expr1);
154
155struct zuc_event_listener *
156zuc_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
172char *
173pack_int32(char *ptr, int32_t val)
174{
175 memcpy(ptr, &val, sizeof(val));
176 return ptr + sizeof(val);
177}
178
179char *
180pack_intptr_t(char *ptr, intptr_t val)
181{
182 memcpy(ptr, &val, sizeof(val));
183 return ptr + sizeof(val);
184}
185
186static char *
187pack_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
199void
200destroy(void *data)
201{
202 free(data);
203}
204
205void
206test_started(void *data, struct zuc_test *test)
207{
208 struct collector_data *cdata = data;
209 cdata->test = test;
210}
211
212void
213test_ended(void *data, struct zuc_test *test)
214{
215 struct collector_data *cdata = data;
216 cdata->test = NULL;
217}
218
219void
220check_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
233void
234collect_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
242void
243store_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
330char const *
331unpack_int32(char const *ptr, int32_t *val)
332{
333 memcpy(val, ptr, sizeof(*val));
334 return ptr + sizeof(*val);
335}
336
337char const *
338unpack_intptr_t(char const *ptr, intptr_t *val)
339{
340 memcpy(val, ptr, sizeof(*val));
341 return ptr + sizeof(*val);
342}
343
344char const *
345unpack_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
356static char const *
357unpack_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
372struct zuc_event *
373unpack_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
404int
405zuc_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}