diff --git a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/DivulgenceIT.scala b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/DivulgenceIT.scala index c5709c713463..7d0d4ce0b424 100644 --- a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/DivulgenceIT.scala +++ b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/DivulgenceIT.scala @@ -3,8 +3,6 @@ package com.digitalasset.platform.tests.integration.ledger.api -import java.util.UUID - import akka.stream.scaladsl.Sink import com.digitalasset.daml.lf.data.{ImmArray, Ref} import com.digitalasset.daml.lf.data.Ref.{ContractIdString, LedgerString} @@ -26,7 +24,12 @@ import com.digitalasset.ledger.api.v1.ledger_offset._ import com.digitalasset.ledger.api.v1.transaction_filter._ import com.digitalasset.ledger.client.services.acs.ActiveContractSetClient import com.digitalasset.ledger.client.services.transactions.TransactionClient -import com.digitalasset.platform.apitesting.{LedgerContext, MultiLedgerFixture, TestTemplateIds} +import com.digitalasset.platform.apitesting.{ + LedgerContext, + MultiLedgerFixture, + TestIdsGenerator, + TestTemplateIds +} import com.digitalasset.platform.participant.util.LfEngineToApi import com.google.protobuf.timestamp.Timestamp import org.scalatest.Inside.inside @@ -50,6 +53,7 @@ class DivulgenceIT protected val testTemplateIds = new TestTemplateIds(config) protected val templateIds = testTemplateIds.templateIds + protected val testIdsGenerator = new TestIdsGenerator(config) private implicit def party(s: String): Ref.Party = Ref.Party.assertFromString(s) private implicit def pkgId(s: String): Ref.PackageId = Ref.PackageId.assertFromString(s) @@ -157,12 +161,10 @@ class DivulgenceIT // but that it is visible in the transaction trees. case class Setup(div1Cid: String, div2Cid: String) - private val runSuffix: UUID = UUID.randomUUID - private def createDivulgence1(ctx: LedgerContext, workflowId: String): Future[ContractIdString] = create( ctx, - s"create-Divulgence1-$runSuffix", + testIdsGenerator.testCommandId("create-Divulgence1"), workflowId, "alice", templateIds.divulgence1, @@ -172,7 +174,7 @@ class DivulgenceIT private def createDivulgence2(ctx: LedgerContext, workflowId: String): Future[ContractIdString] = create( ctx, - s"create-Divulgence2-$runSuffix", + testIdsGenerator.testCommandId("create-Divulgence2"), workflowId, "bob", templateIds.divulgence2, @@ -190,7 +192,7 @@ class DivulgenceIT workflowId: String): Future[Unit] = exercise( ctx, - s"exercise-Divulgence2Fetch-$runSuffix", + testIdsGenerator.testCommandId("exercise-Divulgence2Fetch"), workflowId, "alice", templateIds.divulgence2, @@ -208,7 +210,7 @@ class DivulgenceIT workflowId: String): Future[Unit] = exercise( ctx, - s"exercise-Divulgence2Fetch-$runSuffix", + testIdsGenerator.testCommandId("exercise-Divulgence2Fetch"), workflowId, "alice", templateIds.divulgence2, @@ -228,7 +230,7 @@ class DivulgenceIT Map("alice" -> Filters.defaultInstance, "bob" -> Filters.defaultInstance)) "should not expose divulged contracts in flat stream" in allFixtures { ctx => - val wfid = s"divulgence-test-workflow-id-$runSuffix" + val wfid = testIdsGenerator.testWorkflowId("divulgence-test-workflow-id") for { beforeTest <- transactionClient(ctx).getLedgerEnd.map(_.getOffset) div1Cid <- createDivulgence1(ctx, wfid) @@ -321,7 +323,7 @@ class DivulgenceIT } "should not expose divulged contracts in ACS" in allFixtures { ctx => - val wfid = s"divulgence-test-workflow-id-$runSuffix" + val wfid = testIdsGenerator.testWorkflowId("divulgence-test-workflow-id") for { beforeTest <- transactionClient(ctx).getLedgerEnd.map(_.getOffset) div1Cid <- createDivulgence1(ctx, wfid) diff --git a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/PackageManagementServiceIT.scala b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/PackageManagementServiceIT.scala index 596541d48d94..404351b8ceb4 100644 --- a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/PackageManagementServiceIT.scala +++ b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/PackageManagementServiceIT.scala @@ -12,7 +12,7 @@ import com.digitalasset.daml.lf.archive.{DarReader, Decode} import com.digitalasset.daml.lf.language.Ast import com.digitalasset.daml_lf.DamlLf.Archive -import scala.util.{Random, Try} +import scala.util.Try import com.digitalasset.ledger.api.testing.utils.{ AkkaBeforeAndAfterAll, IsStatusException, @@ -24,7 +24,7 @@ import com.digitalasset.ledger.api.v1.transaction_filter.{Filters, TransactionFi import com.digitalasset.ledger.api.v1.value.{Identifier, Record, RecordField} import com.digitalasset.ledger.client.services.admin.PackageManagementClient import com.digitalasset.platform.apitesting.LedgerContextExtensions._ -import com.digitalasset.platform.apitesting.MultiLedgerFixture +import com.digitalasset.platform.apitesting.{MultiLedgerFixture, TestIdsGenerator} import com.digitalasset.platform.participant.util.ValueConversions._ import io.grpc.Status import com.google.protobuf.ByteString @@ -46,13 +46,11 @@ class PackageManagementServiceIT with Matchers with BazelRunfiles { - private val runSuffix = "-" + Random.alphanumeric.take(10).mkString - private val partyNameMangler = - (partyText: String) => partyText + runSuffix + Random.alphanumeric.take(10).mkString - private val commandIdMangler = - (testName: String, nodeId: String) => s"ledger-api-test-tool-$testName-$nodeId-$runSuffix" - override protected def config: Config = Config.default.copy(darFiles = Nil) + protected val testIdsGenerator = new TestIdsGenerator(config) + + private def commandNodeIdUnifier(testName: String, nodeId: String) = + testIdsGenerator.testCommandId(s"ledger-api-test-tool-$testName-$nodeId") private def packageManagementService(stub: PackageManagementService): PackageManagementClient = new PackageManagementClient(stub) @@ -136,7 +134,7 @@ class PackageManagementServiceIT } "should accept commands using the uploaded package" in allFixtures { ctx => - val party = partyNameMangler("operator") + val party = testIdsGenerator.testPartyName("operator") val createArg = Record(fields = List(RecordField("operator", party.asParty))) def createCmd = CreateCommand(Some(Identifier(testPackageId, "", "Test", "Dummy")), Some(createArg)).wrap @@ -147,7 +145,8 @@ class PackageManagementServiceIT _ <- client.uploadDarFile(ByteString.copyFrom(testDarBytes)) createTx <- ctx.testingHelpers.submitAndListenForSingleResultOfCommand( ctx.testingHelpers - .submitRequestWithId(commandIdMangler("PackageManagementServiceIT_commands", "create")) + .submitRequestWithId( + commandNodeIdUnifier("PackageManagementServiceIT_commands", "create")) .update( _.commands.commands := List(createCmd), _.commands.party := party diff --git a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TimeServiceDisabledIT.scala b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TimeServiceDisabledIT.scala index dc68cdafe461..3895bf5b5b32 100644 --- a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TimeServiceDisabledIT.scala +++ b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TimeServiceDisabledIT.scala @@ -21,7 +21,6 @@ import org.scalatest._ import org.scalatest.concurrent.AsyncTimeLimitedTests import org.scalatest.time.Span import org.scalatest.time.SpanSugar._ - import scalaz.syntax.tag._ @SuppressWarnings( diff --git a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TransactionServiceIT.scala b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TransactionServiceIT.scala index dd29c5f8d7b0..5a66b0066904 100644 --- a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TransactionServiceIT.scala +++ b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/TransactionServiceIT.scala @@ -8,8 +8,6 @@ import java.time.{Duration, Instant} import akka.Done import akka.stream.scaladsl.{Flow, Sink} import com.digitalasset.daml.lf.data.Ref -import com.digitalasset.daml.lf.data.Ref.QualifiedName -import com.digitalasset.daml.lf.types.Ledger import com.digitalasset.grpc.adapter.utils.DirectExecutionContext import com.digitalasset.ledger.api.domain.{EventId, LedgerId} import com.digitalasset.ledger.api.testing.utils.MockMessages.{party, _} @@ -35,7 +33,12 @@ import com.digitalasset.ledger.client.services.commands.CommandUpdater import com.digitalasset.ledger.client.services.transactions.TransactionClient import com.digitalasset.platform.api.v1.event.EventOps._ import com.digitalasset.platform.apitesting.LedgerContextExtensions._ -import com.digitalasset.platform.apitesting.{LedgerContext, MultiLedgerFixture, TestTemplateIds} +import com.digitalasset.platform.apitesting.{ + LedgerContext, + MultiLedgerFixture, + TestIdsGenerator, + TestTemplateIds +} import com.digitalasset.platform.esf.TestExecutionSequencerFactory import com.digitalasset.platform.participant.util.ValueConversions._ import com.digitalasset.platform.services.time.TimeProviderType @@ -50,7 +53,6 @@ import scalaz.{ICons, NonEmptyList, Tag} import scala.collection.{breakOut, immutable} import scala.concurrent.Future -import scala.util.Random @SuppressWarnings(Array("org.wartremover.warts.Any")) class TransactionServiceIT @@ -71,14 +73,7 @@ class TransactionServiceIT protected val helpers = new TransactionServiceHelpers(config) protected val testTemplateIds = new TestTemplateIds(config) protected val templateIds = testTemplateIds.templateIds - - val runSuffix = "-" + Random.alphanumeric.take(10).mkString - val partyNameMangler = - (partyText: String) => partyText + runSuffix + Random.alphanumeric.take(10).mkString - val commandIdMangler: ((QualifiedName, Int, Ledger.ScenarioNodeId) => String) = - (testName, stepId, nodeId) => { - s"ledger-api-test-tool-$testName-$stepId-$nodeId-$runSuffix" - } + protected val testIdsGenerator = new TestIdsGenerator(config) override val timeLimit: Span = scaled(300.seconds) @@ -324,7 +319,8 @@ class TransactionServiceIT "expose transactions to non-submitting stakeholders without the commandId" in allFixtures { c => c.submitCreateAndReturnTransaction( - s"Checking_commandId_visibility_for_non-submitter_party-${runSuffix}", + testIdsGenerator.testCommandId( + "Checking_commandId_visibility_for_non-submitter_party"), templateIds.agreementFactory, List("receiver" -> party1.asParty, "giver" -> party2.asParty).asRecordFields, party2, @@ -335,7 +331,7 @@ class TransactionServiceIT } "expose only the requested templates to the client" in allFixtures { context => - val commandId = s"Client_should_see_only_the_Dummy_create-${runSuffix}" + val commandId = testIdsGenerator.testCommandId("Client_should_see_only_the_Dummy_create") val templateInSubscription = templateIds.dummy val otherTemplateCreated = templateIds.dummyFactory for { @@ -358,8 +354,8 @@ class TransactionServiceIT "expose contract Ids that are ready to be used for exercising choices" in allFixtures { context => - val factoryCreation = s"Creating_factory-${runSuffix}" - val exercisingChoice = s"Exercising_choice_on_factory-${runSuffix}" + val factoryCreation = testIdsGenerator.testCommandId("Creating_factory") + val exercisingChoice = testIdsGenerator.testCommandId("Exercising_choice_on_factory") val exercisedTemplate = templateIds.dummyFactory for { createdEvent <- context.submitCreate( @@ -384,8 +380,9 @@ class TransactionServiceIT "expose contract Ids that are results of exercising choices when filtering by template" in allFixtures { context => - val factoryCreation = s"Creating_second_factory-${runSuffix}" - val exercisingChoice = s"Exercising_choice_on_second_factory-${runSuffix}" + val factoryCreation = testIdsGenerator.testCommandId("Creating_second_factory") + val exercisingChoice = + testIdsGenerator.testCommandId("Exercising_choice_on_second_factory") val exercisedTemplate = templateIds.dummyFactory for { creation <- context.submitCreate( @@ -428,7 +425,7 @@ class TransactionServiceIT "reject exercising a choice where an assertion fails" in allFixtures { c => for { dummy <- c.submitCreate( - s"Create_for_assertion_failing_test-${runSuffix}", + testIdsGenerator.testCommandId("Create_for_assertion_failing_test"), templateIds.dummy, List("operator" -> party.asParty).asRecordFields, party) @@ -457,11 +454,12 @@ class TransactionServiceIT val expectedArg = paramShowcaseArgsWithoutLabels for { create <- c.submitCreate( - s"Creating_contract_with_a_multitude_of_param_types-${runSuffix}", + testIdsGenerator.testCommandId("Creating_contract_with_a_multitude_of_param_types"), template, paramShowcaseArgs(templateIds.testPackageId), "party", - verbose = false) + verbose = false + ) } yield { create.getCreateArguments.recordId shouldBe empty create.getCreateArguments.fields shouldEqual expectedArg @@ -474,7 +472,8 @@ class TransactionServiceIT for { create <- c.submitCreate( - s"Creating_contract_with_a_multitude_of_verbose_param_types-${runSuffix}", + testIdsGenerator.testCommandId( + "Creating_contract_with_a_multitude_of_verbose_param_types"), template, arg, "party", @@ -527,7 +526,7 @@ class TransactionServiceIT val template = templateIds.parameterShowcase for { create <- c.submitCreate( - s"Huge_command_with_a_long_list-${runSuffix}", + testIdsGenerator.testCommandId("Huge_command_with_a_long_list"), template, arg, "party" @@ -542,7 +541,7 @@ class TransactionServiceIT val giver = "Alice" for { created <- c.submitCreateWithListenerAndReturnEvent( - s"Creating_Agreement_Factory-${runSuffix}", + testIdsGenerator.testCommandId("Creating_Agreement_Factory"), templateIds.agreementFactory, List("receiver" -> receiver.asParty, "giver" -> giver.asParty).asRecordFields, giver, @@ -551,7 +550,7 @@ class TransactionServiceIT choiceResult <- c.testingHelpers.submitAndListenForSingleResultOfCommand( c.command( - s"Calling_non-consuming_choice-${runSuffix}", + testIdsGenerator.testCommandId("Calling_non-consuming_choice"), List( ExerciseCommand( Some(templateIds.agreementFactory), @@ -577,7 +576,7 @@ class TransactionServiceIT for { branchingSignatories <- c.submitCreateWithListenerAndReturnEvent( - s"BranchingSignatoriesTrue-${runSuffix}", + testIdsGenerator.testCommandId("BranchingSignatoriesTrue"), templateIds.branchingSignatories, branchingSignatoriesArg, party1, @@ -591,7 +590,7 @@ class TransactionServiceIT val branchingSignatoriesArg = getBranchingSignatoriesArg(false, party1, party2) c.submitCreateWithListenerAndAssertNotVisible( - s"BranchingSignatoriesFalse-${runSuffix}", + testIdsGenerator.testCommandId("BranchingSignatoriesFalse"), templateIds.branchingSignatories, branchingSignatoriesArg, party2, @@ -604,7 +603,7 @@ class TransactionServiceIT val expectedArg = branchingControllersArgs.map(_.copy(label = "")) for { branchingControllers <- c.submitCreateWithListenerAndReturnEvent( - s"BranchingControllersTrue-${runSuffix}", + testIdsGenerator.testCommandId("BranchingControllersTrue"), templateId, branchingControllersArgs, party1, @@ -619,7 +618,7 @@ class TransactionServiceIT val branchingControllersArgs = getBranchingControllerArgs(party1, party2, party3, false) c.submitCreateWithListenerAndAssertNotVisible( - s"BranchingControllersFalse-${runSuffix}", + testIdsGenerator.testCommandId("BranchingControllersFalse"), templateId, branchingControllersArgs, party1, @@ -639,7 +638,7 @@ class TransactionServiceIT .sequence(observers.map(observer => for { withObservers <- c.submitCreateWithListenerAndReturnEvent( - s"Obs1create:${observer}-${runSuffix}", + testIdsGenerator.testCommandId(s"Obs1create:${observer}"), templateIds.withObservers, withObserversArg, giver, @@ -660,7 +659,7 @@ class TransactionServiceIT val expectedArgs = createArguments.map(_.copy(label = "")) c.submitCreate( - s"Creating_contract_with_a_Nothing_argument-${runSuffix}", + testIdsGenerator.testCommandId("Creating_contract_with_a_Nothing_argument"), templateIds.nothingArgument, createArguments, "party") @@ -678,17 +677,19 @@ class TransactionServiceIT "expose the default agreement text in CreatedEvents for templates with no explicit agreement text" in allFixtures { c => val resultF = c.submitCreate( - s"Creating_dummy_contract_for_default_agreement_text_test-${runSuffix}", + testIdsGenerator.testCommandId( + "Creating_dummy_contract_for_default_agreement_text_test"), templateIds.dummy, List(RecordField("operator", party1.asParty)), - party1) + party1 + ) resultF.map(_.agreementText shouldBe Some("")) } "expose the correct stakeholders" in allFixtures { c => val resultF = c.submitCreate( - s"Creating_CallablePayout_contract_for_stakeholders_test-${runSuffix}", + testIdsGenerator.testCommandId("Creating_CallablePayout_contract_for_stakeholders_test"), templateIds.callablePayout, List( RecordField("giver", party1.asParty), @@ -706,7 +707,8 @@ class TransactionServiceIT "not expose the contract key in CreatedEvents for templates that do not have them" in allFixtures { c => val resultF = c.submitCreate( - s"Creating_CallablePayout_contract_for_contract_key_test-${runSuffix}", + testIdsGenerator.testCommandId( + "Creating_CallablePayout_contract_for_contract_key_test"), templateIds.callablePayout, List( RecordField("giver", party1.asParty), @@ -720,7 +722,7 @@ class TransactionServiceIT "expose the contract key in CreatedEvents for templates that have them" in allFixtures { c => val resultF = c.submitCreate( - s"Creating_TextKey_contract_for_contract_key_test-${runSuffix}", + testIdsGenerator.testCommandId("Creating_TextKey_contract_for_contract_key_test"), templateIds.textKey, List( RecordField("tkParty", party1.asParty), @@ -751,12 +753,12 @@ class TransactionServiceIT for { agreement <- createAgreement(c, "MA1", receiver, giver) triProposal <- c.submitCreate( - s"MA1proposal-${runSuffix}", + testIdsGenerator.testCommandId("MA1proposal"), templateIds.triProposal, triProposalArg, operator) tx <- c.submitExercise( - s"MA1acceptance-${runSuffix}", + testIdsGenerator.testCommandId("MA1acceptance"), templateIds.agreement, List("cid" -> Value(ContractId(triProposal.contractId))).asRecordValue, "AcceptTriProposal", @@ -777,12 +779,12 @@ class TransactionServiceIT val expectedArg = triProposalArg.map(_.copy(label = "")) for { triProposal <- c.submitCreate( - s"MA2proposal-${runSuffix}", + testIdsGenerator.testCommandId("MA2proposal"), templateIds.triProposal, triProposalArg, operator) tx <- c.submitExercise( - s"MA2acceptance-${runSuffix}", + testIdsGenerator.testCommandId("MA2acceptance"), templateIds.triProposal, unitArg, "TriProposalAccept", @@ -799,7 +801,7 @@ class TransactionServiceIT val triProposalArg = mkTriProposalArg(operator, receiver, giver) for { triProposal <- c.submitCreate( - s"MA3proposal-${runSuffix}", + testIdsGenerator.testCommandId("MA3proposal"), templateIds.triProposal, triProposalArg, operator) @@ -830,7 +832,7 @@ class TransactionServiceIT for { agreement <- createAgreement(c, "MA4", receiver, giver) triProposal <- c.submitCreate( - s"MA4proposal-${runSuffix}", + testIdsGenerator.testCommandId("MA4proposal"), templateIds.triProposal, triProposalArg, operator) @@ -855,12 +857,12 @@ class TransactionServiceIT val arguments = List("street", "city", "state", "zip") for { dummy <- c.submitCreate( - s"Create_dummy_for_creating_AddressWrapper-${runSuffix}", + testIdsGenerator.testCommandId("Create_dummy_for_creating_AddressWrapper"), templateIds.dummy, List("operator" -> party.asParty).asRecordFields, party) exercise <- c.submitExercise( - s"Creating_AddressWrapper-${runSuffix}", + testIdsGenerator.testCommandId("Creating_AddressWrapper"), templateIds.dummy, List("address" -> arguments.map(e => e -> e.asText).asRecordValue).asRecordValue, "WrapWithAddress", @@ -921,13 +923,13 @@ class TransactionServiceIT val createAndFetchTid = templateIds.createAndFetch for { createdEvent <- context.submitCreate( - s"CreateAndFetch_Create-$runSuffix", + testIdsGenerator.testCommandId("CreateAndFetch_Create"), createAndFetchTid, List("p" -> party.asParty).asRecordFields, party) cid = createdEvent.contractId exerciseTx <- context.submitExercise( - s"CreateAndFetch_Run-$runSuffix", + testIdsGenerator.testCommandId("CreateAndFetch_Run"), createAndFetchTid, Value(Value.Sum.Record(Record())), "CreateAndFetch_Run", @@ -1566,7 +1568,7 @@ class TransactionServiceIT prefix: String, commandsPerSection: Int, context: LedgerContext): Future[Done] = { - insertCommands(s"${prefix}-${runSuffix}", commandsPerSection, context) + insertCommands(testIdsGenerator.testCommandId(prefix), commandsPerSection, context) } private def lastOffsetIn(secondSection: immutable.Seq[Transaction]): Option[LedgerOffset] = { @@ -1657,7 +1659,7 @@ class TransactionServiceIT ): Future[CreatedEvent] = { for { agreementFactory <- c.submitCreate( - commandId + s"factory_creation-${runSuffix}", + commandId + testIdsGenerator.testCommandId("factory_creation"), templateIds.agreementFactory, List( "receiver" -> receiver.asParty, @@ -1666,12 +1668,13 @@ class TransactionServiceIT giver ) tx <- c.submitExercise( - commandId + s"_acceptance-${runSuffix}", + commandId + testIdsGenerator.testCommandId("_acceptance"), templateIds.agreementFactory, unitArg, "AgreementFactoryAccept", agreementFactory.contractId, - receiver) + receiver + ) } yield { getHead(c.testingHelpers.createdEventsIn(tx)) } @@ -1690,7 +1693,7 @@ class TransactionServiceIT ): Future[Assertion] = c.testingHelpers.assertCommandFailsWithCode( c.command( - s"${commandId}-${runSuffix}", + testIdsGenerator.testCommandId(commandId), List(ExerciseCommand(Some(template), contractId, choice, Some(arg)).wrap)) .update( _.commands.party := submitter @@ -1708,7 +1711,8 @@ class TransactionServiceIT for { creation <- context.submitCreate( - s"Creating_contract_with_a_multitude_of_param_types_for_exercising-${runSuffix}_$choice#$lbl", + testIdsGenerator.testCommandId( + s"Creating_contract_with_a_multitude_of_param_types_for_exercising_$choice#$lbl"), templateIds.parameterShowcase, paramShowcaseArgs(templateIds.testPackageId), MockMessages.party @@ -1723,7 +1727,7 @@ class TransactionServiceIT exerciseTx <- context.testingHelpers.submitAndListenForSingleResultOfCommand( context .command( - s"Exercising_with_a_multitiude_of_params-${runSuffix}_$choice#$lbl", + testIdsGenerator.testCommandId(s"Exercising_with_a_multitiude_of_params_$choice#$lbl"), List(exerciseCommand)), getAllContracts ) diff --git a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/transaction/TransactionBackpressureIT.scala b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/transaction/TransactionBackpressureIT.scala index 1e723fb67c59..bbc44b83a93e 100644 --- a/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/transaction/TransactionBackpressureIT.scala +++ b/ledger/ledger-api-integration-tests/src/test/itsuite/scala/com/digitalasset/platform/tests/integration/ledger/api/transaction/TransactionBackpressureIT.scala @@ -3,8 +3,6 @@ package com.digitalasset.platform.tests.integration.ledger.api.transaction -import java.util.UUID - import akka.stream.ThrottleMode import akka.stream.scaladsl.{Sink, Source} import com.digitalasset.ledger.api.testing.utils.{ @@ -15,7 +13,7 @@ import com.digitalasset.ledger.api.testing.utils.{ import com.digitalasset.ledger.api.v1.ledger_offset.LedgerOffset import com.digitalasset.ledger.api.v1.ledger_offset.LedgerOffset.LedgerBoundary.LEDGER_BEGIN import com.digitalasset.ledger.api.v1.ledger_offset.LedgerOffset.Value.Boundary -import com.digitalasset.platform.apitesting.{MultiLedgerFixture, TestCommands} +import com.digitalasset.platform.apitesting.{MultiLedgerFixture, TestCommands, TestIdsGenerator} import org.scalatest._ import org.scalatest.concurrent.ScalaFutures import org.scalatest.time.Span @@ -36,6 +34,7 @@ class TransactionBackpressureIT with MultiLedgerFixture { protected val testCommands = new TestCommands(config) + protected val testIdsGenerator = new TestIdsGenerator(config) override def timeLimit: Span = scaled(300.seconds) @@ -48,8 +47,6 @@ class TransactionBackpressureIT "The transaction service when serving multiple subscriptions" should { - val runSuffix = UUID.randomUUID() - "handle back pressure" in allFixtures { ctx => val noOfCommands = 1000 val noOfSubscriptions = 10 @@ -61,8 +58,8 @@ class TransactionBackpressureIT Source(1 to noOfCommands) .throttle(10, 1.second) .mapAsync(10)(i => - commandClient.submitSingleCommand( - testCommands.oneKbCommandRequest(ctx.ledgerId, s"command-$i-$runSuffix"))) + commandClient.submitSingleCommand(testCommands + .oneKbCommandRequest(ctx.ledgerId, testIdsGenerator.testCommandId(s"command-$i")))) .runWith(Sink.ignore) def subscribe(begin: LedgerOffset, rate: Int) = diff --git a/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/PlatformApplications.scala b/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/PlatformApplications.scala index bae524964159..ad3531354f41 100644 --- a/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/PlatformApplications.scala +++ b/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/PlatformApplications.scala @@ -41,6 +41,8 @@ object PlatformApplications { persistenceEnabled: Boolean = false, maxNumberOfAcsContracts: Option[Int] = None, commandConfiguration: CommandConfiguration = SandboxConfig.defaultCommandConfig, + uniqueCommandIdentifiers: Boolean = true, + uniquePartyIdentifiers: Boolean = true, remoteApiEndpoint: Option[RemoteApiEndpoint] = None) { require( Duration.ofSeconds(timeModel.minTtl.getSeconds) == timeModel.minTtl && @@ -56,6 +58,12 @@ object PlatformApplications { def withLedgerIdMode(mode: LedgerIdMode): Config = copy(ledgerId = mode) + def withUniquePartyIdentifiers(uniqueIdentifiers: Boolean): Config = + copy(uniquePartyIdentifiers = uniqueIdentifiers) + + def withUniqueCommandIdentifiers(uniqueIdentifiers: Boolean): Config = + copy(uniqueCommandIdentifiers = uniqueIdentifiers) + def withParties(p1: String, rest: String*) = copy(parties = NonEmptyList(p1, rest: _*)) def withCommitterParty(committer: String) = copy(committerParty = committer) diff --git a/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/apitesting/CommandTransactionChecks.scala b/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/apitesting/CommandTransactionChecks.scala index a75b64a9905c..a7162af603ff 100644 --- a/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/apitesting/CommandTransactionChecks.scala +++ b/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/apitesting/CommandTransactionChecks.scala @@ -65,6 +65,7 @@ abstract class CommandTransactionChecks protected val testTemplateIds = new TestTemplateIds(config) protected val templateIds = testTemplateIds.templateIds + protected val testIdsGenerator = new TestIdsGenerator(config) override protected def config: Config = Config.default @@ -104,8 +105,6 @@ abstract class CommandTransactionChecks private val emptyRecordValue = Value(Value.Sum.Record(Record())) - private val runSuffix = UUID.randomUUID() - def assertCompletionIsSuccessful(completion: Completion): Assertion = { inside(completion) { case c => c.getStatus should have('code (0)) @@ -116,7 +115,7 @@ abstract class CommandTransactionChecks "reading completions" should { "return the completion of submitted commands for the submitting application" in allFixtures { ctx => - val commandId = s"Submitting_application_sees_this-$runSuffix" + val commandId = testIdsGenerator.testCommandId("Submitting_application_sees_this") val request = createCommandWithId(ctx, commandId) for { commandClient <- ctx.commandClient() @@ -133,7 +132,7 @@ abstract class CommandTransactionChecks } "not expose completions of submitted commands to other applications" in allFixtures { ctx => - val commandId = s"The_other_application_does_not_see_this-$runSuffix" + val commandId = testIdsGenerator.testCommandId("The_other_application_does_not_see_this") val request = createCommandWithId(ctx, commandId) for { commandClient <- ctx.commandClient() @@ -152,7 +151,7 @@ abstract class CommandTransactionChecks "not expose completions of submitted commands to the application if it down't include the submitting party" in allFixtures { ctx => val commandId = - s"The_application_should_subscribe_with_the_submitting_party_to_see_this-$runSuffix" + testIdsGenerator.testCommandId("The_application_should_subscribe_with_the_submitting_party_to_see_this") val request = createCommandWithId(ctx, commandId) for { commandClient <- ctx.commandClient() @@ -176,15 +175,15 @@ abstract class CommandTransactionChecks // note that the submitting party is not a stakeholder in any event, // so this test relies on the sandbox exposing the transactions to the // submitter. - val factoryCreation = s"Creating_factory_Trees-$runSuffix" - val exercisingChoice = s"Exercising_choice_on_factory_Trees-$runSuffix" + val factoryCreation = testIdsGenerator.testCommandId("Creating_factory_Trees") + val exercisingChoice = testIdsGenerator.testCommandId("Exercising_choice_on_factory_Trees") for { factoryContractId <- findCreatedEventInResultOf( ctx, factoryCreation, templateIds.dummyFactory) transaction <- ctx.testingHelpers.submitAndListenForSingleTreeResultOfCommand( - requestToCallExerciseWithId(ctx, factoryContractId.contractId, s"$exercisingChoice-$runSuffix"), + requestToCallExerciseWithId(ctx, factoryContractId.contractId, testIdsGenerator.testCommandId(exercisingChoice)), getAllContracts) } yield { val exercisedEvent = ctx.testingHelpers.topLevelExercisedIn(transaction).head @@ -248,7 +247,7 @@ abstract class CommandTransactionChecks } "run callable payout and return the right events" in allFixtures { ctx => - val commandId = s"callable_payout_command-$runSuffix" + val commandId = testIdsGenerator.testCommandId("callable_payout_command") val arg = Record( Some(templateIds.callablePayout), List( @@ -292,7 +291,7 @@ abstract class CommandTransactionChecks "expose transactions to non-submitting stakeholders without the commandId" in allFixtures { ctx => val receiver = "receiver" val giver = "giver" - val commandId = s"Testing_if_non-submitting_stakeholder_sees_the_commandId-$runSuffix" + val commandId = testIdsGenerator.testCommandId("Testing_if_non-submitting_stakeholder_sees_the_commandId") val createCmd = createAgreementFactory(ctx, receiver, giver, commandId) ctx.testingHelpers.submitAndListenForSingleResultOfCommand( createCmd, @@ -307,12 +306,12 @@ abstract class CommandTransactionChecks for { agreement <- createAgreement(ctx, "MA1", receiver, giver) triProposal <- ctx.testingHelpers.simpleCreate( - s"MA1proposal-$runSuffix", + testIdsGenerator.testCommandId("MA1proposal"), operator, templateIds.triProposal, triProposalArg) tx <- ctx.testingHelpers.simpleExercise( - s"MA1acceptance-$runSuffix", + testIdsGenerator.testCommandId("MA1acceptance"), giver, templateIds.agreement, agreement.contractId, @@ -337,12 +336,12 @@ abstract class CommandTransactionChecks val triProposalArg = mkTriProposalArg(operator, giver, giver) for { triProposal <- ctx.testingHelpers.simpleCreate( - s"MA2proposal-$runSuffix", + testIdsGenerator.testCommandId("MA2proposal"), operator, templateIds.triProposal, triProposalArg) tx <- ctx.testingHelpers.simpleExercise( - s"MA2acceptance-$runSuffix", + testIdsGenerator.testCommandId("MA2acceptance"), giver, templateIds.triProposal, triProposal.contractId, @@ -365,12 +364,12 @@ abstract class CommandTransactionChecks val triProposalArg = mkTriProposalArg(operator, receiver, giver) for { triProposal <- ctx.testingHelpers.simpleCreate( - s"MA3proposal-$runSuffix", + testIdsGenerator.testCommandId("MA3proposal"), operator, templateIds.triProposal, triProposalArg) assertion <- ctx.testingHelpers.failingExercise( - s"MA3acceptance-$runSuffix", + testIdsGenerator.testCommandId("MA3acceptance"), giver, templateIds.triProposal, triProposal.contractId, @@ -392,14 +391,14 @@ abstract class CommandTransactionChecks "reject exercising a multi-actor choice with too many authorizers" ignore allFixtures { ctx => val triProposalArg = mkTriProposalArg(operator, giver, giver) for { - agreement <- createAgreement(ctx, s"MA4-$runSuffix", receiver, giver) + agreement <- createAgreement(ctx, testIdsGenerator.testCommandId("MA4"), receiver, giver) triProposal <- ctx.testingHelpers.simpleCreate( - s"MA4proposal-$runSuffix", + testIdsGenerator.testCommandId("MA4proposal"), operator, templateIds.triProposal, triProposalArg) assertion <- ctx.testingHelpers.failingExercise( - s"MA4acceptance-$runSuffix", + testIdsGenerator.testCommandId("MA4acceptance"), giver, templateIds.agreement, agreement.contractId, @@ -424,17 +423,17 @@ abstract class CommandTransactionChecks pf("delegate", delegate) ) val delegatedCreate = ctx.testingHelpers.simpleCreate( - s"SDVl3-$runSuffix", + testIdsGenerator.testCommandId("SDVl3"), owner, templateIds.delegated, Record(Some(templateIds.delegated), Seq(pf("owner", owner), RecordField(value = Some(Value(Value.Sum.Text(key))))))) val delegationCreate = ctx.testingHelpers.simpleCreate( - s"SDVl4-$runSuffix", + testIdsGenerator.testCommandId("SDVl4"), owner, templateIds.delegation, Record(Some(templateIds.delegation), odArgs)) val showIdCreate = ctx.testingHelpers.simpleCreate( - s"SDVl5-$runSuffix", + testIdsGenerator.testCommandId("SDVl5"), owner, templateIds.showDelegated, Record(Some(templateIds.showDelegated), odArgs)) @@ -457,7 +456,7 @@ abstract class CommandTransactionChecks ) ) _ <- ctx.testingHelpers.simpleExercise( - s"SDVl6-$runSuffix", + testIdsGenerator.testCommandId("SDVl6"), submitter = owner, template = templateIds.showDelegated, contractId = showIdEv.contractId, @@ -465,7 +464,7 @@ abstract class CommandTransactionChecks arg = Value(Value.Sum.Record(fetchArg)), ) _ <- ctx.testingHelpers.simpleExercise( - s"SDVl7-$runSuffix", + testIdsGenerator.testCommandId("SDVl7"), submitter = delegate, template = templateIds.delegation, contractId = delegationEv.contractId, @@ -473,7 +472,7 @@ abstract class CommandTransactionChecks arg = Value(Value.Sum.Record(fetchArg)), ) _ <- ctx.testingHelpers.simpleExercise( - s"SDVl8-$runSuffix", + testIdsGenerator.testCommandId("SDVl8"), submitter = delegate, template = templateIds.delegation, contractId = delegationEv.contractId, @@ -490,12 +489,12 @@ abstract class CommandTransactionChecks // unique keys. This is not so great though, it'd be better to have a clean environment. val key = s"${UUID.randomUUID.toString}-key" val delegatedCreate = ctx.testingHelpers.simpleCreate( - s"TDVl3-$runSuffix", + testIdsGenerator.testCommandId("TDVl3"), owner, templateIds.delegated, Record(Some(templateIds.delegated), Seq(pf("owner", owner), RecordField(value = Some(Value(Value.Sum.Text(key))))))) val delegationCreate = ctx.testingHelpers.simpleCreate( - s"TDVl4-$runSuffix", + testIdsGenerator.testCommandId("TDVl4"), owner, templateIds.delegation, Record(Some(templateIds.delegation), Seq(pf("owner", owner), pf("delegate", delegate)))) @@ -517,7 +516,7 @@ abstract class CommandTransactionChecks ) ) fetchResult <- ctx.testingHelpers.failingExercise( - s"TDVl5-$runSuffix", + testIdsGenerator.testCommandId("TDVl5"), submitter = delegate, template = templateIds.delegation, contractId = delegationEv.contractId, @@ -527,7 +526,7 @@ abstract class CommandTransactionChecks pattern = "dependency error: couldn't find contract" ) _ <- ctx.testingHelpers.simpleExercise( - s"TDVl6-$runSuffix", + testIdsGenerator.testCommandId("TDVl6"), submitter = delegate, template = templateIds.delegation, contractId = delegationEv.contractId, @@ -538,7 +537,7 @@ abstract class CommandTransactionChecks } "DAML engine returns Unit as argument to Nothing" in allFixtures { ctx => - val commandId = s"Creating_contract_with_a_Nothing_argument-$runSuffix" + val commandId = testIdsGenerator.testCommandId("Creating_contract_with_a_Nothing_argument") val variantId = None @@ -597,7 +596,7 @@ abstract class CommandTransactionChecks f flatMap { _ => for { withObservers <- ctx.testingHelpers.simpleCreateWithListener( - s"Obs1create:$observer-$runSuffix", + testIdsGenerator.testCommandId(s"Obs1create:$observer"), giver, observer, templateIds.withObservers, @@ -619,12 +618,12 @@ abstract class CommandTransactionChecks f flatMap { _ => for { withObservers <- ctx.testingHelpers.simpleCreate( - s"Obs2create:$observer-$runSuffix", + testIdsGenerator.testCommandId(s"Obs2create:$observer"), giver, templateIds.withObservers, withObserversArg) tx <- ctx.testingHelpers.simpleExerciseWithListener( - s"Obs2exercise:$observer-$runSuffix", + testIdsGenerator.testCommandId(s"Obs2exercise:$observer"), giver, observer, templateIds.withObservers, @@ -659,14 +658,14 @@ abstract class CommandTransactionChecks Value(Value.Sum.Record(Record(fields = List(RecordField(value = p.asParty), RecordField(value = s"$keyPrefix-$k".asText))))) for { cid1 <- ctx.testingHelpers.simpleCreate( - s"CK-test-cid1-$runSuffix", + testIdsGenerator.testCommandId("CK-test-cid1"), alice, templateIds.textKey, textKeyRecord(alice, key, List(bob)) ) // duplicate keys are not ok _ <- ctx.testingHelpers.failingCreate( - s"CK-test-duplicate-key-$runSuffix", + testIdsGenerator.testCommandId("CK-test-duplicate-key"), alice, templateIds.textKey, textKeyRecord(alice, key, List(bob)), @@ -675,12 +674,12 @@ abstract class CommandTransactionChecks ) // create handles to perform lookups / fetches aliceTKO <- ctx.testingHelpers.simpleCreate( - s"CK-test-aliceTKO-$runSuffix", + testIdsGenerator.testCommandId("CK-test-aliceTKO"), alice, templateIds.textKeyOperations, Record(fields = List(RecordField(value = alice.asParty)))) bobTKO <- ctx.testingHelpers.simpleCreate( - s"CK-test-bobTKO-$runSuffix", + testIdsGenerator.testCommandId("CK-test-bobTKO"), bob, templateIds.textKeyOperations, Record(fields = List(RecordField(value = bob.asParty))) @@ -690,7 +689,7 @@ abstract class CommandTransactionChecks lookupNone = Value(Value.Sum.Optional(Optional(None))) lookupSome = (cid: String) => Value(Value.Sum.Optional(Optional(Some(cid.asContractId)))) _ <- ctx.testingHelpers.failingExercise( - s"CK-test-bob-unauthorized-1-$runSuffix", + testIdsGenerator.testCommandId("CK-test-bob-unauthorized-1"), bob, templateIds.textKeyOperations, bobTKO.contractId, @@ -704,7 +703,7 @@ abstract class CommandTransactionChecks ) // ..and non-existing ones _ <- ctx.testingHelpers.failingExercise( - s"CK-test-bob-unauthorized-2-$runSuffix", + testIdsGenerator.testCommandId("CK-test-bob-unauthorized-2"), bob, templateIds.textKeyOperations, bobTKO.contractId, @@ -718,7 +717,7 @@ abstract class CommandTransactionChecks "requires authorizers") // successful, authorized lookup _ <- ctx.testingHelpers.simpleExercise( - s"CK-test-alice-lookup-found-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-lookup-found"), alice, templateIds.textKeyOperations, aliceTKO.contractId, @@ -730,7 +729,7 @@ abstract class CommandTransactionChecks RecordField(value = lookupSome(cid1.contractId))))))) // successful fetch _ <- ctx.testingHelpers.simpleExercise( - s"CK-test-alice-fetch-found-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-fetch-found"), alice, templateIds.textKeyOperations, aliceTKO.contractId, @@ -742,7 +741,7 @@ abstract class CommandTransactionChecks RecordField(value = cid1.contractId.asContractId)))))) // failing, authorized lookup _ <- ctx.testingHelpers.simpleExercise( - s"CK-test-alice-lookup-not-found-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-lookup-not-found"), alice, templateIds.textKeyOperations, aliceTKO.contractId, @@ -754,7 +753,7 @@ abstract class CommandTransactionChecks RecordField(value = lookupNone)))))) // failing fetch _ <- ctx.testingHelpers.failingExercise( - s"CK-test-alice-fetch-not-found-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-fetch-not-found"), alice, templateIds.textKeyOperations, aliceTKO.contractId, @@ -769,14 +768,14 @@ abstract class CommandTransactionChecks // now we exercise the contract, thus archiving it, and then verify // that we cannot look it up anymore _ <- ctx.testingHelpers.simpleExercise( - s"CK-test-alice-consume-cid1-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-consume-cid1"), alice, templateIds.textKey, cid1.contractId, "TextKeyChoice", emptyRecordValue) _ <- ctx.testingHelpers.simpleExercise( - s"CK-test-alice-lookup-after-consume-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-lookup-after-consume"), alice, templateIds.textKeyOperations, aliceTKO.contractId, @@ -787,13 +786,13 @@ abstract class CommandTransactionChecks RecordField(value = textKeyKey(alice, key)), RecordField(value = lookupNone)))))) cid2 <- ctx.testingHelpers.simpleCreate( - s"CK-test-cid2-$runSuffix", + testIdsGenerator.testCommandId("CK-test-cid2"), alice, templateIds.textKey, textKeyRecord(alice, "test-key-2", List(bob)) ) _ <- ctx.testingHelpers.simpleExercise( - s"CK-test-alice-consume-and-lookup-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-consume-and-lookup"), alice, templateIds.textKeyOperations, aliceTKO.contractId, @@ -806,7 +805,7 @@ abstract class CommandTransactionChecks ) // failing create when a maintainer is not a signatory _ <- ctx.testingHelpers.failingCreate( - s"CK-test-alice-create-maintainer-not-signatory-$runSuffix", + testIdsGenerator.testCommandId("CK-test-alice-create-maintainer-not-signatory"), alice, templateIds.maintainerNotSignatory, Record(fields = List(RecordField(value = alice.asParty), RecordField(value = bob.asParty))), @@ -821,7 +820,7 @@ abstract class CommandTransactionChecks val alice = "Alice" for { _ <- ctx.testingHelpers.failingCreate( - s"Decimal-scale-$runSuffix", + testIdsGenerator.testCommandId("Decimal-scale"), alice, templateIds.decimalRounding, Record(fields = List(RecordField(value = Some(alice.asParty)), RecordField(value = Some("0.00000000005".asDecimal)))), @@ -829,7 +828,7 @@ abstract class CommandTransactionChecks "Could not read Decimal string" ) _ <- ctx.testingHelpers.failingCreate( - s"Decimal-bounds-positive-$runSuffix", + testIdsGenerator.testCommandId("Decimal-bounds-positive"), alice, templateIds.decimalRounding, Record(fields = List(RecordField(value = Some(alice.asParty)), RecordField(value = Some("10000000000000000000000000000.0000000000".asDecimal)))), @@ -837,7 +836,7 @@ abstract class CommandTransactionChecks "Could not read Decimal string" ) _ <- ctx.testingHelpers.failingCreate( - s"Decimal-bounds-negative-$runSuffix", + testIdsGenerator.testCommandId("Decimal-bounds-negative"), alice, templateIds.decimalRounding, Record(fields = List(RecordField(value = Some(alice.asParty)), RecordField(value = Some("-10000000000000000000000000000.0000000000".asDecimal)))), @@ -865,7 +864,7 @@ abstract class CommandTransactionChecks Value(Value.Sum.Record(Record(fields = List(RecordField(value = p.asParty), RecordField(value = s"$keyPrefix-$k".asText))))) for { _ <- ctx.testingHelpers.failingExerciseByKey( - s"EK-test-alice-exercise-before-create-$runSuffix", + testIdsGenerator.testCommandId("EK-test-alice-exercise-before-create"), alice, templateIds.textKey, textKeyKey(alice, key), @@ -875,7 +874,7 @@ abstract class CommandTransactionChecks "couldn't find key" ) _ <- ctx.testingHelpers.simpleCreate( - s"EK-test-cid1-$runSuffix", + testIdsGenerator.testCommandId("EK-test-cid1"), alice, templateIds.textKey, textKeyRecord(alice, key, List(bob)) @@ -883,14 +882,14 @@ abstract class CommandTransactionChecks // now we exercise by key, thus archiving it, and then verify // that we cannot look it up anymore _ <- ctx.testingHelpers.simpleExerciseByKey( - s"EK-test-alice-exercise-$runSuffix", + testIdsGenerator.testCommandId("EK-test-alice-exercise"), alice, templateIds.textKey, textKeyKey(alice, key), "TextKeyChoice", emptyRecordValue) _ <- ctx.testingHelpers.failingExerciseByKey( - s"EK-test-alice-exercise-consumed-$runSuffix", + testIdsGenerator.testCommandId("EK-test-alice-exercise-consumed"), alice, templateIds.textKey, textKeyKey(alice, key), @@ -919,7 +918,7 @@ abstract class CommandTransactionChecks .update(_.commands.ledgerId := context.ledgerId.unwrap) "process valid commands successfully" in allFixtures{ c => - val cmdId = s"valid-create-and-exercise-cmd-$runSuffix" + val cmdId = testIdsGenerator.testCommandId("valid-create-and-exercise-cmd") val request = newRequest(c, validCreateAndExercise) .update(_.commands.commandId := cmdId) @@ -959,7 +958,7 @@ abstract class CommandTransactionChecks "fail for invalid create arguments" in allFixtures{ implicit c => val createAndExercise = validCreateAndExercise.copy(createArguments = Some(Record())) val request = newRequest(c, createAndExercise) - .update(_.commands.commandId := s"fail-for-invalid-create-args-$runSuffix") + .update(_.commands.commandId := testIdsGenerator.testCommandId("fail-for-invalid-create-args")) val response = submitCommand(c, request) response.map(_.getStatus should have('code (Code.INVALID_ARGUMENT.value))) @@ -970,7 +969,7 @@ abstract class CommandTransactionChecks validCreateAndExercise.copy(choiceArgument = Some(Value(Value.Sum.Bool(false)))) val request = newRequest(c, createAndExercise) .update(_.commands.commands := Seq[Command](Command(Command.Command.CreateAndExercise(createAndExercise)))) - .update(_.commands.commandId := s"fail-for-invalid-choice-args-$runSuffix") + .update(_.commands.commandId := testIdsGenerator.testCommandId("fail-for-invalid-choice-args")) val response = submitCommand(c, request) response.map(_.getStatus should have('code (Code.INVALID_ARGUMENT.value))) @@ -981,7 +980,7 @@ abstract class CommandTransactionChecks val request = newRequest(c, createAndExercise) .update(_.commands.commands := Seq[Command](Command(Command.Command.CreateAndExercise(createAndExercise)))) - .update(_.commands.commandId := s"fail-for-invalid-choice-$runSuffix") + .update(_.commands.commandId := testIdsGenerator.testCommandId("fail-for-invalid-choice")) val response = submitCommand(c, request) response.map(_.getStatus should have('code (Code.INVALID_ARGUMENT.value))) @@ -1044,12 +1043,12 @@ abstract class CommandTransactionChecks ).asRecordOf(templateIds.agreementFactory) for { agreementFactory <- ctx.testingHelpers.simpleCreate( - s"$commandId-factory-$runSuffix", + testIdsGenerator.testCommandId(s"$commandId-factory"), giver, templateIds.agreementFactory, agreementFactoryArg) tx <- ctx.testingHelpers.simpleExercise( - s"$commandId-agreement-$runSuffix", + testIdsGenerator.testCommandId(s"$commandId-agreement"), receiver, templateIds.agreementFactory, agreementFactory.contractId, @@ -1123,7 +1122,7 @@ abstract class CommandTransactionChecks val command: SubmitRequest = createParamShowcaseWith( ctx, - s"Creating_contract_with_a_multitude_of_param_types_for_exercising__$choice#$lbl-$runSuffix", + testIdsGenerator.testCommandId(s"Creating_contract_with_a_multitude_of_param_types_for_exercising__$choice#$lbl"), paramShowcaseArgs) for { tx <- ctx.testingHelpers.submitAndListenForSingleResultOfCommand(command, getAllContracts) @@ -1135,7 +1134,7 @@ abstract class CommandTransactionChecks choice, exerciseArg).wrap tx <- ctx.testingHelpers.submitAndListenForSingleTreeResultOfCommand( - ctx.testingHelpers.submitRequestWithId(s"Exercising_with_a_multitiude_of_params__$choice#$lbl-$runSuffix") + ctx.testingHelpers.submitRequestWithId(testIdsGenerator.testCommandId(s"Exercising_with_a_multitiude_of_params__$choice#$lbl")) .update(_.commands.update(_.commands := List(exercise))), getAllContracts, true diff --git a/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/apitesting/TestIdsGenerator.scala b/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/apitesting/TestIdsGenerator.scala new file mode 100644 index 000000000000..fe3c29f0831d --- /dev/null +++ b/ledger/ledger-api-integration-tests/src/test/lib/scala/com/digitalasset/platform/apitesting/TestIdsGenerator.scala @@ -0,0 +1,26 @@ +// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.digitalasset.platform.apitesting + +import com.digitalasset.platform.PlatformApplications + +import scala.util.Random + +/** + * Provides a mechanism to randomize various identifiers used in testing per run of a process. + * + * It enables Ledger API Test Tool to be run against a persistent Ledger API endpoint repeatedly by avoiding + * duplication of identifiers. + */ +class TestIdsGenerator(config: PlatformApplications.Config) { + lazy val runSuffix = Random.alphanumeric.take(10).mkString + lazy val runCommandSuffix = if (config.uniqueCommandIdentifiers) "-" + runSuffix else "" + // Using runCommandSuffix, since there does not seem to be a need to treat workflow ids differently than command ids. + // Yet lets wrap those identifiers into an appropriate function so we could do it in the future. + lazy val runWorkflowSuffix = runCommandSuffix + lazy val runPartySuffix = if (config.uniquePartyIdentifiers) "-" + runSuffix else "" + def testPartyName(partyText: String) = partyText + runPartySuffix + def testCommandId(commandId: String) = commandId + runCommandSuffix + def testWorkflowId(workflowId: String) = workflowId + runWorkflowSuffix +} diff --git a/ledger/ledger-api-integration-tests/src/test/semanticsuite/scala/com/digitalasset/platform/semantictest/SandboxSemanticTestsLfRunner.scala b/ledger/ledger-api-integration-tests/src/test/semanticsuite/scala/com/digitalasset/platform/semantictest/SandboxSemanticTestsLfRunner.scala index cde83ed2937b..eb5f6540b727 100644 --- a/ledger/ledger-api-integration-tests/src/test/semanticsuite/scala/com/digitalasset/platform/semantictest/SandboxSemanticTestsLfRunner.scala +++ b/ledger/ledger-api-integration-tests/src/test/semanticsuite/scala/com/digitalasset/platform/semantictest/SandboxSemanticTestsLfRunner.scala @@ -14,13 +14,11 @@ import com.digitalasset.ledger.api.testing.utils.{ AkkaBeforeAndAfterAll, SuiteResourceManagementAroundAll } -import com.digitalasset.platform.apitesting.MultiLedgerFixture +import com.digitalasset.platform.apitesting.{MultiLedgerFixture, TestIdsGenerator} import com.digitalasset.platform.services.time.TimeProviderType import org.scalatest.concurrent.ScalaFutures import org.scalatest.{AsyncWordSpec, Matchers} -import scala.util.Random - class SandboxSemanticTestsLfRunner extends AsyncWordSpec with Matchers @@ -36,6 +34,7 @@ class SandboxSemanticTestsLfRunner Config.default .withDarFile(defaultDarFile.toPath) .withTimeProvider(TimeProviderType.StaticAllowBackwards) + protected val testIdsGenerator = new TestIdsGenerator(config) lazy val (mainPkgId, packages, darFile) = { val df = config.darFiles.head.toFile @@ -47,13 +46,9 @@ class SandboxSemanticTestsLfRunner } s"a ledger launched with $darFile" should { - val runSuffix = "-" + Random.alphanumeric.take(10).mkString - val partyNameMangler = - (partyText: String) => partyText + runSuffix + Random.alphanumeric.take(10).mkString - val commandIdMangler: ((QualifiedName, Int, L.ScenarioNodeId) => String) = - (scenario, stepId, nodeId) => { - s"ledger-api-test-tool-$scenario-$stepId-$nodeId-$runSuffix" - } + val scenarioCommandIdMangler: ((QualifiedName, Int, L.ScenarioNodeId) => String) = + (scenario, stepId, nodeId) => + testIdsGenerator.testCommandId(s"ledger-api-test-tool-$scenario-$stepId-${nodeId}") for { (pkgId, names) <- SemanticTester.scenarios(Map(mainPkgId -> packages(mainPkgId))) // we only care about the main pkg name <- names @@ -70,8 +65,8 @@ class SandboxSemanticTestsLfRunner commandSubmissionTtlScaleFactor = config.commandSubmissionTtlScaleFactor), pkgId, packages, - partyNameMangler, - commandIdMangler + testIdsGenerator.testPartyName, + scenarioCommandIdMangler ).testScenario(name) } yield succeed } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Cli.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Cli.scala index 59ee45311e88..42975232617f 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Cli.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Cli.scala @@ -78,6 +78,20 @@ object Cli { .action((_, c) => c.copy(verbose = true)) .text("Prints full stacktraces on failures.") + opt[Unit]("stable-party-identifiers") + .abbr("sp") + .action((_, c) => c.copy(uniquePartyIdentifiers = false)) + .text("""Use the same party identifiers for each run. By default + |those are randomized for each execution of the tool to ensure that + |the tests are not being failed by command and party deduplication mechanisms.""".stripMargin) + + opt[Unit]("stable-command-identifiers") + .abbr("sc") + .action((_, c) => c.copy(uniqueCommandIdentifiers = false)) + .text("""Use the same command identifiers for each run. By default + |those are randomized for each execution of the tool to ensure that + |the tests are not being failed by command and party deduplication mechanisms.""".stripMargin) + opt[Unit]("must-fail") .action((_, c) => c.copy(mustFail = true)) .text("""Reverse success status logic of the tool. Use this flag if you expect one or diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Config.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Config.scala index 299354a5ade2..7d0e228b4001 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Config.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Config.scala @@ -20,7 +20,9 @@ final case class Config( excluded: Set[String], included: Set[String], listTests: Boolean, - allTests: Boolean + allTests: Boolean, + uniquePartyIdentifiers: Boolean, + uniqueCommandIdentifiers: Boolean ) object Config { @@ -37,6 +39,8 @@ object Config { excluded = Set.empty, included = Set.empty, listTests = false, - allTests = false + allTests = false, + uniquePartyIdentifiers = true, + uniqueCommandIdentifiers = true, ) } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/LedgerApiTestTool.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/LedgerApiTestTool.scala index b04dfc6b3a6a..15503bed4aa3 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/LedgerApiTestTool.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/LedgerApiTestTool.scala @@ -45,6 +45,8 @@ object LedgerApiTestTool { .withTimeProvider(TimeProviderType.WallClock) .withLedgerIdMode(LedgerIdMode.Dynamic()) .withCommandSubmissionTtlScaleFactor(toolConfig.commandSubmissionTtlScaleFactor) + .withUniquePartyIdentifiers(toolConfig.uniquePartyIdentifiers) + .withUniqueCommandIdentifiers(toolConfig.uniqueCommandIdentifiers) .withRemoteApiEndpoint( RemoteApiEndpoint.default .withHost(toolConfig.host) @@ -127,16 +129,11 @@ object LedgerApiTestTool { name => new SandboxSemanticTestsLfRunner { override def suiteName: String = name - override def actorSystemName = s"${name}TestToolActorSystem" - override def fixtureIdsEnabled: Set[LedgerBackend] = Set(LedgerBackend.RemoteApiProxy) - override implicit lazy val patienceConfig: PatienceConfig = PatienceConfig(Span(60L, Seconds)) - override def spanScaleFactor: Double = toolConfig.timeoutScaleFactor - override protected def config: Config = commonConfig.withDarFile(resourceAsFile(semanticTestsResource)) } diff --git a/unreleased.rst b/unreleased.rst index 10000089d531..f06e88b50076 100644 --- a/unreleased.rst +++ b/unreleased.rst @@ -10,3 +10,8 @@ HEAD — ongoing -------------- - [Sandbox] Added `--log-level` command line flag. +- [Ledger API] Added new CLI flags ``--stable-party-identifiers`` and + ``--stable-command-identifiers`` to the :doc:`Ledger API Test Tool + ` to allow disabling randomization of party + and command identifiers. It is useful for testing of ledgers which are + configured with a predefined static set of parties.