From 7a07e155deaa97ac210de67523063063397c173a Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 12 Aug 2022 17:16:15 -0700 Subject: [PATCH] Include core_ext and bin/sequel when doing coverage testing 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. --- Rakefile | 12 +++--- bin/sequel | 14 +++++-- lib/sequel/extensions/symbol_aref.rb | 2 + spec/bin_shim | 1 + spec/bin_spec.rb | 56 +++++++++++++++++++++++++++- spec/sequel_coverage.rb | 24 +++++++++--- 6 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 spec/bin_shim diff --git a/Rakefile b/Rakefile index 6f68667dd9..e6af896be4 100644 --- a/Rakefile +++ b/Rakefile @@ -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' @@ -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 diff --git a/bin/sequel b/bin/sequel index 253597d9eb..41bd9e6feb 100755 --- a/bin/sequel +++ b/bin/sequel @@ -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 @@ -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 @@ -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: diff --git a/lib/sequel/extensions/symbol_aref.rb b/lib/sequel/extensions/symbol_aref.rb index e5930f68f2..1c1b25fd25 100644 --- a/lib/sequel/extensions/symbol_aref.rb +++ b/lib/sequel/extensions/symbol_aref.rb @@ -35,6 +35,7 @@ def [](v) class Symbol prepend Sequel::SymbolAref end +# :nocov: else class Symbol if method_defined?(:[]) @@ -51,3 +52,4 @@ def [](v) end end end +# :nocov: diff --git a/spec/bin_shim b/spec/bin_shim new file mode 100644 index 0000000000..6d3ba32ce2 --- /dev/null +++ b/spec/bin_shim @@ -0,0 +1 @@ +load(File.join(Dir.pwd, 'bin/sequel')) diff --git a/spec/bin_spec.rb b/spec/bin_spec.rb index a0d5c4615c..72aa0265a5 100644 --- a/spec/bin_spec.rb +++ b/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" @@ -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 @@ -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(<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 diff --git a/spec/sequel_coverage.rb b/spec/sequel_coverage.rb index eb59212b45..dac17eaa34 100644 --- a/spec/sequel_coverage.rb +++ b/spec/sequel_coverage.rb @@ -1,4 +1,3 @@ -require 'coverage' require 'simplecov' def SimpleCov.sequel_coverage(opts = {}) @@ -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