daml-lf-encoder: validate dar generated by the encoder (#3339)

This commit is contained in:
Remy 2019-11-05 16:15:08 +01:00 committed by mergify[bot]
parent 90679c93f8
commit 2885766826
24 changed files with 202 additions and 104 deletions

View File

@ -1120,7 +1120,6 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
PLText(getInternedStr(lfPrimLit.getTextInternedStr))
case PLF.PrimLit.SumCase.NUMERIC_INTERNED_STR =>
assertSince(LV.Features.numeric, "PrimLit.numeric")
assertSince(LV.Features.internedStrings, "PrimLit.decimal_interned_str")
toPLNumeric(getInternedStr(lfPrimLit.getNumericInternedStr))
case PLF.PrimLit.SumCase.PARTY_INTERNED_STR =>
assertSince(LV.Features.internedStrings, "PrimLit.party_interned_str")

View File

@ -100,18 +100,35 @@ da_scala_binary(
]
[
genrule(
name = "testing-dar-%s" % target,
srcs = [":lf_%s" % target],
outs = ["test-%s.dar" % target],
cmd = "$(location :encoder_binary) $(SRCS) --output $@ --target %s" % target,
tools = [":encoder_binary"],
visibility = [
"//daml-lf:__subpackages__",
"//extractor:__subpackages__",
"//language-support:__subpackages__",
],
)
[
genrule(
name = "testing-dar-%s" % target,
srcs = [":lf_%s" % target],
outs = ["test-%s.dar" % target],
cmd = "$(location :encoder_binary) $(SRCS) --output $@ --target %s" % target,
tools = [":encoder_binary"],
visibility = [
"//daml-lf:__subpackages__",
"//extractor:__subpackages__",
"//language-support:__subpackages__",
],
),
sh_test(
name = "validate-dar-%s" % target,
srcs = ["src/validate.sh"],
args = [
"$(location //daml-lf/repl:repl)",
"$(location :testing-dar-%s)" % target,
],
data = [
"//daml-lf/repl",
"testing-dar-%s" % target,
],
deps = [
"@bazel_tools//tools/bash/runfiles",
],
),
]
for target in lf_targets
]

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Bool {
module BoolMod {
record @serializable Box = { x: Bool, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Bool:Box {party} this)),
signatories (PartyMod:one (BoolMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Bool:Box",
agreement "Agreement for BoolMod:Box",
choices {
}
};

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Date {
module DateMod {
record @serializable Box = { x: Date, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Date:Box {party} this)),
signatories (PartyMod:one (DateMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Date:Box",
agreement "Agreement for DateMod:Box",
choices {
}
};

View File

@ -1,17 +1,32 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Decimal {
module DecimalMod {
record @serializable Box = { x: Numeric 10, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Decimal:Box {party} this)),
signatories (PartyMod:one (DecimalMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Decimal:Box",
agreement "Agreement for DecimalMod:Box",
choices {
}
};
val build0: DecimalMod:Box = DecimalMod:Box {
x = 0.0000000000 ,
party = 'Alice'
};
val buildMax: DecimalMod:Box = DecimalMod:Box {
x = 9999999999999999999999999999.9999999999 ,
party = 'Alice'
};
val buildMin: DecimalMod:Box = DecimalMod:Box {
x = -9999999999999999999999999999.9999999999 ,
party = 'Alice'
};
}

View File

@ -1,42 +1,42 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Enum {
module EnumMod {
enum @serializable Color = Red | Green | Blue;
record @serializable Box = { x: Enum:Color, party: Party } ;
record @serializable Box = { x: EnumMod:Color, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Enum:Box {party} this)),
signatories (PartyMod:one (EnumMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement",
agreement "Agreement for EnumMod:Box",
choices {
}
};
val createColoredContract: Enum:Color -> Scenario (ContractId Enum:Box) = \ (color: Enum:Color) ->
commit @(ContractId Enum:Box) 'Bob' (create @Enum:Box (Enum:Box { x = color, party = 'Bob' }));
val createColoredContract: EnumMod:Color -> Scenario (ContractId EnumMod:Box) = \ (color: EnumMod:Color) ->
commit @(ContractId EnumMod:Box) 'Bob' (create @EnumMod:Box (EnumMod:Box { x = color, party = 'Bob' }));
val createContracts: Scenario Unit =
sbind
c1 : ContractId Enum:Box <- Enum:createColoredContract Enum:Color:Red ;
c2 : ContractId Enum:Box <- Enum:createColoredContract Enum:Color:Green ;
c3 : ContractId Enum:Box <- Enum:createColoredContract Enum:Color:Blue
c1 : ContractId EnumMod:Box <- EnumMod:createColoredContract EnumMod:Color:Red ;
c2 : ContractId EnumMod:Box <- EnumMod:createColoredContract EnumMod:Color:Green ;
c3 : ContractId EnumMod:Box <- EnumMod:createColoredContract EnumMod:Color:Blue
in
spure @Unit () ;
enum Nothing = ;
variant @serializable OptionalColor = NoColor: Unit | SomeColor: Enum:Color;
variant @serializable OptionalColor = NoColor: Unit | SomeColor: EnumMod:Color;
variant @serializable ColoredTree = Leaf: Unit | Node : Enum:ColoredTree.Node;
variant @serializable ColoredTree = Leaf: Unit | Node : EnumMod:ColoredTree.Node;
record @serializable ColoredTree.Node = {
color: Enum:Color,
left: Enum:ColoredTree,
right: Enum:ColoredTree
color: EnumMod:Color,
left: EnumMod:ColoredTree,
right: EnumMod:ColoredTree
};
}

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Int64 {
module Int64Mod {
record @serializable Box = { x: Int64, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Int64:Box {party} this)),
signatories (PartyMod:one (Int64Mod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Int64:Box",
agreement "Agreement for Int64Mod:Box",
choices {
}
};

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module List {
module ListMod {
record @serializable Box = { x: List Int64, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (List:Box {party} this)),
signatories (PartyMod:one (ListMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement",
agreement "Agreement for ListMod:Box",
choices {
}
};

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Map {
module MapMod {
record @serializable Box = { x: Map Int64, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Map:Box {party} this)),
signatories (PartyMod:one (MapMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement",
agreement "Agreement MapMod:Box",
choices {
}
};

View File

@ -1,7 +1,7 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Numeric {
module NumericMod {
record @serializable Box = {
x0: Numeric 0,
@ -13,11 +13,35 @@ module Numeric {
template (this : Box) = {
precondition True,
signatories (Party:one (Numeric:Box {party} this)),
signatories (PartyMod:one (NumericMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Numeric:Box",
agreement "Agreement for NumericMod:Box",
choices {
}
};
val build0: NumericMod:Box = NumericMod:Box {
x0 = 0. ,
x10 = 0.0000000000 ,
x17 = 0.00000000000000000 ,
x37 = 0.0000000000000000000000000000000000000 ,
party = 'Alice'
};
val buildMax: NumericMod:Box = NumericMod:Box {
x0 = 99999999999999999999999999999999999999. ,
x10 = 9999999999999999999999999999.9999999999 ,
x17 = 999999999999999999999.99999999999999999 ,
x37 = 9.9999999999999999999999999999999999999 ,
party = 'Alice'
};
val buildMin: NumericMod:Box = NumericMod:Box {
x0 = -99999999999999999999999999999999999999. ,
x10 = -9999999999999999999999999999.9999999999 ,
x17 = -999999999999999999999.99999999999999999 ,
x37 = -9.9999999999999999999999999999999999999 ,
party = 'Alice'
};
}

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Option {
module OptionMod {
record @serializable Box = { x: Option Int64, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Option:Box {party} this)),
signatories (PartyMod:one (OptionMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement",
agreement "Agreement for OptionMod:Box",
choices {
}
};

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Party {
module PartyMod {
record @serializable Box = { x: Party, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Party:Box {party} this)),
signatories (PartyMod:one (PartyMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Party:Box",
agreement "Agreement for PartyMod:Box",
choices {
}
};

View File

@ -1,17 +1,17 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Record {
module RecordMod {
record @serializable Pair (a:*) (b: *) = { fst: a, snd: b };
record @serializable Box = { x: Record:Pair Int64 (Numeric 10), party: Party } ;
record @serializable Box = { x: RecordMod:Pair Int64 (Numeric 10), party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Record:Box {party} this)),
signatories (PartyMod:one (RecordMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement",
agreement "Agreement for RecordMod:Box",
choices {
}
};

View File

@ -1,17 +1,22 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Text {
module TextMod {
record @serializable Box = { x: Text, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Text:Box {party} this)),
signatories (PartyMod:one (TextMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Text:Box",
agreement "Agreement for TextMod:Box",
choices {
}
};
val build: TextMod:Box = TextMod:Box {
x = "some text",
party = 'Alice'
};
}

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Timestamp {
module TimestampMod {
record @serializable Box = { x: Timestamp, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Timestamp:Box {party} this)),
signatories (PartyMod:one (TimestampMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Timestamp:Box",
agreement "Agreement for TimestampMod:Box",
choices {
}
};

View File

@ -1,15 +1,15 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Unit {
module UnitMod {
record @serializable Box = { x: Unit, party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Unit:Box {party} this)),
signatories (PartyMod:one (UnitMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement for Unit:Box",
agreement "Agreement for UnitMod:Box",
choices {
}
};

View File

@ -1,17 +1,17 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module Variant {
module VariantMod {
variant @serializable Either (a:*) (b: *) = Left: a | Right: b ;
record @serializable Box = { x: Variant:Either Int64 (Numeric 10), party: Party } ;
record @serializable Box = { x: VariantMod:Either Int64 (Numeric 10), party: Party } ;
template (this : Box) = {
precondition True,
signatories (Party:one (Variant:Box {party} this)),
signatories (PartyMod:one (VariantMod:Box {party} this)),
observers (Nil @Party),
agreement "Agreement",
agreement "Agreement for VariantMod:Box",
choices {
}
};

32
daml-lf/encoder/src/validate.sh Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Copyright (c) 2019 The DAML Authors. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
set -eu
# --- begin runfiles.bash initialization ---
# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash).
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---
DAML_LF_REPL=$(rlocation "$TEST_WORKSPACE/$1")
FILE=$(rlocation "$TEST_WORKSPACE/$2")
$DAML_LF_REPL validate "$FILE"

View File

@ -98,7 +98,7 @@ object Main extends App {
object Repl {
def repl(): Unit = repl(initialState())
def repl(darFile: String): Unit = repl(load(darFile))
def repl(darFile: String): Unit = repl(load(darFile) getOrElse initialState())
def repl(state0: State): Unit = {
var state = state0
state.history.load
@ -114,22 +114,28 @@ object Repl {
state.history.save
}
def testAll(allowDev: Boolean, file: String): (Boolean, State) = {
val state = load(file)
cmdValidate(state)
cmdTestAll(state)
private implicit class StateOp(val x: (Boolean, State)) extends AnyVal {
def fMap(f: State => (Boolean, State)): (Boolean, State) =
x match {
case (true, state) => f(state)
case _ => x
}
def getOrElse(default: => State) =
x match {
case (true, state) => state
case _ => default
}
}
def test(allowDev: Boolean, id: String, file: String): (Boolean, State) = {
val state = load(file)
cmdValidate(state)
invokeScenario(state, Seq(id))
}
def testAll(allowDev: Boolean, file: String): (Boolean, State) =
load(file) fMap cmdValidate fMap cmdTestAll
def validate(allowDev: Boolean, file: String): (Boolean, State) = {
val state = load(file)
cmdValidate(state)
}
def test(allowDev: Boolean, id: String, file: String): (Boolean, State) =
load(file) fMap cmdValidate fMap (x => invokeScenario(x, Seq(id)))
def validate(allowDev: Boolean, file: String): (Boolean, State) =
load(file) fMap cmdValidate
def cmdValidate(state: State): (Boolean, State) = {
val validationResults = state.packages.keys.map(Validation.checkPackage(state.packages, _))
@ -320,7 +326,7 @@ object Repl {
}
// Load DAML-LF packages from a set of files.
def load(darFile: String): State = {
def load(darFile: String): (Boolean, State) = {
val state = initialState()
try {
val packages =
@ -335,7 +341,7 @@ object Repl {
packagesMap.flatMap(_._2.modules.values.map(_.definitions.size)).sum
println(s"$ndefs definitions from $npkgs package(s) loaded.")
rebuildReader(
true -> rebuildReader(
state.copy(
packages = packagesMap,
scenarioRunner = ScenarioRunnerHelper(packagesMap)
@ -345,7 +351,7 @@ object Repl {
val sw = new StringWriter
ex.printStackTrace(new PrintWriter(sw))
println("Failed to load packages: " + ex.toString + ", stack trace: " + sw.toString)
state
(false, state)
}
}
}

View File

@ -25,7 +25,7 @@ class EnumSpec
override protected def darFile = new File(rlocation("daml-lf/encoder/test-1.6.dar"))
override def scenario: Option[String] = Some("Enum:createContracts")
override def scenario: Option[String] = Some("EnumMod:createContracts")
"Enum" should "be extracted" in {
getContracts should have length 3

View File

@ -10,7 +10,7 @@ import com.daml.ledger.javaapi.data.Record;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import test.decimal.Box;
import test.decimalmod.Box;
import java.math.BigDecimal;

View File

@ -12,9 +12,9 @@ import com.daml.ledger.javaapi.data.Unit;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import test.enum$.*;
import test.enum$.optionalcolor.*;
import test.enum$.coloredtree.*;
import test.enummod.*;
import test.enummod.optionalcolor.*;
import test.enummod.coloredtree.*;
import static org.junit.jupiter.api.Assertions.*;

View File

@ -10,7 +10,7 @@ import com.daml.ledger.javaapi.data.Record;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import test.numeric.Box;
import test.numericmod.Box;
import java.math.BigDecimal;

View File

@ -4,7 +4,7 @@
package com.digitalasset.codegen
import com.digitalasset.ledger.client.binding.{Value, Primitive => P}
import com.digitalasset.sample.{Enum, Record, Variant}
import com.digitalasset.sample.{EnumMod, RecordMod, VariantMod}
import org.scalatest.{Matchers, WordSpec}
class DataTypeIT extends WordSpec with Matchers {
@ -12,31 +12,31 @@ class DataTypeIT extends WordSpec with Matchers {
"Value.decode follows by Value.encode" should {
"idempotent on records" in {
import Record.Pair._
import RecordMod.Pair._
type T = Record.Pair[P.Int64, P.Numeric]
type T = RecordMod.Pair[P.Int64, P.Numeric]
val record: T = Record.Pair(1, 1.1)
val record: T = RecordMod.Pair(1, 1.1)
Value.decode[T](Value.encode(record)) shouldBe Some(record)
}
"idempotent on variants" in {
import Variant.Either._
import VariantMod.Either._
type T = Variant.Either[P.Int64, P.Numeric]
type T = VariantMod.Either[P.Int64, P.Numeric]
val variant1: T = Variant.Either.Left(1)
val variant2: T = Variant.Either.Right(1.1)
val variant1: T = VariantMod.Either.Left(1)
val variant2: T = VariantMod.Either.Right(1.1)
Value.decode[T](Value.encode(variant1)) shouldBe Some(variant1)
Value.decode[T](Value.encode(variant2)) shouldBe Some(variant2)
}
"enums" in {
import Enum.Color._
import EnumMod.Color._
for (color <- List(Enum.Color.Red, Enum.Color.Blue, Enum.Color.Green))
for (color <- List(EnumMod.Color.Red, EnumMod.Color.Blue, EnumMod.Color.Green))
Value.decode(Value.encode(color)) shouldBe Some(color)
}