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
@@ -1,91 +1,183 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../../tools/strict_warnings"
3
4
  require "active_support"
4
5
  require "active_support/testing/autorun"
5
6
  require "active_support/testing/method_call_assertions"
6
7
  require "active_support/testing/stream"
8
+ require "active_record/testing/query_assertions"
7
9
  require "active_record/fixtures"
8
10
 
9
11
  require "cases/validations_repair_helper"
12
+ require_relative "../config"
13
+ require_relative "../support/config"
14
+ require_relative "../support/connection"
15
+ require_relative "../support/adapter_helper"
16
+ require_relative "../support/load_schema_helper"
10
17
 
11
18
  module ActiveRecord
12
19
  # = Active Record Test Case
13
20
  #
14
21
  # Defines some test assertions to test against SQL queries.
15
- class TestCase < ActiveSupport::TestCase #:nodoc:
22
+ class TestCase < ActiveSupport::TestCase # :nodoc:
16
23
  include ActiveSupport::Testing::MethodCallAssertions
17
24
  include ActiveSupport::Testing::Stream
25
+ include ActiveRecord::Assertions::QueryAssertions
18
26
  include ActiveRecord::TestFixtures
19
27
  include ActiveRecord::ValidationsRepairHelper
28
+ include AdapterHelper
29
+ extend AdapterHelper
30
+ include LoadSchemaHelper
31
+ extend LoadSchemaHelper
20
32
 
21
- self.fixture_path = FIXTURES_ROOT
33
+ self.fixture_paths = [FIXTURES_ROOT]
22
34
  self.use_instantiated_fixtures = false
23
35
  self.use_transactional_tests = true
24
36
 
25
- def create_fixtures(*fixture_set_names, &block)
26
- ActiveRecord::FixtureSet.create_fixtures(ActiveRecord::TestCase.fixture_path, fixture_set_names, fixture_class_names, &block)
37
+ def after_teardown
38
+ super
39
+ check_connection_leaks
27
40
  end
28
41
 
29
- def teardown
30
- SQLCounter.clear_log
42
+ def check_connection_leaks
43
+ return if in_memory_db?
44
+
45
+ # Make sure tests didn't leave a connection owned by some background thread
46
+ # which could lead to some slow wait in a subsequent thread.
47
+ leaked_conn = []
48
+ ActiveRecord::Base.connection_handler.each_connection_pool do |pool|
49
+ # Ensure all in flights tasks are completed.
50
+ # Otherwise they may still hold a connection.
51
+ if pool.async_executor
52
+ if pool.async_executor.scheduled_task_count != pool.async_executor.completed_task_count
53
+ pool.connections.each do |conn|
54
+ if conn.in_use? && conn.owner != Fiber.current && conn.owner != Thread.current
55
+ if conn.owner.respond_to?(:join)
56
+ conn.owner&.join(0.5)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ # Avoid racing the pool reaper while it is performing maintenance.
64
+ pool.reaper_lock do
65
+ pool.reap
66
+ pool.connections.each do |conn|
67
+ if conn.in_use?
68
+ if conn.owner != Fiber.current && conn.owner != Thread.current
69
+ leaked_conn << [conn.owner, conn.owner.backtrace]
70
+ conn.owner&.kill
71
+ end
72
+ conn.steal!
73
+ pool.checkin(conn)
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ if leaked_conn.size > 0
80
+ puts "Found #{leaked_conn.size} leaked connections"
81
+ leaked_conn.each do |owner, backtrace|
82
+ puts "owner: #{owner}"
83
+ puts "backtrace:\n#{backtrace}"
84
+ puts
85
+ end
86
+ raise "Found #{leaked_conn.size} leaked connection after #{self.class.name}##{name}"
87
+ end
31
88
  end
32
89
 
33
- def capture_sql
34
- ActiveRecord::Base.connection.materialize_transactions
35
- SQLCounter.clear_log
36
- yield
37
- SQLCounter.log.dup
90
+ def create_fixtures(*fixture_set_names)
91
+ ActiveRecord::FixtureSet.create_fixtures(ActiveRecord::TestCase.fixture_paths, fixture_set_names, fixture_class_names)
38
92
  end
39
93
 
