Skip to content

Commit 48d8f86

Browse files
committed
TableFixture: Fix test to properly handle exceptions on background thread.
Also fix indenting.
1 parent cb03ccd commit 48d8f86

File tree

4 files changed

+112
-40
lines changed

4 files changed

+112
-40
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Security.Permissions;
4+
using System.Threading;
5+
6+
namespace NHibernate.Test
7+
{
8+
/// <summary>
9+
/// Helper class to execute a method on another thread, catching all exceptions then rethrowing them
10+
/// on another thread that calls Join().
11+
/// </summary>
12+
/// TODO: Explore if this can be merged with MultiThreadRunner (probably should add exception handling to the latter).
13+
class CrossThreadTestRunner
14+
{
15+
private Exception _lastException;
16+
private readonly Thread _thread;
17+
private readonly ThreadStart _start;
18+
19+
private const string remoteStackTraceFieldName = "_remoteStackTraceString";
20+
21+
private static readonly FieldInfo RemoteStackTraceField = typeof(Exception).GetField(remoteStackTraceFieldName,
22+
BindingFlags.Instance |
23+
BindingFlags.NonPublic);
24+
25+
public CrossThreadTestRunner(ThreadStart start)
26+
{
27+
_start = start;
28+
_thread = new Thread(Run);
29+
_thread.SetApartmentState(ApartmentState.STA);
30+
}
31+
32+
public void Start()
33+
{
34+
_lastException = null;
35+
_thread.Start();
36+
}
37+
38+
public void Join()
39+
{
40+
_thread.Join();
41+
42+
if (_lastException != null)
43+
{
44+
ThrowExceptionPreservingStack(_lastException);
45+
}
46+
}
47+
48+
private void Run()
49+
{
50+
try
51+
{
52+
_start.Invoke();
53+
}
54+
catch (Exception e)
55+
{
56+
_lastException = e;
57+
}
58+
}
59+
60+
[ReflectionPermission(SecurityAction.Demand)]
61+
private static void ThrowExceptionPreservingStack(Exception exception)
62+
{
63+
if (RemoteStackTraceField != null)
64+
{
65+
RemoteStackTraceField.SetValue(exception, exception.StackTrace + Environment.NewLine);
66+
}
67+
throw exception;
68+
}
69+
}
70+
}

src/NHibernate.Test/MappingTest/TableFixture.cs

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -62,43 +62,44 @@ public void SchemaNameQuoted()
6262
Assert.AreEqual("[schema].name", tbl.GetQualifiedName(dialect));
6363
}
6464

65-
[Test]
66-
public void TablesUniquelyNamed()
67-
{
68-
Table tbl1 = new Table();
69-
Table tbl2 = new Table();
70-
71-
Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
72-
}
73-
74-
[Test]
75-
public void TablesUniquelyNamedOnlyWithinThread()
76-
{
77-
var uniqueIntegerList = new System.Collections.Concurrent.ConcurrentBag<int>();
78-
var method = new ThreadStart(() =>
79-
{
80-
Table tbl1 = new Table();
81-
Table tbl2 = new Table();
82-
83-
// Store these values for later comparison
84-
uniqueIntegerList.Add(tbl1.UniqueInteger);
85-
uniqueIntegerList.Add(tbl2.UniqueInteger);
86-
87-
// Ensure that within a thread we have unique integers
88-
Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
89-
});
90-
91-
var thread1 = new Thread(method);
92-
var thread2 = new Thread(method);
93-
94-
thread1.Start();
95-
thread2.Start();
96-
97-
thread1.Join();
98-
thread2.Join();
99-
100-
Assert.AreEqual(4, uniqueIntegerList.Count);
101-
Assert.AreEqual(2, uniqueIntegerList.Distinct().Count());
102-
}
103-
}
65+
[Test]
66+
public void TablesUniquelyNamed()
67+
{
68+
Table tbl1 = new Table();
69+
Table tbl2 = new Table();
70+
71+
Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
72+
}
73+
74+
[Test]
75+
public void TablesUniquelyNamedOnlyWithinThread()
76+
{
77+
var uniqueIntegerList = new System.Collections.Concurrent.ConcurrentBag<int>();
78+
var method = new ThreadStart(() =>
79+
{
80+
Table tbl1 = new Table();
81+
Table tbl2 = new Table();
82+
83+
// Store these values for later comparison
84+
uniqueIntegerList.Add(tbl1.UniqueInteger);
85+
uniqueIntegerList.Add(tbl2.UniqueInteger);
86+
87+
// Ensure that within a thread we have unique integers
88+
Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
89+
});
90+
91+
var thread1 = new CrossThreadTestRunner(method);
92+
var thread2 = new CrossThreadTestRunner(method);
93+
94+
thread1.Start();
95+
thread2.Start();
96+
97+
thread1.Join();
98+
thread2.Join();
99+
100+
// There should in total be 4 tables, but only two distinct identifiers.
101+
Assert.AreEqual(4, uniqueIntegerList.Count);
102+
Assert.AreEqual(2, uniqueIntegerList.Distinct().Count());
103+
}
104+
}
104105
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@
214214
<Compile Include="Criteria\MaterialResource.cs" />
215215
<Compile Include="Criteria\ProjectionsTest.cs" />
216216
<Compile Include="Criteria\Reptile.cs" />
217+
<Compile Include="CrossThreadTestRunner.cs" />
217218
<Compile Include="DialectTest\FunctionTests\SubstringSupportFixture.cs" />
218219
<Compile Include="DialectTest\FunctionTests\SequenceSupportFixture.cs" />
219220
<Compile Include="DialectTest\Ingres9DialectFixture.cs" />

src/NHibernate/Mapping/Table.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public enum SchemaAction
2525
[Serializable]
2626
public class Table : IRelationalModel
2727
{
28-
[ThreadStatic]
28+
[ThreadStatic]
2929
private static int tableCounter;
3030

3131
private readonly List<string> checkConstraints = new List<string>();

0 commit comments

Comments
 (0)