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.
Files changed (592) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Makefile +13 -9
  3. data/ext/extconf.rb +176 -110
  4. data/ext/ibm_db.c +60 -0
  5. data/ext/ibm_db.o +0 -0
  6. data/ext/ibm_db.so +0 -0
  7. data/ext/mkmf.log +6 -6
  8. data/ext/ruby_ibm_db_cli.c +14 -10
  9. data/ext/ruby_ibm_db_cli.h +4 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/IBM_DB.rb +2 -2
  12. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
  13. data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
  14. data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
  15. data/test/activejob/destroy_association_async_job_test.rb +62 -0
  16. data/test/activejob/destroy_association_async_test.rb +147 -11
  17. data/test/activejob/job_runtime_test.rb +41 -0
  18. data/test/activejob/unloadable_base_job.rb +3 -0
  19. data/test/cases/active_record_schema_test.rb +196 -0
  20. data/test/cases/active_record_test.rb +21 -0
  21. data/test/cases/adapter_prevent_writes_test.rb +26 -202
  22. data/test/cases/adapter_test.rb +592 -82
  23. data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
  24. data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
  25. data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
  26. data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
  27. data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
  28. data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
  29. data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
  30. data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
  31. data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
  32. data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
  33. data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
  34. data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
  35. data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
  36. data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
  38. data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
  39. data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
  40. data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
  41. data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
  42. data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
  43. data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
  44. data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
  45. data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
  46. data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
  47. data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
  48. data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
  49. data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
  50. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
  51. data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
  52. data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
  53. data/test/cases/adapters/postgresql/array_test.rb +6 -6
  54. data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
  55. data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
  56. data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
  57. data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
  58. data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
  59. data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
  60. data/test/cases/adapters/postgresql/citext_test.rb +7 -1
  61. data/test/cases/adapters/postgresql/collation_test.rb +1 -1
  62. data/test/cases/adapters/postgresql/composite_test.rb +1 -1
  63. data/test/cases/adapters/postgresql/connection_test.rb +43 -36
  64. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
  65. data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
  66. data/test/cases/adapters/postgresql/date_test.rb +2 -2
  67. data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
  68. data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
  69. data/test/cases/adapters/postgresql/domain_test.rb +1 -1
  70. data/test/cases/adapters/postgresql/enum_test.rb +208 -8
  71. data/test/cases/adapters/postgresql/explain_test.rb +25 -6
  72. data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
  73. data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
  74. data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
  75. data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
  76. data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
  77. data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
  78. data/test/cases/adapters/postgresql/integer_test.rb +1 -1
  79. data/test/cases/adapters/postgresql/interval_test.rb +9 -17
  80. data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
  81. data/test/cases/adapters/postgresql/json_test.rb +5 -0
  82. data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
  83. data/test/cases/adapters/postgresql/money_test.rb +17 -9
  84. data/test/cases/adapters/postgresql/network_test.rb +13 -1
  85. data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
  86. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
  87. data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
  88. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
  89. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
  90. data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
  91. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
  92. data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
  93. data/test/cases/adapters/postgresql/range_test.rb +185 -21
  94. data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
  95. data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
  96. data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
  97. data/test/cases/adapters/postgresql/schema_test.rb +270 -20
  98. data/test/cases/adapters/postgresql/serial_test.rb +5 -5
  99. data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
  100. data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
  101. data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
  102. data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
  103. data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
  104. data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
  105. data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
  106. data/test/cases/adapters/postgresql/xml_test.rb +1 -1
  107. data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
  108. data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
  109. data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
  110. data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
  111. data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
  112. data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
  113. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
  114. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
  115. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
  116. data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
  117. data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
  118. data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
  119. data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
  120. data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
  121. data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
  122. data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
  123. data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
  124. data/test/cases/aggregations_test.rb +16 -0
  125. data/test/cases/annotate_test.rb +14 -12
  126. data/test/cases/arel/attributes/attribute_test.rb +86 -47
  127. data/test/cases/arel/collectors/bind_test.rb +1 -1
  128. data/test/cases/arel/collectors/composite_test.rb +11 -1
  129. data/test/cases/arel/collectors/sql_string_test.rb +1 -1
  130. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
  131. data/test/cases/arel/delete_manager_test.rb +0 -6
  132. data/test/cases/arel/factory_methods_test.rb +45 -0
  133. data/test/cases/arel/insert_manager_test.rb +1 -7
  134. data/test/cases/arel/nodes/as_test.rb +12 -0
  135. data/test/cases/arel/nodes/ascending_test.rb +1 -1
  136. data/test/cases/arel/nodes/bin_test.rb +1 -1
  137. data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
  138. data/test/cases/arel/nodes/cte_test.rb +46 -0
  139. data/test/cases/arel/nodes/descending_test.rb +1 -1
  140. data/test/cases/arel/nodes/equality_test.rb +3 -3
  141. data/test/cases/arel/nodes/filter_test.rb +37 -0
  142. data/test/cases/arel/nodes/fragments_test.rb +38 -0
  143. data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
  144. data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
  145. data/test/cases/arel/nodes/node_test.rb +1 -1
  146. data/test/cases/arel/nodes/or_test.rb +2 -2
  147. data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
  148. data/test/cases/arel/nodes/table_alias_test.rb +12 -0
  149. data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
  150. data/test/cases/arel/nodes/update_statement_test.rb +4 -0
  151. data/test/cases/arel/nodes_test.rb +3 -2
  152. data/test/cases/arel/select_manager_test.rb +12 -12
  153. data/test/cases/arel/support/fake_record.rb +22 -17
  154. data/test/cases/arel/table_test.rb +15 -25
  155. data/test/cases/arel/update_manager_test.rb +51 -6
  156. data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
  157. data/test/cases/arel/visitors/dot_test.rb +177 -2
  158. data/test/cases/arel/visitors/mysql_test.rb +49 -1
  159. data/test/cases/arel/visitors/postgres_test.rb +1 -31
  160. data/test/cases/arel/visitors/sqlite_test.rb +1 -1
  161. data/test/cases/arel/visitors/to_sql_test.rb +330 -20
  162. data/test/cases/assertions/query_assertions_test.rb +136 -0
  163. data/test/cases/associations/belongs_to_associations_test.rb +502 -41
  164. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
  165. data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
  166. data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
  167. data/test/cases/associations/eager_singularization_test.rb +1 -1
  168. data/test/cases/associations/eager_test.rb +255 -93
  169. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
  170. data/test/cases/associations/has_many_associations_test.rb +282 -72
  171. data/test/cases/associations/has_many_through_associations_test.rb +172 -45
  172. data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
  173. data/test/cases/associations/has_one_associations_test.rb +160 -29
  174. data/test/cases/associations/has_one_through_associations_test.rb +64 -15
  175. data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
  176. data/test/cases/associations/inner_join_association_test.rb +36 -6
  177. data/test/cases/associations/inverse_associations_test.rb +177 -40
  178. data/test/cases/associations/join_model_test.rb +17 -12
  179. data/test/cases/associations/left_outer_join_association_test.rb +14 -3
  180. data/test/cases/associations/nested_error_test.rb +116 -0
  181. data/test/cases/associations/nested_through_associations_test.rb +54 -19
  182. data/test/cases/associations/required_test.rb +1 -1
  183. data/test/cases/associations_test.rb +1278 -21
  184. data/test/cases/asynchronous_queries_test.rb +310 -0
  185. data/test/cases/attribute_methods/read_test.rb +6 -0
  186. data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
  187. data/test/cases/attribute_methods_test.rb +565 -46
  188. data/test/cases/attributes_test.rb +42 -1
  189. data/test/cases/autosave_association_test.rb +645 -92
  190. data/test/cases/base_prevent_writes_test.rb +28 -159
  191. data/test/cases/base_test.rb +434 -209
  192. data/test/cases/batches_test.rb +441 -57
  193. data/test/cases/binary_test.rb +31 -0
  194. data/test/cases/bind_parameter_test.rb +107 -16
  195. data/test/cases/cache_key_test.rb +7 -7
  196. data/test/cases/calculations_test.rb +541 -110
  197. data/test/cases/callbacks_test.rb +0 -1
  198. data/test/cases/clone_test.rb +5 -4
  199. data/test/cases/coders/yaml_column_test.rb +97 -2
  200. data/test/cases/collection_cache_key_test.rb +24 -16
  201. data/test/cases/column_alias_test.rb +2 -8
  202. data/test/cases/column_definition_test.rb +12 -3
  203. data/test/cases/comment_test.rb +23 -26
  204. data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
  205. data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
  206. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
  207. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
  208. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
  209. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
  210. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
  211. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
  212. data/test/cases/connection_adapters/registration_test.rb +98 -0
  213. data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
  214. data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
  215. data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
  216. data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
  217. data/test/cases/connection_handling_test.rb +210 -0
  218. data/test/cases/connection_management_test.rb +44 -7
  219. data/test/cases/connection_pool_test.rb +466 -99
  220. data/test/cases/core_test.rb +167 -9
  221. data/test/cases/counter_cache_test.rb +129 -2
  222. data/test/cases/custom_locking_test.rb +3 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +149 -13
  224. data/test/cases/database_configurations/resolver_test.rb +14 -10
  225. data/test/cases/database_configurations/url_config_test.rb +53 -0
  226. data/test/cases/database_configurations_test.rb +86 -43
  227. data/test/cases/database_selector_test.rb +30 -8
  228. data/test/cases/database_statements_test.rb +10 -14
  229. data/test/cases/date_time_precision_test.rb +141 -11
  230. data/test/cases/date_time_test.rb +19 -1
  231. data/test/cases/defaults_test.rb +107 -41
  232. data/test/cases/delegated_type_test.rb +69 -9
  233. data/test/cases/dirty_test.rb +82 -25
  234. data/test/cases/disconnected_test.rb +10 -9
  235. data/test/cases/dup_test.rb +26 -6
  236. data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
  237. data/test/cases/encryption/cipher_test.rb +65 -0
  238. data/test/cases/encryption/concurrency_test.rb +27 -0
  239. data/test/cases/encryption/config_test.rb +21 -0
  240. data/test/cases/encryption/configurable_test.rb +93 -0
  241. data/test/cases/encryption/contexts_test.rb +105 -0
  242. data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
  243. data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
  244. data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
  245. data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
  246. data/test/cases/encryption/encryptable_record_test.rb +470 -0
  247. data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
  248. data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
  249. data/test/cases/encryption/encryption_schemes_test.rb +240 -0
  250. data/test/cases/encryption/encryptor_test.rb +113 -0
  251. data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
  252. data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
  253. data/test/cases/encryption/helper.rb +152 -0
  254. data/test/cases/encryption/key_generator_test.rb +55 -0
  255. data/test/cases/encryption/key_provider_test.rb +57 -0
  256. data/test/cases/encryption/key_test.rb +17 -0
  257. data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
  258. data/test/cases/encryption/message_serializer_test.rb +82 -0
  259. data/test/cases/encryption/message_test.rb +43 -0
  260. data/test/cases/encryption/null_encryptor_test.rb +21 -0
  261. data/test/cases/encryption/properties_test.rb +69 -0
  262. data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
  263. data/test/cases/encryption/scheme_test.rb +58 -0
  264. data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
  265. data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
  266. data/test/cases/enum_test.rb +374 -72
  267. data/test/cases/errors_test.rb +7 -4
  268. data/test/cases/excluding_test.rb +116 -0
  269. data/test/cases/explain_subscriber_test.rb +6 -1
  270. data/test/cases/explain_test.rb +119 -10
  271. data/test/cases/filter_attributes_test.rb +7 -14
  272. data/test/cases/finder_respond_to_test.rb +3 -3
  273. data/test/cases/finder_test.rb +357 -72
  274. data/test/cases/fixture_set/file_test.rb +9 -0
  275. data/test/cases/fixtures_test.rb +426 -190
  276. data/test/cases/helper.rb +66 -192
  277. data/test/cases/hot_compatibility_test.rb +10 -10
  278. data/test/cases/inheritance_test.rb +51 -61
  279. data/test/cases/inherited_test.rb +40 -0
  280. data/test/cases/insert_all_test.rb +419 -9
  281. data/test/cases/instrumentation_test.rb +202 -30
  282. data/test/cases/integration_test.rb +25 -7
  283. data/test/cases/invalid_connection_test.rb +5 -5
  284. data/test/cases/invertible_migration_test.rb +108 -24
  285. data/test/cases/json_attribute_test.rb +1 -0
  286. data/test/cases/json_serialization_test.rb +5 -5
  287. data/test/cases/json_shared_test_cases.rb +5 -9
  288. data/test/cases/locking_test.rb +67 -31
  289. data/test/cases/log_subscriber_test.rb +17 -15
  290. data/test/cases/marshal_serialization_test.rb +78 -5
  291. data/test/cases/message_pack_test.rb +91 -0
  292. data/test/cases/migration/change_schema_test.rb +77 -46
  293. data/test/cases/migration/change_table_test.rb +129 -114
  294. data/test/cases/migration/check_constraint_test.rb +192 -10
  295. data/test/cases/migration/column_attributes_test.rb +4 -9
  296. data/test/cases/migration/column_positioning_test.rb +2 -2
  297. data/test/cases/migration/columns_test.rb +118 -4
  298. data/test/cases/migration/command_recorder_test.rb +181 -14
  299. data/test/cases/migration/compatibility_test.rb +883 -196
  300. data/test/cases/migration/create_join_table_test.rb +8 -1
  301. data/test/cases/migration/exclusion_constraint_test.rb +192 -0
  302. data/test/cases/migration/foreign_key_test.rb +356 -14
  303. data/test/cases/migration/helper.rb +4 -1
  304. data/test/cases/migration/index_test.rb +67 -2
  305. data/test/cases/migration/invalid_options_test.rb +129 -0
  306. data/test/cases/migration/logger_test.rb +7 -4
  307. data/test/cases/migration/pending_migrations_test.rb +103 -60
  308. data/test/cases/migration/references_foreign_key_test.rb +73 -4
  309. data/test/cases/migration/references_index_test.rb +25 -27
  310. data/test/cases/migration/references_statements_test.rb +27 -3
  311. data/test/cases/migration/rename_table_test.rb +39 -54
  312. data/test/cases/migration/schema_definitions_test.rb +109 -0
  313. data/test/cases/migration/unique_constraint_test.rb +248 -0
  314. data/test/cases/migration_test.rb +677 -220
  315. data/test/cases/migrator_test.rb +102 -75
  316. data/test/cases/multi_db_migrator_test.rb +55 -34
  317. data/test/cases/multiparameter_attributes_test.rb +26 -29
  318. data/test/cases/multiple_db_test.rb +42 -19
  319. data/test/cases/nested_attributes_test.rb +124 -6
  320. data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
  321. data/test/cases/normalized_attribute_test.rb +117 -0
  322. data/test/cases/null_relation_test.rb +35 -2
  323. data/test/cases/persistence/reload_association_cache_test.rb +20 -0
  324. data/test/cases/persistence_test.rb +629 -22
  325. data/test/cases/pooled_connections_test.rb +57 -56
  326. data/test/cases/prepared_statement_status_test.rb +8 -3
  327. data/test/cases/primary_class_test.rb +134 -0
  328. data/test/cases/primary_keys_test.rb +171 -55
  329. data/test/cases/query_cache_test.rb +558 -263
  330. data/test/cases/query_logs_test.rb +293 -0
  331. data/test/cases/quoting_test.rb +39 -72
  332. data/test/cases/readonly_test.rb +50 -12
  333. data/test/cases/reaper_test.rb +22 -6
  334. data/test/cases/reflection_test.rb +207 -9
  335. data/test/cases/relation/and_test.rb +43 -0
  336. data/test/cases/relation/delegation_test.rb +32 -5
  337. data/test/cases/relation/delete_all_test.rb +27 -6
  338. data/test/cases/relation/field_ordered_values_test.rb +128 -0
  339. data/test/cases/relation/load_async_test.rb +650 -0
  340. data/test/cases/relation/merging_test.rb +80 -109
  341. data/test/cases/relation/mutation_test.rb +12 -7
  342. data/test/cases/relation/or_test.rb +11 -8
  343. data/test/cases/relation/order_test.rb +90 -0
  344. data/test/cases/relation/predicate_builder_test.rb +21 -6
  345. data/test/cases/relation/select_test.rb +162 -3
  346. data/test/cases/relation/structural_compatibility_test.rb +38 -0
  347. data/test/cases/relation/update_all_test.rb +81 -27
  348. data/test/cases/relation/where_chain_test.rb +190 -3
  349. data/test/cases/relation/where_clause_test.rb +43 -1
  350. data/test/cases/relation/where_test.rb +95 -7
  351. data/test/cases/relation/with_test.rb +165 -0
  352. data/test/cases/relation_test.rb +42 -37
  353. data/test/cases/relations_test.rb +436 -138
  354. data/test/cases/reload_models_test.rb +18 -14
  355. data/test/cases/reserved_word_test.rb +2 -1
  356. data/test/cases/result_test.rb +14 -22
  357. data/test/cases/sanitize_test.rb +89 -27
  358. data/test/cases/schema_dumper_test.rb +535 -62
  359. data/test/cases/scoping/default_scoping_test.rb +219 -35
  360. data/test/cases/scoping/named_scoping_test.rb +25 -46
  361. data/test/cases/scoping/relation_scoping_test.rb +112 -4
  362. data/test/cases/secure_password_test.rb +108 -0
  363. data/test/cases/secure_token_test.rb +72 -0
  364. data/test/cases/serialization_test.rb +1 -1
  365. data/test/cases/serialized_attribute_test.rb +305 -60
  366. data/test/cases/shard_keys_test.rb +125 -0
  367. data/test/cases/shard_selector_test.rb +45 -0
  368. data/test/cases/signed_id_test.rb +57 -5
  369. data/test/cases/statement_cache_test.rb +31 -30
  370. data/test/cases/statement_invalid_test.rb +8 -4
  371. data/test/cases/store_test.rb +73 -9
  372. data/test/cases/strict_loading_test.rb +327 -13
  373. data/test/cases/table_metadata_test.rb +16 -0
  374. data/test/cases/tasks/database_tasks_test.rb +517 -244
  375. data/test/cases/test_case.rb +254 -60
  376. data/test/cases/test_case_test.rb +69 -0
  377. data/test/cases/test_databases_test.rb +7 -3
  378. data/test/cases/test_fixtures_test.rb +19 -40
  379. data/test/cases/time_precision_test.rb +17 -5
  380. data/test/cases/timestamp_test.rb +124 -16
  381. data/test/cases/token_for_test.rb +165 -0
  382. data/test/cases/touch_later_test.rb +43 -1
  383. data/test/cases/transaction_callbacks_test.rb +325 -8
  384. data/test/cases/transaction_instrumentation_test.rb +453 -0
  385. data/test/cases/transaction_isolation_test.rb +12 -8
  386. data/test/cases/transactions_test.rb +629 -112
  387. data/test/cases/type/date_time_test.rb +7 -1
  388. data/test/cases/type/time_test.rb +9 -0
  389. data/test/cases/type/type_map_test.rb +108 -73
  390. data/test/cases/type/unsigned_integer_test.rb +12 -0
  391. data/test/cases/type_caster/connection_test.rb +19 -0
  392. data/test/cases/type_test.rb +1 -1
  393. data/test/cases/unconnected_test.rb +7 -7
  394. data/test/cases/unsafe_raw_sql_test.rb +39 -8
  395. data/test/cases/validations/absence_validation_test.rb +1 -1
  396. data/test/cases/validations/association_validation_test.rb +25 -3
  397. data/test/cases/validations/numericality_validation_test.rb +3 -9
  398. data/test/cases/validations/presence_validation_test.rb +1 -1
  399. data/test/cases/validations/uniqueness_validation_test.rb +280 -40
  400. data/test/cases/validations_test.rb +2 -2
  401. data/test/cases/view_test.rb +33 -22
  402. data/test/cases/yaml_serialization_test.rb +23 -17
  403. data/test/config.example.yml +58 -56
  404. data/test/config.rb +1 -0
  405. data/test/fixtures/1_need_quoting.yml +2 -0
  406. data/test/fixtures/accounts.yml +5 -0
  407. data/test/fixtures/aircrafts.yml +7 -0
  408. data/test/fixtures/book_identifiers.yml +11 -0
  409. data/test/fixtures/books.yml +5 -4
  410. data/test/fixtures/cake_designers.yml +5 -0
  411. data/test/fixtures/cars.yml +6 -0
  412. data/test/fixtures/chefs.yml +5 -0
  413. data/test/fixtures/clothing_items.yml +23 -0
  414. data/test/fixtures/clubs.yml +1 -1
  415. data/test/fixtures/comments.yml +2 -1
  416. data/test/fixtures/cpk_authors.yml +8 -0
  417. data/test/fixtures/cpk_books.yml +21 -0
  418. data/test/fixtures/cpk_order_agreements.yml +13 -0
  419. data/test/fixtures/cpk_order_tags.yml +15 -0
  420. data/test/fixtures/cpk_orders.yml +11 -0
  421. data/test/fixtures/cpk_posts.yml +12 -0
  422. data/test/fixtures/cpk_reviews.yml +13 -0
  423. data/test/fixtures/cpk_tags.yml +11 -0
  424. data/test/fixtures/drink_designers.yml +5 -0
  425. data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
  426. data/test/fixtures/encrypted_books.yml +4 -0
  427. data/test/fixtures/fk_object_to_point_to.yml +2 -0
  428. data/test/fixtures/memberships.yml +15 -15
  429. data/test/fixtures/paragraphs.yml +5 -0
  430. data/test/fixtures/parrots.yml +4 -0
  431. data/test/fixtures/people.yml +2 -0
  432. data/test/fixtures/pirates.yml +2 -2
  433. data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
  434. data/test/fixtures/references.yml +3 -3
  435. data/test/fixtures/sharded_blog_posts.yml +14 -0
  436. data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
  437. data/test/fixtures/sharded_blogs.yml +8 -0
  438. data/test/fixtures/sharded_comments.yml +22 -0
  439. data/test/fixtures/sharded_tags.yml +34 -0
  440. data/test/fixtures/sponsors.yml +2 -2
  441. data/test/fixtures/topics.yml +1 -0
  442. data/test/fixtures/treasures.yml +4 -0
  443. data/test/fixtures/virtual_columns.yml +5 -0
  444. data/test/fixtures/warehouse_things.yml +1 -1
  445. data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
  446. data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
  447. data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
  448. data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
  449. data/test/migrations/scope/1_unscoped.rb +7 -0
  450. data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
  451. data/test/models/admin/user.rb +2 -0
  452. data/test/models/admin/user_json.rb +48 -0
  453. data/test/models/attachment.rb +7 -0
  454. data/test/models/author.rb +70 -3
  455. data/test/models/author_encrypted.rb +16 -0
  456. data/test/models/bird.rb +1 -1
  457. data/test/models/book.rb +18 -11
  458. data/test/models/book_destroy_async.rb +1 -1
  459. data/test/models/book_encrypted.rb +106 -0
  460. data/test/models/book_identifier.rb +5 -0
  461. data/test/models/branch.rb +11 -0
  462. data/test/models/bulb.rb +1 -1
  463. data/test/models/car.rb +8 -1
  464. data/test/models/cat.rb +1 -1
  465. data/test/models/category.rb +3 -1
  466. data/test/models/chat_message.rb +8 -0
  467. data/test/models/chef.rb +52 -0
  468. data/test/models/clothing_item.rb +12 -0
  469. data/test/models/club.rb +4 -1
  470. data/test/models/comment.rb +7 -4
  471. data/test/models/comment_overlapping_counter_cache.rb +15 -0
  472. data/test/models/company.rb +16 -2
  473. data/test/models/computer.rb +1 -0
  474. data/test/models/contact.rb +3 -3
  475. data/test/models/contract.rb +5 -1
  476. data/test/models/cpk/author.rb +9 -0
  477. data/test/models/cpk/book.rb +55 -0
  478. data/test/models/cpk/book_destroy_async.rb +9 -0
  479. data/test/models/cpk/car.rb +9 -0
  480. data/test/models/cpk/car_review.rb +9 -0
  481. data/test/models/cpk/chapter.rb +16 -0
  482. data/test/models/cpk/chapter_destroy_async.rb +10 -0
  483. data/test/models/cpk/comment.rb +9 -0
  484. data/test/models/cpk/order.rb +55 -0
  485. data/test/models/cpk/order_agreement.rb +10 -0
  486. data/test/models/cpk/order_tag.rb +10 -0
  487. data/test/models/cpk/post.rb +10 -0
  488. data/test/models/cpk/posts_tag.rb +10 -0
  489. data/test/models/cpk/review.rb +9 -0
  490. data/test/models/cpk/tag.rb +10 -0
  491. data/test/models/cpk.rb +15 -0
  492. data/test/models/customer.rb +3 -1
  493. data/test/models/destroy_async_parent.rb +1 -1
  494. data/test/models/developer.rb +44 -3
  495. data/test/models/discount.rb +4 -0
  496. data/test/models/drink_designer.rb +1 -0
  497. data/test/models/editor.rb +8 -0
  498. data/test/models/editorship.rb +6 -0
  499. data/test/models/entry.rb +5 -0
  500. data/test/models/essay.rb +6 -1
  501. data/test/models/essay_destroy_async.rb +1 -0
  502. data/test/models/eye.rb +87 -21
  503. data/test/models/face.rb +1 -1
  504. data/test/models/friendship.rb +3 -0
  505. data/test/models/hardback.rb +7 -0
  506. data/test/models/hotel.rb +2 -0
  507. data/test/models/human.rb +2 -2
  508. data/test/models/invoice.rb +2 -1
  509. data/test/models/invokes_an_undefined_method.rb +5 -0
  510. data/test/models/line_item.rb +6 -0
  511. data/test/models/member.rb +9 -4
  512. data/test/models/membership.rb +2 -2
  513. data/test/models/message.rb +2 -1
  514. data/test/models/need_quoting.rb +5 -0
  515. data/test/models/paragraph.rb +5 -0
  516. data/test/models/parrot.rb +6 -3
  517. data/test/models/person.rb +7 -4
  518. data/test/models/pirate.rb +4 -1
  519. data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
  520. data/test/models/post.rb +65 -2
  521. data/test/models/post_encrypted.rb +15 -0
  522. data/test/models/post_with_prefetched_pk.rb +15 -0
  523. data/test/models/project.rb +1 -0
  524. data/test/models/publication.rb +16 -0
  525. data/test/models/raises_argument_error.rb +5 -0
  526. data/test/models/raises_no_method_error.rb +5 -0
  527. data/test/models/recipient.rb +5 -0
  528. data/test/models/reference.rb +1 -1
  529. data/test/models/reply.rb +1 -1
  530. data/test/models/room.rb +3 -0
  531. data/test/models/sharded/blog.rb +12 -0
  532. data/test/models/sharded/blog_post.rb +17 -0
  533. data/test/models/sharded/blog_post_destroy_async.rb +14 -0
  534. data/test/models/sharded/blog_post_tag.rb +11 -0
  535. data/test/models/sharded/blog_post_with_revision.rb +11 -0
  536. data/test/models/sharded/comment.rb +12 -0
  537. data/test/models/sharded/comment_destroy_async.rb +12 -0
  538. data/test/models/sharded/tag.rb +11 -0
  539. data/test/models/sharded.rb +8 -0
  540. data/test/models/ship.rb +1 -1
  541. data/test/models/shipping_line.rb +11 -0
  542. data/test/models/subscriber.rb +1 -0
  543. data/test/models/subscription.rb +3 -1
  544. data/test/models/too_long_table_name.rb +5 -0
  545. data/test/models/topic.rb +3 -1
  546. data/test/models/traffic_light.rb +2 -2
  547. data/test/models/traffic_light_encrypted.rb +21 -0
  548. data/test/models/translation.rb +9 -0
  549. data/test/models/treasure.rb +1 -1
  550. data/test/models/tyre.rb +1 -1
  551. data/test/models/user.rb +16 -0
  552. data/test/models/user_with_invalid_relation.rb +28 -0
  553. data/test/models/uuid_comment.rb +5 -0
  554. data/test/models/uuid_entry.rb +5 -0
  555. data/test/models/uuid_message.rb +5 -0
  556. data/test/models/zine.rb +2 -1
  557. data/test/schema/mysql2_specific_schema.rb +26 -12
  558. data/test/schema/postgresql_specific_schema.rb +121 -13
  559. data/test/schema/schema.rb +361 -103
  560. data/test/schema/sqlite_specific_schema.rb +17 -6
  561. data/test/schema/trilogy_specific_schema.rb +96 -0
  562. data/test/support/adapter_helper.rb +104 -0
  563. data/test/support/async_helper.rb +15 -0
  564. data/test/support/config.rb +1 -1
  565. data/test/support/connection.rb +14 -2
  566. data/test/support/ddl_helper.rb +1 -1
  567. data/test/support/fake_adapter.rb +42 -0
  568. data/test/support/load_schema_helper.rb +22 -0
  569. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
  570. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
  571. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
  572. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
  573. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
  574. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
  575. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
  576. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
  577. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
  578. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
  579. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
  580. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
  581. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
  582. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
  583. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
  584. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
  585. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
  586. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
  587. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
  588. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
  589. data/test/support/schema_dumping_helper.rb +15 -9
  590. data/test/support/tools.rb +37 -0
  591. data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
  592. metadata +247 -15
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+
5
+ class ActiveRecord::Encryption::KeyGeneratorTest < ActiveRecord::EncryptionTestCase
6
+ setup do
7
+ @generator = ActiveRecord::Encryption::KeyGenerator.new
8
+ end
9
+
10
+ test "generate_random_key generates random keys with the cipher key length by default" do
11
+ assert_not_equal @generator.generate_random_key, @generator.generate_random_key
12
+ assert_equal ActiveRecord::Encryption.cipher.key_length, @generator.generate_random_key.bytesize
13
+ end
14
+
15
+ test "generate_random_key generates random keys with a custom length" do
16
+ assert_not_equal @generator.generate_random_key(length: 10), @generator.generate_random_key(length: 10)
17
+ assert_equal 10, @generator.generate_random_key(length: 10).bytesize
18
+ end
19
+
20
+ test "generate_random_hex_key generates random hexadecimal keys with the cipher key length by default" do
21
+ assert_not_equal @generator.generate_random_hex_key, @generator.generate_random_hex_key
22
+ assert_equal ActiveRecord::Encryption.cipher.key_length, [ @generator.generate_random_hex_key ].pack("H*").bytesize
23
+ end
24
+
25
+ test "generate_random_hex_key generates random hexadecimal keys with a custom length" do
26
+ assert_not_equal @generator.generate_random_hex_key(length: 10), @generator.generate_random_hex_key(length: 10)
27
+ assert_equal 10, [ @generator.generate_random_hex_key(length: 10) ].pack("H*").bytesize
28
+ end
29
+
30
+ test "derive keys using the configured digest algorithm" do
31
+ assert_derive_key "some secret", digest_class: OpenSSL::Digest::SHA1
32
+ assert_derive_key "some secret", digest_class: OpenSSL::Digest::SHA256
33
+ end
34
+
35
+ test "derive_key derives a key with from the provided password with the cipher key length by default" do
36
+ assert_equal @generator.derive_key_from("some password"), @generator.derive_key_from("some password")
37
+ assert_not_equal @generator.derive_key_from("some password"), @generator.derive_key_from("some other password")
38
+ assert_equal ActiveRecord::Encryption.cipher.key_length, @generator.derive_key_from("some password").length
39
+ end
40
+
41
+ test "derive_key derives a key with a custom length" do
42
+ assert_equal @generator.derive_key_from("some password", length: 12), @generator.derive_key_from("some password", length: 12)
43
+ assert_not_equal @generator.derive_key_from("some password", length: 12), @generator.derive_key_from("some other password", length: 12)
44
+ assert_equal 12, @generator.derive_key_from("some password", length: 12).length
45
+ end
46
+
47
+ private
48
+ def assert_derive_key(secret, digest_class: OpenSSL::Digest::SHA256, length: 20)
49
+ expected_derived_key = ActiveSupport::KeyGenerator.new(secret, hash_digest_class: digest_class)
50
+ .generate_key(ActiveRecord::Encryption.config.key_derivation_salt, length)
51
+ assert_equal length, expected_derived_key.length
52
+ ActiveRecord::Encryption.config.hash_digest_class = digest_class
53
+ assert_equal expected_derived_key, ActiveRecord::Encryption::KeyGenerator.new(hash_digest_class: digest_class).derive_key_from(secret, length: length)
54
+ end
55
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+
5
+ class ActiveRecord::Encryption::KeyProviderTest < ActiveRecord::EncryptionTestCase
6
+ setup do
7
+ @message ||= ActiveRecord::Encryption::Message.new(payload: "some secret")
8
+ @keys = build_keys(3)
9
+ @key_provider = ActiveRecord::Encryption::KeyProvider.new(@keys)
10
+ end
11
+
12
+ test "serves a single key for encrypting and decrypting" do
13
+ key = @keys.first
14
+ key_provider = ActiveRecord::Encryption::KeyProvider.new(key)
15
+
16
+ assert_equal key, key_provider.encryption_key
17
+ assert_equal [ key_provider.encryption_key ], key_provider.decryption_keys(@message)
18
+ end
19
+
20
+ test "serves the last key for encrypting" do
21
+ assert_equal @keys.last, @key_provider.encryption_key
22
+ end
23
+
24
+ test "when store_key_references is false, the encryption key contains a reference to the key itself" do
25
+ assert_nil @key_provider.encryption_key.public_tags.encrypted_data_key_id
26
+ end
27
+
28
+ test "when store_key_references is true, the encryption key contains a reference to the key itself" do
29
+ ActiveRecord::Encryption.config.store_key_references = true
30
+
31
+ assert_equal @keys.last.id, @key_provider.encryption_key.public_tags.encrypted_data_key_id
32
+ end
33
+
34
+ test "when the message does not contain any key reference, it returns all the keys" do
35
+ assert_equal @keys, @key_provider.decryption_keys(@message)
36
+ end
37
+
38
+ test "when the message to decrypt contains a reference to the key id, it will return an array only with that message" do
39
+ target_key = @keys[1]
40
+
41
+ @message.headers.encrypted_data_key_id = target_key.id
42
+
43
+ assert_equal [target_key], @key_provider.decryption_keys(@message)
44
+ end
45
+
46
+ test "work with multiple keys when config.store_key_references is false" do
47
+ ActiveRecord::Encryption.config.store_key_references = false
48
+
49
+ assert_encryptor_works_with @key_provider
50
+ end
51
+
52
+ test "work with multiple keys when config.store_key_references is true" do
53
+ ActiveRecord::Encryption.config.store_key_references = true
54
+
55
+ assert_encryptor_works_with @key_provider
56
+ end
57
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+
5
+ class ActiveRecord::Encryption::KeyTest < ActiveRecord::EncryptionTestCase
6
+ test "A key can store a secret and public tags" do
7
+ key = ActiveRecord::Encryption::Key.new("the secret")
8
+ key.public_tags[:key] = "the key reference"
9
+
10
+ assert_equal "the secret", key.secret
11
+ assert_equal "the key reference", key.public_tags[:key]
12
+ end
13
+
14
+ test ".derive_from instantiates a key with its secret derived from the passed password" do
15
+ assert_equal ActiveRecord::Encryption.key_generator.derive_key_from("some password"), ActiveRecord::Encryption::Key.derive_from("some password").secret
16
+ end
17
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+ require "base64"
5
+ require "active_record/encryption/message_pack_message_serializer"
6
+
7
+ class ActiveRecord::Encryption::MessagePackMessageSerializerTest < ActiveRecord::EncryptionTestCase
8
+ setup do
9
+ @serializer = ActiveRecord::Encryption::MessagePackMessageSerializer.new
10
+ end
11
+
12
+ test "serializes messages" do
13
+ message = build_message
14
+ deserialized_message = serialize_and_deserialize(message)
15
+ assert_equal message, deserialized_message
16
+ end
17
+
18
+ test "serializes messages with nested messages in their headers" do
19
+ message = build_message
20
+ message.headers[:other_message] = ActiveRecord::Encryption::Message.new(payload: "some other secret payload", headers: { some_header: "some other value" })
21
+
22
+ deserialized_message = serialize_and_deserialize(message)
23
+ assert_equal message, deserialized_message
24
+ end
25
+
26
+ test "detects random data and raises a decryption error" do
27
+ assert_raises ActiveRecord::Encryption::Errors::Decryption do
28
+ @serializer.load "hey there"
29
+ end
30
+ end
31
+
32
+ test "detects random JSON hashes and raises a decryption error" do
33
+ assert_raises ActiveRecord::Encryption::Errors::Decryption do
34
+ @serializer.load JSON.dump({ some: "other data" })
35
+ end
36
+ end
37
+
38
+ test "raises a TypeError when trying to deserialize other data types" do
39
+ assert_raises TypeError do
40
+ @serializer.load(:it_can_only_deserialize_strings)
41
+ end
42
+ end
43
+
44
+ test "raises ForbiddenClass when trying to serialize other data types" do
45
+ assert_raises ActiveRecord::Encryption::Errors::ForbiddenClass do
46
+ @serializer.dump("it can only serialize messages!")
47
+ end
48
+ end
49
+
50
+ test "raises Decryption when trying to parse message with more than one nested message" do
51
+ message = build_message
52
+ message.headers[:other_message] = ActiveRecord::Encryption::Message.new(payload: "some other secret payload", headers: { some_header: "some other value" })
53
+ message.headers[:other_message].headers[:yet_another_message] = ActiveRecord::Encryption::Message.new(payload: "yet some other secret payload", headers: { some_header: "yet some other value" })
54
+
55
+ assert_raises ActiveRecord::Encryption::Errors::Decryption do
56
+ serialize_and_deserialize(message)
57
+ end
58
+ end
59
+
60
+ private
61
+ def build_message
62
+ payload = "some payload"
63
+ headers = { key_1: "1" }
64
+ ActiveRecord::Encryption::Message.new(payload: payload, headers: headers)
65
+ end
66
+
67
+ def serialize_and_deserialize(message, with: @serializer)
68
+ @serializer.load @serializer.dump(message)
69
+ end
70
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+ require "base64"
5
+
6
+ class ActiveRecord::Encryption::MessageSerializerTest < ActiveRecord::EncryptionTestCase
7
+ setup do
8
+ @serializer = ActiveRecord::Encryption::MessageSerializer.new
9
+ end
10
+
11
+ test "serializes messages" do
12
+ message = build_message
13
+ deserialized_message = serialize_and_deserialize(message)
14
+ assert_equal message, deserialized_message
15
+ end
16
+
17
+ test "serializes messages with nested messages in their headers" do
18
+ message = build_message
19
+ message.headers[:other_message] = ActiveRecord::Encryption::Message.new(payload: "some other secret payload", headers: { some_header: "some other value" })
20
+
21
+ deserialized_message = serialize_and_deserialize(message)
22
+ assert_equal message, deserialized_message
23
+ end
24
+
25
+ test "won't load classes from JSON" do
26
+ class_loading_payload = JSON.dump({ p: ::Base64.strict_encode64("Some payload"), json_class: "MessageSerializerTest::SomeClassThatWillNeverExist" })
27
+
28
+ assert_raises(ArgumentError) { JSON.load(class_loading_payload) }
29
+ assert_nothing_raised { @serializer.load(class_loading_payload) }
30
+ end
31
+
32
+ test "detects random JSON data and raises a decryption error" do
33
+ assert_raises ActiveRecord::Encryption::Errors::Decryption do
34
+ @serializer.load JSON.dump("hey there")
35
+ end
36
+ end
37
+
38
+ test "detects random JSON hashes and raises a decryption error" do
39
+ assert_raises ActiveRecord::Encryption::Errors::Decryption do
40
+ @serializer.load JSON.dump({ some: "other data" })
41
+ end
42
+ end
43
+
44
+ test "detects JSON hashes with a 'p' key that is not encoded in base64" do
45
+ assert_raises ActiveRecord::Encryption::Errors::Encoding do
46
+ @serializer.load JSON.dump({ p: "some data not encoded" })
47
+ end
48
+ end
49
+
50
+ test "raises a TypeError when trying to deserialize other data types" do
51
+ assert_raises TypeError do
52
+ @serializer.load(:it_can_only_deserialize_strings)
53
+ end
54
+ end
55
+
56
+ test "raises ForbiddenClass when trying to serialize other data types" do
57
+ assert_raises ActiveRecord::Encryption::Errors::ForbiddenClass do
58
+ @serializer.dump("it can only serialize messages!")
59
+ end
60
+ end
61
+
62
+ test "raises Decryption when trying to parse message with more than one nested message" do
63
+ message = build_message
64
+ message.headers[:other_message] = ActiveRecord::Encryption::Message.new(payload: "some other secret payload", headers: { some_header: "some other value" })
65
+ message.headers[:other_message].headers[:yet_another_message] = ActiveRecord::Encryption::Message.new(payload: "yet some other secret payload", headers: { some_header: "yet some other value" })
66
+
67
+ assert_raises ActiveRecord::Encryption::Errors::Decryption do
68
+ serialize_and_deserialize(message)
69
+ end
70
+ end
71
+
72
+ private
73
+ def build_message
74
+ payload = "some payload"
75
+ headers = { key_1: "1" }
76
+ ActiveRecord::Encryption::Message.new(payload: payload, headers: headers)
77
+ end
78
+
79
+ def serialize_and_deserialize(message, with: @serializer)
80
+ @serializer.load @serializer.dump(message)
81
+ end
82
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+
5
+ class ActiveRecord::Encryption::MessageTest < ActiveRecord::EncryptionTestCase
6
+ test "add_header lets you add headers" do
7
+ message = ActiveRecord::Encryption::Message.new
8
+ message.headers[:header_1] = "value 1"
9
+
10
+ assert_equal "value 1", message.headers[:header_1]
11
+ end
12
+
13
+ test "add_headers lets you add multiple headers" do
14
+ message = ActiveRecord::Encryption::Message.new
15
+ message.headers.add(header_1: "value 1", header_2: "value 2")
16
+ assert_equal "value 1", message.headers[:header_1]
17
+ assert_equal "value 2", message.headers[:header_2]
18
+ end
19
+
20
+ test "headers can't be overridden" do
21
+ message = ActiveRecord::Encryption::Message.new
22
+ message.headers.add(header_1: "value 1")
23
+
24
+ assert_raises(ActiveRecord::Encryption::Errors::EncryptedContentIntegrity) do
25
+ message.headers.add(header_1: "value 1")
26
+ end
27
+
28
+ assert_raises(ActiveRecord::Encryption::Errors::EncryptedContentIntegrity) do
29
+ message.headers.add(header_1: "value 1")
30
+ end
31
+ end
32
+
33
+ test "validates that payloads are either nil or strings" do
34
+ assert_raises ActiveRecord::Encryption::Errors::ForbiddenClass do
35
+ ActiveRecord::Encryption::Message.new(payload: Date.new)
36
+ ActiveRecord::Encryption::Message.new(payload: [])
37
+ end
38
+
39
+ ActiveRecord::Encryption::Message.new
40
+ ActiveRecord::Encryption::Message.new(payload: "")
41
+ ActiveRecord::Encryption::Message.new(payload: "Some payload")
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+
5
+ class ActiveRecord::Encryption::NullEncryptorTest < ActiveRecord::EncryptionTestCase
6
+ setup do
7
+ @encryptor = ActiveRecord::Encryption::NullEncryptor.new
8
+ end
9
+
10
+ test "encrypt returns the passed data" do
11
+ assert_equal "Some data", @encryptor.encrypt("Some data")
12
+ end
13
+
14
+ test "decrypt returns the passed data" do
15
+ assert_equal "Some data", @encryptor.decrypt("Some data")
16
+ end
17
+
18
+ test "encrypted? returns false" do
19
+ assert_not @encryptor.encrypted?("Some data")
20
+ end
21
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+
5
+ class ActiveRecord::EncryptionPropertiesTest < ActiveRecord::EncryptionTestCase
6
+ setup do
7
+ @properties = ActiveRecord::Encryption::Properties.new
8
+ end
9
+
10
+ test "behaves like a hash" do
11
+ @properties[:key_1] = "value 1"
12
+ @properties[:key_2] = "value 2"
13
+
14
+ assert_equal "value 1", @properties[:key_1]
15
+ assert_equal "value 2", @properties[:key_2]
16
+ end
17
+
18
+ test "defines custom accessors for some default properties" do
19
+ auth_tag = "some auth tag"
20
+
21
+ @properties.auth_tag = auth_tag
22
+ assert_equal auth_tag, @properties.auth_tag
23
+ assert_equal auth_tag, @properties[:at]
24
+ end
25
+
26
+ test "raises EncryptedContentIntegrity when trying to override properties" do
27
+ @properties[:key_1] = "value 1"
28
+
29
+ assert_raises ActiveRecord::Encryption::Errors::EncryptedContentIntegrity do
30
+ @properties[:key_1] = "value 1"
31
+ end
32
+ end
33
+
34
+ test "add will add all the properties passed" do
35
+ @properties.add(key_1: "value 1", key_2: "value 2")
36
+
37
+ assert_equal "value 1", @properties[:key_1]
38
+ assert_equal "value 2", @properties[:key_2]
39
+ end
40
+
41
+ test "validate allowed types on creation" do
42
+ example_of_valid_values.each do |value|
43
+ ActiveRecord::Encryption::Properties.new(some_value: value)
44
+ end
45
+
46
+ assert_raises ActiveRecord::Encryption::Errors::ForbiddenClass do
47
+ ActiveRecord::Encryption::Properties.new(my_class: MyClass.new)
48
+ end
49
+ end
50
+
51
+ test "validate allowed_types setting headers" do
52
+ example_of_valid_values.each.with_index do |value, index|
53
+ @properties["some_value_#{index}"] = value
54
+ end
55
+
56
+ assert_raises ActiveRecord::Encryption::Errors::ForbiddenClass do
57
+ @properties["some_value"] = MyClass.new
58
+ end
59
+ end
60
+
61
+ MyClass = Struct.new(:some_value)
62
+
63
+ class EncryptionMessageSubClass < ActiveRecord::Encryption::Message
64
+ end
65
+
66
+ def example_of_valid_values
67
+ ["a string", 123, 123.5, true, false, nil, :a_symbol, ActiveRecord::Encryption::Message.new, EncryptionMessageSubClass.new]
68
+ end
69
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+
5
+ class ActiveRecord::Encryption::ReadOnlyNullEncryptorTest < ActiveRecord::EncryptionTestCase
6
+ setup do
7
+ @encryptor = ActiveRecord::Encryption::ReadOnlyNullEncryptor.new
8
+ end
9
+
10
+ test "decrypt returns the encrypted message" do
11
+ assert_equal "some text", @encryptor.decrypt("some text")
12
+ end
13
+
14
+ test "encrypt raises an Encryption" do
15
+ assert_raises ActiveRecord::Encryption::Errors::Encryption do
16
+ @encryptor.encrypt("some text")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+ require "models/book"
5
+
6
+ class ActiveRecord::Encryption::SchemeTest < ActiveRecord::EncryptionTestCase
7
+ test "validates config options when using encrypted attributes" do
8
+ assert_invalid_declaration deterministic: false, ignore_case: true
9
+ assert_invalid_declaration key: "1234", key_provider: ActiveRecord::Encryption::DerivedSecretKeyProvider.new("my secret")
10
+ assert_invalid_declaration compress: false, compressor: Zlib
11
+ assert_invalid_declaration compressor: Zlib, encryptor: ActiveRecord::Encryption::Encryptor.new
12
+
13
+ assert_valid_declaration deterministic: true
14
+ assert_valid_declaration key: "1234"
15
+ assert_valid_declaration key_provider: ActiveRecord::Encryption::DerivedSecretKeyProvider.new("my secret")
16
+ end
17
+
18
+ test "should create a encryptor well when compressor is given" do
19
+ MyCompressor = Class.new do
20
+ def self.deflate(data)
21
+ "deflated #{data}"
22
+ end
23
+
24
+ def self.inflate(data)
25
+ data.sub("deflated ", "")
26
+ end
27
+ end
28
+
29
+ type = declare_encrypts_with compressor: MyCompressor
30
+
31
+ assert_equal MyCompressor, type.scheme.to_h[:encryptor].compressor
32
+ end
33
+
34
+ test "should create a encryptor well when compress is false" do
35
+ type = declare_encrypts_with compress: false
36
+
37
+ assert_not type.scheme.to_h[:encryptor].compress?
38
+ end
39
+
40
+ private
41
+ def assert_invalid_declaration(**options)
42
+ assert_raises ActiveRecord::Encryption::Errors::Configuration do
43
+ declare_encrypts_with(options)
44
+ end
45
+ end
46
+
47
+ def assert_valid_declaration(**options)
48
+ assert_nothing_raised do
49
+ declare_encrypts_with(options)
50
+ end
51
+ end
52
+
53
+ def declare_encrypts_with(options)
54
+ Class.new(Book) do
55
+ encrypts :name, **options
56
+ end.type_for_attribute(:name)
57
+ end
58
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+ require "models/post_encrypted"
5
+
6
+ class ActiveRecord::Encryption::UnencryptedAttributesTest < ActiveRecord::EncryptionTestCase
7
+ test "when :support_unencrypted_data is off, it works with unencrypted attributes normally" do
8
+ ActiveRecord::Encryption.config.support_unencrypted_data = true
9
+
10
+ post = ActiveRecord::Encryption.without_encryption { EncryptedPost.create!(title: "The Starfleet is here!", body: "take cover!") }
11
+ assert_not_encrypted_attribute(post, :title, "The Starfleet is here!")
12
+
13
+ # It will encrypt on saving
14
+ post.update! title: "Other title"
15
+ assert_encrypted_attribute(post.reload, :title, "Other title")
16
+ end
17
+
18
+ test "when :support_unencrypted_data is on, it won't work with unencrypted attributes" do
19
+ ActiveRecord::Encryption.config.support_unencrypted_data = false
20
+
21
+ post = ActiveRecord::Encryption.without_encryption { EncryptedPost.create!(title: "The Starfleet is here!", body: "take cover!") }
22
+
23
+ assert_raises ActiveRecord::Encryption::Errors::Decryption do
24
+ post.title
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/encryption/helper"
4
+ require "models/book_encrypted"
5
+ require "models/author_encrypted"
6
+
7
+ class ActiveRecord::Encryption::UniquenessValidationsTest < ActiveRecord::EncryptionTestCase
8
+ test "uniqueness validations work" do
9
+ EncryptedBookWithDowncaseName.create!(name: "dune")
10
+ assert_raises ActiveRecord::RecordInvalid do
11
+ EncryptedBookWithDowncaseName.create!(name: "dune")
12
+ end
13
+ end
14
+
15
+ test "uniqueness validations work when mixing encrypted an unencrypted data" do
16
+ ActiveRecord::Encryption.config.support_unencrypted_data = true
17
+
18
+ UnencryptedBook.create! name: "dune"
19
+ assert_raises ActiveRecord::RecordInvalid do
20
+ EncryptedBookWithDowncaseName.create!(name: "DUNE")
21
+ end
22
+ end
23
+
24
+ test "uniqueness validations do not work when mixing encrypted an unencrypted data and unencrypted data is opted out per-attribute" do
25
+ ActiveRecord::Encryption.config.support_unencrypted_data = true
26
+
27
+ UnencryptedBook.create! name: "dune"
28
+ assert_nothing_raised do
29
+ EncryptedBookWithUnencryptedDataOptedOut.create!(name: "dune")
30
+ end
31
+ end
32
+
33
+ test "uniqueness validations work when mixing encrypted an unencrypted data and unencrypted data is opted in per-attribute" do
34
+ ActiveRecord::Encryption.config.support_unencrypted_data = true
35
+
36
+ UnencryptedBook.create! name: "dune"
37
+ assert_raises ActiveRecord::RecordInvalid do
38
+ EncryptedBookWithUnencryptedDataOptedIn.create!(name: "dune")
39
+ end
40
+ end
41
+
42
+ test "uniqueness validations work when using old encryption schemes" do
43
+ ActiveRecord::Encryption.config.previous = [ { downcase: true, deterministic: true } ]
44
+
45
+ OldEncryptionBook = Class.new(UnencryptedBook) do
46
+ self.table_name = "encrypted_books"
47
+
48
+ validates :name, uniqueness: true
49
+ encrypts :name, deterministic: true, downcase: false
50
+ end
51
+
52
+ OldEncryptionBook.create! name: "dune"
53
+
54
+ assert_raises ActiveRecord::RecordInvalid do
55
+ OldEncryptionBook.create! name: "DUNE"
56
+ end
57
+ end
58
+
59
+ test "uniqueness validation does not revalidate the attribute with current encryption type" do
60
+ EncryptedBookWithUniquenessValidation.create!(name: "dune")
61
+ record = EncryptedBookWithUniquenessValidation.create(name: "dune")
62
+
63
+ assert_equal 1, record.errors.count
64
+ end
65
+ end