40
- def assert_sql(*patterns_to_match)
41
- capture_sql { yield }
42
- ensure
43
- failed_patterns = []
44
- patterns_to_match.each do |pattern|
45
- failed_patterns << pattern unless SQLCounter.log_all.any? { |sql| pattern === sql }
94
+ def capture_sql(include_schema: false)
95
+ counter = SQLCounter.new
96
+ ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
97
+ yield
98
+ if include_schema
99
+ counter.log_all
100
+ else
101
+ counter.log
102
+ end
46
103
  end
47
- assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}"
48
104
  end
49
105
 
50
- def assert_queries(num = 1, options = {})
51
- ignore_none = options.fetch(:ignore_none) { num == :any }
52
- ActiveRecord::Base.connection.materialize_transactions
53
- SQLCounter.clear_log
54
- x = yield
55
- the_log = ignore_none ? SQLCounter.log_all : SQLCounter.log
56
- if num == :any
57
- assert_operator the_log.size, :>=, 1, "1 or more queries expected, but none were executed."
58
- else
59
- mesg = "#{the_log.size} instead of #{num} queries were executed.#{the_log.size == 0 ? '' : "\nQueries:\n#{the_log.join("\n")}"}"
60
- assert_equal num, the_log.size, mesg
106
+ def capture_sql_and_binds
107
+ counter = SQLCounter.new
108
+ ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
109
+ yield
110
+ counter.log_full
61
111
  end
62
- x
63
112
  end
64
113
 
65
- def assert_no_queries(options = {}, &block)
66
- options.reverse_merge! ignore_none: true
67
- assert_queries(0, options, &block)
114
+ # Redefine existing assertion method to explicitly not materialize transactions.
115
+ def assert_queries_match(match, count: nil, include_schema: false, &block)
116
+ counter = SQLCounter.new
117
+ ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
118
+ result = _assert_nothing_raised_or_warn("assert_queries_match", &block)
119
+ queries = include_schema ? counter.log_all : counter.log
120
+ matched_queries = queries.select { |query| match === query }
121
+
122
+ if count
123
+ assert_equal count, matched_queries.size, "#{matched_queries.size} instead of #{count} queries were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
124
+ else
125
+ assert_operator matched_queries.size, :>=, 1, "1 or more queries expected, but none were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
126
+ end
127
+
128
+ result
129
+ end
68
130
  end
69
131
 
70
132
  def assert_column(model, column_name, msg = nil)
71
- assert has_column?(model, column_name), msg
133
+ model.reset_column_information
134
+ assert_includes model.column_names, column_name.to_s, msg
72
135
  end
73
136
 
74
137
  def assert_no_column(model, column_name, msg = nil)
75
- assert_not has_column?(model, column_name), msg
138
+ model.reset_column_information
139
+ assert_not_includes model.column_names, column_name.to_s, msg
76
140
  end
77
141
 
78
- def has_column?(model, column_name)
79
- model.reset_column_information
80
- model.column_names.include?(column_name.to_s)
142
+ def with_has_many_inversing(model = ActiveRecord::Base)
143
+ old = model.has_many_inversing
144
+ model.has_many_inversing = true
145
+ yield
146
+ ensure
147
+ model.has_many_inversing = old
81
148
  end
82
149
 
83
- def with_has_many_inversing
84
- old = ActiveRecord::Base.has_many_inversing
85
- ActiveRecord::Base.has_many_inversing = true
150
+ def with_automatic_scope_inversing(*reflections)
151
+ old = reflections.map { |reflection| reflection.klass.automatic_scope_inversing }
152
+
153
+ reflections.each do |reflection|
154
+ reflection.klass.automatic_scope_inversing = true
155
+ reflection.remove_instance_variable(:@inverse_name) if reflection.instance_variable_defined?(:@inverse_name)
156
+ reflection.remove_instance_variable(:@inverse_of) if reflection.instance_variable_defined?(:@inverse_of)
157
+ end
158
+
86
159
  yield
87
160
  ensure
