mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
ledger-api-test-tool: Run tests on Canton, and fix a few issues. (#3446)
* ledger-api-test-tool-on-canton: Run Canton. * ledger-api-test-tool-on-canton: Run the SemanticTests against Canton. This was _so_ much work. These will probably be flaky, so can't merge them in until we fix the underlying issues with the tests around multi-participant allocation. * ledger-api-test-tool: Wait for parties to arrive on all participants. Thanks to Canton for exacerbating this bug. Can't turn on all the tests on Canton yet as there are other spurious failures. Will investigate next. * ledger-api-test-tool: Move all contract key tests to ContractKeys. If a ledger doesn't support ContractKeys, they need to be able to turn these tests off. * ledger-api-test-tool: If a test name is misspelled, fail immediately. I keep getting names slightly wrong in the `--exclude` arguments and wondering why it didn't work. * client_server: Revert client_server_test.bzl. Turns out I don't know what I'm doing. ¯\_(ツ)_/¯ * sandbox: Don't call `.toString` on an array. Doesn't do much. * dev-env: Don't untar netcat automatically. It needs to be installed with Pacman.
This commit is contained in:
parent
87de36a7fe
commit
c5d9d1014e
47
WORKSPACE
47
WORKSPACE
@ -116,6 +116,26 @@ nixpkgs_package(
|
||||
repositories = dev_env_nix_repos,
|
||||
)
|
||||
|
||||
# netcat dependency
|
||||
nixpkgs_package(
|
||||
name = "netcat_nix",
|
||||
attribute_path = "netcat-gnu",
|
||||
nix_file = "//nix:bazel.nix",
|
||||
nix_file_deps = common_nix_file_deps,
|
||||
repositories = dev_env_nix_repos,
|
||||
)
|
||||
|
||||
dev_env_tool(
|
||||
name = "netcat_dev_env",
|
||||
nix_include = ["bin/nc"],
|
||||
nix_label = "@netcat_nix",
|
||||
nix_paths = ["bin/nc"],
|
||||
tools = ["nc"],
|
||||
win_include = ["usr/bin/nc.exe"],
|
||||
win_paths = ["usr/bin/nc.exe"],
|
||||
win_tool = "msys2",
|
||||
)
|
||||
|
||||
# Tar & gzip dependency
|
||||
nixpkgs_package(
|
||||
name = "tar_nix",
|
||||
@ -181,6 +201,22 @@ nixpkgs_package(
|
||||
repositories = dev_env_nix_repos,
|
||||
)
|
||||
|
||||
nixpkgs_package(
|
||||
name = "coreutils_nix",
|
||||
attribute_path = "coreutils",
|
||||
nix_file = "//nix:bazel.nix",
|
||||
nix_file_deps = common_nix_file_deps,
|
||||
repositories = dev_env_nix_repos,
|
||||
)
|
||||
|
||||
nixpkgs_package(
|
||||
name = "grpcurl_nix",
|
||||
attribute_path = "grpcurl",
|
||||
nix_file = "//nix:bazel.nix",
|
||||
nix_file_deps = common_nix_file_deps,
|
||||
repositories = dev_env_nix_repos,
|
||||
)
|
||||
|
||||
nixpkgs_package(
|
||||
name = "hlint_nix",
|
||||
attribute_path = "hlint",
|
||||
@ -947,3 +983,14 @@ dev_env_tool(
|
||||
],
|
||||
win_tool = "msys2",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "canton",
|
||||
build_file_content = '''
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
filegroup(name="jars", srcs=glob(["lib/**"]))
|
||||
''',
|
||||
sha256 = "b67215655bdcfaf0f4b271ebd3f9ce8f887c3c81a53351f47165a9bf5b93e435",
|
||||
strip_prefix = "canton-0.3.0",
|
||||
urls = ["https://github.com/digital-asset/canton/releases/download/v0.3.0/canton-0.3.0.tar.gz"],
|
||||
)
|
||||
|
@ -4,6 +4,7 @@
|
||||
"url": [
|
||||
"http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz",
|
||||
"http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-jq-1.6-2-any.pkg.tar.xz#/jq.msys2",
|
||||
"http://repo.msys2.org/msys/x86_64/gnu-netcat-0.7.1-1-x86_64.pkg.tar.xz#/netcat.msys2",
|
||||
"http://repo.msys2.org/msys/x86_64/patch-2.7.6-1-x86_64.pkg.tar.xz#/patch.msys2",
|
||||
"http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-openssl-1.1.1.c-1-any.pkg.tar.xz#/openssl.msys2",
|
||||
"http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-postgresql-11.3-1-any.pkg.tar.xz#/pgsql.msys2"
|
||||
@ -11,6 +12,7 @@
|
||||
"hash": [
|
||||
"4e799b5c3efcf9efcb84923656b7bcff16f75a666911abd6620ea8e5e1e9870c",
|
||||
"da8a3b88d6ad1f5d28bc190405de9ca0f802ebcae19080a5b5b2b30a7614272b",
|
||||
"32fa739d26fd49a3f8c22717ae338472d71d4798844cbc0db5e7780131fe69aa",
|
||||
"5c18ce8979e9019d24abd2aee7ddcdf8824e31c4c7e162a204d4dc39b3b73776",
|
||||
"28c8f3acbfa3b5435cd3759cd3f051e7cdeb0c6bb5cfccb7bacb70c8b91f66db",
|
||||
"df53271e77f85f9f2b5fc959da1976af8482cc9ae24229ac8ffd6103f6428123"
|
||||
@ -26,6 +28,7 @@
|
||||
"iex \"$dir\\usr\\bin\\bash.exe -lc 'pacman -S --noconfirm unzip zip mingw-w64-x86_64-gcc'\"",
|
||||
"iex \"$dir\\usr\\bin\\bash.exe -lc 'pacman -S --noconfirm tar diffutils'\"",
|
||||
"iex \"$dir\\usr\\bin\\bash.exe -lc 'pacman -U --noconfirm /jq.msys2'\"",
|
||||
"iex \"$dir\\usr\\bin\\bash.exe -lc 'pacman -U --noconfirm /netcat.msys2'\"",
|
||||
"iex \"$dir\\usr\\bin\\bash.exe -lc 'pacman -U --noconfirm /patch.msys2'\"",
|
||||
"iex \"$dir\\usr\\bin\\bash.exe -lc 'pacman -U --noconfirm /openssl.msys2'\"",
|
||||
"iex \"$dir\\usr\\bin\\bash.exe -lc 'pacman -U --noconfirm /pgsql.msys2'\"",
|
||||
@ -51,6 +54,7 @@
|
||||
"usr\\bin\\expr.exe",
|
||||
"usr\\bin\\ln.exe",
|
||||
"usr\\bin\\ls.exe",
|
||||
"usr\\bin\\nc.exe",
|
||||
"usr\\bin\\rm.exe",
|
||||
"usr\\bin\\sed.exe",
|
||||
"usr\\bin\\sh.exe",
|
||||
|
72
ledger/ledger-api-test-tool-on-canton/BUILD.bazel
Normal file
72
ledger/ledger-api-test-tool-on-canton/BUILD.bazel
Normal file
@ -0,0 +1,72 @@
|
||||
# Copyright (c) 2019 The DAML Authors. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
load("//ledger/ledger-api-test-tool:conformance.bzl", "conformance_test")
|
||||
load("@os_info//:os_info.bzl", "is_windows")
|
||||
|
||||
java_import(
|
||||
name = "canton-lib",
|
||||
jars = ["@canton//:jars"],
|
||||
)
|
||||
|
||||
java_binary(
|
||||
name = "canton",
|
||||
main_class = "com.digitalasset.canton.CantonApp",
|
||||
runtime_deps = [":canton-lib"],
|
||||
)
|
||||
|
||||
# Disabled on Windows because `coreutils` and `grpcurl` aren't easily available.
|
||||
genrule(
|
||||
name = "canton-test-runner-with-dependencies-script",
|
||||
srcs = [
|
||||
":canton-test-runner.sh",
|
||||
],
|
||||
outs = ["canton-test-runner-with-dependencies.sh"],
|
||||
cmd = """
|
||||
cat > $@ <<EOF
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
f=bazel_tools/tools/bash/runfiles/runfiles.bash
|
||||
source "\$${RUNFILES_DIR:-/dev/null}/\$$f" 2>/dev/null || \
|
||||
source "\$$(grep -sm1 "^\$$f " "\$${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
|
||||
source "\$$0.runfiles/\$$f" 2>/dev/null || \
|
||||
source "\$$(grep -sm1 "^\$$f " "\$$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
|
||||
source "\$$(grep -sm1 "^\$$f " "\$$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
|
||||
{ echo>&2 "ERROR: cannot find \$$f"; exit 1; }; f=; set -e
|
||||
|
||||
PATH="\$$(rlocation coreutils_nix/bin):\$$(rlocation jq_nix/bin):\$$(rlocation grpcurl_nix/bin):\$$(rlocation jq_dev_env/bin):\$$(rlocation netcat_dev_env/bin):\$$PATH"
|
||||
export PATH
|
||||
|
||||
EOF
|
||||
cat $< >> $@
|
||||
""",
|
||||
) if not is_windows else None
|
||||
|
||||
# Required because running `canton-test-runner-with-dependencies-script` directly fails.
|
||||
sh_binary(
|
||||
name = "canton-test-runner-with-dependencies",
|
||||
srcs = [":canton-test-runner-with-dependencies-script"],
|
||||
# Ideally these would be part of the script definition above, but that doesn't seem to work.
|
||||
deps = ["@bazel_tools//tools/bash/runfiles"],
|
||||
) if not is_windows else None
|
||||
|
||||
conformance_test(
|
||||
name = "conformance-test",
|
||||
# Ideally these would be part of the script definition above, but that doesn't seem to work.
|
||||
extra_data = [
|
||||
":bootstrap.canton",
|
||||
":canton",
|
||||
":canton.conf",
|
||||
"@coreutils_nix//:bin/base64",
|
||||
"@grpcurl_nix//:bin/grpcurl",
|
||||
"@jq_dev_env//:jq",
|
||||
"@netcat_dev_env//:nc",
|
||||
],
|
||||
ports = [
|
||||
5011,
|
||||
5021,
|
||||
],
|
||||
server = ":canton-test-runner-with-dependencies",
|
||||
) if not is_windows else None
|
7
ledger/ledger-api-test-tool-on-canton/bootstrap.canton
Normal file
7
ledger/ledger-api-test-tool-on-canton/bootstrap.canton
Normal file
@ -0,0 +1,7 @@
|
||||
all start
|
||||
|
||||
all_participants foreach (connect(_, test_domain))
|
||||
|
||||
retryUntilTrue() {
|
||||
all_participants forall (participant_is_active(_, test_domain.name))
|
||||
}
|
126
ledger/ledger-api-test-tool-on-canton/canton-test-runner.sh
Executable file
126
ledger/ledger-api-test-tool-on-canton/canton-test-runner.sh
Executable file
@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2019 The DAML Authors. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
CANTON_COMMAND=(
|
||||
"$(rlocation com_github_digital_asset_daml/ledger/ledger-api-test-tool-on-canton/canton)"
|
||||
daemon
|
||||
"--config=$(rlocation com_github_digital_asset_daml/ledger/ledger-api-test-tool-on-canton/canton.conf)"
|
||||
"--bootstrap=$(rlocation com_github_digital_asset_daml/ledger/ledger-api-test-tool-on-canton/bootstrap.canton)"
|
||||
)
|
||||
|
||||
PARTICIPANT_1_LEDGER_API_HOST=localhost
|
||||
PARTICIPANT_1_LEDGER_API_PORT=5011
|
||||
PARTICIPANT_2_LEDGER_API_HOST=localhost
|
||||
PARTICIPANT_2_LEDGER_API_PORT=5021
|
||||
PARTICIPANTS=(
|
||||
"${PARTICIPANT_1_LEDGER_API_HOST}:${PARTICIPANT_1_LEDGER_API_PORT}"
|
||||
"${PARTICIPANT_2_LEDGER_API_HOST}:${PARTICIPANT_2_LEDGER_API_PORT}"
|
||||
)
|
||||
|
||||
TIMEOUT=30
|
||||
|
||||
function wait_for_ports {
|
||||
local start success host port
|
||||
|
||||
start="$(date +%s)"
|
||||
while true; do
|
||||
if [[ "$(( "$(date +%s)" - start ))" -gt "$TIMEOUT" ]]; then
|
||||
echo >&2 "Timed out after ${TIMEOUT} seconds."
|
||||
return 1
|
||||
fi
|
||||
|
||||
success=true
|
||||
for (( i=1; i < $#; i++ )); do
|
||||
host="${!i}"
|
||||
i=$(( i + 1 ))
|
||||
port="${!i}"
|
||||
if ! nc -w 1 -z "$host" "$port"; then
|
||||
success=false
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if "$success"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
command=("${CANTON_COMMAND[@]}")
|
||||
dars=()
|
||||
port_file=''
|
||||
while (( $# )); do
|
||||
# extract the port file
|
||||
if [[ "$1" == '--port-file' ]]; then
|
||||
port_file="$2"
|
||||
shift
|
||||
shift
|
||||
# upload DARs with the DAML assistant
|
||||
elif [[ "$1" =~ \.dar$ ]]; then
|
||||
dars+=("$1")
|
||||
shift
|
||||
else
|
||||
command+=("$1")
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "$port_file" ]]; then
|
||||
# shellcheck disable=SC2016
|
||||
echo >&2 'You must specify a port file with the `--port-file` switch.'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Redirect the Canton logs to a file for now, because they're really, really noisy.
|
||||
log_file="$(mktemp -t 'canton.XXXXX.log')"
|
||||
echo >&2 'Starting Canton...'
|
||||
echo >&2 "(Logs will be written to \"${log_file}\".)"
|
||||
"${command[@]}" >& "$log_file" &
|
||||
pid="$!"
|
||||
|
||||
sleep 1
|
||||
if ! kill -0 "$pid" 2> /dev/null; then
|
||||
echo >&2 'Failed to start Canton.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function stop {
|
||||
local status
|
||||
status=$?
|
||||
kill "$pid" || :
|
||||
rm -f "$port_file" || :
|
||||
exit "$status"
|
||||
}
|
||||
|
||||
trap stop EXIT INT TERM
|
||||
|
||||
wait_for_ports \
|
||||
"$PARTICIPANT_1_LEDGER_API_HOST" "$PARTICIPANT_1_LEDGER_API_PORT" \
|
||||
"$PARTICIPANT_2_LEDGER_API_HOST" "$PARTICIPANT_2_LEDGER_API_PORT"
|
||||
|
||||
for participant in "${PARTICIPANTS[@]}"; do
|
||||
for dar in "${dars[@]}"; do
|
||||
base64 "$dar" \
|
||||
| jq -R --slurp '{"darFile": .}' \
|
||||
| grpcurl \
|
||||
-plaintext \
|
||||
-d @ \
|
||||
"$participant" \
|
||||
com.digitalasset.ledger.api.v1.admin.PackageManagementService.UploadDarFile \
|
||||
> /dev/null
|
||||
done
|
||||
done
|
||||
|
||||
# This should write two ports, but the runner doesn't support that.
|
||||
echo "$PARTICIPANT_1_LEDGER_API_PORT" > "$port_file"
|
||||
|
||||
echo >&2 'Canton is up and running.'
|
||||
|
||||
wait "$pid"
|
47
ledger/ledger-api-test-tool-on-canton/canton.conf
Normal file
47
ledger/ledger-api-test-tool-on-canton/canton.conf
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2019 The DAML Authors. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
canton {
|
||||
domains {
|
||||
test_domain {
|
||||
storage {
|
||||
type = memory
|
||||
}
|
||||
|
||||
server {
|
||||
public.port = 4011
|
||||
admin.port = 4012
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
participants {
|
||||
participant_1 {
|
||||
storage {
|
||||
type = memory
|
||||
}
|
||||
|
||||
ledger-api {
|
||||
port = 5011
|
||||
}
|
||||
|
||||
admin-api {
|
||||
port = 5012
|
||||
}
|
||||
}
|
||||
|
||||
participant_2 {
|
||||
storage {
|
||||
type = memory
|
||||
}
|
||||
|
||||
ledger-api {
|
||||
port = 5021
|
||||
}
|
||||
|
||||
admin-api {
|
||||
port = 5022
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -73,6 +73,15 @@ object LedgerApiTestTool {
|
||||
sys.exit(0)
|
||||
}
|
||||
|
||||
val missingTests = (config.included ++ config.excluded).filterNot(tests.all.contains)
|
||||
if (missingTests.nonEmpty) {
|
||||
println("The following tests could not be found:")
|
||||
missingTests.foreach { testName =>
|
||||
println(s" - $testName")
|
||||
}
|
||||
sys.exit(2)
|
||||
}
|
||||
|
||||
val included =
|
||||
if (config.allTests) tests.all.keySet
|
||||
else if (config.included.isEmpty) tests.default.keySet
|
||||
|
@ -3,14 +3,15 @@
|
||||
|
||||
package com.daml.ledger.api.testtool.infrastructure
|
||||
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scala.concurrent.duration.{Duration, DurationInt}
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
object Eventually {
|
||||
private val withRetryStrategy = RetryStrategy.exponentialBackoff(10, 10.millis)
|
||||
|
||||
def eventually[A](runAssertion: => Future[A])(implicit ec: ExecutionContext): Future[A] =
|
||||
withRetryStrategy { _ =>
|
||||
def eventually[A](
|
||||
runAssertion: => Future[A],
|
||||
attempts: Int = 10,
|
||||
firstWaitTime: Duration = 10.millis)(implicit ec: ExecutionContext): Future[A] =
|
||||
RetryStrategy.exponentialBackoff(attempts, firstWaitTime) { _ =>
|
||||
runAssertion
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ import com.daml.ledger.api.testtool.infrastructure.Allocation.{
|
||||
ParticipantAllocation,
|
||||
Participants
|
||||
}
|
||||
import com.daml.ledger.api.testtool.infrastructure.Eventually.eventually
|
||||
import com.daml.ledger.api.testtool.infrastructure.participant.ParticipantTestContext
|
||||
import com.digitalasset.ledger.client.binding.Primitive.Party
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
@ -39,12 +41,30 @@ private[testtool] final class LedgerTestContext private[infrastructure] (
|
||||
Future
|
||||
.sequence(allocation.partyCounts.map(partyCount => {
|
||||
val participant = nextParticipant()
|
||||
participant
|
||||
.allocateParties(partyCount.count)
|
||||
.map(parties => Participant(participant, parties: _*))
|
||||
for {
|
||||
parties <- participant.allocateParties(partyCount.count)
|
||||
partiesSet = parties.toSet
|
||||
_ <- eventually(waitForParties(participant, partiesSet))
|
||||
} yield Participant(participant, parties: _*)
|
||||
}))
|
||||
.map(Participants(_: _*))
|
||||
|
||||
private[this] def waitForParties(
|
||||
participant: ParticipantTestContext,
|
||||
expectedParties: Set[Party]): Future[Unit] = {
|
||||
Future
|
||||
.sequence(participants.map(otherParticipant => {
|
||||
otherParticipant
|
||||
.listParties()
|
||||
.map(actualParties => {
|
||||
assert(
|
||||
expectedParties.subsetOf(actualParties),
|
||||
s"Parties from $participant never appeared on $otherParticipant.")
|
||||
})
|
||||
}))
|
||||
.map(_ => ())
|
||||
}
|
||||
|
||||
private[this] def nextParticipant(): ParticipantTestContext =
|
||||
participantsRing.synchronized {
|
||||
participantsRing.next()
|
||||
|
@ -19,7 +19,8 @@ import com.digitalasset.ledger.api.v1.admin.package_management_service.{
|
||||
}
|
||||
import com.digitalasset.ledger.api.v1.admin.party_management_service.{
|
||||
AllocatePartyRequest,
|
||||
GetParticipantIdRequest
|
||||
GetParticipantIdRequest,
|
||||
ListKnownPartiesRequest
|
||||
}
|
||||
import com.digitalasset.ledger.api.v1.command_completion_service.{
|
||||
CompletionStreamRequest,
|
||||
@ -188,6 +189,11 @@ private[testtool] final class ParticipantTestContext private[participant] (
|
||||
def allocateParties(n: Int): Future[Vector[Party]] =
|
||||
Future.sequence(Vector.fill(n)(allocateParty()))
|
||||
|
||||
def listParties(): Future[Set[Party]] =
|
||||
services.partyManagement
|
||||
.listKnownParties(new ListKnownPartiesRequest())
|
||||
.map(_.partyDetails.map(partyDetails => Party(partyDetails.party)).toSet)
|
||||
|
||||
def activeContracts(
|
||||
request: GetActiveContractsRequest): Future[(Option[LedgerOffset], Vector[CreatedEvent])] =
|
||||
for {
|
||||
|
@ -3,13 +3,10 @@
|
||||
|
||||
package com.daml.ledger.api.testtool.tests
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
import com.daml.ledger.api.testtool.infrastructure.Allocation._
|
||||
import com.daml.ledger.api.testtool.infrastructure.Assertions._
|
||||
import com.daml.ledger.api.testtool.infrastructure.TransactionHelpers._
|
||||
import com.daml.ledger.api.testtool.infrastructure.{LedgerSession, LedgerTestSuite}
|
||||
import com.digitalasset.ledger.api.v1.value.{Record, RecordField, Value}
|
||||
import com.digitalasset.ledger.client.binding.Primitive
|
||||
import com.digitalasset.ledger.client.binding.Value.encode
|
||||
import com.digitalasset.ledger.test_stable.Test.CallablePayout._
|
||||
@ -313,57 +310,6 @@ final class CommandService(session: LedgerSession) extends LedgerTestSuite(sessi
|
||||
}
|
||||
}
|
||||
|
||||
test(
|
||||
"CSExerciseByKey",
|
||||
"Exercising by key should be possible only when the corresponding contract is available",
|
||||
allocate(SingleParty)) {
|
||||
case Participants(Participant(ledger, party)) =>
|
||||
val keyString = UUID.randomUUID.toString
|
||||
val expectedKey = Value(
|
||||
Value.Sum.Record(
|
||||
Record(
|
||||
fields = Seq(
|
||||
RecordField("_1", Some(Value(Value.Sum.Party(party.unwrap)))),
|
||||
RecordField("_2", Some(Value(Value.Sum.Text(keyString))))
|
||||
))))
|
||||
for {
|
||||
failureBeforeCreation <- ledger
|
||||
.exerciseByKey(
|
||||
party,
|
||||
TextKey.id,
|
||||
expectedKey,
|
||||
"TextKeyChoice",
|
||||
Value(Value.Sum.Record(Record())))
|
||||
.failed
|
||||
_ <- ledger.create(party, TextKey(party, keyString, Primitive.List.empty))
|
||||
_ <- ledger.exerciseByKey(
|
||||
party,
|
||||
TextKey.id,
|
||||
expectedKey,
|
||||
"TextKeyChoice",
|
||||
Value(Value.Sum.Record(Record())))
|
||||
failureAfterConsuming <- ledger
|
||||
.exerciseByKey(
|
||||
party,
|
||||
TextKey.id,
|
||||
expectedKey,
|
||||
"TextKeyChoice",
|
||||
Value(Value.Sum.Record(Record())))
|
||||
.failed
|
||||
} yield {
|
||||
assertGrpcError(
|
||||
failureBeforeCreation,
|
||||
Status.Code.INVALID_ARGUMENT,
|
||||
"dependency error: couldn't find key"
|
||||
)
|
||||
assertGrpcError(
|
||||
failureAfterConsuming,
|
||||
Status.Code.INVALID_ARGUMENT,
|
||||
"dependency error: couldn't find key"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test(
|
||||
"CSDiscloseCreateToObservers",
|
||||
"Disclose create to observers",
|
||||
|
@ -9,7 +9,9 @@ import com.daml.ledger.api.testtool.infrastructure.Allocation._
|
||||
import com.daml.ledger.api.testtool.infrastructure.Assertions._
|
||||
import com.daml.ledger.api.testtool.infrastructure.Eventually.eventually
|
||||
import com.daml.ledger.api.testtool.infrastructure.Synchronize.synchronize
|
||||
import com.daml.ledger.api.testtool.infrastructure.TransactionHelpers._
|
||||
import com.daml.ledger.api.testtool.infrastructure.{LedgerSession, LedgerTestSuite}
|
||||
import com.digitalasset.ledger.api.v1.value.{Record, RecordField, Value}
|
||||
import com.digitalasset.ledger.test_stable.DA.Types.Tuple2
|
||||
import com.digitalasset.ledger.test_stable.Test.Delegated._
|
||||
import com.digitalasset.ledger.test_stable.Test.Delegation._
|
||||
@ -220,4 +222,77 @@ final class ContractKeys(session: LedgerSession) extends LedgerTestSuite(session
|
||||
assertGrpcError(failedFetch, Status.Code.INVALID_ARGUMENT, "couldn't find key")
|
||||
}
|
||||
}
|
||||
|
||||
test(
|
||||
"CKExposedByTemplate",
|
||||
"The contract key should be exposed if the template specifies one",
|
||||
allocate(SingleParty)) {
|
||||
case Participants(Participant(ledger, party)) =>
|
||||
val expectedKey = "some-fancy-key"
|
||||
for {
|
||||
_ <- ledger.create(party, TextKey(party, expectedKey, List.empty))
|
||||
transactions <- ledger.flatTransactions(party)
|
||||
} yield {
|
||||
val contract = assertSingleton("CKExposedByTemplate", transactions.flatMap(createdEvents))
|
||||
assertEquals(
|
||||
"CKExposedByTemplate",
|
||||
contract.getContractKey.getRecord.fields,
|
||||
Seq(
|
||||
RecordField("_1", Some(Value(Value.Sum.Party(Tag.unwrap(party))))),
|
||||
RecordField("_2", Some(Value(Value.Sum.Text(expectedKey))))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test(
|
||||
"CKExerciseByKey",
|
||||
"Exercising by key should be possible only when the corresponding contract is available",
|
||||
allocate(SingleParty)) {
|
||||
case Participants(Participant(ledger, party)) =>
|
||||
val keyString = UUID.randomUUID.toString
|
||||
val expectedKey = Value(
|
||||
Value.Sum.Record(
|
||||
Record(
|
||||
fields = Seq(
|
||||
RecordField("_1", Some(Value(Value.Sum.Party(Tag.unwrap(party))))),
|
||||
RecordField("_2", Some(Value(Value.Sum.Text(keyString))))
|
||||
))))
|
||||
for {
|
||||
failureBeforeCreation <- ledger
|
||||
.exerciseByKey(
|
||||
party,
|
||||
TextKey.id,
|
||||
expectedKey,
|
||||
"TextKeyChoice",
|
||||
Value(Value.Sum.Record(Record())))
|
||||
.failed
|
||||
_ <- ledger.create(party, TextKey(party, keyString, List.empty))
|
||||
_ <- ledger.exerciseByKey(
|
||||
party,
|
||||
TextKey.id,
|
||||
expectedKey,
|
||||
"TextKeyChoice",
|
||||
Value(Value.Sum.Record(Record())))
|
||||
failureAfterConsuming <- ledger
|
||||
.exerciseByKey(
|
||||
party,
|
||||
TextKey.id,
|
||||
expectedKey,
|
||||
"TextKeyChoice",
|
||||
Value(Value.Sum.Record(Record())))
|
||||
.failed
|
||||
} yield {
|
||||
assertGrpcError(
|
||||
failureBeforeCreation,
|
||||
Status.Code.INVALID_ARGUMENT,
|
||||
"dependency error: couldn't find key"
|
||||
)
|
||||
assertGrpcError(
|
||||
failureAfterConsuming,
|
||||
Status.Code.INVALID_ARGUMENT,
|
||||
"dependency error: couldn't find key"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import com.daml.ledger.api.testtool.infrastructure.Synchronize.synchronize
|
||||
import com.daml.ledger.api.testtool.infrastructure.TransactionHelpers._
|
||||
import com.daml.ledger.api.testtool.infrastructure.{LedgerSession, LedgerTestSuite}
|
||||
import com.digitalasset.ledger.api.v1.transaction.Transaction
|
||||
import com.digitalasset.ledger.api.v1.value.{RecordField, Value}
|
||||
import com.digitalasset.ledger.client.binding.Primitive
|
||||
import com.digitalasset.ledger.client.binding.Value.encode
|
||||
import com.digitalasset.ledger.test_dev.Test.TextContainer
|
||||
@ -665,28 +664,6 @@ class TransactionService(session: LedgerSession) extends LedgerTestSuite(session
|
||||
}
|
||||
}
|
||||
|
||||
test(
|
||||
"TXContractKey",
|
||||
"The contract key should be exposed if the template specifies one",
|
||||
allocate(SingleParty)) {
|
||||
case Participants(Participant(ledger, party)) =>
|
||||
val expectedKey = "some-fancy-key"
|
||||
for {
|
||||
_ <- ledger.create(party, TextKey(party, expectedKey, Primitive.List.empty))
|
||||
transactions <- ledger.flatTransactions(party)
|
||||
} yield {
|
||||
val contract = assertSingleton(s"ContractKey", transactions.flatMap(createdEvents))
|
||||
assertEquals(
|
||||
"ContractKey",
|
||||
contract.getContractKey.getRecord.fields,
|
||||
Seq(
|
||||
RecordField("_1", Some(Value(Value.Sum.Party(Tag.unwrap(party))))),
|
||||
RecordField("_2", Some(Value(Value.Sum.Text(expectedKey))))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test(
|
||||
"TXMultiActorChoiceOk",
|
||||
"Accept exercising a well-authorized multi-actor choice",
|
||||
|
@ -110,7 +110,7 @@ trait PostgresAround {
|
||||
} catch {
|
||||
case NonFatal(e) =>
|
||||
throw new IllegalStateException(
|
||||
s"Cannot start Postgres fixture. Failed command: ${command.toString}",
|
||||
s"Cannot start Postgres fixture. Failed command: ${command.mkString(" ")}",
|
||||
e)
|
||||
}
|
||||
}
|
||||
|
@ -6,15 +6,18 @@
|
||||
}:
|
||||
let shared = rec {
|
||||
inherit (pkgs)
|
||||
coreutils
|
||||
curl
|
||||
docker
|
||||
gawk
|
||||
gnutar
|
||||
grpcurl
|
||||
gzip
|
||||
hlint
|
||||
imagemagick
|
||||
jdk8
|
||||
jq
|
||||
netcat-gnu
|
||||
nodejs
|
||||
patchelf
|
||||
postgresql_9_6
|
||||
|
Loading…
Reference in New Issue
Block a user