1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
|
/*******************************************************************\
Module: Unit test utilities
Author: Diffblue Ltd.
\*******************************************************************/
#include "require_type.h"
#include <testing-utils/use_catch.h>
/// Checks a type is a pointer type optionally with a specific subtype
/// \param type: The type to check
/// \param subtype: An optional subtype. If provided, checks the subtype of the
/// pointer is this.
/// \return A cast to pointer_typet version of type
pointer_typet require_type::require_pointer(
const typet &type,
const std::optional<typet> &subtype)
{
REQUIRE(type.id() == ID_pointer);
const pointer_typet &pointer = to_pointer_type(type);
if(subtype)
REQUIRE(pointer.base_type() == subtype.value());
return pointer;
}
/// Checks that a class has a component with a specific name
/// \param java_class_type: The class that should have the component
/// \param component_name: The name of the component
/// \return The component with the specified name
java_class_typet::componentt require_type::require_component(
const java_class_typet &java_class_type,
const irep_idt &component_name)
{
const auto &component = std::find_if(
java_class_type.components().begin(),
java_class_type.components().end(),
[&component_name](const java_class_typet::componentt &component) {
return component.get_name() == component_name;
});
REQUIRE(component != java_class_type.components().end());
return *component;
}
/// Checks a struct like type has a component with a specific name
/// \param struct_type: The structure that should have the component
/// \param component_name: The name of the component
/// \return The component with the specified name
struct_typet::componentt require_type::require_component(
const struct_typet &struct_type,
const irep_idt &component_name)
{
const auto &componet = std::find_if(
struct_type.components().begin(),
struct_type.components().end(),
[&component_name](const struct_union_typet::componentt &component) {
return component.get_name() == component_name;
});
REQUIRE(componet != struct_type.components().end());
return *componet;
}
/// Checks a type is a code_type (i.e. a function)
/// \param type: The type to check
/// \return The cast version of the type code_type
code_typet require_type::require_code(const typet &type)
{
REQUIRE(type.id() == ID_code);
return to_code_type(type);
}
/// Verify a given type is an code_typet, and that the code it represents
/// accepts a given number of parameters
/// \param type: The type to check
/// \param num_params: check the the given code_typet expects this
/// number of parameters
/// \return The type cast to a code_typet
code_typet
require_type::require_code(const typet &type, const size_t num_params)
{
code_typet code_type = require_code(type);
REQUIRE(code_type.parameters().size() == num_params);
return code_type;
}
/// Checks a type is a java_method_typet (i.e. a function)
/// \param type: The type to check
/// \return The cast version of the type method_type
java_method_typet require_type::require_java_method(const typet &type)
{
REQUIRE(can_cast_type<java_method_typet>(type));
return to_java_method_type(type);
}
/// Verify a given type is an java_method_typet, and that the code it represents
/// accepts a given number of parameters
/// \param type: The type to check
/// \param num_params: check the the given java_method_typet expects this
/// number of parameters
/// \return The type cast to a java_method_typet
java_method_typet
require_type::require_java_method(const typet &type, const size_t num_params)
{
java_method_typet method_type = require_java_method(type);
REQUIRE(method_type.parameters().size() == num_params);
return method_type;
}
/// Verify that a function has a parameter of a specific name.
/// \param function_type: The type of the function
/// \param param_name: The name of the parameter
/// \return A reference to the parameter structure corresponding to this
/// parameter name.
code_typet::parametert require_type::require_parameter(
const code_typet &function_type,
const irep_idt ¶m_name)
{
const auto param = std::find_if(
function_type.parameters().begin(),
function_type.parameters().end(),
[¶m_name](const code_typet::parametert param) {
return param.get_base_name() == param_name;
});
REQUIRE(param != function_type.parameters().end());
return *param;
}
/// Helper function for testing that java generic type arguments match
/// a given expectation.
/// \param type_argument: The generic type argument to test
/// \param expected: The expected value of the argument
/// \return true if the generic type argument meets the expectations
bool require_java_generic_type_argument_expectation(
const reference_typet &type_argument,
const require_type::expected_type_argumentt &expected)
{
switch(expected.kind)
{
case require_type::type_argument_kindt::Var:
{
REQUIRE(is_java_generic_parameter(type_argument));
java_generic_parametert parameter =
to_java_generic_parameter(type_argument);
REQUIRE(parameter.type_variable().get_identifier() == expected.description);
return true;
}
case require_type::type_argument_kindt::Inst:
{
REQUIRE(!is_java_generic_parameter(type_argument));
REQUIRE(
to_struct_tag_type(to_pointer_type(type_argument).base_type())
.get_identifier() == expected.description);
return true;
}
}
// Should be unreachable...
REQUIRE(false);
return false;
}
/// Verify a given type is a java_generic_type
/// \param type: The type to check
/// \return The type, cast to a java_generic_typet
java_generic_typet require_type::require_java_generic_type(const typet &type)
{
REQUIRE(is_java_generic_type(type));
return to_java_generic_type(type);
}
/// Verify a given type is a java_generic_type, checking
/// that it's associated type arguments match a given set of identifiers.
/// Expected usage is something like this:
///
/// require_java_generic_type(type,
/// {{require_type::type_argument_kindt::Inst, "java::java.lang.Integer"},
/// {require_type::type_argument_kindt::Var, "T"}})
///
/// \param type: The type to check
/// \param type_expectations: A set of type argument kinds and identifiers
/// which should be expected as the type arguments of the given generic type.
/// \return The given type, cast to a java_generic_typet
java_generic_typet require_type::require_java_generic_type(
const typet &type,
const require_type::expected_type_argumentst &type_expectations)
{
const java_generic_typet &generic_type =
require_type::require_java_generic_type(type);
const java_generic_typet::generic_type_argumentst &generic_type_arguments =
generic_type.generic_type_arguments();
REQUIRE(generic_type_arguments.size() == type_expectations.size());
REQUIRE(
std::equal(
generic_type_arguments.begin(),
generic_type_arguments.end(),
type_expectations.begin(),
require_java_generic_type_argument_expectation));
return generic_type;
}
/// Verify a given type is a java_generic_parameter, e.g., `T`
/// \param type: The type to check
/// \return The type, cast to a java_generic_parametert
java_generic_parametert
require_type::require_java_generic_parameter(const typet &type)
{
REQUIRE(is_java_generic_parameter(type));
return to_java_generic_parameter(type);
}
/// Verify a given type is a java_generic_parametert with the given name.
/// Expected usage is something like this:
/// require_java_generic_parameter(parameter, "java::Generic::T")
/// \param type: The type to check
/// \param parameter: String with the parameter name.
/// \return The given type, cast to a java_generic_parametert
java_generic_parametert require_type::require_java_generic_parameter(
const typet &type,
const irep_idt ¶meter)
{
const java_generic_parametert &generic_param =
require_type::require_java_generic_parameter(type);
REQUIRE(
require_java_generic_type_argument_expectation(
generic_param, {require_type::type_argument_kindt::Var, parameter}));
return generic_param;
}
/// Test a type to ensure it is not a java generics type.
/// \param type: The type to test
/// \param expect_subtype: Optionally, also test that the subtype of the given
/// type matches this parameter
/// \return The value passed in the first argument
const typet &require_type::require_java_non_generic_type(
const typet &type,
const std::optional<struct_tag_typet> &expect_subtype)
{
REQUIRE(!is_java_generic_parameter(type));
REQUIRE(!is_java_generic_type(type));
if(expect_subtype)
REQUIRE(to_pointer_type(type).base_type() == expect_subtype.value());
return type;
}
/// Checks that the given type is a complete class.
/// \param class_type: type of the class
/// \return class_type of the class
class_typet require_type::require_complete_class(const typet &class_type)
{
REQUIRE(class_type.id() == ID_struct);
const java_class_typet &java_class_type = to_java_class_type(class_type);
REQUIRE(java_class_type.is_class());
REQUIRE_FALSE(java_class_type.get_is_stub());
return java_class_type;
}
/// Checks that the given type is an incomplete class.
/// \param class_type: type of the class
/// \return class_type of the class
class_typet require_type::require_incomplete_class(const typet &class_type)
{
REQUIRE(class_type.id() == ID_struct);
const java_class_typet &java_class_type = to_java_class_type(class_type);
REQUIRE(java_class_type.is_class());
REQUIRE(java_class_type.get_is_stub());
return java_class_type;
}
/// Verify that a class is a valid java generic class.
/// \param class_type: the class
/// \return A reference to the java generic class type.
java_generic_class_typet
require_type::require_java_generic_class(const typet &class_type)
{
REQUIRE(class_type.id() == ID_struct);
const class_typet &class_class_type = to_class_type(class_type);
const java_class_typet &java_class_type =
to_java_class_type(class_class_type);
REQUIRE(is_java_generic_class_type(java_class_type));
const java_generic_class_typet &java_generic_class_type =
to_java_generic_class_type(java_class_type);
return java_generic_class_type;
}
/// Verify that a class is a valid java generic class with the
/// specified list of variables.
/// \param class_type: the class
/// \param type_variables: vector of type variables
/// \return A reference to the java generic class type.
java_generic_class_typet require_type::require_java_generic_class(
const typet &class_type,
const std::initializer_list<irep_idt> &type_variables)
{
const java_generic_class_typet java_generic_class_type =
require_java_generic_class(class_type);
const java_generic_class_typet::generic_typest &generic_type_vars =
java_generic_class_type.generic_types();
REQUIRE(generic_type_vars.size() == type_variables.size());
REQUIRE(
std::equal(
type_variables.begin(),
type_variables.end(),
generic_type_vars.begin(),
[](
const irep_idt &type_var_name,
const java_generic_parametert ¶m) { //NOLINT
REQUIRE(is_java_generic_parameter(param));
return param.type_variable().get_identifier() == type_var_name;
}));
return java_generic_class_type;
}
/// Verify that a class is a complete, valid java generic class.
/// \param class_type: the class
/// \return A reference to the java generic class type.
java_generic_class_typet
require_type::require_complete_java_generic_class(const typet &class_type)
{
require_complete_class(class_type);
return require_java_generic_class(class_type);
}
/// Verify that a class is a complete, valid java generic class with the
/// specified list of variables.
/// \param class_type: the class
/// \param type_variables: vector of type variables
/// \return A reference to the java generic class type.
java_generic_class_typet require_type::require_complete_java_generic_class(
const typet &class_type,
const std::initializer_list<irep_idt> &type_variables)
{
require_complete_java_generic_class(class_type);
return require_java_generic_class(class_type, type_variables);
}
/// Verify that a class is a valid java implicitly generic class.
/// \param class_type: the class
/// \return A reference to the java generic class type.
java_implicitly_generic_class_typet
require_type::require_java_implicitly_generic_class(const typet &class_type)
{
REQUIRE(class_type.id() == ID_struct);
const class_typet &class_class_type = to_class_type(class_type);
const java_class_typet &java_class_type =
to_java_class_type(class_class_type);
REQUIRE(is_java_implicitly_generic_class_type(java_class_type));
const java_implicitly_generic_class_typet
&java_implicitly_generic_class_type =
to_java_implicitly_generic_class_type(java_class_type);
return java_implicitly_generic_class_type;
}
/// Verify that a class is a valid java generic class with the
/// specified list of variables.
/// \param class_type: the class
/// \param implicit_type_variables: vector of type variables
/// \return A reference to the java generic class type.
java_implicitly_generic_class_typet
require_type::require_java_implicitly_generic_class(
const typet &class_type,
const std::initializer_list<irep_idt> &implicit_type_variables)
{
const java_implicitly_generic_class_typet
&java_implicitly_generic_class_type =
require_java_implicitly_generic_class(class_type);
const java_implicitly_generic_class_typet::implicit_generic_typest
&implicit_generic_type_vars =
java_implicitly_generic_class_type.implicit_generic_types();
REQUIRE(implicit_generic_type_vars.size() == implicit_type_variables.size());
auto param = implicit_generic_type_vars.begin();
auto type_var_name = implicit_type_variables.begin();
for(; param != implicit_generic_type_vars.end(); ++param, ++type_var_name)
{
REQUIRE(is_java_generic_parameter(*param));
REQUIRE(param->type_variable().get_identifier() == *type_var_name);
}
return java_implicitly_generic_class_type;
}
/// Verify that a class is a complete, valid java implicitly generic class.
/// \param class_type: the class
/// \return A reference to the java generic class type.
java_implicitly_generic_class_typet
require_type::require_complete_java_implicitly_generic_class(
const typet &class_type)
{
require_complete_class(class_type);
return require_java_implicitly_generic_class(class_type);
}
/// Verify that a class is a complete, valid java generic class with the
/// specified list of variables.
/// \param class_type: the class
/// \param implicit_type_variables: vector of type variables
/// \return A reference to the java generic class type.
java_implicitly_generic_class_typet
require_type::require_complete_java_implicitly_generic_class(
const typet &class_type,
const std::initializer_list<irep_idt> &implicit_type_variables)
{
require_complete_class(class_type);
return require_java_implicitly_generic_class(
class_type, implicit_type_variables);
}
/// Verify that a class is a valid nongeneric java class
/// \param class_type: the class
/// \return A reference to the java generic class type.
java_class_typet
require_type::require_java_non_generic_class(const typet &class_type)
{
REQUIRE(class_type.id() == ID_struct);
const class_typet &class_class_type = to_class_type(class_type);
const java_class_typet &java_class_type =
to_java_class_type(class_class_type);
REQUIRE(!is_java_generic_class_type(java_class_type));
REQUIRE(!is_java_implicitly_generic_class_type(java_class_type));
return java_class_type;
}
/// Verify that a class is a complete, valid nongeneric java class
/// \param class_type: the class
/// \return A reference to the java generic class type.
java_class_typet
require_type::require_complete_java_non_generic_class(const typet &class_type)
{
require_complete_class(class_type);
return require_java_non_generic_class(class_type);
}
/// Verify a given type is a symbol type, optionally with a specific identifier
/// \param type: The type to check
/// \param identifier: The identifier the symbol type should have
/// \return The cast version of the input type
const struct_tag_typet &
require_type::require_struct_tag(const typet &type, const irep_idt &identifier)
{
REQUIRE(type.id() == ID_struct_tag);
const struct_tag_typet &result = to_struct_tag_type(type);
if(!identifier.empty())
{
REQUIRE(result.get_identifier() == identifier);
}
return result;
}
pointer_typet
require_type::require_pointer_to_tag(const typet &type, const irep_idt &tag)
{
const auto pointer_type = require_type::require_pointer(type, {});
require_type::require_struct_tag(pointer_type.base_type(), tag);
return pointer_type;
}
/// Verify a given type is a java generic symbol type
/// \param type: The type to check
/// \param identifier: The identifier to match
/// \return The type, cast to a java_generic_struct_tag_typet
java_generic_struct_tag_typet
require_type::require_java_generic_struct_tag_type(
const typet &type,
const std::string &identifier)
{
struct_tag_typet struct_tag_type = require_struct_tag(type, identifier);
REQUIRE(is_java_generic_struct_tag_type(type));
return to_java_generic_struct_tag_type(type);
}
/// Verify a given type is a java generic symbol type, checking
/// that it's associated type arguments match a given set of identifiers.
/// Expected usage is something like this:
///
/// require_java_generic_struct_tag_type(type, "java::Generic",
/// {{require_type::type_argument_kindt::Inst, "java::java.lang.Integer"},
/// {require_type::type_argument_kindt::Var, "T"}})
///
/// \param type: The type to check
/// \param identifier: The identifier to match
/// \param type_expectations: A set of type argument kinds and identifiers
/// which should be expected as the type arguments of the given generic type
/// \return The given type, cast to a java_generic_struct_tag_typet
java_generic_struct_tag_typet
require_type::require_java_generic_struct_tag_type(
const typet &type,
const std::string &identifier,
const require_type::expected_type_argumentst &type_expectations)
{
const java_generic_struct_tag_typet &generic_base_type =
require_java_generic_struct_tag_type(type, identifier);
const java_generic_typet::generic_type_argumentst &generic_type_arguments =
generic_base_type.generic_types();
REQUIRE(generic_type_arguments.size() == type_expectations.size());
REQUIRE(
std::equal(
generic_type_arguments.begin(),
generic_type_arguments.end(),
type_expectations.begin(),
require_java_generic_type_argument_expectation));
return generic_base_type;
}
/// Verify that the lambda method handles of a class match the given
/// expectation.
/// \param class_type: class type to be verified
/// \param expected_identifiers: expected list of lambda method handle
/// references
/// \return lambda method handles of the class
require_type::java_lambda_method_handlest
require_type::require_lambda_method_handles(
const java_class_typet &class_type,
const std::vector<std::string> &expected_identifiers)
{
const require_type::java_lambda_method_handlest &lambda_method_handles =
class_type.lambda_method_handles();
REQUIRE(lambda_method_handles.size() == expected_identifiers.size());
REQUIRE(std::equal(
lambda_method_handles.begin(),
lambda_method_handles.end(),
expected_identifiers.begin(),
[](
const java_class_typet::java_lambda_method_handlet &lambda_method_handle,
const std::string &expected_identifier) { //NOLINT
return lambda_method_handle.get_lambda_method_descriptor()
.get_identifier() == expected_identifier;
}));
return lambda_method_handles;
}
|