Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

mscorlib recursive resource lookup bug
topeju
#1 Posted : Monday, February 24, 2014 5:55:56 PM(UTC)
Rank: Newbie

Groups: Registered
Joined: 5/12/2013(UTC)
Posts: 9
Location: Finland

Thanks: 1 times
With NCrunch 2.4.0.2, I get an assert failure on one project which used to work just fine, though I cannot say if it started failing after upgrading to 2.4.0.2 (from one of the pre-release 2.x versions), or upgrading JustMock from 2013.3.1211.3 to 2013.3.1320.1 (I did both around the same time).

Screencap of the assert failure shown (sorry, it didn't quite fit on my screen):
nCrunch.TaskRunner451.x86 assert failure (mscorlib recursive resource lookup bug)

Using the Compatibility Mode settings, I found that I need to set Pre-load Assembly References to true, after which the tests run successfully. I found this by going through the settings in the order listed on the Compatibility Mode page, and stopped when the tests started working after changing the aforementioned setting. I could then safely switch the other settings back, and tests still work fine.

(Interestingly, though, NCrunch sees double during test execution: while it is running the tests, it thinks there are two times as many tests as there actually are. After completion, the number drops back down to the correct count.)

The solution I'm testing is an ASP.NET MVC 5 + Web API 2 project on VS 2013 using MSTest for tests and the non-free version of JustMock for mocking (though I don't think I'm using any of the features not present in the free version, if I recall correctly).
Remco
#2 Posted : Monday, February 24, 2014 10:14:45 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Hi, thanks for sharing this issue.

I haven't seen this particular exception before, but as you've mentioned that the 'Pre-load Assembly References' setting makes a difference, I have a broad theory about why it is happening.

When the test environment is built inside an NCrunch workspace, the files being used by the environment are loaded from multiple output directories across multiple workspaces. NCrunch controls this by hooking the AppDomain AssemblyResolve and telling the CLR where to load assemblies from. Because the CLR has many stages of implicit logic in the loading of assemblies, NCrunch relies on the fact that it won't be able to find any target assembly without the AssemblyResolve override, in which case NCrunch can exercise near full control over which assemblies are loaded.

Sometimes though, arrangements of projects can result in the CLR's implicit behaviour finding a target assembly before the AssemblyResolve method kicks in. This usually results in the 'Implicit assembly referencing detected' warning that often shows up on the Tests window. It means that the test runner loaded an assembly at runtime, but the loaded path was not the assembly NCrunch was expecting. There are many things that can do this, such as IoC containers making use of Assembly.LoadFrom, weird build steps that copy files around, customised build systems, etc. JustMock also adds an extra element here as its integration with the CLR profiler allows it to theoretically do almost anything, including manipulating core runtime code that passes through the JIT.

Therefore the correct solution here is the one that you've already found. Make sure you keep the 'Pre-load Assembly References' setting enabled, as this will make NCrunch pre-load all referenced assemblies and remove the implicit logic entirely. There are many situations that can require you to have this setting enabled, and very few of them are worth making code changes to try and alleviate. We may end up on a very long chase to try and find the source of the implicit loading only to find it is something that cannot be feasibly fixed in your environment.

Anyway, I'd like to learn a bit more about the double test execution. How have you observed this? Is it in the Tests Window or the Processing Queue? Is it still happening?


Thanks!

Remco
topeju
#3 Posted : Monday, February 24, 2014 10:25:50 PM(UTC)
Rank: Newbie

Groups: Registered
Joined: 5/12/2013(UTC)
Posts: 9
Location: Finland

Thanks: 1 times
Remco;5385 wrote:
Anyway, I'd like to learn a bit more about the double test execution. How have you observed this? Is it in the Tests Window or the Processing Queue? Is it still happening?


Yes, it's still happening. I've observed it in the Tests Window, where it shows roughly twice the actual number of tests (131 vs 71) being queued for execution, but it seems to be visible in the Processing Queue as well, as it shows first the Build Assembly lines for each project in the solution (once), then rows with:
* Run 27 tests (priority 9)
* Run 27 tests (9)
* Run 32 tests (7)
* Run 32 tests (7)
* Run 1 test (-4)
* Run 1 test (-4)
* Run 5 tests (-8)
* Run 2 tests (-12)
* Run 4 tests (-15)

At a quick glance, the first groups (27 & 27, 32 & 32, and 1 & 1) seem identical in their list of tests to execute. I don't see any duplicates in the last three groups.

(I thought earlier it was exactly twice, but I must have been mistaken or the count has changed.)
Remco
#4 Posted : Monday, February 24, 2014 10:33:52 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
It's physically possible for tests to exist in the queue multiple times, but only if at least one of the instances is already being executed. Normally the pipliner should pull out any existing matching tests within the processing queue when it tries to add new ones.

So if those first three sets of tests were already running at the time you changed your code again, then you could see this happen.

Does it happen for you if you make one single code change while no tests are already running?
topeju
#5 Posted : Tuesday, February 25, 2014 7:00:00 AM(UTC)
Rank: Newbie

Groups: Registered
Joined: 5/12/2013(UTC)
Posts: 9
Location: Finland

Thanks: 1 times
Remco;5387 wrote:
It's physically possible for tests to exist in the queue multiple times, but only if at least one of the instances is already being executed. Normally the pipliner should pull out any existing matching tests within the processing queue when it tries to add new ones.

So if those first three sets of tests were already running at the time you changed your code again, then you could see this happen.

Does it happen for you if you make one single code change while no tests are already running?


Actually, what I did was I clicked the Reset button in NCrunch. I hadn't done any changes to the code. While building (and of course after all tests have been executed), NCrunch shows it's monitoring 71 tests, and during execution, it showed 131 tests (this time; 41+41+13+6+13+6+4+4+3).

Just now, I tried adding "foo" to one variable, and the test queue went to 105 tests, though I did manage to type the entire word while NCrunch was showing "No tests are queued for execution." Then, after those tests completed, I replaced that with the letter "a", and the queue showed 71 tests, so probably it had already queued and executed some tests while I was typing "foo", and the UI was just a bit behind.

In summary, then, it looks like this behaviour only shows up when I click the Reset button in NCrunch.
Remco
#6 Posted : Tuesday, February 25, 2014 7:45:52 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Would you be able to tell me a bit more about the structure of your solution? Do you have multiple test projects? What are the normal execution times for these 71 tests?
topeju
#7 Posted : Tuesday, February 25, 2014 9:58:45 AM(UTC)
Rank: Newbie

Groups: Registered
Joined: 5/12/2013(UTC)
Posts: 9
Location: Finland

Thanks: 1 times
Remco;5389 wrote:
Would you be able to tell me a bit more about the structure of your solution? Do you have multiple test projects? What are the normal execution times for these 71 tests?


The solution has four projects in total: the web application itself, a data access project (which also includes the models), a console utility app (that isn't really being used), and one single MSTest project.

The test project references both the web application and the data access projects, though at the moment the tests only cover the data side. As I mentioned earlier, I use JustMock in some tests (8 in total, IIRC) to mock parts of the application.

I'm not at home at the moment so I cannot execute the tests on my main development machine, but they're pretty fast as they're fairly simple unit tests (and thus don't use the database etc - that's what the mocks are there for). I just ran them on my Mac laptop in a Parallels VM, and they took a total of 3.7 seconds there (half of that time was taken by a single test, no other tests were more than about 0.2 seconds each, with most of them too short to measure).
Remco
#8 Posted : Wednesday, February 26, 2014 12:37:15 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Thanks for sharing these details. I've managed to reproduce the issue and have identified its cause. Basically, there is a sequencing issue inside the engine that is causing it to double-queue some tests in certain situations.

When the Web project is built, the engine automatically queues up any tests that cover it. As soon as the tests project is built, the engine again queues up the tests. The normal mechanism to prevent duplicate queuing fails because the first batch of queued tests are already executing as soon as the test project has finished building.

You'll only notice this problem during a reset of the engine, or when changing the public surface of one of the types within the Web project (which results in a rebuild of both the web project and the test project). The effect on the engine is likely to be minimal because the tests being run/duplicated are usually likely to be the fastest in the queue and will clear very quickly.

This problem has probably existed in NCrunch for the lifetime of the product. Well done for picking up on it!


Cheers,

Remco
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

YAF | YAF © 2003-2011, Yet Another Forum.NET
This page was generated in 0.063 seconds.
Trial NCrunch
Take NCrunch for a spin
Do your fingers a favour and supercharge your testing workflow
Free Download