]> Git Repo - qemu.git/blob - tests/libqtest.c
Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
[qemu.git] / tests / libqtest.c
1 /*
2  * QTest
3  *
4  * Copyright IBM, Corp. 2012
5  * Copyright Red Hat, Inc. 2012
6  *
7  * Authors:
8  *  Anthony Liguori   <[email protected]>
9  *  Paolo Bonzini     <[email protected]>
10  *
11  * This work is licensed under the terms of the GNU GPL, version 2 or later.
12  * See the COPYING file in the top-level directory.
13  *
14  */
15 #include "libqtest.h"
16
17 #include <glib.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/wait.h>
21 #include <sys/un.h>
22 #include <inttypes.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28
29 #include "compiler.h"
30 #include "osdep.h"
31
32 #define MAX_IRQ 256
33
34 QTestState *global_qtest;
35
36 struct QTestState
37 {
38     int fd;
39     int qmp_fd;
40     bool irq_level[MAX_IRQ];
41     GString *rx;
42     gchar *pid_file;
43 };
44
45 #define g_assert_no_errno(ret) do { \
46     g_assert_cmpint(ret, !=, -1); \
47 } while (0)
48
49 static int init_socket(const char *socket_path)
50 {
51     struct sockaddr_un addr;
52     int sock;
53     int ret;
54
55     sock = socket(PF_UNIX, SOCK_STREAM, 0);
56     g_assert_no_errno(sock);
57
58     addr.sun_family = AF_UNIX;
59     snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path);
60     qemu_set_cloexec(sock);
61
62     do {
63         ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
64     } while (ret == -1 && errno == EINTR);
65     g_assert_no_errno(ret);
66     listen(sock, 1);
67
68     return sock;
69 }
70
71 static int socket_accept(int sock)
72 {
73     struct sockaddr_un addr;
74     socklen_t addrlen;
75     int ret;
76
77     do {
78         ret = accept(sock, (struct sockaddr *)&addr, &addrlen);
79     } while (ret == -1 && errno == EINTR);
80     g_assert_no_errno(ret);
81     close(sock);
82
83     return ret;
84 }
85
86 QTestState *qtest_init(const char *extra_args)
87 {
88     QTestState *s;
89     int sock, qmpsock, ret, i;
90     gchar *socket_path;
91     gchar *qmp_socket_path;
92     gchar *pid_file;
93     gchar *command;
94     const char *qemu_binary;
95     pid_t pid;
96
97     qemu_binary = getenv("QTEST_QEMU_BINARY");
98     g_assert(qemu_binary != NULL);
99
100     socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
101     qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
102     pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid());
103
104     s = g_malloc(sizeof(*s));
105
106     sock = init_socket(socket_path);
107     qmpsock = init_socket(qmp_socket_path);
108
109     pid = fork();
110     if (pid == 0) {
111         command = g_strdup_printf("%s "
112                                   "-qtest unix:%s,nowait "
113                                   "-qtest-log /dev/null "
114                                   "-qmp unix:%s,nowait "
115                                   "-pidfile %s "
116                                   "-machine accel=qtest "
117                                   "%s", qemu_binary, socket_path,
118                                   qmp_socket_path, pid_file,
119                                   extra_args ?: "");
120
121         ret = system(command);
122         exit(ret);
123         g_free(command);
124     }
125
126     s->fd = socket_accept(sock);
127     s->qmp_fd = socket_accept(qmpsock);
128
129     s->rx = g_string_new("");
130     s->pid_file = pid_file;
131     for (i = 0; i < MAX_IRQ; i++) {
132         s->irq_level[i] = false;
133     }
134
135     g_free(socket_path);
136     g_free(qmp_socket_path);
137
138     /* Read the QMP greeting and then do the handshake */
139     qtest_qmp(s, "");
140     qtest_qmp(s, "{ 'execute': 'qmp_capabilities' }");
141
142     return s;
143 }
144
145 void qtest_quit(QTestState *s)
146 {
147     FILE *f;
148     char buffer[1024];
149
150     f = fopen(s->pid_file, "r");
151     if (f) {
152         if (fgets(buffer, sizeof(buffer), f)) {
153             pid_t pid = atoi(buffer);
154             int status = 0;
155
156             kill(pid, SIGTERM);
157             waitpid(pid, &status, 0);
158         }
159
160         fclose(f);
161     }
162 }
163
164 static void socket_sendf(int fd, const char *fmt, va_list ap)
165 {
166     gchar *str;
167     size_t size, offset;
168
169     str = g_strdup_vprintf(fmt, ap);
170     size = strlen(str);
171
172     offset = 0;
173     while (offset < size) {
174         ssize_t len;
175
176         len = write(fd, str + offset, size - offset);
177         if (len == -1 && errno == EINTR) {
178             continue;
179         }
180
181         g_assert_no_errno(len);
182         g_assert_cmpint(len, >, 0);
183
184         offset += len;
185     }
186 }
187
188 static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
189 {
190     va_list ap;
191
192     va_start(ap, fmt);
193     socket_sendf(s->fd, fmt, ap);
194     va_end(ap);
195 }
196
197 static GString *qtest_recv_line(QTestState *s)
198 {
199     GString *line;
200     size_t offset;
201     char *eol;
202
203     while ((eol = strchr(s->rx->str, '\n')) == NULL) {
204         ssize_t len;
205         char buffer[1024];
206
207         len = read(s->fd, buffer, sizeof(buffer));
208         if (len == -1 && errno == EINTR) {
209             continue;
210         }
211
212         if (len == -1 || len == 0) {
213             fprintf(stderr, "Broken pipe\n");
214             exit(1);
215         }
216
217         g_string_append_len(s->rx, buffer, len);
218     }
219
220     offset = eol - s->rx->str;
221     line = g_string_new_len(s->rx->str, offset);
222     g_string_erase(s->rx, 0, offset + 1);
223
224     return line;
225 }
226
227 static gchar **qtest_rsp(QTestState *s, int expected_args)
228 {
229     GString *line;
230     gchar **words;
231     int i;
232
233 redo:
234     line = qtest_recv_line(s);
235     words = g_strsplit(line->str, " ", 0);
236     g_string_free(line, TRUE);
237
238     if (strcmp(words[0], "IRQ") == 0) {
239         int irq;
240
241         g_assert(words[1] != NULL);
242         g_assert(words[2] != NULL);
243
244         irq = strtoul(words[2], NULL, 0);
245         g_assert_cmpint(irq, >=, 0);
246         g_assert_cmpint(irq, <, MAX_IRQ);
247
248         if (strcmp(words[1], "raise") == 0) {
249             s->irq_level[irq] = true;
250         } else {
251             s->irq_level[irq] = false;
252         }
253
254         g_strfreev(words);
255         goto redo;
256     }
257
258     g_assert(words[0] != NULL);
259     g_assert_cmpstr(words[0], ==, "OK");
260
261     if (expected_args) {
262         for (i = 0; i < expected_args; i++) {
263             g_assert(words[i] != NULL);
264         }
265     } else {
266         g_strfreev(words);
267     }
268
269     return words;
270 }
271
272 void qtest_qmp(QTestState *s, const char *fmt, ...)
273 {
274     va_list ap;
275     bool has_reply = false;
276     int nesting = 0;
277
278     /* Send QMP request */
279     va_start(ap, fmt);
280     socket_sendf(s->qmp_fd, fmt, ap);
281     va_end(ap);
282
283     /* Receive reply */
284     while (!has_reply || nesting > 0) {
285         ssize_t len;
286         char c;
287
288         len = read(s->qmp_fd, &c, 1);
289         if (len == -1 && errno == EINTR) {
290             continue;
291         }
292
293         switch (c) {
294         case '{':
295             nesting++;
296             has_reply = true;
297             break;
298         case '}':
299             nesting--;
300             break;
301         }
302     }
303 }
304
305 const char *qtest_get_arch(void)
306 {
307     const char *qemu = getenv("QTEST_QEMU_BINARY");
308     const char *end = strrchr(qemu, '/');
309
310     return end + strlen("/qemu-system-");
311 }
312
313 bool qtest_get_irq(QTestState *s, int num)
314 {
315     /* dummy operation in order to make sure irq is up to date */
316     qtest_inb(s, 0);
317
318     return s->irq_level[num];
319 }
320
321 static int64_t qtest_clock_rsp(QTestState *s)
322 {
323     gchar **words;
324     int64_t clock;
325     words = qtest_rsp(s, 2);
326     clock = g_ascii_strtoll(words[1], NULL, 0);
327     g_strfreev(words);
328     return clock;
329 }
330
331 int64_t qtest_clock_step_next(QTestState *s)
332 {
333     qtest_sendf(s, "clock_step\n");
334     return qtest_clock_rsp(s);
335 }
336
337 int64_t qtest_clock_step(QTestState *s, int64_t step)
338 {
339     qtest_sendf(s, "clock_step %"PRIi64"\n", step);
340     return qtest_clock_rsp(s);
341 }
342
343 int64_t qtest_clock_set(QTestState *s, int64_t val)
344 {
345     qtest_sendf(s, "clock_set %"PRIi64"\n", val);
346     return qtest_clock_rsp(s);
347 }
348
349 void qtest_irq_intercept_out(QTestState *s, const char *qom_path)
350 {
351     qtest_sendf(s, "irq_intercept_out %s\n", qom_path);
352     qtest_rsp(s, 0);
353 }
354
355 void qtest_irq_intercept_in(QTestState *s, const char *qom_path)
356 {
357     qtest_sendf(s, "irq_intercept_in %s\n", qom_path);
358     qtest_rsp(s, 0);
359 }
360
361 static void qtest_out(QTestState *s, const char *cmd, uint16_t addr, uint32_t value)
362 {
363     qtest_sendf(s, "%s 0x%x 0x%x\n", cmd, addr, value);
364     qtest_rsp(s, 0);
365 }
366
367 void qtest_outb(QTestState *s, uint16_t addr, uint8_t value)
368 {
369     qtest_out(s, "outb", addr, value);
370 }
371
372 void qtest_outw(QTestState *s, uint16_t addr, uint16_t value)
373 {
374     qtest_out(s, "outw", addr, value);
375 }
376
377 void qtest_outl(QTestState *s, uint16_t addr, uint32_t value)
378 {
379     qtest_out(s, "outl", addr, value);
380 }
381
382 static uint32_t qtest_in(QTestState *s, const char *cmd, uint16_t addr)
383 {
384     gchar **args;
385     uint32_t value;
386
387     qtest_sendf(s, "%s 0x%x\n", cmd, addr);
388     args = qtest_rsp(s, 2);
389     value = strtoul(args[1], NULL, 0);
390     g_strfreev(args);
391
392     return value;
393 }
394
395 uint8_t qtest_inb(QTestState *s, uint16_t addr)
396 {
397     return qtest_in(s, "inb", addr);
398 }
399
400 uint16_t qtest_inw(QTestState *s, uint16_t addr)
401 {
402     return qtest_in(s, "inw", addr);
403 }
404
405 uint32_t qtest_inl(QTestState *s, uint16_t addr)
406 {
407     return qtest_in(s, "inl", addr);
408 }
409
410 static int hex2nib(char ch)
411 {
412     if (ch >= '0' && ch <= '9') {
413         return ch - '0';
414     } else if (ch >= 'a' && ch <= 'f') {
415         return 10 + (ch - 'a');
416     } else if (ch >= 'A' && ch <= 'F') {
417         return 10 + (ch - 'a');
418     } else {
419         return -1;
420     }
421 }
422
423 void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size)
424 {
425     uint8_t *ptr = data;
426     gchar **args;
427     size_t i;
428
429     qtest_sendf(s, "read 0x%" PRIx64 " 0x%zx\n", addr, size);
430     args = qtest_rsp(s, 2);
431
432     for (i = 0; i < size; i++) {
433         ptr[i] = hex2nib(args[1][2 + (i * 2)]) << 4;
434         ptr[i] |= hex2nib(args[1][2 + (i * 2) + 1]);
435     }
436
437     g_strfreev(args);
438 }
439
440 void qtest_add_func(const char *str, void (*fn))
441 {
442     gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
443     g_test_add_func(path, fn);
444 }
445
446 void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)
447 {
448     const uint8_t *ptr = data;
449     size_t i;
450
451     qtest_sendf(s, "write 0x%" PRIx64 " 0x%zx 0x", addr, size);
452     for (i = 0; i < size; i++) {
453         qtest_sendf(s, "%02x", ptr[i]);
454     }
455     qtest_sendf(s, "\n");
456     qtest_rsp(s, 0);
457 }
This page took 0.046818 seconds and 4 git commands to generate.