Files
n8n-openai-adapter/lib/elixir/test/elixir/kernel/errors_test.exs
T

673 lines
19 KiB
Elixir

Code.require_file "../test_helper.exs", __DIR__
defmodule Kernel.ErrorsTest do
use ExUnit.Case, async: true
import CompileAssertion
defmodule UnproperMacro do
defmacro unproper(args), do: args
defmacro exit(args), do: args
end
defrecord Config, integer: 0
test :invalid_token do
assert_compile_fail SyntaxError,
"nofile:1: invalid token: \end",
'\end\nlol\nbarbecue'
end
test :sigil_terminator do
assert_compile_fail TokenMissingError,
"nofile:3: missing terminator: \" (for sigil %r\" starting at line 1)",
'%r"foo\n\n'
assert_compile_fail TokenMissingError,
"nofile:3: missing terminator: } (for sigil %r{ starting at line 1)",
'%r{foo\n\n'
assert_compile_fail TokenMissingError,
"nofile:3: missing terminator: ) (for sigil %r( starting at line 1)",
'%r(f(oo)\n\n'
end
test :dot_terminator do
assert_compile_fail TokenMissingError,
"nofile:1: missing terminator: \" (for function name starting at line 1)",
'foo."bar'
end
test :string_terminator do
assert_compile_fail TokenMissingError,
"nofile:1: missing terminator: \" (for string starting at line 1)",
'"bar'
end
test :heredoc_terminator do
assert_compile_fail TokenMissingError,
"nofile:2: missing terminator: \"\"\" (for heredoc starting at line 1)",
'"""\nbar'
end
test :unexpected_end do
assert_compile_fail SyntaxError,
"nofile:1: unexpected token: end",
'1 end'
end
test :syntax_error do
assert_compile_fail SyntaxError,
"nofile:1: syntax error before: '.'",
'+.foo'
end
test :syntax_error_on_op_ambiguity do
msg = "nofile:1: \"a -1\" looks like a function call but there is a variable named \"a\", " <>
"please use explicit parenthesis or even spaces"
assert_compile_fail SyntaxError, msg, 'a = 1; a -1'
max = 1
assert max == 1
assert (max 1, 2) == 2
end
test :syntax_error_on_parens_call do
msg = "nofile:1: unexpected parenthesis. If you are making a function call, do not " <>
"insert spaces in between the function name and the opening parentheses. " <>
"Syntax error before: '('"
assert_compile_fail SyntaxError, msg, 'foo (hello, world)'
assert_compile_fail SyntaxError, msg, 'foo ()'
assert_compile_fail SyntaxError, msg, 'foo (), 1'
end
test :syntax_error_on_nested_no_parens_call do
msg = "nofile:1: unexpected comma. Parentheses are required to solve ambiguity in " <>
"nested calls. Syntax error before: ','"
assert_compile_fail SyntaxError, msg, '[foo 1, 2]'
assert_compile_fail SyntaxError, msg, '[do: foo 1, 2]'
assert_compile_fail SyntaxError, msg, 'foo(do: bar 1, 2)'
assert_compile_fail SyntaxError, msg, '{foo 1, 2}'
assert_compile_fail SyntaxError, msg, 'foo 1, foo 2, 3'
assert_compile_fail SyntaxError, msg, 'foo(1, foo 2, 3)'
assert is_list []
assert is_list do: 1
assert is_list List.flatten [1]
assert is_atom is_record 1..3, Range
assert is_atom(is_record 1..3, Range)
end
test :syntax_error_with_no_token do
assert_compile_fail TokenMissingError,
"nofile:1: missing terminator: ) (for \"(\" starting at line 1)",
'case 1 ('
end
test :clause_with_defaults do
assert_compile_fail CompileError,
"nofile:3: def hello/1 has default values and multiple clauses, " <>
"use a separate clause for declaring defaults",
'''
defmodule ErrorsTest do
def hello(arg // 0), do: nil
def hello(arg // 1), do: nil
end
'''
end
test :invalid_match_pattern do
assert_compile_fail CompileError,
"nofile:2: invalid pattern in match clause",
'''
case true do
true && true -> true
end
'''
end
test :different_defs_with_defaults do
assert_compile_fail CompileError,
"nofile:3: def hello/3 defaults conflicts with def hello/2",
'''
defmodule ErrorsTest do
def hello(a, b // nil), do: a + b
def hello(a, b // nil, c // nil), do: a + b + c
end
'''
assert_compile_fail CompileError,
"nofile:3: def hello/2 conflicts with defaults from def hello/3",
'''
defmodule ErrorsTest do
def hello(a, b // nil, c // nil), do: a + b + c
def hello(a, b // nil), do: a + b
end
'''
end
test :bad_form do
assert_compile_fail CompileError,
"nofile:2: function bar/0 undefined",
'''
defmodule ErrorsTest do
def foo, do: bar
end
'''
end
test :unbound_var do
assert_compile_fail CompileError,
"nofile:1: unbound variable ^x",
'^x = 1'
end
test :unbound_not_match do
assert_compile_fail CompileError,
"nofile:1: cannot use ^x outside of match clauses",
'^x'
end
test :unbound_expr do
assert_compile_fail SyntaxError,
"nofile:1: the unary operator ^ can only be used with variables, invalid expression ^x(1)",
'^x(1)'
end
test :name_for_defmodule do
assert_compile_fail CompileError,
"nofile:1: invalid module name: 3",
'defmodule 1 + 2, do: 3'
end
test :invalid_scope_for_function do
assert_compile_fail SyntaxError,
"nofile:1: cannot invoke def outside module",
'def Foo, do: 2'
assert_compile_fail SyntaxError,
"nofile:3: cannot invoke defmacro outside module",
'\n\ndefmacro Foo, do: 2'
end
test :invalid_unquote do
assert_compile_fail CompileError,
"nofile:1: unquote called outside quote",
'unquote 1'
end
test :invalid_quote_args do
assert_compile_fail SyntaxError,
"nofile:1: invalid args for quote",
'quote 1'
end
test :invalid_calls do
assert_compile_fail SyntaxError,
"nofile:1: invalid call foo(1)(2)",
'foo(1)(2)'
assert_compile_fail SyntaxError,
"nofile:1: invalid remote call on 1",
'1.foo'
end
test :unhandled_stab do
assert_compile_fail SyntaxError,
"nofile:3: unhandled operator ->",
'''
defmodule Mod do
def fun do
casea foo, do: (bar -> baz)
end
end
'''
end
test :undefined_non_local_function do
assert_compile_fail CompileError,
"nofile:1: function casea/2 undefined",
'casea foo, do: (bar -> baz)'
end
test :invalid_fn_args do
assert_compile_fail TokenMissingError,
"nofile:1: missing terminator: end (for \"fn\" starting at line 1)",
'fn 1'
end
test :function_local_conflict do
assert_compile_fail CompileError,
"nofile:1: imported Kernel.&&/2 conflicts with local function",
'''
defmodule ErrorsTest do
1 && 2
def _ && _, do: :error
end
'''
end
test :macro_local_conflict do
assert_compile_fail CompileError,
"nofile:6: call to local macro &&/2 conflicts with imported Kernel.&&/2, " <>
"please rename the local macro or remove the conflicting import",
'''
defmodule ErrorsTest do
def hello, do: 1 || 2
defmacro _ || _, do: :ok
defmacro _ && _, do: :error
def world, do: 1 && 2
end
'''
end
test :macro_with_undefined_local do
assert_compile_fail UndefinedFunctionError,
"undefined function: ErrorsTest.unknown/1",
'''
defmodule ErrorsTest do
defmacrop bar, do: unknown(1)
def baz, do: bar()
end
'''
end
test :private_macro do
assert_compile_fail UndefinedFunctionError,
"undefined function: ErrorsTest.foo/0",
'''
defmodule ErrorsTest do
defmacrop foo, do: 1
defmacro bar, do: __MODULE__.foo
defmacro baz, do: bar
end
'''
end
test :function_definition_with_alias do
assert_compile_fail SyntaxError,
"nofile:2: function names should start with lowercase characters or underscore, invalid name Bar",
'''
defmodule ErrorsTest do
def Bar do
:baz
end
end
'''
end
test :function_import_conflict do
assert_compile_fail CompileError,
"nofile:3: function exit/1 imported from both :erlang and Kernel, call is ambiguous",
'''
defmodule ErrorsTest do
import :erlang
def foo, do: exit(:test)
end
'''
end
test :import_invalid_macro do
assert_compile_fail CompileError,
"nofile:1: cannot import Kernel.invalid/1 because it doesn't exist",
'import Kernel, only: [invalid: 1]'
end
test :unrequired_macro do
assert_compile_fail SyntaxError,
"nofile:2: you must require Kernel.ErrorsTest.UnproperMacro before invoking " <>
"the macro Kernel.ErrorsTest.UnproperMacro.unproper/1 "
'''
defmodule ErrorsTest do
Kernel.ErrorsTest.UnproperMacro.unproper([])
end
'''
end
test :def_defmacro_clause_change do
assert_compile_fail CompileError,
"nofile:3: defmacro foo/1 already defined as def",
'''
defmodule ErrorsTest do
def foo(1), do: 1
defmacro foo(x), do: x
end
'''
end
test :internal_function_overridden do
assert_compile_fail CompileError,
"nofile:1: function __info__/1 is internal and should not be overridden",
'''
defmodule ErrorsTest do
def __info__(_), do: []
end
'''
end
test :no_macros do
assert_compile_fail CompileError,
"nofile:2: could not load macros from module :lists",
'''
defmodule ErrorsTest do
import :lists, only: :macros
end
'''
end
test :invalid_macro do
assert_compile_fail CompileError,
"nofile: tuples in quoted expressions must have 2 or 3 items, invalid quoted expression: {:foo, :bar, :baz, :bat}",
'''
defmodule ErrorsTest do
defmacrop oops do
{ :foo, :bar, :baz, :bat }
end
def test, do: oops
end
'''
end
test :unloaded_module do
assert_compile_fail CompileError,
"nofile:1: module Certainly.Doesnt.Exist is not loaded and could not be found",
'import Certainly.Doesnt.Exist'
end
test :scheduled_module do
assert_compile_fail CompileError,
"nofile:4: module ErrorsTest.Hygiene is not loaded but was defined. " <>
"This happens because you are trying to use a module in the same context it is defined. " <>
"Try defining the module outside the context that requires it.",
'''
defmodule ErrorsTest do
defmodule Hygiene do
end
import ErrorsTest.Hygiene
end
'''
end
test :already_compiled_module do
assert_compile_fail ArgumentError,
"could not call eval_quoted on module Record " <>
"because it was already compiled",
'Module.eval_quoted Record, quote(do: 1), [], file: __FILE__'
end
test :interpolation_error do
assert_compile_fail SyntaxError,
"nofile:1: \"do\" starting at line 1 is missing terminator \"end\". Unexpected token: )",
'"foo\#{case 1 do )}bar"'
end
test :in_definition_module do
assert_compile_fail CompileError,
"nofile:1: cannot define module ErrorsTest because it is currently being defined",
'defmodule ErrorsTest, do: (defmodule Elixir.ErrorsTest, do: true)'
end
test :invalid_definition do
assert_compile_fail SyntaxError,
"nofile:1: invalid syntax in def 1.(hello)",
'defmodule ErrorsTest, do: (def 1.(hello), do: true)'
end
test :duplicated_bitstring_size do
assert_compile_fail SyntaxError,
"nofile:1: duplicated size definition for bitstring",
'<<1 :: [size(12), size(13)]>>'
end
test :invalid_bitstring_specified do
assert_compile_fail SyntaxError,
"nofile:1: unknown bitstring specifier :atom",
'<<1 :: :atom>>'
assert_compile_fail SyntaxError,
"nofile:1: unknown bitstring specifier unknown",
'<<1 :: unknown>>'
assert_compile_fail SyntaxError,
"nofile:1: unknown bitstring specifier another(12)",
'<<1 :: another(12)>>'
assert_compile_fail SyntaxError,
"nofile:1: size in bitstring expects an integer or a variable as argument",
'<<1 :: size(:a)>>'
assert_compile_fail SyntaxError,
"nofile:1: unit in bitstring expects an integer as argument",
'<<1 :: unit(:x)>>'
end
test :invalid_var! do
assert_compile_fail CompileError,
"nofile:1: expected var!(x) to expand to an existing variable or be a part of a match",
'var!(x)'
end
test :invalid_alias do
assert_compile_fail CompileError,
"nofile:1: invalid :as for alias, nested alias Sample.Lists not allowed",
'alias :lists, as: Sample.Lists'
end
test :invalid_import_option do
assert_compile_fail CompileError,
"nofile:1: unsupported option :ops given to import",
'import :lists, [ops: 1]'
end
test :invalid_access_protocol_not_available do
assert_compile_fail CompileError,
"nofile:2: module Unknown is not loaded and could not be found",
'''
defmodule ErrorsTest do
def sample(Unknown[integer: 0]), do: true
end
'''
end
test :invalid_access_protocol_not_alias do
assert_raise ArgumentError, "dynamic access cannot be invoked inside match and guard clauses", fn ->
defmodule ErrorsTest do
def sample(config[integer: 0]), do: true
end
end
end
test :invalid_access_protocol_not_record do
assert_raise ArgumentError, "cannot use module Kernel.ErrorsTest in access protocol because it does not export __record__/1", fn ->
defmodule ErrorsTest do
def sample(Kernel.ErrorsTest[integer: 0]), do: true
end
end
end
test :invalid_access_protocol_not_keywords do
assert_raise ArgumentError, "expected contents inside brackets to be a keyword list, got: [0]", fn ->
defmodule ErrorsTest do
def sample(Kernel.ErrorsTest.Config[0]), do: true
end
end
end
test :invalid_access_protocol_invalid_keywords do
assert_raise ArgumentError, "record Kernel.ErrorsTest.Config does not have the keys: [:foo]", fn ->
defmodule ErrorsTest do
def sample(Kernel.ErrorsTest.Config[foo: :bar]), do: true
end
end
end
test :invalid_access_protocol_invalid_keywords_outside_match do
assert_compile_fail ArgumentError,
"record Kernel.ErrorsTest.Config does not have the keys: [:foo]",
'Kernel.ErrorsTest.Config[foo: :bar]'
end
test :invalid_rescue_clause do
assert_compile_fail SyntaxError,
"nofile:4: invalid rescue clause. The clause should match on an alias, a variable or be in the `var in [alias]` format",
'try do\n1\nrescue\nUndefinedFunctionError[arity: 1] -> false\nend'
end
test :invalid_bc_return do
assert_compile_fail SyntaxError,
"nofile:1: a bit comprehension expects a bit string << >> to be returned",
'bc x inlist [1, 2, 3], do: x'
end
test :invalid_bc_inbits_gen do
assert_compile_fail SyntaxError,
"nofile:1: a bit comprehension expects a bit string << >> to be used in inbits generators",
'bc x inbits "123", do: <<x>>'
end
test :unbound_cond do
assert_compile_fail ArgumentError,
"unbound variable _ inside cond. If you want the last clause to match, you probably meant to use true ->",
'cond do _ -> true end'
end
test :fun_different_arities do
assert_compile_fail SyntaxError,
"nofile:1: cannot mix clauses with different arities in function definition",
'fn x -> x; x, y -> x + y end'
end
test :new_line_error do
assert_compile_fail SyntaxError,
"nofile:3: syntax error before: newline",
'if true do\n foo = [],\n baz\nend'
end
test :invalid_var_or_function_on_guard do
assert_compile_fail CompileError,
"nofile:2: unknown variable something_that_does_not_exist or " <>
"cannot invoke function something_that_does_not_exist/0 inside guard",
'''
case [] do
[] when something_that_does_not_exist == [] -> :ok
end
'''
end
test :bodyless_function_with_guard do
assert_compile_fail SyntaxError,
"nofile:2: missing do keyword in def",
'''
defmodule ErrorsTest do
def foo(n) when is_number(n)
end
'''
end
test :invalid_function_on_match do
assert_compile_fail CompileError,
"nofile:1: cannot invoke function something_that_does_not_exist/0 inside match",
'case [] do; something_that_does_not_exist() -> :ok; end'
end
test :invalid_remote_on_match do
assert_compile_fail CompileError,
"nofile:1: cannot invoke remote function Hello.something_that_does_not_exist/0 inside match",
'case [] do; Hello.something_that_does_not_exist() -> :ok; end'
end
test :invalid_remote_on_guard do
assert_compile_fail CompileError,
"nofile:1: cannot invoke remote function Hello.something_that_does_not_exist/0 inside guard",
'case [] do; [] when Hello.something_that_does_not_exist == [] -> :ok; end'
end
test :typespec_errors do
assert_compile_fail CompileError,
"nofile:2: type foo() undefined",
'''
defmodule ErrorsTest do
@type omg :: foo
end
'''
assert_compile_fail CompileError,
"nofile:2: spec for undefined function ErrorsTest.omg/0",
'''
defmodule ErrorsTest do
@spec omg :: atom
end
'''
end
test :bad_unquoting do
assert_compile_fail SyntaxError,
"nofile: expected a valid quoted expression, got: {Range, 1, 3}",
'''
defmodule ErrorsTest do
def range(unquote(1..3)), do: :ok
end
'''
end
test :macros_error_stacktrace do
assert [{:erlang, :+, [1, :foo], _}, {ErrorsTest, :sample, 1, _}|_] =
rescue_stacktrace(""")
defmodule ErrorsTest do
defmacro sample(num), do: num + :foo
def other, do: sample(1)
end
"""
end
test :macros_function_clause_stacktrace do
assert [{__MODULE__, :sample, 1, _}|_] =
rescue_stacktrace(""")
defmodule ErrorsTest do
import Kernel.ErrorsTest
sample(1)
end
"""
end
test :macros_interpreted_function_clause_stacktrace do
assert [{ErrorsTest, :sample, 1, _}|_] =
rescue_stacktrace(""")
defmodule ErrorsTest do
defmacro sample(0), do: 0
def other, do: sample(1)
end
"""
end
test :macros_compiled_callback do
assert [{Kernel.ErrorsTest, :__before_compile__, [Macro.Env[module: ErrorsTest]], _}|_] =
rescue_stacktrace(""")
defmodule ErrorsTest do
Module.put_attribute(__MODULE__, :before_compile, Kernel.ErrorsTest)
end
"""
end
defmacro sample(0), do: 0
defmacro before_compile(_) do
quote(do: _)
end
## Helpers
defp rescue_stacktrace(expr) do
result = try do
:elixir.eval(to_char_list(expr), [])
nil
rescue
_ -> System.stacktrace
end
result || raise(ExUnit.AssertionError, message: "Expected function given to rescue_stacktrace to fail")
end
end