-
-
Notifications
You must be signed in to change notification settings - Fork 832
/
DisposalTests.cs
163 lines (132 loc) · 5.68 KB
/
DisposalTests.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using System;
using System.Collections.Generic;
using Autofac.Specification.Test.Util;
using Xunit;
namespace Autofac.Specification.Test.Lifetime
{
public class DisposalTests
{
[Fact]
public void ComponentsAreDisposedEvenIfCurrentScopeEndingThrowsException()
{
var rootScope = new ContainerBuilder().Build();
var nestedScope = rootScope.BeginLifetimeScope(cb => cb.RegisterType<DisposeTracker>().SingleInstance());
nestedScope.CurrentScopeEnding += (sender, args) => throw new DivideByZeroException();
var dt = nestedScope.Resolve<DisposeTracker>();
try
{
nestedScope.Dispose();
}
catch (DivideByZeroException)
{
}
Assert.True(dt.IsDisposed);
}
[Fact]
public void ComponentsResolvedFromContainer_DisposedInReverseDependencyOrder()
{
var builder = new ContainerBuilder();
builder.RegisterType<A>().SingleInstance();
builder.RegisterType<B>().SingleInstance();
var container = builder.Build();
var a = container.Resolve<A>();
var b = container.Resolve<B>();
var disposeOrder = new Queue<object>();
a.Disposing += (s, e) => disposeOrder.Enqueue(a);
b.Disposing += (s, e) => disposeOrder.Enqueue(b);
container.Dispose();
// B1 depends on A1, therefore B1 should be disposed first
Assert.Equal(2, disposeOrder.Count);
Assert.Same(b, disposeOrder.Dequeue());
Assert.Same(a, disposeOrder.Dequeue());
}
[Fact]
public void ComponentsResolvedFromContainerInReverseOrder_DisposedInReverseDependencyOrder()
{
var builder = new ContainerBuilder();
builder.RegisterType<A>().SingleInstance();
builder.RegisterType<B>().SingleInstance();
var container = builder.Build();
var b = container.Resolve<B>();
var a = container.Resolve<A>();
var disposeOrder = new Queue<object>();
a.Disposing += (s, e) => disposeOrder.Enqueue(a);
b.Disposing += (s, e) => disposeOrder.Enqueue(b);
container.Dispose();
// B1 depends on A1, therefore B1 should be disposed first
Assert.Equal(2, disposeOrder.Count);
Assert.Same(b, disposeOrder.Dequeue());
Assert.Same(a, disposeOrder.Dequeue());
}
[Fact]
public void InstancesRegisteredInParentScope_ButResolvedInChild_AreDisposedWithChild()
{
var builder = new ContainerBuilder();
builder.RegisterType<DisposeTracker>();
var parent = builder.Build();
var child = parent.BeginLifetimeScope(b => { });
var dt = child.Resolve<DisposeTracker>();
child.Dispose();
Assert.True(dt.IsDisposed);
}
[Fact]
public void ResolvingFromAnEndedLifetimeProducesObjectDisposedException()
{
var builder = new ContainerBuilder();
builder.RegisterType<object>();
var container = builder.Build();
var lifetime = container.BeginLifetimeScope();
lifetime.Dispose();
Assert.Throws<ObjectDisposedException>(() => lifetime.Resolve<object>());
}
// Issue #960
[Fact]
public void TwoLayersOfExternalRegistration_OnDisposingInnerLayer_OuterLayerRemains()
{
var builder = new ContainerBuilder();
builder.RegisterType<DisposeTracker>().InstancePerLifetimeScope();
// Root has the main registration.
var root = builder.Build();
var rootInstance = root.Resolve<DisposeTracker>();
// Middle has ExternalRegistration pointing upwards.
var middle = root.BeginLifetimeScope(cb => cb.Register(_ => new object()));
var middleInstance = middle.Resolve<DisposeTracker>();
// Child has ExternalRegistration pointing upwards.
var child = middle.BeginLifetimeScope(cb => cb.Register(_ => new object()));
var childInstance = child.Resolve<DisposeTracker>();
Assert.NotSame(rootInstance, middleInstance);
Assert.NotSame(middleInstance, childInstance);
Assert.NotSame(rootInstance, childInstance);
// This should only dispose the registration in child, not the one in middle or root.
child.Dispose();
Assert.True(childInstance.IsDisposed);
Assert.False(middleInstance.IsDisposed);
Assert.False(rootInstance.IsDisposed);
// We check by trying to use the registration in middle.
// If too much got disposed, this will throw ObjectDisposedException.
Assert.Same(middleInstance, middle.Resolve<DisposeTracker>());
Assert.Same(rootInstance, root.Resolve<DisposeTracker>());
// Middle and child should now be disposed.
middle.Dispose();
Assert.True(childInstance.IsDisposed);
Assert.True(middleInstance.IsDisposed);
Assert.False(rootInstance.IsDisposed);
// Now all should be disposed.
root.Dispose();
Assert.True(childInstance.IsDisposed);
Assert.True(middleInstance.IsDisposed);
Assert.True(rootInstance.IsDisposed);
}
private class A : DisposeTracker
{
}
private class B : DisposeTracker
{
public B(A a)
{
this.A = a;
}
public A A { get; private set; }
}
}
}