diff options
Diffstat (limited to 'odcsim-testkit/src/main/kotlin')
6 files changed, 0 insertions, 597 deletions
diff --git a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/BehaviorTestKit.kt b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/BehaviorTestKit.kt deleted file mode 100644 index 65782d52..00000000 --- a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/BehaviorTestKit.kt +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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.testkit - -import com.atlarge.odcsim.ActorContext -import com.atlarge.odcsim.ActorPath -import com.atlarge.odcsim.ActorRef -import com.atlarge.odcsim.Behavior -import com.atlarge.odcsim.Instant -import com.atlarge.odcsim.isAlive -import com.atlarge.odcsim.testkit.internal.BehaviorTestKitImpl -import java.util.UUID - -/** - * Utensils for synchronous testing of [Behavior] instances. - * - * @param T The shape of the messages the behavior accepts. - */ -interface BehaviorTestKit<T : Any> { - /** - * The current point in simulation time. - */ - val time: Instant - - /** - * The current behavior of the simulated actor. - */ - val behavior: Behavior<T> - - /** - * The self reference to the simulated actor inside the test kit. - */ - val ref: ActorRef<T> - - /** - * The context of the simulated actor. - */ - val context: ActorContext<T> - - /** - * The inbox of the simulated actor. - */ - val inbox: TestInbox<T> - - /** - * A flag indicating whether the [Behavior] instance is still alive. - */ - val isAlive: Boolean get() = behavior.isAlive - - /** - * Interpret the specified message at the current point in simulation time using the current behavior. - * - * @return `true` if the message was handled by the behavior, `false` if it was unhandled. - */ - fun run(msg: T): Boolean - - /** - * Interpret the oldest message in the inbox using the current behavior. - * - * @return `true` if the message was handled by the behavior, `false` if it was unhandled. - * @throws NoSuchElementException if the actor's inbox is empty. - */ - fun runOne(): Boolean - - /** - * Interpret the messages in the inbox until the specified point in simulation time is reached. - * - * @param time The time until which the messages in the inbox should be processed. - */ - fun runTo(time: Instant) - - /** - * Create an anonymous [TestInbox] for receiving messages. - */ - fun <U : Any> createInbox(): TestInbox<U> - - /** - * Get the child inbox for the child with the given name, or fail if there is no child with the given name - * spawned - */ - fun <U : Any> childInbox(name: String): TestInbox<U> - - /** - * Get the child inbox for the child referenced by [ref], or fail if it is not a child of this behavior. - */ - fun <U : Any> childInbox(ref: ActorRef<U>): TestInbox<U> - - /** - * Obtain the [BehaviorTestKit] for the child with the given name, or fail if there is no child with the given - * name spawned. - */ - fun <U : Any> childTestKit(name: String): BehaviorTestKit<U> - - /** - * Obtain the [BehaviorTestKit] for the given child [ActorRef]. - */ - fun <U : Any> childTestKit(ref: ActorRef<U>): BehaviorTestKit<U> - - companion object { - /** - * Create a [BehaviorTestKit] instance for the specified [Behavior]. - * - * @param behavior The behavior for which a test kit should be created. - */ - operator fun <T : Any> invoke(behavior: Behavior<T>): BehaviorTestKit<T> = - BehaviorTestKitImpl(behavior, ActorPath.Root(name = "/" + UUID.randomUUID().toString())) - - /** - * Create a [BehaviorTestKit] instance for the specified [Behavior]. - * - * @param behavior The behavior for which a test kit should be created. - */ - @JvmStatic - fun <T : Any> create(behavior: Behavior<T>): BehaviorTestKit<T> = invoke(behavior) - } -} diff --git a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/TestInbox.kt b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/TestInbox.kt deleted file mode 100644 index de240143..00000000 --- a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/TestInbox.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.testkit - -import com.atlarge.odcsim.ActorRef -import com.atlarge.odcsim.Envelope - -/** - * A helper class for testing messages sent to an [ActorRef]. - * - * @param T The shape of the messages the inbox accepts. - */ -interface TestInbox<T : Any> { - /** - * The actor reference of this inbox. - */ - val ref: ActorRef<T> - - /** - * A flag to indicate whether the inbox contains any messages. - */ - val hasMessages: Boolean - - /** - * Receive the oldest message from the inbox and remove it. - * - * @return The message that has been received. - * @throws NoSuchElementException if the inbox is empty. - */ - fun receiveMessage(): T = receiveEnvelope().message - - /** - * Receive the oldest message from the inbox and remove it. - * - * @return The envelope containing the message that has been received. - * @throws NoSuchElementException if the inbox is empty. - */ - fun receiveEnvelope(): Envelope<T> - - /** - * Receive all messages from the inbox and empty it. - * - * @return The list of messages in the inbox. - */ - fun receiveAll(): List<Envelope<T>> - - /** - * Clear all messages from the inbox. - */ - fun clear() - - /** - * Assert that the oldest message is equal to the [expected] message and remove - * it from the inbox. - * - * @param expected The expected message to be the oldest in the inbox. - */ - fun expectMessage(expected: T) - - /** - * Assert that the oldest message is equal to the [expected] message and remove - * it from the inbox. - * - * @param expected The expected message to be the oldest in the inbox. - * @param message The failure message to fail with. - */ - fun expectMessage(expected: T, message: String) -} diff --git a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt deleted file mode 100644 index 79873141..00000000 --- a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.testkit.internal - -import com.atlarge.odcsim.ActorContext -import com.atlarge.odcsim.ActorRef -import com.atlarge.odcsim.ActorSystem -import com.atlarge.odcsim.Behavior -import com.atlarge.odcsim.Duration -import com.atlarge.odcsim.Instant -import com.atlarge.odcsim.internal.logging.LoggerImpl -import org.slf4j.Logger -import java.util.UUID - -/** - * A stubbed [ActorContext] implementation for synchronous behavior testing. - * - * @property owner The owner of this context. - */ -internal class ActorContextStub<T : Any>(private val owner: BehaviorTestKitImpl<T>) : ActorContext<T> { - /** - * The children of this context. - */ - val childActors = HashMap<String, BehaviorTestKitImpl<*>>() - - override val self: ActorRef<T> - get() = owner.ref - - override val children: List<ActorRef<*>> - get() = childActors.values.map { it.ref } - - override val time: Instant - get() = owner.time - - override val system: ActorSystem<*> by lazy { - ActorSystemStub(owner) - } - - override val log: Logger by lazy { - LoggerImpl(this) - } - - override fun getChild(name: String): ActorRef<*>? = childActors[name]?.ref - - override fun <U : Any> send(ref: ActorRef<U>, msg: U, after: Duration) { - if (ref !is TestInboxImpl.ActorRefImpl) { - throw IllegalArgumentException("The referenced ActorRef is not part of the test kit") - } - - ref.send(msg, after) - } - - override fun <U : Any> spawn(behavior: Behavior<U>, name: String): ActorRef<U> { - val btk = BehaviorTestKitImpl(behavior, self.path.child(name)) - childActors[name] = btk - return btk.ref - } - - override fun <U : Any> spawnAnonymous(behavior: Behavior<U>): ActorRef<U> { - return spawn(behavior, "$" + UUID.randomUUID()) - } - - override fun stop(child: ActorRef<*>) { - require(child.path.parent == self.path) { "Only direct children of an actor may be stopped through the actor context." } - childActors -= child.path.name - } - - override fun watch(target: ActorRef<*>) {} - - override fun unwatch(target: ActorRef<*>) {} - - override fun sync(target: ActorRef<*>) {} - - override fun unsync(target: ActorRef<*>) {} - - override fun isSync(target: ActorRef<*>): Boolean = true -} diff --git a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorSystemStub.kt b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorSystemStub.kt deleted file mode 100644 index fee34a48..00000000 --- a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorSystemStub.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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.testkit.internal - -import com.atlarge.odcsim.ActorPath -import com.atlarge.odcsim.ActorRef -import com.atlarge.odcsim.ActorSystem -import com.atlarge.odcsim.Behavior -import com.atlarge.odcsim.Duration -import com.atlarge.odcsim.Instant - -/** - * A stubbed [ActorSystem] for synchronous testing of behavior. - * - * @property owner The owner of this actor system. - */ -internal class ActorSystemStub<T : Any>(private val owner: BehaviorTestKitImpl<T>) : ActorSystem<T> { - override val time: Instant - get() = owner.time - - override val name: String - get() = owner.ref.path.name - - override fun run(until: Duration) = throw IllegalStateException("Cannot run ActorSystem within actor") - - override fun send(msg: T, after: Duration) = owner.context.send(owner.context.self, msg, after) - - override fun terminate() {} - - override val path: ActorPath - get() = owner.ref.path - - override suspend fun <U : Any> spawnSystem(behavior: Behavior<U>, name: String): ActorRef<U> { - throw IllegalStateException("Cannot spawn system actor") - } -} diff --git a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/BehaviorTestKitImpl.kt b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/BehaviorTestKitImpl.kt deleted file mode 100644 index 2bd5b973..00000000 --- a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/BehaviorTestKitImpl.kt +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.testkit.internal - -import com.atlarge.odcsim.ActorPath -import com.atlarge.odcsim.ActorRef -import com.atlarge.odcsim.Behavior -import com.atlarge.odcsim.Instant -import com.atlarge.odcsim.internal.BehaviorInterpreter -import com.atlarge.odcsim.testkit.BehaviorTestKit -import com.atlarge.odcsim.testkit.TestInbox -import java.util.UUID -import kotlin.math.max - -/** - * Default implementation of the [BehaviorTestKit] interface. - * - * @param initialBehavior The initial behavior to initialize the actor of the test kit with. - * @param path The path to the actor. - */ -internal class BehaviorTestKitImpl<T : Any>( - initialBehavior: Behavior<T>, - path: ActorPath -) : BehaviorTestKit<T> { - /** - * The [BehaviorInterpreter] used to interpret incoming messages. - */ - private val interpreter = BehaviorInterpreter(initialBehavior) - - /** - * A flag to indicate whether the behavior was initially started. - */ - private var isStarted: Boolean = false - - override var time: Instant = .0 - private set - - override val inbox: TestInbox<T> = TestInboxImpl(this, path) - - override val behavior: Behavior<T> get() = interpreter.behavior - - override val ref: ActorRef<T> = inbox.ref - - override val context: ActorContextStub<T> = ActorContextStub(this) - - override fun run(msg: T): Boolean { - if (!isStarted) { - isStarted = true - interpreter.start(context) - } - - return interpreter.interpretMessage(context, msg) - } - - override fun runOne(): Boolean { - val (delivery, msg) = inbox.receiveEnvelope() - time = max(time, delivery) - return run(msg) - } - - override fun runTo(time: Instant) { - while (inbox.hasMessages && this.time <= time) { - runOne() - } - this.time = time - } - - override fun <U : Any> createInbox(): TestInbox<U> { - return TestInboxImpl(this, ref.path.child(UUID.randomUUID().toString())) - } - - override fun <U : Any> childInbox(name: String): TestInbox<U> = childTestKit<U>(name).inbox - - override fun <U : Any> childInbox(ref: ActorRef<U>): TestInbox<U> = childTestKit(ref).inbox - - override fun <U : Any> childTestKit(name: String): BehaviorTestKit<U> { - @Suppress("UNCHECKED_CAST") - return context.childActors[ref.path.name] as BehaviorTestKitImpl<U>? ?: throw IllegalArgumentException("$ref is not a child of $this") - } - - override fun <U : Any> childTestKit(ref: ActorRef<U>): BehaviorTestKit<U> { - val btk = childTestKit<U>(ref.path.name) - - if (btk.ref != ref) { - throw IllegalArgumentException("$ref is not a child of $this") - } - - return btk - } -} diff --git a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/TestInboxImpl.kt b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/TestInboxImpl.kt deleted file mode 100644 index 35abd758..00000000 --- a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/TestInboxImpl.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.testkit.internal - -import com.atlarge.odcsim.ActorPath -import com.atlarge.odcsim.ActorRef -import com.atlarge.odcsim.Envelope -import com.atlarge.odcsim.Instant -import com.atlarge.odcsim.testkit.TestInbox -import org.junit.jupiter.api.Assertions.assertEquals -import java.util.PriorityQueue - -/** - * A helper class for testing messages sent to an [ActorRef]. - * - * @param owner The owner of the inbox. - * @param path The path to the test inbox. - * @param T The shape of the messages the inbox accepts. - */ -internal class TestInboxImpl<T : Any>(private val owner: BehaviorTestKitImpl<*>, path: ActorPath) : TestInbox<T> { - /** - * The queue of received messages. - */ - private val inbox = PriorityQueue<Envelope<T>>() - - /** - * The identifier for the next message to be scheduled. - */ - private var nextId: Long = 0 - - override val ref: ActorRef<T> = ActorRefImpl(path) - - override val hasMessages: Boolean - get() = inbox.isNotEmpty() - - override fun receiveEnvelope(): Envelope<T> = inbox.remove() - - override fun receiveAll(): List<Envelope<T>> = inbox.toList().also { inbox.clear() } - - override fun clear() = inbox.clear() - - override fun expectMessage(expected: T) = assertEquals(expected, receiveMessage()) - - override fun expectMessage(expected: T, message: String) = assertEquals(expected, receiveMessage(), message) - - internal inner class ActorRefImpl(override val path: ActorPath) : ActorRef<T> { - /** - * Send the specified message to the actor this reference is pointing to after the specified delay. - * - * @param msg The message to send. - * @param after The delay before the message is received. - */ - fun send(msg: T, after: Instant) { - inbox.add(EnvelopeImpl(nextId++, owner.time + after, msg)) - } - } - - /** - * A wrapper around a message that has been scheduled for processing. - * - * @property id The identifier of the message to keep the priority queue stable. - * @property time The point in time to deliver the message. - * @property message The message to wrap. - */ - private inner class EnvelopeImpl( - val id: Long, - override val time: Instant, - override val message: T - ) : Envelope<T> { - override fun compareTo(other: Envelope<*>): Int { - val cmp = super.compareTo(other) - return if (cmp == 0 && other is EnvelopeImpl) - id.compareTo(other.id) - else - cmp - } - } -} |
