@@ -40,6 +40,97 @@ namespace :gem do
4040 puts "\n To release, run: rake release"
4141 end
4242
43+ desc 'Verify the gem installs and runs with --disable-native-extension'
44+ task :verify_pure_only do
45+ require 'tmpdir'
46+
47+ # The suite already runs everything under CATARACT_PURE=1, but that leaves
48+ # the compiled extension on disk. This installs the built gem with no
49+ # extension at all - the only way to catch a stub Makefile that stops
50+ # satisfying RubyGems, or a file the pure backend needs dropping out of
51+ # spec.files.
52+ Dir . mktmpdir do |dir |
53+ gem_file = File . join ( dir , 'cataract-pure-only.gem' )
54+ gem_home = File . join ( dir , 'gems' )
55+
56+ # Runtime dependencies may already be satisfiable outside this scratch
57+ # home, in which case `gem install` won't copy them in. Keep the
58+ # inherited path on the end so they still resolve, or activating
59+ # cataract fails and surfaces as a bare LoadError. The check asserts
60+ # cataract itself came from the scratch install.
61+ search_path = [ gem_home , ENV . fetch ( 'GEM_PATH' , nil ) ] . compact . reject ( &:empty? )
62+ env = { 'GEM_HOME' => gem_home , 'GEM_PATH' => search_path . join ( File ::PATH_SEPARATOR ) }
63+
64+ sh 'gem' , 'build' , 'cataract.gemspec' , '-o' , gem_file
65+ sh env , 'gem' , 'install' , gem_file , '--no-document' , '--' , '--disable-native-extension'
66+
67+ compiled = Dir . glob ( File . join ( gem_home , '**' , '*.{so,bundle}' ) )
68+ raise "Expected no compiled artifacts, found: #{ compiled . join ( ', ' ) } " unless compiled . empty?
69+
70+ puts "\n ✓ Nothing was compiled"
71+
72+ File . write ( File . join ( dir , 'sample.css' ) , "body { color: red; }\n @media print { .a, .b { margin: 0; } }\n " )
73+
74+ # Run outside this checkout with CATARACT_PURE unset, so the installed
75+ # gem has to reach the pure backend on its own rather than being told to.
76+ check = <<~RUBY
77+ require 'cataract'
78+
79+ # GEM_PATH reaches beyond the scratch install so dependencies resolve,
80+ # so confirm this is the gem we just built and not one already present.
81+ spec = Gem.loaded_specs['cataract']
82+ unless spec && File.realpath(spec.full_gem_path).start_with?('#{ File . realpath ( dir ) } ')
83+ raise "cataract loaded from \# {spec&.full_gem_path.inspect}, not the scratch install"
84+ end
85+
86+ # The build recorded the decision, rather than it being inferred.
87+ if Cataract::BuildConfig::NATIVE_EXTENSION
88+ raise 'BuildConfig::NATIVE_EXTENSION is true; expected the install to have recorded false'
89+ end
90+
91+ # The compiled objects are genuinely absent, not merely unused. Without
92+ # this, a stale extension left on the load path would satisfy every
93+ # other assertion here.
94+ %w[cataract/native_extension cataract/cataract_color].each do |ext|
95+ begin
96+ require ext
97+ rescue LoadError
98+ next
99+ end
100+ raise "\# {ext} loaded; expected no compiled extension to be available"
101+ end
102+
103+ unless Cataract::IMPLEMENTATION == :ruby
104+ raise "Expected the pure backend, got \# {Cataract::IMPLEMENTATION.inspect}"
105+ end
106+
107+ unless defined?(Cataract::Backends::Native).nil?
108+ raise 'Cataract::Backends::Native is defined; the native backend should never have loaded'
109+ end
110+
111+ sheet = Cataract::Stylesheet.parse(File.read('sample.css'))
112+ raise "Expected 3 rules, got \# {sheet.rules_count}" unless sheet.rules_count == 3
113+
114+ css = sheet.to_s
115+ raise "Declaration lost: \# {css.inspect}" unless css.include?('color: red')
116+ raise "Media query lost: \# {css.inspect}" unless css.include?('@media print')
117+
118+ puts "✓ No compiled extension is loadable"
119+ puts "✓ Loaded the \# {Cataract::IMPLEMENTATION} backend and parsed \# {sheet.rules_count} rules"
120+ RUBY
121+
122+ # verbose(false) so rake doesn't echo the whole check script back
123+ Dir . chdir ( dir ) do
124+ verbose ( false ) do
125+ sh env . merge ( 'RUBYOPT' => nil , 'BUNDLE_GEMFILE' => nil , 'CATARACT_PURE' => nil ) ,
126+ RbConfig . ruby , '-e' , check
127+ end
128+ end
129+ end
130+
131+ puts "\n ✓ Pure-only install verified"
132+ end
133+
43134 desc 'Bump version (usage: rake gem:bump[major|minor|patch])'
44135 task :bump , [ :type ] do |_t , args |
45136 type = args [ :type ] || 'patch'
0 commit comments