diff --git a/.github/workflows/build-ruby.yml b/.github/workflows/build-ruby.yml index 3a474a4..520efe3 100644 --- a/.github/workflows/build-ruby.yml +++ b/.github/workflows/build-ruby.yml @@ -145,6 +145,18 @@ jobs: libc: musl arch: ["x86_64", "aarch64"] # centos + - engine: ruby + version: "1.8" + libc: centos + arch: ["x86_64"] + - engine: ruby + version: "1.9" + libc: centos + arch: ["x86_64"] + - engine: ruby + version: "2.0" + libc: centos + arch: ["x86_64"] - engine: ruby version: "2.1" libc: centos diff --git a/Rakefile b/Rakefile index b9cd174..6c23a49 100644 --- a/Rakefile +++ b/Rakefile @@ -3,4 +3,8 @@ # @type self: Rake::TaskLib # load rake tasks from tasks directory -Dir.glob(File.join(__dir__ || Dir.pwd, "tasks", "**", "*.rake")) { |f| import f } +if RUBY_VERSION.start_with?("1.8.") + import File.join(File.dirname(__FILE__) || Dir.pwd, "tasks", "test.rake") +else + Dir.glob(File.join(File.dirname(__FILE__) || Dir.pwd, "tasks", "**", "*.rake")) { |f| import f } +end diff --git a/gemfiles/ruby-1.8.gemfile b/gemfiles/ruby-1.8.gemfile new file mode 100644 index 0000000..301baa9 --- /dev/null +++ b/gemfiles/ruby-1.8.gemfile @@ -0,0 +1,10 @@ +source "https://rubygems.org" + +gem "rake" + +group :test do + # These introduce regexes that are incompatible with 1.8.7 + # - https://github.com/minitest/minitest/commit/b0e07f4dd05d5369b913aa72f8d02609790c090f + # - https://github.com/minitest/minitest/commit/b2eebc2d7c492ce0eb11bb88752b841990f9ac92 + gem "minitest", "~> 5.11.0" +end diff --git a/gemfiles/ruby-1.9.gemfile b/gemfiles/ruby-1.9.gemfile new file mode 100644 index 0000000..b3d4cd4 --- /dev/null +++ b/gemfiles/ruby-1.9.gemfile @@ -0,0 +1,7 @@ +source "https://rubygems.org" + +gem "rake" + +group :test do + gem "minitest" +end diff --git a/gemfiles/ruby-2.0.gemfile b/gemfiles/ruby-2.0.gemfile new file mode 100644 index 0000000..b3d4cd4 --- /dev/null +++ b/gemfiles/ruby-2.0.gemfile @@ -0,0 +1,7 @@ +source "https://rubygems.org" + +gem "rake" + +group :test do + gem "minitest" +end diff --git a/src/engines/ruby/1.8/Dockerfile.centos b/src/engines/ruby/1.8/Dockerfile.centos new file mode 100644 index 0000000..49d74ac --- /dev/null +++ b/src/engines/ruby/1.8/Dockerfile.centos @@ -0,0 +1,196 @@ +# platforms: linux/x86_64 + +# CentOS 7.9 has glibc 2.17 +FROM public.ecr.aws/docker/library/centos:centos7.9.2009 + +# Set yum vault +RUN < /etc/yum.repos.d/CentOS-Base.repo +[base] +name=CentOS-\$releasever - Base +baseurl=http://vault.centos.org/${repo_version}/os/\$basearch/ +gpgcheck=0 + +[updates] +name=CentOS-\$releasever - Updates +baseurl=http://vault.centos.org/${repo_version}/updates/\$basearch/ +gpgcheck=0 + +[extras] +name=CentOS-\$releasever - Extras +baseurl=http://vault.centos.org/${repo_version}/extras/\$basearch/ +gpgcheck=0 + +[centosplus] +name=CentOS-\$releasever - Plus +baseurl=http://vault.centos.org/${repo_version}/centosplus/\$basearch/ +gpgcheck=0 +enabled=0 +EOF +SHELL + +RUN yum makecache -y + +# localedef has been forcefully removed by: +# rm -rf "$target"/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive} +# fun: CentOS 8 has `yum list glibc-langpack-\*` but not CentOS 7 :'( +RUN yum reinstall -y glibc-common + +RUN yum install -y curl gcc make + +# fun: this has to be after `yum install curl gcc make`... but only on aarch64; go figure +# extra fun: table is botched, localedef not happy, swallow result and test `locale` for errors +RUN <&1 | grep -e 'locale: Cannot set LC_.* to default locale: No such file or directory'; then exit 1; fi +SHELL + +# Skip installing gem documentation +COPY < file.c.new +mv file.c.new file.c + +# https://github.com/rbenv/ruby-build/issues/444 +# https://bugs.ruby-lang.org/issues/9065 +# https://github.com/ruby/ruby/commit/f895841e2c2861f8d3ea2247817d6ffd35dff71c.patch +patch -p1 <<'PATCH' +diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c +index 8e6d88f60609b3..29e28ca2f4420f 100644 +--- a/ext/openssl/ossl_pkey_ec.c ++++ b/ext/openssl/ossl_pkey_ec.c +@@ -762,8 +762,10 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) + method = EC_GFp_mont_method(); + } else if (id == s_GFp_nist) { + method = EC_GFp_nist_method(); ++#if !defined(OPENSSL_NO_EC2M) + } else if (id == s_GF2m_simple) { + method = EC_GF2m_simple_method(); ++#endif + } + + if (method) { +@@ -817,8 +819,10 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) + + if (id == s_GFp) { + new_curve = EC_GROUP_new_curve_GFp; ++#if !defined(OPENSSL_NO_EC2M) + } else if (id == s_GF2m) { + new_curve = EC_GROUP_new_curve_GF2m; ++#endif + } else { + ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m"); + } +PATCH + +autoconf + +gnuArch="$(uname -m)-linux-gnu" +./configure \ + --build="$gnuArch" \ + --disable-install-doc \ + --disable-shared +make -j "$(nproc)" +make install + +# find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \ +# | awk '/=>/ { print $(NF-1) }' \ +# | sort -u \ +# | grep -vE '^/usr/local/lib/' \ +# | xargs -r dpkg-query --search \ +# | cut -d: -f1 \ +# | sort -u \ +# | xargs -r apt-mark manual \ +# +# apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# +# find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \ +# | awk '/=>/ { print $(NF-1) }' \ +# | grep -v '=>' \ +# | sort -u \ +# | grep -vE '^/usr/local/lib/' \ +# | xargs -r rpm -qf \ +# | sort -u \ +# | xargs -r yum ?mark-manual? +# +# yum autoremove -y +# yum remove --setopt=clean_requirements_on_remove=1 +# package-cleanup --leaves && yum autoremove # yum-utils +# sudo yum history list pdftk +# sudo yum history undo 88 + +cd / +rm -r /usr/src/ruby +if yum list installed ruby; then exit 1; fi + +# update gem version +curl -o rubygems.tar.gz "https://rubygems.org/rubygems/rubygems-1.6.2.tgz" +echo "cb5261818b931b5ea2cb54bc1d583c47823543fcf9682f0d6298849091c1cea7 *rubygems.tar.gz" | sha256sum --check --strict +mkdir -p /usr/src/rubygems +tar -xzf rubygems.tar.gz -C /usr/src/rubygems --strip-components=1 +rm rubygems.tar.gz + +cd /usr/src/rubygems +ruby setup.rb +cd / +rm -r /usr/src/rubygems + +gem update --system 2.7.11 +gem install bundler --version 1.17.3 --force + +# rough smoke test +ruby --version +gem --version +bundle --version + +SHELL + +# don't create ".bundle" in all our apps +ENV GEM_HOME /usr/local/bundle +ENV BUNDLE_SILENCE_ROOT_WARNING=1 \ + BUNDLE_APP_CONFIG="$GEM_HOME" +ENV PATH $GEM_HOME/bin:$PATH + +# adjust permissions of a few directories for running "gem install" as an arbitrary user +RUN mkdir -p "$GEM_HOME" && chmod 1777 "$GEM_HOME" + +CMD [ "irb" ] + diff --git a/src/engines/ruby/1.9/Dockerfile.centos b/src/engines/ruby/1.9/Dockerfile.centos new file mode 100644 index 0000000..fd3b565 --- /dev/null +++ b/src/engines/ruby/1.9/Dockerfile.centos @@ -0,0 +1,153 @@ +# platforms: linux/x86_64 + +# CentOS 7.9 has glibc 2.17 +FROM public.ecr.aws/docker/library/centos:centos7.9.2009 + +# Set yum vault +RUN < /etc/yum.repos.d/CentOS-Base.repo +[base] +name=CentOS-\$releasever - Base +baseurl=http://vault.centos.org/${repo_version}/os/\$basearch/ +gpgcheck=0 + +[updates] +name=CentOS-\$releasever - Updates +baseurl=http://vault.centos.org/${repo_version}/updates/\$basearch/ +gpgcheck=0 + +[extras] +name=CentOS-\$releasever - Extras +baseurl=http://vault.centos.org/${repo_version}/extras/\$basearch/ +gpgcheck=0 + +[centosplus] +name=CentOS-\$releasever - Plus +baseurl=http://vault.centos.org/${repo_version}/centosplus/\$basearch/ +gpgcheck=0 +enabled=0 +EOF +SHELL + +RUN yum makecache -y + +# localedef has been forcefully removed by: +# rm -rf "$target"/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive} +# fun: CentOS 8 has `yum list glibc-langpack-\*` but not CentOS 7 :'( +RUN yum reinstall -y glibc-common + +RUN yum install -y curl gcc make + +# fun: this has to be after `yum install curl gcc make`... but only on aarch64; go figure +# extra fun: table is botched, localedef not happy, swallow result and test `locale` for errors +RUN <&1 | grep -e 'locale: Cannot set LC_.* to default locale: No such file or directory'; then exit 1; fi +SHELL + +# Skip installing gem documentation +COPY < file.c.new +mv file.c.new file.c + +autoconf + +gnuArch="$(uname -m)-linux-gnu" +./configure \ + --build="$gnuArch" \ + --disable-install-doc \ + --disable-shared +make -j "$(nproc)" +make install + +# find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \ +# | awk '/=>/ { print $(NF-1) }' \ +# | sort -u \ +# | grep -vE '^/usr/local/lib/' \ +# | xargs -r dpkg-query --search \ +# | cut -d: -f1 \ +# | sort -u \ +# | xargs -r apt-mark manual \ +# +# apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# +# find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \ +# | awk '/=>/ { print $(NF-1) }' \ +# | grep -v '=>' \ +# | sort -u \ +# | grep -vE '^/usr/local/lib/' \ +# | xargs -r rpm -qf \ +# | sort -u \ +# | xargs -r yum ?mark-manual? +# +# yum autoremove -y +# yum remove --setopt=clean_requirements_on_remove=1 +# package-cleanup --leaves && yum autoremove # yum-utils +# sudo yum history list pdftk +# sudo yum history undo 88 + +cd / +rm -r /usr/src/ruby +if yum list installed ruby; then exit 1; fi + +# update gem version +gem update --system 2.7.11 +gem install bundler --version 1.17.3 --force + +# rough smoke test +ruby --version +gem --version +bundle --version + +SHELL + +# don't create ".bundle" in all our apps +ENV GEM_HOME /usr/local/bundle +ENV BUNDLE_SILENCE_ROOT_WARNING=1 \ + BUNDLE_APP_CONFIG="$GEM_HOME" +ENV PATH $GEM_HOME/bin:$PATH + +# adjust permissions of a few directories for running "gem install" as an arbitrary user +RUN mkdir -p "$GEM_HOME" && chmod 1777 "$GEM_HOME" + +CMD [ "irb" ] + diff --git a/src/engines/ruby/2.0/Dockerfile.centos b/src/engines/ruby/2.0/Dockerfile.centos new file mode 100644 index 0000000..224b58a --- /dev/null +++ b/src/engines/ruby/2.0/Dockerfile.centos @@ -0,0 +1,153 @@ +# platforms: linux/x86_64 + +# CentOS 7.9 has glibc 2.17 +FROM public.ecr.aws/docker/library/centos:centos7.9.2009 + +# Set yum vault +RUN < /etc/yum.repos.d/CentOS-Base.repo +[base] +name=CentOS-\$releasever - Base +baseurl=http://vault.centos.org/${repo_version}/os/\$basearch/ +gpgcheck=0 + +[updates] +name=CentOS-\$releasever - Updates +baseurl=http://vault.centos.org/${repo_version}/updates/\$basearch/ +gpgcheck=0 + +[extras] +name=CentOS-\$releasever - Extras +baseurl=http://vault.centos.org/${repo_version}/extras/\$basearch/ +gpgcheck=0 + +[centosplus] +name=CentOS-\$releasever - Plus +baseurl=http://vault.centos.org/${repo_version}/centosplus/\$basearch/ +gpgcheck=0 +enabled=0 +EOF +SHELL + +RUN yum makecache -y + +# localedef has been forcefully removed by: +# rm -rf "$target"/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive} +# fun: CentOS 8 has `yum list glibc-langpack-\*` but not CentOS 7 :'( +RUN yum reinstall -y glibc-common + +RUN yum install -y curl gcc make + +# fun: this has to be after `yum install curl gcc make`... but only on aarch64; go figure +# extra fun: table is botched, localedef not happy, swallow result and test `locale` for errors +RUN <&1 | grep -e 'locale: Cannot set LC_.* to default locale: No such file or directory'; then exit 1; fi +SHELL + +# Skip installing gem documentation +COPY < file.c.new +mv file.c.new file.c + +autoconf + +gnuArch="$(uname -m)-linux-gnu" +./configure \ + --build="$gnuArch" \ + --disable-install-doc \ + --disable-shared +make -j "$(nproc)" +make install + +# find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \ +# | awk '/=>/ { print $(NF-1) }' \ +# | sort -u \ +# | grep -vE '^/usr/local/lib/' \ +# | xargs -r dpkg-query --search \ +# | cut -d: -f1 \ +# | sort -u \ +# | xargs -r apt-mark manual \ +# +# apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# +# find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \ +# | awk '/=>/ { print $(NF-1) }' \ +# | grep -v '=>' \ +# | sort -u \ +# | grep -vE '^/usr/local/lib/' \ +# | xargs -r rpm -qf \ +# | sort -u \ +# | xargs -r yum ?mark-manual? +# +# yum autoremove -y +# yum remove --setopt=clean_requirements_on_remove=1 +# package-cleanup --leaves && yum autoremove # yum-utils +# sudo yum history list pdftk +# sudo yum history undo 88 + +cd / +rm -r /usr/src/ruby +if yum list installed ruby; then exit 1; fi + +# update gem version +gem update --system 2.7.11 +gem install bundler --version 1.17.3 --force + +# rough smoke test +ruby --version +gem --version +bundle --version + +SHELL + +# don't create ".bundle" in all our apps +ENV GEM_HOME /usr/local/bundle +ENV BUNDLE_SILENCE_ROOT_WARNING=1 \ + BUNDLE_APP_CONFIG="$GEM_HOME" +ENV PATH $GEM_HOME/bin:$PATH + +# adjust permissions of a few directories for running "gem install" as an arbitrary user +RUN mkdir -p "$GEM_HOME" && chmod 1777 "$GEM_HOME" + +CMD [ "irb" ] + diff --git a/tasks/test.rake b/tasks/test.rake index cc8bee9..c284885 100644 --- a/tasks/test.rake +++ b/tasks/test.rake @@ -5,8 +5,13 @@ begin require "minitest/test_task" rescue LoadError - # Backport "minitest/test_task" for minitest 5.15.0 - require_relative "../vendor/minitest/test_task" + # Backport "minitest/test_task" for minitest 5.15.0 and down + if RUBY_VERSION.start_with?("1.8.") + # Ruby 1.8.7 has no `require_relative` + require File.expand_path(File.join(File.dirname(__FILE__), "../vendor/minitest/test_task.1.8.rb")) + else + require_relative "../vendor/minitest/test_task" + end end Minitest::TestTask.create(:test) do |t| diff --git a/test/engines/test_encoding.rb b/test/engines/test_encoding.rb index 92ab0bf..bd4ecb2 100644 --- a/test/engines/test_encoding.rb +++ b/test/engines/test_encoding.rb @@ -1,24 +1,39 @@ require "minitest/autorun" -# polyfill for Ruby 2.2 and down, used by minitest +# polyfill for Ruby 2.2 and down, used by minitest assertions unless "".respond_to?(:match?) - String.instance_eval do + class String def match?(other) (Regexp === other) ? other.match?(self) : (self == other) end end end +# polyfill for Ruby 1.9.3 and down, used by minitest assertions +unless //.respond_to?(:match?) + class Regexp + def match?(other) + !!match(other) + end + end +end + class TestEncoding < Minitest::Test def test_utf8_lang assert_equal("en_US.UTF-8", ENV["LANG"]) end def test_utf8_string - assert_equal(Encoding::UTF_8, "".encoding) + skip "missing String#encoding" unless "".respond_to?(:encoding) + + expected = (RUBY_VERSION =~ /^(?:1\.8\.|1\.9\.)/) ? Encoding::US_ASCII : Encoding::UTF_8 + + assert_equal(expected, "".encoding) end def test_read_utf8 + skip "missing String#encoding" unless "".respond_to?(:encoding) + contents = File.read("test/fixtures/encoding/utf-8.txt") assert_equal(Encoding::UTF_8, contents.encoding) diff --git a/vendor/minitest/test_task.1.8.rb b/vendor/minitest/test_task.1.8.rb new file mode 100644 index 0000000..a838522 --- /dev/null +++ b/vendor/minitest/test_task.1.8.rb @@ -0,0 +1,208 @@ +require "shellwords" +require "rbconfig" +require "rake/tasklib" + +module Minitest # :nodoc: + + ## + # Minitest::TestTask is a rake helper that generates several rake + # tasks under the main test task's name-space. + # + # task :: the main test task + # task :cmd :: prints the command to use + # task :deps :: runs each test file by itself to find dependency errors + # task :slow :: runs the tests and reports the slowest 25 tests. + # + # Examples: + # + # Minitest::TestTask.create + # + # The most basic and default setup. + # + # Minitest::TestTask.create :my_tests + # + # The most basic/default setup, but with a custom name + # + # Minitest::TestTask.create :unit do |t| + # t.test_globs = ["test/unit/**/*_test.rb"] + # t.warning = false + # end + # + # Customize the name and only run unit tests. + # + # NOTE: To hook this task up to the default, make it a dependency: + # + # task default: :unit + + class TestTask < Rake::TaskLib + WINDOWS = RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ # :nodoc: + + ## + # Create several test-oriented tasks under +name+. Takes an + # optional block to customize variables. + + def self.create name = :test, &block + task = new name + task.instance_eval(&block) if block + task.process_env + task.define + task + end + + ## + # Extra arguments to pass to the tests. Defaults empty but gets + # populated by a number of enviroment variables: + # + # N (-n flag) :: a string or regexp of tests to run. + # X (-e flag) :: a string or regexp of tests to exclude. + # A (arg) :: quick way to inject an arbitrary argument (eg A=--help). + # + # See #process_env + + attr_accessor :extra_args + + ## + # The code to load the framework. Defaults to requiring + # minitest/autorun... + # + # Why do I have this as an option? + + attr_accessor :framework + + ## + # Extra library directories to include. Defaults to %w[lib test + # .]. Also uses $MT_LIB_EXTRAS allowing you to dynamically + # override/inject directories for custom runs. + + attr_accessor :libs + + ## + # The name of the task and base name for the other tasks generated. + + attr_accessor :name + + ## + # File globs to find test files. Defaults to something sensible to + # find test files under the test directory. + + attr_accessor :test_globs + + ## + # Turn on ruby warnings (-w flag). Defaults to true. + + attr_accessor :warning + + ## + # Optional: Additional ruby to run before the test framework is loaded. + + attr_accessor :test_prelude + + ## + # Print out commands as they run. Defaults to Rake's +trace+ (-t + # flag) option. + + attr_accessor :verbose + + ## + # Use TestTask.create instead. + + def initialize name = :test # :nodoc: + self.extra_args = [] + self.framework = %(require "minitest/autorun") + self.libs = %w[lib test .] + self.name = name + self.test_globs = ["test/**/test_*.rb", + "test/**/*_test.rb"] + self.test_prelude = nil + self.verbose = Rake.application.options.trace + self.warning = true + end + + ## + # Extract variables from the environment and convert them to + # command line arguments. See #extra_args. + # + # Environment Variables: + # + # MT_LIB_EXTRAS :: Extra libs to dynamically override/inject for custom runs. + # N :: Tests to run (string or /regexp/). + # X :: Tests to exclude (string or /regexp/). + # A :: Any extra arguments. Honors shell quoting. + # + # Deprecated: + # + # TESTOPTS :: For argument passing, use +A+. + # N :: For parallel testing, use +MT_CPU+. + # FILTER :: Same as +TESTOPTS+. + + def process_env + warn "TESTOPTS is deprecated in Minitest::TestTask. Use A instead" if + ENV["TESTOPTS"] + warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if + ENV["FILTER"] + warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if + ENV["N"] && ENV["N"].to_i > 0 + + lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR + self.libs[0,0] = lib_extras + + extra_args << "-n" << ENV["N"] if ENV["N"] + extra_args << "-e" << ENV["X"] if ENV["X"] + extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"] + extra_args.concat Shellwords.split(ENV["FILTER"]) if ENV["FILTER"] + extra_args.concat Shellwords.split(ENV["A"]) if ENV["A"] + + ENV.delete "N" if ENV["N"] + + # TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"] + # TODO? ENV["RUBY_FLAGS"] + + extra_args.compact! + end + + def define # :nodoc: + desc "Run the test suite. Use N, X, A, and TESTOPTS to add flags/args." + task name do + ruby make_test_cmd, :verbose => verbose + end + + desc "Print out the test command. Good for profiling and other tools." + task "#{name}:cmd" do + puts "ruby #{make_test_cmd}" + end + + desc "Show bottom 25 tests wrt time." + task "#{name}:slow" do + sh ["rake #{name} A=-v", + "egrep '#test_.* s = .'", + "sort -n -k2 -t=", + "tail -25"].join " | " + end + end + + ## + # Generate the test command-line. + + def make_test_cmd globs = test_globs + tests = [] + tests.concat Dir[*globs].sort.shuffle # TODO: SEED -> srand first? + tests.map! { |f| %(require "#{f}") } + + runner = [] + runner << test_prelude if test_prelude + runner << framework + runner.concat tests + runner = runner.join "; " + + args = [] + args << "-I#{libs.join(File::PATH_SEPARATOR)}" unless libs.empty? + args << "-w" if warning + args << '-e' + args << "'#{runner}'" + args << '--' + args << extra_args.map(&:shellescape) + + args.join " " + end + end +end