]> Git Repo - qemu.git/blob - tests/libqos/libqos.c
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.8-20160923' into staging
[qemu.git] / tests / libqos / libqos.c
1 #include "qemu/osdep.h"
2 #include <sys/wait.h>
3
4 #include "libqtest.h"
5 #include "libqos/libqos.h"
6 #include "libqos/pci.h"
7
8 /*** Test Setup & Teardown ***/
9
10 /**
11  * Launch QEMU with the given command line,
12  * and then set up interrupts and our guest malloc interface.
13  */
14 QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
15 {
16     char *cmdline;
17
18     struct QOSState *qs = g_malloc(sizeof(QOSState));
19
20     cmdline = g_strdup_vprintf(cmdline_fmt, ap);
21     qs->qts = qtest_start(cmdline);
22     qs->ops = ops;
23     if (ops && ops->init_allocator) {
24         qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
25     }
26
27     g_free(cmdline);
28     return qs;
29 }
30
31 /**
32  * Launch QEMU with the given command line,
33  * and then set up interrupts and our guest malloc interface.
34  */
35 QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...)
36 {
37     QOSState *qs;
38     va_list ap;
39
40     va_start(ap, cmdline_fmt);
41     qs = qtest_vboot(ops, cmdline_fmt, ap);
42     va_end(ap);
43
44     return qs;
45 }
46
47 /**
48  * Tear down the QEMU instance.
49  */
50 void qtest_shutdown(QOSState *qs)
51 {
52     if (qs->alloc && qs->ops && qs->ops->uninit_allocator) {
53         qs->ops->uninit_allocator(qs->alloc);
54         qs->alloc = NULL;
55     }
56     qtest_quit(qs->qts);
57     g_free(qs);
58 }
59
60 void set_context(QOSState *s)
61 {
62     global_qtest = s->qts;
63 }
64
65 static QDict *qmp_execute(const char *command)
66 {
67     char *fmt;
68     QDict *rsp;
69
70     fmt = g_strdup_printf("{ 'execute': '%s' }", command);
71     rsp = qmp(fmt);
72     g_free(fmt);
73
74     return rsp;
75 }
76
77 void migrate(QOSState *from, QOSState *to, const char *uri)
78 {
79     const char *st;
80     char *s;
81     QDict *rsp, *sub;
82     bool running;
83
84     set_context(from);
85
86     /* Is the machine currently running? */
87     rsp = qmp_execute("query-status");
88     g_assert(qdict_haskey(rsp, "return"));
89     sub = qdict_get_qdict(rsp, "return");
90     g_assert(qdict_haskey(sub, "running"));
91     running = qdict_get_bool(sub, "running");
92     QDECREF(rsp);
93
94     /* Issue the migrate command. */
95     s = g_strdup_printf("{ 'execute': 'migrate',"
96                         "'arguments': { 'uri': '%s' } }",
97                         uri);
98     rsp = qmp(s);
99     g_free(s);
100     g_assert(qdict_haskey(rsp, "return"));
101     QDECREF(rsp);
102
103     /* Wait for STOP event, but only if we were running: */
104     if (running) {
105         qmp_eventwait("STOP");
106     }
107
108     /* If we were running, we can wait for an event. */
109     if (running) {
110         migrate_allocator(from->alloc, to->alloc);
111         set_context(to);
112         qmp_eventwait("RESUME");
113         return;
114     }
115
116     /* Otherwise, we need to wait: poll until migration is completed. */
117     while (1) {
118         rsp = qmp_execute("query-migrate");
119         g_assert(qdict_haskey(rsp, "return"));
120         sub = qdict_get_qdict(rsp, "return");
121         g_assert(qdict_haskey(sub, "status"));
122         st = qdict_get_str(sub, "status");
123
124         /* "setup", "active", "completed", "failed", "cancelled" */
125         if (strcmp(st, "completed") == 0) {
126             QDECREF(rsp);
127             break;
128         }
129
130         if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0)) {
131             QDECREF(rsp);
132             g_usleep(5000);
133             continue;
134         }
135
136         fprintf(stderr, "Migration did not complete, status: %s\n", st);
137         g_assert_not_reached();
138     }
139
140     migrate_allocator(from->alloc, to->alloc);
141     set_context(to);
142 }
143
144 bool have_qemu_img(void)
145 {
146     char *rpath;
147     const char *path = getenv("QTEST_QEMU_IMG");
148     if (!path) {
149         return false;
150     }
151
152     rpath = realpath(path, NULL);
153     if (!rpath) {
154         return false;
155     } else {
156         free(rpath);
157         return true;
158     }
159 }
160
161 void mkimg(const char *file, const char *fmt, unsigned size_mb)
162 {
163     gchar *cli;
164     bool ret;
165     int rc;
166     GError *err = NULL;
167     char *qemu_img_path;
168     gchar *out, *out2;
169     char *qemu_img_abs_path;
170
171     qemu_img_path = getenv("QTEST_QEMU_IMG");
172     g_assert(qemu_img_path);
173     qemu_img_abs_path = realpath(qemu_img_path, NULL);
174     g_assert(qemu_img_abs_path);
175
176     cli = g_strdup_printf("%s create -f %s %s %uM", qemu_img_abs_path,
177                           fmt, file, size_mb);
178     ret = g_spawn_command_line_sync(cli, &out, &out2, &rc, &err);
179     if (err) {
180         fprintf(stderr, "%s\n", err->message);
181         g_error_free(err);
182     }
183     g_assert(ret && !err);
184
185     /* In glib 2.34, we have g_spawn_check_exit_status. in 2.12, we don't.
186      * glib 2.43.91 implementation assumes that any non-zero is an error for
187      * windows, but uses extra precautions for Linux. However,
188      * 0 is only possible if the program exited normally, so that should be
189      * sufficient for our purposes on all platforms, here. */
190     if (rc) {
191         fprintf(stderr, "qemu-img returned status code %d\n", rc);
192     }
193     g_assert(!rc);
194
195     g_free(out);
196     g_free(out2);
197     g_free(cli);
198     free(qemu_img_abs_path);
199 }
200
201 void mkqcow2(const char *file, unsigned size_mb)
202 {
203     return mkimg(file, "qcow2", size_mb);
204 }
205
206 void prepare_blkdebug_script(const char *debug_fn, const char *event)
207 {
208     FILE *debug_file = fopen(debug_fn, "w");
209     int ret;
210
211     fprintf(debug_file, "[inject-error]\n");
212     fprintf(debug_file, "event = \"%s\"\n", event);
213     fprintf(debug_file, "errno = \"5\"\n");
214     fprintf(debug_file, "state = \"1\"\n");
215     fprintf(debug_file, "immediately = \"off\"\n");
216     fprintf(debug_file, "once = \"on\"\n");
217
218     fprintf(debug_file, "[set-state]\n");
219     fprintf(debug_file, "event = \"%s\"\n", event);
220     fprintf(debug_file, "new_state = \"2\"\n");
221     fflush(debug_file);
222     g_assert(!ferror(debug_file));
223
224     ret = fclose(debug_file);
225     g_assert(ret == 0);
226 }
227
228 void generate_pattern(void *buffer, size_t len, size_t cycle_len)
229 {
230     int i, j;
231     unsigned char *tx = (unsigned char *)buffer;
232     unsigned char p;
233     size_t *sx;
234
235     /* Write an indicative pattern that varies and is unique per-cycle */
236     p = rand() % 256;
237     for (i = 0; i < len; i++) {
238         tx[i] = p++ % 256;
239         if (i % cycle_len == 0) {
240             p = rand() % 256;
241         }
242     }
243
244     /* force uniqueness by writing an id per-cycle */
245     for (i = 0; i < len / cycle_len; i++) {
246         j = i * cycle_len;
247         if (j + sizeof(*sx) <= len) {
248             sx = (size_t *)&tx[j];
249             *sx = i;
250         }
251     }
252 }
This page took 0.037174 seconds and 4 git commands to generate.