Reputation: 1182
I have some old code that I'm trying to writes tests for. the code parses a log file (on a background thread) and when finished fires off a passed in delegate.
i.e.
public delegate void finread(LogData l, LRParseState l, string e="");
void Thread_ParseLog(object info) {
var info = ti as ThreadInfo;
// some time later
info.fin(log, state, error);
}
public static void ParseErrorLog(string log, finread fin){
var pts = new ParameterizedThreadStart(Thread_ParseLog);
new Thread(pts).Start(new ThreadInfo(log, fin));
}
The code is production code and every thing works ok and has done for a long time, but when I try and test it I get the "Thread was being aborted." exception raised in the Thread_ParseLog method.
The test looks like this:
void llt(string name, Action<LogData, LRParseState> test) {
finread d = (LogData l, LRParseState s, string e) => {
test(l, s);
};
LogReader.ParseErrorLog(name, d);
}
[TestMethod]
public void Create_LogReader_Big_Log() {
llt(ERROR_LOG, (log, state) => {
Assert.IsTrue(log != null); // never get here!
});
}
The test data is largeish, about 55mb, which takes about 500ms to process normally.
I'm also getting errors in the output window:
Exception thrown: 'System.Threading.ThreadAbortException' in mscorlib.dll System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain. This can happen if the test(s) started a thread but did not stop it. Make sure that all the threads started by the test(s) are stopped before completion.
Which seem to point at some kind of thread sync problems, but there's nothing i can do about the code i'm testing.
It's, obviously, the way I've written my test and I can fix it by changing my test but I'm not sure why its happening.
TIA.
Upvotes: 5
Views: 2830
Reputation: 214
Use an async test method and give it a small delay to run.
[TestMethod]
public async Task Create_LogReader_Big_Log()
{
llt(ERROR_LOG, (log, state) => {
Assert.IsTrue(log != null); // never get here!
});
await Task.Delay(3000);
}
Upvotes: 2
Reputation: 28499
Use synchronization mechanisms like for example a ManualResetEvent
to wait for the asynchronous parts of the test to finish before leaving the test method.
[TestMethod]
public void Create_LogReader_Big_Log() {
// Use this event to wait until the asynchronous code has been executed
// before leaving the test method
ManualResetEvent resetEvent = new ManualResetEvent(false);
LogData logDataReceived = null;
llt(ERROR_LOG, (log, state) => {
logDataReceived = log;
// Signal that the test has reached the end
resetEvent.Set();
});
// Wait for the event to be set
resetEvent.WaitOne();
// Additionally wait for a grace period to allow the other thread to fully terminate
Thread.Sleep(500);
// Now perform the asserts on the received data
Assert.IsTrue(logDataReceived != null);
}
Upvotes: 7