Extend trigger compat tests to be agnostic to high-level changes (#7828)

The trigger runner (delibaretely) only cares about the high-level
API. This means that we can change the high-level API without breaking
backwards compatibility in the runner. However, we do of course have
to change the trigger code written in the high-level API.

This PR addresses this by making the code depend on the
version. Unfortunately we cannot use CPP here (something I don’t say
very often) so this is done in a Bazel function.

The last low-level breaking change was the change to `CommandId`
generation so we go back to that.

changelog_begin
changelog_end
This commit is contained in:
Moritz Kiefer 2020-10-29 14:19:10 +01:00 committed by GitHub
parent 6572457973
commit 90cfe8b955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 116 additions and 116 deletions

View File

@ -79,12 +79,13 @@ config_setting(
if versions.is_at_least(sdk_version, platform_version)
]
last_pre_7632_trigger_version = "1.7.0-snapshot.20201013.5418.0.bda13392"
# Change to `CommandId` generation
first_post_7587_trigger_version = "1.7.0-snapshot.20201012.5405.0.af92198d"
[
daml_trigger_dar(sdk_version)
for sdk_version in sdk_versions
if not versions.is_at_most(last_pre_7632_trigger_version, sdk_version)
if versions.is_at_least(first_post_7587_trigger_version, sdk_version)
]
[
@ -97,7 +98,7 @@ last_pre_7632_trigger_version = "1.7.0-snapshot.20201013.5418.0.bda13392"
# Test that the DAML trigger runner can run DARs built with an older SDK
# version. I.e. where the runner version is at least the SDK version or
# more recent.
if (not versions.is_at_most(last_pre_7632_trigger_version, sdk_version)) and
if versions.is_at_least(first_post_7587_trigger_version, sdk_version) and
versions.is_at_least(sdk_version, platform_version)
]

View File

@ -5,7 +5,69 @@ load(
"@daml//bazel_tools/client_server:client_server_test.bzl",
"client_server_test",
)
load("//bazel_tools:versions.bzl", "version_to_name")
load("//bazel_tools:versions.bzl", "version_to_name", "versions")
def copy_trigger_src(sdk_version):
# To avoid having to mess with Bazels escaping, avoid `$` and backticks.
# We cant use CPP to make this nicer unfortunately since this doesnt work
# with an installed SDK.
return """
module CopyTrigger where
import DA.List hiding (dedup)
import Templates
import Daml.Trigger
copyTrigger : Trigger ()
copyTrigger = Trigger
{{ initialize = pure ()
, updateState = \\_message {acsArg} -> pure ()
, rule = copyRule
, registeredTemplates = AllInDar
, heartbeat = None
}}
copyRule party {acsArg} {stateArg} = do
subscribers : [(ContractId Subscriber, Subscriber)] <- {query} {acsArg}
originals : [(ContractId Original, Original)] <- {query} {acsArg}
copies : [(ContractId Copy, Copy)] <- {query} {acsArg}
let ownedSubscribers = filter (\\(_, s) -> s.subscribedTo == party) subscribers
let ownedOriginals = filter (\\(_, o) -> o.owner == party) originals
let ownedCopies = filter (\\(_, c) -> c.original.owner == party) copies
let subscribingParties = map (\\(_, s) -> s.subscriber) ownedSubscribers
let groupedCopies : [[(ContractId Copy, Copy)]]
groupedCopies = groupOn snd (sortOn snd ownedCopies)
let copiesToKeep = map head groupedCopies
let archiveDuplicateCopies = concatMap tail groupedCopies
let archiveMissingOriginal = filter (\\(_, c) -> notElem c.original (map snd ownedOriginals)) copiesToKeep
let archiveMissingSubscriber = filter (\\(_, c) -> notElem c.subscriber subscribingParties) copiesToKeep
let archiveCopies = dedup (map fst (archiveDuplicateCopies <> archiveMissingOriginal <> archiveMissingSubscriber))
forA archiveCopies (\\cid -> dedupExercise cid Archive)
let neededCopies = [Copy m o | (_, m) <- ownedOriginals, o <- subscribingParties]
let createCopies = filter (\\c -> notElem c (map snd copiesToKeep)) neededCopies
mapA dedupCreate createCopies
pure ()
dedup : Eq k => [k] -> [k]
dedup [] = []
dedup (x :: xs) = x :: dedup (filter (/= x) xs)
""".format(
stateArg = "_" if versions.is_at_most(last_pre_7674_version, sdk_version) else "",
acsArg = "acs" if versions.is_at_most(last_pre_7632_version, sdk_version) else "",
query = "(pure . getContracts)" if versions.is_at_most(last_pre_7632_version, sdk_version) else "query",
)
# Removal of state argument.
last_pre_7674_version = "1.7.0-snapshot.20201013.5418.0.bda13392"
# Removal of ACS argument
last_pre_7632_version = "1.7.0-snapshot.20201012.5405.0.af92198d"
def daml_trigger_dar(sdk_version):
daml = "@daml-sdk-{sdk_version}//:daml".format(
@ -16,8 +78,8 @@ def daml_trigger_dar(sdk_version):
sdk_version = version_to_name(sdk_version),
),
srcs = [
"//bazel_tools/daml_trigger:example/src/CopyTrigger.daml",
"//bazel_tools/daml_trigger:example/src/TestScript.daml",
"//bazel_tools/daml_trigger:example/src/Templates.daml",
],
outs = ["trigger-example-{sdk_version}.dar".format(
sdk_version = version_to_name(sdk_version),
@ -29,8 +91,9 @@ TMP_DIR=$$(mktemp -d)
cleanup() {{ rm -rf $$TMP_DIR; }}
trap cleanup EXIT
mkdir -p $$TMP_DIR/src
cp -L $(location //bazel_tools/daml_trigger:example/src/CopyTrigger.daml) $$TMP_DIR/src/
echo "{copy_trigger}" > $$TMP_DIR/src/CopyTrigger.daml
cp -L $(location //bazel_tools/daml_trigger:example/src/TestScript.daml) $$TMP_DIR/src/
cp -L $(location //bazel_tools/daml_trigger:example/src/Templates.daml) $$TMP_DIR/src/
cat <<EOF >$$TMP_DIR/daml.yaml
sdk-version: {sdk_version}
name: trigger-example
@ -46,6 +109,7 @@ $(location {daml}) build --project-root=$$TMP_DIR -o $$PWD/$(OUTS)
""".format(
daml = daml,
sdk_version = sdk_version,
copy_trigger = copy_trigger_src(sdk_version),
),
)

View File

@ -1,109 +0,0 @@
-- Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
module CopyTrigger where
import DA.List hiding (dedup)
import Daml.Trigger
-- ORIGINAL_TEMPLATE_BEGIN
template Original
with
owner : Party
name : Text
textdata : Text
where
signatory owner
key (owner, name) : (Party, Text)
maintainer key._1
-- ORIGINAL_TEMPLATE_END
deriving instance Ord Original
-- SUBSCRIBER_TEMPLATE_BEGIN
template Subscriber
with
subscriber : Party
subscribedTo : Party
where
signatory subscriber
observer subscribedTo
key (subscriber, subscribedTo) : (Party, Party)
maintainer key._1
-- SUBSCRIBER_TEMPLATE_END
-- COPY_TEMPLATE_BEGIN
template Copy
with
original : Original
subscriber : Party
where
signatory (signatory original)
observer subscriber
-- COPY_TEMPLATE_END
deriving instance Ord Copy
-- TRIGGER_BEGIN
copyTrigger : Trigger ()
copyTrigger = Trigger
{ initialize = pure ()
, updateState = \_message -> pure ()
, rule = copyRule
, registeredTemplates = AllInDar
, heartbeat = None
}
-- TRIGGER_END
-- RULE_SIGNATURE_BEGIN
copyRule : Party -> TriggerA () ()
copyRule party = do
-- RULE_SIGNATURE_END
-- ACS_QUERY_BEGIN
subscribers : [(ContractId Subscriber, Subscriber)] <- query @Subscriber
originals : [(ContractId Original, Original)] <- query @Original
copies : [(ContractId Copy, Copy)] <- query @Copy
-- ACS_QUERY_END
-- ACS_FILTER_BEGIN
let ownedSubscribers = filter (\(_, s) -> s.subscribedTo == party) subscribers
let ownedOriginals = filter (\(_, o) -> o.owner == party) originals
let ownedCopies = filter (\(_, c) -> c.original.owner == party) copies
-- ACS_FILTER_END
-- SUBSCRIBING_PARTIES_BEGIN
let subscribingParties = map (\(_, s) -> s.subscriber) ownedSubscribers
-- SUBSCRIBING_PARTIES_END
-- GROUP_COPIES_BEGIN
let groupedCopies : [[(ContractId Copy, Copy)]]
groupedCopies = groupOn snd $ sortOn snd $ ownedCopies
let copiesToKeep = map head groupedCopies
let archiveDuplicateCopies = concatMap tail groupedCopies
-- GROUP_COPIES_END
-- ARCHIVE_COPIES_BEGIN
let archiveMissingOriginal = filter (\(_, c) -> c.original `notElem` map snd ownedOriginals) copiesToKeep
let archiveMissingSubscriber = filter (\(_, c) -> c.subscriber `notElem` subscribingParties) copiesToKeep
let archiveCopies = dedup $ map fst $ archiveDuplicateCopies <> archiveMissingOriginal <> archiveMissingSubscriber
-- ARCHIVE_COPIES_END
-- ARCHIVE_COMMAND_BEGIN
forA archiveCopies $ \cid -> dedupExercise cid Archive
-- ARCHIVE_COMMAND_END
-- CREATE_COPIES_BEGIN
let neededCopies = [Copy m o | (_, m) <- ownedOriginals, o <- subscribingParties]
let createCopies = filter (\c -> c `notElem` map snd copiesToKeep) neededCopies
mapA dedupCreate createCopies
-- CREATE_COPIES_END
pure ()
-- | The dedup function from DA.List requires an Ord constraint which we do not have for `ContractId k`. Therefore,
-- we resort to the n^2 version for now. Once we have Maps we can use those to implement a more efficient dedup.
dedup : Eq k => [k] -> [k]
dedup [] = []
dedup (x :: xs) = x :: dedup (filter (/= x) xs)

View File

@ -0,0 +1,44 @@
-- Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
module Templates where
-- ORIGINAL_TEMPLATE_BEGIN
template Original
with
owner : Party
name : Text
textdata : Text
where
signatory owner
key (owner, name) : (Party, Text)
maintainer key._1
-- ORIGINAL_TEMPLATE_END
deriving instance Ord Original
-- SUBSCRIBER_TEMPLATE_BEGIN
template Subscriber
with
subscriber : Party
subscribedTo : Party
where
signatory subscriber
observer subscribedTo
key (subscriber, subscribedTo) : (Party, Party)
maintainer key._1
-- SUBSCRIBER_TEMPLATE_END
-- COPY_TEMPLATE_BEGIN
template Copy
with
original : Original
subscriber : Party
where
signatory (signatory original)
observer subscriber
-- COPY_TEMPLATE_END
deriving instance Ord Copy

View File

@ -3,7 +3,7 @@
module TestScript where
import CopyTrigger
import Templates
import DA.Assert
import DA.Time
import Daml.Script