Skip to content

Commit

Permalink
Include core_ext and bin/sequel when doing coverage testing
Browse files Browse the repository at this point in the history
Add ability to test subprocesses when running specs, necessary
for bin/sequel coverage testing.

Because coverage calculation doesn't really work for the ruby
script directly executed, or that uses load instead of require,

Add nocov markers in bin/sequel around code that would load irb,
and around code that cannot be hit on SQLite (SQLite is used
for testing). Also add nocov markers in the symbol_aref
extension (tested with the core extension) for Ruby 1.9 specific
code.

Add some bin/sequel tests for additional coverage. Add the ability
to force printing status for each row copied, and print the status
after copying the row instead of before.
  • Loading branch information
jeremyevans committed Aug 13, 2022
1 parent 2b8f341 commit 7a07e15
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 14 deletions.
12 changes: 7 additions & 5 deletions Rakefile
Expand Up @@ -112,15 +112,15 @@ spec_task.call("Run core and model specs together", :spec_core_model, 'spec/core
spec_task.call("Run core specs", :spec_core, 'spec/core_spec.rb', false, false)
spec_task.call("Run model specs", :spec_model, 'spec/model_spec.rb', false, false)
spec_task.call("Run plugin/extension specs", :spec_plugin, 'spec/plugin_spec.rb', "plugin-extension", true)
spec_task.call("Run bin/sequel specs", :spec_bin, 'spec/bin_spec.rb', false, false)
spec_task.call("Run core extensions specs", :spec_core_ext, 'spec/core_extensions_spec.rb', true, true)
spec_task.call("Run integration tests", :spec_integration, 'spec/adapter_spec.rb none', true, true)
spec_task.call("Run bin/sequel specs", :spec_bin, 'spec/bin_spec.rb', 'bin', false)
spec_task.call("Run core extensions specs", :spec_core_ext, 'spec/core_extensions_spec.rb', 'core-ext', true)
spec_task.call("Run integration tests", :spec_integration, 'spec/adapter_spec.rb none', '1', true)

%w'postgres sqlite mysql oracle mssql db2 sqlanywhere'.each do |adapter|
spec_task.call("Run #{adapter} tests", :"spec_#{adapter}", "spec/adapter_spec.rb #{adapter}", true, true)
spec_task.call("Run #{adapter} tests", :"spec_#{adapter}", "spec/adapter_spec.rb #{adapter}", adapter, true)
end

spec_task.call("Run model specs without the associations code", :_spec_model_no_assoc, 'spec/model_no_assoc_spec.rb', false)
spec_task.call("Run model specs without the associations code", :_spec_model_no_assoc, 'spec/model_no_assoc_spec.rb', false, false)
desc "Run model specs without the associations code"
task :spec_model_no_assoc do
ENV['SEQUEL_NO_ASSOCIATIONS'] = '1'
Expand All @@ -132,6 +132,8 @@ task :spec_cov do
ENV['SEQUEL_MERGE_COVERAGE'] = '1'
Rake::Task['spec_core_model_cov'].invoke
Rake::Task['spec_plugin_cov'].invoke
Rake::Task['spec_core_ext_cov'].invoke
Rake::Task['spec_bin_cov'].invoke
end

task :spec_ci=>[:spec_core, :spec_model, :spec_plugin, :spec_core_ext] do
Expand Down
14 changes: 11 additions & 3 deletions bin/sequel
Expand Up @@ -194,7 +194,11 @@ begin
TO_DB = connect_proc[db2]
same_db = DB.database_type==TO_DB.database_type
index_opts = {:same_db=>same_db}

# :nocov:
index_opts[:index_names] = :namespace if !DB.global_index_namespace? && TO_DB.global_index_namespace?
# :nocov:

if DB.database_type == :sqlite && !same_db
# SQLite integer types allows 64-bit integers
TO_DB.extension :integer64
Expand All @@ -212,18 +216,20 @@ begin
puts "Begin copying data"
DB.transaction do
TO_DB.transaction do
all_status_lines = ENV['SEQUEL_BIN_STATUS_ALL_LINES']

DB.tables.each do |table|
puts "Begin copying records for table: #{table}"
time = Time.now
to_ds = TO_DB.from(table)
j = 0
DB.from(table).each do |record|
if Time.now - time > 5
to_ds.insert(record)
j += 1
if Time.now - time > 5 || all_status_lines
puts "Status: #{j} records copied"
time = Time.now
end
to_ds.insert(record)
j += 1
end
puts "Finished copying #{j} records for table: #{table}"
end
Expand Down Expand Up @@ -260,8 +266,10 @@ if !ARGV.empty?
ARGV.each{|v| load(v)}
elsif !$stdin.isatty
eval($stdin.read)
# :nocov:
else
require 'irb'
puts "Your database is stored in DB..."
IRB.start
end
# :nocov:
2 changes: 2 additions & 0 deletions lib/sequel/extensions/symbol_aref.rb
Expand Up @@ -35,6 +35,7 @@ def [](v)
class Symbol
prepend Sequel::SymbolAref
end
# :nocov:
else
class Symbol
if method_defined?(:[])
Expand All @@ -51,3 +52,4 @@ def [](v)
end
end
end
# :nocov:
1 change: 1 addition & 0 deletions spec/bin_shim
@@ -0,0 +1 @@
load(File.join(Dir.pwd, 'bin/sequel'))
56 changes: 55 additions & 1 deletion spec/bin_spec.rb
@@ -1,6 +1,11 @@
require 'rbconfig'
require 'yaml'

if ENV['COVERAGE']
require_relative "sequel_coverage"
SimpleCov.sequel_coverage(:subprocesses=>true)
end

RUBY = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['RUBY_INSTALL_NAME'])
OUTPUT = "spec/bin-sequel-spec-output-#{$$}.log"
TMP_FILE = "spec/bin-sequel-tmp-#{$$}.rb"
Expand Down Expand Up @@ -29,7 +34,7 @@

