Open hauleth opened 5 years ago
Hi @hauleth ! Interesting (and hard) case! Thank you for spending time to make an Erlang equivalent.
Concuerror needs the abstract syntax tree of a module in order to instrument it, so it will be infeasible to fix this problem if that tree is not available in any way from Elixir script files.
As a line of investigation for you, is it possible to get coverage information for .exs
files? If so, is cover
used for that? cover
is also instrumenting using the AST, so perhaps a similar approach can be followed to send a test to Concuerror.
@aronisstav I have found the problematic line and it seems that it cannot be solved right now due to Erlang issue (ERL-805). And no, cover:compile(Mod)
do not work as well on such module.
@hauleth Right, but I am afraid that this is a design decision: there are no such introspection capabilities (i.e. "show me the abstract code of this loaded beam for which I have no file on disk") on the Erlang/OTP VM.
@aronisstav the point is that you can get that data, what is more, you get it each time when you build your module in-memory in Elixir (it doesn't fully work in Erlang version, probably there are other steps involved there) you get that data back:
{:module, ConcuerrorElixirExampleTest, bin, _} =
defmodule ConcuerrorElixirExampleTest do
def message_test do
this = self()
spawn(fn -> send(this, :foo) end)
spawn(fn -> send(this, :bar) end)
receive do
msg -> :foo = msg
end
end
end
IO.inspect :beam_lib.chunks(bin, [:abstract_code])
So this need to be stored somewhere (for example for error reporting), so it need to be fetchable in some way, the question is how.
@aronisstav temporary workaround could be if you would expose API that accept compiled module binary or AST instead of requiring module name. That would allow me to create few Elixir hacks to get it working.
@hauleth Such an API can be built by:
load_binary/3
in https://github.com/parapluu/Concuerror/blob/master/src/concuerror_loader.erl (the value for the Instrumented
argument is returned by get_instrumented_table
)concuerror_loader:initialise([]),
concuerror_loader:load_binary(..., ..., ...), %% the new function
concuerror:run([...]).
Do you want to take a shot at it yourself and get back if you have more questions? If you get some use from it, I will be very happy to help further with merging such a PR.
I have achieved some success with this code:
defmodule ConcuerrorElixirExampleTest do
use ExUnit.Case, async: true
doctest ConcuerrorElixirExample
@after_compile __MODULE__
def message_test do
this = self()
spawn(fn -> send(this, :foo) end)
spawn(fn -> send(this, :bar) end)
receive do
msg -> assert :foo == msg
end
end
test "Foo" do
beam = Agent.get(:conc_mod, fn beam -> beam end)
:concuerror_loader.initialize([])
:concuerror_loader.load_binary(__MODULE__, to_charlist(__ENV__.file), beam)
:concuerror.run(module: __MODULE__, test: :message_test)
end
def __after_compile__(_env, beam) do
Agent.start(fn -> beam end, name: :conc_mod)
end
end
This raises another question #300.
https://github.com/erlang/otp/issues/3755 was closed, though I can't tell if it was actually fixed. Is this still an issue? 🤔
@Nezteb yes, it is still issue. It was not fixed and will not be fixed. I have an idea for workaround, but never had time to sit and write that code.
Describe the bug
Concuerror silently fails on in-memory modules.
To Reproduce
This will success but there will be information that module cannot be loaded, which in fact mean that it silently does nothing.
Expected behavior
It should run tests.
It could fail, but it would be infeasible, as Elixir tests are defined in way similar to this, which makes testing them with
concuerror
quite troublesome (you need to create additional module in separate file (that is compiled) and only then you can run test on it).Environment (please complete the following information):
master
Additional context
This was found when tried to run Concuerror tests on Elixir tests.
Example Elixir code:
This must be saved as file with
.exs
extension and ran viaelixir file.exs
to reproduce error.