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