mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-03-04 13:00:25 +00:00
* propagation of the ask pattern into the unique number actor * TaskWorkflow as a replacement for TaskResolver; includes working tests * AvailabilityPolicy has been changed slightly; number source restriction mechanic has been completely removed * TaskResolver is gone and done and TaskWorkflow replaces it * number pool variety * every zone gets a custom tailored 'environment' number pool, as well as all other number pools; uns involves many more static functions and hard-defined variables * repairs to uns and guidtask tests; worked uns into unops, an actorless version, but did not integrate into server * shuffled around files in the guid package, causing import threshing; wrote extensive comments; repaired tests; classes related to the old unique number system have been removed * created straightforward tasks; simplified number pool actor calls; repaired tests due to modifications to generic pool * bad merge recovery
116 lines
4.3 KiB
Scala
116 lines
4.3 KiB
Scala
// Copyright (c) 2021 PSForever
|
|
package objects
|
|
|
|
import net.psforever.objects.guid.{Task, TaskBundle, TaskWorkflow}
|
|
import org.scalatest.flatspec.AsyncFlatSpec
|
|
|
|
import scala.concurrent.Future
|
|
import scala.util.Failure
|
|
|
|
class AsyncTaskWorkflowTest extends AsyncFlatSpec {
|
|
case class StringAppendTask(product: StringBuilder, str: String) extends Task {
|
|
def action() = { Future({ product.append(str) }) }
|
|
def undo() = {
|
|
val index = product.indexOf(str)
|
|
product.replace(index, index + str.length, "[successful task undo]")
|
|
}
|
|
def isSuccessful() = { product.indexOf(str) > -1 }
|
|
}
|
|
|
|
case class FailedStringAppendTask(product: StringBuilder, str: String) extends Task {
|
|
def action() = { Future(Failure(new Exception("intentional failure"))) }
|
|
def undo() = {
|
|
val index = product.indexOf(str)
|
|
product.replace(index, index + str.length, "[failed task undo]")
|
|
}
|
|
def isSuccessful() = { product.indexOf(str) > -1 }
|
|
}
|
|
|
|
behavior of "TaskWorkFlow"
|
|
|
|
it should "append a string as a task" in {
|
|
val test: StringBuilder = new StringBuilder()
|
|
assert(test.mkString.isEmpty)
|
|
val result = TaskWorkflow.execute(TaskBundle(StringAppendTask(test, "hello")))
|
|
result map { _ =>
|
|
assert(test.mkString.equals("hello"), "async result does not equal 'hello'")
|
|
}
|
|
}
|
|
|
|
it should "append the strings in order of subtask then main task" in {
|
|
val test: StringBuilder = new StringBuilder()
|
|
assert(test.mkString.isEmpty)
|
|
val result = TaskWorkflow.execute(TaskBundle(StringAppendTask(test, " world"), StringAppendTask(test, "hello")))
|
|
result map { _ =>
|
|
assert(test.mkString.equals("hello world"), "async result does not equal 'hello world'")
|
|
}
|
|
}
|
|
|
|
it should "append the strings in order of subtasks then main task, with the subtasks being in either order" in {
|
|
val test: StringBuilder = new StringBuilder()
|
|
assert(test.mkString.isEmpty)
|
|
val result = TaskWorkflow.execute(TaskBundle(
|
|
StringAppendTask(test, " world"),
|
|
Seq(
|
|
TaskBundle(StringAppendTask(test, " hello")),
|
|
TaskBundle(StringAppendTask(test, " or goodbye"))
|
|
)
|
|
))
|
|
result map { _ =>
|
|
val output = test.mkString
|
|
assert(
|
|
output.equals(" or goodbye hello world") || output.equals(" hello or goodbye world"),
|
|
s"async result '$output' does not equal either pattern"
|
|
)
|
|
}
|
|
}
|
|
|
|
it should "if a task fails, do not undo it" in {
|
|
val test: StringBuilder = new StringBuilder()
|
|
assert(test.mkString.isEmpty)
|
|
val result = TaskWorkflow.execute(TaskBundle(FailedStringAppendTask(test, " world")))
|
|
result map { _ =>
|
|
val output = test.mkString
|
|
assert(output.equals(""),"async result was written when should have not been written")
|
|
//see implementation of FailedStringAppendTask.undo
|
|
}
|
|
}
|
|
|
|
it should "if a middling subtask fails, its parent task will not be executed or undone, but its own subtask will be undone (1)" in {
|
|
val test: StringBuilder = new StringBuilder()
|
|
assert(test.mkString.isEmpty)
|
|
val result = TaskWorkflow.execute(TaskBundle(
|
|
StringAppendTask(test, " world"),
|
|
TaskBundle(FailedStringAppendTask(test, "hello"), StringAppendTask(test, " or goodbye")))
|
|
)
|
|
result map { _ =>
|
|
val output = test.mkString
|
|
assert(output.equals("[successful task undo]"),s"async result, formerly successful, was written as if it had failed - $output")
|
|
//see implementation of StringAppendTask.undo
|
|
}
|
|
}
|
|
|
|
it should "if a middling subtask fails, its parent task will not be executed or undone, but its own subtasks will be undone (2)" in {
|
|
val test: StringBuilder = new StringBuilder()
|
|
assert(test.mkString.isEmpty)
|
|
val result = TaskWorkflow.execute(TaskBundle(
|
|
StringAppendTask(test, " world"),
|
|
TaskBundle(FailedStringAppendTask(test, "hello"), List(
|
|
TaskBundle(StringAppendTask(test, " or goodbye")),
|
|
TaskBundle(StringAppendTask(test, " or something"))
|
|
))
|
|
))
|
|
result map { _ =>
|
|
val output = test.mkString
|
|
assert(
|
|
output.equals("[successful task undo][successful task undo]"),
|
|
s"async result, formerly successful, was written as if it had failed - $output"
|
|
)
|
|
//see implementation of StringAppendTask.undo
|
|
}
|
|
}
|
|
}
|
|
|
|
object TaskWorkflowTest {
|
|
/** placeholder */
|
|
}
|