1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2002-2018. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  *
20 
21  */
22 /*
23  * Author: Rickard Green
24  * Modified: Bj�rn-Egil Dahlberg
25  * -	compare_tuple
26  * -	compare_string
27  * -	compare_list
28  * -	compare_list and string
29  */
30 
31 #include "runner.h"
32 #include "erl_interface.h"
33 #include <stdio.h>
34 #include <string.h>
35 
36 typedef unsigned int uint;
37 
38 #define MAX_NC_EXT_SIZE 100
39 
40 static unsigned char *
41 write_pid(unsigned char *buf, char *node, uint cre, uint ser, uint num);
42 static unsigned char *
43 write_port(unsigned char *buf, char *node, uint cre, uint id);
44 static unsigned char *
45 write_ref(unsigned char *buf, char *node, uint cre, uint id[], uint no_ids);
46 static void
47 test_compare_ext(char *test_desc,
48 		 unsigned char *ext1,
49 		 unsigned char *end_ext1,
50 		 unsigned char *ext2,
51 		 unsigned char *end_ext2,
52 		 int exp_res);
53 
54 /*
55  * Test erl_compare_ext with tuples
56  */
TESTCASE(compare_tuple)57 TESTCASE(compare_tuple) {
58     // erlang:term_to_binary ({'b'})
59     unsigned char term1[] = { 131, 104, 1, 100, 0, 1, 98 };
60     // erlang:term_to_binary ({'a', 'a'})
61     unsigned char term2[] = { 131, 104, 2, 100, 0, 1, 97, 100, 0, 1, 97 };
62     unsigned char *start_a, *start_b, *end_a, *end_b;
63 
64     erl_init(NULL, 0);
65     start_a = term1;
66     start_b = term2;
67     end_a   = term1 + 7;
68     end_b   = term2 + 11;
69 
70     test_compare_ext("tuples", start_a, end_a, start_b, end_b, -1);
71 
72     report(1);
73 }
74 
75 /*
76  * Test erl_compare_ext with lists
77  */
78 
TESTCASE(compare_list)79 TESTCASE(compare_list) {
80     unsigned char *start_a, *start_b, *end_a, *end_b;
81     // erlang:term_to_binary([a,b,[],3412])
82     unsigned char term1[] = {131,108,0,0,0,4,100,0,1,97,100,0,1,98,106,98,0,0,13,84,106};
83     // erlang:term_to_binary([34,{a,n},a,erlang])
84     unsigned char term2[] = {131,108,0,0,0,4,97,34,104,2,100,0,1,97,100,0,1,110,100,0,1,97,100,0,6,101,114,108,97,110,103,106};
85 
86     // erlang:term_to_binary([0])
87     unsigned char term3[] = {131,107,0,1,0};
88     // erlang:term_to_binary([0, 1000])
89     unsigned char term4[] = {131,108,0,0,0,2,97,0,98,0,0,3,232,106};
90 
91     // erlang:term_to_binary([a|b])
92     unsigned char term5a[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,98};
93     // erlang:term_to_binary([a|c])
94     unsigned char term5b[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,99};
95 
96     erl_init(NULL, 0);
97     start_a = term1;
98     start_b = term2;
99     end_a   = term1 + 21;
100     end_b   = term2 + 32;
101 
102     test_compare_ext("lists", start_a, end_a, start_b, end_b, 1);
103 
104     start_a = term3;
105     start_b = term4;
106     end_a   = term3 + sizeof(term3);
107     end_b   = term4 + sizeof(term4);
108 
109     test_compare_ext("lists1", start_a, end_a, start_b, end_b, -1);
110 
111     start_a = term5a;
112     start_b = term5b;
113     end_a   = term5a + sizeof(term5a);
114     end_b   = term5b + sizeof(term5b);
115 
116     test_compare_ext("lists5", start_a, end_a, start_b, end_b, -1);
117 
118     report(1);
119 }
120 
121 /*
122  * Test erl_compare_ext with strings
123  */
124 
TESTCASE(compare_string)125 TESTCASE(compare_string) {
126     unsigned char *start_a, *start_b, *end_a, *end_b;
127     // erlang:term_to_binary("hej")
128     unsigned char term1[] = {131,107,0,3,104,101,106};
129     // erlang:term_to_binary("erlang")
130     unsigned char term2[] = {131,107,0,6,101,114,108,97,110,103};
131 
132     erl_init(NULL, 0);
133     start_a = term1;
134     start_b = term2;
135     end_a   = term1 + 7;
136     end_b   = term2 + 10;
137 
138     test_compare_ext("strings", start_a, end_a, start_b, end_b, 1);
139 
140     report(1);
141 }
142 
143 /*
144  * Test erl_compare_ext with lists and strings
145  */
146 
TESTCASE(compare_list_string)147 TESTCASE(compare_list_string) {
148     unsigned char *start_a, *start_b, *end_a, *end_b;
149     // erlang:term_to_binary("hej")
150     unsigned char term1[] = {131,107,0,3,104,101,106};
151     // erlang:term_to_binary([a,b,[],3412])
152     unsigned char term2[] = {131,108,0,0,0,4,100,0,1,97,100,0,1,98,106,98,0,0,13,84,106};
153 
154     erl_init(NULL, 0);
155     start_a = term1;
156     start_b = term2;
157     end_a   = term1 + 7;
158     end_b   = term2 + 21;
159 
160     test_compare_ext("strings", start_a, end_a, start_b, end_b, -1);
161 
162     report(1);
163 }
164 
165 
166 
167 /*
168  * Test erl_compare_ext with node containers
169  */
TESTCASE(compare_nc_ext)170 TESTCASE(compare_nc_ext)
171 {
172     int res;
173     unsigned char buf_a[MAX_NC_EXT_SIZE], buf_b[MAX_NC_EXT_SIZE];
174     unsigned char *end_a, *end_b;
175     uint id[3];
176 
177     erl_init(NULL, 0);
178 
179 
180     /*
181      * Test pids ----------------------------------------------------
182      *
183      * Significance (most -> least):
184      *   nodename, creation, serial, number, nodename, creation
185      *
186      */
187 
188     end_a = write_pid(buf_a, "b@b", 2, 4711, 1);
189 
190     end_b = write_pid(buf_b, "a@b", 1, 4710, 2);
191     test_compare_ext("pid test 1", buf_a, end_a, buf_b, end_b, -1);
192 
193     end_b = write_pid(buf_b, "a@b", 1, 4712, 1);
194     test_compare_ext("pid test 2", buf_a, end_a, buf_b, end_b, -1);
195 
196     end_b = write_pid(buf_b, "c@b", 1, 4711, 1);
197     test_compare_ext("pid test 3", buf_a, end_a, buf_b, end_b, -1);
198 
199     end_b = write_pid(buf_b, "b@b", 3, 4711, 1);
200     test_compare_ext("pid test 4", buf_a, end_a, buf_b, end_b, -1);
201 
202     end_b = write_pid(buf_b, "b@b", 2, 4711, 1);
203     test_compare_ext("pid test 5", buf_a, end_a, buf_b, end_b, 0);
204 
205 
206     /*
207      * Test ports ---------------------------------------------------
208      *
209      * Significance (most -> least):
210      *   nodename, creation, number
211      *
212      * OBS: Comparison between ports has changed in R9. This
213      *      since it wasn't stable in R8 (and eariler releases).
214      *      Significance used to be: dist_slot, number,
215      *      creation.
216      */
217 
218     end_a = write_port(buf_a, "b@b", 2, 4711),
219 
220     end_b = write_port(buf_b, "c@b", 1, 4710);
221     test_compare_ext("port test 1", buf_a, end_a, buf_b, end_b, -1);
222 
223     end_b = write_port(buf_b, "b@b", 3, 4710);
224     test_compare_ext("port test 2", buf_a, end_a, buf_b, end_b, -1);
225 
226     end_b = write_port(buf_b, "b@b", 2, 4712);
227     test_compare_ext("port test 3", buf_a, end_a, buf_b, end_b, -1);
228 
229     end_b = write_port(buf_b, "b@b", 2, 4711);
230     test_compare_ext("port test 4", buf_a, end_a, buf_b, end_b, 0);
231 
232     /*
233      * Test refs ----------------------------------------------------
234      * Significance (most -> least):
235      * nodename, creation, (number high, number mid), number low,
236      *
237      * OBS: Comparison between refs has changed in R9. This
238      *      since it wasn't stable in R8 (and eariler releases).
239      *      Significance used to be: dist_slot, number,
240      *      creation.
241      *
242      */
243 
244     /* Long & Long */
245 
246     id[0] = 4711; id[1] = 4711, id[2] = 4711;
247     end_a = write_ref(buf_a, "b@b", 2, id, 3);
248 
249 
250     id[0] = 4710; id[1] = 4710; id[2] = 4710;
251     end_b = write_ref(buf_b, "c@b", 1, id, 3);
252     test_compare_ext("ref test 1", buf_a, end_a, buf_b, end_b, -1);
253 
254     id[0] = 4710; id[1] = 4710; id[2] = 4710;
255     end_b = write_ref(buf_b, "b@b", 3, id, 3);
256     test_compare_ext("ref test 2", buf_a, end_a, buf_b, end_b, -1);
257 
258     id[0] = 4710; id[1] = 4710; id[2] = 4712;
259     end_b = write_ref(buf_b, "b@b", 2, id, 3);
260     test_compare_ext("ref test 3", buf_a, end_a, buf_b, end_b, -1);
261 
262     id[0] = 4710; id[1] = 4712; id[2] = 4711;
263     end_b = write_ref(buf_b, "b@b", 2, id, 3);
264     test_compare_ext("ref test 4", buf_a, end_a, buf_b, end_b, -1);
265 
266     id[0] = 4712; id[1] = 4711; id[2] = 4711;
267     end_b = write_ref(buf_b, "b@b", 2, id, 3);
268     test_compare_ext("ref test 5", buf_a, end_a, buf_b, end_b, -1);
269 
270     id[0] = 4711; id[1] = 4711; id[2] = 4711;
271     end_b = write_ref(buf_b, "b@b", 2, id, 3);
272     test_compare_ext("ref test 6", buf_a, end_a, buf_b, end_b, 0);
273 
274     /* Long & Short */
275     id[0] = 4711; id[1] = 0, id[2] = 0;
276     end_a = write_ref(buf_a, "b@b", 2, id, 3);
277 
278 
279     id[0] = 4710;
280     end_b = write_ref(buf_b, "c@b", 1, id, 1);
281     test_compare_ext("ref test 7", buf_a, end_a, buf_b, end_b, -1);
282 
283     id[0] = 4710;
284     end_b = write_ref(buf_b, "b@b", 3, id, 1);
285     test_compare_ext("ref test 8", buf_a, end_a, buf_b, end_b, -1);
286 
287     id[0] = 4712;
288     end_b = write_ref(buf_b, "b@b", 2, id, 1);
289     test_compare_ext("ref test 9", buf_a, end_a, buf_b, end_b, -1);
290 
291     id[0] = 4711;
292     end_b = write_ref(buf_b, "b@b", 2, id, 1);
293     test_compare_ext("ref test 10", buf_a, end_a, buf_b, end_b, 0);
294 
295     /* Short & Long */
296     id[0] = 4711;
297     end_a = write_ref(buf_a, "b@b", 2, id, 1);
298 
299 
300     id[0] = 4710; id[1] = 0, id[2] = 0;
301     end_b = write_ref(buf_b, "c@b", 1, id, 3);
302     test_compare_ext("ref test 11", buf_a, end_a, buf_b, end_b, -1);
303 
304     id[0] = 4710; id[1] = 0, id[2] = 0;
305     end_b = write_ref(buf_b, "b@b", 3, id, 3);
306     test_compare_ext("ref test 12", buf_a, end_a, buf_b, end_b, -1);
307 
308     id[0] = 4712; id[1] = 0, id[2] = 0;
309     end_b = write_ref(buf_b, "b@b", 2, id, 3);
310     test_compare_ext("ref test 13", buf_a, end_a, buf_b, end_b, -1);
311 
312     id[0] = 4711; id[1] = 0, id[2] = 0;
313     end_b = write_ref(buf_b, "b@b", 2, id, 3);
314     test_compare_ext("ref test 14", buf_a, end_a, buf_b, end_b, 0);
315 
316     /* Short & Short */
317     id[0] = 4711;
318     end_a = write_ref(buf_a, "b@b", 2, id, 1);
319 
320 
321     id[0] = 4710;
322     end_b = write_ref(buf_b, "c@b", 1, id, 1);
323     test_compare_ext("ref test 15", buf_a, end_a, buf_b, end_b, -1);
324 
325     id[0] = 4710;
326     end_b = write_ref(buf_b, "b@b", 3, id, 1);
327     test_compare_ext("ref test 16", buf_a, end_a, buf_b, end_b, -1);
328 
329     id[0] = 4712;
330     end_b = write_ref(buf_b, "b@b", 2, id, 1);
331     test_compare_ext("ref test 17", buf_a, end_a, buf_b, end_b, -1);
332 
333     id[0] = 4711;
334     end_b = write_ref(buf_b, "b@b", 2, id, 1);
335     test_compare_ext("ref test 18", buf_a, end_a, buf_b, end_b, 0);
336 
337     report(1);
338 }
339 
340 static void
test_compare_ext(char * test_desc,unsigned char * ext1,unsigned char * end_ext1,unsigned char * ext2,unsigned char * end_ext2,int exp_res)341 test_compare_ext(char *test_desc,
342 		 unsigned char *ext1,
343 		 unsigned char *end_ext1,
344 		 unsigned char *ext2,
345 		 unsigned char *end_ext2,
346 		 int exp_res)
347 {
348     int er, ar;
349     unsigned char *e1, *e2;
350     int reversed_args;
351     char ext_str[MAX_NC_EXT_SIZE*4 + 1];
352     char *es;
353 
354     message("*** %s ***", test_desc);
355     message("  erl_compare_ext() arguments:", test_desc);
356 
357     es = &ext_str[0];
358 
359     e1 = ext1;
360     while (e1 < end_ext1)
361 	es += sprintf(es, "%d,", *(e1++));
362     *(--es) = '\0';
363     message("    e1 = <<%s>>", ext_str);
364 
365 
366     es = &ext_str[0];
367 
368     e2 = ext2;
369     while (e2 < end_ext2)
370 	es += sprintf(es, "%d,", *(e2++));
371     *(--es) = '\0';
372     message("    e2 = <<%s>>", ext_str);
373 
374     message("Starting %s...", test_desc);
375 
376 
377     reversed_args = 0;
378     er = exp_res;
379     e1 = ext1;
380     e2 = ext2;
381 
382  reversed_args_start:
383 
384     ar = erl_compare_ext(e1, e2);
385     if (er < 0) {
386 	if (ar > 0)
387 	    fail("expected result e1 < e2; actual result e1 > e2\n");
388 	else if (ar == 0)
389 	    fail("expected result e1 < e2; actual result e1 = e2\n");
390     }
391     else if (er > 0) {
392 	if (ar < 0)
393 	    fail("expected result e1 > e2; actual result e1 < e2\n");
394 	else if (ar == 0)
395 	    fail("expected result e1 > e2; actual result e1 = e2\n");
396     }
397     else {
398 	if (ar > 0)
399 	    fail("expected result e1 = e2; actual result e1 > e2\n");
400 	else if (ar < 0)
401 	    fail("expected result e1 = e2; actual result e1 < e2\n");
402     }
403 
404     message("%s", "SUCCEEDED!");
405     if (!reversed_args) {
406 	message("Starting %s with reversed arguments...", test_desc);
407 	e2 = ext1;
408 	e1 = ext2;
409 	if (exp_res < 0)
410 	    er = 1;
411 	else if (exp_res > 0)
412 	    er = -1;
413 	reversed_args = 1;
414 	goto reversed_args_start;
415     }
416 
417     message("%s", "");
418 
419 }
420 
421 
422 #define SMALL_ATOM_UTF8_EXT (119)
423 #define REFERENCE_EXT     (101)
424 #define PORT_EXT          (102)
425 #define PID_EXT           (103)
426 #define NEW_REFERENCE_EXT (114)
427 
428 
429 #define PUT_UINT16(E, X) ((E)[0] = ((X) >> 8) & 0xff,  \
430 			  (E)[1] = (X) & 0xff)
431 
432 #define PUT_UINT32(E, X) ((E)[0] = ((X) >> 24) & 0xff, \
433 			  (E)[1] = ((X) >> 16) & 0xff, \
434 			  (E)[2] = ((X) >> 8) & 0xff,  \
435 			  (E)[3] = (X) & 0xff)
436 
437 static unsigned char *
write_atom(unsigned char * buf,char * atom)438 write_atom(unsigned char *buf, char *atom)
439 {
440     uint len;
441 
442     len = 0;
443     while(atom[len]) {
444 	buf[len + 2] = atom[len];
445 	len++;
446     }
447     buf[0] = SMALL_ATOM_UTF8_EXT;
448     buf[1] = len;
449 
450     return buf + 2 + len;
451 }
452 
453 static unsigned char *
write_pid(unsigned char * buf,char * node,uint cre,uint num,uint ser)454 write_pid(unsigned char *buf, char *node, uint cre, uint num, uint ser)
455 {
456     unsigned char *e = buf;
457 
458     *(e++) = PID_EXT;
459     e = write_atom(e, node);
460     PUT_UINT32(e, num & ((1 << 15) - 1));
461     e += 4;
462     PUT_UINT32(e, ser & ((1 << 3) - 1));
463     e += 4;
464     *(e++) = cre & ((1 << 2) - 1);
465 
466     return e;
467 }
468 
469 static unsigned char *
write_port(unsigned char * buf,char * node,uint cre,uint id)470 write_port(unsigned char *buf, char *node, uint cre, uint id)
471 {
472     unsigned char *e = buf;
473 
474     *(e++) = PORT_EXT;
475     e = write_atom(e, node);
476     PUT_UINT32(e, id & ((1 << 15) - 1));
477     e += 4;
478     *(e++) = cre & ((1 << 2) - 1);
479 
480     return e;
481 }
482 
483 static unsigned char *
write_ref(unsigned char * buf,char * node,uint cre,uint id[],uint no_ids)484 write_ref(unsigned char *buf, char *node, uint cre, uint id[], uint no_ids)
485 {
486     int i;
487     unsigned char *e = buf;
488 
489     if (no_ids == 1) {
490 	*(e++) = REFERENCE_EXT;
491 	e = write_atom(e, node);
492 	PUT_UINT32(e, id[0] & ((1 << 15) - 1));
493 	e += 4;
494 	*(e++) = cre & ((1 << 2) - 1);
495     }
496     else {
497 	*(e++) = NEW_REFERENCE_EXT;
498 	PUT_UINT16(e, no_ids);
499 	e += 2;
500 	e = write_atom(e, node);
501 	*(e++) = cre & ((1 << 2) - 1);
502 	for (i = 0; i < no_ids; i++) {
503 	    PUT_UINT32(e, id[i]);
504 	    e += 4;
505 	}
506     }
507 
508     return e;
509 }
510 
511