mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-10 10:46:11 +03:00
scenario-tester: Allow to mangle names used in scenarios before their executions. (#795)
* Allow to mangle names used in scenarios before their executions. This allows to run a scenario against a long-running server repeatedly and avoid clashes between runs, since each party is unique (up to the randomness used). * ScenarioRunner: add test for partyNameMangler
This commit is contained in:
parent
debef0ec89
commit
b3e2e10897
@ -6,6 +6,7 @@ load(
|
||||
"da_scala_binary",
|
||||
"da_scala_library",
|
||||
"da_scala_test_suite",
|
||||
"lf_scalacopts",
|
||||
)
|
||||
|
||||
da_scala_library(
|
||||
@ -23,3 +24,16 @@ da_scala_library(
|
||||
"//daml-lf/transaction",
|
||||
],
|
||||
)
|
||||
|
||||
da_scala_test_suite(
|
||||
name = "scenario-interpreter_tests",
|
||||
size = "small",
|
||||
srcs = glob(["src/test/**/*.scala"]),
|
||||
scalacopts = lf_scalacopts,
|
||||
deps = [
|
||||
":scenario-interpreter",
|
||||
"//daml-lf/data",
|
||||
"//daml-lf/interpreter",
|
||||
"//daml-lf/lfpackage",
|
||||
],
|
||||
)
|
||||
|
@ -13,14 +13,22 @@ import com.digitalasset.daml.lf.speedy.SError._
|
||||
import com.digitalasset.daml.lf.speedy.SResult._
|
||||
import com.digitalasset.daml.lf.transaction.Node.GlobalKey
|
||||
|
||||
//
|
||||
// Speedy scenario runner that uses the reference ledger.
|
||||
//
|
||||
|
||||
private case class SRunnerException(err: SError) extends RuntimeException(err.toString)
|
||||
|
||||
final case class ScenarioRunner(machine: Speedy.Machine) {
|
||||
/** Speedy scenario runner that uses the reference ledger.
|
||||
*
|
||||
* @constructor Creates a runner using an instance of [[Speedy.Machine]].
|
||||
* @param partyNameMangler allows to amend party names defined in scenarios,
|
||||
* before they are executed against a ledger. The function should be idempotent
|
||||
* in the context of a single {@code ScenarioRunner} life-time, i.e. return the
|
||||
* same result each time given the same argument. Should return values compatible
|
||||
* with [[com.digitalasset.daml.lf.data.Ref.SimpleString]].
|
||||
*/
|
||||
final case class ScenarioRunner(
|
||||
machine: Speedy.Machine,
|
||||
partyNameMangler: (String => String) = identity) {
|
||||
var ledger: Ledger = Ledger.initialLedger(Time.Timestamp.Epoch)
|
||||
|
||||
import scala.util.{Try, Success, Failure}
|
||||
|
||||
def run(): Either[(SError, Ledger), (Double, Int, Ledger)] =
|
||||
@ -83,11 +91,13 @@ final case class ScenarioRunner(machine: Speedy.Machine) {
|
||||
private def crash(reason: String) =
|
||||
throw SRunnerException(SErrorCrash(reason))
|
||||
|
||||
private def getParty(partyText: String, callback: Party => Unit) =
|
||||
SimpleString.fromString(partyText) match {
|
||||
private def getParty(partyText: String, callback: Party => Unit) = {
|
||||
val mangledPartyText = partyNameMangler(partyText)
|
||||
SimpleString.fromString(mangledPartyText) match {
|
||||
case Right(s) => callback(s)
|
||||
case _ => throw SRunnerException(ScenarioErrorInvalidPartyName(partyText))
|
||||
}
|
||||
}
|
||||
|
||||
private def mustFail(tx: Transaction, committer: Party) = {
|
||||
// Update expression evaluated successfully,
|
||||
|
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.digitalasset.daml.lf.speedy
|
||||
|
||||
import com.digitalasset.daml.lf.PureCompiledPackages
|
||||
import com.digitalasset.daml.lf.data.Ref
|
||||
import com.digitalasset.daml.lf.lfpackage.Ast
|
||||
import com.digitalasset.daml.lf.lfpackage.Ast.ScenarioGetParty
|
||||
import org.scalatest._
|
||||
import org.scalatest.concurrent.ScalaFutures
|
||||
|
||||
class ScenarioRunnerTest extends AsyncWordSpec with Matchers with ScalaFutures {
|
||||
|
||||
"ScenarioRunner" can {
|
||||
"mangle party names correctly" in {
|
||||
val e = Ast.EScenario(ScenarioGetParty(Ast.EPrimLit(Ast.PLText("foo-bar"))))
|
||||
val m = Speedy.Machine.fromExpr(e, PureCompiledPackages(Map.empty).right.get, true)
|
||||
val sr = ScenarioRunner(m, (s) => s + "-XXX")
|
||||
sr.run()
|
||||
m.ctrl shouldBe Speedy.CtrlValue(SValue.SParty(Ref.Party.assertFromString("foo-bar-XXX")))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -27,10 +27,18 @@ import scala.annotation.tailrec
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.reflect.{ClassTag, classTag}
|
||||
|
||||
/** Scenario tester.
|
||||
*
|
||||
* @constructor Creates new tester.
|
||||
* @param partyNameMangler allows to amend party names defined in scenarios,
|
||||
* before they are executed against ledger created with {@code createLedger}.
|
||||
* See {@code ScenarioRunner.partyNameMangler} for details.
|
||||
*/
|
||||
class SemanticTester(
|
||||
createLedger: Set[SimpleString] => SemanticTester.GenericLedger,
|
||||
packageToTest: PackageId,
|
||||
packages: Map[PackageId, Package])(implicit ec: ExecutionContext) {
|
||||
packages: Map[PackageId, Package],
|
||||
partyNameMangler: (String => String) = identity)(implicit ec: ExecutionContext) {
|
||||
import SemanticTester._
|
||||
|
||||
// result ledgers from all scenarios found in packages
|
||||
@ -48,7 +56,7 @@ class SemanticTester(
|
||||
case (name, DValue(_, _, body, isTest)) if isTest =>
|
||||
val qualifiedName = QualifiedName(module.name, name)
|
||||
val machine = buildMachine(body)
|
||||
ScenarioRunner(machine).run() match {
|
||||
ScenarioRunner(machine, partyNameMangler = partyNameMangler).run() match {
|
||||
case Left((err, _ledger @ _)) =>
|
||||
sys.error(s"error running scenario $err in scenario: $qualifiedName")
|
||||
case Right((_time @ _, _steps @ _, ledger)) =>
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
package com.daml.ledger.api.testtool
|
||||
|
||||
import java.io.{File, StringWriter, PrintWriter}
|
||||
import java.nio.file.{Files, StandardCopyOption, Paths, Path}
|
||||
import java.io.{File, PrintWriter, StringWriter}
|
||||
import java.nio.file.{Files, Path, Paths, StandardCopyOption}
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.stream.ActorMaterializer
|
||||
@ -19,6 +19,7 @@ import com.digitalasset.platform.semantictest.SemanticTestAdapter
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.{Await, ExecutionContext}
|
||||
import scala.collection.breakOut
|
||||
import scala.util.Random
|
||||
|
||||
object LedgerApiTestTool {
|
||||
|
||||
@ -61,13 +62,17 @@ object LedgerApiTestTool {
|
||||
}
|
||||
var failed = false
|
||||
|
||||
val runSuffix = Random.alphanumeric.take(10).mkString
|
||||
var partyNameMangler = (partyText: String) => s"$partyText-$runSuffix"
|
||||
|
||||
try {
|
||||
scenarios.foreach {
|
||||
case (pkgId, names) =>
|
||||
val tester = new SemanticTester(
|
||||
parties => new SemanticTestAdapter(ledger, packages, parties.map(_.underlyingString)),
|
||||
pkgId,
|
||||
packages)
|
||||
packages,
|
||||
partyNameMangler)
|
||||
names
|
||||
.foreach { name =>
|
||||
println(s"Testing scenario: $name")
|
||||
|
Loading…
Reference in New Issue
Block a user