149 lines
4.5 KiB
C#
149 lines
4.5 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: UnitTest.cs
|
||
|
//
|
||
|
// Note:
|
||
|
//
|
||
|
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Threading;
|
||
|
|
||
|
namespace Microsoft.Singularity.UnitTest
|
||
|
{
|
||
|
public sealed class UnitTest
|
||
|
{
|
||
|
public enum Result
|
||
|
{
|
||
|
Passed = 0,
|
||
|
Failed = 1
|
||
|
}
|
||
|
|
||
|
public delegate void TestDelegate();
|
||
|
|
||
|
internal sealed class TestCommand
|
||
|
{
|
||
|
private string /*!*/ description;
|
||
|
private TestDelegate /*!*/ testDelegate;
|
||
|
|
||
|
internal TestCommand(string /*!*/ description,
|
||
|
TestDelegate /*!*/ testDelegate)
|
||
|
{
|
||
|
this.description = description;
|
||
|
this.testDelegate = testDelegate;
|
||
|
}
|
||
|
|
||
|
internal string Description { get { return description; } }
|
||
|
internal void Execute() { testDelegate(); }
|
||
|
}
|
||
|
|
||
|
private static ArrayList! tests = new ArrayList();
|
||
|
private static object classLock = new object();
|
||
|
|
||
|
private static int runThreadId;
|
||
|
private static volatile int otherThreadExceptions = 0;
|
||
|
private static volatile bool expectAssertionFailure = false;
|
||
|
|
||
|
public static void Add(string /*!*/ description,
|
||
|
TestDelegate /*!*/ test)
|
||
|
{
|
||
|
tests.Add(new TestCommand(description, test));
|
||
|
}
|
||
|
|
||
|
public static void Clear()
|
||
|
{
|
||
|
tests.Clear();
|
||
|
}
|
||
|
|
||
|
public static void ExpectNextAssertionFails()
|
||
|
{
|
||
|
lock (classLock) {
|
||
|
UnitTest.expectAssertionFailure = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void ExpectNextAssertionPasses()
|
||
|
{
|
||
|
lock (classLock) {
|
||
|
UnitTest.expectAssertionFailure = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static Result Run(bool stopOnFailure)
|
||
|
{
|
||
|
runThreadId = GetCurrentThreadId();
|
||
|
|
||
|
int failures = 0;
|
||
|
|
||
|
foreach (TestCommand! tc in tests) {
|
||
|
Result r = Result.Passed;
|
||
|
try {
|
||
|
Console.Write("Running test {0}...", tc.Description);
|
||
|
lock (classLock) {
|
||
|
UnitTest.otherThreadExceptions = 0;
|
||
|
}
|
||
|
tc.Execute();
|
||
|
lock (classLock) {
|
||
|
if (UnitTest.otherThreadExceptions == 0) {
|
||
|
Console.WriteLine("Passed.");
|
||
|
}
|
||
|
else {
|
||
|
Console.WriteLine("Failed.");
|
||
|
r = Result.Failed;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (FailedAssertionException fae) {
|
||
|
Console.WriteLine("Failed.");
|
||
|
Console.WriteLine(fae);
|
||
|
r = Result.Failed;
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
Console.WriteLine("Failed: Unexpected exception caught.");
|
||
|
Console.WriteLine(e);
|
||
|
r = Result.Failed;
|
||
|
}
|
||
|
if (r == Result.Failed) {
|
||
|
failures++;
|
||
|
if (stopOnFailure) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return (failures == 0) ? Result.Passed : Result.Failed;
|
||
|
}
|
||
|
|
||
|
private static int GetCurrentThreadId()
|
||
|
{
|
||
|
#if SINGULARITY
|
||
|
return Thread.CurrentThread.GetThreadId();
|
||
|
#else
|
||
|
return AppDomain.GetCurrentThreadId();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
internal static void Throw(FailedAssertionException /*!*/ e)
|
||
|
{
|
||
|
lock (classLock) {
|
||
|
|
||
|
if (UnitTest.expectAssertionFailure == true) {
|
||
|
UnitTest.expectAssertionFailure = false;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int threadId = GetCurrentThreadId();
|
||
|
if (threadId != runThreadId) {
|
||
|
UnitTest.otherThreadExceptions++;
|
||
|
Console.WriteLine("Tester Failure on thread {0}: {1}",
|
||
|
threadId, e);
|
||
|
}
|
||
|
}
|
||
|
throw e;
|
||
|
}
|
||
|
}
|
||
|
}
|