test-prof 0.12.2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 796e133e85e58fec13b94d1dd51c3c9c934e122d04470115ef15788916a55d0b
4
- data.tar.gz: a8519944d9f36a9a74371b6a9fc19e69ecfbd1155679f178a3d6b6a62425dff3
3
+ metadata.gz: b43e971bbd8c55a38c657e3338dc625d5860bd067e96385f310885024a1c5cc5
4
+ data.tar.gz: 6d4b767d0ed366be1b27521e986785b6ddfa9f2008eb9640c76baae55084bb34
5
5
  SHA512:
6
- metadata.gz: ca5c8984a8ca9c4b2051be517bb462f8f0b9ba8ac582dd9cb74abeee81a98869400cbdf4e54e446de27215674bf0c90fe3b4dbeefdba620a1c5c67ff4a0ea0ce
7
- data.tar.gz: 4591aadd9f5616d939f7e9fcf91e4b8f635f921722bbed4225b8094cd78f7e557efbf3c58e45a0ebac18acf02f5744697e87a46524081124ebf15c0232dd2e08
6
+ metadata.gz: 1b490801a31def008b6e8c77dff834e67c4c27a96d9d09fbe626dbed0009cb541da48acc7308905f3f8b722e8fc6f6bde39ebce5362e928abb0c2d319f259248
7
+ data.tar.gz: 825b2ca0cd5f0c4ea235c5df11686a39799a70685a1ae0911facceb383facec815bed04322336ec67867b51e3a0152d150ed9fe7db9f01bb1acea520fd095258
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## master (unrealeased)
4
4
 
5
+ ## 1.0.0.rc1 (2020-12-30)
6
+
7
+ - Remove deprecated `AggregateFailures` cop. ([@palkan][])
8
+
9
+ - Remove `ActiveRecordSharedConnection`. ([@palkan][])
10
+
11
+ - Add `AnyFixture#register_dump` to _cache_ fixtures using SQL dumps. ([@palkan][])
12
+
13
+ - Replaced `TestProf::AnyFixture.reporting_enabled = true` with `TestProf::AnyFixture.config.reporting_enabled = true`. ([@palkan][])
14
+
15
+ - Add support for RSpec aliases detection when linting specs using `let_it_be`/`before_all` with `rubocop-rspec` 2.0 ([@pirj][])
16
+
5
17
  ## 0.12.2 (2020-09-03)
6
18
 
7
19
  - Execute Minitest `before_all` in the context of the current test object. ([@palkan][])
@@ -18,18 +18,3 @@ RSpec/AggregateExamples:
18
18
  - validate_length_of
19
19
  - validate_inclusion_of
20
20
  - validates_exclusion_of
21
-
22
- # TODO: remove this one we hit 1.0
23
- RSpec/AggregateFailures:
24
- Description: Checks if example group contains two or more aggregatable examples.
25
- Enabled: false
26
- StyleGuide: https://rspec.rubystyle.guide/#expectation-per-example
27
- AddAggregateFailuresMetadata: true
28
- MatchersWithSideEffects:
29
- - allow_value
30
- - allow_values
31
- - validate_presence_of
32
- - validate_absence_of
33
- - validate_length_of
34
- - validate_inclusion_of
35
- - validates_exclusion_of
@@ -0,0 +1,6 @@
1
+ RSpec:
2
+ Language:
3
+ Helpers:
4
+ - let_it_be
5
+ Hooks:
6
+ - before_all
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "test_prof/ext/float_duration"
4
+ require "test_prof/any_fixture/dump"
4
5
 
5
6
  module TestProf
6
7
  # Make DB fixtures from blocks.
@@ -9,6 +10,58 @@ module TestProf
9
10
 
10
11
  using FloatDuration
11
12
 
