/
TypedActorLifecycleSpec.scala
151 lines (133 loc) · 5.23 KB
/
TypedActorLifecycleSpec.scala
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
package akka.actor
import org.junit.runner.RunWith
import org.scalatest.{BeforeAndAfterAll, Spec}
import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.ShouldMatchers
import akka.actor.TypedActor._
import akka.config.Supervision._
import java.util.concurrent.CountDownLatch
import akka.config.TypedActorConfigurator
import akka.Testing
/**
* @author Martin Krasser
*/
@RunWith(classOf[JUnitRunner])
class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAfterAll {
var conf1: TypedActorConfigurator = _
var conf2: TypedActorConfigurator = _
override protected def beforeAll() = {
val strategy = AllForOneStrategy(classOf[Exception] :: Nil, 3, 1000)
val comp3 = new SuperviseTypedActor(classOf[SamplePojo], classOf[SamplePojoImpl], permanent(), 1000)
val comp4 = new SuperviseTypedActor(classOf[SamplePojo], classOf[SamplePojoImpl], temporary(), 1000)
conf1 = new TypedActorConfigurator().configure(strategy, Array(comp3)).supervise
conf2 = new TypedActorConfigurator().configure(strategy, Array(comp4)).supervise
}
override protected def afterAll() = {
conf1.stop
conf2.stop
}
describe("TypedActor lifecycle management") {
it("should restart supervised, non-annotated typed actor on failure") {
SamplePojoImpl.reset
val obj = conf1.getInstance[SamplePojo](classOf[SamplePojo])
val cdl = new CountDownLatch(2)
SamplePojoImpl.latch = cdl
assert(AspectInitRegistry.initFor(obj) ne null)
try {
obj.fail
fail("expected exception not thrown")
} catch {
case e: RuntimeException => {
cdl.await
assert(SamplePojoImpl._pre)
assert(SamplePojoImpl._post)
assert(!SamplePojoImpl._down)
// assert(AspectInitRegistry.initFor(obj) ne null)
}
}
}
it("should shutdown supervised, non-annotated typed actor on failure") {
SamplePojoImpl.reset
val obj = conf2.getInstance[SamplePojo](classOf[SamplePojo])
val cdl = new CountDownLatch(1)
SamplePojoImpl.latch = cdl
assert(AspectInitRegistry.initFor(obj) ne null)
try {
obj.fail
fail("expected exception not thrown")
} catch {
case e: RuntimeException => {
cdl.await
assert(!SamplePojoImpl._pre)
assert(!SamplePojoImpl._post)
assert(SamplePojoImpl._down)
// assert(AspectInitRegistry.initFor(obj) eq null)
}
}
}
it("should shutdown non-supervised, non-initialized typed actor on TypedActor.stop") {
SamplePojoImpl.reset
val obj = TypedActor.newInstance(classOf[SamplePojo], classOf[SamplePojoImpl])
TypedActor.stop(obj)
assert(!SamplePojoImpl._pre)
assert(!SamplePojoImpl._post)
assert(SamplePojoImpl._down)
}
it("both preRestart and postRestart methods should be invoked when an actor is restarted") {
SamplePojoImpl.reset
val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl])
val supervisor = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl])
link(supervisor, pojo, OneForOneStrategy(classOf[Throwable] :: Nil, 3, 2000))
pojo.throwException
Thread.sleep(500)
SimpleJavaPojoImpl._pre should be(true)
SimpleJavaPojoImpl._post should be(true)
}
it("should be stopped when supervision cannot handle the problem in") {
val actorSupervision = new SuperviseTypedActor(classOf[TypedActorFailer],classOf[TypedActorFailerImpl],permanent(), Testing.time(30000))
val conf = new TypedActorConfigurator().configure(OneForOneStrategy(Nil, 3, 500000), Array(actorSupervision)).inject.supervise
try {
val first = conf.getInstance(classOf[TypedActorFailer])
try {
first.fail
fail("shouldn't get here")
} catch {
case r: RuntimeException if r.getMessage == "expected" => //expected
}
val second = conf.getInstance(classOf[TypedActorFailer])
first should be (second)
try {
second.fail
fail("shouldn't get here")
} catch {
case r: ActorInitializationException if r.getMessage == "Actor has not been started, you need to invoke 'actor.start' before using it" => //expected
}
} finally {
conf.stop
}
}
it("should be restarted when supervision handles the problem in") {
val actorSupervision = new SuperviseTypedActor(classOf[TypedActorFailer],classOf[TypedActorFailerImpl],permanent(), Testing.time(30000))
val conf = new TypedActorConfigurator().configure(OneForOneStrategy(classOf[Throwable] :: Nil, 3, 500000), Array(actorSupervision)).inject.supervise
try {
val first = conf.getInstance(classOf[TypedActorFailer])
try {
first.fail
fail("shouldn't get here")
} catch {
case r: RuntimeException if r.getMessage == "expected" => //expected
}
val second = conf.getInstance(classOf[TypedActorFailer])
first should be (second)
try {
second.fail
fail("shouldn't get here")
} catch {
case r: RuntimeException if r.getMessage == "expected" => //expected
}
} finally {
conf.stop
}
}
}
}