1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stddef.h>
4 
5 #include <msgpuck.h>
6 
7 #include <tarantool/tarantool.h>
8 #include <tarantool/tnt_net.h>
9 
10 #include "common.h"
11 #include "tnt_assoc.h"
12 
13 void
hex_dump(const char * desc,const char * addr,size_t len)14 hex_dump (const char *desc, const char *addr, size_t len) {
15 	size_t i;
16 	unsigned char buff[17];
17 	unsigned char *pc = (unsigned char*)addr;
18 
19 	if (desc != NULL)
20 		printf ("%s:\n", desc);
21 	for (i = 0; i < len; i++) {
22 		if ((i % 16) == 0) {
23 			if (i != 0) printf ("  %s\n", buff);
24 			printf ("  %04x ", (unsigned int)i);
25 		}
26 		printf (" %02x", pc[i]);
27 		if ((pc[i] < 0x20) || (pc[i] > 0x7e))
28 			buff[i % 16] = '.';
29 		else
30 			buff[i % 16] = pc[i];
31 		buff[(i % 16) + 1] = '\0';
32 	}
33 	while ((i % 16) != 0) {
34 		printf ("   ");
35 		i++;
36 	}
37 	printf ("  %s\n", buff);
38 }
39 
40 void
hex_dump_c(const char * addr,size_t len)41 hex_dump_c (const char *addr, size_t len) {
42 	const char *addr_end = addr + len;
43 	size_t n = 0;
44 	while (addr < addr_end) {
45 		if (n == 0) { printf("\""); n = 14; }
46 		printf("\\x%02x", *(unsigned char *)addr);
47 		addr += 1; n -= 1;
48 		if (n == 0) { printf("\"\n"); }
49 	}
50 	if (n != 0) { printf("\"\n"); }
51 }
52 
53 static inline void
mp_dump_hex(const char * addr,size_t len)54 mp_dump_hex (const char *addr, size_t len) {
55 	const char *addr_end = addr + len;
56 	printf("\"");
57 	while (addr < addr_end) printf("\\x%02x", *(unsigned char *)addr++);
58 	printf("\"");
59 }
60 
61 void
mp_dump(const char * addr,size_t len)62 mp_dump (const char *addr, size_t len) {
63 	printf("mp_dump_begin\n  ");
64 	const char *addr_end = addr + len;
65 	struct mp_dump_stack stack[128];
66 	memset(stack, 0, sizeof(struct mp_dump_stack) * 128);
67 	size_t stack_size = 0;
68 	char begin = 1;
69 	while (addr < addr_end) {
70 		if (begin) {
71 			begin = 0;
72 		} else {
73 			if (stack_size > 0) {
74 				while (stack_size > 0 && stack[stack_size - 1].lft == 0) {
75 					switch (stack[stack_size - 1].type) {
76 					case (MP_ARRAY):
77 						printf("]");
78 						break;
79 					case (MP_MAP):
80 						printf("}");
81 						break;
82 					default:
83 						printf("???");
84 					}
85 					stack_size -= 1;
86 				}
87 				if (stack_size > 0 && stack[stack_size - 1].type == MP_MAP) {
88 					if (stack[stack_size - 1].lft % 2) {
89 						printf(":");
90 					} else if (!stack[stack_size - 1].start_flag) {
91 						printf(",");
92 					}
93 					if (!stack[stack_size - 1].start_flag)
94 						printf(" ");
95 					stack[stack_size - 1].start_flag = 0;
96 					stack[stack_size - 1].lft -= 1;
97 				}
98 			}
99 			if (!stack_size) {
100 				printf("\n  ");
101 			}
102 		}
103 		switch (mp_typeof(*addr)) {
104 		case (MP_NIL):
105 			printf("nil");
106 			mp_decode_nil(&addr);
107 			break;
108 		case (MP_UINT):
109 			printf("%zd", mp_decode_uint(&addr));
110 			break;
111 		case (MP_INT):
112 			printf("%zd", mp_decode_int(&addr));
113 			break;
114 		case (MP_STR): {
115 			uint32_t str_len = 0;
116 			const char *str = mp_decode_str(&addr, &str_len);
117 			printf("\"%.*s\"", str_len, str);
118 			break;
119 		}
120 		case (MP_BIN): {
121 			uint32_t bin_len = 0;
122 			const char *bin = mp_decode_bin(&addr, &bin_len);
123 			mp_dump_hex(bin, bin_len);
124 			break;
125 		}
126 		case (MP_ARRAY):
127 			stack[stack_size++] = (struct mp_dump_stack){
128 				.type = MP_ARRAY,
129 				.start_flag = 1,
130 				.lft = mp_decode_array(&addr)
131 			};
132 			printf("[");
133 			break;
134 		case (MP_MAP):
135 			stack[stack_size++] = (struct mp_dump_stack){
136 				.type = MP_MAP,
137 				.start_flag = 1,
138 				.lft = mp_decode_map(&addr) * 2
139 			};
140 			printf("{");
141 			break;
142 		case (MP_BOOL):
143 			if (mp_decode_bool(&addr)) {
144 				printf ("true");
145 			} else {
146 				printf ("false");
147 			}
148 			break;
149 		case (MP_FLOAT):
150 			printf("%f", mp_decode_float(&addr));
151 			break;
152 		case (MP_DOUBLE):
153 			printf("%f", mp_decode_double(&addr));
154 			break;
155 		case (MP_EXT):
156 			printf("ext");
157 			mp_next(&addr);
158 			break;
159 		default:
160 			printf("whattheheck");
161 			mp_next(&addr);
162 		}
163 	}
164 	while (stack_size > 0 && stack[stack_size - 1].lft == 0) {
165 		switch (stack[stack_size - 1].type) {
166 		case (MP_ARRAY):
167 			printf("]");
168 			break;
169 		case (MP_MAP):
170 			printf("}");
171 			break;
172 		default:
173 			printf("???");
174 		}
175 		stack_size -= 1;
176 	}
177 	printf("\n");
178 }
179 
180 int
check_bbytes(const char * buf,size_t buf_size,const char * bb,size_t bb_size)181 check_bbytes(const char *buf, size_t buf_size, const char *bb, size_t bb_size) {
182 	if (bb == NULL) goto error;
183 	if (buf_size != bb_size) goto error;
184 	if (memcmp(buf, bb, bb_size)) goto error;
185 	return 0;
186 error:
187 	if (bb) {
188 		hex_dump("expected", bb, bb_size);
189 		mp_dump(bb, bb_size);
190 	}
191 	hex_dump("got", (const char *)buf, buf_size);
192 	mp_dump(buf, buf_size);
193 	hex_dump_c((const char *)buf, buf_size);
194 	return -1;
195 }
196 
197 int
check_rbytes(struct tnt_reply * s,const char * bb,size_t bb_size)198 check_rbytes(struct tnt_reply *s, const char *bb, size_t bb_size) {
199 	return check_bbytes(s->buf, s->buf_size, bb, bb_size);
200 }
201 
202 int
check_sbytes(struct tnt_stream * s,const char * bb,size_t bb_size)203 check_sbytes(struct tnt_stream *s, const char *bb, size_t bb_size) {
204 	return check_bbytes(TNT_SBUF_DATA(s), TNT_SBUF_SIZE(s), bb, bb_size);
205 }
206 
207 int
check_nbytes(struct tnt_stream * s,const char * bb,size_t bb_size)208 check_nbytes(struct tnt_stream *s, const char *bb, size_t bb_size) {
209 	struct tnt_stream_net *sn = TNT_SNET_CAST(s);
210 	return check_bbytes(sn->sbuf.buf, sn->sbuf.off, bb, bb_size);
211 }
212 
dump_schema_index(struct tnt_schema_sval * sval)213 int dump_schema_index(struct tnt_schema_sval *sval) {
214 	mh_int_t ipos = 0;
215 	mh_foreach(sval->index, ipos) {
216 		struct tnt_schema_ival *ival = NULL;
217 		ival = (*mh_assoc_node(sval->index, ipos))->data;
218 		printf("    %d: %s\n", ival->number, ival->name);
219 	}
220 	return 0;
221 }
222 
dump_schema(struct tnt_stream * s)223 int dump_schema(struct tnt_stream *s) {
224 	struct mh_assoc_t *schema = (TNT_SNET_CAST(s)->schema)->space_hash;
225 	mh_int_t spos = 0;
226 	mh_foreach(schema, spos) {
227 		struct tnt_schema_sval *sval = NULL;
228 		sval = (*mh_assoc_node(schema, spos))->data;
229 		printf("  %d: %s\n", sval->number, sval->name);
230 		(void )dump_schema_index(sval);
231 	}
232 	return 0;
233 }
234