13
+ # AnyFixture configuration
14
+ class Configuration
15
+ attr_accessor :reporting_enabled, :dumps_dir, :dump_sequence_start,
16
+ :import_dump_via_cli, :dump_matching_queries, :force_matching_dumps
17
+ attr_reader :default_dump_watch_paths
18
+
19
+ alias reporting_enabled? reporting_enabled
20
+ alias import_dump_via_cli? import_dump_via_cli
21
+
22
+ def initialize
23
+ @reporting_enabled = ENV["ANYFIXTURE_REPORT"] == "1"
24
+ @dumps_dir = "any_dumps"
25
+ @default_dump_watch_paths = %w[
26
+ db/schema.rb
27
+ db/structure.sql
28
+ ]
29
+ @dump_sequence_start = 123_654
30
+ @dump_matching_queries = /^$/
31
+ @import_dump_via_cli = ENV["ANYFIXTURE_IMPORT_DUMP_CLI"] == "1"
32
+ @before_dump = []
33
+ @after_dump = []
34
+ @force_matching_dumps =
35
+ if ENV["ANYFIXTURE_FORCE_DUMP"] == "1"
36
+ /.*/
37
+ elsif ENV["ANYFIXTURE_FORCE_DUMP"]
38
+ /#{ENV["ANYFIXTURE_FORCE_DUMP"]}/
39
+ else
40
+ /^$/
41
+ end
42
+ end
43
+
44
+ def before_dump(&block)
45
+ if block_given?
46
+ @before_dump << block
47
+ else
48
+ @before_dump
49
+ end
50
+ end
51
+
52
+ def after_dump(&block)
53
+ if block_given?
54
+ @after_dump << block
55
+ else
56
+ @after_dump
57
+ end
58
+ end
59
+
60
+ def dump_sequence_random_start
61
+ rand(dump_sequence_start..(dump_sequence_start * 2))
62
+ end
63
+ end
64
+
12
65
  class Cache # :nodoc:
13
66
  attr_reader :store, :stats
14
67
 
@@ -40,22 +93,74 @@ module TestProf
40
93
  class << self
41
94
  include Logging
42
95
 
43
- attr_accessor :reporting_enabled
96
+ def config
97
+ @config ||= Configuration.new
98
+ end
99
+
100
+ def configure
101
+ yield config
102
+ end
103
+
104
+ # Backward compatibility
105
+ def reporting_enabled=(val)
106
+ warn "AnyFixture.reporting_enabled is deprecated and will be removed in 1.1. Use AnyFixture.config.reporting_enabled instead"
107
+ config.reporting_enabled = val
108
+ end
44
109
 
45
- def reporting_enabled?
46
- reporting_enabled == true
110
+ def reporting_enabled
111
+ warn "AnyFixture.reporting_enabled is deprecated and will be removed in 1.1. Use AnyFixture.config.reporting_enabled instead"
112
+ config.reporting_enabled
47
113
  end
48
114
 
115
+ alias reporting_enabled? reporting_enabled
116
+
49
117
  # Register a block of code as a fixture,
50
118
  # returns the result of the block execution
51
119
  def register(id)
52
- cache.fetch(id) do
120
+ cached(id) do
53
121
  ActiveSupport::Notifications.subscribed(method(:subscriber), "sql.active_record") do
54
122
  yield
55
123
  end
56
124
  end
57
125
  end
58
126
 
127
+ def cached(id)
128
+ cache.fetch(id) { yield }
129
+ end
130
+
131
+ # Create and register new SQL dump.
132
+ # Use `watch` to provide additional paths to watch for
133
+ # dump re-generation
134
+ def register_dump(name, clean: true, **options)
135
+ called_from = caller_locations(1, 1).first.path
136
+ watch = options.delete(:watch) || [called_from]
137
+ cache_key = options.delete(:cache_key)
138
+ skip = options.delete(:skip_if)
139
+
140
+ id = "sql/#{name}"
141
+
142
+ register_method = clean ? :register : :cached
143
+
144
+ public_send(register_method, id) do
145
+ dump = Dump.new(name, watch: watch, cache_key: cache_key)
146
+
147
+ unless dump.force?
148
+ next if skip&.call(dump: dump)
149
+
150
+ next dump.within_prepared_env(import: true, **options) { dump.load } if dump.exists?
151
+ end
152
+
153
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record", dump.subscriber)
154
+ res = dump.within_prepared_env(**options) { yield }
155
+
156
+ dump.commit!
157
+
158
+ res
159
+ ensure
160
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
161
+ end
162
+ end
163
+
59
164
  # Clean all affected tables (but do not reset cache)
60
165
  def clean
