Skip to content

Commit

Permalink
[DPP-572] Add ledger API test case for verifying conformance to `--mi…
Browse files Browse the repository at this point in the history
…n-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
  • Loading branch information
pbatko-da authored Sep 20, 2021
1 parent 3e13e3d commit 855ecdf
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 78 deletions.
8 changes: 8 additions & 0 deletions ledger/ledger-api-test-tool/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ da_scala_binary(
"//ledger/test-common:model-tests-%s.scala" % lf_version,
"//ledger/test-common:dar-files-%s-lib" % lf_version,
"//ledger-api/grpc-definitions:ledger_api_proto_scala",
"//ledger/ledger-api-common",
"//libs-scala/build-info",
"//libs-scala/grpc-utils",
"//libs-scala/resources",
Expand Down Expand Up @@ -124,6 +125,10 @@ da_scala_binary(
"//daml-lf/data",
"//language-support/scala/bindings",
"//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:package_management-tests-%s.scala" % lf_version,
"//ledger/test-common:model-tests-%s.scala" % lf_version,
Expand All @@ -134,6 +139,8 @@ da_scala_binary(
"//libs-scala/timer-utils",
"@maven//:io_grpc_grpc_api",
"@maven//:io_grpc_grpc_context",
"@maven//:io_grpc_grpc_netty",
"@maven//:io_netty_netty_handler",
"@maven//:org_slf4j_slf4j_api",
],
),
Expand Down Expand Up @@ -245,6 +252,7 @@ conformance_test(
# Retired tests will be eventually removed.
"--additional=LotsOfPartiesIT",
"--additional=TransactionScaleIT",
"--additional=TLSOnePointThreeIT",
"--exclude=CommandDeduplicationIT",
# 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@ object Cli {

head(
"""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)
.action((address, config) => config.copy(participants = config.participants :+ address))
.action((address, config) =>
config.copy(participantsEndpoints = config.participantsEndpoints :+ address)
)
.unbounded()
.optional()
.text("Addresses of the participants to test, specified as `<host>:<port>`.")
Expand Down Expand Up @@ -105,7 +107,7 @@ object Cli {
.optional()
.text(
"""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)

Expand All @@ -119,9 +121,9 @@ object Cli {
.action((v, c) => c.copy(timeoutScaleFactor = v))
.text(
"""Scale factor for timeouts used in all test suites. Useful to tune timeouts
|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,
|use numbers lower than 1.0 to make test timeouts more strict.""".stripMargin
|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,
|use numbers lower than 1.0 to make test timeouts more strict.""".stripMargin
)

opt[String](name = "load-scale-factor")
Expand All @@ -144,36 +146,36 @@ object Cli {
.action((_, c) => c.copy(mustFail = true))
.text(
"""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
|least one test fails, and it will fail when all tests succeed. Defaults to
|false.""".stripMargin
|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
|false.""".stripMargin
)

opt[Unit]('x', "extract")
.action((_, c) => c.copy(extract = true))
.text(
"""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")
.action((ex, c) => c.copy(excluded = c.excluded ++ ex))
.unbounded()
.text(
"""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,
|i.e. `--exclude=a,b` is the same as `--exclude=a --exclude=b`.""".stripMargin
|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
)

opt[Seq[String]]("include")
.action((inc, c) => c.copy(included = c.included ++ inc))
.unbounded()
.text(
"""A comma-separated list of inclusion prefixes. If not specified,
|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.
|Can be specified multiple times, i.e. `--include=a,b` is the same as `--include=a --include=b`.
|Mutually exclusive with `--additional`.""".stripMargin
|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.
|Can be specified multiple times, i.e. `--include=a,b` is the same as `--include=a --include=b`.
|Mutually exclusive with `--additional`.""".stripMargin
)

opt[Seq[String]]("additional")
Expand All @@ -182,9 +184,9 @@ object Cli {
.unbounded()
.text(
"""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.
|Can be specified multiple times, i.e. `--additional=a,b` is the same as `--additional=a --additional=b`.
|Mutually exclusive with `--include`.""".stripMargin
|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`.
|Mutually exclusive with `--include`.""".stripMargin
)

opt[Seq[String]]("perf-tests")
Expand All @@ -209,7 +211,7 @@ object Cli {
.action((_, c) => c.copy(shuffleParticipants = true))
.text(
"""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")
Expand All @@ -221,16 +223,16 @@ object Cli {
.action((_, c) => c.copy(partyAllocation = PartyAllocationConfiguration.OpenWorld))
.text(
"""Do not allocate parties explicitly.
|Instead, expect the ledger to allocate parties dynamically.
|Party names must be their hints.""".stripMargin
|Instead, expect the ledger to allocate parties dynamically.
|Party names must be their hints.""".stripMargin
)

opt[Unit]("list")
.action((_, c) => c.copy(listTestSuites = true))
.text(
"""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
|matches all tests in a given suite.""".stripMargin
|Test names always start with their suite name, so using the suite name as a prefix
|matches all tests in a given suite.""".stripMargin
)

opt[Unit]("list-all")
Expand All @@ -252,7 +254,7 @@ object Cli {
.action((x, c) => c.copy(ledgerClockGranularity = x))
.text(
"""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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@

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.tls.TlsConfiguration

import java.io.File
import java.nio.file.Path
import scala.concurrent.duration.FiniteDuration

final case class Config(
participants: Vector[(String, Int)],
participantsEndpoints: Vector[(String, Int)],
maxConnectionAttempts: Int,
darPackages: List[File],
mustFail: Boolean,
Expand All @@ -32,11 +31,16 @@ final case class Config(
partyAllocation: PartyAllocationConfiguration,
ledgerClockGranularity: FiniteDuration,
uploadDars: Boolean,
)
) {
def withTlsConfig(modify: TlsConfiguration => TlsConfiguration): Config = {
val base = tlsConfig.getOrElse(TlsConfiguration.Empty)
copy(tlsConfig = Some(modify(base)))
}
}

object Config {
val default: Config = Config(
participants = Vector.empty,
participantsEndpoints = Vector.empty,
maxConnectionAttempts = 10,
darPackages = Nil,
mustFail = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@

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.Result.Excluded
import com.daml.ledger.api.testtool.infrastructure._
Expand All @@ -17,6 +13,9 @@ import io.grpc.netty.{NegotiationType, NettyChannelBuilder}
import org.slf4j.LoggerFactory

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.{ExecutionContext, Future}
import scala.util.{Failure, Success}
Expand Down Expand Up @@ -57,6 +56,7 @@ object LedgerApiTestTool {
println()
Tests.PerformanceTestsKeys.foreach(println(_))
}

private def printAvailableTestSuites(testSuites: Vector[LedgerTestSuite]): Unit = {
println("Listing test suites. Run with --list-all to see individual tests.")
printListOfTests(testSuites)(_.name)
Expand Down Expand Up @@ -126,7 +126,7 @@ object LedgerApiTestTool {
sys.exit(0)
}

if (config.participants.isEmpty) {
if (config.participantsEndpoints.isEmpty) {
println("No participant to test, exiting.")
sys.exit(0)
}
Expand Down Expand Up @@ -220,8 +220,11 @@ object LedgerApiTestTool {
cases: Vector[LedgerTestCase],
concurrentTestRuns: Int,
)(implicit executionContext: ExecutionContext): Future[LedgerTestCasesRunner] = {
initializeParticipantChannels(config.participants, config.tlsConfig).asFuture.map(
participants =>
initializeParticipantChannels(
config.participantsEndpoints,
config.tlsConfig,
).asFuture
.map((participants: Vector[ChannelEndpoint]) =>
new LedgerTestCasesRunner(
testCases = cases,
participants = participants,
Expand All @@ -232,8 +235,9 @@ object LedgerApiTestTool {
concurrentTestRuns = concurrentTestRuns,
uploadDars = config.uploadDars,
identifierSuffix = identifierSuffix,
clientTlsConfiguration = config.tlsConfig,
)
)
)
}

private def initializeParticipantChannel(
Expand All @@ -257,12 +261,18 @@ object LedgerApiTestTool {
private def initializeParticipantChannels(
participants: Vector[(String, Int)],
tlsConfig: Option[TlsConfiguration],
)(implicit executionContext: ExecutionContext): Resource[Vector[Channel]] = {
val participantChannelOwners =
)(implicit executionContext: ExecutionContext): Resource[Vector[ChannelEndpoint]] = {
val channelResources: Seq[Resource[ChannelEndpoint]] =
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)
}

}
Original file line number Diff line number Diff line change
@@ -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)

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
package com.daml.ledger.api.testtool.infrastructure

import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantSession
import com.daml.ledger.api.tls.TlsConfiguration

import scala.concurrent.{ExecutionContext, Future}
import scala.util.Random

private[infrastructure] final class LedgerSession private (
participantSessions: Vector[(String, ParticipantSession)],
shuffleParticipants: Boolean,
clientTlsConfiguration: Option[TlsConfiguration],
)(implicit val executionContext: ExecutionContext) {
private[infrastructure] def createTestContext(
applicationId: String,
Expand All @@ -21,7 +23,12 @@ private[infrastructure] final class LedgerSession private (
else participantSessions
Future
.traverse(sessions) { case (endpointId, session) =>
session.createTestContext(endpointId, applicationId, identifierSuffix)
session.createTestContext(
endpointId,
applicationId,
identifierSuffix,
clientTlsConfiguration,
)
}
.map(new LedgerTestContext(_))
}
Expand All @@ -31,10 +38,15 @@ object LedgerSession {
def apply(
participantSessions: Vector[ParticipantSession],
shuffleParticipants: Boolean,
clientTlsConfiguration: Option[TlsConfiguration],
)(implicit executionContext: ExecutionContext): LedgerSession = {
val endpointIdProvider =
Identification.circularWithIndex(Identification.greekAlphabet)
val sessions = participantSessions.map(endpointIdProvider() -> _)
new LedgerSession(sessions, shuffleParticipants)
new LedgerSession(
sessions,
shuffleParticipants,
clientTlsConfiguration,
)
}
}
Loading

0 comments on commit 855ecdf

Please sign in to comment.