From db758fb1f6a02170069537894b94392297395209 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 1 Nov 2017 13:33:49 +0000 Subject: [PATCH 1/2] Add some unit test helper functions, useful for Java generics unit tests --- unit/testing-utils/require_type.cpp | 117 ++++++++++++++++++++++++++++ unit/testing-utils/require_type.h | 25 +++++- 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/unit/testing-utils/require_type.cpp b/unit/testing-utils/require_type.cpp index 882f39005c4..098279a9083 100644 --- a/unit/testing-utils/require_type.cpp +++ b/unit/testing-utils/require_type.cpp @@ -59,6 +59,21 @@ code_typet require_type::require_code(const typet &type) 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; +} + /// 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 @@ -78,3 +93,105 @@ code_typet::parametert require_type::require_parameter( REQUIRE(param != function_type.parameters().end()); return *param; } + +/// Verify a given type is a java_generic_type, optionally checking +/// that it's associated type variables match a given set of identifiers +/// \param type The type to check +/// \param type_variables An optional set of type variable identifiers which +/// should be expected as the type parameters of the generic type. +/// \return The given type, cast to a java_generic_typet +const java_generic_typet &require_type::require_java_generic_type_variables( + const typet &type, + const optionalt> &type_variables) +{ + REQUIRE(is_java_generic_type(type)); + const java_generic_typet &generic_type=to_java_generic_type(type); + if(type_variables) + { + const java_generic_typet::generic_type_variablest &generic_type_vars= + generic_type.generic_type_variables(); + REQUIRE(generic_type_vars.size()==type_variables.value().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) + { + REQUIRE(!is_java_generic_inst_parameter((param))); + return param.type_variable().get_identifier()==type_var_name; + })); + } + + return generic_type; +} + +/// Verify a given type is a java_generic_type, optionally checking +/// that it's associated type variables match a given set of identifiers +/// \param type The type to check +/// \param type_variables An optional set of type variable identifiers which +/// should be expected as the type parameters of the generic type. +/// \return The given type, cast to a java_generic_typet +const java_generic_typet +&require_type::require_java_generic_type_instantiations( + const typet &type, + const optionalt> &type_instantiations) +{ + REQUIRE(is_java_generic_type(type)); + const java_generic_typet &generic_type=to_java_generic_type(type); + if(type_instantiations) + { + const java_generic_typet::generic_type_variablest &generic_type_vars= + generic_type.generic_type_variables(); + REQUIRE(generic_type_vars.size()==type_instantiations.value().size()); + REQUIRE( + std::equal( + type_instantiations->begin(), + type_instantiations->end(), + generic_type_vars.begin(), + [](const irep_idt &type_id, const java_generic_parametert ¶m) + { + REQUIRE(is_java_generic_inst_parameter((param))); + return param.subtype()==symbol_typet(type_id); + })); + } + + + return generic_type; +} + +/// Verify a given type is a java_generic_parameter, optionally checking +/// that it's associated type variables match a given set of identifiers +/// \param type The type to check +/// \param type_variables An optional set of type variable identifiers which +/// should be expected as the type parameters of the generic type. +/// \return The given type, cast to a java_generic_typet +const java_generic_parametert +&require_type::require_java_generic_parameter_variables( + const typet &type, + const optionalt &type_variable) +{ + REQUIRE(is_java_generic_parameter(type)); + const java_generic_parametert &generic_param=to_java_generic_parameter(type); + if(type_variable) + { + const java_generic_parametert::type_variablet &generic_type_var= + generic_param.type_variable(); + REQUIRE(!is_java_generic_inst_parameter((generic_param))); + REQUIRE(generic_type_var.get_identifier()==type_variable.value()); + } + + return generic_param; +} + +const typet &require_type::require_java_non_generic_type( + const typet &type, + const optionalt &expect_type) +{ + REQUIRE(!is_java_generic_parameter(type)); + REQUIRE(!is_java_generic_type(type)); + REQUIRE(!is_java_generic_inst_parameter(type)); + if(expect_type) + REQUIRE(type.subtype()==symbol_typet(expect_type.value())); + return type; +} diff --git a/unit/testing-utils/require_type.h b/unit/testing-utils/require_type.h index 488abb5da44..1beb9c5f56d 100644 --- a/unit/testing-utils/require_type.h +++ b/unit/testing-utils/require_type.h @@ -17,6 +17,8 @@ #include #include +#include + // NOLINTNEXTLINE(readability/namespace) namespace require_type @@ -29,8 +31,29 @@ struct_typet::componentt require_component( const irep_idt &component_name); code_typet require_code(const typet &type); + code_typet::parametert require_parameter(const code_typet &function_type, const irep_idt ¶m_name); + +code_typet require_code( + const typet &type, + const size_t num_params); + +const java_generic_typet &require_java_generic_type_variables( + const typet &type, + const optionalt> &type_variables); + +const java_generic_typet &require_java_generic_type_instantiations( + const typet &type, + const optionalt> &type_instantiations); + +const java_generic_parametert &require_java_generic_parameter_variables( + const typet &type, + const optionalt &type_variables); + +const typet &require_java_non_generic_type( + const typet &type, + const optionalt &expect_type); } -#endif +#endif // CPROVER_TESTING_UTILS_REQUIRE_TYPE_H From 0507355bd70438ff3d3656d81b1e8516e8af24d1 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 1 Nov 2017 16:39:19 +0000 Subject: [PATCH 2/2] Refactored unit test helpers to be more general and extend their use-cases --- unit/testing-utils/require_type.cpp | 124 +++++++++++++++------------- unit/testing-utils/require_type.h | 24 ++++-- 2 files changed, 81 insertions(+), 67 deletions(-) diff --git a/unit/testing-utils/require_type.cpp b/unit/testing-utils/require_type.cpp index 098279a9083..9d8233a52d8 100644 --- a/unit/testing-utils/require_type.cpp +++ b/unit/testing-utils/require_type.cpp @@ -78,7 +78,7 @@ code_typet require_type::require_code( /// \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. +/// parameter name. code_typet::parametert require_type::require_parameter( const code_typet &function_type, const irep_idt ¶m_name) @@ -94,104 +94,110 @@ code_typet::parametert require_type::require_parameter( return *param; } -/// Verify a given type is a java_generic_type, optionally checking -/// that it's associated type variables match a given set of identifiers -/// \param type The type to check -/// \param type_variables An optional set of type variable identifiers which -/// should be expected as the type parameters of the generic type. -/// \return The given type, cast to a java_generic_typet -const java_generic_typet &require_type::require_java_generic_type_variables( - const typet &type, - const optionalt> &type_variables) +/// Helper function for testing that java_generic_parametert types match +/// a given expectation. +/// \param param The generic parameter to test +/// \param expected The expected value of the parameter +/// \return true if the generic parameter type meets the expectations +bool require_java_generic_parametert_expectation( + const java_generic_parametert ¶m, + const require_type::expected_type_parametert &expected) { - REQUIRE(is_java_generic_type(type)); - const java_generic_typet &generic_type=to_java_generic_type(type); - if(type_variables) + switch(expected.kind) { - const java_generic_typet::generic_type_variablest &generic_type_vars= - generic_type.generic_type_variables(); - REQUIRE(generic_type_vars.size()==type_variables.value().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) - { - REQUIRE(!is_java_generic_inst_parameter((param))); - return param.type_variable().get_identifier()==type_var_name; - })); + case require_type::type_parameter_kindt::Var: + REQUIRE(!is_java_generic_inst_parameter((param))); + REQUIRE(param.type_variable().get_identifier()==expected.description); + return true; + case require_type::type_parameter_kindt::Inst: + REQUIRE(is_java_generic_inst_parameter((param))); + REQUIRE(param.subtype()==symbol_typet(expected.description)); + return true; } - - return generic_type; + // Should be unreachable... + REQUIRE(false); + return false; } + /// Verify a given type is a java_generic_type, optionally checking -/// that it's associated type variables match a given set of identifiers +/// that it's associated type variables match a given set of identifiers. +/// Expected usage is something like this: +/// +/// require_java_generic_type(type, +/// {{Inst,"java::java.lang.Integer"},{Var,"T"}}) +/// /// \param type The type to check -/// \param type_variables An optional set of type variable identifiers which -/// should be expected as the type parameters of the generic type. +/// \param type_expectations An optional set of type variable kinds +/// and identifiers which should be expected as the type parameters of the +/// given generic type. /// \return The given type, cast to a java_generic_typet -const java_generic_typet -&require_type::require_java_generic_type_instantiations( +java_generic_typet require_type::require_java_generic_type( const typet &type, - const optionalt> &type_instantiations) + const optionalt &type_expectations) { REQUIRE(is_java_generic_type(type)); const java_generic_typet &generic_type=to_java_generic_type(type); - if(type_instantiations) + if(type_expectations) { const java_generic_typet::generic_type_variablest &generic_type_vars= generic_type.generic_type_variables(); - REQUIRE(generic_type_vars.size()==type_instantiations.value().size()); + REQUIRE(generic_type_vars.size()==type_expectations->size()); REQUIRE( std::equal( - type_instantiations->begin(), - type_instantiations->end(), generic_type_vars.begin(), - [](const irep_idt &type_id, const java_generic_parametert ¶m) - { - REQUIRE(is_java_generic_inst_parameter((param))); - return param.subtype()==symbol_typet(type_id); - })); + generic_type_vars.end(), + type_expectations->begin(), + require_java_generic_parametert_expectation)); } - return generic_type; } /// Verify a given type is a java_generic_parameter, optionally checking -/// that it's associated type variables match a given set of identifiers +/// that it's associated type variables match a given set of expectations. +/// Expected usage is something like this: +/// +/// require_java_generic_parameter(parameter, {Inst,"java::java.lang.Integer"}) +/// +/// or +/// +/// require_java_generic_parameter(parameter, {Var,"T"}) +/// /// \param type The type to check -/// \param type_variables An optional set of type variable identifiers which -/// should be expected as the type parameters of the generic type. -/// \return The given type, cast to a java_generic_typet -const java_generic_parametert -&require_type::require_java_generic_parameter_variables( +/// \param type_expectation An optional description of the identifiers/kinds +/// which / should be expected as the type parameter of the generic parameter. +/// \return The given type, cast to a java_generic_parametert +java_generic_parametert require_type::require_java_generic_parameter( const typet &type, - const optionalt &type_variable) + const optionalt &type_expectation) { REQUIRE(is_java_generic_parameter(type)); const java_generic_parametert &generic_param=to_java_generic_parameter(type); - if(type_variable) + if(type_expectation) { - const java_generic_parametert::type_variablet &generic_type_var= - generic_param.type_variable(); - REQUIRE(!is_java_generic_inst_parameter((generic_param))); - REQUIRE(generic_type_var.get_identifier()==type_variable.value()); + REQUIRE( + require_java_generic_parametert_expectation( + generic_param, + type_expectation.value())); } 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 optionalt &expect_type) + const optionalt &expect_subtype) { REQUIRE(!is_java_generic_parameter(type)); REQUIRE(!is_java_generic_type(type)); REQUIRE(!is_java_generic_inst_parameter(type)); - if(expect_type) - REQUIRE(type.subtype()==symbol_typet(expect_type.value())); + if(expect_subtype) + REQUIRE(type.subtype()==expect_subtype.value()); return type; } diff --git a/unit/testing-utils/require_type.h b/unit/testing-utils/require_type.h index 1beb9c5f56d..215f5335cf0 100644 --- a/unit/testing-utils/require_type.h +++ b/unit/testing-utils/require_type.h @@ -39,21 +39,29 @@ code_typet require_code( const typet &type, const size_t num_params); -const java_generic_typet &require_java_generic_type_variables( - const typet &type, - const optionalt> &type_variables); +// A mini DSL for describing an expected set of type parameters for a +// java_generic_typet +enum class type_parameter_kindt { Inst, Var }; +struct expected_type_parametert +{ + type_parameter_kindt kind; + irep_idt description; +}; +typedef std::initializer_list + expected_type_parameterst; -const java_generic_typet &require_java_generic_type_instantiations( +java_generic_typet require_java_generic_type( const typet &type, - const optionalt> &type_instantiations); + const optionalt &type_expectations); + -const java_generic_parametert &require_java_generic_parameter_variables( +java_generic_parametert require_java_generic_parameter( const typet &type, - const optionalt &type_variables); + const optionalt &type_expectation); const typet &require_java_non_generic_type( const typet &type, - const optionalt &expect_type); + const optionalt &expect_subtype); } #endif // CPROVER_TESTING_UTILS_REQUIRE_TYPE_H