@@ -6,6 +6,7 @@ Author: Diffblue Limited.
6
6
7
7
\*******************************************************************/
8
8
9
+ #include < testing-utils/expr_query.h>
9
10
#include < testing-utils/use_catch.h>
10
11
11
12
#include < util/irep.h>
@@ -14,7 +15,9 @@ Author: Diffblue Limited.
14
15
#include < java-testing-utils/load_java_class.h>
15
16
#include < java-testing-utils/require_type.h>
16
17
18
+ #include < java_bytecode/java_bytecode_convert_method_class.h>
17
19
#include < java_bytecode/java_utils.h>
20
+ #include < testing-utils/message.h>
18
21
19
22
SCENARIO (
20
23
" java_bytecode_convert_bridge_method" ,
@@ -286,3 +289,232 @@ SCENARIO(
286
289
}
287
290
}
288
291
}
292
+
293
+ // / Allow access to private methods so that they can be unit tested
294
+ class java_bytecode_convert_method_unit_testt
295
+ {
296
+ public:
297
+ static exprt
298
+ convert_aload (const irep_idt &statement, const exprt::operandst &op)
299
+ {
300
+ return java_bytecode_convert_methodt::convert_aload (statement, op);
301
+ }
302
+
303
+ static code_blockt convert_astore (
304
+ java_bytecode_convert_methodt &converter,
305
+ const irep_idt &statement,
306
+ const exprt::operandst &op,
307
+ const source_locationt &location)
308
+ {
309
+ return converter.convert_astore (statement, op, location);
310
+ }
311
+ };
312
+
313
+ SCENARIO (
314
+ " baload byte array" ,
315
+ " [core][java_bytecode][java_bytecode_convert_method][convert_aload]" )
316
+ {
317
+ GIVEN (" A byte array" )
318
+ {
319
+ const typet byte_array_type = java_array_type (' b' );
320
+ const symbol_exprt byte_array{" byte_array" , byte_array_type};
321
+ const exprt offset = from_integer (1 , java_int_type ());
322
+ WHEN (" baload is called on the byte array" )
323
+ {
324
+ const exprt result =
325
+ java_bytecode_convert_method_unit_testt::convert_aload (
326
+ " baload" , {byte_array, offset});
327
+ THEN (" The Result is of the form `(int)(*(byte_array->data + offset))`" )
328
+ // See \ref java_bytecode_promotion on why we need a typecast to int.
329
+ {
330
+ const auto query = make_query (result)
331
+ .as <typecast_exprt>()[0 ]
332
+ .as <dereference_exprt>()[0 ]
333
+ .as <plus_exprt>();
334
+ REQUIRE (query[1 ].get () == offset);
335
+ auto member = query[0 ].as <member_exprt>();
336
+ REQUIRE (member.get ().get_component_name () == " data" );
337
+ REQUIRE (member[0 ].as <dereference_exprt>()[0 ].get () == byte_array);
338
+ REQUIRE (result.type () == java_int_type ());
339
+ // byte_array->data has type *byte
340
+ REQUIRE (member.get ().type () == pointer_type (java_byte_type ()));
341
+ }
342
+ }
343
+ }
344
+ }
345
+
346
+ SCENARIO (
347
+ " baload boolean array" ,
348
+ " [core][java_bytecode][java_bytecode_convert_method][convert_aload]" )
349
+ {
350
+ GIVEN (" A boolean array" )
351
+ {
352
+ const typet boolean_array_type = java_array_type (' z' );
353
+ const symbol_exprt boolean_array{" boolean_array" , boolean_array_type};
354
+ const exprt offset = from_integer (2 , java_int_type ());
355
+ WHEN (" baload is called on the byte array" )
356
+ {
357
+ const exprt result =
358
+ java_bytecode_convert_method_unit_testt::convert_aload (
359
+ " baload" , {boolean_array, offset});
360
+ THEN (" The result is of the form `(int)(*(boolean_array->data + offset))`" )
361
+ // See \ref java_bytecode_promotion on why we need a typecast to int.
362
+ {
363
+ const auto query = make_query (result)
364
+ .as <typecast_exprt>()[0 ]
365
+ .as <dereference_exprt>()[0 ]
366
+ .as <plus_exprt>();
367
+ REQUIRE (query[1 ].get () == offset);
368
+ REQUIRE (
369
+ query[0 ].as <member_exprt>()[0 ].as <dereference_exprt>()[0 ].get () ==
370
+ boolean_array);
371
+ // boolean_array->data has type *boolean
372
+ REQUIRE (
373
+ query[0 ].as <member_exprt>().get ().type () ==
374
+ pointer_type (java_boolean_type ()));
375
+ }
376
+ }
377
+ }
378
+ }
379
+
380
+ SCENARIO (
381
+ " iaload int array" ,
382
+ " [core][java_bytecode][java_bytecode_convert_method][convert_aload]" )
383
+ {
384
+ GIVEN (" An int array" )
385
+ {
386
+ const typet int_array_type = java_array_type (' i' );
387
+ const symbol_exprt int_array{" int_array" , int_array_type};
388
+ const exprt offset = from_integer (2 , java_int_type ());
389
+ WHEN (" iaload is called on the int array" )
390
+ {
391
+ const exprt result =
392
+ java_bytecode_convert_method_unit_testt::convert_aload (
393
+ " iaload" , {int_array, offset});
394
+ THEN (" The result is of the form `*(int_array->data + offset)`" )
395
+ {
396
+ const auto query =
397
+ make_query (result).as <dereference_exprt>()[0 ].as <plus_exprt>();
398
+ REQUIRE (query[1 ].get () == offset);
399
+ REQUIRE (
400
+ query[0 ].as <member_exprt>()[0 ].as <dereference_exprt>()[0 ].get () ==
401
+ int_array);
402
+ // int_array->data has type *int
403
+ REQUIRE (
404
+ query[0 ].as <member_exprt>().get ().type () ==
405
+ pointer_type (java_int_type ()));
406
+ }
407
+ }
408
+ }
409
+ }
410
+
411
+ SCENARIO (
412
+ " astore" ,
413
+ " [core][java_bytecode][java_bytecode_convert_method][convert_astore]" )
414
+ {
415
+ symbol_tablet symbol_table;
416
+ java_string_library_preprocesst string_preprocess;
417
+ const class_hierarchyt class_hierarchy;
418
+ java_bytecode_convert_methodt converter{symbol_table,
419
+ null_message_handler,
420
+ 10 ,
421
+ true ,
422
+ {},
423
+ string_preprocess,
424
+ class_hierarchy,
425
+ false };
426
+
427
+ GIVEN (" An int array" )
428
+ {
429
+ const source_locationt location;
430
+ const typet int_array_type = java_array_type (' i' );
431
+ const symbol_exprt int_array{" int_array" , int_array_type};
432
+ const exprt offset = from_integer (3 , java_int_type ());
433
+ const exprt value = from_integer (4 , java_int_type ());
434
+ WHEN (" iastore is called on the int array" )
435
+ {
436
+ const code_blockt result =
437
+ java_bytecode_convert_method_unit_testt::convert_astore (
438
+ converter, " iastore" , {int_array, offset, value}, location);
439
+ THEN (
440
+ " The result contains 1 statement of the form `*(int_array->data + 3) = "
441
+ " 4`" )
442
+ {
443
+ REQUIRE (result.statements ().size () == 1 );
444
+ auto query = make_query (result.statements ()[0 ]).as <code_assignt>();
445
+ REQUIRE (query[1 ].get () == value);
446
+ auto plus = query[0 ].as <dereference_exprt>()[0 ].as <plus_exprt>();
447
+ REQUIRE (plus[1 ].get () == offset);
448
+ REQUIRE (
449
+ plus[0 ].as <member_exprt>().get ().get_component_name () == " data" );
450
+ REQUIRE (
451
+ plus[0 ].as <member_exprt>()[0 ].as <dereference_exprt>()[0 ].get () ==
452
+ int_array);
453
+ THEN (" int_array->data has type *int" )
454
+ {
455
+ REQUIRE (
456
+ plus[0 ].as <member_exprt>().get ().type () ==
457
+ pointer_type (java_int_type ()));
458
+ }
459
+ }
460
+ }
461
+ }
462
+
463
+ GIVEN (" A boolean array" )
464
+ {
465
+ const source_locationt location;
466
+ const typet boolean_array_type = java_array_type (' z' );
467
+ const symbol_exprt boolean_array{" boolean_array" , boolean_array_type};
468
+ const exprt offset = from_integer (3 , java_int_type ());
469
+ const exprt value = from_integer (true , java_boolean_type ());
470
+ WHEN (" bastore is called on the boolean array" )
471
+ {
472
+ const code_blockt result =
473
+ java_bytecode_convert_method_unit_testt::convert_astore (
474
+ converter, " bastore" , {boolean_array, offset, value}, location);
475
+ THEN (
476
+ " The result contains 1 statement of the form "
477
+ " `*(boolean_array->data + 3) = true`" )
478
+ {
479
+ REQUIRE (result.statements ().size () == 1 );
480
+ auto query = make_query (result.statements ()[0 ]).as <code_assignt>();
481
+ REQUIRE (query[1 ].get () == value);
482
+ auto plus = query[0 ].as <dereference_exprt>()[0 ].as <plus_exprt>();
483
+ REQUIRE (plus[1 ].get () == offset);
484
+ REQUIRE (
485
+ plus[0 ].as <member_exprt>().get ().get_component_name () == " data" );
486
+ REQUIRE (
487
+ plus[0 ].as <member_exprt>()[0 ].as <dereference_exprt>()[0 ].get () ==
488
+ boolean_array);
489
+ THEN (" boolean_array->data has type *boolean" )
490
+ {
491
+ REQUIRE (
492
+ plus[0 ].as <member_exprt>().get ().type () ==
493
+ pointer_type (java_boolean_type ()));
494
+ }
495
+ }
496
+ }
497
+ WHEN (" iastore is called on the boolean array" )
498
+ {
499
+ const code_blockt result =
500
+ java_bytecode_convert_method_unit_testt::convert_astore (
501
+ converter, " iastore" , {boolean_array, offset, value}, location);
502
+ THEN (
503
+ " The result contains 1 statement of the form "
504
+ " `*(((int[])boolean_array)->data + offset)`" )
505
+ {
506
+ REQUIRE (result.statements ().size () == 1 );
507
+ REQUIRE (
508
+ make_query (result.statements ()[0 ])
509
+ .as <code_assignt>()[0 ]
510
+ .as <dereference_exprt>()[0 ]
511
+ .as <plus_exprt>()[0 ]
512
+ .as <member_exprt>()[0 ]
513
+ .as <dereference_exprt>()[0 ]
514
+ .as <typecast_exprt>()
515
+ .get ()
516
+ .type () == java_array_type (' i' ));
517
+ }
518
+ }
519
+ }
520
+ }
0 commit comments