summaryrefslogtreecommitdiff
path: root/odcsim-core/src/test
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2019-04-24 15:24:34 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2019-05-13 20:26:46 +0200
commit7e87f2964595ee3cfab84db84c3c7efb66a89d15 (patch)
tree5b1b5cd7afe321784c34e0032b2f0d9f40349f48 /odcsim-core/src/test
parentf0a8f3906d6f4d94900117b4d9f0bd9e58f33e10 (diff)
refactor: Require ActorContext for sending messages
This change makes it mandatory to send messages to an actor via the sender's ActorContext in order for the engine to maintain consistency in time between actors.
Diffstat (limited to 'odcsim-core/src/test')
-rw-r--r--odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemFactoryTest.kt6
-rw-r--r--odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemTest.kt115
-rw-r--r--odcsim-core/src/test/kotlin/com/atlarge/odcsim/BehaviorTest.kt15
-rw-r--r--odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt50
4 files changed, 112 insertions, 74 deletions
diff --git a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemFactoryTest.kt b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemFactoryTest.kt
index 3830f09e..11652606 100644
--- a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemFactoryTest.kt
+++ b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemFactoryTest.kt
@@ -24,8 +24,6 @@
package com.atlarge.odcsim
-import com.atlarge.odcsim.dsl.empty
-import com.atlarge.odcsim.dsl.setup
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
@@ -46,7 +44,7 @@ abstract class ActorSystemFactoryTest {
fun `should create a system with correct name`() {
val factory = createFactory()
val name = "test"
- val system = factory(Behavior.empty<Unit>(), name)
+ val system = factory(empty<Unit>(), name)
assertEquals(name, system.name)
}
@@ -57,7 +55,7 @@ abstract class ActorSystemFactoryTest {
@Test
fun `should create a system with correct root behavior`() {
val factory = createFactory()
- val system = factory(Behavior.setup<Unit> { throw UnsupportedOperationException() }, "test")
+ val system = factory(setup<Unit> { throw UnsupportedOperationException() }, "test")
assertThrows<UnsupportedOperationException> { system.run(until = 10.0) }
}
diff --git a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemTest.kt b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemTest.kt
index 3385767b..e9cc3886 100644
--- a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemTest.kt
+++ b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/ActorSystemTest.kt
@@ -24,12 +24,6 @@
package com.atlarge.odcsim
-import com.atlarge.odcsim.Behavior.Companion.same
-import com.atlarge.odcsim.dsl.empty
-import com.atlarge.odcsim.dsl.ignore
-import com.atlarge.odcsim.dsl.receive
-import com.atlarge.odcsim.dsl.receiveMessage
-import com.atlarge.odcsim.dsl.setup
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
@@ -55,7 +49,7 @@ abstract class ActorSystemTest {
@Test
fun `should have a name`() {
val name = "test"
- val system = factory(Behavior.empty<Unit>(), name)
+ val system = factory(empty<Unit>(), name)
assertEquals(name, system.name)
}
@@ -65,7 +59,7 @@ abstract class ActorSystemTest {
*/
@Test
fun `should have a path`() {
- val system = factory(Behavior.empty<Unit>(), "test")
+ val system = factory(empty<Unit>(), "test")
assertTrue(system.path is ActorPath.Root)
}
@@ -75,7 +69,7 @@ abstract class ActorSystemTest {
*/
@Test
fun `should start at t=0`() {
- val system = factory(Behavior.empty<Unit>(), name = "test")
+ val system = factory(empty<Unit>(), name = "test")
assertTrue(Math.abs(system.time) < DELTA)
}
@@ -85,7 +79,7 @@ abstract class ActorSystemTest {
*/
@Test
fun `should not accept negative instants for running`() {
- val system = factory(Behavior.empty<Unit>(), name = "test")
+ val system = factory(empty<Unit>(), name = "test")
assertThrows<IllegalArgumentException> { system.run(-10.0) }
}
@@ -96,7 +90,7 @@ abstract class ActorSystemTest {
@Test
fun `should not jump backward in time`() {
val until = 10.0
- val system = factory(Behavior.empty<Unit>(), name = "test")
+ val system = factory(empty<Unit>(), name = "test")
system.run(until = until)
system.run(until = until - 0.5)
@@ -109,7 +103,7 @@ abstract class ActorSystemTest {
@Test
fun `should jump forward in time`() {
val until = 10.0
- val system = factory(Behavior.empty<Unit>(), name = "test")
+ val system = factory(empty<Unit>(), name = "test")
system.run(until = until)
assertTrue(Math.abs(system.time - until) < DELTA)
@@ -120,12 +114,11 @@ abstract class ActorSystemTest {
*/
@Test
fun `should order messages at the instant by insertion time`() {
- val behavior = Behavior.receiveMessage<Int> { msg ->
+ val behavior = receiveMessage<Int> { msg ->
assertEquals(1, msg)
-
- Behavior.receiveMessage {
+ receiveMessage {
assertEquals(2, it)
- Behavior.ignore()
+ ignore()
}
}
val system = factory(behavior, name = "test")
@@ -140,7 +133,7 @@ abstract class ActorSystemTest {
@Test
fun `should not process messages after deadline`() {
var counter = 0
- val behavior = Behavior.receiveMessage<Unit> { _ ->
+ val behavior = receiveMessage<Unit> { _ ->
counter++
same()
}
@@ -156,7 +149,7 @@ abstract class ActorSystemTest {
*/
@Test
fun `should not initialize root actor if not run`() {
- factory(Behavior.setup<Unit> { TODO() }, name = "test")
+ factory(setup<Unit> { TODO() }, name = "test")
}
@Nested
@@ -167,7 +160,7 @@ abstract class ActorSystemTest {
*/
@Test
fun `should disallow messages in the past`() {
- val system = factory(Behavior.empty<Unit>(), name = "test")
+ val system = factory(empty<Unit>(), name = "test")
assertThrows<IllegalArgumentException> { system.send(Unit, after = -1.0) }
}
}
@@ -180,9 +173,9 @@ abstract class ActorSystemTest {
*/
@Test
fun `should pre-start at t=0 if root`() {
- val behavior = Behavior.setup<Unit> { ctx ->
+ val behavior = setup<Unit> { ctx ->
assertTrue(Math.abs(ctx.time) < DELTA)
- Behavior.ignore()
+ ignore()
}
val system = factory(behavior, "test")
@@ -195,12 +188,12 @@ abstract class ActorSystemTest {
@Test
fun `should allow spawning of child actors`() {
var spawned = false
- val behavior = Behavior.setup<Unit> { spawned = true; Behavior.empty() }
+ val behavior = setup<Unit> { spawned = true; empty() }
- val system = factory(Behavior.setup<Unit> { ctx ->
+ val system = factory(setup<Unit> { ctx ->
val ref = ctx.spawn(behavior, "child")
assertEquals("child", ref.path.name)
- Behavior.ignore()
+ ignore()
}, name = "test")
system.run(until = 10.0)
@@ -212,12 +205,12 @@ abstract class ActorSystemTest {
*/
@Test
fun `should allow stopping of child actors`() {
- val system = factory(Behavior.setup<Unit> { ctx ->
- val ref = ctx.spawn(Behavior.receiveMessage<Unit> { throw UnsupportedOperationException() }, "child")
+ val system = factory(setup<Unit> { ctx ->
+ val ref = ctx.spawn(receiveMessage<Unit> { throw UnsupportedOperationException() }, "child")
assertTrue(ctx.stop(ref))
assertEquals("child", ref.path.name)
- Behavior.ignore()
+ ignore()
}, name = "test")
system.run(until = 10.0)
@@ -228,15 +221,14 @@ abstract class ActorSystemTest {
*/
@Test
fun `should only be able to terminate child actors`() {
- val system = factory(Behavior.setup<Unit> { ctx ->
- val child1 = ctx.spawn(Behavior.ignore<Unit>(), "child-1")
-
- ctx.spawn(Behavior.setup<Unit> {
- assertFalse(it.stop(child1))
- Behavior.ignore()
+ val system = factory(setup<Unit> { ctx1 ->
+ val child1 = ctx1.spawn(ignore<Unit>(), "child-1")
+ ctx1.spawn(setup<Unit> { ctx2 ->
+ assertFalse(ctx2.stop(child1))
+ ignore()
}, "child-2")
- Behavior.ignore()
+ ignore()
}, name = "test")
system.run()
}
@@ -246,11 +238,11 @@ abstract class ActorSystemTest {
*/
@Test
fun `should not be able to stop an already terminated child`() {
- val system = factory(Behavior.setup<Unit> { ctx ->
- val child = ctx.spawn(Behavior.ignore<Unit>(), "child")
+ val system = factory(setup<Unit> { ctx ->
+ val child = ctx.spawn(ignore<Unit>(), "child")
ctx.stop(child)
assertFalse(ctx.stop(child))
- Behavior.ignore()
+ ignore()
}, name = "test")
system.run()
}
@@ -260,20 +252,20 @@ abstract class ActorSystemTest {
*/
@Test
fun `should terminate children of child when terminating it`() {
- val system = factory(Behavior.setup<ActorRef<Unit>> { ctx1 ->
- val root = ctx1.self
- val child = ctx1.spawn(Behavior.setup<Unit> {
- val child = ctx1.spawn(Behavior.receiveMessage<Unit> {
+ val system = factory(setup<ActorRef<Unit>> { ctx ->
+ val root = ctx.self
+ val child = ctx.spawn(setup<Unit> {
+ val child = ctx.spawn(receiveMessage<Unit> {
throw IllegalStateException("DELIBERATE")
}, "child")
- root.send(child)
- Behavior.ignore()
+ ctx.send(root, child)
+ ignore()
}, "child")
- Behavior.receive { ctx2, msg ->
- assertTrue(ctx2.stop(child))
- msg.send(Unit) // This actor should be stopped now and not receive the message anymore
- Behavior.stopped()
+ receiveMessage { msg ->
+ assertTrue(ctx.stop(child))
+ ctx.send(msg, Unit) // This actor should be stopped now and not receive the message anymore
+ stopped()
}
}, name = "test")
@@ -281,19 +273,18 @@ abstract class ActorSystemTest {
}
/**
- * Test whether [Behavior.Companion.same] works correctly.
+ * Test whether [same] works correctly.
*/
@Test
fun `should keep same behavior on same`() {
var counter = 0
- val behavior = Behavior.setup<Unit> { ctx ->
- counter++
- ctx.self.send(Unit)
-
- Behavior.receiveMessage {
+ val behavior = setup<Unit> { ctx ->
+ counter++
+ ctx.send(ctx.self, Unit)
+ receiveMessage {
counter++
- Behavior.same()
+ same()
}
}
@@ -308,9 +299,9 @@ abstract class ActorSystemTest {
@Test
fun `should have reference to itself`() {
var flag = false
- val behavior: Behavior<Unit> = Behavior.setup { ctx ->
- ctx.self.send(Unit)
- Behavior.receiveMessage { flag = true; same() }
+ val behavior: Behavior<Unit> = setup { ctx ->
+ ctx.send(ctx.self, Unit)
+ receiveMessage { flag = true; same() }
}
val system = factory(behavior, "test")
@@ -319,20 +310,20 @@ abstract class ActorSystemTest {
}
/**
- * Test whether we cannot start an actor with the [Behavior.Companion.same] behavior.
+ * Test whether we cannot start an actor with the [same] behavior.
*/
@Test
fun `should not start with same behavior`() {
- val system = factory(Behavior.same<Unit>(), "test")
+ val system = factory(same<Unit>(), "test")
assertThrows<IllegalArgumentException> { system.run() }
}
/**
- * Test whether we can start an actor with the [Behavior.Companion.stopped] behavior.
+ * Test whether we can start an actor with the [stopped] behavior.
*/
@Test
fun `should start with stopped behavior`() {
- val system = factory(Behavior.stopped<Unit>(), "test")
+ val system = factory(stopped<Unit>(), "test")
system.run()
}
@@ -343,7 +334,7 @@ abstract class ActorSystemTest {
@Test
fun `should stop if it crashes`() {
var counter = 0
- val system = factory(Behavior.receiveMessage<Unit> {
+ val system = factory(receiveMessage<Unit> {
counter++
throw IllegalArgumentException("STAGED")
}, "test")
diff --git a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/BehaviorTest.kt b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/BehaviorTest.kt
index 6f97e428..1eb4f3b9 100644
--- a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/BehaviorTest.kt
+++ b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/BehaviorTest.kt
@@ -24,7 +24,6 @@
package com.atlarge.odcsim
-import com.atlarge.odcsim.dsl.setup
import com.atlarge.odcsim.internal.BehaviorInterpreter
import com.nhaarman.mockitokotlin2.mock
import org.junit.jupiter.api.DisplayName
@@ -37,12 +36,12 @@ import org.junit.jupiter.api.assertThrows
@DisplayName("Behavior")
class BehaviorTest {
/**
- * Test whether we cannot start an actor with the [Behavior.Companion.unhandled] behavior.
+ * Test whether we cannot start an actor with the [unhandled] behavior.
*/
@Test
fun `should not start with unhandled behavior`() {
val ctx = mock<ActorContext<Unit>>()
- val interpreter = BehaviorInterpreter(Behavior.unhandled<Unit>())
+ val interpreter = BehaviorInterpreter(unhandled<Unit>())
assertThrows<IllegalArgumentException> { interpreter.start(ctx) }
}
@@ -52,27 +51,27 @@ class BehaviorTest {
@Test
fun `should not start with deferred unhandled behavior`() {
val ctx = mock<ActorContext<Unit>>()
- val interpreter = BehaviorInterpreter(Behavior.setup<Unit> { Behavior.unhandled() })
+ val interpreter = BehaviorInterpreter(setup<Unit> { unhandled() })
assertThrows<IllegalArgumentException> { interpreter.start(ctx) }
}
/**
- * Test whether deferred behavior that returns [Behavior.Companion.same] fails.
+ * Test whether deferred behavior that returns [same] fails.
*/
@Test
fun `should not allow setup to return same`() {
val ctx = mock<ActorContext<Unit>>()
- val interpreter = BehaviorInterpreter(Behavior.setup<Unit> { Behavior.same() })
+ val interpreter = BehaviorInterpreter(setup<Unit> { same() })
assertThrows<IllegalArgumentException> { interpreter.start(ctx) }
}
/**
- * Test whether deferred behavior that returns [Behavior.Companion.unhandled] fails.
+ * Test whether deferred behavior that returns [unhandled] fails.
*/
@Test
fun `should not allow setup to return unhandled`() {
val ctx = mock<ActorContext<Unit>>()
- val interpreter = BehaviorInterpreter(Behavior.setup<Unit> { Behavior.unhandled() })
+ val interpreter = BehaviorInterpreter(setup<Unit> { unhandled() })
assertThrows<IllegalArgumentException> { interpreter.start(ctx) }
}
}
diff --git a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt
new file mode 100644
index 00000000..d6bf6a74
--- /dev/null
+++ b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt
@@ -0,0 +1,50 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.odcsim
+
+import com.atlarge.odcsim.coroutines.suspending
+import com.atlarge.odcsim.coroutines.SuspendingBehavior
+import com.atlarge.odcsim.internal.BehaviorInterpreter
+import com.atlarge.odcsim.internal.EmptyBehavior
+import com.nhaarman.mockitokotlin2.mock
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.DisplayName
+import org.junit.jupiter.api.Test
+
+/**
+ * Test suite for [SuspendingBehavior] using Kotlin Coroutines.
+ */
+@DisplayName("Coroutines")
+internal class CoroutinesTest {
+ private val ctx = mock<ActorContext<Nothing>>()
+
+ @Test
+ fun `should immediately return new behavior`() {
+ val behavior = suspending<Nothing> { empty() }
+ val interpreter = BehaviorInterpreter(behavior)
+ interpreter.start(ctx)
+ assertTrue(interpreter.behavior as Behavior<*> is EmptyBehavior)
+ }
+}