88
- ActiveRecord::Base.has_many_inversing = old
161
+ reflections.each_with_index do |reflection, i|
162
+ reflection.klass.automatic_scope_inversing = old[i]
163
+ reflection.remove_instance_variable(:@inverse_name) if reflection.instance_variable_defined?(:@inverse_name)
164
+ reflection.remove_instance_variable(:@inverse_of) if reflection.instance_variable_defined?(:@inverse_of)
165
+ end
166
+ end
167
+
168
+ def with_db_warnings_action(action, warnings_to_ignore = [])
169
+ original_db_warnings_ignore = ActiveRecord.db_warnings_ignore
170
+
171
+ ActiveRecord.db_warnings_action = action
172
+ ActiveRecord.db_warnings_ignore = warnings_to_ignore
173
+
174
+ ActiveRecord::Base.lease_connection.disconnect! # Disconnect from the db so that we reconfigure the connection
175
+
176
+ yield
177
+ ensure
178
+ ActiveRecord.db_warnings_action = @original_db_warnings_action
179
+ ActiveRecord.db_warnings_ignore = original_db_warnings_ignore
180
+ ActiveRecord::Base.lease_connection.disconnect!
89
181
  end
90
182
 
91
183
  def reset_callbacks(klass, kind)
@@ -101,6 +193,115 @@ module ActiveRecord
101
193
  subclass.send("_#{kind}_callbacks=", old_callbacks[subclass])
102
194
  end
103
195
  end
196
+
197
+ def with_postgresql_datetime_type(type)
198
+ adapter = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
199
+ adapter.remove_instance_variable(:@native_database_types) if adapter.instance_variable_defined?(:@native_database_types)
200
+ datetime_type_was = adapter.datetime_type
201
+ adapter.datetime_type = type
202
+ yield
203
+ ensure
204
+ adapter = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
205
+ adapter.datetime_type = datetime_type_was
206
+ adapter.remove_instance_variable(:@native_database_types) if adapter.instance_variable_defined?(:@native_database_types)
207
+ end
208
+
209
+ def with_env_tz(new_tz = "US/Eastern")
210
+ old_tz, ENV["TZ"] = ENV["TZ"], new_tz
211
+ yield
212
+ ensure
213
+ old_tz ? ENV["TZ"] = old_tz : ENV.delete("TZ")
214
+ end
215
+
216
+ def with_timezone_config(cfg)
217
+ verify_default_timezone_config
218
+
219
+ old_default_zone = ActiveRecord.default_timezone
220
+ old_awareness = ActiveRecord::Base.time_zone_aware_attributes
221
+ old_aware_types = ActiveRecord::Base.time_zone_aware_types
222
+ old_zone = Time.zone
223
+
224
+ if cfg.has_key?(:default)
225
+ ActiveRecord.default_timezone = cfg[:default]
226
+ end
227
+ if cfg.has_key?(:aware_attributes)
228
+ ActiveRecord::Base.time_zone_aware_attributes = cfg[:aware_attributes]
229
+ end
230
+ if cfg.has_key?(:aware_types)
231
+ ActiveRecord::Base.time_zone_aware_types = cfg[:aware_types]
232
+ end
233
+ if cfg.has_key?(:zone)
234
+ Time.zone = cfg[:zone]
235
+ end
236
+ yield
237
+ ensure
238
+ ActiveRecord.default_timezone = old_default_zone
239
+ ActiveRecord::Base.time_zone_aware_attributes = old_awareness
240
+ ActiveRecord::Base.time_zone_aware_types = old_aware_types
241
+ Time.zone = old_zone
242
+ end
243
+
244
+ # This method makes sure that tests don't leak global state related to time zones.
245
+ EXPECTED_ZONE = nil
246
+ EXPECTED_DEFAULT_TIMEZONE = :utc
247
+ EXPECTED_AWARE_TYPES = [:datetime, :time]
248
+ EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES = false
249
+ def verify_default_timezone_config
250
+ if Time.zone != EXPECTED_ZONE
251
+ $stderr.puts <<-MSG
252
+ \n#{self}
253
+ Global state `Time.zone` was leaked.
254
+ Expected: #{EXPECTED_ZONE}
255
+ Got: #{Time.zone}
256
+ MSG
257
+ end
258
+ if ActiveRecord.default_timezone != EXPECTED_DEFAULT_TIMEZONE
259
+ $stderr.puts <<-MSG
260
+ \n#{self}
261
+ Global state `ActiveRecord.default_timezone` was leaked.
262
+ Expected: #{EXPECTED_DEFAULT_TIMEZONE}
263
+ Got: #{ActiveRecord.default_timezone}
264
+ MSG
265
+ end
266
+ if ActiveRecord::Base.time_zone_aware_attributes != EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES
267
+ $stderr.puts <<-MSG
268
+ \n#{self}
269
+ Global state `ActiveRecord::Base.time_zone_aware_attributes` was leaked.
270
+ Expected: #{EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES}
271
+ Got: #{ActiveRecord::Base.time_zone_aware_attributes}
272
+ MSG
273
+ end
274
+ if ActiveRecord::Base.time_zone_aware_types != EXPECTED_AWARE_TYPES
275
+ $stderr.puts <<-MSG
276
+ \n#{self}
277
+ Global state `ActiveRecord::Base.time_zone_aware_types` was leaked.
278
+ Expected: #{EXPECTED_AWARE_TYPES}
279
+ Got: #{ActiveRecord::Base.time_zone_aware_types}
280
+ MSG
281
+ end
282
+ end
283
+
284
+ def clean_up_connection_handler
285
+ handler = ActiveRecord::Base.connection_handler
286
+ handler.instance_variable_get(:@connection_name_to_pool_manager).each do |owner, pool_manager|
287
+ pool_manager.role_names.each do |role_name|
288
+ next if role_name == ActiveRecord::Base.default_role &&
289
+ # TODO: Remove this helper when `remove_connection` for different shards is fixed.
290
+ # See https://github.com/rails/rails/pull/49382.
291
+ ["ActiveRecord::Base", "ARUnit2Model", "Contact", "ContactSti"].include?(owner)
292
+ pool_manager.remove_role(role_name)
293
+ end
294
+ end
295
+ end
296
+
297
+ def quote_table_name(name)
298
+ ActiveRecord::Base.adapter_class.quote_table_name(name)
299
+ end
300
+
301
+ # Connect to the database
302
+ ARTest.connect
303
+ # Load database schema
304
+ load_schema
104
305
  end