61
166
  disable_referential_integrity do
@@ -76,7 +181,13 @@ module TestProf
76
181
 
77
182
  def subscriber(_event, _start, _finish, _id, data)
78
183
  matches = data.fetch(:sql).match(INSERT_RXP)
79
- tables_cache[matches[1]] = true if matches
184
+ return unless matches
185
+
186
+ table_name = matches[1]
187
+
188
+ return if /sqlite_sequence/.match?(table_name)
189
+
190
+ tables_cache[table_name] = true
80
191
  end
81
192
 
82
193
  def report_stats
@@ -148,7 +259,5 @@ module TestProf
148
259
  connection.disable_referential_integrity { yield }
149
260
  end
150
261
  end
151
-
152
- self.reporting_enabled = ENV["ANYFIXTURE_REPORT"] == "1"
153
262
  end
154
263
  end
@@ -0,0 +1,207 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_prof/any_fixture/dump/digest"
4
+
5
+ require "set"
6
+
7
+ module TestProf
8
+ module AnyFixture
9
+ MODIFY_RXP = /^(INSERT INTO|UPDATE|DELETE FROM) ([\S]+)/i.freeze
10
+ ANY_FIXTURE_RXP = /(\/\*|\-\-).*\bany_fixture:dump/.freeze
11
+ ANY_FIXTURE_IGNORE_RXP = /(\/\*|\-\-).*\bany_fixture:ignore/.freeze
12
+
13
+ using(Module.new do
14
+ refine Object do
15
+ def to_digest
16
+ to_s
17
+ end
18
+ end
19
+
20
+ refine NilClass do
21
+ def to_digest
22
+ nil
23
+ end
24
+ end
25
+
26
+ refine Hash do
27
+ def to_digest
28
+ map { |k, v| [k.to_digest, v.to_digest].compact.join("_") }
29
+ end
30
+ end
31
+
32
+ refine Array do
33
+ def to_digest
34
+ map { |v| v.to_digest }.compact.join("-")
35
+ end
36
+ end
37
+ end)
38
+
39
+ class Dump
40
+ class Subscriber
41
+ attr_reader :path, :tmp_path
42
+
43
+ def initialize(path, adapter)
44
+ @path = path
45
+ @adapter = adapter
46
+ @tmp_path = path + ".tmp"
47
+ @reset_pk = Set.new
48
+ @file = File.open(tmp_path, "w")
49
+ end
50
+
51
+ def start(_event, _id, payload)
52
+ sql = payload.fetch(:sql)
53
+ return if sql.match?(ANY_FIXTURE_IGNORE_RXP)
54
+
55
+ matches = sql.match(MODIFY_RXP)
56
+ return unless matches
57
+
58
+ reset_pk!(matches[2]) if /insert/i.match?(matches[1])
59
+ end
60
+
61
+ def finish(_event, _id, payload)
62
+ sql = payload.fetch(:sql)
63
+ return unless trackable_sql?(sql)
64
+
65
+ sql = payload[:binds].any? ? adapter.compile_sql(sql, quoted(payload[:binds])) : +sql
66
+
67
+ sql.tr!("\n", " ")
68
+
69
+ file.write(sql + ";\n")
70
+ end
71
+
72
+ def commit
73
+ file.close
74
+
75
+ FileUtils.mv(tmp_path, path)
76
+ end
77
+
78
+ private
79
+
80
+ attr_reader :file, :reset_pk, :adapter
81
+
82
+ def reset_pk!(table_name)
83
+ return if /sqlite_sequence/.match?(table_name)
84
+
85
+ return if reset_pk.include?(table_name)
86
+
87
+ adapter.reset_sequence!(table_name, AnyFixture.config.dump_sequence_random_start)
88
+ reset_pk << table_name
89
+ end
90
+
91
+ def trackable_sql?(sql)
92
+ return false if sql.match?(ANY_FIXTURE_IGNORE_RXP)
93
+
94
+ sql.match?(MODIFY_RXP) || sql.match?(ANY_FIXTURE_RXP) || sql.match?(AnyFixture.config.dump_matching_queries)
95
+ end
96
+
97
+ def quoted(val)
98
+ if val.is_a?(Array)
99
+ val.map { |v| quoted(v) }
100
+ elsif val.is_a?(ActiveRecord::Relation::QueryAttribute)
101
+ quoted(val.value_for_database)
102
+ else
103
+ ActiveRecord::Base.connection.quote(val)
104
+ end
105
+ end
106
+ end
107
+
108
+ attr_reader :name, :digest, :path, :subscriber, :success
109
+ alias success? success
110
+
111
+ def initialize(name, watch: [], cache_key: nil)
112
+ @name = name
113
+ @digest = [
114
+ Digest.call(*watch),
115
+ cache_key.to_digest
116
+ ].compact.join("-")
117
+
118
+ @path = build_path(name, digest)
119
+
120
+ @success = false
121
+
122
+ @adapter =
123
+ case ActiveRecord::Base.connection.adapter_name
124
+ when /sqlite/i
125
+ require "test_prof/any_fixture/dump/sqlite"
126
+ SQLite.new
127
+ when /postgresql/i
128
+ require "test_prof/any_fixture/dump/postgresql"
129
+ PostgreSQL.new
130
+ else
131
+ raise ArgumentError,
132
+ "Your current database adapter (#{ActiveRecord::Base.connection.adapter_name}) " \
133
+ "is currently not supported. So far, we only support SQLite and PostgreSQL"
134
+ end
135
+
136
+ @subscriber = Subscriber.new(path, adapter)
137
+ end
138
+
139
+ def exists?
140
+ File.exist?(path)
141
+ end
142
+
143
+ def force?
144
+ AnyFixture.config.force_matching_dumps.match?(name)
145
+ end
146
+
147
+ def load
148
+ return import_via_active_record unless AnyFixture.config.import_dump_via_cli?
149
+
150
+ adapter.import(path) || import_via_active_record
151
+ end
152
+
153
+ def commit!
154
+ subscriber.commit
155
+ end
156
+
157
+ def within_prepared_env(before: nil, after: nil, import: false)
158
+ run_before_callbacks(callback: before, dump: self, import: false)
159
+ yield.tap do
160
+ @success = true
161
+ end
162
+ ensure
163
+ run_after_callbacks(callback: after, dump: self, import: false)
164
+ end
165
+
166
+ private
167
+
168
+ attr_reader :adapter
169
+
170
+ def import_via_active_record
171
+ conn = ActiveRecord::Base.connection
172
+
173
+ File.open(path).each_line do |query|
174
+ next if query.empty?
175
+
176
+ conn.execute query
177
+ end
178
+ end
179
+
180
+ def build_path(name, digest)
181
+ dir = TestProf.artifact_path(
182
+ File.join(AnyFixture.config.dumps_dir)
183
+ )
184
+
185
+ FileUtils.mkdir_p(dir)
186
+
187
+ File.join(dir, "#{name}-#{digest}.sql")
188
+ end
189
+
190
+ def run_before_callbacks(callback:, **options)
191
+ # First, call config-defined setup callbacks
192
+ AnyFixture.config.before_dump.each { |clbk| clbk.call(**options) }
193
+ # Then, adapter-defined callbacks
194
+ adapter.setup_env unless options[:import]
195
+ # Finally, user-provided callback
196
+ callback&.call(**options)
197
+ end
198
+
199
+ def run_after_callbacks(callback:, **options)
200
+ # The order is vice versa to setup
201
+ callback&.call(**options)
202
+ adapter.teardown_env unless options[:import]
203
+ AnyFixture.config.after_dump.each { |clbk| clbk.call(**options) }
204
+ end
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestProf
4
+ module AnyFixture
5
+ class Dump
6
+ class BaseAdapter
7
+ def reset_sequence!(_table_name, _start)
8
+ end
9
+
10
+ def compile_sql(sql, _binds)
11
+ sql
12
+ end
13
+
14
+ def setup_env
15
+ end
16
+
17
+ def teardown_env
18
+ end
19
+
20
+ def import(_path)
21
+ false
22
+ end
23
+
24
+ private
25
+
26
+ def while_disconnected
27
+ conn.disconnect!
28
+ yield
29
+ ensure
30
+ conn.reconnect!
31
+ end
32
+
33
+ def conn
34
+ ActiveRecord::Base.connection
35
+ end
36
+
37
+ def execute(query)
38
+ conn.execute(query)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha1"
4
+
5
+ module TestProf
6
+ module AnyFixture
7
+ class Dump
8
+ module Digest
9
+ module_function
10
+
11
+ def call(*paths)
12
+ files = (AnyFixture.config.default_dump_watch_paths + paths).each_with_object([]) do |path_or_glob, acc|
13
+ if File.file?(path_or_glob)
14
+ acc << path_or_glob
15
+ else
16
+ acc = acc.concat Dir[path_or_glob]
17
+ end
18
+ acc
19
+ end
20
+
21
+ return if files.empty?
22
+
23
+ file_ids = files.sort.map { |f| "#{File.basename(f)}/#{::Digest::SHA1.file(f).hexdigest}" }
24
+ ::Digest::SHA1.hexdigest(file_ids.join("/"))
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_prof/any_fixture/dump/base_adapter"
4
+
5
+ module TestProf
6
+ module AnyFixture
7
+ class Dump
8
+ class PostgreSQL < BaseAdapter
9
+ UUID_FUNCTIONS = %w[
10
+ gen_random_uuid
11
+ uuid_generate_v4
12
+ ]
13
+
14
+ def reset_sequence!(table_name, start)
15
+ _pk, sequence = conn.pk_and_sequence_for(table_name)
16
+ return unless sequence
17
+
18
+ sequence_name = "#{sequence.schema}.#{sequence.identifier}"
19
+
20
+ execute <<~SQL
21
+ ALTER SEQUENCE #{sequence_name} RESTART WITH #{start}; -- any_fixture:dump
22
+ SQL
23
+ end
24
+
25
+ def compile_sql(sql, binds)
26
+ sql.gsub(/\$\d+/) { binds.shift }
27
+ end
28
+
29
+ def import(path)
30
+ # Test if psql is installed
31
+ `psql --version`
32
+
33
+ tasks = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(conn.pool.spec.config.with_indifferent_access)
34
+
35
+ while_disconnected do
36
+ tasks.structure_load(path, "--output=/dev/null")
37
+ end
38
+
39
+ true
40
+ rescue Errno::ENOENT
41
+ false
42
+ end
43
+
44
+ def setup_env
45
+ # Mock UUID generating functions to provide consistent results
46
+ quoted_functions = UUID_FUNCTIONS.map { |func| "'#{func}'" }.join(", ")
47
+
48
+ @uuid_funcs = execute <<~SQL
49
+ SELECT
50
+ pp.proname, pn.nspname,
51
+ pg_get_functiondef(pp.oid) AS definition
52
+ FROM pg_proc pp
53
+ JOIN pg_namespace pn
54
+ ON pn.oid = pp.pronamespace
55
+ WHERE pp.proname in (#{quoted_functions})
56
+ ORDER BY pp.oid;
57
+ SQL
58
+
59
+ uuid_funcs.each do |(func, ns, _)|
60
+ execute <<~SQL
61
+ CREATE OR REPLACE FUNCTION #{ns}.#{func}()
62
+ RETURNS UUID
63
+ LANGUAGE SQL
64
+ AS $$
65
+ SELECT md5(random()::TEXT)::UUID;
66
+ $$; -- any_fixture:dump
67
+ SQL
68
+ end
69
+
70
+ execute <<~SQL
71
+ SELECT setseed(#{rand}); -- any_fixture:dump
72
+ SQL
73
+ end
74
+
75
+ def teardown_env
76
+ uuid_funcs.each do |(func, ns, definition)|
77
+ execute "#{definition}; -- any_fixture:dump"
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ attr_reader :uuid_funcs
84
+
85
+ def execute(query)
86
+ super.values
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_prof/any_fixture/dump/base_adapter"
4
+
5
+ module TestProf
6
+ module AnyFixture
7
+ class Dump
8
+ class SQLite < BaseAdapter
9
+ def reset_sequence!(table_name, start)
10
+ execute <<~SQL.chomp
11
+ DELETE FROM sqlite_sequence WHERE name=#{table_name}
12
+ SQL
13
+
14
+ execute <<~SQL.chomp
15
+ INSERT INTO sqlite_sequence (name, seq)
16
+ VALUES (#{table_name}, #{start})
17
+ SQL
18
+ end
19
+
20
+ def compile_sql(sql, binds)
21
+ sql.gsub(/\?/) { binds.shift }
22
+ end
23
+
24
+ def import(path)
25
+ db = conn.pool.spec.config[:database]
26
+ return false if %r{:memory:}.match?(db)
27
+
28
+ # Check that sqlite3 is installed
29
+ `sqlite3 --version`
30
+
31
+ while_disconnected do
32
+ `sqlite3 #{db} < "#{path}"`
33
+ end
34
+
35
+ true
36
+ rescue Errno::ENOENT
37
+ false
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,10 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if ::ActiveRecord::VERSION::MAJOR < 4
4
- require "test_prof/ext/active_record_3"
5
- using TestProf::ActiveRecord3Transactions
6
- end
7
-
8
3
  module TestProf
9
4
  module BeforeAll
10
5
  module Adapters
@@ -11,4 +11,3 @@ require "rubocop"
11
11
 
12
12
  require_relative "cops/inject"
13
13
  require "test_prof/cops/rspec/aggregate_examples"
14
- require "test_prof/cops/rspec/aggregate_failures"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestProf
4
- VERSION = "0.12.2"
4
+ VERSION = "1.0.0.rc1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-prof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.2
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-03 00:00:00.000000000 Z
11
+ date: 2020-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -119,6 +119,7 @@ files:
119
119
  - assets/tagprof.demo.html
120
120
  - assets/tagprof.template.html
121
121
  - config/default.yml
122
+ - config/rubocop-rspec.yml
122
123
  - lib/minitest/base_reporter.rb
123
124
  - lib/minitest/event_prof_formatter.rb
124
125
  - lib/minitest/test_prof_plugin.rb
@@ -126,6 +127,11 @@ files:
126
127
  - lib/test_prof.rb
127
128
  - lib/test_prof/any_fixture.rb
128
129
  - lib/test_prof/any_fixture/dsl.rb
130
+ - lib/test_prof/any_fixture/dump.rb
131
+ - lib/test_prof/any_fixture/dump/base_adapter.rb
132
+ - lib/test_prof/any_fixture/dump/digest.rb
133
+ - lib/test_prof/any_fixture/dump/postgresql.rb
134
+ - lib/test_prof/any_fixture/dump/sqlite.rb
129
135
  - lib/test_prof/before_all.rb
130
136
  - lib/test_prof/before_all/adapters/active_record.rb
131
137
  - lib/test_prof/before_all/isolator.rb
@@ -136,7 +142,6 @@ files:
136
142
  - lib/test_prof/cops/rspec/aggregate_examples/matchers_with_side_effects.rb
137
143
  - lib/test_prof/cops/rspec/aggregate_examples/metadata_helpers.rb
138
144
  - lib/test_prof/cops/rspec/aggregate_examples/node_matchers.rb
139
- - lib/test_prof/cops/rspec/aggregate_failures.rb
140
145
  - lib/test_prof/cops/rspec/language.rb
141
146
  - lib/test_prof/event_prof.rb
142
147
  - lib/test_prof/event_prof/custom_events.rb
@@ -148,7 +153,6 @@ files:
148
153
  - lib/test_prof/event_prof/monitor.rb
149
154
  - lib/test_prof/event_prof/profiler.rb
150
155
  - lib/test_prof/event_prof/rspec.rb
151
- - lib/test_prof/ext/active_record_3.rb
152
156
  - lib/test_prof/ext/active_record_refind.rb
153
157
  - lib/test_prof/ext/array_bsearch_index.rb
154
158
  - lib/test_prof/ext/factory_bot_strategy.rb
@@ -173,8 +177,6 @@ files:
173
177
  - lib/test_prof/factory_prof/printers/flamegraph.rb
174
178
  - lib/test_prof/factory_prof/printers/simple.rb
175
179
  - lib/test_prof/logging.rb
176
- - lib/test_prof/recipes/active_record_one_love.rb
177
- - lib/test_prof/recipes/active_record_shared_connection.rb
178
180
  - lib/test_prof/recipes/logging.rb
179
181
  - lib/test_prof/recipes/minitest/before_all.rb
180
182
  - lib/test_prof/recipes/minitest/sample.rb
@@ -228,9 +230,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
228
230
  version: 2.5.0
229
231
  required_rubygems_version: !ruby/object:Gem::Requirement
230
232
  requirements:
231
- - - ">="
233
+ - - ">"
232
234
  - !ruby/object:Gem::Version
233
- version: '0'
235
+ version: 1.3.1
234
236
  requirements: []
235
237
  rubygems_version: 3.0.6
236
238
  signing_key:
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module RSpec
6
- class AggregateExamples
7
- def self.registry
8
- RuboCop::Cop::Cop.registry
9
- end
10
- end
11
-
12
- class AggregateFailures < AggregateExamples
13
- def initialize(*)
14
- super
15
- self.class.just_once { warn "`AggregateFailures` cop has been renamed to `AggregateExamples`." }
16
- end
17
-
18
- def self.just_once
19
- return if @already_done
20
- yield
21
- @already_done = true
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TestProf
4
- # Add missing `begin_transaction` and `rollback_transaction` methods
5
- module ActiveRecord3Transactions
6
- refine ::ActiveRecord::ConnectionAdapters::AbstractAdapter do
7
- def begin_transaction(joinable: true)
8
- if open_transactions > 0
9
- increment_open_transactions
10
- create_savepoint
11
- else
12
- begin_db_transaction
13
- end
14
- self.transaction_joinable = joinable
15
- end
16
-
17
- def rollback_transaction(*)
18
- if open_transactions > 1
19
- rollback_to_savepoint
20
- else
21
- rollback_db_transaction
22
- end
23
- decrement_open_transactions
24
- end
25
- end
26
- end
27
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "./active_record_shared_connection"
4
-
5
- # One ❤️
6
- TestProf::ActiveRecordOneLove = TestProf::ActiveRecordSharedConnection
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TestProf
4
- # Forces ActiveRecord to use the same connection between threads
5
- module ActiveRecordSharedConnection # :nodoc: all
6
- class << self
7
- attr_reader :connection
8
-
9
- def enable!
10
- self.connection = ActiveRecord::Base.connection
11
- end
12
-
13
- def disable!
14
- self.connection = nil
15
- end
16
-
17
- def ignore(&block)
18
- raise ArgumentError, "Block is required" unless block_given?
19
-
20
- @ignores ||= []
21
-
22
- ignores << block
23
- end
24
-
25
- def ignored?(config)
26
- !ignores.nil? && ignores.any? { |clbk| clbk.call(config) }
27
- end
28
-
29
- private
30
-
31
- attr_reader :ignores
32
-
33
- def connection=(conn)
34
- @connection = conn
35
- connection.singleton_class.prepend Connection
36
- connection
37
- end
38
- end
39
-
40
- module Connection
41
- def shared_lock
42
- @shared_lock ||= Mutex.new
43
- end
44
-
45
- def exec_cache(*)
46
- shared_lock.synchronize { super }
47
- end
48
-
49
- def exec_no_cache(*)
50
- shared_lock.synchronize { super }
51
- end
52
-
53
- def execute(*)
54
- shared_lock.synchronize { super }
55
- end
56
- end
57
-
58
- module Ext
59
- def connection
60
- return super if ActiveRecordSharedConnection.ignored?(connection_config)
61
- ActiveRecordSharedConnection.connection || super
62
- end
63
- end
64
- end
65
- end
66
-
67
- ActiveSupport.on_load(:active_record) do
68
- if ::ActiveRecord::Base.connection.pool.respond_to?(:lock_thread=)
69
- TestProf.log :warn, "You activated ActiveRecordSharedConnection patch for the Rails version,\n" \
70
- "which has a built-in support for the same functionality.\n" \
71
- "Consider removing it, 'cause this could result in unexpected behaviour.\n\n" \
72
- "Read more in the docs: https://test-prof.evilmartians.io/#/active_record_shared_connection"
73
- end
74
-
75
- TestProf::ActiveRecordSharedConnection.enable!
76
- ActiveRecord::Base.singleton_class.prepend TestProf::ActiveRecordSharedConnection::Ext
77
- end