# frozen_string_literal: true require "base64" require "webmock/minitest" require "minitest/autorun" require "dhall" class TestResolve < Minitest::Test def setup @relative_to = Dhall::Import::RelativePath.new @resolver = Dhall::Resolvers::Default.new( path_reader: lambda do |sources| sources.map do |source| Promise.resolve(Base64.decode64({ "var" => "AA", "import" => "hRgY9gADY3Zhcg", "a" => "hRgY9gADYWI", "b" => "hRgY9gADYWE", "self" => "hRgY9gADZHNlbGY", "text" => "aGFp", "moretext" => "hRgY9gEDZHRleHQ", "2text" => "hAMGhRgY9gEDZHRleHSFGBj2AANobW9yZXRleHQ", "using" => "iBgY9gAAhRgY9gADZ2hlYWRlcnNkZS50ZGF09g", "headers" => "gwT2ggiiZmhlYWRlcoISYnRoZXZhbHVlghJidHY" }.fetch(source.pathname.to_s))) end end ) end def subject(expr) expr.resolve(resolver: @resolver, relative_to: @relative_to).sync end def test_nothing_to_resolve expr = Dhall::Function.of_arguments( Dhall::Variable["Natural"], body: Dhall::Variable["_"] ) assert_equal expr, expr.resolve(resolver: Dhall::Resolvers::None.new).sync end def test_import_as_text expr = Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Text, Dhall::Import::RelativePath.new("text") ) assert_equal Dhall::Text.new(value: "hai"), subject(expr) end def test_one_level_to_resolve expr = Dhall::Function.of_arguments( Dhall::Variable["Natural"], body: Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::RelativePath.new("var") ) ) assert_equal expr.with(body: Dhall::Variable["_"]), subject(expr) end def test_two_levels_to_resolve expr = Dhall::Function.of_arguments( Dhall::Variable["Natural"], body: Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::RelativePath.new("import") ) ) assert_equal expr.with(body: Dhall::Variable["_"]), subject(expr) end def test_self_loop expr = Dhall::Function.of_arguments( Dhall::Variable["Natural"], body: Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::RelativePath.new("self") ) ) assert_raises Dhall::ImportLoopException do subject(expr) end end def test_two_level_loop expr = Dhall::Function.of_arguments( Dhall::Variable["Natural"], body: Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::RelativePath.new("a") ) ) assert_raises Dhall::ImportLoopException do subject(expr) end end def test_two_references_no_loop expr = Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::RelativePath.new("2text") ) assert_equal( Dhall::Operator::TextConcatenate.new( lhs: Dhall::Text.new(value: "hai"), rhs: Dhall::Text.new(value: "hai") ), subject(expr) ) end def test_missing expr = Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::MissingImport.new ) assert_raises Dhall::ImportFailedException do subject(expr) end end def test_integrity_check_failure expr = Dhall::Import.new( Dhall::Import::IntegrityCheck.new("sha256", "badhash"), Dhall::Import::Expression, Dhall::Import::RelativePath.new("var") ) assert_raises Dhall::Import::IntegrityCheck::FailureException do subject(expr) end end def test_fallback_to_expr expr = Dhall::Operator::ImportFallback.new( lhs: Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::MissingImport.new ), rhs: Dhall::Variable["fallback"] ) assert_equal( Dhall::Variable["fallback"], subject(expr) ) end def test_fallback_to_import expr = Dhall::Operator::ImportFallback.new( lhs: Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::MissingImport.new ), rhs: Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::RelativePath.new("import") ) ) assert_equal Dhall::Variable["_"], subject(expr) end def test_headers stub_request(:get, "http://e.td/t") .with(headers: { "Th" => "tv" }) .to_return(status: 200, body: "\x00".b) expr = Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::RelativePath.new("using") ) assert_equal Dhall::Variable["_"], subject(expr) end def test_ipfs stub_request(:get, "http://localhost:8000/ipfs/TESTCID") .to_return(status: 200, body: "\x00".b) expr = Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::AbsolutePath.new("ipfs", "TESTCID") ) assert_equal Dhall::Variable["_"], expr.resolve.sync end def test_ipfs_public_gateway stub_request(:get, "http://localhost:8000/ipfs/TESTCID") .to_return(status: 500) stub_request(:get, "https://cloudflare-ipfs.com/ipfs/TESTCID") .to_return(status: 200, body: "_") expr = Dhall::Import.new( Dhall::Import::IntegrityCheck.new, Dhall::Import::Expression, Dhall::Import::AbsolutePath.new("ipfs", "TESTCID") ) assert_equal Dhall::Variable["_"], expr.resolve.sync end DIRPATH = Pathname.new(File.dirname(__FILE__)) TESTS = DIRPATH + "../dhall-lang/tests/import/" Pathname.glob(TESTS + "success/**/*A.dhall").each do |path| test = path.relative_path_from(TESTS).to_s.sub(/A\.dhall$/, "") define_method("test_#{test}") do assert_equal( Dhall::Parser.parse_file(TESTS + "#{test}B.dhall").value, Dhall::Parser.parse_file(path).value.resolve( relative_to: Dhall::Import::Path.from_string(path) ).sync ) end end Pathname.glob(TESTS + "failure/**/*.dhall").each do |path| test = path.relative_path_from(TESTS).to_s.sub(/\.dhall$/, "") define_method("test_#{test}") do stub_request( :get, "https://raw.githubusercontent.com/dhall-lang/dhall-lang/" \ "master/tests/import/data/referentiallyOpaque.dhall" ).to_return(status: 200, body: "env:HOME as Text") assert_raises Dhall::ImportFailedException do Dhall::Parser.parse_file(path).value.resolve( relative_to: Dhall::Import::Path.from_string(path) ).sync end end end NTESTS = DIRPATH + "../dhall-lang/tests/normalization/" # Sanity check that all expressions can pass through the resolver Pathname.glob(NTESTS + "**/*A.dhall").each do |path| test = path.relative_path_from(TESTS).to_s.sub(/A\.dhall$/, "") next if test =~ /prelude\/|remoteSystems/ define_method("test_#{test}") do expr = Dhall::Parser.parse_file(path).value assert_equal expr, expr.resolve.sync end end end