105
306
 
106
307
  class PostgreSQLTestCase < TestCase
@@ -109,34 +310,27 @@ module ActiveRecord
109
310
  end
110
311
  end
111
312
 
112
- class Mysql2TestCase < TestCase
313
+ class AbstractMysqlTestCase < TestCase
113
314
  def self.run(*args)
114
- super if current_adapter?(:Mysql2Adapter)
315
+ super if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
115
316
  end
116
317
  end
117
318
 
118
- class SQLite3TestCase < TestCase
319
+ class Mysql2TestCase < TestCase
119
320
  def self.run(*args)
120
- super if current_adapter?(:SQLite3Adapter)
321
+ super if current_adapter?(:Mysql2Adapter)
121
322
  end
122
323
  end
123
324
 
124
- class SQLCounter
125
- class << self
126
- attr_accessor :ignored_sql, :log, :log_all
127
- def clear_log; self.log = []; self.log_all = []; end
325
+ class TrilogyTestCase < TestCase
326
+ def self.run(*args)
327
+ super if current_adapter?(:TrilogyAdapter)
128
328
  end
329
+ end
129
330
 
130
- clear_log
131
-
132
- def call(name, start, finish, message_id, values)
133
- return if values[:cached]
134
-
135
- sql = values[:sql]
136
- self.class.log_all << sql
137
- self.class.log << sql unless ["SCHEMA", "TRANSACTION"].include? values[:name]
331
+ class SQLite3TestCase < TestCase
332
+ def self.run(*args)
333
+ super if current_adapter?(:SQLite3Adapter)
138
334
  end
139
335
  end
