mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-09 15:37:05 +03:00
[DPP-572] Add ledger API test case for verifying conformance to --min-tls-version
flag. (#10898)
Add CLI flag to select minimum enabled TLS version for participant server CHANGELOG_BEGIN Sandbox: Add CLI flag `--min-tls-version` to select minimum enabled TLS version for participant server. CHANGELOG_END
This commit is contained in:
parent
3e13e3d87e
commit
855ecdf1a7
@ -91,6 +91,7 @@ da_scala_binary(
|
|||||||
"//ledger/test-common:model-tests-%s.scala" % lf_version,
|
"//ledger/test-common:model-tests-%s.scala" % lf_version,
|
||||||
"//ledger/test-common:dar-files-%s-lib" % lf_version,
|
"//ledger/test-common:dar-files-%s-lib" % lf_version,
|
||||||
"//ledger-api/grpc-definitions:ledger_api_proto_scala",
|
"//ledger-api/grpc-definitions:ledger_api_proto_scala",
|
||||||
|
"//ledger/ledger-api-common",
|
||||||
"//libs-scala/build-info",
|
"//libs-scala/build-info",
|
||||||
"//libs-scala/grpc-utils",
|
"//libs-scala/grpc-utils",
|
||||||
"//libs-scala/resources",
|
"//libs-scala/resources",
|
||||||
@ -124,6 +125,10 @@ da_scala_binary(
|
|||||||
"//daml-lf/data",
|
"//daml-lf/data",
|
||||||
"//language-support/scala/bindings",
|
"//language-support/scala/bindings",
|
||||||
"//ledger/ledger-api-common",
|
"//ledger/ledger-api-common",
|
||||||
|
"//ledger/ledger-resources",
|
||||||
|
"//libs-scala/resources",
|
||||||
|
"//libs-scala/resources-akka",
|
||||||
|
"//libs-scala/resources-grpc",
|
||||||
"//ledger/test-common:test-common-%s" % lf_version,
|
"//ledger/test-common:test-common-%s" % lf_version,
|
||||||
"//ledger/test-common:package_management-tests-%s.scala" % lf_version,
|
"//ledger/test-common:package_management-tests-%s.scala" % lf_version,
|
||||||
"//ledger/test-common:model-tests-%s.scala" % lf_version,
|
"//ledger/test-common:model-tests-%s.scala" % lf_version,
|
||||||
@ -134,6 +139,8 @@ da_scala_binary(
|
|||||||
"//libs-scala/timer-utils",
|
"//libs-scala/timer-utils",
|
||||||
"@maven//:io_grpc_grpc_api",
|
"@maven//:io_grpc_grpc_api",
|
||||||
"@maven//:io_grpc_grpc_context",
|
"@maven//:io_grpc_grpc_context",
|
||||||
|
"@maven//:io_grpc_grpc_netty",
|
||||||
|
"@maven//:io_netty_netty_handler",
|
||||||
"@maven//:org_slf4j_slf4j_api",
|
"@maven//:org_slf4j_slf4j_api",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -245,6 +252,7 @@ conformance_test(
|
|||||||
# Retired tests will be eventually removed.
|
# Retired tests will be eventually removed.
|
||||||
"--additional=LotsOfPartiesIT",
|
"--additional=LotsOfPartiesIT",
|
||||||
"--additional=TransactionScaleIT",
|
"--additional=TransactionScaleIT",
|
||||||
|
"--additional=TLSOnePointThreeIT",
|
||||||
"--exclude=CommandDeduplicationIT",
|
"--exclude=CommandDeduplicationIT",
|
||||||
# Makes sure that deprecated CLI options can still be used to make sure existing CI pipelines are not broken.
|
# Makes sure that deprecated CLI options can still be used to make sure existing CI pipelines are not broken.
|
||||||
# This test should fail if any deprecated CLI option has any effect whatsoever -- they are preserved
|
# This test should fail if any deprecated CLI option has any effect whatsoever -- they are preserved
|
||||||
|
@ -73,11 +73,13 @@ object Cli {
|
|||||||
|
|
||||||
head(
|
head(
|
||||||
"""The Ledger API Test Tool is a command line tool for testing the correctness of
|
"""The Ledger API Test Tool is a command line tool for testing the correctness of
|
||||||
|ledger implementations based on Daml and Ledger API.""".stripMargin
|
|ledger implementations based on Daml and Ledger API.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
arg[(String, Int)]("[endpoints...]")(endpointRead)
|
arg[(String, Int)]("[endpoints...]")(endpointRead)
|
||||||
.action((address, config) => config.copy(participants = config.participants :+ address))
|
.action((address, config) =>
|
||||||
|
config.copy(participantsEndpoints = config.participantsEndpoints :+ address)
|
||||||
|
)
|
||||||
.unbounded()
|
.unbounded()
|
||||||
.optional()
|
.optional()
|
||||||
.text("Addresses of the participants to test, specified as `<host>:<port>`.")
|
.text("Addresses of the participants to test, specified as `<host>:<port>`.")
|
||||||
@ -105,7 +107,7 @@ object Cli {
|
|||||||
.optional()
|
.optional()
|
||||||
.text(
|
.text(
|
||||||
"""TLS: The crt file to be used as the cert chain.
|
"""TLS: The crt file to be used as the cert chain.
|
||||||
|Required if any other TLS parameters are set. Applied to all endpoints.""".stripMargin
|
|Required if any other TLS parameters are set. Applied to all endpoints.""".stripMargin
|
||||||
)
|
)
|
||||||
.action(crtConfig)
|
.action(crtConfig)
|
||||||
|
|
||||||
@ -119,9 +121,9 @@ object Cli {
|
|||||||
.action((v, c) => c.copy(timeoutScaleFactor = v))
|
.action((v, c) => c.copy(timeoutScaleFactor = v))
|
||||||
.text(
|
.text(
|
||||||
"""Scale factor for timeouts used in all test suites. Useful to tune timeouts
|
"""Scale factor for timeouts used in all test suites. Useful to tune timeouts
|
||||||
|depending on the environment and the Ledger implementation under test.
|
|depending on the environment and the Ledger implementation under test.
|
||||||
|Defaults to 1.0. Use numbers higher than 1.0 to make test timeouts more lax,
|
|Defaults to 1.0. Use numbers higher than 1.0 to make test timeouts more lax,
|
||||||
|use numbers lower than 1.0 to make test timeouts more strict.""".stripMargin
|
|use numbers lower than 1.0 to make test timeouts more strict.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[String](name = "load-scale-factor")
|
opt[String](name = "load-scale-factor")
|
||||||
@ -144,16 +146,16 @@ object Cli {
|
|||||||
.action((_, c) => c.copy(mustFail = true))
|
.action((_, c) => c.copy(mustFail = true))
|
||||||
.text(
|
.text(
|
||||||
"""Reverse success status logic of the tool. Use this flag if you expect one or
|
"""Reverse success status logic of the tool. Use this flag if you expect one or
|
||||||
|more or the scenario tests to fail. If enabled, the tool will succeed when at
|
|more or the scenario tests to fail. If enabled, the tool will succeed when at
|
||||||
|least one test fails, and it will fail when all tests succeed. Defaults to
|
|least one test fails, and it will fail when all tests succeed. Defaults to
|
||||||
|false.""".stripMargin
|
|false.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Unit]('x', "extract")
|
opt[Unit]('x', "extract")
|
||||||
.action((_, c) => c.copy(extract = true))
|
.action((_, c) => c.copy(extract = true))
|
||||||
.text(
|
.text(
|
||||||
"""Extract a DAR necessary to test a Daml ledger and exit without running tests.
|
"""Extract a DAR necessary to test a Daml ledger and exit without running tests.
|
||||||
|The DAR needs to be manually loaded into a Daml ledger for the tool to work.""".stripMargin
|
|The DAR needs to be manually loaded into a Daml ledger for the tool to work.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Seq[String]]("exclude")
|
opt[Seq[String]]("exclude")
|
||||||
@ -161,8 +163,8 @@ object Cli {
|
|||||||
.unbounded()
|
.unbounded()
|
||||||
.text(
|
.text(
|
||||||
"""A comma-separated list of exclusion prefixes. Tests whose name start with
|
"""A comma-separated list of exclusion prefixes. Tests whose name start with
|
||||||
|any of the given prefixes will be skipped. Can be specified multiple times,
|
|any of the given prefixes will be skipped. Can be specified multiple times,
|
||||||
|i.e. `--exclude=a,b` is the same as `--exclude=a --exclude=b`.""".stripMargin
|
|i.e. `--exclude=a,b` is the same as `--exclude=a --exclude=b`.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Seq[String]]("include")
|
opt[Seq[String]]("include")
|
||||||
@ -170,10 +172,10 @@ object Cli {
|
|||||||
.unbounded()
|
.unbounded()
|
||||||
.text(
|
.text(
|
||||||
"""A comma-separated list of inclusion prefixes. If not specified,
|
"""A comma-separated list of inclusion prefixes. If not specified,
|
||||||
|all default tests are included. If specified, only tests that match at least one
|
|all default tests are included. If specified, only tests that match at least one
|
||||||
|of the given inclusion prefixes (and none of the given exclusion prefixes) will be run.
|
|of the given inclusion prefixes (and none of the given exclusion prefixes) will be run.
|
||||||
|Can be specified multiple times, i.e. `--include=a,b` is the same as `--include=a --include=b`.
|
|Can be specified multiple times, i.e. `--include=a,b` is the same as `--include=a --include=b`.
|
||||||
|Mutually exclusive with `--additional`.""".stripMargin
|
|Mutually exclusive with `--additional`.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Seq[String]]("additional")
|
opt[Seq[String]]("additional")
|
||||||
@ -182,9 +184,9 @@ object Cli {
|
|||||||
.unbounded()
|
.unbounded()
|
||||||
.text(
|
.text(
|
||||||
"""A comma-separated list of additional prefixes. If specified, also tests that match at least one
|
"""A comma-separated list of additional prefixes. If specified, also tests that match at least one
|
||||||
|of the given inclusion prefixes (and none of the given exclusion prefixes) will be run.
|
|of the given inclusion prefixes (and none of the given exclusion prefixes) will be run.
|
||||||
|Can be specified multiple times, i.e. `--additional=a,b` is the same as `--additional=a --additional=b`.
|
|Can be specified multiple times, i.e. `--additional=a,b` is the same as `--additional=a --additional=b`.
|
||||||
|Mutually exclusive with `--include`.""".stripMargin
|
|Mutually exclusive with `--include`.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Seq[String]]("perf-tests")
|
opt[Seq[String]]("perf-tests")
|
||||||
@ -209,7 +211,7 @@ object Cli {
|
|||||||
.action((_, c) => c.copy(shuffleParticipants = true))
|
.action((_, c) => c.copy(shuffleParticipants = true))
|
||||||
.text(
|
.text(
|
||||||
"""Shuffle the list of participants used in a test.
|
"""Shuffle the list of participants used in a test.
|
||||||
|By default participants are used in the order they're given.""".stripMargin
|
|By default participants are used in the order they're given.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Unit]("no-wait-for-parties")
|
opt[Unit]("no-wait-for-parties")
|
||||||
@ -221,16 +223,16 @@ object Cli {
|
|||||||
.action((_, c) => c.copy(partyAllocation = PartyAllocationConfiguration.OpenWorld))
|
.action((_, c) => c.copy(partyAllocation = PartyAllocationConfiguration.OpenWorld))
|
||||||
.text(
|
.text(
|
||||||
"""Do not allocate parties explicitly.
|
"""Do not allocate parties explicitly.
|
||||||
|Instead, expect the ledger to allocate parties dynamically.
|
|Instead, expect the ledger to allocate parties dynamically.
|
||||||
|Party names must be their hints.""".stripMargin
|
|Party names must be their hints.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Unit]("list")
|
opt[Unit]("list")
|
||||||
.action((_, c) => c.copy(listTestSuites = true))
|
.action((_, c) => c.copy(listTestSuites = true))
|
||||||
.text(
|
.text(
|
||||||
"""Lists all available test suites that can be used in the include and exclude options.
|
"""Lists all available test suites that can be used in the include and exclude options.
|
||||||
|Test names always start with their suite name, so using the suite name as a prefix
|
|Test names always start with their suite name, so using the suite name as a prefix
|
||||||
|matches all tests in a given suite.""".stripMargin
|
|matches all tests in a given suite.""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Unit]("list-all")
|
opt[Unit]("list-all")
|
||||||
@ -252,7 +254,7 @@ object Cli {
|
|||||||
.action((x, c) => c.copy(ledgerClockGranularity = x))
|
.action((x, c) => c.copy(ledgerClockGranularity = x))
|
||||||
.text(
|
.text(
|
||||||
"""Specify the largest interval that you will see between clock ticks
|
"""Specify the largest interval that you will see between clock ticks
|
||||||
|on the ledger under test. The default is \"1s\" (1 second).""".stripMargin
|
|on the ledger under test. The default is \"1s\" (1 second).""".stripMargin
|
||||||
)
|
)
|
||||||
|
|
||||||
opt[Unit]("skip-dar-upload")
|
opt[Unit]("skip-dar-upload")
|
||||||
|
@ -3,16 +3,15 @@
|
|||||||
|
|
||||||
package com.daml.ledger.api.testtool
|
package com.daml.ledger.api.testtool
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
import com.daml.ledger.api.testtool.infrastructure.PartyAllocationConfiguration
|
import com.daml.ledger.api.testtool.infrastructure.PartyAllocationConfiguration
|
||||||
import com.daml.ledger.api.tls.TlsConfiguration
|
import com.daml.ledger.api.tls.TlsConfiguration
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Path
|
||||||
import scala.concurrent.duration.FiniteDuration
|
import scala.concurrent.duration.FiniteDuration
|
||||||
|
|
||||||
final case class Config(
|
final case class Config(
|
||||||
participants: Vector[(String, Int)],
|
participantsEndpoints: Vector[(String, Int)],
|
||||||
maxConnectionAttempts: Int,
|
maxConnectionAttempts: Int,
|
||||||
darPackages: List[File],
|
darPackages: List[File],
|
||||||
mustFail: Boolean,
|
mustFail: Boolean,
|
||||||
@ -32,11 +31,16 @@ final case class Config(
|
|||||||
partyAllocation: PartyAllocationConfiguration,
|
partyAllocation: PartyAllocationConfiguration,
|
||||||
ledgerClockGranularity: FiniteDuration,
|
ledgerClockGranularity: FiniteDuration,
|
||||||
uploadDars: Boolean,
|
uploadDars: Boolean,
|
||||||
)
|
) {
|
||||||
|
def withTlsConfig(modify: TlsConfiguration => TlsConfiguration): Config = {
|
||||||
|
val base = tlsConfig.getOrElse(TlsConfiguration.Empty)
|
||||||
|
copy(tlsConfig = Some(modify(base)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object Config {
|
object Config {
|
||||||
val default: Config = Config(
|
val default: Config = Config(
|
||||||
participants = Vector.empty,
|
participantsEndpoints = Vector.empty,
|
||||||
maxConnectionAttempts = 10,
|
maxConnectionAttempts = 10,
|
||||||
darPackages = Nil,
|
darPackages = Nil,
|
||||||
mustFail = false,
|
mustFail = false,
|
||||||
|
@ -3,10 +3,6 @@
|
|||||||
|
|
||||||
package com.daml.ledger.api.testtool
|
package com.daml.ledger.api.testtool
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.{Files, Paths, StandardCopyOption}
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
import com.daml.ledger.api.testtool.infrastructure.Reporter.ColorizedPrintStreamReporter
|
import com.daml.ledger.api.testtool.infrastructure.Reporter.ColorizedPrintStreamReporter
|
||||||
import com.daml.ledger.api.testtool.infrastructure.Result.Excluded
|
import com.daml.ledger.api.testtool.infrastructure.Result.Excluded
|
||||||
import com.daml.ledger.api.testtool.infrastructure._
|
import com.daml.ledger.api.testtool.infrastructure._
|
||||||
@ -17,6 +13,9 @@ import io.grpc.netty.{NegotiationType, NettyChannelBuilder}
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
import scala.collection.compat._
|
import scala.collection.compat._
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.{Files, Paths, StandardCopyOption}
|
||||||
|
import java.util.concurrent.Executors
|
||||||
import scala.concurrent.duration.DurationInt
|
import scala.concurrent.duration.DurationInt
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
import scala.util.{Failure, Success}
|
import scala.util.{Failure, Success}
|
||||||
@ -57,6 +56,7 @@ object LedgerApiTestTool {
|
|||||||
println()
|
println()
|
||||||
Tests.PerformanceTestsKeys.foreach(println(_))
|
Tests.PerformanceTestsKeys.foreach(println(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def printAvailableTestSuites(testSuites: Vector[LedgerTestSuite]): Unit = {
|
private def printAvailableTestSuites(testSuites: Vector[LedgerTestSuite]): Unit = {
|
||||||
println("Listing test suites. Run with --list-all to see individual tests.")
|
println("Listing test suites. Run with --list-all to see individual tests.")
|
||||||
printListOfTests(testSuites)(_.name)
|
printListOfTests(testSuites)(_.name)
|
||||||
@ -126,7 +126,7 @@ object LedgerApiTestTool {
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.participants.isEmpty) {
|
if (config.participantsEndpoints.isEmpty) {
|
||||||
println("No participant to test, exiting.")
|
println("No participant to test, exiting.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
}
|
}
|
||||||
@ -220,8 +220,11 @@ object LedgerApiTestTool {
|
|||||||
cases: Vector[LedgerTestCase],
|
cases: Vector[LedgerTestCase],
|
||||||
concurrentTestRuns: Int,
|
concurrentTestRuns: Int,
|
||||||
)(implicit executionContext: ExecutionContext): Future[LedgerTestCasesRunner] = {
|
)(implicit executionContext: ExecutionContext): Future[LedgerTestCasesRunner] = {
|
||||||
initializeParticipantChannels(config.participants, config.tlsConfig).asFuture.map(
|
initializeParticipantChannels(
|
||||||
participants =>
|
config.participantsEndpoints,
|
||||||
|
config.tlsConfig,
|
||||||
|
).asFuture
|
||||||
|
.map((participants: Vector[ChannelEndpoint]) =>
|
||||||
new LedgerTestCasesRunner(
|
new LedgerTestCasesRunner(
|
||||||
testCases = cases,
|
testCases = cases,
|
||||||
participants = participants,
|
participants = participants,
|
||||||
@ -232,8 +235,9 @@ object LedgerApiTestTool {
|
|||||||
concurrentTestRuns = concurrentTestRuns,
|
concurrentTestRuns = concurrentTestRuns,
|
||||||
uploadDars = config.uploadDars,
|
uploadDars = config.uploadDars,
|
||||||
identifierSuffix = identifierSuffix,
|
identifierSuffix = identifierSuffix,
|
||||||
|
clientTlsConfiguration = config.tlsConfig,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def initializeParticipantChannel(
|
private def initializeParticipantChannel(
|
||||||
@ -257,12 +261,18 @@ object LedgerApiTestTool {
|
|||||||
private def initializeParticipantChannels(
|
private def initializeParticipantChannels(
|
||||||
participants: Vector[(String, Int)],
|
participants: Vector[(String, Int)],
|
||||||
tlsConfig: Option[TlsConfiguration],
|
tlsConfig: Option[TlsConfiguration],
|
||||||
)(implicit executionContext: ExecutionContext): Resource[Vector[Channel]] = {
|
)(implicit executionContext: ExecutionContext): Resource[Vector[ChannelEndpoint]] = {
|
||||||
val participantChannelOwners =
|
val channelResources: Seq[Resource[ChannelEndpoint]] =
|
||||||
for ((host, port) <- participants) yield {
|
for ((host, port) <- participants) yield {
|
||||||
initializeParticipantChannel(host, port, tlsConfig)
|
val channelOwner: ResourceOwner[Channel] =
|
||||||
|
initializeParticipantChannel(host, port, tlsConfig)
|
||||||
|
channelOwner
|
||||||
|
.acquire()
|
||||||
|
.map(channel =>
|
||||||
|
ChannelEndpoint.forRemote(channel = channel, hostname = host, port = port)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Resource.sequence(participantChannelOwners.map(_.acquire()))
|
Resource.sequence(channelResources)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package com.daml.ledger.api.testtool.infrastructure
|
||||||
|
|
||||||
|
import io.grpc.Channel
|
||||||
|
|
||||||
|
sealed trait Endpoint
|
||||||
|
|
||||||
|
object Endpoint {
|
||||||
|
|
||||||
|
final case object InProcess extends Endpoint
|
||||||
|
|
||||||
|
final case class Remote(hostname: String, port: Int) extends Endpoint
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final case class ChannelEndpoint(channel: Channel, endpoint: Endpoint)
|
||||||
|
|
||||||
|
object ChannelEndpoint {
|
||||||
|
|
||||||
|
def forRemote(channel: Channel, hostname: String, port: Int): ChannelEndpoint =
|
||||||
|
ChannelEndpoint(channel, Endpoint.Remote(hostname, port))
|
||||||
|
|
||||||
|
def forInProcess(channel: Channel): ChannelEndpoint = ChannelEndpoint(channel, Endpoint.InProcess)
|
||||||
|
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
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
|
||||||
@ -11,6 +12,7 @@ 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(
|
||||||
applicationId: String,
|
applicationId: String,
|
||||||
@ -21,7 +23,12 @@ private[infrastructure] final class LedgerSession private (
|
|||||||
else participantSessions
|
else participantSessions
|
||||||
Future
|
Future
|
||||||
.traverse(sessions) { case (endpointId, session) =>
|
.traverse(sessions) { case (endpointId, session) =>
|
||||||
session.createTestContext(endpointId, applicationId, identifierSuffix)
|
session.createTestContext(
|
||||||
|
endpointId,
|
||||||
|
applicationId,
|
||||||
|
identifierSuffix,
|
||||||
|
clientTlsConfiguration,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.map(new LedgerTestContext(_))
|
.map(new LedgerTestContext(_))
|
||||||
}
|
}
|
||||||
@ -31,10 +38,15 @@ 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)
|
||||||
val sessions = participantSessions.map(endpointIdProvider() -> _)
|
val sessions = participantSessions.map(endpointIdProvider() -> _)
|
||||||
new LedgerSession(sessions, shuffleParticipants)
|
new LedgerSession(
|
||||||
|
sessions,
|
||||||
|
shuffleParticipants,
|
||||||
|
clientTlsConfiguration,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
package com.daml.ledger.api.testtool.infrastructure
|
package com.daml.ledger.api.testtool.infrastructure
|
||||||
|
|
||||||
import java.util.concurrent.{ExecutionException, TimeoutException}
|
|
||||||
import java.util.{Timer, TimerTask}
|
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
import akka.stream.Materializer
|
import akka.stream.Materializer
|
||||||
import akka.stream.scaladsl.{Sink, Source}
|
import akka.stream.scaladsl.{Sink, Source}
|
||||||
@ -16,9 +13,12 @@ import com.daml.ledger.api.testtool.infrastructure.participant.{
|
|||||||
ParticipantSession,
|
ParticipantSession,
|
||||||
ParticipantTestContext,
|
ParticipantTestContext,
|
||||||
}
|
}
|
||||||
import io.grpc.{Channel, ClientInterceptor}
|
import com.daml.ledger.api.tls.TlsConfiguration
|
||||||
|
import io.grpc.ClientInterceptor
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
import java.util.concurrent.{ExecutionException, TimeoutException}
|
||||||
|
import java.util.{Timer, TimerTask}
|
||||||
import scala.concurrent.duration.{Duration, DurationInt}
|
import scala.concurrent.duration.{Duration, DurationInt}
|
||||||
import scala.concurrent.{ExecutionContext, Future, Promise}
|
import scala.concurrent.{ExecutionContext, Future, Promise}
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
@ -41,7 +41,7 @@ object LedgerTestCasesRunner {
|
|||||||
|
|
||||||
final class LedgerTestCasesRunner(
|
final class LedgerTestCasesRunner(
|
||||||
testCases: Vector[LedgerTestCase],
|
testCases: Vector[LedgerTestCase],
|
||||||
participants: Vector[Channel],
|
participants: Vector[ChannelEndpoint],
|
||||||
maxConnectionAttempts: Int = 10,
|
maxConnectionAttempts: Int = 10,
|
||||||
partyAllocation: PartyAllocationConfiguration = ClosedWorldWaitingForAllParticipants,
|
partyAllocation: PartyAllocationConfiguration = ClosedWorldWaitingForAllParticipants,
|
||||||
shuffleParticipants: Boolean = false,
|
shuffleParticipants: Boolean = false,
|
||||||
@ -50,6 +50,7 @@ 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 {
|
||||||
@ -150,13 +151,18 @@ 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
|
||||||
.sequence(sessions.map { session =>
|
.sequence(sessions.map { session =>
|
||||||
for {
|
for {
|
||||||
context <- session.createInitContext("upload-dars", identifierSuffix)
|
context <- session.createInitContext(
|
||||||
|
applicationId = "upload-dars",
|
||||||
|
identifierSuffix = identifierSuffix,
|
||||||
|
clientTlsConfiguration = clientTlsConfiguration,
|
||||||
|
)
|
||||||
_ <- Future.sequence(Dars.resources.map(uploadDar(context, _)))
|
_ <- Future.sequence(Dars.resources.map(uploadDar(context, _)))
|
||||||
} yield ()
|
} yield ()
|
||||||
})
|
})
|
||||||
@ -188,18 +194,22 @@ final class LedgerTestCasesRunner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def run(
|
private def run(
|
||||||
participants: Vector[Channel]
|
participants: Vector[ChannelEndpoint]
|
||||||
)(implicit
|
)(implicit
|
||||||
materializer: Materializer,
|
materializer: Materializer,
|
||||||
executionContext: ExecutionContext,
|
executionContext: ExecutionContext,
|
||||||
): Future[Vector[LedgerTestSummary]] = {
|
): Future[Vector[LedgerTestSummary]] = {
|
||||||
val (concurrentTestCases, sequentialTestCases) = testCases.partition(_.runConcurrently)
|
val (concurrentTestCases, sequentialTestCases) = testCases.partition(_.runConcurrently)
|
||||||
ParticipantSession(partyAllocation, participants, maxConnectionAttempts, commandInterceptors)
|
ParticipantSession(partyAllocation, participants, maxConnectionAttempts, commandInterceptors)
|
||||||
.flatMap { sessions =>
|
.flatMap { sessions: Vector[ParticipantSession] =>
|
||||||
val ledgerSession = LedgerSession(sessions, shuffleParticipants)
|
val ledgerSession = LedgerSession(
|
||||||
|
sessions,
|
||||||
|
shuffleParticipants,
|
||||||
|
clientTlsConfiguration = clientTlsConfiguration,
|
||||||
|
)
|
||||||
val testResults =
|
val testResults =
|
||||||
for {
|
for {
|
||||||
_ <- uploadDarsIfRequired(sessions)
|
_ <- uploadDarsIfRequired(sessions, clientTlsConfiguration)
|
||||||
concurrentTestResults <- runTestCases(
|
concurrentTestResults <- runTestCases(
|
||||||
ledgerSession,
|
ledgerSession,
|
||||||
concurrentTestCases,
|
concurrentTestCases,
|
||||||
|
@ -42,10 +42,11 @@ private[testtool] final class LedgerTestContext private[infrastructure] (
|
|||||||
val participantAllocations = allocation.partyCounts.map(nextParticipant() -> _)
|
val participantAllocations = allocation.partyCounts.map(nextParticipant() -> _)
|
||||||
val participantsUnderTest = participantAllocations.map(_._1)
|
val participantsUnderTest = participantAllocations.map(_._1)
|
||||||
Future
|
Future
|
||||||
.sequence(participantAllocations.map { case (participant, partyCount) =>
|
.sequence(participantAllocations.map {
|
||||||
participant
|
case (participant: ParticipantTestContext, partyCount) =>
|
||||||
.preallocateParties(partyCount.count, participantsUnderTest)
|
participant
|
||||||
.map(parties => Participant(participant, parties: _*))
|
.preallocateParties(partyCount.count, participantsUnderTest)
|
||||||
|
.map(parties => Participant(participant, parties: _*))
|
||||||
})
|
})
|
||||||
.map(allocatedParticipants => Participants(allocatedParticipants: _*))
|
.map(allocatedParticipants => Participants(allocatedParticipants: _*))
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ private[testtool] abstract class LedgerTestSuite {
|
|||||||
repeated,
|
repeated,
|
||||||
)((ec: ExecutionContext) => (_: Seq[ParticipantTestContext]) => testCase(ec))
|
)((ec: ExecutionContext) => (_: Seq[ParticipantTestContext]) => testCase(ec))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final def testGivenAllParticipants(
|
protected final def testGivenAllParticipants(
|
||||||
shortIdentifier: String,
|
shortIdentifier: String,
|
||||||
description: String,
|
description: String,
|
||||||
|
@ -4,14 +4,17 @@
|
|||||||
package com.daml.ledger.api.testtool.infrastructure.participant
|
package com.daml.ledger.api.testtool.infrastructure.participant
|
||||||
|
|
||||||
import com.daml.ledger.api.testtool.infrastructure.{
|
import com.daml.ledger.api.testtool.infrastructure.{
|
||||||
|
ChannelEndpoint,
|
||||||
|
Endpoint,
|
||||||
Errors,
|
Errors,
|
||||||
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.timer.RetryStrategy
|
import com.daml.timer.RetryStrategy
|
||||||
import io.grpc.{Channel, ClientInterceptor}
|
import io.grpc.ClientInterceptor
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
import scala.concurrent.duration.DurationInt
|
import scala.concurrent.duration.DurationInt
|
||||||
@ -27,28 +30,39 @@ private[infrastructure] final class ParticipantSession private (
|
|||||||
// The test tool is designed to run tests in an isolated environment but changing the
|
// The test tool is designed to run tests in an isolated environment but changing the
|
||||||
// global state of the ledger breaks this assumption, no matter what.
|
// global state of the ledger breaks this assumption, no matter what.
|
||||||
ledgerId: String,
|
ledgerId: String,
|
||||||
|
ledgerEndpoint: Endpoint,
|
||||||
)(implicit val executionContext: ExecutionContext) {
|
)(implicit val executionContext: ExecutionContext) {
|
||||||
|
|
||||||
private[testtool] def createInitContext(
|
private[testtool] def createInitContext(
|
||||||
applicationId: String,
|
applicationId: String,
|
||||||
identifierSuffix: String,
|
identifierSuffix: String,
|
||||||
|
clientTlsConfiguration: Option[TlsConfiguration],
|
||||||
): Future[ParticipantTestContext] =
|
): Future[ParticipantTestContext] =
|
||||||
createTestContext("init", applicationId, identifierSuffix)
|
createTestContext(
|
||||||
|
"init",
|
||||||
|
applicationId,
|
||||||
|
identifierSuffix,
|
||||||
|
clientTlsConfiguration = clientTlsConfiguration,
|
||||||
|
)
|
||||||
|
|
||||||
private[testtool] def createTestContext(
|
private[testtool] def createTestContext(
|
||||||
endpointId: String,
|
endpointId: String,
|
||||||
applicationId: String,
|
applicationId: String,
|
||||||
identifierSuffix: String,
|
identifierSuffix: String,
|
||||||
|
clientTlsConfiguration: Option[TlsConfiguration],
|
||||||
): 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 ParticipantTestContext(
|
||||||
ledgerId,
|
ledgerId = ledgerId,
|
||||||
endpointId,
|
endpointId = endpointId,
|
||||||
applicationId,
|
applicationId = applicationId,
|
||||||
identifierSuffix,
|
identifierSuffix = identifierSuffix,
|
||||||
end,
|
referenceOffset = end,
|
||||||
services,
|
services = services,
|
||||||
partyAllocation,
|
partyAllocation = partyAllocation,
|
||||||
|
ledgerEndpoint = ledgerEndpoint,
|
||||||
|
clientTlsConfiguration = clientTlsConfiguration,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,14 +71,14 @@ object ParticipantSession {
|
|||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
partyAllocation: PartyAllocationConfiguration,
|
partyAllocation: PartyAllocationConfiguration,
|
||||||
participants: Vector[Channel],
|
participants: Vector[ChannelEndpoint],
|
||||||
maxConnectionAttempts: Int,
|
maxConnectionAttempts: Int,
|
||||||
commandInterceptors: Seq[ClientInterceptor],
|
commandInterceptors: Seq[ClientInterceptor],
|
||||||
)(implicit
|
)(implicit
|
||||||
executionContext: ExecutionContext
|
executionContext: ExecutionContext
|
||||||
): Future[Vector[ParticipantSession]] =
|
): Future[Vector[ParticipantSession]] =
|
||||||
Future.traverse(participants) { participant =>
|
Future.traverse(participants) { participant: ChannelEndpoint =>
|
||||||
val services = new LedgerServices(participant, commandInterceptors)
|
val services = new LedgerServices(participant.channel, commandInterceptors)
|
||||||
for {
|
for {
|
||||||
ledgerId <- RetryStrategy
|
ledgerId <- RetryStrategy
|
||||||
.exponentialBackoff(attempts = maxConnectionAttempts, 100.millis) { (attempt, wait) =>
|
.exponentialBackoff(attempts = maxConnectionAttempts, 100.millis) { (attempt, wait) =>
|
||||||
@ -80,7 +94,12 @@ object ParticipantSession {
|
|||||||
.recoverWith { case NonFatal(exception) =>
|
.recoverWith { case NonFatal(exception) =>
|
||||||
Future.failed(new Errors.ParticipantConnectionException(exception))
|
Future.failed(new Errors.ParticipantConnectionException(exception))
|
||||||
}
|
}
|
||||||
} yield new ParticipantSession(partyAllocation, services, ledgerId)
|
} yield new ParticipantSession(
|
||||||
|
partyAllocation = partyAllocation,
|
||||||
|
services = services,
|
||||||
|
ledgerId = ledgerId,
|
||||||
|
ledgerEndpoint = participant.endpoint,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,16 @@
|
|||||||
package com.daml.ledger.api.testtool.infrastructure.participant
|
package com.daml.ledger.api.testtool.infrastructure.participant
|
||||||
|
|
||||||
import java.time.{Clock, Instant}
|
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.{
|
import com.daml.ledger.api.testtool.infrastructure.{
|
||||||
|
Endpoint,
|
||||||
Identification,
|
Identification,
|
||||||
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,
|
||||||
@ -105,6 +106,8 @@ private[testtool] final class ParticipantTestContext private[participant] (
|
|||||||
referenceOffset: LedgerOffset,
|
referenceOffset: LedgerOffset,
|
||||||
services: LedgerServices,
|
services: LedgerServices,
|
||||||
partyAllocation: PartyAllocationConfiguration,
|
partyAllocation: PartyAllocationConfiguration,
|
||||||
|
val ledgerEndpoint: Endpoint,
|
||||||
|
val clientTlsConfiguration: Option[TlsConfiguration],
|
||||||
)(implicit ec: ExecutionContext) {
|
)(implicit ec: ExecutionContext) {
|
||||||
|
|
||||||
import ParticipantTestContext._
|
import ParticipantTestContext._
|
||||||
|
@ -0,0 +1,128 @@
|
|||||||
|
// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package com.daml.ledger.api.testtool.suites
|
||||||
|
|
||||||
|
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.{Endpoint, LedgerTestSuite}
|
||||||
|
import com.daml.ledger.api.tls.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.{
|
||||||
|
GetLedgerIdentityRequest,
|
||||||
|
LedgerIdentityServiceGrpc,
|
||||||
|
}
|
||||||
|
import com.daml.ledger.resources.{ResourceContext, ResourceOwner}
|
||||||
|
import io.grpc.StatusRuntimeException
|
||||||
|
import io.grpc.netty.NettyChannelBuilder
|
||||||
|
|
||||||
|
import scala.concurrent.Future
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
import scala.util.{Failure, Success, Try}
|
||||||
|
|
||||||
|
/** Verifies that the given participant server correctly handles TLSv1.3 only mode.
|
||||||
|
*
|
||||||
|
* It works by creating and exercising a series of client service stubs, each over different TLS version.
|
||||||
|
* Only TLSv1.3 connection is expected to succeed.
|
||||||
|
* Connections over lower TLS versions are expected to fail.
|
||||||
|
*/
|
||||||
|
final class TLSOnePointThreeIT extends LedgerTestSuite {
|
||||||
|
|
||||||
|
testTlsConnection(clientTlsVersion = TlsVersion.V1_3, assertConnectionOk = true)
|
||||||
|
testTlsConnection(clientTlsVersion = TlsVersion.V1_2, assertConnectionOk = false)
|
||||||
|
testTlsConnection(clientTlsVersion = TlsVersion.V1_1, assertConnectionOk = false)
|
||||||
|
testTlsConnection(clientTlsVersion = TlsVersion.V1, assertConnectionOk = false)
|
||||||
|
|
||||||
|
def testTlsConnection(clientTlsVersion: TlsVersion, assertConnectionOk: Boolean): Unit = {
|
||||||
|
val (what, assertionOnServerResponse) =
|
||||||
|
if (assertConnectionOk)
|
||||||
|
("accept", assertSuccessfulConnection)
|
||||||
|
else
|
||||||
|
("reject", assertFailedConnection)
|
||||||
|
|
||||||
|
testGivenAllParticipants(
|
||||||
|
s"ConnectionOnTLSv13FromClientOn${clientTlsVersion.version.replace(".", "")}",
|
||||||
|
s"A ledger API server should ${what} a ${clientTlsVersion} connection",
|
||||||
|
allocate(NoParties),
|
||||||
|
) { implicit ec => (testContexts: Seq[ParticipantTestContext]) =>
|
||||||
|
{ case _ =>
|
||||||
|
// preconditions
|
||||||
|
assume(testContexts.nonEmpty, "Missing an expected participant test context!")
|
||||||
|
val firstTextContext = testContexts.head
|
||||||
|
assume(
|
||||||
|
firstTextContext.clientTlsConfiguration.isDefined,
|
||||||
|
"Missing required TLS configuration!",
|
||||||
|
)
|
||||||
|
val tlsConfiguration = firstTextContext.clientTlsConfiguration.get
|
||||||
|
assume(
|
||||||
|
tlsConfiguration.enabled,
|
||||||
|
"TLS configuration is disabled but expected to be enabled!",
|
||||||
|
)
|
||||||
|
assume(
|
||||||
|
firstTextContext.ledgerEndpoint.isInstanceOf[Endpoint.Remote],
|
||||||
|
"Expected a remote (i.e. with a hostname and port) ledger endpoint!",
|
||||||
|
)
|
||||||
|
val Endpoint.Remote(ledgerHostname, ledgerPort) =
|
||||||
|
firstTextContext.ledgerEndpoint.asInstanceOf[Endpoint.Remote]
|
||||||
|
|
||||||
|
// given
|
||||||
|
val sslContext = tlsConfiguration
|
||||||
|
.client(enabledProtocols = Seq(clientTlsVersion))
|
||||||
|
.getOrElse(throw new IllegalStateException("Missing SslContext!"))
|
||||||
|
val serviceStubOwner: ResourceOwner[LedgerIdentityServiceBlockingStub] = for {
|
||||||
|
channel <- ResourceOwner.forChannel(
|
||||||
|
builder = NettyChannelBuilder
|
||||||
|
.forAddress(ledgerHostname, ledgerPort)
|
||||||
|
.useTransportSecurity()
|
||||||
|
.sslContext(sslContext),
|
||||||
|
shutdownTimeout = 2.seconds,
|
||||||
|
)
|
||||||
|
} yield LedgerIdentityServiceGrpc.blockingStub(channel)
|
||||||
|
|
||||||
|
// when
|
||||||
|
val response: Future[String] = serviceStubOwner.use { identityService =>
|
||||||
|
val response = identityService.getLedgerIdentity(new GetLedgerIdentityRequest())
|
||||||
|
Future.successful(response.ledgerId)
|
||||||
|
}(ResourceContext(ec))
|
||||||
|
|
||||||
|
// then
|
||||||
|
response.transform[Unit] {
|
||||||
|
assertionOnServerResponse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy val assertSuccessfulConnection: Try[String] => Try[Unit] = {
|
||||||
|
case Success(ledgerId) =>
|
||||||
|
Try[Unit] {
|
||||||
|
assert(
|
||||||
|
assertion = ledgerId ne null,
|
||||||
|
message = s"Expected a not null ledger id!",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
case Failure(exception) =>
|
||||||
|
throw new AssertionError(s"Failed to receive a successful server response!", exception)
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy val assertFailedConnection: Try[String] => Try[Unit] = {
|
||||||
|
case Success(ledgerId) =>
|
||||||
|
Try[Unit] {
|
||||||
|
assert(
|
||||||
|
assertion = false,
|
||||||
|
message =
|
||||||
|
s"Connection succeeded and returned ledgerId: ${ledgerId} but expected connection failure!",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
case Failure(_: StatusRuntimeException) => Success[Unit](())
|
||||||
|
case Failure(other) =>
|
||||||
|
Try[Unit] {
|
||||||
|
assert(
|
||||||
|
assertion = false,
|
||||||
|
message = s"Unexpected failure: ${other}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -75,6 +75,7 @@ object Tests {
|
|||||||
new MultiPartySubmissionIT,
|
new MultiPartySubmissionIT,
|
||||||
new ParticipantPruningIT,
|
new ParticipantPruningIT,
|
||||||
new MonotonicRecordTimeIT,
|
new MonotonicRecordTimeIT,
|
||||||
|
new TLSOnePointThreeIT,
|
||||||
)
|
)
|
||||||
|
|
||||||
val retired: Vector[LedgerTestSuite] =
|
val retired: Vector[LedgerTestSuite] =
|
||||||
|
@ -167,7 +167,6 @@ private[daml] object ApiServices {
|
|||||||
optTimeServiceBackend.map(tsb =>
|
optTimeServiceBackend.map(tsb =>
|
||||||
new TimeServiceAuthorization(ApiTimeService.create(ledgerId, tsb), authorizer)
|
new TimeServiceAuthorization(ApiTimeService.create(ledgerId, tsb), authorizer)
|
||||||
)
|
)
|
||||||
|
|
||||||
val writeServiceBackedApiServices =
|
val writeServiceBackedApiServices =
|
||||||
intitializeWriteServiceBackedApiServices(
|
intitializeWriteServiceBackedApiServices(
|
||||||
ledgerId,
|
ledgerId,
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
|
|
||||||
package com.daml.nonrepudiation.postgresql
|
package com.daml.nonrepudiation.postgresql
|
||||||
|
|
||||||
import java.time.{Clock, Duration}
|
|
||||||
|
|
||||||
import com.daml.doobie.logging.Slf4jLogHandler
|
import com.daml.doobie.logging.Slf4jLogHandler
|
||||||
|
import com.daml.ledger.api.testtool.infrastructure
|
||||||
import com.daml.ledger.api.testtool.infrastructure.{
|
import com.daml.ledger.api.testtool.infrastructure.{
|
||||||
LedgerTestCase,
|
LedgerTestCase,
|
||||||
LedgerTestCasesRunner,
|
LedgerTestCasesRunner,
|
||||||
@ -34,6 +33,7 @@ import org.scalatest.flatspec.AsyncFlatSpec
|
|||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import org.scalatest.{Inside, OptionValues}
|
import org.scalatest.{Inside, OptionValues}
|
||||||
|
|
||||||
|
import java.time.{Clock, Duration}
|
||||||
import scala.concurrent.duration.DurationInt
|
import scala.concurrent.duration.DurationInt
|
||||||
|
|
||||||
final class NonRepudiationProxyConformance
|
final class NonRepudiationProxyConformance
|
||||||
@ -109,10 +109,11 @@ final class NonRepudiationProxyConformance
|
|||||||
proxy.use { _ =>
|
proxy.use { _ =>
|
||||||
val runner = new LedgerTestCasesRunner(
|
val runner = new LedgerTestCasesRunner(
|
||||||
testCases = conformanceTestCases,
|
testCases = conformanceTestCases,
|
||||||
participants = Vector(proxyChannel),
|
participants = Vector(infrastructure.ChannelEndpoint.forInProcess(proxyChannel)),
|
||||||
commandInterceptors = Seq(
|
commandInterceptors = Seq(
|
||||||
SigningInterceptor.signCommands(key, certificate)
|
SigningInterceptor.signCommands(key, certificate)
|
||||||
),
|
),
|
||||||
|
clientTlsConfiguration = config.tlsConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
runner.runTests.map { summaries =>
|
runner.runTests.map { summaries =>
|
||||||
|
Loading…
Reference in New Issue
Block a user