Closed kjw1 closed 10 years ago
Here's the test I was trying to run:
handle_message_test() ->
meck:new(chat_adapter_locator),
meck:new(chat_adapter_history),
meck:new(jabberer),
meck:expect(chat_adapter_locator, find_adapter,
fun(<<"from_phone_number">>) ->
{<<"from_phone_number">>, <<"anon@someserver">>, fake_pid}
end),
meck:expect(chat_adapter_locator, find_convo,
fun(<<"from_phone_number">>) ->
{<<"from_phone_number">>, <<"somejid@someserver">>}
end),
meck:expect(chat_adapter_history, record_message,
fun(<<"somejid@someserver">>, <<"from_phone_number">>, in, "some text!") ->
ok
end),
meck:expect(jabberer, send_message,
fun(fake_pid, <<"somejid@someserver">>, "some text!") ->
ok
end),
handle_message([{<<"From">>, <<"from_phone_number">>}, {<<"Body">>, <<"some text!">>}]),
meck:unload(jabberer),
meck:unload(chat_adapter_history),
meck:unload(chat_adapter_locator).
Hmm, seems somehow to be related to the cover data that Meck exports. When mocking a module, Meck saves the cover data, creates the mock, and when unloaded, restores the original module and cover data. This temporary file seems to go missing in between these steps.
One possible solution would be to try to restore the data, but only if the file exists. It would be interesting to find out why it goes missing in the first place though.
I'll try running the tests for meck on the machine and see if it fails anything, maybe I can figure out what the problem is.
I think there has to be some sort of race condition, but I'm not sure what it is. The temporary files are created, since I can see them being written with inotify, so maybe that's why meck can't find them. Also, sometimes the files end up written to the project root directory, not the eunit directory. Not sure what causes that, either.
Just to see what would happen, I disabled the tests on a module I was trying to meck, and the tests ran fine.
Still poking around, will post more updates later.
Do you run tests in parallel somehow? Could it be that you mock the same module twice somehow, like new(M), new(M), unload(M), unload(M) % Crash here
?
I'm only using meck in that one module. Even if eunit is running the tests in parallel, it shouldn't be mocking anything twice. I don't think I'm mocking the same module twice in this test, either. The test code is in one of my previous comments. I'll try to make a project that can replicate this behavior.
I made a trivial project which fails, even on my dev machine:
https://github.com/kjw1/meck_test
EDIT: Whoops, might be an error in the test itself, let me fix that first
Alright, I did some more experiments but I'm just more confused. First of all, I'm mocking 2 modules, chat_adapter_locator and chat_adapter history. If I have plain tests of the form:
some_test() ->
ok = ok.
then it works. However, if I have a test generator:
some_test() ->
{setup,
fun() -> ok end,
fun(_) -> ok end,
fun(_) -> [ fun() -> ok = ok end ]
}.
in one of those 2 modules, then it crashes. Right now I'm looking at covertool to see if that's causing issues. If that's the case I can try running that separately.
Doesn't seem to be covertool, either. I managed to strip down my work project so it literally has no code in the modules I'm testing but it's still failing. I'll put it in my test app repo soon, maybe you can take a look and see if it works for you.
It actually doesn't seem to have anything to do with cover at all. That is probably just a side effect of it crashing somewhere else. I don't have cover enabled anymore and it still crashes. I'm going to try this on another similar machine to make sure it still happens there.
I checked on another Ubuntu 12.04 LTS machine, and the same bug still happens. The meck test repository I posted earlier has the broken code. Just run
rebar compile
rebar eunit skip_deps=true
and it should crash. Please let me know if you have time to take a look.
I was seeing the same error, for me it turned out that I tried to unload a module I never mocked. Hope that helps you!
I managed to solve my problem by not having the tests in the same file as the module. I'm guessing this model isn't compatible with the way meck works. Thanks for your suggestion.
Were you mocking the same module you ran the test code from?
No, it was a different module.
I can repro *unexpected termination of test process* ::killed
by running two beam instances in parallel running the same tests in a loop. I straced the beam processes, and they did not ever operate on any coverdata files.
@dcsommer The *unexpected termination of test process* ::killed
messages comes from EUnit and doesn't necessarily have anything to do with Meck.
I should have left more details. The eunit process is crashing (causing that message) when I meck:unload()
a module in the teardown of a {setup, _, _, _}
test. I'll try to create a minimal repro program and report back.
https://github.com/eproxus/meck/issues/123#issuecomment-402217769 @dcsommer did you ever figure this out? I'm hitting the exact same issue (and am using the same test generator style and unloading there.
The strange part is this is the first time it happens in my project of about 50 files even though I'm using this pattern elsewhere.
It also matters what order the tests are run in -- I believe because it fails when I'm mecking a module it already tested.
Example:
rebar3 eunit -mmod_1,mod_2
mod2 has meck:new([mod_1)
in the setup and meck:unload()
in the teardown.
This crashes, but if I do rebar3 eunit -mmod_2,mod_1
it all works fine.
(Un?)fortunately my error disappeared and I was unable to repro it. If you have a 100% repro here, that is quite interesting. It is a known no-no to mock a module you are currently executing, but it seems like meck should be able to mock a previously loaded module.
On Fri, Aug 17, 2018 at 1:02 PM Paul Selden notifications@github.com wrote:
123 (comment)
https://github.com/eproxus/meck/issues/123#issuecomment-402217769 @dcsommer https://github.com/dcsommer did you ever figure this out? I'm hitting the exact same issue (and am using the same test generator style and unloading there.
The strange part is this is the first time it happens in my project of about 50 files even though I'm using this pattern elsewhere.
It also matters what order the tests are run in -- I believe because it fails when I'm mecking a module it already tested.
Example:
rebar3 eunit -mmod_1,mod_2
mod2 has meck:new([mod_1) in the setup and meck:unload() in the teardown.
This crashes, but if I do rebar3 eunit -mmod_2,mod_1 it all works fine.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/eproxus/meck/issues/123#issuecomment-413973873, or mute the thread https://github.com/notifications/unsubscribe-auth/ABCFINRTwX70XYTx8JNp3-mzTbjaa_Wbks5uRyE-gaJpZM4B4eLw .
@pselden @dcsommer Are you both using unlink
as an option or not? I assume it won't make a difference, since I have a hunch the problems are not Meck's fault. When Meck is reloading twice it kills some EUnit process that is lying around having references to the mocked module.
One test to reproduce/verify this could be to replace the mocking with a normal module reload to see if you can trigger the same problem.
I created a reproducible case here, but found out that it is only a problem in OTP 18 (my other project is also using that version still): https://github.com/pselden/test_meck_error
You can use ERLANG_VERSION=18 make
to start a docker shell using the given erlang version (or use whatever you want for version switching locally) and then run rebar3 eunit
. Crashes in 18, passes in 19.
I have an eunit test where I'm trying to meck some other modules I'm also testing. Is this supposed to work? For some reason this works on my dev machine, but not on my build machine.
Running Erlang 16B03 on both, rebar 2.2 Dev machine is Mac OS X Mavericks Build machine is Ubuntu 12.04 LTS