# simplecov must be loaded FIRST. Only the files required after it gets loaded # will be profiled !!! if ENV['TEST_ENABLE_COVERAGE'] == '1' begin require 'simplecov' SimpleCov.start do command_name 'master' add_filter "/test/" end rescue LoadError require 'autoproj' Autoproj.warn "coverage is disabled because the 'simplecov' gem cannot be loaded" rescue Exception => e require 'autoproj' Autoproj.warn "coverage is disabled: #{e.message}" end end require 'minitest/autorun' require 'autoproj' require 'flexmock/minitest' FlexMock.partials_are_based = true require 'minitest/spec' if ENV['TEST_ENABLE_PRY'] != '0' begin require 'pry' rescue Exception Autoproj.warn "debugging is disabled because the 'pry' gem cannot be loaded" end end module Autoproj # This module is the common setup for all tests # # It should be included in the toplevel describe blocks # # @example # require 'rubylib/test' # describe Autoproj do # include Autoproj::SelfTest # end # module SelfTest # Define package managers for the next workspace created by {#ws_create} # # Use {#ws_define_package_manager} # # Two package managers called 'os' and 'os_indep' are always created, # 'os' is used as the os package manager. # # @return [Hash] attr_reader :ws_package_managers # The workspace created by the last call to #ws_create attr_reader :ws def setup if ENV['AUTOPROJ_CURRENT_ROOT'] raise "cannot have a workspace's env.sh loaded while running the "\ "Autoproj test suite" end if defined?(Autoproj::CLI::Main) Autoproj::CLI::Main.default_report_on_package_failures = :raise end FileUtils.rm_rf fixture_gem_home @gem_server_pid = nil @tmpdir = Array.new @ws = nil @ws_package_managers = Hash.new Autobuild.logdir = make_tmpdir ws_define_package_manager 'os' ws_define_package_manager 'os_indep' Autobuild.progress_display_period = 0 super end def teardown super @tmpdir.each do |dir| FileUtils.remove_entry_secure dir end Rake::Task.clear Autobuild::Package.clear Autoproj.silent = false stop_gem_server if @gem_server_pid FileUtils.rm_rf fixture_gem_home if defined?(Autoproj::CLI::Main) Autoproj::CLI::Main.default_report_on_package_failures = nil end if ENV.delete('AUTOPROJ_CURRENT_ROOT') raise "AUTOPROJ_CURRENT_ROOT has been set by this test !!!!" end end def data_path(*args) File.expand_path(File.join(*args), File.join(__dir__, '..', '..', 'test', 'data')) end def create_bootstrap ws_create end def skip_long_tests? ENV['AUTOPROJ_SKIP_LONG_TESTS'] == '1' end def make_tmpdir dir = Dir.mktmpdir @tmpdir << dir dir end def scripts_dir File.expand_path(File.join('..', '..', 'test', 'scripts'), __dir__) end def find_gem_dir(gem_name) Bundler.definition.specs.each do |spec| return spec if spec.name == gem_name end nil end def autoproj_gemfile_to_local_checkout autoproj_dir = find_gem_dir('autoproj').full_gem_path autobuild_dir = find_gem_dir('autobuild').full_gem_path "source \"http://localhost:8808\" gem 'autoproj', path: '#{autoproj_dir}' gem 'autobuild', path: '#{autobuild_dir}' " end def invoke_test_script(name, *arguments, dir: nil, gemfile_source: nil, use_autoproj_from_rubygems: (ENV['USE_AUTOPROJ_FROM_RUBYGEMS'] == '1'), interactive: true, seed_config: File.join(scripts_dir, 'seed-config.yml'), env: Hash.new, display_output: false, copy_from: nil, **system_options) package_base_dir = File.expand_path(File.join('..', '..'), __dir__) script = File.expand_path(name, scripts_dir) unless File.file?(script) raise ArgumentError, "no test script #{name} in #{scripts_dir}" end arguments << '--seed-config' << seed_config if seed_config dir ||= make_tmpdir if gemfile_source || !use_autoproj_from_rubygems gemfile_path = File.join(dir, 'Gemfile-dev') File.open(gemfile_path, 'w') do |io| io.puts(gemfile_source || autoproj_gemfile_to_local_checkout) end arguments << "--gemfile" << gemfile_path << "--gem-source" << "http://localhost:8808" end arguments << "--no-interactive" unless interactive if copy_from test_workspace = File.expand_path(copy_from, scripts_dir) if File.directory?(test_workspace) FileUtils.cp_r test_workspace, dir dir = File.join(dir, File.basename(test_workspace)) end end result = nil stdout, stderr = capture_subprocess_io do default_env = Hash[ 'TEST_COMMAND_NAME' => to_s.gsub(/[^\w]/, '_'), 'PACKAGE_BASE_DIR' => package_base_dir, 'RUBY' => Gem.ruby ] result = Autoproj.bundler_unbundled_system( default_env.merge(env), script, *arguments, in: :close, **Hash[chdir: dir].merge(system_options)) end if !result puts stdout puts stderr flunk("test script #{name} failed") elsif display_output puts stdout puts stderr end [dir, stdout, stderr] end def fixture_gem_home File.join(__dir__, '..', '..', 'vendor', 'test_gem_home') end def prepare_fixture_gem_home FileUtils.rm_rf fixture_gem_home bundled_gems_path = File.expand_path(File.join("..", ".."), find_gem_dir('utilrb').full_gem_path) FileUtils.cp_r bundled_gems_path, fixture_gem_home vendor = File.join(__dir__, '..', '..', 'vendor') bundler_filename = "bundler-#{Bundler::VERSION}.gem" cached_bundler_gem = File.join(vendor, bundler_filename) unless File.file?(cached_bundler_gem) FileUtils.mkdir_p vendor Autoproj.bundler_unbundled_system( Ops::Install.guess_gem_program, 'fetch', '-v', Bundler::VERSION, 'bundler', chdir: vendor) unless File.file?(bundler_filename) raise "cannot download the bundler gem" end end capture_subprocess_io do Autoproj.bundler_unbundled_system( Hash['GEM_HOME' => fixture_gem_home, 'GEM_PATH' => nil], Ops::Install.guess_gem_program, 'install', '--no-document', cached_bundler_gem) end end def start_gem_server(path = fixture_gem_home) require 'socket' require 'rubygems/server' if @gem_server_pid raise ArgumentError, "#start_gem_server already called, "\ "call stop_gem_server before calling start_gem_server again" end @gem_server_pid = spawn( Hash['RUBYOPT' => nil], Gem.ruby, Ops::Install.guess_gem_program, 'server', '--quiet', '--dir', path, out: :close, err: :close) loop do begin TCPSocket.new('127.0.0.1', 8808) break rescue Errno::ECONNREFUSED # rubocop:disable Lint/HandleExceptions end end end def stop_gem_server Process.kill 'INT', @gem_server_pid Process.waitpid @gem_server_pid @gem_server_pid = nil end def capture_deprecation_message level = Autoproj.warn_deprecated_level Autoproj.warn_deprecated_level = -1 capture_subprocess_io do yield end ensure Autoproj.warn_deprecated_level = level end def find_bundled_gem_path(bundler, gem_name, gemfile) out_r, out_w = IO.pipe result = Autoproj.bundler_unbundled_system( bundler, 'show', gem_name, out: out_w, chdir: File.dirname(gemfile)) out_w.close output = out_r.read.chomp assert result, "bundler show #{gem_name} failed, output: '#{output}'" output end def workspace_env(varname) _, stdout, = invoke_test_script 'display-env.sh', varname, dir: install_dir stdout.chomp end def in_ws Dir.chdir(@ws.root_dir) do yield end end attr_reader :ws_os_package_resolver def ws_define_package_manager(name, strict: false, call_while_empty: false) manager = Class.new(PackageManagers::Manager) manager.class_eval do define_method(:strict?) { strict } define_method(:call_while_empty?) { call_while_empty } end manager = flexmock(manager) ws_package_managers[name] = manager end def ws_create_os_package_resolver @ws_os_package_resolver = OSPackageResolver.new( operating_system: [['test_os_family'], ['test_os_version']], package_managers: ws_package_managers.keys, os_package_manager: 'os') end def ws_create(dir = make_tmpdir, partial_config: false) require 'autoproj/ops/main_config_switcher' FileUtils.cp_r Ops::MainConfigSwitcher::MAIN_CONFIGURATION_TEMPLATE, File.join(dir, 'autoproj') FileUtils.mkdir_p File.join(dir, '.autoproj') ws_create_os_package_resolver @ws = Workspace.new( dir, os_package_resolver: ws_os_package_resolver, package_managers: ws_package_managers) unless partial_config ws.config.set 'osdeps_mode', 'all' ws.config.set 'apt_dpkg_update', true end ws.config.set 'GITHUB', 'http,ssh', true ws.config.set 'GITORIOUS', 'http,ssh', true ws.config.set 'gems_install_path', File.join(dir, 'gems') ws.prefix_dir = make_tmpdir ws.config.save # Make a valid (albeit empty) Gemfile File.open(File.join(ws.dot_autoproj_dir, 'Gemfile'), 'w').close ws end def ws_clear_layout ws.manifest.clear_layout end def ws_define_package_set(name, vcs = VCSDefinition.from_raw(type: 'none'), **options) package_set = PackageSet.new(ws, vcs, name: name, **options) ws.manifest.register_package_set(package_set) package_set end def ws_create_local_package_set(name, path, source_data: Hash.new, **options) vcs = VCSDefinition.from_raw(type: 'local', url: path) package_set = PackageSet.new(ws, vcs, name: name, **options) FileUtils.mkdir_p(path) File.open(File.join(path, 'source.yml'), 'w') do |io| YAML.dump(Hash['name' => name].merge(source_data), io) end ws.manifest.register_package_set(package_set) package_set end def ws_add_package_set_to_layout(name, vcs = VCSDefinition.from_raw(type: 'none'), **options) package_set = ws_define_package_set(name, vcs, **options) ws.manifest.add_package_set_to_layout(package_set) package_set end def ws_add_metapackage_to_layout(name, *packages) meta = ws.manifest.metapackage(name, *packages) ws.manifest.add_metapackage_to_layout(meta) meta end def ws_define_osdep_entries(entries, file: nil) ws_os_package_resolver.add_entries(entries, file: file) end def ws_add_osdep_entries_to_layout(entries) ws_os_package_resolver.add_entries(entries) entries.each_key do |pkg_name| ws.manifest.add_package_to_layout(pkg_name) end end def ws_define_package(package_type, package_name, package_set: ws.manifest.main_package_set, create: true, &block) package = Autobuild.send(package_type, package_name) ws_setup_package( package, package_set: package_set, create: create, &block ) end def ws_setup_package(package, package_set: ws.manifest.main_package_set, create: true) package.srcdir = File.join(ws.root_dir, package.name.to_s) FileUtils.mkdir_p package.srcdir if create autoproj_package = ws.register_package(package, nil, package_set) yield(package) if block_given? autoproj_package end def ws_define_package_vcs(package, vcs_spec) package.package_set.add_version_control_entry(package.name, vcs_spec) end def ws_define_package_overrides(package, package_set, vcs_spec) package_set.add_overrides_entry(package.name, vcs_spec) end def ws_add_package_to_layout(package_type, package_name, package_set: ws.manifest.main_package_set, &block) pkg = ws_define_package(package_type, package_name, package_set: package_set, &block) ws.manifest.add_package_to_layout(pkg) pkg end def ws_set_version_control_entry(package, entry) package.package_set.add_version_control_entry(package.name, entry) end def ws_set_overrides_entry(package, package_set, entry) package_set.add_overrides_entry(package.name, entry) end def ws_setup_package_dirs(package, create_srcdir: true) package.autobuild.srcdir = srcdir = File.join(ws.root_dir, package.name) if create_srcdir FileUtils.mkdir_p srcdir elsif File.directory?(srcdir) FileUtils.rm_rf srcdir end package.autobuild.builddir = builddir = File.join(ws.root_dir, 'build', package.name) package.autobuild.prefix = prefix = File.join(ws.root_dir, 'prefix', package.name) [srcdir, builddir, prefix] end def ws_create_git_package_set(name, source_data = Hash.new) dir = make_tmpdir unless system('git', 'init', chdir: dir, out: :close) raise "failed to run git init" end File.open(File.join(dir, 'source.yml'), 'w') do |io| YAML.dump(Hash['name' => name].merge(source_data), io) end unless system('git', 'add', 'source.yml', chdir: dir, out: :close) raise "failed to add the source.yml" end unless system('git', 'commit', '-m', 'add source.yml', chdir: dir, out: :close) raise "failed to commit the source.yml" end dir end def ws_create_package_set_file(pkg_set, name, content) path = File.join(pkg_set.raw_local_dir, name) FileUtils.mkdir_p File.dirname(path) File.open(path, 'w') do |io| io.write content end path end def ws_create_package_file(pkg, name, content) path = File.join(pkg.autobuild.srcdir, name) FileUtils.mkdir_p File.dirname(path) File.open(path, 'w') do |io| io.write content end path end def gemfile_aruba base_dir = File.expand_path('../../', __dir__) gemfile_path = File.join(base_dir, 'tmp', 'Gemfile.local') File.open(gemfile_path, 'w') do |io| io.write <<~GEMFILE source 'https://rubygems.org' gem 'autoproj', path: '#{base_dir}' GEMFILE end gemfile_path end end end class Minitest::Test # rubocop:disable Style/ClassAndModuleChildren include Autoproj::SelfTest end