From 17d20bc5aabc7c9c393c44dc6b9c2d707c2e25f2 Mon Sep 17 00:00:00 2001 From: Nicu Reut Date: Fri, 15 Oct 2021 17:24:06 +0200 Subject: [PATCH 1/5] ledger-api-test-tool: Add command line argument --static-time which makes the test tool aware that the ledger is running in static time For command deduplication conformance tests this allows us to forward the time so that the tests can run in static time mode as well CHANGELOG_BEGIN CHANGELOG_END --- .../com/daml/ledger/api/testtool/Cli.scala | 6 ++++ .../com/daml/ledger/api/testtool/Config.scala | 2 ++ .../api/testtool/LedgerApiTestTool.scala | 1 + .../CommandDeduplicationBase.scala | 17 +++++---- .../KVCommandDeduplicationBase.scala | 36 ++++++++++++++++--- .../participant/ParticipantTestContext.scala | 14 +++++++- .../AppendOnlyKVCommandDeduplicationIT.scala | 3 +- .../suites/CommandDeduplicationIT.scala | 11 +++--- .../suites/KVCommandDeduplicationIT.scala | 7 ++-- .../ledger/api/testtool/tests/Defaults.scala | 2 ++ .../ledger/api/testtool/tests/Tests.scala | 9 +++-- ledger/sandbox/BUILD.bazel | 7 ++++ 12 files changed, 91 insertions(+), 24 deletions(-) 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 bf63b16dd83c..433311bd2a2c 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 @@ -255,6 +255,12 @@ object Cli { success ) + opt[Unit]("static-time") + .optional() + .hidden() + .action((_, c) => c.copy(staticTime = true)) + .text("The ledger is run using static time") + help("help").text("Prints this usage text") } 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 810e6e2db77e..6f2202cfb195 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 @@ -31,6 +31,7 @@ final case class Config( partyAllocation: PartyAllocationConfiguration, ledgerClockGranularity: FiniteDuration, uploadDars: Boolean, + staticTime: Boolean, ) { def withTlsConfig(modify: TlsConfiguration => TlsConfiguration): Config = { val base = tlsConfig.getOrElse(TlsConfiguration.Empty) @@ -60,5 +61,6 @@ object Config { partyAllocation = PartyAllocationConfiguration.ClosedWorldWaitingForAllParticipants, ledgerClockGranularity = tests.Defaults.LedgerClockGranularity, uploadDars = true, + staticTime = false, ) } 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 4b3b8b1dc4c4..eac1d46ae444 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 @@ -96,6 +96,7 @@ object LedgerApiTestTool { val optionalTests: Vector[LedgerTestSuite] = Tests.optional( timeoutScaleFactor = config.timeoutScaleFactor, ledgerClockGranularity = config.ledgerClockGranularity, + staticTime = config.staticTime, ) val visibleTests: Vector[LedgerTestSuite] = defaultTests ++ optionalTests val allTests: Vector[LedgerTestSuite] = visibleTests ++ Tests.retired diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala index 010e6462a2e3..bccf5a618a49 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala @@ -19,7 +19,6 @@ import com.daml.ledger.api.v1.ledger_offset.LedgerOffset import com.daml.ledger.client.binding.Primitive.Party import com.daml.ledger.test.model.DA.Types.Tuple2 import com.daml.ledger.test.model.Test.{Dummy, DummyWithAnnotation, TextKey, TextKeyOperations} -import com.daml.timer.Delayed import io.grpc.Status.Code import scala.annotation.nowarn @@ -40,9 +39,9 @@ private[testtool] abstract class CommandDeduplicationBase( def deduplicationFeatures: DeduplicationFeatures - protected def runGivenDeduplicationWait( + protected def runWithDelay( participants: Seq[ParticipantTestContext] - )(test: Duration => Future[Unit])(implicit + )(test: (() => Future[Unit]) => Future[Unit])(implicit ec: ExecutionContext ): Future[Unit] @@ -62,7 +61,7 @@ private[testtool] abstract class CommandDeduplicationBase( deduplicationDuration.asProtobuf ) ) - runGivenDeduplicationWait(configuredParticipants) { deduplicationWait => + runWithDelay(configuredParticipants) { delay => for { // Submit command (first deduplication window) // Note: the second submit() in this block is deduplicated and thus rejected by the ledger API server, @@ -70,7 +69,7 @@ private[testtool] abstract class CommandDeduplicationBase( completion1 <- submitRequestAndAssertCompletionAccepted(ledger)(request, party) _ <- submitRequestAndAssertDeduplication(ledger)(request, party) // Wait until the end of first deduplication window - _ <- Delayed.by(deduplicationWait)(()) + _ <- delay() // Submit command (second deduplication window) // Note: the deduplication window is guaranteed to have passed on both @@ -169,14 +168,14 @@ private[testtool] abstract class CommandDeduplicationBase( .update( _.commands.deduplicationTime := deduplicationDuration.asProtobuf ) - runGivenDeduplicationWait(configuredParticipants) { deduplicationWait => + runWithDelay(configuredParticipants) { delay => for { // Submit command (first deduplication window) _ <- ledger.submitAndWait(request) _ <- submitAndWaitRequestAndAssertDeduplication(ledger)(request) // Wait until the end of first deduplication window - _ <- Delayed.by(deduplicationWait)(()) + _ <- delay() // Submit command (second deduplication window) _ <- ledger.submitAndWait(request) @@ -206,7 +205,7 @@ private[testtool] abstract class CommandDeduplicationBase( case currentElement :: tail => currentElement.flatMap(value => generateVariations(tail).map(value :: _)) } - runGivenDeduplicationWait(configuredParticipants) { deduplicationWait => + runWithDelay(configuredParticipants) { delay => { val numberOfCalls = 4 Future // cover all the different generated variations of submit and submitAndWait @@ -237,7 +236,7 @@ private[testtool] abstract class CommandDeduplicationBase( _ <- submitAndAssertDeduplicated(secondCall) // Wait until the end of first deduplication window - _ <- Delayed.by(deduplicationWait)(()) + _ <- delay() // Submit command (second deduplication window) _ <- submitAndAssertAccepted(thirdCall) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala index 4a2b71afb76c..43498c1f57fd 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala @@ -30,6 +30,7 @@ import scala.util.control.NonFatal abstract class KVCommandDeduplicationBase( timeoutScaleFactor: Double, ledgerTimeInterval: FiniteDuration, + staticTime: Boolean, ) extends CommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval) { private[this] val logger = LoggerFactory.getLogger(getClass.getName) @@ -53,7 +54,7 @@ abstract class KVCommandDeduplicationBase( // Validate committer deduplication duplicateCompletion <- submitRequestAndAssertAsyncDeduplication(ledger)(request, party) // Wait for the end of committer deduplication - _ <- Delayed.by(maxDeduplicationDuration.plus(minSkew))(()) + _ <- delay(ledger, maxDeduplicationDuration, minSkew) // Deduplication has finished completion2 <- submitRequestAndAssertCompletionAccepted(ledger)(request, party) // Inspect created contracts @@ -98,14 +99,39 @@ abstract class KVCommandDeduplicationBase( } ) - protected override def runGivenDeduplicationWait( + protected override def runWithDelay( participants: Seq[ParticipantTestContext] - )(test: Duration => Future[Unit])(implicit ec: ExecutionContext): Future[Unit] = { + )(test: (() => Future[Unit]) => Future[Unit])(implicit ec: ExecutionContext): Future[Unit] = { runWithConfig(participants) { case (maxDeduplicationDuration, minSkew) => - test(maxDeduplicationDuration.plus(minSkew).plus(ledgerWaitInterval)) + val anyParticipant = participants.head + test(() => delay(anyParticipant, maxDeduplicationDuration, minSkew)) } } + private def delay( + ledger: ParticipantTestContext, + maxDeduplicationDuration: Duration, + minSkew: Duration, + )(implicit ec: ExecutionContext) = { + val committerDeduplicationWindow = + maxDeduplicationDuration.plus(minSkew).plus(ledgerWaitInterval) + if (staticTime) { + forwardTimeWithDuration(ledger, committerDeduplicationWindow) + } else { + Delayed.by(committerDeduplicationWindow)(()) + } + } + + private def forwardTimeWithDuration(ledger: ParticipantTestContext, duration: Duration)(implicit + ec: ExecutionContext + ) = { + ledger + .time() + .flatMap(currentTime => { + ledger.setTime(currentTime, currentTime.plusMillis(duration.toMillis)) + }) + } + private def runWithConfig( participants: Seq[ParticipantTestContext] )( @@ -184,7 +210,7 @@ abstract class KVCommandDeduplicationBase( }) } - /** Try to run the [[update]] sequentially on all the participants. + /** Try to run the update sequentially on all the participants. * The function returns the first success or the last failure of the update operation. * Useful for updating the configuration when we don't know which participant can update the config, * as only the first one that submitted the initial configuration has the permissions to do so. diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/ParticipantTestContext.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/ParticipantTestContext.scala index 4371a3baf1f8..9c502837b618 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/ParticipantTestContext.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/ParticipantTestContext.scala @@ -4,6 +4,7 @@ package com.daml.ledger.api.testtool.infrastructure.participant import java.time.{Clock, Instant} + import com.daml.ledger.api.refinements.ApiTypes.TemplateId import com.daml.ledger.api.testtool.infrastructure.Eventually.eventually import com.daml.ledger.api.testtool.infrastructure.ProtobufConverters._ @@ -58,7 +59,7 @@ import com.daml.ledger.api.v1.ledger_configuration_service.{ } import com.daml.ledger.api.v1.ledger_offset.LedgerOffset import com.daml.ledger.api.v1.package_service._ -import com.daml.ledger.api.v1.testing.time_service.{GetTimeRequest, GetTimeResponse} +import com.daml.ledger.api.v1.testing.time_service.{GetTimeRequest, GetTimeResponse, SetTimeRequest} import com.daml.ledger.api.v1.transaction.{Transaction, TransactionTree} import com.daml.ledger.api.v1.transaction_filter.{Filters, InclusiveFilters, TransactionFilter} import com.daml.ledger.api.v1.transaction_service.{ @@ -172,6 +173,17 @@ private[testtool] final class ParticipantTestContext private[participant] ( Clock.systemUTC().instant() } + def setTime(currentTime: Instant, newTime: Instant): Future[Unit] = + services.time + .setTime( + SetTimeRequest( + ledgerId = ledgerId, + currentTime = Some(currentTime.asProtobuf), + newTime = Some(newTime.asProtobuf), + ) + ) + .map(_ => ()) + def listKnownPackages(): Future[Seq[PackageDetails]] = services.packageManagement .listKnownPackages(new ListKnownPackagesRequest) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/AppendOnlyKVCommandDeduplicationIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/AppendOnlyKVCommandDeduplicationIT.scala index aa22dfdb559e..b409175408ba 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/AppendOnlyKVCommandDeduplicationIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/AppendOnlyKVCommandDeduplicationIT.scala @@ -17,7 +17,8 @@ import scala.concurrent.duration.FiniteDuration class AppendOnlyKVCommandDeduplicationIT( timeoutScaleFactor: Double, ledgerTimeInterval: FiniteDuration, -) extends KVCommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval) { + staticTime: Boolean, +) extends KVCommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval, staticTime) { override protected def testNamingPrefix: String = "AppendOnlyKVCommandDeduplication" diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala index 314f4443ac9e..c1d6a9ffe54e 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala @@ -6,8 +6,9 @@ package com.daml.ledger.api.testtool.suites import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase.DeduplicationFeatures import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext +import com.daml.timer.Delayed -import scala.concurrent.duration.{Duration, FiniteDuration} +import scala.concurrent.duration.FiniteDuration import scala.concurrent.{ExecutionContext, Future} /** Command deduplication tests for participant side deduplication @@ -16,10 +17,12 @@ import scala.concurrent.{ExecutionContext, Future} final class CommandDeduplicationIT(timeoutScaleFactor: Double, ledgerTimeInterval: FiniteDuration) extends CommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval) { - override def runGivenDeduplicationWait( + override def runWithDelay( participants: Seq[ParticipantTestContext] - )(test: Duration => Future[Unit])(implicit ec: ExecutionContext): Future[Unit] = { - test(defaultDeduplicationWindowWait) + )(test: (() => Future[Unit]) => Future[Unit])(implicit + ec: ExecutionContext + ): Future[Unit] = { + test(() => Delayed.by(defaultDeduplicationWindowWait)(())) } override def testNamingPrefix: String = "ParticipantCommandDeduplication" diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/KVCommandDeduplicationIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/KVCommandDeduplicationIT.scala index 11388a536675..48cd1fa26376 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/KVCommandDeduplicationIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/KVCommandDeduplicationIT.scala @@ -16,8 +16,11 @@ import scala.concurrent.duration.FiniteDuration * The committer side deduplication period adds `minSkew` to the participant-side one, so we have to account for that as well. * If updating the time model fails then the tests will assume a `minSkew` of 1 second. */ -class KVCommandDeduplicationIT(timeoutScaleFactor: Double, ledgerTimeInterval: FiniteDuration) - extends KVCommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval) { +class KVCommandDeduplicationIT( + timeoutScaleFactor: Double, + ledgerTimeInterval: FiniteDuration, + staticTime: Boolean, +) extends KVCommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval, staticTime) { override def testNamingPrefix: String = "KVCommandDeduplication" diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Defaults.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Defaults.scala index de211591dab1..6ac7a7782e75 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Defaults.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Defaults.scala @@ -15,4 +15,6 @@ object Defaults { // We therefore limit the maximum number of concurrent tests, to avoid overwhelming the ledger. val ConcurrentRuns: Int = sys.runtime.availableProcessors min 4 + val StaticTime: Boolean = false + } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala index 535237d14751..7fcbe686408f 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala @@ -64,14 +64,19 @@ object Tests { def optional( timeoutScaleFactor: Double = Defaults.TimeoutScaleFactor, ledgerClockGranularity: FiniteDuration = Defaults.LedgerClockGranularity, + staticTime: Boolean = Defaults.StaticTime, ): Vector[LedgerTestSuite] = Vector( new AppendOnlyCompletionDeduplicationInfoIT(CommandService), new AppendOnlyCompletionDeduplicationInfoIT(CommandSubmissionService), - new AppendOnlyKVCommandDeduplicationIT(timeoutScaleFactor, ledgerClockGranularity), + new AppendOnlyKVCommandDeduplicationIT( + timeoutScaleFactor, + ledgerClockGranularity, + staticTime, + ), new AppendOnlyCommandDeduplicationParallelIT, new ContractIdIT, - new KVCommandDeduplicationIT(timeoutScaleFactor, ledgerClockGranularity), + new KVCommandDeduplicationIT(timeoutScaleFactor, ledgerClockGranularity, staticTime), new MultiPartySubmissionIT, new ParticipantPruningIT, new MonotonicRecordTimeIT, diff --git a/ledger/sandbox/BUILD.bazel b/ledger/sandbox/BUILD.bazel index 1c5ce6cc8c93..24446a9b64af 100644 --- a/ledger/sandbox/BUILD.bazel +++ b/ledger/sandbox/BUILD.bazel @@ -323,10 +323,17 @@ server_conformance_test( name = "next-conformance-test-static-time", server_args = [ "--static-time", + "--max-deduplication-duration=PT5S", ] + APPEND_ONLY_ARGS, servers = NEXT_SERVERS, test_tool_args = [ + "--static-time", "--open-world", + "--additional=AppendOnlyCommandDeduplicationParallelIT", + "--additional=AppendOnlyCompletionDeduplicationInfoITCommandService", + "--additional=AppendOnlyCompletionDeduplicationInfoITCommandSubmissionService", + "--additional=AppendOnlyKVCommandDeduplicationIT", + "--exclude=AppendOnlyKVCommandDeduplicationIT:AppendOnlyKVCommandDeduplicationSimpleDeduplicationMixedClients", # we run calls in parallel and with static time we advance the time, therefore this cannot be run in static time "--exclude=CommandDeduplicationIT", # It's a KV ledger so it needs the KV variant "--exclude=ClosedWorldIT", ], From 12f1fee57ad990fed396687512abb2214ca82d1e Mon Sep 17 00:00:00 2001 From: nicu-da Date: Fri, 15 Oct 2021 09:08:16 -0700 Subject: [PATCH 2/5] Update ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/Cli.scala Co-authored-by: Samir Talwar --- .../src/main/scala/com/daml/ledger/api/testtool/Cli.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 433311bd2a2c..e9d1f544a324 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 @@ -259,7 +259,7 @@ object Cli { .optional() .hidden() .action((_, c) => c.copy(staticTime = true)) - .text("The ledger is run using static time") + .text("Must be enabled if the ledger is using static time") help("help").text("Prints this usage text") } From 2ad219ee4a9dc3d5366ba07c0d97388b163d6f22 Mon Sep 17 00:00:00 2001 From: Nicu Reut Date: Fri, 15 Oct 2021 18:15:32 +0200 Subject: [PATCH 3/5] Do not run conformance test that cannot run in static time --- .../main/scala/com/daml/ledger/api/testtool/Config.scala | 2 +- .../com/daml/ledger/api/testtool/LedgerApiTestTool.scala | 1 + .../deduplication/CommandDeduplicationBase.scala | 6 ++++-- .../deduplication/KVCommandDeduplicationBase.scala | 2 +- .../api/testtool/suites/CommandDeduplicationIT.scala | 7 +++++-- .../scala/com/daml/ledger/api/testtool/tests/Tests.scala | 3 ++- ledger/sandbox/BUILD.bazel | 1 - 7 files changed, 14 insertions(+), 8 deletions(-) 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 6f2202cfb195..25c79676cac3 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 @@ -61,6 +61,6 @@ object Config { partyAllocation = PartyAllocationConfiguration.ClosedWorldWaitingForAllParticipants, ledgerClockGranularity = tests.Defaults.LedgerClockGranularity, uploadDars = true, - staticTime = false, + staticTime = tests.Defaults.StaticTime, ) } 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 eac1d46ae444..327e89c4ca92 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 @@ -92,6 +92,7 @@ object LedgerApiTestTool { val defaultTests: Vector[LedgerTestSuite] = Tests.default( timeoutScaleFactor = config.timeoutScaleFactor, ledgerClockGranularity = config.ledgerClockGranularity, + staticTime = config.staticTime, ) val optionalTests: Vector[LedgerTestSuite] = Tests.optional( timeoutScaleFactor = config.timeoutScaleFactor, diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala index bccf5a618a49..dc5a43343d0a 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala @@ -30,6 +30,7 @@ import scala.util.{Failure, Success} private[testtool] abstract class CommandDeduplicationBase( timeoutScaleFactor: Double, ledgerTimeInterval: FiniteDuration, + staticTime: Boolean, ) extends LedgerTestSuite { val deduplicationDuration: FiniteDuration = scaledDuration(3.seconds) @@ -191,8 +192,9 @@ private[testtool] abstract class CommandDeduplicationBase( } ) - // Without the submission id we cannot assert the received completions for parallel submissions - if (deduplicationFeatures.appendOnlySchema) + // appendOnlySchema - without the submission id we cannot assert the received completions for parallel submissions + // staticTime - we run calls in parallel and with static time we advance the time, therefore this cannot be run in static time + if (deduplicationFeatures.appendOnlySchema && !staticTime) testGivenAllParticipants( s"${testNamingPrefix}SimpleDeduplicationMixedClients", "Deduplicate commands within the deduplication time window using the command client and the command submission client", diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala index 43498c1f57fd..317fe8bb2a09 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala @@ -31,7 +31,7 @@ abstract class KVCommandDeduplicationBase( timeoutScaleFactor: Double, ledgerTimeInterval: FiniteDuration, staticTime: Boolean, -) extends CommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval) { +) extends CommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval, staticTime) { private[this] val logger = LoggerFactory.getLogger(getClass.getName) testGivenAllParticipants( diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala index c1d6a9ffe54e..e4c0ca2036b8 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala @@ -14,8 +14,11 @@ import scala.concurrent.{ExecutionContext, Future} /** Command deduplication tests for participant side deduplication * Should be disabled for ledgers that have committer side deduplication enabled (KV) */ -final class CommandDeduplicationIT(timeoutScaleFactor: Double, ledgerTimeInterval: FiniteDuration) - extends CommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval) { +final class CommandDeduplicationIT( + timeoutScaleFactor: Double, + ledgerTimeInterval: FiniteDuration, + staticTime: Boolean, +) extends CommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval, staticTime) { override def runWithDelay( participants: Seq[ParticipantTestContext] diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala index 7fcbe686408f..c5f780301177 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala @@ -26,11 +26,12 @@ object Tests { def default( timeoutScaleFactor: Double = Defaults.TimeoutScaleFactor, ledgerClockGranularity: FiniteDuration = Defaults.LedgerClockGranularity, + staticTime: Boolean = Defaults.StaticTime, ): Vector[LedgerTestSuite] = Vector( new ActiveContractsServiceIT, new ClosedWorldIT, - new CommandDeduplicationIT(timeoutScaleFactor, ledgerClockGranularity), + new CommandDeduplicationIT(timeoutScaleFactor, ledgerClockGranularity, staticTime), new CommandServiceIT, new CommandSubmissionCompletionIT, new ConfigManagementServiceIT, diff --git a/ledger/sandbox/BUILD.bazel b/ledger/sandbox/BUILD.bazel index 24446a9b64af..b1dfa0de503e 100644 --- a/ledger/sandbox/BUILD.bazel +++ b/ledger/sandbox/BUILD.bazel @@ -333,7 +333,6 @@ server_conformance_test( "--additional=AppendOnlyCompletionDeduplicationInfoITCommandService", "--additional=AppendOnlyCompletionDeduplicationInfoITCommandSubmissionService", "--additional=AppendOnlyKVCommandDeduplicationIT", - "--exclude=AppendOnlyKVCommandDeduplicationIT:AppendOnlyKVCommandDeduplicationSimpleDeduplicationMixedClients", # we run calls in parallel and with static time we advance the time, therefore this cannot be run in static time "--exclude=CommandDeduplicationIT", # It's a KV ledger so it needs the KV variant "--exclude=ClosedWorldIT", ], From 55f8057cefd95140df2153af479f7faa31772bf2 Mon Sep 17 00:00:00 2001 From: Nicu Reut Date: Fri, 15 Oct 2021 18:16:14 +0200 Subject: [PATCH 4/5] Remove hidden from static time flag for ledger api test tool --- .../src/main/scala/com/daml/ledger/api/testtool/Cli.scala | 1 - 1 file changed, 1 deletion(-) 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 e9d1f544a324..94dbf41a136c 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 @@ -257,7 +257,6 @@ object Cli { opt[Unit]("static-time") .optional() - .hidden() .action((_, c) => c.copy(staticTime = true)) .text("Must be enabled if the ledger is using static time") From 970f494d52c08f73346b7a556c91b1049a62f93b Mon Sep 17 00:00:00 2001 From: Samir Talwar Date: Mon, 18 Oct 2021 14:24:18 +0200 Subject: [PATCH 5/5] ledger-api-test-tool: Clarify parts of the deduplication tests. Co-authored-by: Fabio Tudone --- .../CommandDeduplicationBase.scala | 38 +++++++++++-------- .../KVCommandDeduplicationBase.scala | 18 +++++---- .../suites/CommandDeduplicationIT.scala | 16 ++++---- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala index dc5a43343d0a..17b48485f8a8 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala @@ -6,10 +6,10 @@ package com.daml.ledger.api.testtool.infrastructure.deduplication import java.util.UUID import com.daml.ledger.api.testtool.infrastructure.Allocation._ -import com.daml.ledger.api.testtool.infrastructure.Assertions.{assertGrpcError, assertSingleton, _} +import com.daml.ledger.api.testtool.infrastructure.Assertions._ import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite import com.daml.ledger.api.testtool.infrastructure.ProtobufConverters._ -import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase.DeduplicationFeatures +import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase._ import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext import com.daml.ledger.api.v1.command_service.SubmitAndWaitRequest import com.daml.ledger.api.v1.command_submission_service.SubmitRequest @@ -40,11 +40,11 @@ private[testtool] abstract class CommandDeduplicationBase( def deduplicationFeatures: DeduplicationFeatures - protected def runWithDelay( + protected def runWithDeduplicationDelay( participants: Seq[ParticipantTestContext] - )(test: (() => Future[Unit]) => Future[Unit])(implicit - ec: ExecutionContext - ): Future[Unit] + )( + testWithDelayMechanism: DelayMechanism => Future[Unit] + )(implicit ec: ExecutionContext): Future[Unit] protected def testNamingPrefix: String @@ -58,11 +58,10 @@ private[testtool] abstract class CommandDeduplicationBase( val request = ledger .submitRequest(party, DummyWithAnnotation(party, "Duplicate command").create.command) .update( - _.commands.deduplicationPeriod := DeduplicationPeriod.DeduplicationTime( - deduplicationDuration.asProtobuf - ) + _.commands.deduplicationPeriod := + DeduplicationPeriod.DeduplicationTime(deduplicationDuration.asProtobuf) ) - runWithDelay(configuredParticipants) { delay => + runWithDeduplicationDelay(configuredParticipants) { delay => for { // Submit command (first deduplication window) // Note: the second submit() in this block is deduplicated and thus rejected by the ledger API server, @@ -169,7 +168,7 @@ private[testtool] abstract class CommandDeduplicationBase( .update( _.commands.deduplicationTime := deduplicationDuration.asProtobuf ) - runWithDelay(configuredParticipants) { delay => + runWithDeduplicationDelay(configuredParticipants) { delay => for { // Submit command (first deduplication window) _ <- ledger.submitAndWait(request) @@ -193,7 +192,8 @@ private[testtool] abstract class CommandDeduplicationBase( ) // appendOnlySchema - without the submission id we cannot assert the received completions for parallel submissions - // staticTime - we run calls in parallel and with static time we advance the time, therefore this cannot be run in static time + // staticTime - we run calls in parallel and with static time we would need to advance the time, + // therefore this cannot be run in static time if (deduplicationFeatures.appendOnlySchema && !staticTime) testGivenAllParticipants( s"${testNamingPrefix}SimpleDeduplicationMixedClients", @@ -207,7 +207,8 @@ private[testtool] abstract class CommandDeduplicationBase( case currentElement :: tail => currentElement.flatMap(value => generateVariations(tail).map(value :: _)) } - runWithDelay(configuredParticipants) { delay => + + runWithDeduplicationDelay(configuredParticipants) { delay => { val numberOfCalls = 4 Future // cover all the different generated variations of submit and submitAndWait @@ -221,17 +222,20 @@ private[testtool] abstract class CommandDeduplicationBase( val submitRequest = ledger .submitRequest(party, Dummy(party).create.command) .update(_.commands.commandId := submitAndWaitRequest.getCommands.commandId) + def submitAndAssertAccepted(submitAndWait: Boolean) = { if (submitAndWait) ledger.submitAndWait(submitAndWaitRequest) else submitRequestAndAssertCompletionAccepted(ledger)(submitRequest, party) .map(_ => ()) } + def submitAndAssertDeduplicated(submitAndWait: Boolean) = { if (submitAndWait) submitAndWaitRequestAndAssertDeduplication(ledger)(submitAndWaitRequest) else submitRequestAndAssertDeduplication(ledger)(submitRequest, party) } + for { // Submit command (first deduplication window) _ <- submitAndAssertAccepted(firstCall) @@ -328,6 +332,7 @@ private[testtool] abstract class CommandDeduplicationBase( ) ) } + protected def submitRequestAndAssertCompletionAccepted( ledger: ParticipantTestContext )(request: SubmitRequest, parties: Party*)(implicit ec: ExecutionContext): Future[Completion] = { @@ -445,10 +450,13 @@ private[testtool] abstract class CommandDeduplicationBase( } object CommandDeduplicationBase { + trait DelayMechanism { + def apply(): Future[Unit] + } /** @param participantDeduplication If participant deduplication is enabled then we will receive synchronous rejections - * @param appendOnlySchema For [[Completion]], the submission id and deduplication period are filled only for append only schemas - * Therefore, we need to assert on those fields only if it's an append only schema + * @param appendOnlySchema For [[Completion]], the submission id and deduplication period are filled only for append only schemas + * Therefore, we need to assert on those fields only if it's an append only schema */ case class DeduplicationFeatures( participantDeduplication: Boolean, diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala index 317fe8bb2a09..8d248c00907b 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/KVCommandDeduplicationBase.scala @@ -10,6 +10,7 @@ import com.daml.ledger.api.testtool.infrastructure.Allocation.{ allocate, } import com.daml.ledger.api.testtool.infrastructure.ProtobufConverters._ +import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase.DelayMechanism import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext import com.daml.ledger.api.v1.admin.config_management_service.TimeModel import com.daml.ledger.api.v1.commands.Commands.DeduplicationPeriod @@ -99,12 +100,14 @@ abstract class KVCommandDeduplicationBase( } ) - protected override def runWithDelay( + protected override def runWithDeduplicationDelay( participants: Seq[ParticipantTestContext] - )(test: (() => Future[Unit]) => Future[Unit])(implicit ec: ExecutionContext): Future[Unit] = { + )( + testWithDelayMechanism: DelayMechanism => Future[Unit] + )(implicit ec: ExecutionContext): Future[Unit] = { runWithConfig(participants) { case (maxDeduplicationDuration, minSkew) => val anyParticipant = participants.head - test(() => delay(anyParticipant, maxDeduplicationDuration, minSkew)) + testWithDelayMechanism(() => delay(anyParticipant, maxDeduplicationDuration, minSkew)) } } @@ -122,15 +125,15 @@ abstract class KVCommandDeduplicationBase( } } - private def forwardTimeWithDuration(ledger: ParticipantTestContext, duration: Duration)(implicit - ec: ExecutionContext - ) = { + private def forwardTimeWithDuration( + ledger: ParticipantTestContext, + duration: Duration, + )(implicit ec: ExecutionContext): Future[Unit] = ledger .time() .flatMap(currentTime => { ledger.setTime(currentTime, currentTime.plusMillis(duration.toMillis)) }) - } private def runWithConfig( participants: Seq[ParticipantTestContext] @@ -190,6 +193,7 @@ abstract class KVCommandDeduplicationBase( () } } + for { time <- anyParticipant.time() updatedModel = timeModelUpdate(timeModel.getTimeModel) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala index e4c0ca2036b8..8426b2d3556e 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandDeduplicationIT.scala @@ -4,7 +4,10 @@ package com.daml.ledger.api.testtool.suites import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase -import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase.DeduplicationFeatures +import com.daml.ledger.api.testtool.infrastructure.deduplication.CommandDeduplicationBase.{ + DeduplicationFeatures, + DelayMechanism, +} import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext import com.daml.timer.Delayed @@ -20,13 +23,12 @@ final class CommandDeduplicationIT( staticTime: Boolean, ) extends CommandDeduplicationBase(timeoutScaleFactor, ledgerTimeInterval, staticTime) { - override def runWithDelay( + override def runWithDeduplicationDelay( participants: Seq[ParticipantTestContext] - )(test: (() => Future[Unit]) => Future[Unit])(implicit - ec: ExecutionContext - ): Future[Unit] = { - test(() => Delayed.by(defaultDeduplicationWindowWait)(())) - } + )( + testWithDelayMechanism: DelayMechanism => Future[Unit] + )(implicit ec: ExecutionContext): Future[Unit] = + testWithDelayMechanism(() => Delayed.by(defaultDeduplicationWindowWait)(())) override def testNamingPrefix: String = "ParticipantCommandDeduplication"