Extract the participant test context interface [KVL-1320] (#13476)

This commit is contained in:
nicu-da 2022-04-06 04:58:24 -07:00 committed by GitHub
parent b9c9acfb9e
commit f94cec2764
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 573 additions and 259 deletions

View File

@ -4,7 +4,6 @@
package com.daml.ledger.api.testtool.infrastructure package com.daml.ledger.api.testtool.infrastructure
import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantSession import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantSession
import com.daml.ledger.api.tls.TlsConfiguration
import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.{ExecutionContext, Future}
import scala.util.Random import scala.util.Random
@ -12,7 +11,6 @@ import scala.util.Random
private[infrastructure] final class LedgerSession private ( private[infrastructure] final class LedgerSession private (
participantSessions: Vector[(String, ParticipantSession)], participantSessions: Vector[(String, ParticipantSession)],
shuffleParticipants: Boolean, shuffleParticipants: Boolean,
clientTlsConfiguration: Option[TlsConfiguration],
)(implicit val executionContext: ExecutionContext) { )(implicit val executionContext: ExecutionContext) {
private[infrastructure] def createTestContext( private[infrastructure] def createTestContext(
@ -28,7 +26,6 @@ private[infrastructure] final class LedgerSession private (
endpointId, endpointId,
applicationId, applicationId,
identifierSuffix, identifierSuffix,
clientTlsConfiguration,
session.features, session.features,
) )
} }
@ -42,7 +39,6 @@ object LedgerSession {
def apply( def apply(
participantSessions: Vector[ParticipantSession], participantSessions: Vector[ParticipantSession],
shuffleParticipants: Boolean, shuffleParticipants: Boolean,
clientTlsConfiguration: Option[TlsConfiguration],
)(implicit executionContext: ExecutionContext): LedgerSession = { )(implicit executionContext: ExecutionContext): LedgerSession = {
val endpointIdProvider = val endpointIdProvider =
Identification.circularWithIndex(Identification.greekAlphabet) Identification.circularWithIndex(Identification.greekAlphabet)
@ -50,7 +46,6 @@ object LedgerSession {
new LedgerSession( new LedgerSession(
sessions, sessions,
shuffleParticipants, shuffleParticipants,
clientTlsConfiguration,
) )
} }

View File

@ -15,7 +15,6 @@ import com.daml.ledger.api.testtool.infrastructure.participant.{
ParticipantSession, ParticipantSession,
ParticipantTestContext, ParticipantTestContext,
} }
import com.daml.ledger.api.tls.TlsConfiguration
import io.grpc.ClientInterceptor import io.grpc.ClientInterceptor
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -50,7 +49,6 @@ final class LedgerTestCasesRunner(
uploadDars: Boolean = true, uploadDars: Boolean = true,
identifierSuffix: String = "test", identifierSuffix: String = "test",
commandInterceptors: Seq[ClientInterceptor] = Seq.empty, commandInterceptors: Seq[ClientInterceptor] = Seq.empty,
clientTlsConfiguration: Option[TlsConfiguration],
) { ) {
private[this] val verifyRequirements: Try[Unit] = private[this] val verifyRequirements: Try[Unit] =
Try { Try {
@ -161,8 +159,7 @@ final class LedgerTestCasesRunner(
} }
private def uploadDarsIfRequired( private def uploadDarsIfRequired(
sessions: Vector[ParticipantSession], sessions: Vector[ParticipantSession]
clientTlsConfiguration: Option[TlsConfiguration],
)(implicit executionContext: ExecutionContext): Future[Unit] = )(implicit executionContext: ExecutionContext): Future[Unit] =
if (uploadDars) { if (uploadDars) {
Future Future
@ -171,7 +168,6 @@ final class LedgerTestCasesRunner(
context <- session.createInitContext( context <- session.createInitContext(
applicationId = "upload-dars", applicationId = "upload-dars",
identifierSuffix = identifierSuffix, identifierSuffix = identifierSuffix,
clientTlsConfiguration = clientTlsConfiguration,
features = session.features, features = session.features,
) )
_ <- Future.sequence(Dars.resources.map(uploadDar(context, _))) _ <- Future.sequence(Dars.resources.map(uploadDar(context, _)))
@ -240,11 +236,10 @@ final class LedgerTestCasesRunner(
val ledgerSession = LedgerSession( val ledgerSession = LedgerSession(
sessions, sessions,
shuffleParticipants, shuffleParticipants,
clientTlsConfiguration = clientTlsConfiguration,
) )
val testResults = val testResults =
for { for {
_ <- uploadDarsIfRequired(sessions, clientTlsConfiguration) _ <- uploadDarsIfRequired(sessions)
concurrentTestResults <- runTestCases( concurrentTestResults <- runTestCases(
ledgerSession, ledgerSession,
concurrentTestCases, concurrentTestCases,

View File

@ -7,10 +7,8 @@ import java.time.Duration
import com.daml.api.util.DurationConversion import com.daml.api.util.DurationConversion
import com.daml.ledger.api.testtool.infrastructure.Assertions.{assertDefined, fail} import com.daml.ledger.api.testtool.infrastructure.Assertions.{assertDefined, fail}
import com.daml.ledger.api.testtool.infrastructure.participant.{ import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext
CompletionResponse, import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext.CompletionResponse
ParticipantTestContext,
}
import com.daml.ledger.api.v1.experimental_features.CommandDeduplicationPeriodSupport.{ import com.daml.ledger.api.v1.experimental_features.CommandDeduplicationPeriodSupport.{
DurationSupport, DurationSupport,
OffsetSupport, OffsetSupport,

View File

@ -10,7 +10,6 @@ import com.daml.ledger.api.testtool.infrastructure.{
LedgerServices, LedgerServices,
PartyAllocationConfiguration, PartyAllocationConfiguration,
} }
import com.daml.ledger.api.tls.TlsConfiguration
import com.daml.ledger.api.v1.ledger_identity_service.GetLedgerIdentityRequest import com.daml.ledger.api.v1.ledger_identity_service.GetLedgerIdentityRequest
import com.daml.ledger.api.v1.transaction_service.GetLedgerEndRequest import com.daml.ledger.api.v1.transaction_service.GetLedgerEndRequest
import com.daml.ledger.api.v1.version_service.GetLedgerApiVersionRequest import com.daml.ledger.api.v1.version_service.GetLedgerApiVersionRequest
@ -41,14 +40,12 @@ private[infrastructure] final class ParticipantSession private (
private[testtool] def createInitContext( private[testtool] def createInitContext(
applicationId: String, applicationId: String,
identifierSuffix: String, identifierSuffix: String,
clientTlsConfiguration: Option[TlsConfiguration],
features: Features, features: Features,
): Future[ParticipantTestContext] = ): Future[ParticipantTestContext] =
createTestContext( createTestContext(
"init", "init",
applicationId, applicationId,
identifierSuffix, identifierSuffix,
clientTlsConfiguration = clientTlsConfiguration,
features = features, features = features,
) )
@ -56,12 +53,11 @@ private[infrastructure] final class ParticipantSession private (
endpointId: String, endpointId: String,
applicationId: String, applicationId: String,
identifierSuffix: String, identifierSuffix: String,
clientTlsConfiguration: Option[TlsConfiguration],
features: Features, features: Features,
): Future[ParticipantTestContext] = ): Future[ParticipantTestContext] =
for { for {
end <- services.transaction.getLedgerEnd(new GetLedgerEndRequest(ledgerId)).map(_.getOffset) end <- services.transaction.getLedgerEnd(new GetLedgerEndRequest(ledgerId)).map(_.getOffset)
} yield new ParticipantTestContext( } yield new SingleParticipantTestContext(
ledgerId = ledgerId, ledgerId = ledgerId,
endpointId = endpointId, endpointId = endpointId,
applicationId = applicationId, applicationId = applicationId,
@ -70,7 +66,6 @@ private[infrastructure] final class ParticipantSession private (
services = services, services = services,
partyAllocationConfig = partyAllocationConfig, partyAllocationConfig = partyAllocationConfig,
ledgerEndpoint = ledgerEndpoint, ledgerEndpoint = ledgerEndpoint,
clientTlsConfiguration = clientTlsConfiguration,
features = features, features = features,
) )
} }

View File

@ -0,0 +1,382 @@
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.api.testtool.infrastructure.participant
import java.time.Instant
import com.daml.ledger.api.refinements.ApiTypes.TemplateId
import com.daml.ledger.api.testtool.infrastructure.Endpoint
import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext.CompletionResponse
import com.daml.ledger.api.testtool.infrastructure.time.DelayMechanism
import com.daml.ledger.api.v1.active_contracts_service.GetActiveContractsRequest
import com.daml.ledger.api.v1.admin.config_management_service.{
GetTimeModelResponse,
SetTimeModelRequest,
SetTimeModelResponse,
TimeModel,
}
import com.daml.ledger.api.v1.admin.package_management_service.{
PackageDetails,
UploadDarFileRequest,
}
import com.daml.ledger.api.v1.admin.participant_pruning_service.PruneResponse
import com.daml.ledger.api.v1.admin.party_management_service.PartyDetails
import com.daml.ledger.api.v1.command_completion_service.{
Checkpoint,
CompletionEndRequest,
CompletionEndResponse,
CompletionStreamRequest,
CompletionStreamResponse,
}
import com.daml.ledger.api.v1.command_service.{
SubmitAndWaitForTransactionIdResponse,
SubmitAndWaitForTransactionResponse,
SubmitAndWaitForTransactionTreeResponse,
SubmitAndWaitRequest,
}
import com.daml.ledger.api.v1.command_submission_service.SubmitRequest
import com.daml.ledger.api.v1.commands.Command
import com.daml.ledger.api.v1.completion.Completion
import com.daml.ledger.api.v1.event.CreatedEvent
import com.daml.ledger.api.v1.ledger_configuration_service.LedgerConfiguration
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset
import com.daml.ledger.api.v1.package_service.{GetPackageResponse, PackageStatus}
import com.daml.ledger.api.v1.transaction.{Transaction, TransactionTree}
import com.daml.ledger.api.v1.transaction_service.{
GetTransactionByEventIdRequest,
GetTransactionByIdRequest,
GetTransactionsRequest,
GetTransactionsResponse,
}
import com.daml.ledger.api.v1.value.{Identifier, Value}
import com.daml.ledger.client.binding.{Primitive, Template}
import com.daml.lf.data.Ref.HexString
import com.google.protobuf.ByteString
import io.grpc.health.v1.health.HealthCheckResponse
import io.grpc.stub.StreamObserver
import scala.concurrent.Future
trait ParticipantTestContext extends UserManagementTestContext {
val begin: LedgerOffset =
LedgerOffset(LedgerOffset.Value.Boundary(LedgerOffset.LedgerBoundary.LEDGER_BEGIN))
/** A reference to the moving ledger end. If you want a fixed reference to the offset at
* a given point in time, use [[currentEnd]]
*/
val end: LedgerOffset =
LedgerOffset(LedgerOffset.Value.Boundary(LedgerOffset.LedgerBoundary.LEDGER_END))
val ledgerId: String
val applicationId: String
val endpointId: String
def ledgerEndpoint: Endpoint
def features: Features
def referenceOffset: LedgerOffset
def nextKeyId: () => String
def nextUserId: () => String
def delayMechanism: DelayMechanism
/** Gets the absolute offset of the ledger end at a point in time. Use [[end]] if you need
* a reference to the moving end of the ledger.
*/
def currentEnd(): Future[LedgerOffset]
/** Works just like [[currentEnd]] but allows to override the ledger identifier.
*
* Used only for low-level testing. Please use the other method unless you want to test the
* behavior of the ledger end endpoint with a wrong ledger identifier.
*/
def currentEnd(overrideLedgerId: String): Future[LedgerOffset]
/** Returns an absolute offset that is beyond the current ledger end.
*
* Note: offsets are opaque byte strings, but they are lexicographically sortable.
* Prepending the current absolute ledger end with non-zero bytes creates an offset that
* is be beyond the current ledger end for the ledger API server.
* The offset might however not be valid for the underlying ledger.
* This method can therefore only be used for offsets that are only interpreted by the
* ledger API server and not sent to the ledger.
*/
def offsetBeyondLedgerEnd(): Future[LedgerOffset]
def time(): Future[Instant]
def setTime(currentTime: Instant, newTime: Instant): Future[Unit]
def listKnownPackages(): Future[Seq[PackageDetails]]
def uploadDarFile(bytes: ByteString): Future[Unit] =
uploadDarFile(new UploadDarFileRequest(bytes))
def uploadDarRequest(bytes: ByteString): UploadDarFileRequest
def uploadDarFile(request: UploadDarFileRequest): Future[Unit]
def participantId(): Future[String]
def listPackages(): Future[Seq[String]]
def getPackage(packageId: String): Future[GetPackageResponse]
def getPackageStatus(packageId: String): Future[PackageStatus]
/** Managed version of party allocation, should be used anywhere a party has
* to be allocated unless the party management service itself is under test
*/
def allocateParty(): Future[Primitive.Party]
/** Non managed version of party allocation. Use exclusively when testing the party management service.
*/
def allocateParty(
partyIdHint: Option[String],
displayName: Option[String],
): Future[Primitive.Party]
def allocateParties(n: Int): Future[Vector[Primitive.Party]]
def getParties(parties: Seq[Primitive.Party]): Future[Seq[PartyDetails]]
def listKnownParties(): Future[Set[Primitive.Party]]
/** @return a future that completes when all the participants can list all the expected parties
*/
def waitForParties(
otherParticipants: Iterable[ParticipantTestContext],
expectedParties: Set[Primitive.Party],
): Future[Unit]
def activeContracts(
request: GetActiveContractsRequest
): Future[(Option[LedgerOffset], Vector[CreatedEvent])]
def activeContractsRequest(
parties: Seq[Primitive.Party],
templateIds: Seq[Identifier] = Seq.empty,
): GetActiveContractsRequest
def activeContracts(parties: Primitive.Party*): Future[Vector[CreatedEvent]]
def activeContractsByTemplateId(
templateIds: Seq[Identifier],
parties: Primitive.Party*
): Future[Vector[CreatedEvent]]
/** Create a [[GetTransactionsRequest]] with a set of [[Party]] objects.
* You should use this only when you need to tweak the request of [[flatTransactions]]
* or [[transactionTrees]], otherwise use the shortcut override that allows you to
* directly pass a set of [[Party]]
*/
def getTransactionsRequest(
parties: Seq[Primitive.Party],
templateIds: Seq[TemplateId] = Seq.empty,
begin: LedgerOffset = referenceOffset,
): GetTransactionsRequest
def transactionStream(
request: GetTransactionsRequest,
responseObserver: StreamObserver[GetTransactionsResponse],
): Unit
def flatTransactionsByTemplateId(
templateId: TemplateId,
parties: Primitive.Party*
): Future[Vector[Transaction]]
/** Non-managed version of [[flatTransactions]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactions(request: GetTransactionsRequest): Future[Vector[Transaction]]
/** Managed version of [[flatTransactions]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactions(parties: Primitive.Party*): Future[Vector[Transaction]]
/** Non-managed version of [[flatTransactions]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactions(take: Int, request: GetTransactionsRequest): Future[Vector[Transaction]]
/** Managed version of [[flatTransactions]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactions(take: Int, parties: Primitive.Party*): Future[Vector[Transaction]]
def transactionTreesByTemplateId(
templateId: TemplateId,
parties: Primitive.Party*
): Future[Vector[TransactionTree]]
/** Non-managed version of [[transactionTrees]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def transactionTrees(request: GetTransactionsRequest): Future[Vector[TransactionTree]]
/** Managed version of [[transactionTrees]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def transactionTrees(parties: Primitive.Party*): Future[Vector[TransactionTree]]
/** Non-managed version of [[transactionTrees]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def transactionTrees(
take: Int,
request: GetTransactionsRequest,
): Future[Vector[TransactionTree]]
/** Managed version of [[transactionTrees]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def transactionTrees(take: Int, parties: Primitive.Party*): Future[Vector[TransactionTree]]
/** Create a [[GetTransactionByIdRequest]] with an identifier and a set of [[Party]] objects.
* You should use this only when you need to tweak the request of [[transactionTreeById]] or
* [[flatTransactionById]], otherwise use the shortcut override that allows you to directly
* pass the identifier and parties.
*/
def getTransactionByIdRequest(
transactionId: String,
parties: Seq[Primitive.Party],
): GetTransactionByIdRequest
/** Non-managed version of [[transactionTreeById]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def transactionTreeById(request: GetTransactionByIdRequest): Future[TransactionTree]
/** Managed version of [[transactionTrees]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def transactionTreeById(transactionId: String, parties: Primitive.Party*): Future[TransactionTree]
/** Non-managed version of [[flatTransactionById]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactionById(request: GetTransactionByIdRequest): Future[Transaction]
/** Managed version of [[flatTransactionById]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactionById(transactionId: String, parties: Primitive.Party*): Future[Transaction]
/** Create a [[GetTransactionByEventIdRequest]] with an identifier and a set of [[Party]] objects.
* You should use this only when you need to tweak the request of [[transactionTreeByEventId]] or
* [[flatTransactionByEventId]], otherwise use the shortcut override that allows you to directly
* pass the identifier and parties.
*/
def getTransactionByEventIdRequest(
eventId: String,
parties: Seq[Primitive.Party],
): GetTransactionByEventIdRequest
/** Non-managed version of [[transactionTreeByEventId]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def transactionTreeByEventId(request: GetTransactionByEventIdRequest): Future[TransactionTree]
/** Managed version of [[transactionTreeByEventId]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def transactionTreeByEventId(eventId: String, parties: Primitive.Party*): Future[TransactionTree]
/** Non-managed version of [[flatTransactionByEventId]], use this only if you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactionByEventId(request: GetTransactionByEventIdRequest): Future[Transaction]
/** Managed version of [[flatTransactionByEventId]], use this unless you need to tweak the request (i.e. to test low-level details)
*/
def flatTransactionByEventId(eventId: String, parties: Primitive.Party*): Future[Transaction]
def create[T](
party: Primitive.Party,
template: Template[T],
): Future[Primitive.ContractId[T]]
def create[T](
actAs: List[Primitive.Party],
readAs: List[Primitive.Party],
template: Template[T],
): Future[Primitive.ContractId[T]]
def createAndGetTransactionId[T](
party: Primitive.Party,
template: Template[T],
): Future[(String, Primitive.ContractId[T])]
def exercise[T](
party: Primitive.Party,
exercise: Primitive.Party => Primitive.Update[T],
): Future[TransactionTree]
def exercise[T](
actAs: List[Primitive.Party],
readAs: List[Primitive.Party],
exercise: => Primitive.Update[T],
): Future[TransactionTree]
def exerciseForFlatTransaction[T](
party: Primitive.Party,
exercise: Primitive.Party => Primitive.Update[T],
): Future[Transaction]
def exerciseAndGetContract[T](
party: Primitive.Party,
exercise: Primitive.Party => Primitive.Update[Any],
): Future[Primitive.ContractId[T]]
def exerciseByKey[T](
party: Primitive.Party,
template: Primitive.TemplateId[T],
key: Value,
choice: String,
argument: Value,
): Future[TransactionTree]
def submitRequest(
actAs: List[Primitive.Party],
readAs: List[Primitive.Party],
commands: Command*
): SubmitRequest
def submitRequest(party: Primitive.Party, commands: Command*): SubmitRequest
def submitAndWaitRequest(
actAs: List[Primitive.Party],
readAs: List[Primitive.Party],
commands: Command*
): SubmitAndWaitRequest
def submitAndWaitRequest(party: Primitive.Party, commands: Command*): SubmitAndWaitRequest
def submit(request: SubmitRequest): Future[Unit]
def submitAndWait(request: SubmitAndWaitRequest): Future[Unit]
def submitAndWaitForTransactionId(
request: SubmitAndWaitRequest
): Future[SubmitAndWaitForTransactionIdResponse]
def submitAndWaitForTransaction(
request: SubmitAndWaitRequest
): Future[SubmitAndWaitForTransactionResponse]
def submitAndWaitForTransactionTree(
request: SubmitAndWaitRequest
): Future[SubmitAndWaitForTransactionTreeResponse]
def completionStreamRequest(from: LedgerOffset = referenceOffset)(
parties: Primitive.Party*
): CompletionStreamRequest
def completionEnd(request: CompletionEndRequest): Future[CompletionEndResponse]
def completionStream(
request: CompletionStreamRequest,
streamObserver: StreamObserver[CompletionStreamResponse],
): Unit
def firstCompletions(request: CompletionStreamRequest): Future[Vector[Completion]]
def firstCompletions(parties: Primitive.Party*): Future[Vector[Completion]]
def findCompletionAtOffset(
offset: HexString,
p: Completion => Boolean,
)(parties: Primitive.Party*): Future[Option[CompletionResponse]]
def findCompletion(
request: CompletionStreamRequest
)(p: Completion => Boolean): Future[Option[CompletionResponse]]
def findCompletion(parties: Primitive.Party*)(
p: Completion => Boolean
): Future[Option[CompletionResponse]]
def checkpoints(n: Int, request: CompletionStreamRequest): Future[Vector[Checkpoint]]
def checkpoints(n: Int, from: LedgerOffset = referenceOffset)(
parties: Primitive.Party*
): Future[Vector[Checkpoint]]
def firstCheckpoint(request: CompletionStreamRequest): Future[Checkpoint]
def firstCheckpoint(parties: Primitive.Party*): Future[Checkpoint]
def nextCheckpoint(request: CompletionStreamRequest): Future[Checkpoint]
def nextCheckpoint(from: LedgerOffset, parties: Primitive.Party*): Future[Checkpoint]
def configuration(overrideLedgerId: Option[String] = None): Future[LedgerConfiguration]
def checkHealth(): Future[HealthCheckResponse]
def watchHealth(): Future[Seq[HealthCheckResponse]]
def getTimeModel(): Future[GetTimeModelResponse]
def setTimeModel(
mrt: Instant,
generation: Long,
newTimeModel: TimeModel,
): Future[SetTimeModelResponse]
def setTimeModelRequest(
mrt: Instant,
generation: Long,
newTimeModel: TimeModel,
): SetTimeModelRequest
def setTimeModel(
request: SetTimeModelRequest
): Future[SetTimeModelResponse]
private[infrastructure] def preallocateParties(
n: Int,
participants: Iterable[ParticipantTestContext],
): Future[Vector[Primitive.Party]]
def prune(
pruneUpTo: LedgerOffset,
attempts: Int = 10,
pruneAllDivulgedContracts: Boolean = false,
): Future[PruneResponse]
}
object ParticipantTestContext {
case class CompletionResponse(completion: Completion, offset: LedgerOffset, recordTime: Instant)
}

View File

@ -8,6 +8,7 @@ import java.time.{Clock, Instant}
import com.daml.ledger.api.refinements.ApiTypes.TemplateId import com.daml.ledger.api.refinements.ApiTypes.TemplateId
import com.daml.ledger.api.testtool.infrastructure.Eventually.eventually import com.daml.ledger.api.testtool.infrastructure.Eventually.eventually
import com.daml.ledger.api.testtool.infrastructure.ProtobufConverters._ import com.daml.ledger.api.testtool.infrastructure.ProtobufConverters._
import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext.CompletionResponse
import com.daml.ledger.api.testtool.infrastructure.time.{ import com.daml.ledger.api.testtool.infrastructure.time.{
DelayMechanism, DelayMechanism,
StaticTimeDelayMechanism, StaticTimeDelayMechanism,
@ -19,7 +20,6 @@ import com.daml.ledger.api.testtool.infrastructure.{
LedgerServices, LedgerServices,
PartyAllocationConfiguration, PartyAllocationConfiguration,
} }
import com.daml.ledger.api.tls.TlsConfiguration
import com.daml.ledger.api.v1.active_contracts_service.{ import com.daml.ledger.api.v1.active_contracts_service.{
GetActiveContractsRequest, GetActiveContractsRequest,
GetActiveContractsResponse, GetActiveContractsResponse,
@ -97,52 +97,26 @@ import scala.concurrent.{ExecutionContext, Future}
import scala.util.Failure import scala.util.Failure
import scala.util.control.NonFatal import scala.util.control.NonFatal
private[testtool] object ParticipantTestContext {
private[this] def filter(templateIds: Seq[Identifier]): Filters =
new Filters(
if (templateIds.isEmpty) None
else Some(new InclusiveFilters(templateIds))
)
private def transactionFilter(
parties: Seq[String],
templateIds: Seq[Identifier],
): Some[TransactionFilter] =
Some(new TransactionFilter(Map(parties.map(_ -> filter(templateIds)): _*)))
}
/** Exposes services running on some participant server in a test case. /** Exposes services running on some participant server in a test case.
* *
* Each time a test case is run it receives a fresh instance of [[ParticipantTestContext]] * Each time a test case is run it receives a fresh instance of [[SingleParticipantTestContext]]
* (one for every used participant server). * (one for every used participant server).
*/ */
final class ParticipantTestContext private[participant] ( final class SingleParticipantTestContext private[participant] (
val ledgerId: String, val ledgerId: String,
val endpointId: String, val endpointId: String,
val applicationId: String, val applicationId: String,
val identifierSuffix: String, identifierSuffix: String,
referenceOffset: LedgerOffset, val referenceOffset: LedgerOffset,
protected[participant] val services: LedgerServices, protected[participant] val services: LedgerServices,
partyAllocationConfig: PartyAllocationConfiguration, partyAllocationConfig: PartyAllocationConfiguration,
val ledgerEndpoint: Endpoint, val ledgerEndpoint: Endpoint,
val clientTlsConfiguration: Option[TlsConfiguration],
val features: Features, val features: Features,
)(protected[participant] implicit val ec: ExecutionContext) )(protected[participant] implicit val ec: ExecutionContext)
extends UserManagementTestContext { extends ParticipantTestContext {
private val logger = ContextualizedLogger.get(getClass) private val logger = ContextualizedLogger.get(getClass)
import ParticipantTestContext._ import SingleParticipantTestContext._
val begin: LedgerOffset =
LedgerOffset(LedgerOffset.Value.Boundary(LedgerOffset.LedgerBoundary.LEDGER_BEGIN))
/** A reference to the moving ledger end. If you want a fixed reference to the offset at
* a given point in time, use [[currentEnd]]
*/
val end: LedgerOffset =
LedgerOffset(LedgerOffset.Value.Boundary(LedgerOffset.LedgerBoundary.LEDGER_END))
private[this] val identifierPrefix = private[this] val identifierPrefix =
s"$applicationId-$endpointId-$identifierSuffix" s"$applicationId-$endpointId-$identifierSuffix"
@ -159,47 +133,30 @@ final class ParticipantTestContext private[participant] (
private[this] val nextCommandId: () => String = nextIdGenerator("command") private[this] val nextCommandId: () => String = nextIdGenerator("command")
private[this] val nextSubmissionId: () => String = nextIdGenerator("submission") private[this] val nextSubmissionId: () => String = nextIdGenerator("submission")
private[this] val workflowId: String = s"$applicationId-$identifierSuffix" private[this] val workflowId: String = s"$applicationId-$identifierSuffix"
val nextKeyId: () => String = nextIdGenerator("key") override val nextKeyId: () => String = nextIdGenerator("key")
val nextUserId: () => String = nextIdGenerator("user", lowerCase = true) override val nextUserId: () => String = nextIdGenerator("user", lowerCase = true)
lazy val delayMechanism: DelayMechanism = if (features.staticTime) { override lazy val delayMechanism: DelayMechanism = if (features.staticTime) {
new StaticTimeDelayMechanism(this) new StaticTimeDelayMechanism(this)
} else } else
new TimeDelayMechanism() new TimeDelayMechanism()
override def toString: String = s"participant $endpointId" override def toString: String = s"participant $endpointId"
/** Gets the absolute offset of the ledger end at a point in time. Use [[end]] if you need override def currentEnd(): Future[LedgerOffset] =
* a reference to the moving end of the ledger.
*/
def currentEnd(): Future[LedgerOffset] =
services.transaction services.transaction
.getLedgerEnd(new GetLedgerEndRequest(ledgerId)) .getLedgerEnd(new GetLedgerEndRequest(ledgerId))
.map(_.getOffset) .map(_.getOffset)
/** Works just like [[currentEnd]] but allows to override the ledger identifier. override def currentEnd(overrideLedgerId: String): Future[LedgerOffset] =
*
* Used only for low-level testing. Please use the other method unless you want to test the
* behavior of the ledger end endpoint with a wrong ledger identifier.
*/
def currentEnd(overrideLedgerId: String): Future[LedgerOffset] =
services.transaction services.transaction
.getLedgerEnd(new GetLedgerEndRequest(overrideLedgerId)) .getLedgerEnd(new GetLedgerEndRequest(overrideLedgerId))
.map(_.getOffset) .map(_.getOffset)
/** Returns an absolute offset that is beyond the current ledger end. override def offsetBeyondLedgerEnd(): Future[LedgerOffset] =
*
* Note: offsets are opaque byte strings, but they are lexicographically sortable.
* Prepending the current absolute ledger end with non-zero bytes creates an offset that
* is be beyond the current ledger end for the ledger API server.
* The offset might however not be valid for the underlying ledger.
* This method can therefore only be used for offsets that are only interpreted by the
* ledger API server and not sent to the ledger.
*/
def offsetBeyondLedgerEnd(): Future[LedgerOffset] =
currentEnd().map(end => LedgerOffset(LedgerOffset.Value.Absolute("FFFF" + end.getAbsolute))) currentEnd().map(end => LedgerOffset(LedgerOffset.Value.Absolute("FFFF" + end.getAbsolute)))
def time(): Future[Instant] = override def time(): Future[Instant] =
new StreamConsumer[GetTimeResponse](services.time.getTime(new GetTimeRequest(ledgerId), _)) new StreamConsumer[GetTimeResponse](services.time.getTime(new GetTimeRequest(ledgerId), _))
.first() .first()
.map(_.map(r => r.getCurrentTime.asJava).get) .map(_.map(r => r.getCurrentTime.asJava).get)
@ -207,7 +164,7 @@ final class ParticipantTestContext private[participant] (
Clock.systemUTC().instant() Clock.systemUTC().instant()
} }
def setTime(currentTime: Instant, newTime: Instant): Future[Unit] = override def setTime(currentTime: Instant, newTime: Instant): Future[Unit] =
services.time services.time
.setTime( .setTime(
SetTimeRequest( SetTimeRequest(
@ -218,51 +175,46 @@ final class ParticipantTestContext private[participant] (
) )
.map(_ => ()) .map(_ => ())
def listKnownPackages(): Future[Seq[PackageDetails]] = override def listKnownPackages(): Future[Seq[PackageDetails]] =
services.packageManagement services.packageManagement
.listKnownPackages(new ListKnownPackagesRequest) .listKnownPackages(new ListKnownPackagesRequest)
.map(_.packageDetails) .map(_.packageDetails)
def uploadDarFile(bytes: ByteString): Future[Unit] = override def uploadDarRequest(bytes: ByteString): UploadDarFileRequest =
uploadDarFile(new UploadDarFileRequest(bytes))
def uploadDarRequest(bytes: ByteString): UploadDarFileRequest =
new UploadDarFileRequest(bytes, nextSubmissionId()) new UploadDarFileRequest(bytes, nextSubmissionId())
def uploadDarFile(request: UploadDarFileRequest): Future[Unit] = override def uploadDarFile(request: UploadDarFileRequest): Future[Unit] =
services.packageManagement services.packageManagement
.uploadDarFile(request) .uploadDarFile(request)
.map(_ => ()) .map(_ => ())
def participantId(): Future[String] = override def participantId(): Future[String] =
services.partyManagement services.partyManagement
.getParticipantId(new GetParticipantIdRequest) .getParticipantId(new GetParticipantIdRequest)
.map(_.participantId) .map(_.participantId)
def listPackages(): Future[Seq[String]] = override def listPackages(): Future[Seq[String]] =
services.packages services.packages
.listPackages(new ListPackagesRequest(ledgerId)) .listPackages(new ListPackagesRequest(ledgerId))
.map(_.packageIds) .map(_.packageIds)
def getPackage(packageId: String): Future[GetPackageResponse] = override def getPackage(packageId: String): Future[GetPackageResponse] =
services.packages.getPackage(new GetPackageRequest(ledgerId, packageId)) services.packages.getPackage(new GetPackageRequest(ledgerId, packageId))
def getPackageStatus(packageId: String): Future[PackageStatus] = override def getPackageStatus(packageId: String): Future[PackageStatus] =
services.packages services.packages
.getPackageStatus(new GetPackageStatusRequest(ledgerId, packageId)) .getPackageStatus(new GetPackageStatusRequest(ledgerId, packageId))
.map(_.packageStatus) .map(_.packageStatus)
/** Managed version of party allocation, should be used anywhere a party has override def allocateParty(): Future[Party] =
* to be allocated unless the party management service itself is under test
*/
def allocateParty(): Future[Party] =
services.partyManagement services.partyManagement
.allocateParty(new AllocatePartyRequest(partyIdHint = nextPartyHintId())) .allocateParty(new AllocatePartyRequest(partyIdHint = nextPartyHintId()))
.map(r => Party(r.partyDetails.get.party)) .map(r => Party(r.partyDetails.get.party))
/** Non managed version of party allocation. Use exclusively when testing the party management service. override def allocateParty(
*/ partyIdHint: Option[String],
def allocateParty(partyIdHint: Option[String], displayName: Option[String]): Future[Party] = displayName: Option[String],
): Future[Party] =
services.partyManagement services.partyManagement
.allocateParty( .allocateParty(
new AllocatePartyRequest( new AllocatePartyRequest(
@ -272,22 +224,20 @@ final class ParticipantTestContext private[participant] (
) )
.map(r => Party(r.partyDetails.get.party)) .map(r => Party(r.partyDetails.get.party))
def allocateParties(n: Int): Future[Vector[Party]] = override def allocateParties(n: Int): Future[Vector[Party]] =
Future.sequence(Vector.fill(n)(allocateParty())) Future.sequence(Vector.fill(n)(allocateParty()))
def getParties(parties: Seq[Party]): Future[Seq[PartyDetails]] = override def getParties(parties: Seq[Party]): Future[Seq[PartyDetails]] =
services.partyManagement services.partyManagement
.getParties(GetPartiesRequest(parties.map(_.unwrap))) .getParties(GetPartiesRequest(parties.map(_.unwrap)))
.map(_.partyDetails) .map(_.partyDetails)
def listKnownParties(): Future[Set[Party]] = override def listKnownParties(): Future[Set[Party]] =
services.partyManagement services.partyManagement
.listKnownParties(new ListKnownPartiesRequest()) .listKnownParties(new ListKnownPartiesRequest())
.map(_.partyDetails.map(partyDetails => Party(partyDetails.party)).toSet) .map(_.partyDetails.map(partyDetails => Party(partyDetails.party)).toSet)
/** @return a future that completes when all the participants can list all the expected parties override def waitForParties(
*/
def waitForParties(
otherParticipants: Iterable[ParticipantTestContext], otherParticipants: Iterable[ParticipantTestContext],
expectedParties: Set[Party], expectedParties: Set[Party],
): Future[Unit] = ): Future[Unit] =
@ -311,7 +261,7 @@ final class ParticipantTestContext private[participant] (
Future.unit Future.unit
} }
def activeContracts( override def activeContracts(
request: GetActiveContractsRequest request: GetActiveContractsRequest
): Future[(Option[LedgerOffset], Vector[CreatedEvent])] = ): Future[(Option[LedgerOffset], Vector[CreatedEvent])] =
for { for {
@ -322,7 +272,7 @@ final class ParticipantTestContext private[participant] (
.map(c => LedgerOffset(LedgerOffset.Value.Absolute(c.offset))) -> contracts .map(c => LedgerOffset(LedgerOffset.Value.Absolute(c.offset))) -> contracts
.flatMap(_.activeContracts) .flatMap(_.activeContracts)
def activeContractsRequest( override def activeContractsRequest(
parties: Seq[Party], parties: Seq[Party],
templateIds: Seq[Identifier] = Seq.empty, templateIds: Seq[Identifier] = Seq.empty,
): GetActiveContractsRequest = ): GetActiveContractsRequest =
@ -332,21 +282,16 @@ final class ParticipantTestContext private[participant] (
verbose = true, verbose = true,
) )
def activeContracts(parties: Party*): Future[Vector[CreatedEvent]] = override def activeContracts(parties: Party*): Future[Vector[CreatedEvent]] =
activeContractsByTemplateId(Seq.empty, parties: _*) activeContractsByTemplateId(Seq.empty, parties: _*)
def activeContractsByTemplateId( override def activeContractsByTemplateId(
templateIds: Seq[Identifier], templateIds: Seq[Identifier],
parties: Party* parties: Party*
): Future[Vector[CreatedEvent]] = ): Future[Vector[CreatedEvent]] =
activeContracts(activeContractsRequest(parties, templateIds)).map(_._2) activeContracts(activeContractsRequest(parties, templateIds)).map(_._2)
/** Create a [[GetTransactionsRequest]] with a set of [[Party]] objects. override def getTransactionsRequest(
* You should use this only when you need to tweak the request of [[flatTransactions]]
* or [[transactionTrees]], otherwise use the shortcut override that allows you to
* directly pass a set of [[Party]]
*/
def getTransactionsRequest(
parties: Seq[Party], parties: Seq[Party],
templateIds: Seq[TemplateId] = Seq.empty, templateIds: Seq[TemplateId] = Seq.empty,
begin: LedgerOffset = referenceOffset, begin: LedgerOffset = referenceOffset,
@ -372,133 +317,101 @@ final class ParticipantTestContext private[participant] (
): Future[Vector[Res]] = ): Future[Vector[Res]] =
new StreamConsumer[Res](service(request, _)).all() new StreamConsumer[Res](service(request, _)).all()
def transactionStream( override def transactionStream(
request: GetTransactionsRequest, request: GetTransactionsRequest,
responseObserver: StreamObserver[GetTransactionsResponse], responseObserver: StreamObserver[GetTransactionsResponse],
): Unit = ): Unit =
services.transaction.getTransactions(request, responseObserver) services.transaction.getTransactions(request, responseObserver)
def flatTransactionsByTemplateId( override def flatTransactionsByTemplateId(
templateId: TemplateId, templateId: TemplateId,
parties: Party* parties: Party*
): Future[Vector[Transaction]] = ): Future[Vector[Transaction]] =
flatTransactions(getTransactionsRequest(parties, Seq(templateId))) flatTransactions(getTransactionsRequest(parties, Seq(templateId)))
/** Non-managed version of [[flatTransactions]], use this only if you need to tweak the request (i.e. to test low-level details) override def flatTransactions(request: GetTransactionsRequest): Future[Vector[Transaction]] =
*/
def flatTransactions(request: GetTransactionsRequest): Future[Vector[Transaction]] =
transactions(request, services.transaction.getTransactions) transactions(request, services.transaction.getTransactions)
.map(_.flatMap(_.transactions)) .map(_.flatMap(_.transactions))
/** Managed version of [[flatTransactions]], use this unless you need to tweak the request (i.e. to test low-level details) override def flatTransactions(parties: Party*): Future[Vector[Transaction]] =
*/
def flatTransactions(parties: Party*): Future[Vector[Transaction]] =
flatTransactions(getTransactionsRequest(parties)) flatTransactions(getTransactionsRequest(parties))
/** Non-managed version of [[flatTransactions]], use this only if you need to tweak the request (i.e. to test low-level details) override def flatTransactions(
*/ take: Int,
def flatTransactions(take: Int, request: GetTransactionsRequest): Future[Vector[Transaction]] = request: GetTransactionsRequest,
): Future[Vector[Transaction]] =
transactions(take, request, services.transaction.getTransactions) transactions(take, request, services.transaction.getTransactions)
.map(_.flatMap(_.transactions)) .map(_.flatMap(_.transactions))
/** Managed version of [[flatTransactions]], use this unless you need to tweak the request (i.e. to test low-level details) override def flatTransactions(take: Int, parties: Party*): Future[Vector[Transaction]] =
*/
def flatTransactions(take: Int, parties: Party*): Future[Vector[Transaction]] =
flatTransactions(take, getTransactionsRequest(parties)) flatTransactions(take, getTransactionsRequest(parties))
def transactionTreesByTemplateId( override def transactionTreesByTemplateId(
templateId: TemplateId, templateId: TemplateId,
parties: Party* parties: Party*
): Future[Vector[TransactionTree]] = ): Future[Vector[TransactionTree]] =
transactionTrees(getTransactionsRequest(parties, Seq(templateId))) transactionTrees(getTransactionsRequest(parties, Seq(templateId)))
/** Non-managed version of [[transactionTrees]], use this only if you need to tweak the request (i.e. to test low-level details) override def transactionTrees(request: GetTransactionsRequest): Future[Vector[TransactionTree]] =
*/
def transactionTrees(request: GetTransactionsRequest): Future[Vector[TransactionTree]] =
transactions(request, services.transaction.getTransactionTrees) transactions(request, services.transaction.getTransactionTrees)
.map(_.flatMap(_.transactions)) .map(_.flatMap(_.transactions))
/** Managed version of [[transactionTrees]], use this unless you need to tweak the request (i.e. to test low-level details) override def transactionTrees(parties: Party*): Future[Vector[TransactionTree]] =
*/
def transactionTrees(parties: Party*): Future[Vector[TransactionTree]] =
transactionTrees(getTransactionsRequest(parties)) transactionTrees(getTransactionsRequest(parties))
/** Non-managed version of [[transactionTrees]], use this only if you need to tweak the request (i.e. to test low-level details) override def transactionTrees(
*/
def transactionTrees(
take: Int, take: Int,
request: GetTransactionsRequest, request: GetTransactionsRequest,
): Future[Vector[TransactionTree]] = ): Future[Vector[TransactionTree]] =
transactions(take, request, services.transaction.getTransactionTrees) transactions(take, request, services.transaction.getTransactionTrees)
.map(_.flatMap(_.transactions)) .map(_.flatMap(_.transactions))
/** Managed version of [[transactionTrees]], use this unless you need to tweak the request (i.e. to test low-level details) override def transactionTrees(take: Int, parties: Party*): Future[Vector[TransactionTree]] =
*/
def transactionTrees(take: Int, parties: Party*): Future[Vector[TransactionTree]] =
transactionTrees(take, getTransactionsRequest(parties)) transactionTrees(take, getTransactionsRequest(parties))
/** Create a [[GetTransactionByIdRequest]] with an identifier and a set of [[Party]] objects. override def getTransactionByIdRequest(
* You should use this only when you need to tweak the request of [[transactionTreeById]] or
* [[flatTransactionById]], otherwise use the shortcut override that allows you to directly
* pass the identifier and parties.
*/
def getTransactionByIdRequest(
transactionId: String, transactionId: String,
parties: Seq[Party], parties: Seq[Party],
): GetTransactionByIdRequest = ): GetTransactionByIdRequest =
new GetTransactionByIdRequest(ledgerId, transactionId, Tag.unsubst(parties)) new GetTransactionByIdRequest(ledgerId, transactionId, Tag.unsubst(parties))
/** Non-managed version of [[transactionTreeById]], use this only if you need to tweak the request (i.e. to test low-level details) override def transactionTreeById(request: GetTransactionByIdRequest): Future[TransactionTree] =
*/
def transactionTreeById(request: GetTransactionByIdRequest): Future[TransactionTree] =
services.transaction.getTransactionById(request).map(_.getTransaction) services.transaction.getTransactionById(request).map(_.getTransaction)
/** Managed version of [[transactionTrees]], use this unless you need to tweak the request (i.e. to test low-level details) override def transactionTreeById(
*/ transactionId: String,
def transactionTreeById(transactionId: String, parties: Party*): Future[TransactionTree] = parties: Party*
): Future[TransactionTree] =
transactionTreeById(getTransactionByIdRequest(transactionId, parties)) transactionTreeById(getTransactionByIdRequest(transactionId, parties))
/** Non-managed version of [[flatTransactionById]], use this only if you need to tweak the request (i.e. to test low-level details) override def flatTransactionById(request: GetTransactionByIdRequest): Future[Transaction] =
*/
def flatTransactionById(request: GetTransactionByIdRequest): Future[Transaction] =
services.transaction.getFlatTransactionById(request).map(_.getTransaction) services.transaction.getFlatTransactionById(request).map(_.getTransaction)
/** Managed version of [[flatTransactionById]], use this unless you need to tweak the request (i.e. to test low-level details) override def flatTransactionById(transactionId: String, parties: Party*): Future[Transaction] =
*/
def flatTransactionById(transactionId: String, parties: Party*): Future[Transaction] =
flatTransactionById(getTransactionByIdRequest(transactionId, parties)) flatTransactionById(getTransactionByIdRequest(transactionId, parties))
/** Create a [[GetTransactionByEventIdRequest]] with an identifier and a set of [[Party]] objects. override def getTransactionByEventIdRequest(
* You should use this only when you need to tweak the request of [[transactionTreeByEventId]] or
* [[flatTransactionByEventId]], otherwise use the shortcut override that allows you to directly
* pass the identifier and parties.
*/
def getTransactionByEventIdRequest(
eventId: String, eventId: String,
parties: Seq[Party], parties: Seq[Party],
): GetTransactionByEventIdRequest = ): GetTransactionByEventIdRequest =
new GetTransactionByEventIdRequest(ledgerId, eventId, Tag.unsubst(parties)) new GetTransactionByEventIdRequest(ledgerId, eventId, Tag.unsubst(parties))
/** Non-managed version of [[transactionTreeByEventId]], use this only if you need to tweak the request (i.e. to test low-level details) override def transactionTreeByEventId(
*/ request: GetTransactionByEventIdRequest
def transactionTreeByEventId(request: GetTransactionByEventIdRequest): Future[TransactionTree] = ): Future[TransactionTree] =
services.transaction.getTransactionByEventId(request).map(_.getTransaction) services.transaction.getTransactionByEventId(request).map(_.getTransaction)
/** Managed version of [[transactionTreeByEventId]], use this unless you need to tweak the request (i.e. to test low-level details) override def transactionTreeByEventId(eventId: String, parties: Party*): Future[TransactionTree] =
*/
def transactionTreeByEventId(eventId: String, parties: Party*): Future[TransactionTree] =
transactionTreeByEventId(getTransactionByEventIdRequest(eventId, parties)) transactionTreeByEventId(getTransactionByEventIdRequest(eventId, parties))
/** Non-managed version of [[flatTransactionByEventId]], use this only if you need to tweak the request (i.e. to test low-level details) override def flatTransactionByEventId(
*/ request: GetTransactionByEventIdRequest
def flatTransactionByEventId(request: GetTransactionByEventIdRequest): Future[Transaction] = ): Future[Transaction] =
services.transaction services.transaction
.getFlatTransactionByEventId(request) .getFlatTransactionByEventId(request)
.map(_.getTransaction) .map(_.getTransaction)
/** Managed version of [[flatTransactionByEventId]], use this unless you need to tweak the request (i.e. to test low-level details) override def flatTransactionByEventId(eventId: String, parties: Party*): Future[Transaction] =
*/
def flatTransactionByEventId(eventId: String, parties: Party*): Future[Transaction] =
flatTransactionByEventId(getTransactionByEventIdRequest(eventId, parties)) flatTransactionByEventId(getTransactionByEventIdRequest(eventId, parties))
private def extractContracts[T](transaction: Transaction): Seq[Primitive.ContractId[T]] = private def extractContracts[T](transaction: Transaction): Seq[Primitive.ContractId[T]] =
@ -506,7 +419,7 @@ final class ParticipantTestContext private[participant] (
Primitive.ContractId(e.contractId) Primitive.ContractId(e.contractId)
} }
def create[T]( override def create[T](
party: Party, party: Party,
template: Template[T], template: Template[T],
): Future[Primitive.ContractId[T]] = ): Future[Primitive.ContractId[T]] =
@ -515,7 +428,7 @@ final class ParticipantTestContext private[participant] (
) )
.map(response => extractContracts(response.getTransaction).head) .map(response => extractContracts(response.getTransaction).head)
def create[T]( override def create[T](
actAs: List[Party], actAs: List[Party],
readAs: List[Party], readAs: List[Party],
template: Template[T], template: Template[T],
@ -524,7 +437,7 @@ final class ParticipantTestContext private[participant] (
submitAndWaitRequest(actAs, readAs, template.create.command) submitAndWaitRequest(actAs, readAs, template.create.command)
).map(response => extractContracts(response.getTransaction).head) ).map(response => extractContracts(response.getTransaction).head)
def createAndGetTransactionId[T]( override def createAndGetTransactionId[T](
party: Party, party: Party,
template: Template[T], template: Template[T],
): Future[(String, Primitive.ContractId[T])] = ): Future[(String, Primitive.ContractId[T])] =
@ -538,7 +451,7 @@ final class ParticipantTestContext private[participant] (
}.head }.head
) )
def exercise[T]( override def exercise[T](
party: Party, party: Party,
exercise: Party => Primitive.Update[T], exercise: Party => Primitive.Update[T],
): Future[TransactionTree] = ): Future[TransactionTree] =
@ -546,7 +459,7 @@ final class ParticipantTestContext private[participant] (
submitAndWaitRequest(party, exercise(party).command) submitAndWaitRequest(party, exercise(party).command)
).map(_.getTransaction) ).map(_.getTransaction)
def exercise[T]( override def exercise[T](
actAs: List[Party], actAs: List[Party],
readAs: List[Party], readAs: List[Party],
exercise: => Primitive.Update[T], exercise: => Primitive.Update[T],
@ -555,7 +468,7 @@ final class ParticipantTestContext private[participant] (
submitAndWaitRequest(actAs, readAs, exercise.command) submitAndWaitRequest(actAs, readAs, exercise.command)
).map(_.getTransaction) ).map(_.getTransaction)
def exerciseForFlatTransaction[T]( override def exerciseForFlatTransaction[T](
party: Party, party: Party,
exercise: Party => Primitive.Update[T], exercise: Party => Primitive.Update[T],
): Future[Transaction] = ): Future[Transaction] =
@ -563,7 +476,7 @@ final class ParticipantTestContext private[participant] (
submitAndWaitRequest(party, exercise(party).command) submitAndWaitRequest(party, exercise(party).command)
).map(_.getTransaction) ).map(_.getTransaction)
def exerciseAndGetContract[T]( override def exerciseAndGetContract[T](
party: Party, party: Party,
exercise: Party => Primitive.Update[Any], exercise: Party => Primitive.Update[Any],
): Future[Primitive.ContractId[T]] = ): Future[Primitive.ContractId[T]] =
@ -574,7 +487,7 @@ final class ParticipantTestContext private[participant] (
.map(extractContracts) .map(extractContracts)
.map(_.head.asInstanceOf[Primitive.ContractId[T]]) .map(_.head.asInstanceOf[Primitive.ContractId[T]])
def exerciseByKey[T]( override def exerciseByKey[T](
party: Party, party: Party,
template: Primitive.TemplateId[T], template: Primitive.TemplateId[T],
key: Value, key: Value,
@ -597,7 +510,11 @@ final class ParticipantTestContext private[participant] (
) )
).map(_.getTransaction) ).map(_.getTransaction)
def submitRequest(actAs: List[Party], readAs: List[Party], commands: Command*): SubmitRequest = override def submitRequest(
actAs: List[Party],
readAs: List[Party],
commands: Command*
): SubmitRequest =
new SubmitRequest( new SubmitRequest(
Some( Some(
new Commands( new Commands(
@ -613,7 +530,7 @@ final class ParticipantTestContext private[participant] (
) )
) )
def submitRequest(party: Party, commands: Command*): SubmitRequest = override def submitRequest(party: Party, commands: Command*): SubmitRequest =
new SubmitRequest( new SubmitRequest(
Some( Some(
new Commands( new Commands(
@ -628,7 +545,7 @@ final class ParticipantTestContext private[participant] (
) )
) )
def submitAndWaitRequest( override def submitAndWaitRequest(
actAs: List[Party], actAs: List[Party],
readAs: List[Party], readAs: List[Party],
commands: Command* commands: Command*
@ -648,7 +565,7 @@ final class ParticipantTestContext private[participant] (
) )
) )
def submitAndWaitRequest(party: Party, commands: Command*): SubmitAndWaitRequest = override def submitAndWaitRequest(party: Party, commands: Command*): SubmitAndWaitRequest =
new SubmitAndWaitRequest( new SubmitAndWaitRequest(
Some( Some(
new Commands( new Commands(
@ -663,50 +580,52 @@ final class ParticipantTestContext private[participant] (
) )
) )
def submit(request: SubmitRequest): Future[Unit] = override def submit(request: SubmitRequest): Future[Unit] =
services.commandSubmission.submit(request).map(_ => ()) services.commandSubmission.submit(request).map(_ => ())
def submitAndWait(request: SubmitAndWaitRequest): Future[Unit] = override def submitAndWait(request: SubmitAndWaitRequest): Future[Unit] =
services.command.submitAndWait(request).map(_ => ()) services.command.submitAndWait(request).map(_ => ())
def submitAndWaitForTransactionId( override def submitAndWaitForTransactionId(
request: SubmitAndWaitRequest request: SubmitAndWaitRequest
): Future[SubmitAndWaitForTransactionIdResponse] = ): Future[SubmitAndWaitForTransactionIdResponse] =
services.command.submitAndWaitForTransactionId(request) services.command.submitAndWaitForTransactionId(request)
def submitAndWaitForTransaction( override def submitAndWaitForTransaction(
request: SubmitAndWaitRequest request: SubmitAndWaitRequest
): Future[SubmitAndWaitForTransactionResponse] = ): Future[SubmitAndWaitForTransactionResponse] =
services.command.submitAndWaitForTransaction(request) services.command.submitAndWaitForTransaction(request)
def submitAndWaitForTransactionTree( override def submitAndWaitForTransactionTree(
request: SubmitAndWaitRequest request: SubmitAndWaitRequest
): Future[SubmitAndWaitForTransactionTreeResponse] = ): Future[SubmitAndWaitForTransactionTreeResponse] =
services.command services.command
.submitAndWaitForTransactionTree(request) .submitAndWaitForTransactionTree(request)
def completionStreamRequest(from: LedgerOffset = referenceOffset)(parties: Party*) = override def completionStreamRequest(from: LedgerOffset = referenceOffset)(
parties: Party*
): CompletionStreamRequest =
new CompletionStreamRequest(ledgerId, applicationId, parties.map(_.unwrap), Some(from)) new CompletionStreamRequest(ledgerId, applicationId, parties.map(_.unwrap), Some(from))
def completionEnd(request: CompletionEndRequest): Future[CompletionEndResponse] = override def completionEnd(request: CompletionEndRequest): Future[CompletionEndResponse] =
services.commandCompletion.completionEnd(request) services.commandCompletion.completionEnd(request)
def completionStream( override def completionStream(
request: CompletionStreamRequest, request: CompletionStreamRequest,
streamObserver: StreamObserver[CompletionStreamResponse], streamObserver: StreamObserver[CompletionStreamResponse],
): Unit = ): Unit =
services.commandCompletion.completionStream(request, streamObserver) services.commandCompletion.completionStream(request, streamObserver)
def firstCompletions(request: CompletionStreamRequest): Future[Vector[Completion]] = override def firstCompletions(request: CompletionStreamRequest): Future[Vector[Completion]] =
new StreamConsumer[CompletionStreamResponse]( new StreamConsumer[CompletionStreamResponse](
services.commandCompletion.completionStream(request, _) services.commandCompletion.completionStream(request, _)
).find(_.completions.nonEmpty) ).find(_.completions.nonEmpty)
.map(_.completions.toVector) .map(_.completions.toVector)
def firstCompletions(parties: Party*): Future[Vector[Completion]] = override def firstCompletions(parties: Party*): Future[Vector[Completion]] =
firstCompletions(completionStreamRequest()(parties: _*)) firstCompletions(completionStreamRequest()(parties: _*))
def findCompletionAtOffset( override def findCompletionAtOffset(
offset: Ref.HexString, offset: Ref.HexString,
p: Completion => Boolean, p: Completion => Boolean,
)(parties: Party*): Future[Option[CompletionResponse]] = { )(parties: Party*): Future[Option[CompletionResponse]] = {
@ -720,7 +639,7 @@ final class ParticipantTestContext private[participant] (
findCompletion(reportedOffsetCompletionStreamRequest)(p) findCompletion(reportedOffsetCompletionStreamRequest)(p)
} }
def findCompletion( override def findCompletion(
request: CompletionStreamRequest request: CompletionStreamRequest
)(p: Completion => Boolean): Future[Option[CompletionResponse]] = )(p: Completion => Boolean): Future[Option[CompletionResponse]] =
new StreamConsumer[CompletionStreamResponse]( new StreamConsumer[CompletionStreamResponse](
@ -733,35 +652,35 @@ final class ParticipantTestContext private[participant] (
.map(CompletionResponse(_, checkpoint.getOffset, checkpoint.getRecordTime.asJava)) .map(CompletionResponse(_, checkpoint.getOffset, checkpoint.getRecordTime.asJava))
}) })
def findCompletion(parties: Party*)( override def findCompletion(parties: Party*)(
p: Completion => Boolean p: Completion => Boolean
): Future[Option[CompletionResponse]] = ): Future[Option[CompletionResponse]] =
findCompletion(completionStreamRequest()(parties: _*))(p) findCompletion(completionStreamRequest()(parties: _*))(p)
def checkpoints(n: Int, request: CompletionStreamRequest): Future[Vector[Checkpoint]] = override def checkpoints(n: Int, request: CompletionStreamRequest): Future[Vector[Checkpoint]] =
new StreamConsumer[CompletionStreamResponse]( new StreamConsumer[CompletionStreamResponse](
services.commandCompletion.completionStream(request, _) services.commandCompletion.completionStream(request, _)
).filterTake(_.checkpoint.isDefined)(n) ).filterTake(_.checkpoint.isDefined)(n)
.map(_.map(_.getCheckpoint)) .map(_.map(_.getCheckpoint))
def checkpoints(n: Int, from: LedgerOffset = referenceOffset)( override def checkpoints(n: Int, from: LedgerOffset)(
parties: Party* parties: Party*
): Future[Vector[Checkpoint]] = ): Future[Vector[Checkpoint]] =
checkpoints(n, completionStreamRequest(from)(parties: _*)) checkpoints(n, completionStreamRequest(from)(parties: _*))
def firstCheckpoint(request: CompletionStreamRequest): Future[Checkpoint] = override def firstCheckpoint(request: CompletionStreamRequest): Future[Checkpoint] =
checkpoints(1, request).map(_.head) checkpoints(1, request).map(_.head)
def firstCheckpoint(parties: Party*): Future[Checkpoint] = override def firstCheckpoint(parties: Party*): Future[Checkpoint] =
firstCheckpoint(completionStreamRequest()(parties: _*)) firstCheckpoint(completionStreamRequest()(parties: _*))
def nextCheckpoint(request: CompletionStreamRequest): Future[Checkpoint] = override def nextCheckpoint(request: CompletionStreamRequest): Future[Checkpoint] =
checkpoints(1, request).map(_.head) checkpoints(1, request).map(_.head)
def nextCheckpoint(from: LedgerOffset, parties: Party*): Future[Checkpoint] = override def nextCheckpoint(from: LedgerOffset, parties: Party*): Future[Checkpoint] =
nextCheckpoint(completionStreamRequest(from)(parties: _*)) nextCheckpoint(completionStreamRequest(from)(parties: _*))
def configuration(overrideLedgerId: Option[String] = None): Future[LedgerConfiguration] = override def configuration(overrideLedgerId: Option[String] = None): Future[LedgerConfiguration] =
new StreamConsumer[GetLedgerConfigurationResponse]( new StreamConsumer[GetLedgerConfigurationResponse](
services.configuration services.configuration
.getLedgerConfiguration( .getLedgerConfiguration(
@ -771,39 +690,39 @@ final class ParticipantTestContext private[participant] (
).first() ).first()
.map(_.fold(sys.error("No ledger configuration available."))(_.getLedgerConfiguration)) .map(_.fold(sys.error("No ledger configuration available."))(_.getLedgerConfiguration))
def checkHealth(): Future[HealthCheckResponse] = override def checkHealth(): Future[HealthCheckResponse] =
services.health.check(HealthCheckRequest()) services.health.check(HealthCheckRequest())
def watchHealth(): Future[Seq[HealthCheckResponse]] = override def watchHealth(): Future[Seq[HealthCheckResponse]] =
new StreamConsumer[HealthCheckResponse](services.health.watch(HealthCheckRequest(), _)) new StreamConsumer[HealthCheckResponse](services.health.watch(HealthCheckRequest(), _))
.within(1.second) .within(1.second)
def getTimeModel(): Future[GetTimeModelResponse] = override def getTimeModel(): Future[GetTimeModelResponse] =
services.configManagement.getTimeModel(GetTimeModelRequest()) services.configManagement.getTimeModel(GetTimeModelRequest())
def setTimeModel( override def setTimeModel(
mrt: Instant, mrt: Instant,
generation: Long, generation: Long,
newTimeModel: TimeModel, newTimeModel: TimeModel,
): Future[SetTimeModelResponse] = ): Future[SetTimeModelResponse] =
setTimeModel(setTimeModelRequest(mrt, generation, newTimeModel)) setTimeModel(setTimeModelRequest(mrt, generation, newTimeModel))
def setTimeModelRequest( override def setTimeModelRequest(
mrt: Instant, mrt: Instant,
generation: Long, generation: Long,
newTimeModel: TimeModel, newTimeModel: TimeModel,
): SetTimeModelRequest = ): SetTimeModelRequest =
SetTimeModelRequest(nextSubmissionId(), Some(mrt.asProtobuf), generation, Some(newTimeModel)) SetTimeModelRequest(nextSubmissionId(), Some(mrt.asProtobuf), generation, Some(newTimeModel))
def setTimeModel( override def setTimeModel(
request: SetTimeModelRequest request: SetTimeModelRequest
): Future[SetTimeModelResponse] = ): Future[SetTimeModelResponse] =
services.configManagement.setTimeModel(request) services.configManagement.setTimeModel(request)
def prune( override def prune(
pruneUpTo: String, pruneUpTo: LedgerOffset,
attempts: Int, attempts: Int = 10,
pruneAllDivulgedContracts: Boolean, pruneAllDivulgedContracts: Boolean = false,
): Future[PruneResponse] = ): Future[PruneResponse] =
// Distributed ledger participants need to reach global consensus prior to pruning. Hence the "eventually" here: // Distributed ledger participants need to reach global consensus prior to pruning. Hence the "eventually" here:
eventually( eventually(
@ -811,7 +730,7 @@ final class ParticipantTestContext private[participant] (
runAssertion = { runAssertion = {
services.participantPruning services.participantPruning
.prune( .prune(
PruneRequest(pruneUpTo, nextSubmissionId(), pruneAllDivulgedContracts) PruneRequest(pruneUpTo.getAbsolute, nextSubmissionId(), pruneAllDivulgedContracts)
) )
.andThen { case Failure(exception) => .andThen { case Failure(exception) =>
logger.warn("Failed to prune", exception)(LoggingContext.ForTesting) logger.warn("Failed to prune", exception)(LoggingContext.ForTesting)
@ -819,14 +738,7 @@ final class ParticipantTestContext private[participant] (
}, },
) )
def prune( private[infrastructure] override def preallocateParties(
pruneUpTo: LedgerOffset,
attempts: Int = 10,
pruneAllDivulgedContracts: Boolean = false,
): Future[PruneResponse] =
prune(pruneUpTo.getAbsolute, attempts, pruneAllDivulgedContracts)
private[infrastructure] def preallocateParties(
n: Int, n: Int,
participants: Iterable[ParticipantTestContext], participants: Iterable[ParticipantTestContext],
): Future[Vector[Party]] = ): Future[Vector[Party]] =
@ -844,4 +756,18 @@ final class ParticipantTestContext private[participant] (
Future.successful(Vector.fill(n)(Party(nextPartyHintId()))) Future.successful(Vector.fill(n)(Party(nextPartyHintId())))
} }
case class CompletionResponse(completion: Completion, offset: LedgerOffset, recordTime: Instant) private[testtool] object SingleParticipantTestContext {
private[this] def filter(templateIds: Seq[Identifier]): Filters =
new Filters(
if (templateIds.isEmpty) None
else Some(new InclusiveFilters(templateIds))
)
private def transactionFilter(
parties: Seq[String],
templateIds: Seq[Identifier],
): Some[TransactionFilter] =
Some(new TransactionFilter(Map(parties.map(_ -> filter(templateIds)): _*)))
}

View File

@ -187,7 +187,6 @@ final class TestRunner(availableTests: AvailableTests, config: Config) {
concurrentTestRuns = concurrentTestRuns, concurrentTestRuns = concurrentTestRuns,
uploadDars = config.uploadDars, uploadDars = config.uploadDars,
identifierSuffix = identifierSuffix, identifierSuffix = identifierSuffix,
clientTlsConfiguration = config.tlsConfig,
) )
) )
} }

View File

@ -4,6 +4,7 @@
package com.daml.ledger.api.testtool.suites package com.daml.ledger.api.testtool.suites
import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite
import com.daml.ledger.api.tls.TlsConfiguration
package object v1_14 { package object v1_14 {
def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] = def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] =
@ -12,6 +13,6 @@ package object v1_14 {
new ExceptionsIT, new ExceptionsIT,
)).sortBy(_.name) )).sortBy(_.name)
def optional(): Vector[LedgerTestSuite] = def optional(tlsConfig: Option[TlsConfiguration]): Vector[LedgerTestSuite] =
v1_8.optional() v1_8.optional(tlsConfig)
} }

View File

@ -4,6 +4,7 @@
package com.daml.ledger.api.testtool.suites package com.daml.ledger.api.testtool.suites
import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite
import com.daml.ledger.api.tls.TlsConfiguration
package object v1_8 { package object v1_8 {
def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] = def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] =
@ -49,9 +50,9 @@ package object v1_8 {
new WronglyTypedContractIdIT, new WronglyTypedContractIdIT,
) )
def optional(): Vector[LedgerTestSuite] = def optional(tlsConfiguration: Option[TlsConfiguration]): Vector[LedgerTestSuite] =
Vector( Vector(
new TLSOnePointThreeIT, new TLSOnePointThreeIT(tlsConfiguration),
new TLSAtLeastOnePointTwoIT, new TLSAtLeastOnePointTwoIT(tlsConfiguration),
) )
} }

View File

@ -18,10 +18,8 @@ import com.daml.ledger.api.testtool.infrastructure.assertions.CommandDeduplicati
assertDeduplicationDuration, assertDeduplicationDuration,
assertDeduplicationOffset, assertDeduplicationOffset,
} }
import com.daml.ledger.api.testtool.infrastructure.participant.{ import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext
CompletionResponse, import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext.CompletionResponse
ParticipantTestContext,
}
import com.daml.ledger.api.testtool.infrastructure.time.DelayMechanism import com.daml.ledger.api.testtool.infrastructure.time.DelayMechanism
import com.daml.ledger.api.v1.admin.config_management_service.TimeModel import com.daml.ledger.api.v1.admin.config_management_service.TimeModel
import com.daml.ledger.api.v1.command_service.SubmitAndWaitRequest import com.daml.ledger.api.v1.command_service.SubmitAndWaitRequest

View File

@ -34,7 +34,11 @@ class ParticipantPruningIT extends LedgerTestSuite {
)(implicit ec => { case Participants(Participant(participant)) => )(implicit ec => { case Participants(Participant(participant)) =>
for { for {
failure <- participant failure <- participant
.prune("", attempts = 1, pruneAllDivulgedContracts = true) .prune(
LedgerOffset(LedgerOffset.Value.Absolute("")),
attempts = 1,
pruneAllDivulgedContracts = true,
)
.mustFail("pruning without specifying an offset") .mustFail("pruning without specifying an offset")
} yield { } yield {
assertGrpcError( assertGrpcError(
@ -52,7 +56,11 @@ class ParticipantPruningIT extends LedgerTestSuite {
)(implicit ec => { case Participants(Participant(participant)) => )(implicit ec => { case Participants(Participant(participant)) =>
for { for {
cannotPruneNonHexOffset <- participant cannotPruneNonHexOffset <- participant
.prune("covfefe", attempts = 1, pruneAllDivulgedContracts = true) .prune(
LedgerOffset(LedgerOffset.Value.Absolute("covfefe")),
attempts = 1,
pruneAllDivulgedContracts = true,
)
.mustFail("pruning, specifying a non-hexadecimal offset") .mustFail("pruning, specifying a non-hexadecimal offset")
} yield { } yield {
assertGrpcError( assertGrpcError(

View File

@ -6,7 +6,7 @@ package com.daml.ledger.api.testtool.suites.v1_8
import com.daml.ledger.api.testtool.infrastructure.Allocation.{NoParties, allocate} import com.daml.ledger.api.testtool.infrastructure.Allocation.{NoParties, allocate}
import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext
import com.daml.ledger.api.testtool.infrastructure.{Endpoint, LedgerTestSuite} import com.daml.ledger.api.testtool.infrastructure.{Endpoint, LedgerTestSuite}
import com.daml.ledger.api.tls.TlsVersion import com.daml.ledger.api.tls.{TlsConfiguration, TlsVersion}
import com.daml.ledger.api.tls.TlsVersion.TlsVersion import com.daml.ledger.api.tls.TlsVersion.TlsVersion
import com.daml.ledger.api.v1.ledger_identity_service.LedgerIdentityServiceGrpc.LedgerIdentityServiceBlockingStub import com.daml.ledger.api.v1.ledger_identity_service.LedgerIdentityServiceGrpc.LedgerIdentityServiceBlockingStub
import com.daml.ledger.api.v1.ledger_identity_service.{ import com.daml.ledger.api.v1.ledger_identity_service.{
@ -26,8 +26,12 @@ import scala.util.{Failure, Success, Try}
* - accepts TLSv1.3 connections, * - accepts TLSv1.3 connections,
* - rejects TLSv1.2 (or lower) connections. * - rejects TLSv1.2 (or lower) connections.
*/ */
final class TLSOnePointThreeIT final class TLSOnePointThreeIT(
extends TlsIT(shortIdentifierPrefix = "ServerOnTLSv13ConnectionFromClientOn") { clientTlsConfiguration: Option[TlsConfiguration]
) extends TlsIT(
shortIdentifierPrefix = "ServerOnTLSv13ConnectionFromClientOn",
clientTlsConfiguration,
) {
testTlsConnection( testTlsConnection(
clientTlsVersions = Seq[TlsVersion](TlsVersion.V1_2, TlsVersion.V1_3), clientTlsVersions = Seq[TlsVersion](TlsVersion.V1_2, TlsVersion.V1_3),
assertConnectionOk = true, assertConnectionOk = true,
@ -42,8 +46,12 @@ final class TLSOnePointThreeIT
* - accepts either TLSv1.2 or TLSv1.3 connections, * - accepts either TLSv1.2 or TLSv1.3 connections,
* - rejects TLSv1.1 (or lower) connections. * - rejects TLSv1.1 (or lower) connections.
*/ */
final class TLSAtLeastOnePointTwoIT final class TLSAtLeastOnePointTwoIT(
extends TlsIT(shortIdentifierPrefix = "ServerOnTLSConnectionFromClientOn") { clientTlsConfiguration: Option[TlsConfiguration]
) extends TlsIT(
shortIdentifierPrefix = "ServerOnTLSConnectionFromClientOn",
clientTlsConfiguration,
) {
testTlsConnection( testTlsConnection(
clientTlsVersions = Seq[TlsVersion](TlsVersion.V1_2, TlsVersion.V1_3), clientTlsVersions = Seq[TlsVersion](TlsVersion.V1_2, TlsVersion.V1_3),
assertConnectionOk = true, assertConnectionOk = true,
@ -58,7 +66,10 @@ final class TLSAtLeastOnePointTwoIT
* *
* It works by creating and exercising a series of client service stubs, each over different TLS version. * It works by creating and exercising a series of client service stubs, each over different TLS version.
*/ */
abstract class TlsIT(shortIdentifierPrefix: String) extends LedgerTestSuite { abstract class TlsIT(
shortIdentifierPrefix: String,
clientTlsConfiguration: Option[TlsConfiguration],
) extends LedgerTestSuite {
def testTlsConnection(clientTlsVersion: TlsVersion, assertConnectionOk: Boolean): Unit = { def testTlsConnection(clientTlsVersion: TlsVersion, assertConnectionOk: Boolean): Unit = {
testTlsConnection( testTlsConnection(
@ -89,10 +100,10 @@ abstract class TlsIT(shortIdentifierPrefix: String) extends LedgerTestSuite {
assume(testContexts.nonEmpty, "Missing an expected participant test context!") assume(testContexts.nonEmpty, "Missing an expected participant test context!")
val firstTextContext = testContexts.head val firstTextContext = testContexts.head
assume( assume(
firstTextContext.clientTlsConfiguration.isDefined, clientTlsConfiguration.isDefined,
"Missing required TLS configuration!", "Missing required TLS configuration!",
) )
val tlsConfiguration = firstTextContext.clientTlsConfiguration.get val tlsConfiguration = clientTlsConfiguration.get
assume( assume(
tlsConfiguration.enabled, tlsConfiguration.enabled,
"TLS configuration is disabled but expected to be enabled!", "TLS configuration is disabled but expected to be enabled!",

View File

@ -4,11 +4,12 @@
package com.daml.ledger.api.testtool.suites package com.daml.ledger.api.testtool.suites
import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite
import com.daml.ledger.api.tls.TlsConfiguration
package object v1_dev { package object v1_dev {
def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] = def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] =
v1_14.default(timeoutScaleFactor) v1_14.default(timeoutScaleFactor)
def optional(): Vector[LedgerTestSuite] = def optional(tlsConfig: Option[TlsConfiguration]): Vector[LedgerTestSuite] =
v1_14.optional() v1_14.optional(tlsConfig)
} }

View File

@ -42,7 +42,8 @@ class NamesSpec extends AnyWordSpec with Matchers {
} }
object NamesSpec { object NamesSpec {
private val allTestSuites = v1_dev.default(timeoutScaleFactor = 1) ++ v1_dev.optional() private val allTestSuites =
v1_dev.default(timeoutScaleFactor = 1) ++ v1_dev.optional(tlsConfig = None)
private val allTestSuiteNames = allTestSuites.map(_.name).sorted private val allTestSuiteNames = allTestSuites.map(_.name).sorted
private val allTests = allTestSuites.flatMap(_.tests) private val allTests = allTestSuites.flatMap(_.tests)

View File

@ -4,11 +4,12 @@
package com.daml.ledger.api.testtool package com.daml.ledger.api.testtool
import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite
import com.daml.ledger.api.tls.TlsConfiguration
object Tests { object Tests {
def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] = def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] =
suites.v1_14.default(timeoutScaleFactor) suites.v1_14.default(timeoutScaleFactor)
def optional(): Vector[LedgerTestSuite] = def optional(tlsConfig: Option[TlsConfiguration]): Vector[LedgerTestSuite] =
suites.v1_14.optional() suites.v1_14.optional(tlsConfig)
} }

View File

@ -4,11 +4,12 @@
package com.daml.ledger.api.testtool package com.daml.ledger.api.testtool
import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite
import com.daml.ledger.api.tls.TlsConfiguration
object Tests { object Tests {
def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] = def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] =
suites.v1_8.default(timeoutScaleFactor) suites.v1_8.default(timeoutScaleFactor)
def optional(): Vector[LedgerTestSuite] = def optional(tlsConfig: Option[TlsConfiguration]): Vector[LedgerTestSuite] =
suites.v1_8.optional() suites.v1_8.optional(tlsConfig)
} }

View File

@ -4,11 +4,12 @@
package com.daml.ledger.api.testtool package com.daml.ledger.api.testtool
import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite
import com.daml.ledger.api.tls.TlsConfiguration
object Tests { object Tests {
def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] = def default(timeoutScaleFactor: Double): Vector[LedgerTestSuite] =
suites.v1_dev.default(timeoutScaleFactor) suites.v1_dev.default(timeoutScaleFactor)
def optional(): Vector[LedgerTestSuite] = def optional(tlsConfig: Option[TlsConfiguration]): Vector[LedgerTestSuite] =
suites.v1_dev.optional() suites.v1_dev.optional(tlsConfig)
} }

View File

@ -14,7 +14,7 @@ object Main {
Tests.default(timeoutScaleFactor = config.timeoutScaleFactor) Tests.default(timeoutScaleFactor = config.timeoutScaleFactor)
override def optionalTests: Vector[LedgerTestSuite] = override def optionalTests: Vector[LedgerTestSuite] =
Tests.optional() Tests.optional(config.tlsConfig)
} }
new TestRunner(availableTests, config).runAndExit() new TestRunner(availableTests, config).runAndExit()
} }

View File

@ -65,7 +65,7 @@ object Main {
val ledgerApiTests = List() val ledgerApiTests = List()
.concat(suites.v1_14.default(timeoutScaleFactor = 0L)) .concat(suites.v1_14.default(timeoutScaleFactor = 0L))
.concat(suites.v1_14.optional()) .concat(suites.v1_14.optional(tlsConfig = None))
val testSuites: List[Suite] = ScalaTestAdapter.loadTestSuites(runpathList) val testSuites: List[Suite] = ScalaTestAdapter.loadTestSuites(runpathList)