sequel 4.22.0 → 4.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +22 -0
- data/README.rdoc +6 -0
- data/Rakefile +59 -81
- data/doc/migration.rdoc +2 -0
- data/doc/release_notes/4.23.0.txt +65 -0
- data/doc/sharding.rdoc +16 -14
- data/doc/testing.rdoc +61 -77
- data/lib/sequel/adapters/jdbc.rb +1 -0
- data/lib/sequel/adapters/mock.rb +0 -1
- data/lib/sequel/adapters/postgres.rb +1 -0
- data/lib/sequel/adapters/postgresql.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +3 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +9 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/transactions.rb +2 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +12 -12
- data/lib/sequel/extensions/date_arithmetic.rb +0 -4
- data/lib/sequel/extensions/pagination.rb +14 -2
- data/lib/sequel/extensions/pg_enum.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/delay_add_association.rb +50 -0
- data/lib/sequel/plugins/list.rb +2 -2
- data/lib/sequel/plugins/nested_attributes.rb +8 -28
- data/lib/sequel/plugins/update_refresh.rb +50 -0
- data/lib/sequel/plugins/validate_associated.rb +55 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +29 -29
- data/spec/adapters/firebird_spec.rb +97 -103
- data/spec/adapters/informix_spec.rb +25 -25
- data/spec/adapters/mssql_spec.rb +156 -172
- data/spec/adapters/mysql_spec.rb +334 -359
- data/spec/adapters/oracle_spec.rb +67 -69
- data/spec/adapters/postgres_spec.rb +1298 -1249
- data/spec/adapters/spec_helper.rb +2 -35
- data/spec/adapters/sqlanywhere_spec.rb +39 -39
- data/spec/adapters/sqlite_spec.rb +203 -200
- data/spec/bin_spec.rb +57 -59
- data/spec/core/connection_pool_spec.rb +402 -401
- data/spec/core/database_spec.rb +953 -944
- data/spec/core/dataset_spec.rb +2178 -2168
- data/spec/core/deprecated_spec.rb +19 -19
- data/spec/core/expression_filters_spec.rb +415 -415
- data/spec/core/mock_adapter_spec.rb +212 -212
- data/spec/core/object_graph_spec.rb +73 -73
- data/spec/core/placeholder_literalizer_spec.rb +71 -71
- data/spec/core/schema_generator_spec.rb +44 -44
- data/spec/core/schema_spec.rb +470 -472
- data/spec/core/spec_helper.rb +5 -20
- data/spec/core/version_spec.rb +2 -2
- data/spec/core_extensions_spec.rb +320 -320
- data/spec/extensions/accessed_columns_spec.rb +12 -12
- data/spec/extensions/active_model_spec.rb +3 -3
- data/spec/extensions/after_initialize_spec.rb +2 -2
- data/spec/extensions/arbitrary_servers_spec.rb +23 -23
- data/spec/extensions/association_dependencies_spec.rb +34 -34
- data/spec/extensions/association_pks_spec.rb +98 -98
- data/spec/extensions/association_proxies_spec.rb +33 -33
- data/spec/extensions/auto_validations_spec.rb +46 -46
- data/spec/extensions/blacklist_security_spec.rb +19 -18
- data/spec/extensions/blank_spec.rb +36 -36
- data/spec/extensions/boolean_readers_spec.rb +36 -36
- data/spec/extensions/caching_spec.rb +82 -82
- data/spec/extensions/class_table_inheritance_spec.rb +72 -72
- data/spec/extensions/column_conflicts_spec.rb +19 -14
- data/spec/extensions/column_select_spec.rb +19 -19
- data/spec/extensions/columns_introspection_spec.rb +43 -43
- data/spec/extensions/composition_spec.rb +64 -64
- data/spec/extensions/connection_validator_spec.rb +92 -90
- data/spec/extensions/constraint_validations_plugin_spec.rb +92 -92
- data/spec/extensions/constraint_validations_spec.rb +80 -80
- data/spec/extensions/core_refinements_spec.rb +220 -220
- data/spec/extensions/csv_serializer_spec.rb +44 -44
- data/spec/extensions/current_datetime_timestamp_spec.rb +8 -8
- data/spec/extensions/dataset_associations_spec.rb +65 -65
- data/spec/extensions/dataset_source_alias_spec.rb +16 -16
- data/spec/extensions/date_arithmetic_spec.rb +51 -58
- data/spec/extensions/defaults_setter_spec.rb +19 -19
- data/spec/extensions/delay_add_association_spec.rb +52 -0
- data/spec/extensions/dirty_spec.rb +51 -51
- data/spec/extensions/eager_each_spec.rb +8 -8
- data/spec/extensions/empty_array_ignore_nulls_spec.rb +10 -10
- data/spec/extensions/error_splitter_spec.rb +2 -2
- data/spec/extensions/error_sql_spec.rb +4 -4
- data/spec/extensions/eval_inspect_spec.rb +3 -3
- data/spec/extensions/filter_having_spec.rb +8 -8
- data/spec/extensions/force_encoding_spec.rb +30 -30
- data/spec/extensions/from_block_spec.rb +7 -7
- data/spec/extensions/graph_each_spec.rb +19 -19
- data/spec/extensions/hash_aliases_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +100 -100
- data/spec/extensions/inflector_spec.rb +54 -54
- data/spec/extensions/input_transformer_spec.rb +10 -10
- data/spec/extensions/insert_returning_select_spec.rb +8 -8
- data/spec/extensions/instance_filters_spec.rb +26 -26
- data/spec/extensions/instance_hooks_spec.rb +85 -85
- data/spec/extensions/json_serializer_spec.rb +68 -68
- data/spec/extensions/lazy_attributes_spec.rb +49 -49
- data/spec/extensions/list_spec.rb +77 -75
- data/spec/extensions/looser_typecasting_spec.rb +16 -16
- data/spec/extensions/many_through_many_spec.rb +627 -627
- data/spec/extensions/meta_def_spec.rb +7 -7
- data/spec/extensions/migration_spec.rb +217 -217
- data/spec/extensions/modification_detection_spec.rb +20 -20
- data/spec/extensions/mssql_optimistic_locking_spec.rb +21 -21
- data/spec/extensions/named_timezones_spec.rb +18 -18
- data/spec/extensions/nested_attributes_spec.rb +107 -107
- data/spec/extensions/null_dataset_spec.rb +24 -24
- data/spec/extensions/optimistic_locking_spec.rb +21 -21
- data/spec/extensions/pagination_spec.rb +52 -52
- data/spec/extensions/pg_array_associations_spec.rb +273 -273
- data/spec/extensions/pg_array_ops_spec.rb +52 -52
- data/spec/extensions/pg_array_spec.rb +152 -152
- data/spec/extensions/pg_enum_spec.rb +13 -13
- data/spec/extensions/pg_hstore_ops_spec.rb +63 -63
- data/spec/extensions/pg_hstore_spec.rb +84 -84
- data/spec/extensions/pg_inet_spec.rb +15 -15
- data/spec/extensions/pg_interval_spec.rb +29 -29
- data/spec/extensions/pg_json_ops_spec.rb +86 -84
- data/spec/extensions/pg_json_spec.rb +104 -104
- data/spec/extensions/pg_loose_count_spec.rb +6 -6
- data/spec/extensions/pg_range_ops_spec.rb +24 -24
- data/spec/extensions/pg_range_spec.rb +143 -143
- data/spec/extensions/pg_row_ops_spec.rb +14 -14
- data/spec/extensions/pg_row_plugin_spec.rb +12 -12
- data/spec/extensions/pg_row_spec.rb +118 -118
- data/spec/extensions/pg_static_cache_updater_spec.rb +28 -28
- data/spec/extensions/pg_typecast_on_load_spec.rb +21 -21
- data/spec/extensions/prepared_statements_associations_spec.rb +42 -42
- data/spec/extensions/prepared_statements_safe_spec.rb +18 -18
- data/spec/extensions/prepared_statements_spec.rb +28 -28
- data/spec/extensions/prepared_statements_with_pk_spec.rb +11 -11
- data/spec/extensions/pretty_table_spec.rb +16 -16
- data/spec/extensions/query_literals_spec.rb +37 -37
- data/spec/extensions/query_spec.rb +32 -32
- data/spec/extensions/rcte_tree_spec.rb +141 -141
- data/spec/extensions/round_timestamps_spec.rb +21 -21
- data/spec/extensions/schema_caching_spec.rb +8 -8
- data/spec/extensions/schema_dumper_spec.rb +78 -78
- data/spec/extensions/schema_spec.rb +31 -27
- data/spec/extensions/scissors_spec.rb +3 -3
- data/spec/extensions/select_remove_spec.rb +14 -14
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +28 -28
- data/spec/extensions/serialization_modification_detection_spec.rb +33 -33
- data/spec/extensions/serialization_spec.rb +79 -78
- data/spec/extensions/server_block_spec.rb +17 -17
- data/spec/extensions/set_overrides_spec.rb +30 -30
- data/spec/extensions/sharding_spec.rb +65 -65
- data/spec/extensions/shared_caching_spec.rb +29 -29
- data/spec/extensions/single_table_inheritance_spec.rb +79 -79
- data/spec/extensions/skip_create_refresh_spec.rb +3 -3
- data/spec/extensions/spec_helper.rb +4 -29
- data/spec/extensions/split_array_nil_spec.rb +9 -9
- data/spec/extensions/split_values_spec.rb +7 -7
- data/spec/extensions/sql_expr_spec.rb +32 -32
- data/spec/extensions/static_cache_spec.rb +123 -123
- data/spec/extensions/string_date_time_spec.rb +34 -34
- data/spec/extensions/string_stripper_spec.rb +15 -15
- data/spec/extensions/subclasses_spec.rb +31 -31
- data/spec/extensions/table_select_spec.rb +15 -15
- data/spec/extensions/tactical_eager_loading_spec.rb +23 -23
- data/spec/extensions/thread_local_timezones_spec.rb +13 -13
- data/spec/extensions/timestamps_spec.rb +40 -40
- data/spec/extensions/to_dot_spec.rb +34 -34
- data/spec/extensions/touch_spec.rb +52 -52
- data/spec/extensions/tree_spec.rb +72 -72
- data/spec/extensions/typecast_on_load_spec.rb +25 -25
- data/spec/extensions/unlimited_update_spec.rb +2 -2
- data/spec/extensions/update_or_create_spec.rb +36 -36
- data/spec/extensions/update_primary_key_spec.rb +35 -35
- data/spec/extensions/update_refresh_spec.rb +41 -0
- data/spec/extensions/validate_associated_spec.rb +52 -0
- data/spec/extensions/validation_class_methods_spec.rb +314 -317
- data/spec/extensions/validation_helpers_spec.rb +195 -195
- data/spec/extensions/xml_serializer_spec.rb +48 -48
- data/spec/guards_helper.rb +55 -0
- data/spec/integration/associations_test.rb +1089 -1088
- data/spec/integration/database_test.rb +29 -29
- data/spec/integration/dataset_test.rb +661 -661
- data/spec/integration/eager_loader_test.rb +147 -147
- data/spec/integration/migrator_test.rb +122 -122
- data/spec/integration/model_test.rb +70 -70
- data/spec/integration/plugin_test.rb +682 -640
- data/spec/integration/prepared_statement_test.rb +172 -172
- data/spec/integration/schema_test.rb +245 -245
- data/spec/integration/spec_helper.rb +1 -64
- data/spec/integration/timezone_test.rb +17 -17
- data/spec/integration/transaction_test.rb +87 -87
- data/spec/integration/type_test.rb +33 -33
- data/spec/model/association_reflection_spec.rb +130 -121
- data/spec/model/associations_spec.rb +1112 -1113
- data/spec/model/base_spec.rb +197 -196
- data/spec/model/class_dataset_methods_spec.rb +118 -118
- data/spec/model/dataset_methods_spec.rb +49 -49
- data/spec/model/eager_loading_spec.rb +705 -702
- data/spec/model/hooks_spec.rb +169 -168
- data/spec/model/inflector_spec.rb +5 -5
- data/spec/model/model_spec.rb +287 -297
- data/spec/model/plugins_spec.rb +47 -47
- data/spec/model/record_spec.rb +534 -535
- data/spec/model/spec_helper.rb +3 -21
- data/spec/model/validations_spec.rb +72 -70
- data/spec/spec_config.rb +8 -0
- metadata +41 -9
- data/lib/sequel/adapters/fdbsql.rb +0 -286
- data/lib/sequel/adapters/jdbc/fdbsql.rb +0 -66
- data/lib/sequel/adapters/openbase.rb +0 -54
- data/lib/sequel/adapters/shared/fdbsql.rb +0 -550
- data/spec/adapters/fdbsql_spec.rb +0 -429
- data/spec/rspec_helper.rb +0 -22
data/spec/bin_spec.rb
CHANGED
|
@@ -26,7 +26,7 @@ DB2 = Sequel.connect("#{CONN_PREFIX}#{BIN_SPEC_DB2}")
|
|
|
26
26
|
File.delete(BIN_SPEC_DB) if File.file?(BIN_SPEC_DB)
|
|
27
27
|
File.delete(BIN_SPEC_DB2) if File.file?(BIN_SPEC_DB2)
|
|
28
28
|
|
|
29
|
-
require
|
|
29
|
+
require 'minitest/autorun'
|
|
30
30
|
|
|
31
31
|
describe "bin/sequel" do
|
|
32
32
|
def bin(opts={})
|
|
@@ -41,22 +41,20 @@ describe "bin/sequel" do
|
|
|
41
41
|
File.delete(BIN_SPEC_DB) if File.file?(BIN_SPEC_DB)
|
|
42
42
|
File.delete(BIN_SPEC_DB2) if File.file?(BIN_SPEC_DB2)
|
|
43
43
|
File.delete(TMP_FILE) if File.file?(TMP_FILE)
|
|
44
|
-
end
|
|
45
|
-
after(:all) do
|
|
46
44
|
File.delete(OUTPUT) if File.file?(OUTPUT)
|
|
47
45
|
end
|
|
48
46
|
|
|
49
47
|
it "-h should print the help" do
|
|
50
48
|
help = bin(:args=>"-h", :no_conn=>true)
|
|
51
|
-
help.
|
|
52
|
-
help.
|
|
49
|
+
help.must_match(/\ASequel: The Database Toolkit for Ruby/)
|
|
50
|
+
help.must_match(/^Usage: sequel /)
|
|
53
51
|
end
|
|
54
52
|
|
|
55
53
|
it "-c should run code" do
|
|
56
|
-
bin(:args=>'-c "print DB.tables.inspect"').
|
|
54
|
+
bin(:args=>'-c "print DB.tables.inspect"').must_equal '[]'
|
|
57
55
|
DB.create_table(:a){Integer :a}
|
|
58
|
-
bin(:args=>'-c "print DB.tables.inspect"').
|
|
59
|
-
bin(:args=>'-v -c "print DB.tables.inspect"').
|
|
56
|
+
bin(:args=>'-c "print DB.tables.inspect"').must_equal '[:a]'
|
|
57
|
+
bin(:args=>'-v -c "print DB.tables.inspect"').strip.must_equal "sequel #{Sequel.version}\n[:a]"
|
|
60
58
|
end
|
|
61
59
|
|
|
62
60
|
it "-C should copy databases" do
|
|
@@ -70,7 +68,7 @@ describe "bin/sequel" do
|
|
|
70
68
|
end
|
|
71
69
|
DB[:a].insert(1, 'foo')
|
|
72
70
|
DB[:b].insert(1)
|
|
73
|
-
bin(:args=>'-C', :post=>"#{CONN_PREFIX}#{BIN_SPEC_DB2}").
|
|
71
|
+
bin(:args=>'-C', :post=>"#{CONN_PREFIX}#{BIN_SPEC_DB2}").must_match Regexp.new(<<END)
|
|
74
72
|
Databases connections successful
|
|
75
73
|
Migrations dumped successfully
|
|
76
74
|
Tables created
|
|
@@ -86,15 +84,15 @@ Begin adding foreign key constraints
|
|
|
86
84
|
Finished adding foreign key constraints
|
|
87
85
|
Database copy finished in \\d\\.\\d+ seconds
|
|
88
86
|
END
|
|
89
|
-
DB2.tables.sort_by{|t| t.to_s}.
|
|
90
|
-
DB[:a].all.
|
|
91
|
-
DB[:b].all.
|
|
92
|
-
DB2.schema(:a).map{|col, sch| [col, *sch.values_at(:allow_null, :default, :primary_key, :db_type, :type, :ruby_default)]}.
|
|
93
|
-
DB2.schema(:b).map{|col, sch| [col, *sch.values_at(:allow_null, :default, :primary_key, :db_type, :type, :ruby_default)]}.
|
|
94
|
-
DB2.indexes(:a).
|
|
95
|
-
DB2.indexes(:b).
|
|
96
|
-
DB2.foreign_key_list(:a).
|
|
97
|
-
DB2.foreign_key_list(:b).
|
|
87
|
+
DB2.tables.sort_by{|t| t.to_s}.must_equal [:a, :b]
|
|
88
|
+
DB[:a].all.must_equal [{:a=>1, :name=>'foo'}]
|
|
89
|
+
DB[:b].all.must_equal [{:a=>1}]
|
|
90
|
+
DB2.schema(:a).map{|col, sch| [col, *sch.values_at(:allow_null, :default, :primary_key, :db_type, :type, :ruby_default)]}.must_equal [[:a, false, nil, true, "integer", :integer, nil], [:name, true, nil, false, "varchar(255)", :string, nil]]
|
|
91
|
+
DB2.schema(:b).map{|col, sch| [col, *sch.values_at(:allow_null, :default, :primary_key, :db_type, :type, :ruby_default)]}.must_equal [[:a, true, nil, false, "integer", :integer, nil]]
|
|
92
|
+
DB2.indexes(:a).must_equal({})
|
|
93
|
+
DB2.indexes(:b).must_equal(:b_a_index=>{:unique=>false, :columns=>[:a]})
|
|
94
|
+
DB2.foreign_key_list(:a).must_equal []
|
|
95
|
+
DB2.foreign_key_list(:b).must_equal [{:columns=>[:a], :table=>:a, :key=>nil, :on_update=>:no_action, :on_delete=>:no_action}]
|
|
98
96
|
end
|
|
99
97
|
|
|
100
98
|
it "-d and -D should dump generic and specific migrations" do
|
|
@@ -106,7 +104,7 @@ END
|
|
|
106
104
|
foreign_key :a, :a
|
|
107
105
|
index :a
|
|
108
106
|
end
|
|
109
|
-
bin(:args=>'-d').
|
|
107
|
+
bin(:args=>'-d').must_equal <<END
|
|
110
108
|
Sequel.migration do
|
|
111
109
|
change do
|
|
112
110
|
create_table(:a) do
|
|
@@ -122,7 +120,7 @@ Sequel.migration do
|
|
|
122
120
|
end
|
|
123
121
|
end
|
|
124
122
|
END
|
|
125
|
-
bin(:args=>'-D').
|
|
123
|
+
bin(:args=>'-D').must_equal <<END
|
|
126
124
|
Sequel.migration do
|
|
127
125
|
change do
|
|
128
126
|
create_table(:a) do
|
|
@@ -141,79 +139,79 @@ END
|
|
|
141
139
|
end
|
|
142
140
|
|
|
143
141
|
it "-E should echo SQL statements to stdout" do
|
|
144
|
-
bin(:args=>'-E -c DB.tables').
|
|
142
|
+
bin(:args=>'-E -c DB.tables').must_match %r{SELECT \* FROM `sqlite_master` WHERE \(type = 'table' AND NOT name = 'sqlite_sequence'\)\n}
|
|
145
143
|
end
|
|
146
144
|
|
|
147
145
|
it "-I should include directory in load path" do
|
|
148
|
-
bin(:args=>'-Ifoo -c "p 1 if $:.include?(\'foo\')"').
|
|
146
|
+
bin(:args=>'-Ifoo -c "p 1 if $:.include?(\'foo\')"').must_equal "1\n"
|
|
149
147
|
end
|
|
150
148
|
|
|
151
149
|
it "-l should log SQL statements to file" do
|
|
152
|
-
bin(:args=>"-l #{TMP_FILE} -c DB.tables").
|
|
153
|
-
File.read(TMP_FILE).
|
|
150
|
+
bin(:args=>"-l #{TMP_FILE} -c DB.tables").must_equal ''
|
|
151
|
+
File.read(TMP_FILE).must_match %r{SELECT \* FROM `sqlite_master` WHERE \(type = 'table' AND NOT name = 'sqlite_sequence'\)\n}
|
|
154
152
|
end
|
|
155
153
|
|
|
156
154
|
it "-L should load all *.rb files in given directory" do
|
|
157
|
-
bin(:args=>'-L ./lib/sequel/connection_pool -c "p [Sequel::SingleConnectionPool, Sequel::ThreadedConnectionPool, Sequel::ShardedSingleConnectionPool, Sequel::ShardedThreadedConnectionPool].length"').
|
|
155
|
+
bin(:args=>'-L ./lib/sequel/connection_pool -c "p [Sequel::SingleConnectionPool, Sequel::ThreadedConnectionPool, Sequel::ShardedSingleConnectionPool, Sequel::ShardedThreadedConnectionPool].length"').must_equal "4\n"
|
|
158
156
|
end
|
|
159
157
|
|
|
160
158
|
it "-m should migrate database up" do
|
|
161
|
-
bin(:args=>"-m spec/files/integer_migrations").
|
|
162
|
-
DB.tables.sort_by{|t| t.to_s}.
|
|
159
|
+
bin(:args=>"-m spec/files/integer_migrations").must_equal ''
|
|
160
|
+
DB.tables.sort_by{|t| t.to_s}.must_equal [:schema_info, :sm1111, :sm2222, :sm3333]
|
|
163
161
|
end
|
|
164
162
|
|
|
165
163
|
it "-M should specify version to migrate to" do
|
|
166
|
-
bin(:args=>"-m spec/files/integer_migrations -M 2").
|
|
167
|
-
DB.tables.sort_by{|t| t.to_s}.
|
|
164
|
+
bin(:args=>"-m spec/files/integer_migrations -M 2").must_equal ''
|
|
165
|
+
DB.tables.sort_by{|t| t.to_s}.must_equal [:schema_info, :sm1111, :sm2222]
|
|
168
166
|
end
|
|
169
167
|
|
|
170
168
|
it "-N should not test for a valid connection" do
|
|
171
|
-
bin(:no_conn=>true, :args=>"-c '' -N #{CONN_PREFIX}spec/nonexistent/foo").
|
|
172
|
-
bin(:no_conn=>true, :args=>"-c '' #{CONN_PREFIX}spec/nonexistent/foo", :stderr=>true).
|
|
169
|
+
bin(:no_conn=>true, :args=>"-c '' -N #{CONN_PREFIX}spec/nonexistent/foo").must_equal ''
|
|
170
|
+
bin(:no_conn=>true, :args=>"-c '' #{CONN_PREFIX}spec/nonexistent/foo", :stderr=>true).must_match(/\AError: Sequel::DatabaseConnectionError: /)
|
|
173
171
|
end
|
|
174
172
|
|
|
175
173
|
it "-r should require a given library" do
|
|
176
|
-
bin(:args=>'-rsequel/extensions/sql_expr -c "print DB.literal(1.sql_expr)"').
|
|
174
|
+
bin(:args=>'-rsequel/extensions/sql_expr -c "print DB.literal(1.sql_expr)"').must_equal "1"
|
|
177
175
|
end
|
|
178
176
|
|
|
179
177
|
it "-S should dump the schema cache" do
|
|
180
|
-
bin(:args=>"-S #{TMP_FILE}").
|
|
181
|
-
Marshal.load(File.read(TMP_FILE)).
|
|
178
|
+
bin(:args=>"-S #{TMP_FILE}").must_equal ''
|
|
179
|
+
Marshal.load(File.read(TMP_FILE)).must_equal({})
|
|
182
180
|
DB.create_table(:a){Integer :a}
|
|
183
|
-
bin(:args=>"-S #{TMP_FILE}").
|
|
184
|
-
Marshal.load(File.read(TMP_FILE)).
|
|
181
|
+
bin(:args=>"-S #{TMP_FILE}").must_equal ''
|
|
182
|
+
Marshal.load(File.read(TMP_FILE)).must_equal("`a`"=>[[:a, {:type=>:integer, :db_type=>"integer", :ruby_default=>nil, :allow_null=>true, :default=>nil, :primary_key=>false}]])
|
|
185
183
|
end
|
|
186
184
|
|
|
187
185
|
it "-t should output full backtraces on error" do
|
|
188
|
-
bin(:args=>'-c "lambda{lambda{lambda{raise \'foo\'}.call}.call}.call"', :stderr=>true).count("\n").
|
|
189
|
-
bin(:args=>'-t -c "lambda{lambda{lambda{raise \'foo\'}.call}.call}.call"', :stderr=>true).count("\n").
|
|
186
|
+
bin(:args=>'-c "lambda{lambda{lambda{raise \'foo\'}.call}.call}.call"', :stderr=>true).count("\n").must_be :<, 3
|
|
187
|
+
bin(:args=>'-t -c "lambda{lambda{lambda{raise \'foo\'}.call}.call}.call"', :stderr=>true).count("\n").must_be :>, 3
|
|
190
188
|
end
|
|
191
189
|
|
|
192
190
|
it "-v should output the Sequel version and exit if database is not given" do
|
|
193
|
-
bin(:args=>"-v", :no_conn=>true).
|
|
191
|
+
bin(:args=>"-v", :no_conn=>true).strip.must_equal "sequel #{Sequel.version}"
|
|
194
192
|
end
|
|
195
193
|
|
|
196
194
|
it "should error if using -M without -m" do
|
|
197
|
-
bin(:args=>'-M 2', :stderr=>true).
|
|
195
|
+
bin(:args=>'-M 2', :stderr=>true).must_equal "Error: Must specify -m if using -M\n"
|
|
198
196
|
end
|
|
199
197
|
|
|
200
198
|
it "should error if using mutually exclusive options together" do
|
|
201
|
-
bin(:args=>'-c foo -d', :stderr=>true).
|
|
202
|
-
bin(:args=>'-D -d', :stderr=>true).
|
|
203
|
-
bin(:args=>'-m foo -d', :stderr=>true).
|
|
204
|
-
bin(:args=>'-S foo -d', :stderr=>true).
|
|
205
|
-
bin(:args=>'-S foo -C', :stderr=>true).
|
|
199
|
+
bin(:args=>'-c foo -d', :stderr=>true).must_equal "Error: Cannot specify -c and -d together\n"
|
|
200
|
+
bin(:args=>'-D -d', :stderr=>true).must_equal "Error: Cannot specify -D and -d together\n"
|
|
201
|
+
bin(:args=>'-m foo -d', :stderr=>true).must_equal "Error: Cannot specify -m and -d together\n"
|
|
202
|
+
bin(:args=>'-S foo -d', :stderr=>true).must_equal "Error: Cannot specify -S and -d together\n"
|
|
203
|
+
bin(:args=>'-S foo -C', :stderr=>true).must_equal "Error: Cannot specify -S and -C together\n"
|
|
206
204
|
end
|
|
207
205
|
|
|
208
206
|
it "should use a mock database if no database is given" do
|
|
209
|
-
bin(:args=>'-c "print DB.adapter_scheme"', :no_conn=>true).
|
|
207
|
+
bin(:args=>'-c "print DB.adapter_scheme"', :no_conn=>true).must_equal "mock"
|
|
210
208
|
end
|
|
211
209
|
|
|
212
210
|
it "should work with a yaml config file" do
|
|
213
211
|
File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(CONN_HASH))}
|
|
214
|
-
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).
|
|
212
|
+
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[]"
|
|
215
213
|
DB.create_table(:a){Integer :a}
|
|
216
|
-
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).
|
|
214
|
+
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
|
|
217
215
|
end
|
|
218
216
|
|
|
219
217
|
it "should work with a yaml config file with string keys" do
|
|
@@ -221,36 +219,36 @@ END
|
|
|
221
219
|
CONN_HASH.each{|k,v| h[k.to_s] = v}
|
|
222
220
|
File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(h))}
|
|
223
221
|
DB.create_table(:a){Integer :a}
|
|
224
|
-
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).
|
|
222
|
+
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
|
|
225
223
|
end
|
|
226
224
|
|
|
227
225
|
it "should work with a yaml config file with environments" do
|
|
228
226
|
File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(:development=>CONN_HASH))}
|
|
229
|
-
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).
|
|
227
|
+
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[]"
|
|
230
228
|
DB.create_table(:a){Integer :a}
|
|
231
|
-
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).
|
|
229
|
+
bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
|
|
232
230
|
end
|
|
233
231
|
|
|
234
232
|
it "-e should set environment for yaml config file" do
|
|
235
233
|
File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(:foo=>CONN_HASH))}
|
|
236
|
-
bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).
|
|
234
|
+
bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).must_equal "[]"
|
|
237
235
|
DB.create_table(:a){Integer :a}
|
|
238
|
-
bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).
|
|
236
|
+
bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
|
|
239
237
|
File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump('foo'=>CONN_HASH))}
|
|
240
|
-
bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).
|
|
238
|
+
bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
|
|
241
239
|
end
|
|
242
240
|
|
|
243
241
|
it "should run code in given filenames" do
|
|
244
242
|
File.open(TMP_FILE, 'wb'){|f| f.write('print DB.tables.inspect')}
|
|
245
|
-
bin(:post=>TMP_FILE).
|
|
243
|
+
bin(:post=>TMP_FILE).must_equal '[]'
|
|
246
244
|
DB.create_table(:a){Integer :a}
|
|
247
|
-
bin(:post=>TMP_FILE).
|
|
248
|
-
bin(:post=>TMP_FILE, :args=>'-v').
|
|
245
|
+
bin(:post=>TMP_FILE).must_equal '[:a]'
|
|
246
|
+
bin(:post=>TMP_FILE, :args=>'-v').strip.must_equal "sequel #{Sequel.version}\n[:a]"
|
|
249
247
|
end
|
|
250
248
|
|
|
251
249
|
it "should run code provided on stdin" do
|
|
252
|
-
bin(:pre=>'echo print DB.tables.inspect | ').
|
|
250
|
+
bin(:pre=>'echo print DB.tables.inspect | ').must_equal '[]'
|
|
253
251
|
DB.create_table(:a){Integer :a}
|
|
254
|
-
bin(:pre=>'echo print DB.tables.inspect | ').
|
|
252
|
+
bin(:pre=>'echo print DB.tables.inspect | ').must_equal '[:a]'
|
|
255
253
|
end
|
|
256
254
|
end
|
|
@@ -15,32 +15,32 @@ describe "An empty ConnectionPool" do
|
|
|
15
15
|
@cpool = Sequel::ConnectionPool.get_pool(mock_db.call, CONNECTION_POOL_DEFAULTS)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
@cpool.available_connections.
|
|
18
|
+
it "should have no available connections" do
|
|
19
|
+
@cpool.available_connections.must_equal []
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
@cpool.allocated.
|
|
22
|
+
it "should have no allocated connections" do
|
|
23
|
+
@cpool.allocated.must_equal({})
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
@cpool.created_count.
|
|
26
|
+
it "should have a created_count of zero" do
|
|
27
|
+
@cpool.created_count.must_equal 0
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
describe "ConnectionPool options" do
|
|
32
|
-
|
|
32
|
+
it "should support string option values" do
|
|
33
33
|
cpool = Sequel::ConnectionPool.get_pool(mock_db.call, {:max_connections=>'5', :pool_timeout=>'3', :pool_sleep_time=>'0.01'})
|
|
34
|
-
cpool.max_size.
|
|
35
|
-
cpool.instance_variable_get(:@timeout).
|
|
36
|
-
cpool.instance_variable_get(:@sleep_time).
|
|
34
|
+
cpool.max_size.must_equal 5
|
|
35
|
+
cpool.instance_variable_get(:@timeout).must_equal 3
|
|
36
|
+
cpool.instance_variable_get(:@sleep_time).must_equal 0.01 unless cpool.class::USE_WAITER
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>0)}.
|
|
41
|
-
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>-10)}.
|
|
42
|
-
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'-10')}.
|
|
43
|
-
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'0')}.
|
|
39
|
+
it "should raise an error unless size is positive" do
|
|
40
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>0)}.must_raise(Sequel::Error)
|
|
41
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>-10)}.must_raise(Sequel::Error)
|
|
42
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'-10')}.must_raise(Sequel::Error)
|
|
43
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'0')}.must_raise(Sequel::Error)
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -51,86 +51,86 @@ describe "A connection pool handling connections" do
|
|
|
51
51
|
@cpool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){:got_connection}, CONNECTION_POOL_DEFAULTS.merge(:max_connections=>@max_size))
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
it "#hold should increment #created_count" do
|
|
55
55
|
@cpool.hold do
|
|
56
|
-
@cpool.created_count.
|
|
57
|
-
@cpool.hold {@cpool.hold {@cpool.created_count.
|
|
58
|
-
Thread.new{@cpool.hold {@cpool.created_count.
|
|
56
|
+
@cpool.created_count.must_equal 1
|
|
57
|
+
@cpool.hold {@cpool.hold {@cpool.created_count.must_equal 1}}
|
|
58
|
+
Thread.new{@cpool.hold {_(@cpool.created_count).must_equal 2}}.join
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
it "#hold should add the connection to the #allocated array" do
|
|
63
63
|
@cpool.hold do
|
|
64
|
-
@cpool.allocated.size.
|
|
64
|
+
@cpool.allocated.size.must_equal 1
|
|
65
65
|
|
|
66
|
-
@cpool.allocated.
|
|
66
|
+
@cpool.allocated.must_equal(Thread.current=>:got_connection)
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
@cpool.hold {|conn| conn.
|
|
70
|
+
it "#hold should yield a new connection" do
|
|
71
|
+
@cpool.hold {|conn| conn.must_equal :got_connection}
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
it "a connection should be de-allocated after it has been used in #hold" do
|
|
75
75
|
@cpool.hold {}
|
|
76
|
-
@cpool.allocated.size.
|
|
76
|
+
@cpool.allocated.size.must_equal 0
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
@cpool.hold {:block_return}.
|
|
79
|
+
it "#hold should return the value of its block" do
|
|
80
|
+
@cpool.hold {:block_return}.must_equal :block_return
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
if RUBY_VERSION < '1.9.0' and !defined?(RUBY_ENGINE)
|
|
84
|
-
|
|
84
|
+
it "#hold should remove dead threads from the pool if it reaches its max_size" do
|
|
85
85
|
Thread.new{@cpool.hold{Thread.current.exit!}}.join
|
|
86
|
-
@cpool.allocated.keys.map{|t| t.alive?}.
|
|
86
|
+
@cpool.allocated.keys.map{|t| t.alive?}.must_equal [false]
|
|
87
87
|
|
|
88
88
|
Thread.new{@cpool.hold{Thread.current.exit!}}.join
|
|
89
|
-
@cpool.allocated.keys.map{|t| t.alive?}.
|
|
89
|
+
@cpool.allocated.keys.map{|t| t.alive?}.must_equal [false, false]
|
|
90
90
|
|
|
91
91
|
Thread.new{@cpool.hold{}}.join
|
|
92
|
-
@cpool.allocated.
|
|
92
|
+
@cpool.allocated.must_equal({})
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
it "#make_new should not make more than max_size connections" do
|
|
97
97
|
q = Queue.new
|
|
98
98
|
50.times{Thread.new{@cpool.hold{q.pop}}}
|
|
99
99
|
50.times{q.push nil}
|
|
100
|
-
@cpool.created_count.
|
|
100
|
+
@cpool.created_count.must_be :<=, @max_size
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
@max_size.
|
|
105
|
-
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.
|
|
106
|
-
@max_size.
|
|
103
|
+
it "database's disconnect connection method should be called when a disconnect is detected" do
|
|
104
|
+
@max_size.must_equal 2
|
|
105
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
|
106
|
+
@max_size.must_equal 3
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
@cpool.created_count.
|
|
109
|
+
it "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
|
110
|
+
@cpool.created_count.must_equal 0
|
|
111
111
|
q, q1 = Queue.new, Queue.new
|
|
112
112
|
@cpool.hold{Thread.new{@cpool.hold{q1.pop; q.push nil}; q1.pop; q.push nil}; q1.push nil; q.pop; q1.push nil; q.pop}
|
|
113
|
-
@cpool.created_count.
|
|
114
|
-
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.
|
|
115
|
-
@cpool.created_count.
|
|
116
|
-
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.
|
|
117
|
-
@cpool.created_count.
|
|
118
|
-
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.
|
|
119
|
-
@cpool.created_count.
|
|
113
|
+
@cpool.created_count.must_equal 2
|
|
114
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
|
115
|
+
@cpool.created_count.must_equal 1
|
|
116
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
|
117
|
+
@cpool.created_count.must_equal 0
|
|
118
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
|
119
|
+
@cpool.created_count.must_equal 0
|
|
120
120
|
end
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
describe "A connection pool handling connection errors" do
|
|
124
|
-
|
|
124
|
+
it "#hold should raise a Sequel::DatabaseConnectionError if an exception is raised by the connection_proc" do
|
|
125
125
|
cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS){raise Interrupt}
|
|
126
|
-
proc{cpool.hold{:block_return}}.
|
|
127
|
-
cpool.created_count.
|
|
126
|
+
proc{cpool.hold{:block_return}}.must_raise(Sequel::DatabaseConnectionError)
|
|
127
|
+
cpool.created_count.must_equal 0
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
it "#hold should raise a Sequel::DatabaseConnectionError if nil is returned by the connection_proc" do
|
|
131
131
|
cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS){nil}
|
|
132
|
-
proc{cpool.hold{:block_return}}.
|
|
133
|
-
cpool.created_count.
|
|
132
|
+
proc{cpool.hold{:block_return}}.must_raise(Sequel::DatabaseConnectionError)
|
|
133
|
+
cpool.created_count.must_equal 0
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
|
|
@@ -144,24 +144,24 @@ describe "ConnectionPool#hold" do
|
|
|
144
144
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{c.new}, CONNECTION_POOL_DEFAULTS)
|
|
145
145
|
end
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
it "shoulda use the database's connect method to get new connections" do
|
|
148
148
|
res = nil
|
|
149
149
|
@pool.hold {|c| res = c}
|
|
150
|
-
res.
|
|
151
|
-
res.value.
|
|
150
|
+
res.must_be_kind_of(@c)
|
|
151
|
+
res.value.must_equal 1
|
|
152
152
|
@pool.hold {|c| res = c}
|
|
153
|
-
res.
|
|
154
|
-
res.value.
|
|
153
|
+
res.must_be_kind_of(@c)
|
|
154
|
+
res.value.must_equal 1 # the connection maker is invoked only once
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
it "should be re-entrant by the same thread" do
|
|
158
158
|
cc = nil
|
|
159
159
|
@pool.hold {|c| @pool.hold {|c1| @pool.hold {|c2| cc = c2}}}
|
|
160
|
-
cc.
|
|
160
|
+
cc.must_be_kind_of(@c)
|
|
161
161
|
end
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
proc {@pool.hold {|c| c.foobar}}.
|
|
163
|
+
it "should catch exceptions and reraise them" do
|
|
164
|
+
proc {@pool.hold {|c| c.foobar}}.must_raise(NoMethodError)
|
|
165
165
|
end
|
|
166
166
|
end
|
|
167
167
|
|
|
@@ -172,51 +172,51 @@ describe "A connection pool with a max size of 1" do
|
|
|
172
172
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{icp.call; 'herro'}, CONNECTION_POOL_DEFAULTS.merge(:max_connections=>1))
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
it "should let only one thread access the connection at any time" do
|
|
176
176
|
cc,c1, c2 = nil
|
|
177
177
|
q, q1 = Queue.new, Queue.new
|
|
178
178
|
|
|
179
179
|
t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; q1.push nil; q.pop}}
|
|
180
180
|
q1.pop
|
|
181
|
-
cc.
|
|
182
|
-
c1.
|
|
181
|
+
cc.must_equal 'herro'
|
|
182
|
+
c1.must_equal 'herro'
|
|
183
183
|
|
|
184
184
|
t2 = Thread.new {@pool.hold {|c| c2 = c.dup; q1.push nil; q.pop;}}
|
|
185
185
|
|
|
186
186
|
# connection held by t1
|
|
187
|
-
t1.
|
|
188
|
-
t2.
|
|
187
|
+
t1.must_be :alive?
|
|
188
|
+
t2.must_be :alive?
|
|
189
189
|
|
|
190
|
-
cc.
|
|
191
|
-
c1.
|
|
192
|
-
c2.
|
|
190
|
+
cc.must_equal 'herro'
|
|
191
|
+
c1.must_equal 'herro'
|
|
192
|
+
c2.must_equal nil
|
|
193
193
|
|
|
194
|
-
@pool.available_connections.
|
|
195
|
-
@pool.allocated.
|
|
194
|
+
@pool.available_connections.must_be :empty?
|
|
195
|
+
@pool.allocated.must_equal(t1=>cc)
|
|
196
196
|
|
|
197
197
|
cc.gsub!('rr', 'll')
|
|
198
198
|
q.push nil
|
|
199
199
|
q1.pop
|
|
200
200
|
|
|
201
201
|
t1.join
|
|
202
|
-
t2.
|
|
202
|
+
t2.must_be :alive?
|
|
203
203
|
|
|
204
|
-
c2.
|
|
204
|
+
c2.must_equal 'hello'
|
|
205
205
|
|
|
206
|
-
@pool.available_connections.
|
|
207
|
-
@pool.allocated.
|
|
206
|
+
@pool.available_connections.must_be :empty?
|
|
207
|
+
@pool.allocated.must_equal(t2=>cc)
|
|
208
208
|
|
|
209
209
|
#connection released
|
|
210
210
|
q.push nil
|
|
211
211
|
t2.join
|
|
212
212
|
|
|
213
|
-
@invoked_count.
|
|
214
|
-
@pool.size.
|
|
215
|
-
@pool.available_connections.
|
|
216
|
-
@pool.allocated.
|
|
213
|
+
@invoked_count.must_equal 1
|
|
214
|
+
@pool.size.must_equal 1
|
|
215
|
+
@pool.available_connections.must_equal [cc]
|
|
216
|
+
@pool.allocated.must_be :empty?
|
|
217
217
|
end
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
it "should let the same thread reenter #hold" do
|
|
220
220
|
c1, c2, c3 = nil
|
|
221
221
|
@pool.hold do |c|
|
|
222
222
|
c1 = c
|
|
@@ -227,19 +227,19 @@ describe "A connection pool with a max size of 1" do
|
|
|
227
227
|
end
|
|
228
228
|
end
|
|
229
229
|
end
|
|
230
|
-
c1.
|
|
231
|
-
c2.
|
|
232
|
-
c3.
|
|
230
|
+
c1.must_equal 'herro'
|
|
231
|
+
c2.must_equal 'herro'
|
|
232
|
+
c3.must_equal 'herro'
|
|
233
233
|
|
|
234
|
-
@invoked_count.
|
|
235
|
-
@pool.size.
|
|
236
|
-
@pool.available_connections.size.
|
|
237
|
-
@pool.allocated.
|
|
234
|
+
@invoked_count.must_equal 1
|
|
235
|
+
@pool.size.must_equal 1
|
|
236
|
+
@pool.available_connections.size.must_equal 1
|
|
237
|
+
@pool.allocated.must_be :empty?
|
|
238
238
|
end
|
|
239
239
|
end
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
ThreadedConnectionPoolSpecs = shared_description do
|
|
242
|
+
it "should not have all_connections yield connections allocated to other threads" do
|
|
243
243
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
|
|
244
244
|
q, q1 = Queue.new, Queue.new
|
|
245
245
|
t = Thread.new do
|
|
@@ -250,13 +250,13 @@ shared_examples_for "A threaded connection pool" do
|
|
|
250
250
|
end
|
|
251
251
|
pool.hold do |c1|
|
|
252
252
|
q1.pop
|
|
253
|
-
pool.all_connections{|c| c.
|
|
253
|
+
pool.all_connections{|c| c.must_equal c1}
|
|
254
254
|
q.push nil
|
|
255
255
|
end
|
|
256
256
|
t.join
|
|
257
257
|
end
|
|
258
258
|
|
|
259
|
-
|
|
259
|
+
it "should wait until a connection is available if all are checked out" do
|
|
260
260
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0.1, :pool_sleep_time=>0))
|
|
261
261
|
q, q1 = Queue.new, Queue.new
|
|
262
262
|
t = Thread.new do
|
|
@@ -267,12 +267,12 @@ shared_examples_for "A threaded connection pool" do
|
|
|
267
267
|
end
|
|
268
268
|
end
|
|
269
269
|
q1.pop
|
|
270
|
-
proc{pool.hold{}}.
|
|
270
|
+
proc{pool.hold{}}.must_raise(Sequel::PoolTimeout)
|
|
271
271
|
q.push nil
|
|
272
272
|
t.join
|
|
273
273
|
end
|
|
274
274
|
|
|
275
|
-
|
|
275
|
+
it "should not have all_connections yield all available connections" do
|
|
276
276
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
|
|
277
277
|
q, q1 = Queue.new, Queue.new
|
|
278
278
|
b = []
|
|
@@ -291,128 +291,128 @@ shared_examples_for "A threaded connection pool" do
|
|
|
291
291
|
t.join
|
|
292
292
|
a = []
|
|
293
293
|
pool.all_connections{|c| a << c}
|
|
294
|
-
a.sort.
|
|
294
|
+
a.sort.must_equal b.sort
|
|
295
295
|
end
|
|
296
296
|
|
|
297
|
-
|
|
297
|
+
it "should raise a PoolTimeout error if a connection couldn't be acquired before timeout" do
|
|
298
298
|
q, q1 = Queue.new, Queue.new
|
|
299
299
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
|
|
300
300
|
t = Thread.new{pool.hold{|c| q1.push nil; q.pop}}
|
|
301
301
|
q1.pop
|
|
302
|
-
proc{pool.hold{|c|}}.
|
|
302
|
+
proc{pool.hold{|c|}}.must_raise(Sequel::PoolTimeout)
|
|
303
303
|
q.push nil
|
|
304
304
|
t.join
|
|
305
305
|
end
|
|
306
306
|
|
|
307
307
|
it "should not add a disconnected connection back to the pool if the disconnection_proc raises an error" do
|
|
308
308
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| raise Sequel::Error}, &@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
|
|
309
|
-
proc{pool.hold{raise Sequel::DatabaseDisconnectError}}.
|
|
310
|
-
pool.available_connections.length.
|
|
309
|
+
proc{pool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::Error)
|
|
310
|
+
pool.available_connections.length.must_equal 0
|
|
311
311
|
end
|
|
312
312
|
|
|
313
|
-
|
|
313
|
+
it "should let five threads simultaneously access separate connections" do
|
|
314
314
|
cc = {}
|
|
315
315
|
threads = []
|
|
316
316
|
q, q1, q2 = Queue.new, Queue.new, Queue.new
|
|
317
317
|
|
|
318
318
|
5.times{|i| threads << Thread.new{@pool.hold{|c| q.pop; cc[i] = c; q1.push nil; q2.pop}}; q.push nil; q1.pop}
|
|
319
|
-
threads.each {|t| t.
|
|
320
|
-
cc.size.
|
|
321
|
-
@invoked_count.
|
|
322
|
-
@pool.size.
|
|
323
|
-
@pool.available_connections.
|
|
319
|
+
threads.each {|t| t.must_be :alive?}
|
|
320
|
+
cc.size.must_equal 5
|
|
321
|
+
@invoked_count.must_equal 5
|
|
322
|
+
@pool.size.must_equal 5
|
|
323
|
+
@pool.available_connections.must_be :empty?
|
|
324
324
|
|
|
325
325
|
h = {}
|
|
326
326
|
i = 0
|
|
327
327
|
threads.each{|t| h[t] = (i+=1)}
|
|
328
|
-
@pool.allocated.
|
|
329
|
-
@pool.available_connections.
|
|
328
|
+
@pool.allocated.must_equal h
|
|
329
|
+
@pool.available_connections.must_equal []
|
|
330
330
|
5.times{q2.push nil}
|
|
331
331
|
threads.each{|t| t.join}
|
|
332
332
|
|
|
333
|
-
@pool.available_connections.size.
|
|
334
|
-
@pool.allocated.
|
|
333
|
+
@pool.available_connections.size.must_equal 5
|
|
334
|
+
@pool.allocated.must_be :empty?
|
|
335
335
|
end
|
|
336
336
|
|
|
337
|
-
|
|
337
|
+
it "should block threads until a connection becomes available" do
|
|
338
338
|
cc = {}
|
|
339
339
|
threads = []
|
|
340
340
|
q, q1 = Queue.new, Queue.new
|
|
341
341
|
|
|
342
342
|
5.times{|i| threads << Thread.new{@pool.hold{|c| cc[i] = c; q1.push nil; q.pop}}}
|
|
343
343
|
5.times{q1.pop}
|
|
344
|
-
threads.each {|t| t.
|
|
345
|
-
@pool.available_connections.
|
|
344
|
+
threads.each {|t| t.must_be :alive?}
|
|
345
|
+
@pool.available_connections.must_be :empty?
|
|
346
346
|
|
|
347
347
|
3.times {|i| threads << Thread.new {@pool.hold {|c| cc[i + 5] = c; q1.push nil}}}
|
|
348
348
|
|
|
349
|
-
threads[5].
|
|
350
|
-
threads[6].
|
|
351
|
-
threads[7].
|
|
352
|
-
cc.size.
|
|
353
|
-
cc[5].
|
|
354
|
-
cc[6].
|
|
355
|
-
cc[7].
|
|
349
|
+
threads[5].must_be :alive?
|
|
350
|
+
threads[6].must_be :alive?
|
|
351
|
+
threads[7].must_be :alive?
|
|
352
|
+
cc.size.must_equal 5
|
|
353
|
+
cc[5].must_equal nil
|
|
354
|
+
cc[6].must_equal nil
|
|
355
|
+
cc[7].must_equal nil
|
|
356
356
|
|
|
357
357
|
5.times{q.push nil}
|
|
358
358
|
5.times{|i| threads[i].join}
|
|
359
359
|
3.times{q1.pop}
|
|
360
360
|
3.times{|i| threads[i+5].join}
|
|
361
361
|
|
|
362
|
-
threads.each {|t| t.
|
|
362
|
+
threads.each {|t| t.wont_be :alive?}
|
|
363
363
|
|
|
364
|
-
@pool.size.
|
|
365
|
-
@invoked_count.
|
|
366
|
-
@pool.available_connections.size.
|
|
367
|
-
@pool.allocated.
|
|
364
|
+
@pool.size.must_equal 5
|
|
365
|
+
@invoked_count.must_equal 5
|
|
366
|
+
@pool.available_connections.size.must_equal 5
|
|
367
|
+
@pool.allocated.must_be :empty?
|
|
368
368
|
end
|
|
369
369
|
|
|
370
|
-
|
|
370
|
+
it "should store connections in a stack if :connection_handling=>:stack" do
|
|
371
371
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:stack))
|
|
372
372
|
c2 = nil
|
|
373
373
|
c = @pool.hold{|cc| Thread.new{@pool.hold{|cc2| c2 = cc2}}.join; cc}
|
|
374
|
-
@pool.size.
|
|
375
|
-
@pool.hold{|cc| cc.
|
|
376
|
-
@pool.hold{|cc| cc.
|
|
374
|
+
@pool.size.must_equal 2
|
|
375
|
+
@pool.hold{|cc| cc.must_equal c}
|
|
376
|
+
@pool.hold{|cc| cc.must_equal c}
|
|
377
377
|
@pool.hold do |cc|
|
|
378
|
-
cc.
|
|
379
|
-
Thread.new{@pool.hold{|cc2| cc2.
|
|
378
|
+
cc.must_equal c
|
|
379
|
+
Thread.new{@pool.hold{|cc2| cc2.must_equal c2}}
|
|
380
380
|
end
|
|
381
381
|
end
|
|
382
382
|
|
|
383
|
-
|
|
383
|
+
it "should store connections in a queue if :connection_handling=>:queue" do
|
|
384
384
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:queue))
|
|
385
385
|
c2 = nil
|
|
386
386
|
c = @pool.hold{|cc| Thread.new{@pool.hold{|cc2| c2 = cc2}}.join; cc}
|
|
387
|
-
@pool.size.
|
|
388
|
-
@pool.hold{|cc| cc.
|
|
389
|
-
@pool.hold{|cc| cc.
|
|
387
|
+
@pool.size.must_equal 2
|
|
388
|
+
@pool.hold{|cc| cc.must_equal c2}
|
|
389
|
+
@pool.hold{|cc| cc.must_equal c}
|
|
390
390
|
@pool.hold do |cc|
|
|
391
|
-
cc.
|
|
392
|
-
Thread.new{@pool.hold{|cc2| cc2.
|
|
391
|
+
cc.must_equal c2
|
|
392
|
+
Thread.new{@pool.hold{|cc2| cc2.must_equal c}}
|
|
393
393
|
end
|
|
394
394
|
end
|
|
395
395
|
|
|
396
|
-
|
|
396
|
+
it "should not store connections if :connection_handling=>:disconnect" do
|
|
397
397
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:disconnect))
|
|
398
398
|
d = []
|
|
399
399
|
meta_def(@pool.db, :disconnect_connection){|c| d << c}
|
|
400
400
|
@pool.hold do |cc|
|
|
401
|
-
cc.
|
|
402
|
-
Thread.new{@pool.hold{|cc2| cc2.
|
|
403
|
-
d.
|
|
404
|
-
@pool.hold{|cc3| cc3.
|
|
401
|
+
cc.must_equal 1
|
|
402
|
+
Thread.new{@pool.hold{|cc2| _(cc2).must_equal 2}}.join
|
|
403
|
+
d.must_equal [2]
|
|
404
|
+
@pool.hold{|cc3| cc3.must_equal 1}
|
|
405
405
|
end
|
|
406
|
-
@pool.size.
|
|
407
|
-
d.
|
|
406
|
+
@pool.size.must_equal 0
|
|
407
|
+
d.must_equal [2, 1]
|
|
408
408
|
|
|
409
|
-
@pool.hold{|cc| cc.
|
|
410
|
-
@pool.size.
|
|
411
|
-
d.
|
|
409
|
+
@pool.hold{|cc| cc.must_equal 3}
|
|
410
|
+
@pool.size.must_equal 0
|
|
411
|
+
d.must_equal [2, 1, 3]
|
|
412
412
|
|
|
413
|
-
@pool.hold{|cc| cc.
|
|
414
|
-
@pool.size.
|
|
415
|
-
d.
|
|
413
|
+
@pool.hold{|cc| cc.must_equal 4}
|
|
414
|
+
@pool.size.must_equal 0
|
|
415
|
+
d.must_equal [2, 1, 3, 4]
|
|
416
416
|
end
|
|
417
417
|
end
|
|
418
418
|
|
|
@@ -424,7 +424,7 @@ describe "Threaded Unsharded Connection Pool" do
|
|
|
424
424
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts)
|
|
425
425
|
end
|
|
426
426
|
|
|
427
|
-
|
|
427
|
+
include ThreadedConnectionPoolSpecs
|
|
428
428
|
end
|
|
429
429
|
|
|
430
430
|
describe "Threaded Sharded Connection Pool" do
|
|
@@ -435,7 +435,7 @@ describe "Threaded Sharded Connection Pool" do
|
|
|
435
435
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts)
|
|
436
436
|
end
|
|
437
437
|
|
|
438
|
-
|
|
438
|
+
include ThreadedConnectionPoolSpecs
|
|
439
439
|
end
|
|
440
440
|
|
|
441
441
|
describe "ConnectionPool#disconnect" do
|
|
@@ -451,34 +451,34 @@ describe "ConnectionPool#disconnect" do
|
|
|
451
451
|
threads.each {|t| t.join}
|
|
452
452
|
end
|
|
453
453
|
|
|
454
|
-
|
|
455
|
-
@pool.size.
|
|
456
|
-
@pool.available_connections.size.
|
|
457
|
-
@pool.available_connections.each {|c| c[:id].
|
|
454
|
+
it "should invoke the given block for each available connection" do
|
|
455
|
+
@pool.size.must_equal 5
|
|
456
|
+
@pool.available_connections.size.must_equal 5
|
|
457
|
+
@pool.available_connections.each {|c| c[:id].wont_equal nil}
|
|
458
458
|
conns = []
|
|
459
459
|
meta_def(@pool.db, :disconnect_connection){|c| conns << c}
|
|
460
460
|
@pool.disconnect
|
|
461
|
-
conns.size.
|
|
461
|
+
conns.size.must_equal 5
|
|
462
462
|
end
|
|
463
463
|
|
|
464
|
-
|
|
465
|
-
@pool.size.
|
|
464
|
+
it "should remove all available connections" do
|
|
465
|
+
@pool.size.must_equal 5
|
|
466
466
|
@pool.disconnect
|
|
467
|
-
@pool.size.
|
|
467
|
+
@pool.size.must_equal 0
|
|
468
468
|
end
|
|
469
469
|
|
|
470
|
-
|
|
471
|
-
@pool.size.
|
|
470
|
+
it "should disconnect connections in use as soon as they are no longer in use" do
|
|
471
|
+
@pool.size.must_equal 5
|
|
472
472
|
@pool.hold do |conn|
|
|
473
|
-
@pool.available_connections.size.
|
|
474
|
-
@pool.available_connections.each {|c| c.
|
|
473
|
+
@pool.available_connections.size.must_equal 4
|
|
474
|
+
@pool.available_connections.each {|c| c.wont_be_same_as(conn)}
|
|
475
475
|
conns = []
|
|
476
476
|
meta_def(@pool.db, :disconnect_connection){|c| conns << c}
|
|
477
477
|
@pool.disconnect
|
|
478
|
-
conns.size.
|
|
479
|
-
@pool.size.
|
|
478
|
+
conns.size.must_equal 4
|
|
479
|
+
@pool.size.must_equal 1
|
|
480
480
|
end
|
|
481
|
-
@pool.size.
|
|
481
|
+
@pool.size.must_equal 0
|
|
482
482
|
end
|
|
483
483
|
end
|
|
484
484
|
|
|
@@ -488,187 +488,187 @@ describe "A connection pool with multiple servers" do
|
|
|
488
488
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}}))
|
|
489
489
|
end
|
|
490
490
|
|
|
491
|
-
|
|
491
|
+
it "should support preconnect method that immediately creates the maximum number of connections" do
|
|
492
492
|
@pool.send(:preconnect)
|
|
493
493
|
i = 0
|
|
494
494
|
@pool.all_connections{|c1| i+=1}
|
|
495
|
-
i.
|
|
495
|
+
i.must_equal @pool.max_size * 2
|
|
496
496
|
end
|
|
497
497
|
|
|
498
|
-
|
|
498
|
+
it "#all_connections should return connections for all servers" do
|
|
499
499
|
@pool.hold{}
|
|
500
|
-
@pool.all_connections{|c1| c1.
|
|
500
|
+
@pool.all_connections{|c1| c1.must_equal "default1"}
|
|
501
501
|
a = []
|
|
502
502
|
@pool.hold(:read_only) do |c|
|
|
503
503
|
@pool.all_connections{|c1| a << c1}
|
|
504
504
|
end
|
|
505
|
-
a.sort_by{|c| c.to_s}.
|
|
505
|
+
a.sort_by{|c| c.to_s}.must_equal ["default1", "read_only1"]
|
|
506
506
|
end
|
|
507
507
|
|
|
508
|
-
|
|
509
|
-
@pool.servers.sort_by{|s| s.to_s}.
|
|
508
|
+
it "#servers should return symbols for all servers" do
|
|
509
|
+
@pool.servers.sort_by{|s| s.to_s}.must_equal [:default, :read_only]
|
|
510
510
|
end
|
|
511
511
|
|
|
512
|
-
|
|
513
|
-
@pool.size.
|
|
512
|
+
it "should use the :default server by default" do
|
|
513
|
+
@pool.size.must_equal 0
|
|
514
514
|
@pool.hold do |c|
|
|
515
|
-
c.
|
|
516
|
-
@pool.allocated.
|
|
515
|
+
c.must_equal "default1"
|
|
516
|
+
@pool.allocated.must_equal(Thread.current=>"default1")
|
|
517
517
|
end
|
|
518
|
-
@pool.available_connections.
|
|
519
|
-
@pool.size.
|
|
520
|
-
@invoked_counts.
|
|
518
|
+
@pool.available_connections.must_equal ["default1"]
|
|
519
|
+
@pool.size.must_equal 1
|
|
520
|
+
@invoked_counts.must_equal(:default=>1)
|
|
521
521
|
end
|
|
522
522
|
|
|
523
|
-
|
|
523
|
+
it "should use the :default server an invalid server is used" do
|
|
524
524
|
@pool.hold do |c1|
|
|
525
|
-
c1.
|
|
525
|
+
c1.must_equal "default1"
|
|
526
526
|
@pool.hold(:blah) do |c2|
|
|
527
|
-
c2.
|
|
527
|
+
c2.must_equal c1
|
|
528
528
|
@pool.hold(:blah2) do |c3|
|
|
529
|
-
c2.
|
|
529
|
+
c2.must_equal c3
|
|
530
530
|
end
|
|
531
531
|
end
|
|
532
532
|
end
|
|
533
533
|
end
|
|
534
534
|
|
|
535
|
-
|
|
535
|
+
it "should support a :servers_hash option used for converting the server argument" do
|
|
536
536
|
ic = @invoked_counts
|
|
537
537
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, CONNECTION_POOL_DEFAULTS.merge(:servers_hash=>Hash.new(:read_only), :servers=>{:read_only=>{}}))
|
|
538
538
|
@pool.hold(:blah) do |c1|
|
|
539
|
-
c1.
|
|
539
|
+
c1.must_equal "read_only1"
|
|
540
540
|
@pool.hold(:blah) do |c2|
|
|
541
|
-
c2.
|
|
541
|
+
c2.must_equal c1
|
|
542
542
|
@pool.hold(:blah2) do |c3|
|
|
543
|
-
c2.
|
|
543
|
+
c2.must_equal c3
|
|
544
544
|
end
|
|
545
545
|
end
|
|
546
546
|
end
|
|
547
547
|
|
|
548
548
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, CONNECTION_POOL_DEFAULTS.merge(:servers_hash=>Hash.new{|h,k| raise Sequel::Error}, :servers=>{:read_only=>{}}))
|
|
549
|
-
proc{@pool.hold(:blah){|c1|}}.
|
|
549
|
+
proc{@pool.hold(:blah){|c1|}}.must_raise(Sequel::Error)
|
|
550
550
|
end
|
|
551
551
|
|
|
552
|
-
|
|
553
|
-
@pool.size(:read_only).
|
|
552
|
+
it "should use the requested server if server is given" do
|
|
553
|
+
@pool.size(:read_only).must_equal 0
|
|
554
554
|
@pool.hold(:read_only) do |c|
|
|
555
|
-
c.
|
|
556
|
-
@pool.allocated(:read_only).
|
|
555
|
+
c.must_equal "read_only1"
|
|
556
|
+
@pool.allocated(:read_only).must_equal(Thread.current=>"read_only1")
|
|
557
557
|
end
|
|
558
|
-
@pool.available_connections(:read_only).
|
|
559
|
-
@pool.size(:read_only).
|
|
560
|
-
@invoked_counts.
|
|
558
|
+
@pool.available_connections(:read_only).must_equal ["read_only1"]
|
|
559
|
+
@pool.size(:read_only).must_equal 1
|
|
560
|
+
@invoked_counts.must_equal(:read_only=>1)
|
|
561
561
|
end
|
|
562
562
|
|
|
563
|
-
|
|
563
|
+
it "#hold should only yield connections for the server requested" do
|
|
564
564
|
@pool.hold(:read_only) do |c|
|
|
565
|
-
c.
|
|
566
|
-
@pool.allocated(:read_only).
|
|
565
|
+
c.must_equal "read_only1"
|
|
566
|
+
@pool.allocated(:read_only).must_equal(Thread.current=>"read_only1")
|
|
567
567
|
@pool.hold do |d|
|
|
568
|
-
d.
|
|
568
|
+
d.must_equal "default1"
|
|
569
569
|
@pool.hold do |e|
|
|
570
|
-
e.
|
|
571
|
-
@pool.hold(:read_only){|b| b.
|
|
570
|
+
e.must_equal d
|
|
571
|
+
@pool.hold(:read_only){|b| b.must_equal c}
|
|
572
572
|
end
|
|
573
|
-
@pool.allocated.
|
|
573
|
+
@pool.allocated.must_equal(Thread.current=>"default1")
|
|
574
574
|
end
|
|
575
575
|
end
|
|
576
|
-
@invoked_counts.
|
|
576
|
+
@invoked_counts.must_equal(:read_only=>1, :default=>1)
|
|
577
577
|
end
|
|
578
578
|
|
|
579
|
-
|
|
579
|
+
it "#disconnect should disconnect from all servers" do
|
|
580
580
|
@pool.hold(:read_only){}
|
|
581
581
|
@pool.hold{}
|
|
582
582
|
conns = []
|
|
583
|
-
@pool.size.
|
|
584
|
-
@pool.size(:read_only).
|
|
583
|
+
@pool.size.must_equal 1
|
|
584
|
+
@pool.size(:read_only).must_equal 1
|
|
585
585
|
meta_def(@pool.db, :disconnect_connection){|c| conns << c}
|
|
586
586
|
@pool.disconnect
|
|
587
|
-
conns.sort.
|
|
588
|
-
@pool.size.
|
|
589
|
-
@pool.size(:read_only).
|
|
590
|
-
@pool.hold(:read_only){|c| c.
|
|
591
|
-
@pool.hold{|c| c.
|
|
587
|
+
conns.sort.must_equal %w'default1 read_only1'
|
|
588
|
+
@pool.size.must_equal 0
|
|
589
|
+
@pool.size(:read_only).must_equal 0
|
|
590
|
+
@pool.hold(:read_only){|c| c.must_equal 'read_only2'}
|
|
591
|
+
@pool.hold{|c| c.must_equal 'default2'}
|
|
592
592
|
end
|
|
593
593
|
|
|
594
|
-
|
|
594
|
+
it "#add_servers should add new servers to the pool" do
|
|
595
595
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
|
596
596
|
|
|
597
597
|
pool.hold{}
|
|
598
598
|
pool.hold(:server2){}
|
|
599
599
|
pool.hold(:server3){}
|
|
600
600
|
pool.hold(:server1) do
|
|
601
|
-
pool.allocated.length.
|
|
602
|
-
pool.allocated(:server1).length.
|
|
603
|
-
pool.allocated(:server2).
|
|
604
|
-
pool.allocated(:server3).
|
|
605
|
-
pool.available_connections.length.
|
|
606
|
-
pool.available_connections(:server1).length.
|
|
607
|
-
pool.available_connections(:server2).
|
|
608
|
-
pool.available_connections(:server3).
|
|
601
|
+
pool.allocated.length.must_equal 0
|
|
602
|
+
pool.allocated(:server1).length.must_equal 1
|
|
603
|
+
pool.allocated(:server2).must_equal nil
|
|
604
|
+
pool.allocated(:server3).must_equal nil
|
|
605
|
+
pool.available_connections.length.must_equal 1
|
|
606
|
+
pool.available_connections(:server1).length.must_equal 0
|
|
607
|
+
pool.available_connections(:server2).must_equal nil
|
|
608
|
+
pool.available_connections(:server3).must_equal nil
|
|
609
609
|
|
|
610
610
|
pool.add_servers([:server2, :server3])
|
|
611
611
|
pool.hold(:server2){}
|
|
612
612
|
pool.hold(:server3) do
|
|
613
|
-
pool.allocated.length.
|
|
614
|
-
pool.allocated(:server1).length.
|
|
615
|
-
pool.allocated(:server2).length.
|
|
616
|
-
pool.allocated(:server3).length.
|
|
617
|
-
pool.available_connections.length.
|
|
618
|
-
pool.available_connections(:server1).length.
|
|
619
|
-
pool.available_connections(:server2).length.
|
|
620
|
-
pool.available_connections(:server3).length.
|
|
613
|
+
pool.allocated.length.must_equal 0
|
|
614
|
+
pool.allocated(:server1).length.must_equal 1
|
|
615
|
+
pool.allocated(:server2).length.must_equal 0
|
|
616
|
+
pool.allocated(:server3).length.must_equal 1
|
|
617
|
+
pool.available_connections.length.must_equal 1
|
|
618
|
+
pool.available_connections(:server1).length.must_equal 0
|
|
619
|
+
pool.available_connections(:server2).length.must_equal 1
|
|
620
|
+
pool.available_connections(:server3).length.must_equal 0
|
|
621
621
|
end
|
|
622
622
|
end
|
|
623
623
|
end
|
|
624
624
|
|
|
625
|
-
|
|
625
|
+
it "#add_servers should ignore existing keys" do
|
|
626
626
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
|
627
627
|
|
|
628
|
-
pool.allocated.length.
|
|
629
|
-
pool.allocated(:server1).length.
|
|
630
|
-
pool.available_connections.length.
|
|
631
|
-
pool.available_connections(:server1).length.
|
|
628
|
+
pool.allocated.length.must_equal 0
|
|
629
|
+
pool.allocated(:server1).length.must_equal 0
|
|
630
|
+
pool.available_connections.length.must_equal 0
|
|
631
|
+
pool.available_connections(:server1).length.must_equal 0
|
|
632
632
|
pool.hold do |c1|
|
|
633
|
-
c1.
|
|
634
|
-
pool.allocated.length.
|
|
635
|
-
pool.allocated(:server1).length.
|
|
636
|
-
pool.available_connections.length.
|
|
637
|
-
pool.available_connections(:server1).length.
|
|
633
|
+
c1.must_equal :default
|
|
634
|
+
pool.allocated.length.must_equal 1
|
|
635
|
+
pool.allocated(:server1).length.must_equal 0
|
|
636
|
+
pool.available_connections.length.must_equal 0
|
|
637
|
+
pool.available_connections(:server1).length.must_equal 0
|
|
638
638
|
pool.hold(:server1) do |c2|
|
|
639
|
-
c2.
|
|
640
|
-
pool.allocated.length.
|
|
641
|
-
pool.allocated(:server1).length.
|
|
642
|
-
pool.available_connections.length.
|
|
643
|
-
pool.available_connections(:server1).length.
|
|
639
|
+
c2.must_equal :server1
|
|
640
|
+
pool.allocated.length.must_equal 1
|
|
641
|
+
pool.allocated(:server1).length.must_equal 1
|
|
642
|
+
pool.available_connections.length.must_equal 0
|
|
643
|
+
pool.available_connections(:server1).length.must_equal 0
|
|
644
644
|
pool.add_servers([:default, :server1])
|
|
645
|
-
pool.allocated.length.
|
|
646
|
-
pool.allocated(:server1).length.
|
|
647
|
-
pool.available_connections.length.
|
|
648
|
-
pool.available_connections(:server1).length.
|
|
645
|
+
pool.allocated.length.must_equal 1
|
|
646
|
+
pool.allocated(:server1).length.must_equal 1
|
|
647
|
+
pool.available_connections.length.must_equal 0
|
|
648
|
+
pool.available_connections(:server1).length.must_equal 0
|
|
649
649
|
end
|
|
650
|
-
pool.allocated.length.
|
|
651
|
-
pool.allocated(:server1).length.
|
|
652
|
-
pool.available_connections.length.
|
|
653
|
-
pool.available_connections(:server1).length.
|
|
650
|
+
pool.allocated.length.must_equal 1
|
|
651
|
+
pool.allocated(:server1).length.must_equal 0
|
|
652
|
+
pool.available_connections.length.must_equal 0
|
|
653
|
+
pool.available_connections(:server1).length.must_equal 1
|
|
654
654
|
pool.add_servers([:default, :server1])
|
|
655
|
-
pool.allocated.length.
|
|
656
|
-
pool.allocated(:server1).length.
|
|
657
|
-
pool.available_connections.length.
|
|
658
|
-
pool.available_connections(:server1).length.
|
|
655
|
+
pool.allocated.length.must_equal 1
|
|
656
|
+
pool.allocated(:server1).length.must_equal 0
|
|
657
|
+
pool.available_connections.length.must_equal 0
|
|
658
|
+
pool.available_connections(:server1).length.must_equal 1
|
|
659
659
|
end
|
|
660
|
-
pool.allocated.length.
|
|
661
|
-
pool.allocated(:server1).length.
|
|
662
|
-
pool.available_connections.length.
|
|
663
|
-
pool.available_connections(:server1).length.
|
|
660
|
+
pool.allocated.length.must_equal 0
|
|
661
|
+
pool.allocated(:server1).length.must_equal 0
|
|
662
|
+
pool.available_connections.length.must_equal 1
|
|
663
|
+
pool.available_connections(:server1).length.must_equal 1
|
|
664
664
|
pool.add_servers([:default, :server1])
|
|
665
|
-
pool.allocated.length.
|
|
666
|
-
pool.allocated(:server1).length.
|
|
667
|
-
pool.available_connections.length.
|
|
668
|
-
pool.available_connections(:server1).length.
|
|
665
|
+
pool.allocated.length.must_equal 0
|
|
666
|
+
pool.allocated(:server1).length.must_equal 0
|
|
667
|
+
pool.available_connections.length.must_equal 1
|
|
668
|
+
pool.available_connections(:server1).length.must_equal 1
|
|
669
669
|
end
|
|
670
670
|
|
|
671
|
-
|
|
671
|
+
it "#remove_servers should disconnect available connections immediately" do
|
|
672
672
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :max_connections=>5, :servers=>{:server1=>{}})
|
|
673
673
|
threads = []
|
|
674
674
|
q, q1 = Queue.new, Queue.new
|
|
@@ -677,57 +677,57 @@ describe "A connection pool with multiple servers" do
|
|
|
677
677
|
5.times{q.push nil}
|
|
678
678
|
threads.each {|t| t.join}
|
|
679
679
|
|
|
680
|
-
pool.size(:server1).
|
|
680
|
+
pool.size(:server1).must_equal 5
|
|
681
681
|
pool.remove_servers([:server1])
|
|
682
|
-
pool.size(:server1).
|
|
682
|
+
pool.size(:server1).must_equal 0
|
|
683
683
|
end
|
|
684
684
|
|
|
685
|
-
|
|
685
|
+
it "#remove_servers should disconnect connections in use as soon as they are returned to the pool" do
|
|
686
686
|
dc = []
|
|
687
687
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| dc << c}){|c| c}, :servers=>{:server1=>{}})
|
|
688
688
|
c1 = nil
|
|
689
689
|
pool.hold(:server1) do |c|
|
|
690
|
-
pool.size(:server1).
|
|
691
|
-
dc.
|
|
690
|
+
pool.size(:server1).must_equal 1
|
|
691
|
+
dc.must_equal []
|
|
692
692
|
pool.remove_servers([:server1])
|
|
693
|
-
pool.size(:server1).
|
|
694
|
-
dc.
|
|
693
|
+
pool.size(:server1).must_equal 0
|
|
694
|
+
dc.must_equal []
|
|
695
695
|
c1 = c
|
|
696
696
|
end
|
|
697
|
-
pool.size(:server1).
|
|
698
|
-
dc.
|
|
697
|
+
pool.size(:server1).must_equal 0
|
|
698
|
+
dc.must_equal [c1]
|
|
699
699
|
end
|
|
700
700
|
|
|
701
|
-
|
|
701
|
+
it "#remove_servers should remove server related data structures immediately" do
|
|
702
702
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
|
703
|
-
pool.available_connections(:server1).
|
|
704
|
-
pool.allocated(:server1).
|
|
703
|
+
pool.available_connections(:server1).must_equal []
|
|
704
|
+
pool.allocated(:server1).must_equal({})
|
|
705
705
|
pool.remove_servers([:server1])
|
|
706
|
-
pool.available_connections(:server1).
|
|
707
|
-
pool.allocated(:server1).
|
|
706
|
+
pool.available_connections(:server1).must_equal nil
|
|
707
|
+
pool.allocated(:server1).must_equal nil
|
|
708
708
|
end
|
|
709
709
|
|
|
710
|
-
|
|
710
|
+
it "#remove_servers should not allow the removal of the default server" do
|
|
711
711
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
|
712
|
-
|
|
713
|
-
proc{pool.remove_servers([:default])}.
|
|
712
|
+
pool.remove_servers([:server1])
|
|
713
|
+
proc{pool.remove_servers([:default])}.must_raise(Sequel::Error)
|
|
714
714
|
end
|
|
715
715
|
|
|
716
|
-
|
|
716
|
+
it "#remove_servers should ignore servers that have already been removed" do
|
|
717
717
|
dc = []
|
|
718
718
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| dc << c}){|c| c}, :servers=>{:server1=>{}})
|
|
719
719
|
c1 = nil
|
|
720
720
|
pool.hold(:server1) do |c|
|
|
721
|
-
pool.size(:server1).
|
|
722
|
-
dc.
|
|
721
|
+
pool.size(:server1).must_equal 1
|
|
722
|
+
dc.must_equal []
|
|
723
723
|
pool.remove_servers([:server1])
|
|
724
724
|
pool.remove_servers([:server1])
|
|
725
|
-
pool.size(:server1).
|
|
726
|
-
dc.
|
|
725
|
+
pool.size(:server1).must_equal 0
|
|
726
|
+
dc.must_equal []
|
|
727
727
|
c1 = c
|
|
728
728
|
end
|
|
729
|
-
pool.size(:server1).
|
|
730
|
-
dc.
|
|
729
|
+
pool.size(:server1).must_equal 0
|
|
730
|
+
dc.must_equal [c1]
|
|
731
731
|
end
|
|
732
732
|
end
|
|
733
733
|
|
|
@@ -738,20 +738,20 @@ describe "SingleConnectionPool" do
|
|
|
738
738
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{1234}, ST_CONNECTION_POOL_DEFAULTS)
|
|
739
739
|
end
|
|
740
740
|
|
|
741
|
-
|
|
741
|
+
it "should provide a #hold method" do
|
|
742
742
|
conn = nil
|
|
743
743
|
@pool.hold{|c| conn = c}
|
|
744
|
-
conn.
|
|
744
|
+
conn.must_equal 1234
|
|
745
745
|
end
|
|
746
746
|
|
|
747
|
-
|
|
747
|
+
it "should provide a #disconnect method" do
|
|
748
748
|
conn = nil
|
|
749
749
|
x = nil
|
|
750
750
|
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| conn = c}){1234}, ST_CONNECTION_POOL_DEFAULTS)
|
|
751
751
|
pool.hold{|c| x = c}
|
|
752
|
-
x.
|
|
752
|
+
x.must_equal 1234
|
|
753
753
|
pool.disconnect
|
|
754
|
-
conn.
|
|
754
|
+
conn.must_equal 1234
|
|
755
755
|
end
|
|
756
756
|
end
|
|
757
757
|
|
|
@@ -762,242 +762,242 @@ describe "A single threaded pool with multiple servers" do
|
|
|
762
762
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){|c| c}, ST_CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}}))
|
|
763
763
|
end
|
|
764
764
|
|
|
765
|
-
|
|
765
|
+
it "should support preconnect method that immediately creates the maximum number of connections" do
|
|
766
766
|
@pool.send(:preconnect)
|
|
767
767
|
i = 0
|
|
768
768
|
@pool.all_connections{|c1| i+=1}
|
|
769
|
-
i.
|
|
769
|
+
i.must_equal 2
|
|
770
770
|
end
|
|
771
771
|
|
|
772
|
-
|
|
772
|
+
it "#all_connections should return connections for all servers" do
|
|
773
773
|
@pool.hold{}
|
|
774
|
-
@pool.all_connections{|c1| c1.
|
|
774
|
+
@pool.all_connections{|c1| c1.must_equal :default}
|
|
775
775
|
a = []
|
|
776
776
|
@pool.hold(:read_only) do
|
|
777
777
|
@pool.all_connections{|c1| a << c1}
|
|
778
778
|
end
|
|
779
|
-
a.sort_by{|c| c.to_s}.
|
|
779
|
+
a.sort_by{|c| c.to_s}.must_equal [:default, :read_only]
|
|
780
780
|
end
|
|
781
781
|
|
|
782
|
-
|
|
783
|
-
@pool.servers.sort_by{|s| s.to_s}.
|
|
782
|
+
it "#servers should return symbols for all servers" do
|
|
783
|
+
@pool.servers.sort_by{|s| s.to_s}.must_equal [:default, :read_only]
|
|
784
784
|
end
|
|
785
785
|
|
|
786
|
-
|
|
787
|
-
@pool.hold(:blah){|c| c.
|
|
786
|
+
it "#add_servers should add new servers to the pool" do
|
|
787
|
+
@pool.hold(:blah){|c| c.must_equal :default}
|
|
788
788
|
@pool.add_servers([:blah])
|
|
789
|
-
@pool.hold(:blah){|c| c.
|
|
789
|
+
@pool.hold(:blah){|c| c.must_equal :blah}
|
|
790
790
|
end
|
|
791
791
|
|
|
792
|
-
|
|
793
|
-
@pool.hold{|c| c.
|
|
794
|
-
@pool.hold(:read_only){|c| c.
|
|
792
|
+
it "#add_servers should ignore keys already existing" do
|
|
793
|
+
@pool.hold{|c| c.must_equal :default}
|
|
794
|
+
@pool.hold(:read_only){|c| c.must_equal :read_only}
|
|
795
795
|
@pool.add_servers([:default, :read_only])
|
|
796
|
-
@pool.conn.
|
|
797
|
-
@pool.conn(:read_only).
|
|
796
|
+
@pool.conn.must_equal :default
|
|
797
|
+
@pool.conn(:read_only).must_equal :read_only
|
|
798
798
|
end
|
|
799
799
|
|
|
800
|
-
|
|
801
|
-
@pool.hold(:read_only){|c| c.
|
|
800
|
+
it "#remove_servers should remove servers from the pool" do
|
|
801
|
+
@pool.hold(:read_only){|c| c.must_equal :read_only}
|
|
802
802
|
@pool.remove_servers([:read_only])
|
|
803
|
-
@pool.hold(:read_only){|c| c.
|
|
803
|
+
@pool.hold(:read_only){|c| c.must_equal :default}
|
|
804
804
|
end
|
|
805
805
|
|
|
806
|
-
|
|
807
|
-
proc{@pool.remove_servers([:default])}.
|
|
806
|
+
it "#remove_servers should not allow the removal of the default server" do
|
|
807
|
+
proc{@pool.remove_servers([:default])}.must_raise(Sequel::Error)
|
|
808
808
|
end
|
|
809
809
|
|
|
810
|
-
|
|
811
|
-
@pool.hold(:read_only){|c| c.
|
|
812
|
-
@pool.conn(:read_only).
|
|
810
|
+
it "#remove_servers should disconnect connection immediately" do
|
|
811
|
+
@pool.hold(:read_only){|c| c.must_equal :read_only}
|
|
812
|
+
@pool.conn(:read_only).must_equal :read_only
|
|
813
813
|
@pool.remove_servers([:read_only])
|
|
814
|
-
@pool.conn(:read_only).
|
|
814
|
+
@pool.conn(:read_only).must_equal nil
|
|
815
815
|
@pool.hold{}
|
|
816
|
-
@pool.conn(:read_only).
|
|
816
|
+
@pool.conn(:read_only).must_equal :default
|
|
817
817
|
end
|
|
818
818
|
|
|
819
|
-
|
|
820
|
-
|
|
819
|
+
it "#remove_servers should ignore keys that do not exist" do
|
|
820
|
+
@pool.remove_servers([:blah])
|
|
821
821
|
end
|
|
822
822
|
|
|
823
|
-
|
|
824
|
-
@pool.hold{|c| c.
|
|
825
|
-
@pool.conn.
|
|
823
|
+
it "should use the :default server by default" do
|
|
824
|
+
@pool.hold{|c| c.must_equal :default}
|
|
825
|
+
@pool.conn.must_equal :default
|
|
826
826
|
end
|
|
827
827
|
|
|
828
|
-
|
|
828
|
+
it "should use the :default server an invalid server is used" do
|
|
829
829
|
@pool.hold do |c1|
|
|
830
|
-
c1.
|
|
830
|
+
c1.must_equal :default
|
|
831
831
|
@pool.hold(:blah) do |c2|
|
|
832
|
-
c2.
|
|
832
|
+
c2.must_equal c1
|
|
833
833
|
@pool.hold(:blah2) do |c3|
|
|
834
|
-
c2.
|
|
834
|
+
c2.must_equal c3
|
|
835
835
|
end
|
|
836
836
|
end
|
|
837
837
|
end
|
|
838
838
|
end
|
|
839
839
|
|
|
840
|
-
|
|
841
|
-
@pool.hold(:read_only){|c| c.
|
|
842
|
-
@pool.conn(:read_only).
|
|
840
|
+
it "should use the requested server if server is given" do
|
|
841
|
+
@pool.hold(:read_only){|c| c.must_equal :read_only}
|
|
842
|
+
@pool.conn(:read_only).must_equal :read_only
|
|
843
843
|
end
|
|
844
844
|
|
|
845
|
-
|
|
845
|
+
it "#hold should only yield connections for the server requested" do
|
|
846
846
|
@pool.hold(:read_only) do |c|
|
|
847
|
-
c.
|
|
847
|
+
c.must_equal :read_only
|
|
848
848
|
@pool.hold do |d|
|
|
849
|
-
d.
|
|
849
|
+
d.must_equal :default
|
|
850
850
|
@pool.hold do |e|
|
|
851
|
-
e.
|
|
852
|
-
@pool.hold(:read_only){|b| b.
|
|
851
|
+
e.must_equal d
|
|
852
|
+
@pool.hold(:read_only){|b| b.must_equal c}
|
|
853
853
|
end
|
|
854
854
|
end
|
|
855
855
|
end
|
|
856
|
-
@pool.conn.
|
|
857
|
-
@pool.conn(:read_only).
|
|
856
|
+
@pool.conn.must_equal :default
|
|
857
|
+
@pool.conn(:read_only).must_equal :read_only
|
|
858
858
|
end
|
|
859
859
|
|
|
860
|
-
|
|
860
|
+
it "#disconnect should disconnect from all servers" do
|
|
861
861
|
@pool.hold(:read_only){}
|
|
862
862
|
@pool.hold{}
|
|
863
|
-
@pool.conn.
|
|
864
|
-
@pool.conn(:read_only).
|
|
863
|
+
@pool.conn.must_equal :default
|
|
864
|
+
@pool.conn(:read_only).must_equal :read_only
|
|
865
865
|
@pool.disconnect
|
|
866
|
-
@max_size.
|
|
867
|
-
@pool.conn.
|
|
868
|
-
@pool.conn(:read_only).
|
|
866
|
+
@max_size.must_equal 4
|
|
867
|
+
@pool.conn.must_equal nil
|
|
868
|
+
@pool.conn(:read_only).must_equal nil
|
|
869
869
|
end
|
|
870
870
|
|
|
871
|
-
|
|
872
|
-
@max_size.
|
|
873
|
-
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.
|
|
874
|
-
@max_size.
|
|
871
|
+
it ":disconnection_proc option should set the disconnection proc to use" do
|
|
872
|
+
@max_size.must_equal 2
|
|
873
|
+
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
|
874
|
+
@max_size.must_equal 3
|
|
875
875
|
end
|
|
876
876
|
|
|
877
|
-
|
|
878
|
-
@pool.instance_variable_get(:@conns).length.
|
|
877
|
+
it "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
|
878
|
+
@pool.instance_variable_get(:@conns).length.must_equal 0
|
|
879
879
|
@pool.hold{}
|
|
880
|
-
@pool.instance_variable_get(:@conns).length.
|
|
881
|
-
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.
|
|
882
|
-
@pool.instance_variable_get(:@conns).length.
|
|
880
|
+
@pool.instance_variable_get(:@conns).length.must_equal 1
|
|
881
|
+
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
|
882
|
+
@pool.instance_variable_get(:@conns).length.must_equal 0
|
|
883
883
|
end
|
|
884
884
|
end
|
|
885
885
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
@class.new(mock_db.call{123}, {}).pool_type.
|
|
886
|
+
AllConnectionPoolClassesSpecs = shared_description do
|
|
887
|
+
it "should have pool_type return a symbol" do
|
|
888
|
+
@class.new(mock_db.call{123}, {}).pool_type.must_be_kind_of(Symbol)
|
|
889
889
|
end
|
|
890
890
|
|
|
891
|
-
|
|
891
|
+
it "should have all_connections yield current and available connections" do
|
|
892
892
|
p = @class.new(mock_db.call{123}, {})
|
|
893
|
-
p.hold{|c| p.all_connections{|c1| c.
|
|
893
|
+
p.hold{|c| p.all_connections{|c1| c.must_equal c1}}
|
|
894
894
|
end
|
|
895
895
|
|
|
896
|
-
|
|
896
|
+
it "should have a size method that gives the current size of the pool" do
|
|
897
897
|
p = @class.new(mock_db.call{123}, {})
|
|
898
|
-
p.size.
|
|
898
|
+
p.size.must_equal 0
|
|
899
899
|
p.hold{}
|
|
900
|
-
p.size.
|
|
900
|
+
p.size.must_equal 1
|
|
901
901
|
end
|
|
902
902
|
|
|
903
|
-
|
|
904
|
-
@class.new(mock_db.call{123}, {}).max_size.
|
|
903
|
+
it "should have a max_size method that gives the maximum size of the pool" do
|
|
904
|
+
@class.new(mock_db.call{123}, {}).max_size.must_be :>=, 1
|
|
905
905
|
end
|
|
906
906
|
|
|
907
|
-
|
|
907
|
+
it "should support preconnect method that immediately creates the maximum number of connections" do
|
|
908
908
|
p = @class.new(mock_db.call{123}, {})
|
|
909
909
|
p.send(:preconnect)
|
|
910
910
|
i = 0
|
|
911
911
|
p.all_connections{|c1| i+=1}
|
|
912
|
-
i.
|
|
912
|
+
i.must_equal p.max_size
|
|
913
913
|
end
|
|
914
914
|
|
|
915
|
-
|
|
915
|
+
it "should be able to modify after_connect proc after the pool is created" do
|
|
916
916
|
a = []
|
|
917
917
|
p = @class.new(mock_db.call{123}, {})
|
|
918
918
|
p.after_connect = pr = proc{|c| a << c}
|
|
919
|
-
p.after_connect.
|
|
920
|
-
a.
|
|
919
|
+
p.after_connect.must_equal pr
|
|
920
|
+
a.must_equal []
|
|
921
921
|
p.hold{}
|
|
922
|
-
a.
|
|
922
|
+
a.must_equal [123]
|
|
923
923
|
end
|
|
924
924
|
|
|
925
|
-
|
|
925
|
+
it "should not raise an error when disconnecting twice" do
|
|
926
926
|
c = @class.new(mock_db.call{123}, {})
|
|
927
|
-
|
|
928
|
-
|
|
927
|
+
c.disconnect
|
|
928
|
+
c.disconnect
|
|
929
929
|
end
|
|
930
930
|
|
|
931
|
-
|
|
931
|
+
it "should yield a connection created by the initialize block to hold" do
|
|
932
932
|
x = nil
|
|
933
933
|
@class.new(mock_db.call{123}, {}).hold{|c| x = c}
|
|
934
|
-
x.
|
|
934
|
+
x.must_equal 123
|
|
935
935
|
end
|
|
936
936
|
|
|
937
|
-
|
|
937
|
+
it "should have the initialize block accept a shard/server argument" do
|
|
938
938
|
x = nil
|
|
939
939
|
@class.new(mock_db.call{|c| [c, c]}, {}).hold{|c| x = c}
|
|
940
|
-
x.
|
|
940
|
+
x.must_equal [:default, :default]
|
|
941
941
|
end
|
|
942
942
|
|
|
943
|
-
|
|
943
|
+
it "should have respect an :after_connect proc that is called with each newly created connection" do
|
|
944
944
|
x = nil
|
|
945
945
|
@class.new(mock_db.call{123}, :after_connect=>proc{|c| x = [c, c]}).hold{}
|
|
946
|
-
x.
|
|
946
|
+
x.must_equal [123, 123]
|
|
947
947
|
@class.new(mock_db.call{123}, :after_connect=>lambda{|c| x = [c, c]}).hold{}
|
|
948
|
-
x.
|
|
948
|
+
x.must_equal [123, 123]
|
|
949
949
|
@class.new(mock_db.call{123}, :after_connect=>proc{|c, s| x = [c, s]}).hold{}
|
|
950
|
-
x.
|
|
950
|
+
x.must_equal [123, :default]
|
|
951
951
|
@class.new(mock_db.call{123}, :after_connect=>lambda{|c, s| x = [c, s]}).hold{}
|
|
952
|
-
x.
|
|
952
|
+
x.must_equal [123, :default]
|
|
953
953
|
end
|
|
954
954
|
|
|
955
|
-
|
|
956
|
-
proc{@class.new(mock_db.call{|c| raise Exception}, {}).hold{}}.
|
|
955
|
+
it "should raise a DatabaseConnectionError if the connection raises an exception" do
|
|
956
|
+
proc{@class.new(mock_db.call{|c| raise Exception}, {}).hold{}}.must_raise(Sequel::DatabaseConnectionError)
|
|
957
957
|
end
|
|
958
958
|
|
|
959
|
-
|
|
960
|
-
proc{@class.new(mock_db.call{}, {}).hold{}}.
|
|
959
|
+
it "should raise a DatabaseConnectionError if the initialize block returns nil" do
|
|
960
|
+
proc{@class.new(mock_db.call{}, {}).hold{}}.must_raise(Sequel::DatabaseConnectionError)
|
|
961
961
|
end
|
|
962
962
|
|
|
963
|
-
|
|
963
|
+
it "should call the disconnection_proc option if the hold block raises a DatabaseDisconnectError" do
|
|
964
964
|
x = nil
|
|
965
|
-
proc{@class.new(mock_db.call(proc{|c| x = c}){123}).hold{raise Sequel::DatabaseDisconnectError}}.
|
|
966
|
-
x.
|
|
965
|
+
proc{@class.new(mock_db.call(proc{|c| x = c}){123}).hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
|
966
|
+
x.must_equal 123
|
|
967
967
|
end
|
|
968
968
|
|
|
969
|
-
|
|
969
|
+
it "should have a disconnect method that disconnects the connection" do
|
|
970
970
|
x = nil
|
|
971
971
|
c = @class.new(mock_db.call(proc{|c1| x = c1}){123})
|
|
972
972
|
c.hold{}
|
|
973
|
-
x.
|
|
973
|
+
x.must_equal nil
|
|
974
974
|
c.disconnect
|
|
975
|
-
x.
|
|
975
|
+
x.must_equal 123
|
|
976
976
|
end
|
|
977
977
|
|
|
978
|
-
|
|
978
|
+
it "should have a reentrent hold method" do
|
|
979
979
|
o = Object.new
|
|
980
980
|
c = @class.new(mock_db.call{o}, {})
|
|
981
981
|
c.hold do |x|
|
|
982
|
-
x.
|
|
982
|
+
x.must_equal o
|
|
983
983
|
c.hold do |x1|
|
|
984
|
-
x1.
|
|
984
|
+
x1.must_equal o
|
|
985
985
|
c.hold do |x2|
|
|
986
|
-
x2.
|
|
986
|
+
x2.must_equal o
|
|
987
987
|
end
|
|
988
988
|
end
|
|
989
989
|
end
|
|
990
990
|
end
|
|
991
991
|
|
|
992
|
-
|
|
993
|
-
@class.new(mock_db.call{123}, {}).servers.
|
|
992
|
+
it "should have a servers method that returns an array of shard/server symbols" do
|
|
993
|
+
@class.new(mock_db.call{123}, {}).servers.must_equal [:default]
|
|
994
994
|
end
|
|
995
995
|
|
|
996
|
-
|
|
996
|
+
it "should have a servers method that returns an array of shard/server symbols" do
|
|
997
997
|
c = @class.new(mock_db.call{123}, {})
|
|
998
|
-
c.size.
|
|
998
|
+
c.size.must_equal 0
|
|
999
999
|
c.hold{}
|
|
1000
|
-
c.size.
|
|
1000
|
+
c.size.must_equal 1
|
|
1001
1001
|
end
|
|
1002
1002
|
end
|
|
1003
1003
|
|
|
@@ -1010,6 +1010,7 @@ Sequel::ConnectionPool::CONNECTION_POOL_MAP.keys.each do |k, v|
|
|
|
1010
1010
|
before do
|
|
1011
1011
|
@class = Sequel::ConnectionPool.send(:connection_pool_class, opts)
|
|
1012
1012
|
end
|
|
1013
|
-
|
|
1013
|
+
|
|
1014
|
+
include AllConnectionPoolClassesSpecs
|
|
1014
1015
|
end
|
|
1015
1016
|
end
|