diff options
Diffstat (limited to 'test/prism/test_helper.rb')
-rw-r--r-- | test/prism/test_helper.rb | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/test/prism/test_helper.rb b/test/prism/test_helper.rb new file mode 100644 index 0000000000..77af7e7b45 --- /dev/null +++ b/test/prism/test_helper.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +require "prism" +require "ripper" +require "pp" +require "test/unit" +require "tempfile" + +puts "Using prism backend: #{Prism::BACKEND}" if ENV["PRISM_FFI_BACKEND"] + +# It is useful to have a diff even if the strings to compare are big +# However, ruby/ruby does not have a version of Test::Unit with access to +# max_diff_target_string_size +if defined?(Test::Unit::Assertions::AssertionMessage) + Test::Unit::Assertions::AssertionMessage.max_diff_target_string_size = 5000 +end + +module Prism + class TestCase < ::Test::Unit::TestCase + private + + if RUBY_ENGINE == "ruby" + # Check that the given source is valid syntax by compiling it with RubyVM. + def check_syntax(source) + $VERBOSE, previous = nil, $VERBOSE + + begin + RubyVM::InstructionSequence.compile(source) + ensure + $VERBOSE = previous + end + end + + # Assert that the given source is valid Ruby syntax by attempting to + # compile it, and then implicitly checking that it does not raise an + # syntax errors. + def assert_valid_syntax(source) + check_syntax(source) + end + + # Refute that the given source is invalid Ruby syntax by attempting to + # compile it and asserting that it raises a SyntaxError. + def refute_valid_syntax(source) + assert_raise(SyntaxError) { check_syntax(source) } + end + else + def assert_valid_syntax(source) + end + + def refute_valid_syntax(source) + end + end + + def assert_raises(*args, &block) + raise "Use assert_raise instead" + end + + def assert_equal_nodes(expected, actual, compare_location: true, parent: nil) + assert_equal expected.class, actual.class + + case expected + when Array + assert_equal( + expected.size, + actual.size, + -> { "Arrays were different sizes. Parent: #{parent.pretty_inspect}" } + ) + + expected.zip(actual).each do |(expected_element, actual_element)| + assert_equal_nodes( + expected_element, + actual_element, + compare_location: compare_location, + parent: actual + ) + end + when SourceFileNode + expected_deconstruct = expected.deconstruct_keys(nil) + actual_deconstruct = actual.deconstruct_keys(nil) + assert_equal expected_deconstruct.keys, actual_deconstruct.keys + + # Filepaths can be different if test suites were run on different + # machines. We accommodate for this by comparing the basenames, and not + # the absolute filepaths. + expected_filepath = expected_deconstruct.delete(:filepath) + actual_filepath = actual_deconstruct.delete(:filepath) + + assert_equal expected_deconstruct, actual_deconstruct + assert_equal File.basename(expected_filepath), File.basename(actual_filepath) + when Node + deconstructed_expected = expected.deconstruct_keys(nil) + deconstructed_actual = actual.deconstruct_keys(nil) + assert_equal deconstructed_expected.keys, deconstructed_actual.keys + + deconstructed_expected.each_key do |key| + assert_equal_nodes( + deconstructed_expected[key], + deconstructed_actual[key], + compare_location: compare_location, + parent: actual + ) + end + when Location + assert_operator actual.start_offset, :<=, actual.end_offset, -> { + "start_offset > end_offset for #{actual.inspect}, parent is #{parent.pretty_inspect}" + } + + if compare_location + assert_equal( + expected.start_offset, + actual.start_offset, + -> { "Start locations were different. Parent: #{parent.pretty_inspect}" } + ) + + assert_equal( + expected.end_offset, + actual.end_offset, + -> { "End locations were different. Parent: #{parent.pretty_inspect}" } + ) + end + else + assert_equal expected, actual + end + end + end +end |