Open bterone opened 3 years ago
@bterone thanks for the detailed bug report. Out of interest, can you try stubbing :erlang.integer_to_binary/2
instead? It seems that Integer.to_string/1..2
is inlined into that function by the compiler.
Hi, thanks for taking your time to respond 😄 , I'm a bit unsure how to copy the :erlang
atom to stub. Do I need some sort of adapter module to stub, or is there some macro that could help me out? 🤔
Hey @bterone. All module names in Elixir and Erlang are atoms. You should just be able to do Mimic.copy(:erlang)
and then stub the function as per usual.
I think in general we want to avoid touching the standard lib.
I guess we could add a validation to copy
to not allow some modules? 🤔
We can probably get all Elixir modules using this:
iex(3)> :application.get_key(:elixir, :modules)
{:ok,
[Access, Agent.Server, Agent, Application, ArgumentError, ArithmeticError,
Atom, BadArityError, BadBooleanError, BadFunctionError, BadMapError,
BadStructError, Base, Behaviour, Bitwise, Calendar.ISO,
Calendar.TimeZoneDatabase, Calendar.UTCOnlyTimeZoneDatabase, Calendar,
CaseClauseError, Code.Formatter, Code.Identifier, Code.LoadError,
Code.Typespec, Code, Collectable.BitString, Collectable.File.Stream,
Collectable.HashDict, Collectable.HashSet, Collectable.IO.Stream,
Collectable.List, Collectable.Map, Collectable.MapSet, Collectable,
CompileError, CondClauseError, Config.Provider, Config.Reader, Config,
Date.Range, Date, DateTime, Dict, DynamicSupervisor, Enum.EmptyError,
Enum.OutOfBoundsError, Enum, Enumerable.Date.Range, ...]}
Not sure about Erlang though
Oh I agree. I just thought it was worth seeing if this fixed it because it may hint at something weird about the compiler inlining.
Hey @bterone. All module names in Elixir and Erlang are atoms. You should just be able to do
Mimic.copy(:erlang)
and then stub the function as per usual.
Hi @jimsynz, I've tried using Mimic.copy(:erlang)
but it seems to fail when trying to fetch the compile options from that atom as it doesn't exist 🤔
** (Protocol.UndefinedError) protocol Enumerable not implemented for nil of type Atom. This protocol is implemented for the following type(s): HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream
(elixir 1.11.4) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.11.4) lib/enum.ex:141: Enumerable.reduce/3
(elixir 1.11.4) lib/enum.ex:3473: Enum.filter/2
(mimic 1.5.0) lib/mimic/module.ex:65: Mimic.Module.compiler_options/1
(mimic 1.5.0) lib/mimic/module.ex:43: Mimic.Module.rename_module/2
(mimic 1.5.0) lib/mimic/module.ex:27: Mimic.Module.replace!/1
(mimic 1.5.0) lib/mimic.ex:344: Mimic.copy/1
test/test_helper.exs:4: (file)
When checking that line that was causing the issue
Even modifying the Keyword.get(:options)
to give an empty []
as default has an error when we try to do :compile.forms(forms, compiler_options(module))
on line 43 🤔
** (CaseClauseError) no case clause matching: {:error, [{'erlang.erl', [{{353, 2}, :erl_lint, {:bad_module, {:erlang, :adler32, 1}}}, {{359, 2}, :erl_lint, {:bad_module, {:erlang, :adler32, 2}}}, {{366, 2}, :erl_lint, {:bad_module, {:erlang, :adler32_combine, 3}}}, {{374, 2}, :erl_lint, {:bad_module, {:erlang, :append_element, 2}}}, {{518, 2}, :erl_lint, {:bad_module, {:erlang, :bump_reductions, 1}}}, {{531, 2}, :erl_lint, {:bad_module, {:erlang, :call_on_load_function, 1}}}, {{537, 2}, :erl_lint, {:bad_module, {:erlang, :cancel_timer, 1}}}, {{546, 2}, :erl_lint, {:bad_module, {:erlang, :cancel_timer, 2}}}, {{602, 2}, :erl_lint, {:bad_module, {:erlang, :crc32, 1}}}, {{608, 2}, :erl_lint, {:bad_module, {:erlang, :crc32, 2}}}, {{615, 2}, :erl_lint, {:bad_module, {:erlang, :crc32_combine, 3}}}, {{629, 2}, :erl_lint, {:bad_module, {:erlang, :decode_packet, 3}}}, {{726, 2}, :erl_lint, {:bad_module, {:erlang, :delete_element, 2}}}, {{773, 2}, :erl_lint, {:bad_module, {:erlang, :display, 1}}}, {{779, 2}, :erl_lint, {:bad_module, {:erlang, :display_nl, 0}}}, {{784, 2}, :erl_lint, {:bad_module, {:erlang, :display_string, 1}}}, {{790, 2}, :erl_lint, {:bad_module, {:erlang, :dt_append_vm_tag_data, 1}}}, {{797, 2}, :erl_lint, {:bad_module, {:erlang, :dt_get_tag, 0}}}, {{802, 2}, :erl_lint, {:bad_module, {:erlang, :dt_get_tag_data, 0}}}, {{807, 2}, :erl_lint, {:bad_module, {:erlang, :dt_prepend_vm_tag_data, 1}}}, {{814, 2}, :erl_lint, {:bad_module, {:erlang, :dt_put_tag, 1}}}, {{820, 2}, :erl_lint, {:bad_module, {:erlang, :dt_restore_tag, 1}}}, {{826, 2}, :erl_lint, {:bad_module, {:erlang, :dt_spread_tag, 1}}}, {{888, 2}, :erl_lint, {:bad_module, {:erlang, :exit_signal, 2}}}, {{895, 2}, :erl_lint, {:bad_module, {:erlang, :external_size, 1}}}, {{901, 2}, :erl_lint, {:bad_module, {:erlang, :external_size, 2}}}, {{908, 2}, :erl_lint, {:bad_module, {:erlang, :finish_loading, 1}}}, {{917, 2}, :erl_lint, {:bad_module, {:erlang, :finish_after_on_load, 2}}}, {{970, 2}, :erl_lint, {:bad_module, {:erlang, :fun_info, 2}}}, {{978, 2}, :erl_lint, {:bad_module, {:erlang, :fun_info_mfa, 1}}}, {{987, 2}, :erl_lint, {:bad_module, {:erlang, :fun_to_list, 1}}}, {{993, 2}, :erl_lint, {:bad_module, {:erlang, :function_exported, 3}}}, {{1067, 2}, :erl_lint, {:bad_module, {:erlang, :garbage_collect_message_area, 0}}}, {{1099, 2}, :erl_lint, {:bad_module, {:erlang, :get_module_info, 1}}}, {{1157, 2}, :erl_lint, {:bad_module, {:erlang, :has_prepared_code_on_load, 1}}}, {{1163, 2}, :erl_lint, {:bad_module, {:erlang, :hibernate, 3}}}, {{1171, 2}, :erl_lint, {:bad_module, {:erlang, :insert_element, 3}}}, {{1204, 2}, :erl_lint, {:bad_module, {:erlang, :iolist_to_iovec, ...}}}, {{1215, 2}, :erl_lint, {:bad_module, {:erlang, ...}}}, {{1316, 2}, :erl_lint, {:bad_module, {...}}}, {{1322, 2}, :erl_lint, {:bad_module, ...}}, {{1347, 2}, :erl_lint, {...}}, {{1356, ...}, :erl_lint, ...}, {{...}, ...}, {...}, ...]}], [{'erlang.erl', [{{247, 2}, :erl_lint, {:unused_type, {:fun_info_item, 0}}}, {{259, 2}, :erl_lint, {:unused_type, {:seq_trace_info_returns, 0}}}, {{265, 2}, :erl_lint, {:unused_type, {:system_profile_option, 0}}}, {{274, 2}, :erl_lint, {:unused_type, {:system_monitor_option, 0}}}, {{282, 2}, :erl_lint, {:unused_type, {:raise_stacktrace, 0}}}, {{291, 2}, :erl_lint, {:unused_type, {:trace_flag, 0}}}, {{343, 2}, :erl_lint, {:unused_type, {:trace_info_return, 0}}}, {{2119, 2}, :erl_lint, {:unused_type, {:module_info_key, 0}}}, {{2595, 2}, :erl_lint, {:unused_type, {:scheduler_bind_type, 0}}}, {{2699, 2}, :erl_lint, {:unused_type, {:trace_pattern_mfa, 0}}}, {{2717, 2}, :erl_lint, {:unused_type, {:trace_pattern_flag, 0}}}, {{2751, 2}, :erl_lint, {:unused_type, {:cpu_topology, 0}}}, {{3451, 2}, :erl_lint, {:unused_type, {:dst, 0}}}, {{3976, 2}, :erl_lint, {:unused_type, {:memory_type, 0}}}]}]}
(mimic 1.5.0) lib/mimic/module.ex:49: Mimic.Module.rename_module/2
(mimic 1.5.0) lib/mimic/module.ex:27: Mimic.Module.replace!/1
(mimic 1.5.0) lib/mimic.ex:344: Mimic.copy/1
test/test_helper.exs:5: (file)
Not really sure if it's even possible to copy :erlang
. ðŸ’
Issue
Trying to stub the
Integer.to_string/2
method does not work.Environment
Steps to reproduce
It seems the above test will fail, but if it's for some other method, like
Integer.digits/1
it passes.Not really sure what could be the issue without further investigation. 🤔
EDIT: I'll be more than happy to open an example repo reproducing the issue 😄