-
-
Notifications
You must be signed in to change notification settings - Fork 896
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: scripts to assert on packaged gem files and installed gems
some tests are skipped because they assert new behavior which will be implemented in the next few commits. Closes #2076 Closes #2078
- Loading branch information
1 parent
17c7754
commit 8118e97
Showing
2 changed files
with
324 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
#! /usr/bin/env ruby | ||
# frozen_string_literal: true | ||
# | ||
# this script is intended to run as part of the CI test suite. | ||
# | ||
# it inspects the contents of a nokogiri gem file -- both the files and the gemspec -- to ensure | ||
# we're packaging what we expect, and that we're not packaging anything we don't expect. | ||
# | ||
# this file isn't in the `test/` subdirectory because it's intended to be run standalone against a | ||
# built gem file (and not against the source code or behavior of the gem itself). | ||
# | ||
|
||
require "bundler/inline" | ||
|
||
gemfile do | ||
source "https://rubygems.org" | ||
gem "minitest" | ||
gem "minitest-reporters" | ||
end | ||
|
||
require "yaml" | ||
|
||
def usage_and_exit(message = nil) | ||
puts "ERROR: #{message}" if message | ||
puts "USAGE: #{File.basename(__FILE__)} <gemfile> [options]" | ||
exit(1) | ||
end | ||
|
||
usage_and_exit if ARGV.include?("-h") | ||
usage_and_exit unless gemfile = ARGV[0] | ||
usage_and_exit("#{gemfile} does not exist") unless File.file?(gemfile) | ||
usage_and_exit("#{gemfile} is not a gem") unless /\.gem$/.match(gemfile) | ||
gemfile = File.expand_path(gemfile) | ||
|
||
gemfile_contents = Dir.mktmpdir do |dir| | ||
Dir.chdir(dir) do | ||
unless system("tar -xf #{gemfile} data.tar.gz") | ||
raise "could not unpack gem #{gemfile}" | ||
end | ||
%x(tar -ztf data.tar.gz).split("\n") | ||
end | ||
end | ||
|
||
gemspec = Dir.mktmpdir do |dir| | ||
Dir.chdir(dir) do | ||
unless system("tar -xf #{gemfile} metadata.gz") | ||
raise "could not unpack gem #{gemfile}" | ||
end | ||
YAML.load(%x(gunzip -c metadata.gz)) | ||
end | ||
end | ||
|
||
if ARGV.include?("-v") | ||
puts "---------- gemfile contents ----------" | ||
puts gemfile_contents | ||
puts | ||
puts "---------- gemspec ----------" | ||
puts gemspec.to_ruby | ||
puts | ||
end | ||
|
||
require "minitest/autorun" | ||
require "minitest/reporters" | ||
Minitest::Reporters.use!([Minitest::Reporters::SpecReporter.new]) | ||
|
||
puts "Testing '#{gemfile}' (#{gemspec.platform})" | ||
describe File.basename(gemfile) do | ||
let(:cross_rubies_path) { File.join(File.dirname(__FILE__), "..", ".cross_rubies") } | ||
let(:native_ruby_versions) do | ||
File.read(cross_rubies_path).split("\n").map do |line| | ||
line.split(":").first.split(".").take(2).join(".") # ugh | ||
end.uniq.sort | ||
end | ||
|
||
describe "setup" do | ||
it "gemfile contains some files" do | ||
actual = gemfile_contents.length | ||
assert_operator(actual, :>, 60, "expected gemfile to contain more than #{actual} files") | ||
end | ||
|
||
it "gemspec is a Gem::Specfication" do | ||
assert_equal(Gem::Specification, gemspec.class) | ||
end | ||
end | ||
|
||
describe "all platforms" do | ||
it "contains every ruby file in lib/" do | ||
expected = %x(git ls-files lib).split("\n").grep(/\.rb$/).sort | ||
actual = gemfile_contents.grep(%r{^lib/}).grep(/\.rb$/).sort | ||
assert_equal(expected, actual) | ||
end | ||
end | ||
|
||
describe "ruby platform" do | ||
it "contains the port files" do | ||
actual_ports = gemfile_contents.grep(%r{^ports/}) | ||
assert(actual_ports.grep(/libxml2-\d+\.\d+\.\d+\.tar\.gz/).length == 1, | ||
"expected #{actual_ports} to include libxml2") | ||
assert(actual_ports.grep(/libxslt-\d+\.\d+\.\d+\.tar\.gz/).length == 1, | ||
"expected #{actual_ports} to include libxslt") | ||
assert_equal(2, actual_ports.length) | ||
end | ||
|
||
it "contains the patch files" do | ||
actual_patches = gemfile_contents.grep(%r{^patches/}) | ||
assert_operator(actual_patches.length, :>, 0) | ||
end | ||
|
||
it "does not contain header files in lib/nokogiri/include" do | ||
# these are copied to lib/nokogiri/include during compilation, not packaged | ||
assert_empty(gemfile_contents.grep(%r{^lib/.*\.h$})) | ||
end | ||
|
||
it "contains ext/nokogiri" do | ||
assert_operator(gemfile_contents.grep(%r{^ext/nokogiri/.*\.[ch]}).length, :>, 20) | ||
end | ||
|
||
it "does not contain the java jar files" do | ||
assert_empty(gemfile_contents.grep(/.*\.jar$/)) | ||
end | ||
|
||
it "depends on mini_portile2" do | ||
assert(gemspec.dependencies.find { |d| d.name == "mini_portile2" }) | ||
end | ||
|
||
it "includes C files in extra_rdoc_files" do | ||
assert_operator(gemspec.extra_rdoc_files.grep(%r{ext/nokogiri/.*\.c$}).length, :>, 10) | ||
end | ||
end if gemspec.platform == Gem::Platform::RUBY | ||
|
||
describe "native platform" do | ||
it "does not contain the port files" do | ||
actual_ports = gemfile_contents.grep(%r{^ports/}) | ||
assert_empty(actual_ports) | ||
end | ||
|
||
it "does not contain the patch files" do | ||
actual_patches = gemfile_contents.grep(%r{^patches/}) | ||
assert_empty(actual_patches) | ||
end | ||
|
||
it "contains nokogiri header files in lib/nokogiri/include" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/pull/1788" | ||
assert_includes(gemfile_contents, "lib/nokogiri/include/nokogiri.h") | ||
end | ||
|
||
it "contains packaged libraries' header files in lib/nokogiri/include" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/pull/1788" | ||
assert_includes(gemfile_contents, "lib/nokogiri/include/libxml2/libxml/tree.h") | ||
assert_includes(gemfile_contents, "lib/nokogiri/include/libxslt/xslt.h") | ||
assert_includes(gemfile_contents, "lib/nokogiri/include/libexslt/exslt.h") | ||
end | ||
|
||
it "does not contain ext/nokogiri" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/issues/2077" | ||
assert_empty(gemfile_contents.grep(%r{^ext/nokogiri/})) | ||
end | ||
|
||
it "does not contain the java jar files" do | ||
assert_empty(gemfile_contents.grep(/.*\.jar$/)) | ||
end | ||
|
||
it "does not depend on mini_portile2" do | ||
# https://github.com/sparklemotion/nokogiri/issues/2078 | ||
refute(gemspec.dependencies.find { |d| d.name == "mini_portile2" }) | ||
end | ||
|
||
it "packages only ruby-version-specific libraries" do | ||
# https://github.com/sparklemotion/nokogiri/issues/2076 | ||
native_ruby_versions.each do |version| | ||
assert_includes(gemfile_contents, "lib/nokogiri/#{version}/nokogiri.so") | ||
end | ||
refute_includes(gemfile_contents, "lib/nokogiri/nokogiri.so") | ||
end | ||
end if gemspec.platform.is_a?(Gem::Platform) && gemspec.platform.cpu | ||
|
||
describe "java platform" do | ||
it "does not contain the port files" do | ||
actual_ports = gemfile_contents.grep(%r{^ports/}) | ||
assert_empty(actual_ports) | ||
end | ||
|
||
it "does not contain the patch files" do | ||
actual_patches = gemfile_contents.grep(%r{^patches/}) | ||
assert_empty(actual_patches) | ||
end | ||
|
||
it "does not contain header files in lib/nokogiri/include" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/pull/1788" | ||
assert_empty(gemfile_contents.grep(%r{^lib/.*\.h$})) | ||
end | ||
|
||
it "does not contain ext/nokogiri" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/issues/2099" | ||
assert_empty(gemfile_contents.grep(%r{^ext/nokogiri/})) | ||
end | ||
|
||
it "does contains the java jar files" do | ||
actual_jars = gemfile_contents.grep(/.*\.jar$/) | ||
["nokogiri", "isorelax", "jing", "nekodtd", "nekohtml", "serializer", "xalan", "xercesImpl", "xml-apis"].each do |jar| | ||
assert_equal(1, actual_jars.grep(%r{/#{jar}\.jar$}).length, "expected to contain #{jar}.jar") | ||
end | ||
end | ||
|
||
it "does not depend on mini_portile2" do | ||
# https://github.com/sparklemotion/nokogiri/issues/2078 | ||
refute(gemspec.dependencies.find { |d| d.name == "mini_portile2" }) | ||
end | ||
end if gemspec.platform == Gem::Platform.new("java") | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#! /usr/bin/env ruby | ||
# frozen_string_literal: true | ||
# | ||
# this script is intended to run as part of the CI test suite. | ||
# | ||
# it inspects the filesystem of a nokogiri gem installation to ensure it's complete and sane, and | ||
# doesn't install anything we don't expect. | ||
# | ||
# this file isn't in the `test/` subdirectory because it's intended to be run standalone against an | ||
# installed gem (and not against the source code or behavior of the gem itself). | ||
# | ||
|
||
# this line needs to come before the bundler bit, to assert that we're running against an | ||
# already-installed version (and not some other version that bundler/inline might install if it came | ||
# first) | ||
gemspec = Gem::Specification.find_by_name('nokogiri') | ||
raise "could not find installed gem" unless gemspec | ||
|
||
require "bundler/inline" | ||
|
||
gemfile do | ||
source "https://rubygems.org" | ||
gem "minitest" | ||
gem "minitest-reporters" | ||
gem "nokogiri" | ||
end | ||
|
||
require 'nokogiri' | ||
require 'yaml' | ||
|
||
if ARGV.include?("-v") | ||
puts "---------- Nokogiri version info ----------" | ||
puts Nokogiri::VERSION_INFO.to_yaml | ||
puts | ||
puts "---------- Nokogiri installed gemspec ----------" | ||
puts gemspec.to_ruby | ||
puts | ||
end | ||
|
||
require "minitest/autorun" | ||
require "minitest/reporters" | ||
Minitest::Reporters.use!([Minitest::Reporters::SpecReporter.new]) | ||
|
||
puts "Testing #{gemspec.full_name} installed in #{gemspec.base_dir}" | ||
describe gemspec.full_name do | ||
let(:nokogiri_include_dir) { File.join(gemspec.gem_dir, "lib/nokogiri/include") } | ||
|
||
# representative sample of the files | ||
let(:nokogiri_header_files) { ["nokogiri.h", "xml_document.h", "xml_node.h"] } | ||
let(:packaged_library_header_files) { ["libxml2/libxml/tree.h", "libxslt/xslt.h", "libexslt/exslt.h"] } | ||
|
||
it "loads the same version as the spec we've loaded" do | ||
assert_equal(Nokogiri::VERSION, gemspec.version.to_s) | ||
end | ||
|
||
describe "cruby" do | ||
it "installs nokogiri headers" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/pull/1788" | ||
assert(File.directory?(nokogiri_include_dir), | ||
"expected directory to exist: #{nokogiri_include_dir}") | ||
|
||
nokogiri_header_files.each do |header| | ||
assert(File.file?(File.join(nokogiri_include_dir, header)), | ||
"expected #{header} to be installed in #{nokogiri_include_dir}") | ||
end | ||
end | ||
|
||
describe "native platform" do | ||
it "acknowledges it is using packaged, precompiled libraries" do | ||
assert(Nokogiri::VersionInfo.instance.libxml2_using_packaged?) | ||
assert(Nokogiri::VERSION_INFO["libxml"].key?("source")) | ||
assert_equal("packaged", Nokogiri::VERSION_INFO["libxml"]["source"]) | ||
|
||
assert(Nokogiri::VersionInfo.instance.libxml2_precompiled?) | ||
assert(Nokogiri::VERSION_INFO["libxml"].key?("precompiled")) | ||
assert(Nokogiri::VERSION_INFO["libxml"]["precompiled"]) | ||
end | ||
end if gemspec.platform.is_a?(Gem::Platform) && gemspec.platform.cpu | ||
|
||
describe "library" do | ||
describe "packaged" do | ||
it "declares where headers are installed" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/pull/1788" | ||
# this is for nokogumbo and shouldn't be forever | ||
nokogiri_include_parent_dir = File.dirname(nokogiri_include_dir) | ||
assert_equal(nokogiri_include_parent_dir, Nokogiri::VERSION_INFO["libxml"]["libxml2_path"], | ||
"expected Nokogiri::VERSION_INFO to point to #{nokogiri_include_parent_dir}") | ||
end | ||
|
||
it "installs packaged libraries' headers" do | ||
skip "until we fix https://github.com/sparklemotion/nokogiri/pull/1788" | ||
packaged_library_header_files.each do |header| | ||
assert(File.file?(File.join(nokogiri_include_dir, header)), | ||
"expected #{header} to be installed in #{nokogiri_include_dir}") | ||
end | ||
end | ||
end if Nokogiri::VersionInfo.instance.libxml2_using_packaged? | ||
|
||
describe "using system libraries" do | ||
it "doesn't declare where headers are installed" do | ||
refute(Nokogiri::VERSION_INFO["libxml"].key?("libxml2_path")) | ||
end | ||
|
||
it "does not install packaged libraries' headers" do | ||
packaged_library_header_files.each do |header| | ||
dir = File.join(nokogiri_include_dir, File.dirname(header)) | ||
refute(File.directory?(dir), | ||
"expected directory #{dir} to not exist") | ||
end | ||
end | ||
end unless Nokogiri::VersionInfo.instance.libxml2_using_packaged? | ||
end | ||
end unless gemspec.platform == Gem::Platform.new("java") | ||
end |