140
-
141
- ActiveSupport::Notifications.subscribe("sql.active_record", SQLCounter.new)
142
336
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+
5
+ module ActiveRecord
6
+ class TestCaseLeakCheckTest < ActiveRecord::TestCase
7
+ self.use_transactional_tests = false
8
+
9
+ def test_check_connection_leaks_does_not_report_connections_held_for_reaper_maintenance
10
+ skip "checkout_for_maintenance is not supported by IBM_DB" if ActiveRecord::Base.connection.adapter_name == "IBM_DB"
11
+
12
+ pool = ActiveRecord::Base.connection_pool
13
+
14
+ conn = ActiveRecord::Base.lease_connection
15
+ conn.select_value("SELECT 1")
16
+ ActiveRecord::Base.connection_handler.clear_active_connections!
17
+
18
+ assert_not_nil conn
19
+
20
+ release_maintenance_latch = Concurrent::CountDownLatch.new(1)
21
+ leak_check_attempted_latch = Concurrent::CountDownLatch.new(1)
22
+
23
+ maintenance_thread = Thread.new do
24
+ Thread.current.name = "AR Pool Reaper"
25
+
26
+ pool.reaper_lock do
27
+ pool.send(:checkout_for_maintenance, conn)
28
+ release_maintenance_latch.wait
29
+ pool.send(:return_from_maintenance, conn)
30
+ end
31
+ end
32
+
33
+ wait_for(message: "connection was not checked out for maintenance", timeout: 1) do
34
+ conn.in_use?
35
+ end
36
+ assert_not_equal ActiveSupport::IsolatedExecutionState.context, conn.owner
37
+
38
+ original_reaper_lock_method = pool.method(:reaper_lock)
39
+ leak_check_thread = nil
40
+
41
+ pool.stub(:reaper_lock, ->(&block) do
42
+ leak_check_attempted_latch.count_down
43
+ original_reaper_lock_method.call(&block)
44
+ end) do
45
+ leak_check_thread = Thread.new do
46
+ check_connection_leaks
47
+ end
48
+
49
+ wait_for(message: "leak check did not reach the reaper lock", timeout: 1) do
50
+ !leak_check_thread.alive? || leak_check_attempted_latch.wait(0)
51
+ end
52
+
53
+ release_maintenance_latch.count_down
54
+ assert_nothing_raised do
55
+ leak_check_thread.value
56
+ end
57
+ end
58
+ ensure
59
+ release_maintenance_latch&.count_down
60
+ maintenance_thread&.join
61
+ leak_check_thread&.join
62
+
63
+ if conn&.in_use?
64
+ conn.steal!
65
+ pool.checkin(conn)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -5,6 +5,10 @@ require "active_record/test_databases"
5
5
 
6
6
  class TestDatabasesTest < ActiveRecord::TestCase
7
7
  unless in_memory_db?
8
+ def setup
9
+ skip "test_databases_test requires sqlite3 gem" if ActiveRecord::Base.connection.adapter_name == "IBM_DB"
10
+ end
11
+
8
12
  def test_databases_are_created
9
13
  previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "arunit"
10
14
  prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, {
@@ -16,7 +20,7 @@ class TestDatabasesTest < ActiveRecord::TestCase
16
20
  base_db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
17
21
  expected_database = "#{base_db_config.database}-2"
18
22
 
19
- ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _, _) {
23
+ ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _) {
20
24
  assert_equal expected_database, db_config.database
21
25
  }) do
22
26
  ActiveRecord::TestDatabases.create_and_load_schema(2, env_name: "arunit")
@@ -39,7 +43,7 @@ class TestDatabasesTest < ActiveRecord::TestCase
39
43
  base_db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
40
44
  expected_database = "#{base_db_config.database}-#{idx}"
41
45
 
42
- ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _, _) {
46
+ ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _) {
43
47
  assert_equal expected_database, db_config.database
44
48
  }) do
45
49
  ActiveSupport::Testing::Parallelization.after_fork_hooks.each { |cb| cb.call(idx) }
@@ -65,7 +69,7 @@ class TestDatabasesTest < ActiveRecord::TestCase
65
69
  idx = 42
66
70
  base_configs_order = ActiveRecord::Base.configurations.configs_for(env_name: "arunit").map(&:name)
67
71
 
68
- ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _, _) {
72
+ ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _) {
69
73
  assert_equal base_configs_order, ActiveRecord::Base.configurations.configs_for(env_name: "arunit").map(&:name)
70
74
  }) do
71
75
  ActiveSupport::Testing::Parallelization.after_fork_hooks.each { |cb| cb.call(idx) }
