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