1 /*
2 * Copyright © 2019 Manuel Stoeckl
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 "common.h"
27 #include "parsing.h"
28 #include "shadow.h"
29 #include "util.h"
30
31 #include <errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "protocol-test-proto.h"
37
38 /* from parsing.c */
39 bool size_check(const struct msg_data *data, const uint32_t *payload,
40 unsigned int true_length, int fd_length);
41
do_xtype_req_blue(struct context * ctx,const char * interface,uint32_t version,struct wp_object * id,int b,int32_t c,uint32_t d,struct wp_object * e,const char * f,uint32_t g)42 void do_xtype_req_blue(struct context *ctx, const char *interface,
43 uint32_t version, struct wp_object *id, int b, int32_t c,
44 uint32_t d, struct wp_object *e, const char *f, uint32_t g)
45 {
46 char buf[256];
47 sprintf(buf, "%s %u %u %d %d %u %u %s %u", interface, version,
48 id ? id->obj_id : 0, b, c, d, e ? e->obj_id : 0, f, g);
49 printf("%s\n", buf);
50 ctx->drop_this_msg =
51 strcmp(buf, "babacba 4441 992 7771 3331 4442 991 (null) 4443") !=
52 0;
53 }
do_xtype_evt_yellow(struct context * ctx,uint32_t c)54 void do_xtype_evt_yellow(struct context *ctx, uint32_t c)
55 {
56 char buf[256];
57 sprintf(buf, "%u", c);
58 printf("%s\n", buf);
59 ctx->drop_this_msg = strcmp(buf, "4441") != 0;
60 }
do_ytype_req_green(struct context * ctx,uint32_t a,const char * b,const char * c,int d,const char * e,struct wp_object * f,int g_count,const uint8_t * g_val)61 void do_ytype_req_green(struct context *ctx, uint32_t a, const char *b,
62 const char *c, int d, const char *e, struct wp_object *f,
63 int g_count, const uint8_t *g_val)
64 {
65 char buf[256];
66 sprintf(buf, "%u %s %s %d %s %u %d %x|%x|%x|%x|%x|%x|%x|%x", a, b, c, d,
67 e, f ? f->obj_id : 0, g_count, g_val[0], g_val[1],
68 g_val[2], g_val[3], g_val[4], g_val[5], g_val[6],
69 g_val[7]);
70 printf("%s\n", buf);
71 ctx->drop_this_msg =
72 strcmp(buf, "4441 bea (null) 7771 cbbc 991 8 81|80|81|80|90|99|99|99") !=
73 0;
74 }
do_ytype_evt_red(struct context * ctx,struct wp_object * a,int32_t b,int c,struct wp_object * d,int32_t e,int32_t f,struct wp_object * g,int32_t h,uint32_t i,const char * j,int k,int l_count,const uint8_t * l_val,uint32_t n,const char * m,struct wp_object * o,int p,struct wp_object * q)75 void do_ytype_evt_red(struct context *ctx, struct wp_object *a, int32_t b,
76 int c, struct wp_object *d, int32_t e, int32_t f,
77 struct wp_object *g, int32_t h, uint32_t i, const char *j,
78 int k, int l_count, const uint8_t *l_val, uint32_t n,
79 const char *m, struct wp_object *o, int p, struct wp_object *q)
80 {
81 char buf[256];
82 sprintf(buf, "%u %d %d %u %d %d %u %d %u %s %d %d %x|%x|%x %u %s %u %d %u",
83 a ? a->obj_id : 0, b, c, d ? d->obj_id : 0, e, f,
84 g ? g->obj_id : 0, h, i, j, k, l_count, l_val[0],
85 l_val[1], l_val[2], n, m, o ? o->obj_id : 0, p,
86 q ? q->obj_id : 0);
87 printf("%s\n", buf);
88 ctx->drop_this_msg =
89 strcmp(buf, "0 33330 8881 0 33331 33332 0 33333 44440 bcaba 8882 3 80|80|80 99990 (null) 992 8883 991") !=
90 0;
91 }
92
93 struct wire_test {
94 const struct wp_interface *intf;
95 int msg_offset;
96 int fds[4];
97 uint32_t words[50];
98 int nfds;
99 int nwords;
100 };
101
pack_u32(uint8_t a0,uint8_t a1,uint8_t a2,uint8_t a3)102 static inline uint32_t pack_u32(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3)
103 {
104 union {
105 uint8_t s[4];
106 uint32_t v;
107 } u;
108 u.s[0] = a0;
109 u.s[1] = a1;
110 u.s[2] = a2;
111 u.s[3] = a3;
112 return u.v;
113 }
114
115 log_handler_func_t log_funcs[2] = {test_log_handler, test_log_handler};
main(int argc,char ** argv)116 int main(int argc, char **argv)
117 {
118 (void)argc;
119 (void)argv;
120
121 struct message_tracker mt;
122 init_message_tracker(&mt);
123 struct wp_object *old_display = tracker_get(&mt, 1);
124 tracker_remove(&mt, old_display);
125 destroy_wp_object(old_display);
126
127 struct wp_object xobj;
128 xobj.type = &intf_xtype;
129 xobj.is_zombie = false;
130 xobj.obj_id = 991;
131 tracker_insert(&mt, &xobj);
132
133 struct wp_object yobj;
134 yobj.type = &intf_ytype;
135 yobj.is_zombie = false;
136 yobj.obj_id = 992;
137 tracker_insert(&mt, &yobj);
138
139 struct context ctx = {.obj = &xobj, .g = NULL};
140
141 struct wire_test tests[] = {
142 {&intf_xtype, 0, {7771},
143 {8, pack_u32(0x62, 0x61, 0x62, 0x61),
144 pack_u32(0x63, 0x62,
145 0x61,
146 0),
147 4441, yobj.obj_id, 3331,
148 4442, xobj.obj_id, 0,
149 4443},
150 1, 10},
151 {&intf_xtype, 1, {0}, {4441}, 0, 1},
152 {&intf_ytype, 0, {7771},
153 {4441, 4, pack_u32(0x62, 0x65, 0x61, 0),
154 0, 5,
155 pack_u32(0x63, 0x62,
156 0x62,
157 0x63),
158 pack_u32(0, 0x99, 0x99,
159 0x99),
160 xobj.obj_id, 8,
161 pack_u32(0x81, 0x80,
162 0x81,
163 0x80),
164 pack_u32(0x90, 0x99,
165 0x99,
166 0x99)},
167 1, 11},
168 {&intf_ytype, 1, {8881, 8882, 8883},
169 {7770, 33330, 7771, 33331, 33332, 7773,
170 33333, 44440, 6,
171 pack_u32(0x62, 0x63,
172 0x61,
173 0x62),
174 pack_u32(0x61, 0, 0x99,
175 0x99),
176 3,
177 pack_u32(0x80, 0x80,
178 0x80,
179 0x11),
180 99990, 0, yobj.obj_id,
181 xobj.obj_id},
182 3, 17}};
183
184 bool all_success = true;
185 for (size_t t = 0; t < sizeof(tests) / sizeof(tests[0]); t++) {
186 struct wire_test *wt = &tests[t];
187
188 ctx.drop_this_msg = false;
189 wp_callfn_t func = wt->intf->msgs[wt->msg_offset].call;
190
191 (*func)(&ctx, wt->words, wt->fds, &mt);
192 if (ctx.drop_this_msg) {
193 all_success = false;
194 }
195 printf("Function call %s.%s, %s\n", wt->intf->name,
196 get_nth_packed_string(wt->intf->msg_names,
197 wt->msg_offset),
198 ctx.drop_this_msg ? "FAIL" : "pass");
199
200 for (int fdlen = wt->nfds; fdlen >= 0; fdlen--) {
201 for (int length = wt->nwords; length >= 0; length--) {
202 if (fdlen != wt->nfds && length < wt->nwords) {
203 /* the fd check is really trivial */
204 continue;
205 }
206
207 bool expect_success = (wt->nwords == length) &&
208 (fdlen == wt->nfds);
209 printf("Trying: %d/%d words, %d/%d fds\n",
210 length, wt->nwords, fdlen,
211 wt->nfds);
212
213 bool sp = size_check(
214 &wt->intf->msgs[wt->msg_offset],
215 wt->words, (unsigned int)length,
216 fdlen);
217 if (sp != expect_success) {
218 wp_error("size check FAIL (%c, expected %c) at %d/%d chars, %d/%d fds",
219 sp ? 'Y' : 'n',
220 expect_success ? 'Y'
221 : 'n',
222 length, wt->nwords,
223 fdlen, wt->nfds);
224 }
225 all_success &= (sp == expect_success);
226 }
227 }
228 }
229
230 tracker_remove(&mt, &xobj);
231 tracker_remove(&mt, &yobj);
232 cleanup_message_tracker(&mt);
233
234 printf("Net result: %s\n", all_success ? "pass" : "FAIL");
235 return all_success ? EXIT_SUCCESS : EXIT_FAILURE;
236 }
237