@@ -6,6 +6,8 @@ require "fileutils"
6
6
  require "models/zine"
7
7
 
8
8
  class TestFixturesTest < ActiveRecord::TestCase
9
+ self.use_transactional_tests = false
10
+
9
11
  setup do
10
12
  @klass = Class.new
11
13
  @klass.include(ActiveRecord::TestFixtures)
@@ -21,45 +23,18 @@ class TestFixturesTest < ActiveRecord::TestCase
21
23
  assert_equal "foobar", @klass.use_transactional_tests
22
24
  end
23
25
 
24
- unless in_memory_db?
25
- def test_doesnt_rely_on_active_support_test_case_specific_methods_with_legacy_connection_handling
26
- old_value = ActiveRecord::Base.legacy_connection_handling
27
- ActiveRecord::Base.legacy_connection_handling = true
28
-
29
- tmp_dir = Dir.mktmpdir
30
- File.write(File.join(tmp_dir, "zines.yml"), <<~YML)
31
- going_out:
32
- title: Hello
33
- YML
34
-
35
- klass = Class.new(Minitest::Test) do
36
- include ActiveRecord::TestFixtures
37
-
38
- self.fixture_path = tmp_dir
39
- self.use_transactional_tests = true
40
-
41
- fixtures :all
42
-
43
- def test_run_successfuly
44
- assert_equal("Hello", Zine.first.title)
45
- assert_equal("Hello", zines(:going_out).title)
46
- end
47
- end
26
+ def test_inclusion_runs_active_record_fixtures_load_hook
27
+ ActiveSupport.on_load(:active_record_fixtures) do
28
+ self.fixture_paths << "test/fixtures"
29
+ end
30
+ klass = Class.new
48
31
 
49
- old_handler = ActiveRecord::Base.connection_handler
50
- ActiveRecord::Base.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
51
- ActiveRecord::Base.connection_handlers = {}
52
- ActiveRecord::Base.establish_connection(:arunit)
32
+ klass.include(ActiveRecord::TestFixtures)
53
33
 
54
- test_result = klass.new("test_run_successfuly").run
55
- assert_predicate(test_result, :passed?)
56
- ensure
57
- clean_up_legacy_connection_handlers
58
- ActiveRecord::Base.connection_handler = old_handler
59
- FileUtils.rm_r(tmp_dir)
60
- ActiveRecord::Base.legacy_connection_handling = old_value
61
- end
34
+ assert_includes klass.fixture_paths, "test/fixtures"
35
+ end
62
36
 
37
+ unless in_memory_db?
63
38
  def test_doesnt_rely_on_active_support_test_case_specific_methods
64
39
  tmp_dir = Dir.mktmpdir
65
40
  File.write(File.join(tmp_dir, "zines.yml"), <<~YML)
@@ -70,22 +45,26 @@ class TestFixturesTest < ActiveRecord::TestCase
70
45
  klass = Class.new(Minitest::Test) do
71
46
  include ActiveRecord::TestFixtures
72
47
 
73
- self.fixture_path = tmp_dir
48
+ self.fixture_paths = [tmp_dir]
74
49
  self.use_transactional_tests = true
75
50
 
76
- fixtures :all
51
+ # Explicitly load the only fixture set this test needs.
52
+ fixtures :zines
77
53
 
78
- def test_run_successfuly
54
+ def test_run_successfully
79
55
  assert_equal("Hello", Zine.first.title)
80
56
  assert_equal("Hello", zines(:going_out).title)
81
57
  end
82
58
  end
83
59
 
60
+ ActiveSupport::Notifications.unsubscribe(@connection_subscriber)
61
+ @connection_subscriber = nil
62
+
84
63
  old_handler = ActiveRecord::Base.connection_handler
85
64
  ActiveRecord::Base.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
86
65
  ActiveRecord::Base.establish_connection(:arunit)
87
66
 
88
- test_result = klass.new("test_run_successfuly").run
67
+ test_result = klass.new("test_run_successfully").run
89
68
  assert_predicate(test_result, :passed?)
90
69
  ensure
91
70
  ActiveRecord::Base.connection_handler = old_handler
