summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEarlopain <14981592+Earlopain@users.noreply.github.com>2025-01-17 08:53:35 +0100
committerKevin Newton <kddnewton@gmail.com>2025-03-18 13:36:53 -0400
commitfc14d3ac7d4fa14f568d2428b846f391ebdf0d62 (patch)
tree1128c5f3460ee74b4740d5c45e724d0330881a24
parent0b4604d5a0f999d7fdd33a9230587a775301a667 (diff)
[ruby/prism] Allow to test a custom fixtures path during testing
Of course, these won't really be fixtures, but it allows to test against whole codebases without copying them, doing symlinks or something like that. For example, I can tell that over the whole RuboCop codebase, there are only 8 files that produce mismatched ast. Telling what the problem is is a different problem. The ast for real files can and will be huge so I haven't checked yet (maybe parser bug) but it's nice for discoverability regardless https://github.com/ruby/prism/commit/2184d82ba6
-rw-r--r--test/prism/snapshots_test.rb77
-rw-r--r--test/prism/test_helper.rb9
2 files changed, 84 insertions, 2 deletions
diff --git a/test/prism/snapshots_test.rb b/test/prism/snapshots_test.rb
new file mode 100644
index 0000000000..3fbda1f86e
--- /dev/null
+++ b/test/prism/snapshots_test.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+# We don't want to generate snapshots when running
+# against files outside of the project folder.
+return if Prism::TestCase::Fixture.custom_base_path?
+
+module Prism
+ class SnapshotsTest < TestCase
+ # When we pretty-print the trees to compare against the snapshots, we want
+ # to be certain that we print with the same external encoding. This is
+ # because methods like Symbol#inspect take into account external encoding
+ # and it could change how the snapshot is generated. On machines with
+ # certain settings (like LANG=C or -Eascii-8bit) this could have been
+ # changed. So here we're going to force it to be UTF-8 to keep the snapshots
+ # consistent.
+ def setup
+ @previous_default_external = Encoding.default_external
+ ignore_warnings { Encoding.default_external = Encoding::UTF_8 }
+ end
+
+ def teardown
+ ignore_warnings { Encoding.default_external = @previous_default_external }
+ end
+
+ except = []
+
+ # These fail on TruffleRuby due to a difference in Symbol#inspect:
+ # :测试 vs :"测试"
+ if RUBY_ENGINE == "truffleruby"
+ except.push(
+ "emoji_method_calls.txt",
+ "seattlerb/bug202.txt",
+ "seattlerb/magic_encoding_comment.txt"
+ )
+ end
+
+ Fixture.each(except: except) do |fixture|
+ define_method(fixture.test_name) { assert_snapshot(fixture) }
+ end
+
+ private
+
+ def assert_snapshot(fixture)
+ source = fixture.read
+
+ result = Prism.parse(source, filepath: fixture.path)
+ assert result.success?
+
+ printed = PP.pp(result.value, +"", 79)
+ snapshot = fixture.snapshot_path
+
+ if File.exist?(snapshot)
+ saved = File.read(snapshot)
+
+ # If the snapshot file exists, but the printed value does not match the
+ # snapshot, then update the snapshot file.
+ if printed != saved
+ File.write(snapshot, printed)
+ warn("Updated snapshot at #{snapshot}.")
+ end
+
+ # If the snapshot file exists, then assert that the printed value
+ # matches the snapshot.
+ assert_equal(saved, printed)
+ else
+ # If the snapshot file does not yet exist, then write it out now.
+ directory = File.dirname(snapshot)
+ FileUtils.mkdir_p(directory) unless File.directory?(directory)
+
+ File.write(snapshot, printed)
+ warn("Created snapshot at #{snapshot}.")
+ end
+ end
+ end
+end
diff --git a/test/prism/test_helper.rb b/test/prism/test_helper.rb
index b848500283..c5afdc0ea5 100644
--- a/test/prism/test_helper.rb
+++ b/test/prism/test_helper.rb
@@ -38,7 +38,7 @@ module Prism
# are used to define test methods that assert against each fixture in some
# way.
class Fixture
- BASE = File.join(__dir__, "fixtures")
+ BASE = ENV.fetch("FIXTURE_BASE", File.join(__dir__, "fixtures"))
attr_reader :path
@@ -63,9 +63,14 @@ module Prism
end
def self.each(except: [], &block)
- paths = Dir[ENV.fetch("FOCUS") { File.join("**", "*.txt") }, base: BASE] - except
+ glob_pattern = ENV.fetch("FOCUS") { custom_base_path? ? File.join("**", "*.rb") : File.join("**", "*.txt") }
+ paths = Dir[glob_pattern, base: BASE] - except
paths.each { |path| yield Fixture.new(path) }
end
+
+ def self.custom_base_path?
+ ENV.key?("FIXTURE_BASE")
+ end
end
# Yield each encoding that we want to test, along with a range of the