ibm_db 5.6.1 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/Makefile +13 -9
- data/ext/extconf.rb +176 -110
- data/ext/ibm_db.c +60 -0
- data/ext/ibm_db.o +0 -0
- data/ext/ibm_db.so +0 -0
- data/ext/mkmf.log +6 -6
- data/ext/ruby_ibm_db_cli.c +14 -10
- data/ext/ruby_ibm_db_cli.h +4 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/lib/IBM_DB.rb +2 -2
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
- data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
- data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
- data/test/activejob/destroy_association_async_job_test.rb +62 -0
- data/test/activejob/destroy_association_async_test.rb +147 -11
- data/test/activejob/job_runtime_test.rb +41 -0
- data/test/activejob/unloadable_base_job.rb +3 -0
- data/test/cases/active_record_schema_test.rb +196 -0
- data/test/cases/active_record_test.rb +21 -0
- data/test/cases/adapter_prevent_writes_test.rb +26 -202
- data/test/cases/adapter_test.rb +592 -82
- data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
- data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
- data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
- data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
- data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
- data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
- data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
- data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
- data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
- data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
- data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
- data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
- data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
- data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
- data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
- data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
- data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
- data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
- data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
- data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
- data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
- data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
- data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
- data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
- data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
- data/test/cases/adapters/postgresql/array_test.rb +6 -6
- data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
- data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
- data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
- data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
- data/test/cases/adapters/postgresql/citext_test.rb +7 -1
- data/test/cases/adapters/postgresql/collation_test.rb +1 -1
- data/test/cases/adapters/postgresql/composite_test.rb +1 -1
- data/test/cases/adapters/postgresql/connection_test.rb +43 -36
- data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
- data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
- data/test/cases/adapters/postgresql/date_test.rb +2 -2
- data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
- data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
- data/test/cases/adapters/postgresql/domain_test.rb +1 -1
- data/test/cases/adapters/postgresql/enum_test.rb +208 -8
- data/test/cases/adapters/postgresql/explain_test.rb +25 -6
- data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
- data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
- data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
- data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
- data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
- data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
- data/test/cases/adapters/postgresql/integer_test.rb +1 -1
- data/test/cases/adapters/postgresql/interval_test.rb +9 -17
- data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
- data/test/cases/adapters/postgresql/json_test.rb +5 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
- data/test/cases/adapters/postgresql/money_test.rb +17 -9
- data/test/cases/adapters/postgresql/network_test.rb +13 -1
- data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
- data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
- data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
- data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
- data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
- data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
- data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
- data/test/cases/adapters/postgresql/range_test.rb +185 -21
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
- data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
- data/test/cases/adapters/postgresql/schema_test.rb +270 -20
- data/test/cases/adapters/postgresql/serial_test.rb +5 -5
- data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
- data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
- data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
- data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
- data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
- data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
- data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
- data/test/cases/adapters/postgresql/xml_test.rb +1 -1
- data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
- data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
- data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
- data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
- data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
- data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
- data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
- data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
- data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
- data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
- data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
- data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
- data/test/cases/aggregations_test.rb +16 -0
- data/test/cases/annotate_test.rb +14 -12
- data/test/cases/arel/attributes/attribute_test.rb +86 -47
- data/test/cases/arel/collectors/bind_test.rb +1 -1
- data/test/cases/arel/collectors/composite_test.rb +11 -1
- data/test/cases/arel/collectors/sql_string_test.rb +1 -1
- data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
- data/test/cases/arel/delete_manager_test.rb +0 -6
- data/test/cases/arel/factory_methods_test.rb +45 -0
- data/test/cases/arel/insert_manager_test.rb +1 -7
- data/test/cases/arel/nodes/as_test.rb +12 -0
- data/test/cases/arel/nodes/ascending_test.rb +1 -1
- data/test/cases/arel/nodes/bin_test.rb +1 -1
- data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
- data/test/cases/arel/nodes/cte_test.rb +46 -0
- data/test/cases/arel/nodes/descending_test.rb +1 -1
- data/test/cases/arel/nodes/equality_test.rb +3 -3
- data/test/cases/arel/nodes/filter_test.rb +37 -0
- data/test/cases/arel/nodes/fragments_test.rb +38 -0
- data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
- data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
- data/test/cases/arel/nodes/node_test.rb +1 -1
- data/test/cases/arel/nodes/or_test.rb +2 -2
- data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
- data/test/cases/arel/nodes/table_alias_test.rb +12 -0
- data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
- data/test/cases/arel/nodes/update_statement_test.rb +4 -0
- data/test/cases/arel/nodes_test.rb +3 -2
- data/test/cases/arel/select_manager_test.rb +12 -12
- data/test/cases/arel/support/fake_record.rb +22 -17
- data/test/cases/arel/table_test.rb +15 -25
- data/test/cases/arel/update_manager_test.rb +51 -6
- data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
- data/test/cases/arel/visitors/dot_test.rb +177 -2
- data/test/cases/arel/visitors/mysql_test.rb +49 -1
- data/test/cases/arel/visitors/postgres_test.rb +1 -31
- data/test/cases/arel/visitors/sqlite_test.rb +1 -1
- data/test/cases/arel/visitors/to_sql_test.rb +330 -20
- data/test/cases/assertions/query_assertions_test.rb +136 -0
- data/test/cases/associations/belongs_to_associations_test.rb +502 -41
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
- data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
- data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
- data/test/cases/associations/eager_singularization_test.rb +1 -1
- data/test/cases/associations/eager_test.rb +255 -93
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
- data/test/cases/associations/has_many_associations_test.rb +282 -72
- data/test/cases/associations/has_many_through_associations_test.rb +172 -45
- data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
- data/test/cases/associations/has_one_associations_test.rb +160 -29
- data/test/cases/associations/has_one_through_associations_test.rb +64 -15
- data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
- data/test/cases/associations/inner_join_association_test.rb +36 -6
- data/test/cases/associations/inverse_associations_test.rb +177 -40
- data/test/cases/associations/join_model_test.rb +17 -12
- data/test/cases/associations/left_outer_join_association_test.rb +14 -3
- data/test/cases/associations/nested_error_test.rb +116 -0
- data/test/cases/associations/nested_through_associations_test.rb +54 -19
- data/test/cases/associations/required_test.rb +1 -1
- data/test/cases/associations_test.rb +1278 -21
- data/test/cases/asynchronous_queries_test.rb +310 -0
- data/test/cases/attribute_methods/read_test.rb +6 -0
- data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
- data/test/cases/attribute_methods_test.rb +565 -46
- data/test/cases/attributes_test.rb +42 -1
- data/test/cases/autosave_association_test.rb +645 -92
- data/test/cases/base_prevent_writes_test.rb +28 -159
- data/test/cases/base_test.rb +434 -209
- data/test/cases/batches_test.rb +441 -57
- data/test/cases/binary_test.rb +31 -0
- data/test/cases/bind_parameter_test.rb +107 -16
- data/test/cases/cache_key_test.rb +7 -7
- data/test/cases/calculations_test.rb +541 -110
- data/test/cases/callbacks_test.rb +0 -1
- data/test/cases/clone_test.rb +5 -4
- data/test/cases/coders/yaml_column_test.rb +97 -2
- data/test/cases/collection_cache_key_test.rb +24 -16
- data/test/cases/column_alias_test.rb +2 -8
- data/test/cases/column_definition_test.rb +12 -3
- data/test/cases/comment_test.rb +23 -26
- data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
- data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
- data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
- data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
- data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
- data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
- data/test/cases/connection_adapters/registration_test.rb +98 -0
- data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
- data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
- data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
- data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
- data/test/cases/connection_handling_test.rb +210 -0
- data/test/cases/connection_management_test.rb +44 -7
- data/test/cases/connection_pool_test.rb +466 -99
- data/test/cases/core_test.rb +167 -9
- data/test/cases/counter_cache_test.rb +129 -2
- data/test/cases/custom_locking_test.rb +3 -3
- data/test/cases/database_configurations/hash_config_test.rb +149 -13
- data/test/cases/database_configurations/resolver_test.rb +14 -10
- data/test/cases/database_configurations/url_config_test.rb +53 -0
- data/test/cases/database_configurations_test.rb +86 -43
- data/test/cases/database_selector_test.rb +30 -8
- data/test/cases/database_statements_test.rb +10 -14
- data/test/cases/date_time_precision_test.rb +141 -11
- data/test/cases/date_time_test.rb +19 -1
- data/test/cases/defaults_test.rb +107 -41
- data/test/cases/delegated_type_test.rb +69 -9
- data/test/cases/dirty_test.rb +82 -25
- data/test/cases/disconnected_test.rb +10 -9
- data/test/cases/dup_test.rb +26 -6
- data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
- data/test/cases/encryption/cipher_test.rb +65 -0
- data/test/cases/encryption/concurrency_test.rb +27 -0
- data/test/cases/encryption/config_test.rb +21 -0
- data/test/cases/encryption/configurable_test.rb +93 -0
- data/test/cases/encryption/contexts_test.rb +105 -0
- data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
- data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
- data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
- data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
- data/test/cases/encryption/encryptable_record_test.rb +470 -0
- data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
- data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
- data/test/cases/encryption/encryption_schemes_test.rb +240 -0
- data/test/cases/encryption/encryptor_test.rb +113 -0
- data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
- data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
- data/test/cases/encryption/helper.rb +152 -0
- data/test/cases/encryption/key_generator_test.rb +55 -0
- data/test/cases/encryption/key_provider_test.rb +57 -0
- data/test/cases/encryption/key_test.rb +17 -0
- data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
- data/test/cases/encryption/message_serializer_test.rb +82 -0
- data/test/cases/encryption/message_test.rb +43 -0
- data/test/cases/encryption/null_encryptor_test.rb +21 -0
- data/test/cases/encryption/properties_test.rb +69 -0
- data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
- data/test/cases/encryption/scheme_test.rb +58 -0
- data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
- data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
- data/test/cases/enum_test.rb +374 -72
- data/test/cases/errors_test.rb +7 -4
- data/test/cases/excluding_test.rb +116 -0
- data/test/cases/explain_subscriber_test.rb +6 -1
- data/test/cases/explain_test.rb +119 -10
- data/test/cases/filter_attributes_test.rb +7 -14
- data/test/cases/finder_respond_to_test.rb +3 -3
- data/test/cases/finder_test.rb +357 -72
- data/test/cases/fixture_set/file_test.rb +9 -0
- data/test/cases/fixtures_test.rb +426 -190
- data/test/cases/helper.rb +66 -192
- data/test/cases/hot_compatibility_test.rb +10 -10
- data/test/cases/inheritance_test.rb +51 -61
- data/test/cases/inherited_test.rb +40 -0
- data/test/cases/insert_all_test.rb +419 -9
- data/test/cases/instrumentation_test.rb +202 -30
- data/test/cases/integration_test.rb +25 -7
- data/test/cases/invalid_connection_test.rb +5 -5
- data/test/cases/invertible_migration_test.rb +108 -24
- data/test/cases/json_attribute_test.rb +1 -0
- data/test/cases/json_serialization_test.rb +5 -5
- data/test/cases/json_shared_test_cases.rb +5 -9
- data/test/cases/locking_test.rb +67 -31
- data/test/cases/log_subscriber_test.rb +17 -15
- data/test/cases/marshal_serialization_test.rb +78 -5
- data/test/cases/message_pack_test.rb +91 -0
- data/test/cases/migration/change_schema_test.rb +77 -46
- data/test/cases/migration/change_table_test.rb +129 -114
- data/test/cases/migration/check_constraint_test.rb +192 -10
- data/test/cases/migration/column_attributes_test.rb +4 -9
- data/test/cases/migration/column_positioning_test.rb +2 -2
- data/test/cases/migration/columns_test.rb +118 -4
- data/test/cases/migration/command_recorder_test.rb +181 -14
- data/test/cases/migration/compatibility_test.rb +883 -196
- data/test/cases/migration/create_join_table_test.rb +8 -1
- data/test/cases/migration/exclusion_constraint_test.rb +192 -0
- data/test/cases/migration/foreign_key_test.rb +356 -14
- data/test/cases/migration/helper.rb +4 -1
- data/test/cases/migration/index_test.rb +67 -2
- data/test/cases/migration/invalid_options_test.rb +129 -0
- data/test/cases/migration/logger_test.rb +7 -4
- data/test/cases/migration/pending_migrations_test.rb +103 -60
- data/test/cases/migration/references_foreign_key_test.rb +73 -4
- data/test/cases/migration/references_index_test.rb +25 -27
- data/test/cases/migration/references_statements_test.rb +27 -3
- data/test/cases/migration/rename_table_test.rb +39 -54
- data/test/cases/migration/schema_definitions_test.rb +109 -0
- data/test/cases/migration/unique_constraint_test.rb +248 -0
- data/test/cases/migration_test.rb +677 -220
- data/test/cases/migrator_test.rb +102 -75
- data/test/cases/multi_db_migrator_test.rb +55 -34
- data/test/cases/multiparameter_attributes_test.rb +26 -29
- data/test/cases/multiple_db_test.rb +42 -19
- data/test/cases/nested_attributes_test.rb +124 -6
- data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
- data/test/cases/normalized_attribute_test.rb +117 -0
- data/test/cases/null_relation_test.rb +35 -2
- data/test/cases/persistence/reload_association_cache_test.rb +20 -0
- data/test/cases/persistence_test.rb +629 -22
- data/test/cases/pooled_connections_test.rb +57 -56
- data/test/cases/prepared_statement_status_test.rb +8 -3
- data/test/cases/primary_class_test.rb +134 -0
- data/test/cases/primary_keys_test.rb +171 -55
- data/test/cases/query_cache_test.rb +558 -263
- data/test/cases/query_logs_test.rb +293 -0
- data/test/cases/quoting_test.rb +39 -72
- data/test/cases/readonly_test.rb +50 -12
- data/test/cases/reaper_test.rb +22 -6
- data/test/cases/reflection_test.rb +207 -9
- data/test/cases/relation/and_test.rb +43 -0
- data/test/cases/relation/delegation_test.rb +32 -5
- data/test/cases/relation/delete_all_test.rb +27 -6
- data/test/cases/relation/field_ordered_values_test.rb +128 -0
- data/test/cases/relation/load_async_test.rb +650 -0
- data/test/cases/relation/merging_test.rb +80 -109
- data/test/cases/relation/mutation_test.rb +12 -7
- data/test/cases/relation/or_test.rb +11 -8
- data/test/cases/relation/order_test.rb +90 -0
- data/test/cases/relation/predicate_builder_test.rb +21 -6
- data/test/cases/relation/select_test.rb +162 -3
- data/test/cases/relation/structural_compatibility_test.rb +38 -0
- data/test/cases/relation/update_all_test.rb +81 -27
- data/test/cases/relation/where_chain_test.rb +190 -3
- data/test/cases/relation/where_clause_test.rb +43 -1
- data/test/cases/relation/where_test.rb +95 -7
- data/test/cases/relation/with_test.rb +165 -0
- data/test/cases/relation_test.rb +42 -37
- data/test/cases/relations_test.rb +436 -138
- data/test/cases/reload_models_test.rb +18 -14
- data/test/cases/reserved_word_test.rb +2 -1
- data/test/cases/result_test.rb +14 -22
- data/test/cases/sanitize_test.rb +89 -27
- data/test/cases/schema_dumper_test.rb +535 -62
- data/test/cases/scoping/default_scoping_test.rb +219 -35
- data/test/cases/scoping/named_scoping_test.rb +25 -46
- data/test/cases/scoping/relation_scoping_test.rb +112 -4
- data/test/cases/secure_password_test.rb +108 -0
- data/test/cases/secure_token_test.rb +72 -0
- data/test/cases/serialization_test.rb +1 -1
- data/test/cases/serialized_attribute_test.rb +305 -60
- data/test/cases/shard_keys_test.rb +125 -0
- data/test/cases/shard_selector_test.rb +45 -0
- data/test/cases/signed_id_test.rb +57 -5
- data/test/cases/statement_cache_test.rb +31 -30
- data/test/cases/statement_invalid_test.rb +8 -4
- data/test/cases/store_test.rb +73 -9
- data/test/cases/strict_loading_test.rb +327 -13
- data/test/cases/table_metadata_test.rb +16 -0
- data/test/cases/tasks/database_tasks_test.rb +517 -244
- data/test/cases/test_case.rb +254 -60
- data/test/cases/test_case_test.rb +69 -0
- data/test/cases/test_databases_test.rb +7 -3
- data/test/cases/test_fixtures_test.rb +19 -40
- data/test/cases/time_precision_test.rb +17 -5
- data/test/cases/timestamp_test.rb +124 -16
- data/test/cases/token_for_test.rb +165 -0
- data/test/cases/touch_later_test.rb +43 -1
- data/test/cases/transaction_callbacks_test.rb +325 -8
- data/test/cases/transaction_instrumentation_test.rb +453 -0
- data/test/cases/transaction_isolation_test.rb +12 -8
- data/test/cases/transactions_test.rb +629 -112
- data/test/cases/type/date_time_test.rb +7 -1
- data/test/cases/type/time_test.rb +9 -0
- data/test/cases/type/type_map_test.rb +108 -73
- data/test/cases/type/unsigned_integer_test.rb +12 -0
- data/test/cases/type_caster/connection_test.rb +19 -0
- data/test/cases/type_test.rb +1 -1
- data/test/cases/unconnected_test.rb +7 -7
- data/test/cases/unsafe_raw_sql_test.rb +39 -8
- data/test/cases/validations/absence_validation_test.rb +1 -1
- data/test/cases/validations/association_validation_test.rb +25 -3
- data/test/cases/validations/numericality_validation_test.rb +3 -9
- data/test/cases/validations/presence_validation_test.rb +1 -1
- data/test/cases/validations/uniqueness_validation_test.rb +280 -40
- data/test/cases/validations_test.rb +2 -2
- data/test/cases/view_test.rb +33 -22
- data/test/cases/yaml_serialization_test.rb +23 -17
- data/test/config.example.yml +58 -56
- data/test/config.rb +1 -0
- data/test/fixtures/1_need_quoting.yml +2 -0
- data/test/fixtures/accounts.yml +5 -0
- data/test/fixtures/aircrafts.yml +7 -0
- data/test/fixtures/book_identifiers.yml +11 -0
- data/test/fixtures/books.yml +5 -4
- data/test/fixtures/cake_designers.yml +5 -0
- data/test/fixtures/cars.yml +6 -0
- data/test/fixtures/chefs.yml +5 -0
- data/test/fixtures/clothing_items.yml +23 -0
- data/test/fixtures/clubs.yml +1 -1
- data/test/fixtures/comments.yml +2 -1
- data/test/fixtures/cpk_authors.yml +8 -0
- data/test/fixtures/cpk_books.yml +21 -0
- data/test/fixtures/cpk_order_agreements.yml +13 -0
- data/test/fixtures/cpk_order_tags.yml +15 -0
- data/test/fixtures/cpk_orders.yml +11 -0
- data/test/fixtures/cpk_posts.yml +12 -0
- data/test/fixtures/cpk_reviews.yml +13 -0
- data/test/fixtures/cpk_tags.yml +11 -0
- data/test/fixtures/drink_designers.yml +5 -0
- data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
- data/test/fixtures/encrypted_books.yml +4 -0
- data/test/fixtures/fk_object_to_point_to.yml +2 -0
- data/test/fixtures/memberships.yml +15 -15
- data/test/fixtures/paragraphs.yml +5 -0
- data/test/fixtures/parrots.yml +4 -0
- data/test/fixtures/people.yml +2 -0
- data/test/fixtures/pirates.yml +2 -2
- data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
- data/test/fixtures/references.yml +3 -3
- data/test/fixtures/sharded_blog_posts.yml +14 -0
- data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
- data/test/fixtures/sharded_blogs.yml +8 -0
- data/test/fixtures/sharded_comments.yml +22 -0
- data/test/fixtures/sharded_tags.yml +34 -0
- data/test/fixtures/sponsors.yml +2 -2
- data/test/fixtures/topics.yml +1 -0
- data/test/fixtures/treasures.yml +4 -0
- data/test/fixtures/virtual_columns.yml +5 -0
- data/test/fixtures/warehouse_things.yml +1 -1
- data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
- data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
- data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
- data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
- data/test/migrations/scope/1_unscoped.rb +7 -0
- data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
- data/test/models/admin/user.rb +2 -0
- data/test/models/admin/user_json.rb +48 -0
- data/test/models/attachment.rb +7 -0
- data/test/models/author.rb +70 -3
- data/test/models/author_encrypted.rb +16 -0
- data/test/models/bird.rb +1 -1
- data/test/models/book.rb +18 -11
- data/test/models/book_destroy_async.rb +1 -1
- data/test/models/book_encrypted.rb +106 -0
- data/test/models/book_identifier.rb +5 -0
- data/test/models/branch.rb +11 -0
- data/test/models/bulb.rb +1 -1
- data/test/models/car.rb +8 -1
- data/test/models/cat.rb +1 -1
- data/test/models/category.rb +3 -1
- data/test/models/chat_message.rb +8 -0
- data/test/models/chef.rb +52 -0
- data/test/models/clothing_item.rb +12 -0
- data/test/models/club.rb +4 -1
- data/test/models/comment.rb +7 -4
- data/test/models/comment_overlapping_counter_cache.rb +15 -0
- data/test/models/company.rb +16 -2
- data/test/models/computer.rb +1 -0
- data/test/models/contact.rb +3 -3
- data/test/models/contract.rb +5 -1
- data/test/models/cpk/author.rb +9 -0
- data/test/models/cpk/book.rb +55 -0
- data/test/models/cpk/book_destroy_async.rb +9 -0
- data/test/models/cpk/car.rb +9 -0
- data/test/models/cpk/car_review.rb +9 -0
- data/test/models/cpk/chapter.rb +16 -0
- data/test/models/cpk/chapter_destroy_async.rb +10 -0
- data/test/models/cpk/comment.rb +9 -0
- data/test/models/cpk/order.rb +55 -0
- data/test/models/cpk/order_agreement.rb +10 -0
- data/test/models/cpk/order_tag.rb +10 -0
- data/test/models/cpk/post.rb +10 -0
- data/test/models/cpk/posts_tag.rb +10 -0
- data/test/models/cpk/review.rb +9 -0
- data/test/models/cpk/tag.rb +10 -0
- data/test/models/cpk.rb +15 -0
- data/test/models/customer.rb +3 -1
- data/test/models/destroy_async_parent.rb +1 -1
- data/test/models/developer.rb +44 -3
- data/test/models/discount.rb +4 -0
- data/test/models/drink_designer.rb +1 -0
- data/test/models/editor.rb +8 -0
- data/test/models/editorship.rb +6 -0
- data/test/models/entry.rb +5 -0
- data/test/models/essay.rb +6 -1
- data/test/models/essay_destroy_async.rb +1 -0
- data/test/models/eye.rb +87 -21
- data/test/models/face.rb +1 -1
- data/test/models/friendship.rb +3 -0
- data/test/models/hardback.rb +7 -0
- data/test/models/hotel.rb +2 -0
- data/test/models/human.rb +2 -2
- data/test/models/invoice.rb +2 -1
- data/test/models/invokes_an_undefined_method.rb +5 -0
- data/test/models/line_item.rb +6 -0
- data/test/models/member.rb +9 -4
- data/test/models/membership.rb +2 -2
- data/test/models/message.rb +2 -1
- data/test/models/need_quoting.rb +5 -0
- data/test/models/paragraph.rb +5 -0
- data/test/models/parrot.rb +6 -3
- data/test/models/person.rb +7 -4
- data/test/models/pirate.rb +4 -1
- data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
- data/test/models/post.rb +65 -2
- data/test/models/post_encrypted.rb +15 -0
- data/test/models/post_with_prefetched_pk.rb +15 -0
- data/test/models/project.rb +1 -0
- data/test/models/publication.rb +16 -0
- data/test/models/raises_argument_error.rb +5 -0
- data/test/models/raises_no_method_error.rb +5 -0
- data/test/models/recipient.rb +5 -0
- data/test/models/reference.rb +1 -1
- data/test/models/reply.rb +1 -1
- data/test/models/room.rb +3 -0
- data/test/models/sharded/blog.rb +12 -0
- data/test/models/sharded/blog_post.rb +17 -0
- data/test/models/sharded/blog_post_destroy_async.rb +14 -0
- data/test/models/sharded/blog_post_tag.rb +11 -0
- data/test/models/sharded/blog_post_with_revision.rb +11 -0
- data/test/models/sharded/comment.rb +12 -0
- data/test/models/sharded/comment_destroy_async.rb +12 -0
- data/test/models/sharded/tag.rb +11 -0
- data/test/models/sharded.rb +8 -0
- data/test/models/ship.rb +1 -1
- data/test/models/shipping_line.rb +11 -0
- data/test/models/subscriber.rb +1 -0
- data/test/models/subscription.rb +3 -1
- data/test/models/too_long_table_name.rb +5 -0
- data/test/models/topic.rb +3 -1
- data/test/models/traffic_light.rb +2 -2
- data/test/models/traffic_light_encrypted.rb +21 -0
- data/test/models/translation.rb +9 -0
- data/test/models/treasure.rb +1 -1
- data/test/models/tyre.rb +1 -1
- data/test/models/user.rb +16 -0
- data/test/models/user_with_invalid_relation.rb +28 -0
- data/test/models/uuid_comment.rb +5 -0
- data/test/models/uuid_entry.rb +5 -0
- data/test/models/uuid_message.rb +5 -0
- data/test/models/zine.rb +2 -1
- data/test/schema/mysql2_specific_schema.rb +26 -12
- data/test/schema/postgresql_specific_schema.rb +121 -13
- data/test/schema/schema.rb +361 -103
- data/test/schema/sqlite_specific_schema.rb +17 -6
- data/test/schema/trilogy_specific_schema.rb +96 -0
- data/test/support/adapter_helper.rb +104 -0
- data/test/support/async_helper.rb +15 -0
- data/test/support/config.rb +1 -1
- data/test/support/connection.rb +14 -2
- data/test/support/ddl_helper.rb +1 -1
- data/test/support/fake_adapter.rb +42 -0
- data/test/support/load_schema_helper.rb +22 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
- data/test/support/schema_dumping_helper.rb +15 -9
- data/test/support/tools.rb +37 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
- metadata +247 -15
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/encryption/helper"
|
|
4
|
+
require "models/author_encrypted"
|
|
5
|
+
require "models/book_encrypted"
|
|
6
|
+
require "active_record/encryption/message_pack_message_serializer"
|
|
7
|
+
|
|
8
|
+
class ActiveRecord::Encryption::EncryptableRecordMessagePackSerializedTest < ActiveRecord::EncryptionTestCase
|
|
9
|
+
fixtures :encrypted_books
|
|
10
|
+
|
|
11
|
+
test "binary data can be serialized with message pack" do
|
|
12
|
+
all_bytes = (0..255).map(&:chr).join
|
|
13
|
+
book = EncryptedBookWithBinaryMessagePackSerialized.create!(logo: all_bytes)
|
|
14
|
+
assert_encrypted_attribute(book, :logo, all_bytes)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test "binary data can be encrypted uncompressed and serialized with message pack" do
|
|
18
|
+
# Strings below 140 bytes are not compressed
|
|
19
|
+
low_bytes = (0..127).map(&:chr).join
|
|
20
|
+
high_bytes = (128..255).map(&:chr).join
|
|
21
|
+
|
|
22
|
+
assert_encrypted_attribute(EncryptedBookWithBinaryMessagePackSerialized.create!(logo: low_bytes), :logo, low_bytes)
|
|
23
|
+
assert_encrypted_attribute(EncryptedBookWithBinaryMessagePackSerialized.create!(logo: high_bytes), :logo, high_bytes)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
test "text columns cannot be serialized with message pack" do
|
|
27
|
+
assert_raises(ActiveRecord::Encryption::Errors::Encoding) do
|
|
28
|
+
message_pack_serialized_text_class = Class.new(ActiveRecord::Base) do
|
|
29
|
+
self.table_name = "encrypted_books"
|
|
30
|
+
|
|
31
|
+
encrypts :name, message_serializer: ActiveRecord::Encryption::MessagePackMessageSerializer.new
|
|
32
|
+
end
|
|
33
|
+
message_pack_serialized_text_class.create(name: "Dune")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class EncryptedBookWithBinaryMessagePackSerialized < ActiveRecord::Base
|
|
38
|
+
self.table_name = "encrypted_books"
|
|
39
|
+
|
|
40
|
+
encrypts :logo, message_serializer: ActiveRecord::Encryption::MessagePackMessageSerializer.new
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/encryption/helper"
|
|
4
|
+
require "models/author_encrypted"
|
|
5
|
+
require "models/book_encrypted"
|
|
6
|
+
require "models/post_encrypted"
|
|
7
|
+
require "models/traffic_light_encrypted"
|
|
8
|
+
|
|
9
|
+
class ActiveRecord::Encryption::EncryptableRecordTest < ActiveRecord::EncryptionTestCase
|
|
10
|
+
fixtures :encrypted_books, :posts
|
|
11
|
+
|
|
12
|
+
test "encrypts the attribute seamlessly when creating and updating records" do
|
|
13
|
+
post = EncryptedPost.create!(title: "The Starfleet is here!", body: "take cover!")
|
|
14
|
+
assert_encrypted_attribute(post, :title, "The Starfleet is here!")
|
|
15
|
+
|
|
16
|
+
post.update!(title: "The Klingons are coming!")
|
|
17
|
+
assert_encrypted_attribute(post, :title, "The Klingons are coming!")
|
|
18
|
+
|
|
19
|
+
post.title = "You sure?"
|
|
20
|
+
post.save!
|
|
21
|
+
assert_encrypted_attribute(post, :title, "You sure?")
|
|
22
|
+
|
|
23
|
+
post[:title] = "The Klingons are leaving!"
|
|
24
|
+
post.save!
|
|
25
|
+
assert_encrypted_attribute(post, :title, "The Klingons are leaving!")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
test "attribute is not accessible with the wrong key" do
|
|
29
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = false
|
|
30
|
+
|
|
31
|
+
post = EncryptedPost.create!(title: "The Starfleet is here!", body: "take cover!")
|
|
32
|
+
post.reload.tags_count # accessing regular attributes works
|
|
33
|
+
assert_invalid_key_cant_read_attribute(post, :body)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
test "swapping key_providers via with_encryption_context" do
|
|
37
|
+
key_provider1 = ActiveRecord::Encryption::DerivedSecretKeyProvider.new(SecureRandom.base64(32))
|
|
38
|
+
key_provider2 = ActiveRecord::Encryption::DerivedSecretKeyProvider.new(SecureRandom.base64(32))
|
|
39
|
+
|
|
40
|
+
post1 = post2 = nil
|
|
41
|
+
|
|
42
|
+
ActiveRecord::Encryption.with_encryption_context key_provider: key_provider1 do
|
|
43
|
+
post1 = EncryptedPost.create!(title: "post1!", body: "first post!")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
ActiveRecord::Encryption.with_encryption_context key_provider: key_provider2 do
|
|
47
|
+
post2 = EncryptedPost.create!(title: "post2!", body: "second post!")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
post1.reload
|
|
51
|
+
assert_raises ActiveRecord::Encryption::Errors::Decryption do
|
|
52
|
+
post1.title
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
post2.reload
|
|
56
|
+
assert_raises ActiveRecord::Encryption::Errors::Decryption do
|
|
57
|
+
post2.title
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
ActiveRecord::Encryption.with_encryption_context key_provider: key_provider1 do
|
|
61
|
+
post1.reload
|
|
62
|
+
assert_equal "post1!", post1.title
|
|
63
|
+
|
|
64
|
+
post2.reload
|
|
65
|
+
assert_raises ActiveRecord::Encryption::Errors::Decryption do
|
|
66
|
+
post2.title
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
ActiveRecord::Encryption.with_encryption_context key_provider: key_provider2 do
|
|
71
|
+
post2.reload
|
|
72
|
+
assert_equal "post2!", post2.title
|
|
73
|
+
|
|
74
|
+
post1.reload
|
|
75
|
+
assert_raises ActiveRecord::Encryption::Errors::Decryption do
|
|
76
|
+
post1.title
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
test "ignores nil values" do
|
|
82
|
+
assert_nil EncryptedBook.create!(name: nil).name
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
test "ignores empty values" do
|
|
86
|
+
assert_equal "", EncryptedBook.create!(name: "").name
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
test "encrypts serialized attributes" do
|
|
90
|
+
states = ["green", "red"]
|
|
91
|
+
traffic_light = EncryptedTrafficLight.create!(state: states, long_state: states)
|
|
92
|
+
assert_encrypted_attribute(traffic_light, :state, states)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
test "encrypts serialized attributes where encrypts is declared first" do
|
|
96
|
+
states = ["green", "red"]
|
|
97
|
+
traffic_light = EncryptedFirstTrafficLight.create!(state: states, long_state: states)
|
|
98
|
+
assert_encrypted_attribute(traffic_light, :state, states)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
test "encrypts store attributes with accessors" do
|
|
102
|
+
traffic_light = EncryptedTrafficLightWithStoreState.create!(color: "red", long_state: ["green", "red"])
|
|
103
|
+
assert_equal "red", traffic_light.color
|
|
104
|
+
assert_encrypted_attribute(traffic_light, :state, { "color" => "red" })
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
test "can configure a custom key provider on a per-record-class basis through the :key_provider option" do
|
|
108
|
+
post = EncryptedPost.create!(title: "The Starfleet is here!", body: "take cover!")
|
|
109
|
+
assert_encrypted_attribute(post, :body, "take cover!")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
test "can configure a custom key on a per-record-class basis through the :key option" do
|
|
113
|
+
author = EncryptedAuthorWithKey.create!(name: "Stephen King")
|
|
114
|
+
assert_encrypted_attribute(author, :name, "Stephen King")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
test "encrypts multiple attributes with different options at the same time" do
|
|
118
|
+
post = EncryptedPost.create! \
|
|
119
|
+
title: title = "The Starfleet is here!",
|
|
120
|
+
body: body = "<p>the Starfleet is here, we are safe now!</p>"
|
|
121
|
+
|
|
122
|
+
assert_encrypted_attribute(post, :title, title)
|
|
123
|
+
assert_encrypted_attribute(post, :body, body)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
test "encrypted_attributes returns the list of encrypted attributes in a model (each record class holds their own list)" do
|
|
127
|
+
assert_equal Set.new([:title, :body]), EncryptedPost.encrypted_attributes
|
|
128
|
+
assert_not_equal EncryptedAuthor.encrypted_attributes, EncryptedPost.encrypted_attributes
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
test "deterministic_encrypted_attributes returns the list of deterministic encrypted attributes in a model (each record class holds their own list)" do
|
|
132
|
+
assert_equal [:name], EncryptedBook.deterministic_encrypted_attributes
|
|
133
|
+
assert_not_equal EncryptedPost.deterministic_encrypted_attributes, EncryptedBook.deterministic_encrypted_attributes
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
test "by default, encryption is not deterministic" do
|
|
137
|
+
post_1 = EncryptedPost.create!(title: "the same title", body: "some body")
|
|
138
|
+
post_2 = EncryptedPost.create!(title: "the same title", body: "some body")
|
|
139
|
+
|
|
140
|
+
assert_not_equal post_1.ciphertext_for(:title), post_2.ciphertext_for(:title)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
test "deterministic attributes can be searched with Active Record queries" do
|
|
144
|
+
EncryptedBook.create!(name: "Dune")
|
|
145
|
+
|
|
146
|
+
assert EncryptedBook.find_by(name: "Dune")
|
|
147
|
+
assert_not EncryptedBook.find_by(name: "not Dune")
|
|
148
|
+
|
|
149
|
+
assert_equal 1, EncryptedBook.where(name: "Dune").count
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
test "deterministic attributes can be created by passing deterministic: true" do
|
|
153
|
+
book_1 = EncryptedBook.create!(name: "Dune")
|
|
154
|
+
book_2 = EncryptedBook.create!(name: "Dune")
|
|
155
|
+
|
|
156
|
+
assert_equal book_1.ciphertext_for(:name), book_2.ciphertext_for(:name)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
test "deterministic ciphertexts remain constant" do
|
|
160
|
+
# We need to make sure these don't change or existing apps will stop working
|
|
161
|
+
ciphertext = "{\"p\":\"DIohhw==\",\"h\":{\"iv\":\"wEPaDcJP3VNIxaiz\",\"at\":\"X7+2xvvcu1k1if6Dy28Esw==\"}}"
|
|
162
|
+
book = UnencryptedBook.create name: ciphertext
|
|
163
|
+
|
|
164
|
+
book = EncryptedBook.find(book.id)
|
|
165
|
+
assert_equal "Dune", book.name
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
test "encryption errors when saving records will raise the error and don't save anything" do
|
|
169
|
+
assert_no_changes -> { BookThatWillFailToEncryptName.count } do
|
|
170
|
+
assert_raises ActiveRecord::Encryption::Errors::Encryption do
|
|
171
|
+
BookThatWillFailToEncryptName.create!(name: "Dune")
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
test "can work with pre-encryption nil values" do
|
|
177
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
178
|
+
book = ActiveRecord::Encryption.without_encryption { EncryptedBook.create!(name: nil) }
|
|
179
|
+
assert_nil book.name
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
test "can work with pre-encryption empty values" do
|
|
183
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
184
|
+
book = ActiveRecord::Encryption.without_encryption { EncryptedBook.create!(name: "") }
|
|
185
|
+
assert_equal "", book.name
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
test "can't modify encrypted attributes when frozen_encryption is true" do
|
|
189
|
+
post = posts(:welcome).becomes(EncryptedPost)
|
|
190
|
+
post.title = "Some new title"
|
|
191
|
+
assert_predicate post, :valid?
|
|
192
|
+
|
|
193
|
+
ActiveRecord::Encryption.with_encryption_context frozen_encryption: true do
|
|
194
|
+
assert_not post.valid?
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
test "can only save unencrypted attributes when frozen encryption is true" do
|
|
199
|
+
book = encrypted_books(:awdr)
|
|
200
|
+
|
|
201
|
+
ActiveRecord::Encryption.with_encryption_context frozen_encryption: true do
|
|
202
|
+
book.update! updated_at: Time.now
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
ActiveRecord::Encryption.with_encryption_context frozen_encryption: true do
|
|
206
|
+
assert_raises ActiveRecord::RecordInvalid do
|
|
207
|
+
book.update! name: "Some new title"
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
test "won't change the encoding of strings" do
|
|
213
|
+
author_name = "Jorge"
|
|
214
|
+
encoding = author_name.encoding
|
|
215
|
+
author = EncryptedAuthor.create!(name: author_name)
|
|
216
|
+
assert_equal encoding, author.reload.name.encoding
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
test "by default, it's case sensitive" do
|
|
220
|
+
EncryptedBook.create!(name: "Dune")
|
|
221
|
+
assert EncryptedBook.find_by(name: "Dune")
|
|
222
|
+
assert_not EncryptedBook.find_by(name: "dune")
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
test "when using downcase: true it ignores case since everything will be downcase" do
|
|
226
|
+
EncryptedBookWithDowncaseName.create!(name: "Dune")
|
|
227
|
+
assert EncryptedBookWithDowncaseName.find_by(name: "Dune")
|
|
228
|
+
assert EncryptedBookWithDowncaseName.find_by(name: "dune")
|
|
229
|
+
assert EncryptedBookWithDowncaseName.find_by(name: "DUNE")
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
test "when downcase: true it creates content downcased" do
|
|
233
|
+
EncryptedBookWithDowncaseName.create!(name: "Dune")
|
|
234
|
+
assert EncryptedBookWithDowncaseName.find_by_name("dune")
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
test "when ignore_case: true, it ignores case in queries but keep it when reading the attribute" do
|
|
238
|
+
EncryptedBookThatIgnoresCase.create!(name: "Dune")
|
|
239
|
+
book = EncryptedBookThatIgnoresCase.find_by_name("dune")
|
|
240
|
+
assert book
|
|
241
|
+
assert_equal "Dune", book.name
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
test "when ignore_case: true, it keeps both the attribute and the _original counterpart encrypted" do
|
|
245
|
+
book = EncryptedBookThatIgnoresCase.create!(name: "Dune")
|
|
246
|
+
assert_encrypted_attribute book, :name, "Dune"
|
|
247
|
+
assert_encrypted_attribute book, :original_name, "Dune"
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
test "when ignore_case: true, it lets you update attributes normally" do
|
|
251
|
+
book = EncryptedBookThatIgnoresCase.create!(name: "Dune")
|
|
252
|
+
book.update!(name: "Dune II")
|
|
253
|
+
assert_equal "Dune II", book.name
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
test "when ignore_case: true, it returns the actual value when not encrypted" do
|
|
257
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
258
|
+
|
|
259
|
+
book = create_unencrypted_book_ignoring_case name: "Dune"
|
|
260
|
+
assert_equal "Dune", book.name
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
test "when ignore_case: true, users can override accessors and call super" do
|
|
264
|
+
overriding_class = Class.new(EncryptedBookThatIgnoresCase) do
|
|
265
|
+
self.table_name = "books"
|
|
266
|
+
|
|
267
|
+
def name
|
|
268
|
+
"#{super}-overridden"
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
overriding_class.create!(name: "Dune")
|
|
273
|
+
book = overriding_class.find_by_name("dune")
|
|
274
|
+
assert book
|
|
275
|
+
assert_equal "Dune-overridden", book.reload.name
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
test "reading a not encrypted value will raise a Decryption error when :support_unencrypted_data is false" do
|
|
279
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = false
|
|
280
|
+
|
|
281
|
+
book = ActiveRecord::Encryption.without_encryption do
|
|
282
|
+
EncryptedBookThatIgnoresCase.create!(name: "dune")
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
assert_raises(ActiveRecord::Encryption::Errors::Decryption) do
|
|
286
|
+
book.name
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
test "reading a not encrypted value won't raise a Decryption error when :support_unencrypted_data is true" do
|
|
291
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
292
|
+
|
|
293
|
+
author = ActiveRecord::Encryption.without_encryption do
|
|
294
|
+
EncryptedAuthor.create!(name: "Stephen King")
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
assert_equal "Stephen King", author.name
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Only run for adapters that add a default string limit when not provided (MySQL, 255)
|
|
301
|
+
if author_name_limit = EncryptedAuthor.columns_hash["name"].limit
|
|
302
|
+
# No column limits in SQLite
|
|
303
|
+
test "validate column sizes" do
|
|
304
|
+
assert_predicate EncryptedAuthor.new(name: "jorge"), :valid?
|
|
305
|
+
assert_not EncryptedAuthor.new(name: "a" * (author_name_limit + 1)).valid?
|
|
306
|
+
author = EncryptedAuthor.create(name: "a" * (author_name_limit + 1))
|
|
307
|
+
assert_not author.valid?
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
test "track previous changes properly for encrypted attributes" do
|
|
312
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
313
|
+
|
|
314
|
+
book = EncryptedBook.create!(name: "Dune")
|
|
315
|
+
book.update!(created_at: 1.hour.ago)
|
|
316
|
+
assert_not book.name_previously_changed?
|
|
317
|
+
|
|
318
|
+
book.update!(name: "A new title!")
|
|
319
|
+
assert_predicate book, :name_previously_changed?
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
test "forces UTF-8 encoding for deterministic attributes by default" do
|
|
323
|
+
book = EncryptedBook.create!(name: "Dune".encode("ASCII-8BIT"))
|
|
324
|
+
assert_equal Encoding::UTF_8, book.reload.name.encoding
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
test "forces encoding for deterministic attributes based on the configured option" do
|
|
328
|
+
ActiveRecord::Encryption.config.forced_encoding_for_deterministic_encryption = Encoding::US_ASCII
|
|
329
|
+
|
|
330
|
+
book = EncryptedBook.create!(name: "Dune".encode("ASCII-8BIT"))
|
|
331
|
+
assert_equal Encoding::US_ASCII, book.reload.name.encoding
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
test "forced encoding for deterministic attributes will replace invalid characters" do
|
|
335
|
+
book = EncryptedBook.create!(name: "Hello \x93\xfa".b)
|
|
336
|
+
assert_equal "Hello ��", book.reload.name
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
test "forced encoding for deterministic attributes can be disabled" do
|
|
340
|
+
ActiveRecord::Encryption.config.forced_encoding_for_deterministic_encryption = nil
|
|
341
|
+
|
|
342
|
+
book = EncryptedBook.create!(name: "Dune".encode("US-ASCII"))
|
|
343
|
+
assert_equal Encoding::US_ASCII, book.reload.name.encoding
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
test "support encrypted attributes defined on columns with default values" do
|
|
347
|
+
book = EncryptedBook.create!
|
|
348
|
+
assert_encrypted_attribute(book, :name, "<untitled>")
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
test "loading records with encrypted attributes defined on columns with default values" do
|
|
352
|
+
skip unless supports_insert_on_duplicate_update?
|
|
353
|
+
|
|
354
|
+
EncryptedBook.insert({ format: "ebook" })
|
|
355
|
+
book = EncryptedBook.last
|
|
356
|
+
assert_equal "<untitled>", book.name
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
test "can dump and load records that use encryption" do
|
|
360
|
+
book = EncryptedBook.create!
|
|
361
|
+
assert_equal book, Marshal.load(Marshal.dump(book))
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
test "supports decrypting data encrypted non deterministically with SHA1 when digest class is SHA256" do
|
|
365
|
+
ActiveRecord::Encryption.configure \
|
|
366
|
+
primary_key: "the primary key",
|
|
367
|
+
deterministic_key: "the deterministic key",
|
|
368
|
+
key_derivation_salt: "the salt",
|
|
369
|
+
support_sha1_for_non_deterministic_encryption: true
|
|
370
|
+
|
|
371
|
+
key_provider_sha1 = build_derived_key_provider_with OpenSSL::Digest::SHA1
|
|
372
|
+
key_provider_sha256 = build_derived_key_provider_with OpenSSL::Digest::SHA256
|
|
373
|
+
|
|
374
|
+
encrypted_post_class_sha_1 = Class.new(Post) do
|
|
375
|
+
self.table_name = "posts"
|
|
376
|
+
encrypts :title, key_provider: key_provider_sha1
|
|
377
|
+
end
|
|
378
|
+
encrypted_post_class_sha_1.create! title: "Post 1", body: "The post body", type: nil
|
|
379
|
+
|
|
380
|
+
encrypted_post_class_sha_256 = Class.new(Post) do
|
|
381
|
+
self.table_name = "posts"
|
|
382
|
+
encrypts :title, key_provider: key_provider_sha256
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
assert_equal "Post 1", encrypted_post_class_sha_256.last.title
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
test "encryption schemes are resolved when used, not when declared" do
|
|
389
|
+
OtherEncryptedPost = Class.new(Post) do
|
|
390
|
+
self.table_name = "posts"
|
|
391
|
+
encrypts :title
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
ActiveRecord::Encryption.configure \
|
|
395
|
+
primary_key: "the primary key",
|
|
396
|
+
deterministic_key: "the deterministic key",
|
|
397
|
+
key_derivation_salt: "the salt",
|
|
398
|
+
support_sha1_for_non_deterministic_encryption: true
|
|
399
|
+
|
|
400
|
+
assert_predicate OtherEncryptedPost.type_for_attribute(:title).scheme.previous_schemes, :one?
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
test "binary data can be encrypted" do
|
|
404
|
+
all_bytes = (0..255).map(&:chr).join
|
|
405
|
+
assert_equal all_bytes, EncryptedBookWithBinary.create!(logo: all_bytes).logo
|
|
406
|
+
assert_nil EncryptedBookWithBinary.create!(logo: nil).logo
|
|
407
|
+
assert_equal "", EncryptedBookWithBinary.create!(logo: "").logo
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
test "binary data can be encrypted uncompressed" do
|
|
411
|
+
low_bytes = (0..127).map(&:chr).join
|
|
412
|
+
high_bytes = (128..255).map(&:chr).join
|
|
413
|
+
assert_encrypted_attribute EncryptedBookWithBinary.create!(logo: low_bytes), :logo, low_bytes
|
|
414
|
+
assert_encrypted_attribute EncryptedBookWithBinary.create!(logo: high_bytes), :logo, high_bytes
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
test "serialized binary data can be encrypted" do
|
|
418
|
+
json_bytes = (32..127).map(&:chr)
|
|
419
|
+
assert_encrypted_attribute EncryptedBookWithSerializedFirstBinary.create!(logo: json_bytes), :logo, json_bytes
|
|
420
|
+
assert_encrypted_attribute EncryptedBookWithSerializedSecondBinary.create!(logo: json_bytes), :logo, json_bytes
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
test "can compress data with custom compressor" do
|
|
424
|
+
name = "a" * 141
|
|
425
|
+
assert EncryptedBookWithCustomCompressor.create!(name: name).name.start_with?("[compressed]")
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
test "type method returns cast type" do
|
|
429
|
+
assert_equal :string, EncryptedBook.type_for_attribute(:name).type
|
|
430
|
+
|
|
431
|
+
expected_post_body_type = if ActiveRecord::TestCase.current_adapter?(:OracleAdapter, :IBM_DBAdapter)
|
|
432
|
+
:string
|
|
433
|
+
else
|
|
434
|
+
:text
|
|
435
|
+
end
|
|
436
|
+
assert_equal expected_post_body_type, EncryptedPost.type_for_attribute(:body).type
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
test "encrypts normalized data" do
|
|
440
|
+
assert_encrypted_attribute EncryptedBookNormalizedFirst.create!(name: "Book"), :name, "book"
|
|
441
|
+
assert_encrypted_attribute EncryptedBookNormalizedSecond.create!(name: "Book"), :name, "book"
|
|
442
|
+
assert_encrypted_attribute EncryptedBookNormalizedFirst.create!(logo: "Book"), :logo, "book"
|
|
443
|
+
assert_encrypted_attribute EncryptedBookNormalizedSecond.create!(logo: "Book"), :logo, "book"
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
test "encrypts attribute data" do
|
|
447
|
+
assert_encrypted_attribute EncryptedBookAttribute.create!(name: "2024-01-01"), :name, Date.new(2024, 1, 1)
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
private
|
|
451
|
+
def build_derived_key_provider_with(hash_digest_class)
|
|
452
|
+
ActiveRecord::Encryption.with_encryption_context(key_generator: ActiveRecord::Encryption::KeyGenerator.new(hash_digest_class: hash_digest_class)) do
|
|
453
|
+
ActiveRecord::Encryption::DerivedSecretKeyProvider.new(ActiveRecord::Encryption.config.primary_key)
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
class FailingKeyProvider
|
|
458
|
+
def decryption_key(message) end
|
|
459
|
+
|
|
460
|
+
def encryption_key
|
|
461
|
+
raise ActiveRecord::Encryption::Errors::Encryption
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
class BookThatWillFailToEncryptName < UnencryptedBook
|
|
466
|
+
self.table_name = "encrypted_books"
|
|
467
|
+
|
|
468
|
+
encrypts :name, key_provider: FailingKeyProvider.new
|
|
469
|
+
end
|
|
470
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/encryption/helper"
|
|
4
|
+
require "models/book_encrypted"
|
|
5
|
+
|
|
6
|
+
class ActiveRecord::Encryption::EncryptableFixtureTest < ActiveRecord::EncryptionTestCase
|
|
7
|
+
self.use_transactional_tests = false
|
|
8
|
+
|
|
9
|
+
fixtures :encrypted_books, :encrypted_book_that_ignores_cases
|
|
10
|
+
|
|
11
|
+
test "fixtures get encrypted automatically" do
|
|
12
|
+
assert encrypted_books(:awdr).encrypted_attribute?(:name)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "preserved columns due to ignore_case: true gets encrypted automatically" do
|
|
16
|
+
book = encrypted_book_that_ignores_cases(:rfr)
|
|
17
|
+
assert_equal "Ruby for Rails", book.name
|
|
18
|
+
assert_encrypted_attribute book, :name, "Ruby for Rails"
|
|
19
|
+
|
|
20
|
+
assert EncryptedBookThatIgnoresCase.find_by_name("Ruby for Rails")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/encryption/helper"
|
|
4
|
+
|
|
5
|
+
class ActiveRecord::Encryption::EncryptingOnlyEncryptorTest < ActiveRecord::EncryptionTestCase
|
|
6
|
+
setup do
|
|
7
|
+
@encryptor = ActiveRecord::Encryption::EncryptingOnlyEncryptor.new
|
|
8
|
+
ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "decrypt returns the passed data" do
|
|
12
|
+
assert_equal "Some data", @encryptor.decrypt("Some data")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "encrypt encrypts the passed data" do
|
|
16
|
+
encrypted_text = @encryptor.encrypt("Some data")
|
|
17
|
+
assert_not_equal encrypted_text, "Some data"
|
|
18
|
+
assert_equal "Some data", ActiveRecord::Encryption::Encryptor.new.decrypt(encrypted_text)
|
|
19
|
+
end
|
|
20
|
+
end
|