describe "bin/sequel" do
def bin(opts={})
cmd = "#{opts[:pre]}\"#{RUBY}\" -I lib bin/sequel #{opts[:args]} #{"#{CONN_PREFIX}#{BIN_SPEC_DB}" unless opts[:no_conn]} #{opts[:post]}> #{OUTPUT}#{" 2>&1" if opts[:stderr]}"
cmd = "#{opts[:pre]}\"#{RUBY}\" -I lib spec/bin_shim #{opts[:args]} #{"#{CONN_PREFIX}#{BIN_SPEC_DB}" unless opts[:no_conn]} #{opts[:post]}> #{OUTPUT}#{" 2>&1" if opts[:stderr]}"
system(cmd)
File.read(OUTPUT)
end
Expand Down Expand Up @@ -101,6 +106,55 @@ def bin(opts={})
DB2.foreign_key_list(:b).must_equal [{:columns=>[:a], :table=>:a, :key=>nil, :on_update=>:no_action, :on_delete=>:no_action}]
end

it "-C should copy databases showing status while iterating over tables" do
DB.create_table(:a) do
primary_key :a
String :name
end
DB.create_table(:b) do
foreign_key :a, :a
index :a
end
DB[:a].insert(1, 'foo')

begin
ENV['SEQUEL_BIN_STATUS_ALL_LINES'] = '1'
bin(:args=>'-C', :post=>"#{CONN_PREFIX}#{BIN_SPEC_DB2}").must_match Regexp.new(<<END)
Databases connections successful
Migrations dumped successfully
Tables created
Begin copying data
Begin copying records for table: a
Status: 1 records copied
Finished copying 1 records for table: a
Begin copying records for table: b
Finished copying 0 records for table: b
Finished copying data
Begin creating indexes
Finished creating indexes
Begin adding foreign key constraints
Finished adding foreign key constraints
Database copy finished in \\d+\\.\\d+ seconds
END
ensure
ENV.delete('SEQUEL_BIN_STATUS_ALL_LINES')
end

DB2.tables.sort_by{|t| t.to_s}.must_equal [:a, :b]
DB[:a].all.must_equal [{:a=>1, :name=>'foo'}]
DB[:b].all.must_equal []
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, int_type, :integer, nil], [:name, true, nil, false, "varchar(255)", :string, nil]]
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, int_type, :integer, nil]]
DB2.indexes(:a).must_equal({})
DB2.indexes(:b).must_equal(:b_a_index=>{:unique=>false, :columns=>[:a]})
DB2.foreign_key_list(:a).must_equal []
DB2.foreign_key_list(:b).must_equal [{:columns=>[:a], :table=>:a, :key=>nil, :on_update=>:no_action, :on_delete=>:no_action}]
end

it "-C should display error if not given second database" do
bin(:args=>'-C', :stderr=>true).must_include 'Error: Must specify database connection string or path to yaml file as second argument for database you want to copy to'
end

it "-C should convert integer to bigint when copying from SQLite to other databases" do
DB.create_table(:a) do
Integer :id
Expand Down
24 changes: 19 additions & 5 deletions spec/sequel_coverage.rb
@@ -1,4 +1,3 @@
require 'coverage'
require 'simplecov'

def SimpleCov.sequel_coverage(opts = {})
Expand All @@ -10,13 +9,28 @@ def SimpleCov.sequel_coverage(opts = {})
add_group('Missing-Revelent'){|src| src.filename =~ opts[:group] && src.covered_percent < 100} if opts[:group]
add_group('Missing'){|src| src.covered_percent < 100}
add_group('Covered'){|src| src.covered_percent == 100}

if ENV['SEQUEL_MERGE_COVERAGE']
regexps = [%r{lib/sequel/(extensions|plugins)/\w+\.rb\z}, %r{lib/sequel/(\w+\.rb|(dataset|database|model|connection_pool)/\w+\.rb|adapters/mock\.rb)\z}]
add_filter{|src| src.filename !~ Regexp.union(regexps)}
else
add_filter{|src| src.filename !~ opts[:filter]} if opts[:filter]
filter = %r{bin/sequel\z|lib/sequel/(\w+\.rb|(dataset|database|model|connection_pool|extensions|plugins)/\w+\.rb|adapters/mock\.rb)\z}
add_filter{|src| src.filename !~ filter}
elsif opts[:filter]
add_filter{|src| src.filename !~ opts[:filter]}
end

if opts[:subprocesses]
enable_for_subprocesses true
ENV['COVERAGE'] = 'subprocess'
ENV['RUBYOPT'] = "#{ENV['RUBYOPT']} -r ./spec/sequel_coverage"
elsif SEQUEL_COVERAGE == 'subprocess'
command_name "bin-#{$$}"
self.print_error_status = false
formatter SimpleCov::Formatter::SimpleFormatter
end
end
end

SEQUEL_COVERAGE = ENV.delete('COVERAGE')

if SEQUEL_COVERAGE == 'subprocess'
SimpleCov.sequel_coverage
end

0 comments on commit 7a07e15

Please sign in to comment.