@@ -3,15 +3,15 @@
3
3
  require "cases/helper"
4
4
  require "support/schema_dumping_helper"
5
5
 
6
- if supports_datetime_with_precision?
7
- class TimePrecisionTest < ActiveRecord::TestCase
6
+ class TimePrecisionTest < ActiveRecord::TestCase
7
+ if supports_datetime_with_precision?
8
8
  include SchemaDumpingHelper
9
9
  self.use_transactional_tests = false
10
10
 
11
11
  class Foo < ActiveRecord::Base; end
12
12
 
13
13
  setup do
14
- @connection = ActiveRecord::Base.connection
14
+ @connection = ActiveRecord::Base.lease_connection
15
15
  Foo.reset_column_information
16
16
  end
17
17
 
@@ -20,6 +20,8 @@ if supports_datetime_with_precision?
20
20
  end
21
21
 
22
22
  def test_time_data_type_with_precision
23
+ skip "DB2 does not support precision for TIME columns" if current_adapter?(:IBM_DBAdapter)
24
+
23
25
  @connection.create_table(:foos, force: true)
24
26
  @connection.add_column :foos, :start, :time, precision: 3
25
27
  @connection.add_column :foos, :finish, :time, precision: 6
@@ -28,6 +30,8 @@ if supports_datetime_with_precision?
28
30
  end
29
31
 
30
32
  def test_time_precision_is_truncated_on_assignment
33
+ skip "DB2 does not support precision for TIME columns" if current_adapter?(:IBM_DBAdapter)
34
+
31
35
  @connection.create_table(:foos, force: true)
32
36
  @connection.add_column :foos, :start, :time, precision: 0
33
37
  @connection.add_column :foos, :finish, :time, precision: 6
@@ -45,8 +49,10 @@ if supports_datetime_with_precision?
45
49
  assert_equal 123456000, foo.finish.nsec
46
50
  end
47
51
 
48
- unless current_adapter?(:Mysql2Adapter)
52
+ unless current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
49
53
  def test_no_time_precision_isnt_truncated_on_assignment
54
+ skip "DB2 does not support precision for TIME columns" if current_adapter?(:IBM_DBAdapter)
55
+
50
56
  @connection.create_table(:foos, force: true)
51
57
  @connection.add_column :foos, :start, :time
52
58
  @connection.add_column :foos, :finish, :time, precision: 6
@@ -75,6 +81,8 @@ if supports_datetime_with_precision?
75
81
  end
76
82
 
77
83
  def test_invalid_time_precision_raises_error
84
+ skip "DB2 does not support precision for TIME columns" if current_adapter?(:IBM_DBAdapter)
85
+
78
86
  assert_raises ArgumentError do
79
87
  @connection.create_table(:foos, force: true) do |t|
80
88
  t.time :start, precision: 7
@@ -84,6 +92,8 @@ if supports_datetime_with_precision?
84
92
  end
85
93
 
86
94
  def test_formatting_time_according_to_precision
95
+ skip "DB2 does not support precision for TIME columns" if current_adapter?(:IBM_DBAdapter)
96
+
87
97
  @connection.create_table(:foos, force: true) do |t|
88
98
  t.time :start, precision: 0
89
99
  t.time :finish, precision: 4
@@ -101,6 +111,8 @@ if supports_datetime_with_precision?
101
111
  end
102
112
 
103
113
  def test_schema_dump_includes_time_precision
114
+ skip "DB2 does not support precision for TIME columns" if current_adapter?(:IBM_DBAdapter)
115
+
104
116
  @connection.create_table(:foos, force: true) do |t|
105
117
  t.time :start, precision: 4
106
118
  t.time :finish, precision: 6
@@ -110,7 +122,7 @@ if supports_datetime_with_precision?
110
122
  assert_match %r{t\.time\s+"finish",\s+precision: 6$}, output
111
123
  end
112
124
 
113
- if current_adapter?(:PostgreSQLAdapter, :SQLServerAdapter)
125
+ if current_adapter?(:PostgreSQLAdapter)
114
126
  def test_time_precision_with_zero_should_be_dumped
115
127
  @connection.create_table(:foos, force: true) do |t|
116
128
  t.time :start, precision: 0