diff --git a/docs/source/api-testing.rst b/docs/source/api-testing.rst
new file mode 100644
index 0000000000..4281d32347
--- /dev/null
+++ b/docs/source/api-testing.rst
@@ -0,0 +1,467 @@
+.. highlight:: kotlin
+.. raw:: html
+
+
+
+
+API: Testing
+============
+
+.. contents::
+
+Flow testing
+------------
+
+MockNetwork
+^^^^^^^^^^^
+
+Flow testing can be fully automated using a ``MockNetwork`` composed of ``StartedMockNode`` nodes. Each
+``StartedMockNode`` behaves like a regular Corda node, but its services are either in-memory or mocked out.
+
+A ``MockNetwork`` is created as follows:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ class FlowTests {
+ private lateinit var mockNet: MockNetwork
+
+ @Before
+ fun setup() {
+ network = MockNetwork(listOf("my.cordapp.package", "my.other.cordapp.package"))
+ }
+ }
+
+
+ .. sourcecode:: java
+
+ public class IOUFlowTests {
+ private MockNetwork network;
+
+ @Before
+ public void setup() {
+ network = new MockNetwork(ImmutableList.of("my.cordapp.package", "my.other.cordapp.package"));
+ }
+ }
+
+The ``MockNetwork`` requires at a minimum a list of packages. Each package is packaged into a CorDapp JAR and installed
+as a CorDapp on each ``StartedMockNode``.
+
+Configuring the ``MockNetwork``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``MockNetwork`` is configured automatically. You can tweak its configuration using a ``MockNetworkParameters``
+object, or by using named paramters in Kotlin:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ val network = MockNetwork(
+ cordappPackages = listOf("my.cordapp.package", "my.other.cordapp.package"),
+ // If true then each node will be run in its own thread. This can result in race conditions in your
+ // code if not carefully written, but is more realistic and may help if you have flows in your app that
+ // do long blocking operations.
+ threadPerNode = false,
+ // The notaries to use on the mock network. By default you get one mock notary and that is usually
+ // sufficient.
+ notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME)),
+ // If true then messages will not be routed from sender to receiver until you use the
+ // [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code that can
+ // examine the state of the mock network before and after a message is sent, without races and without
+ // the receiving node immediately sending a response.
+ networkSendManuallyPumped = false,
+ // How traffic is allocated in the case where multiple nodes share a single identity, which happens for
+ // notaries in a cluster. You don't normally ever need to change this: it is mostly useful for testing
+ // notary implementations.
+ servicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random())
+
+ val network2 = MockNetwork(listOf("my.cordapp.package", "my.other.cordapp.package"), MockNetworkParameters(
+ // If true then each node will be run in its own thread. This can result in race conditions in your
+ // code if not carefully written, but is more realistic and may help if you have flows in your app that
+ // do long blocking operations.
+ threadPerNode = false,
+ // The notaries to use on the mock network. By default you get one mock notary and that is usually
+ // sufficient.
+ notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME)),
+ // If true then messages will not be routed from sender to receiver until you use the
+ // [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code that can
+ // examine the state of the mock network before and after a message is sent, without races and without
+ // the receiving node immediately sending a response.
+ networkSendManuallyPumped = false,
+ // How traffic is allocated in the case where multiple nodes share a single identity, which happens for
+ // notaries in a cluster. You don't normally ever need to change this: it is mostly useful for testing
+ // notary implementations.
+ servicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random())
+ )
+
+ .. sourcecode:: java
+
+ MockNetwork network = MockNetwork(ImmutableList.of("my.cordapp.package", "my.other.cordapp.package"),
+ new MockNetworkParameters()
+ // If true then each node will be run in its own thread. This can result in race conditions in
+ // your code if not carefully written, but is more realistic and may help if you have flows in
+ // your app that do long blocking operations.
+ .setThreadPerNode(false)
+ // The notaries to use on the mock network. By default you get one mock notary and that is
+ // usually sufficient.
+ .setNotarySpecs(ImmutableList.of(new MockNetworkNotarySpec(DUMMY_NOTARY_NAME)))
+ // If true then messages will not be routed from sender to receiver until you use the
+ // [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code
+ // that can examine the state of the mock network before and after a message is sent, without
+ // races and without the receiving node immediately sending a response.
+ .setNetworkSendManuallyPumped(false)
+ // How traffic is allocated in the case where multiple nodes share a single identity, which
+ // happens for notaries in a cluster. You don't normally ever need to change this: it is mostly
+ // useful for testing notary implementations.
+ .setServicePeerAllocationStrategy(new InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random()));
+
+Adding nodes to the network
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Nodes are created on the ``MockNetwork`` using:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ class FlowTests {
+ private lateinit var mockNet: MockNetwork
+ lateinit var nodeA: StartedMockNode
+ lateinit var nodeB: StartedMockNode
+
+ @Before
+ fun setup() {
+ network = MockNetwork(listOf("my.cordapp.package", "my.other.cordapp.package"))
+ nodeA = network.createPartyNode()
+ // We can optionally give the node a name.
+ nodeB = network.createPartyNode(CordaX500Name("Bank B", "London", "GB"))
+ }
+ }
+
+
+ .. sourcecode:: java
+
+ public class IOUFlowTests {
+ private MockNetwork network;
+ private StartedMockNode a;
+ private StartedMockNode b;
+
+ @Before
+ public void setup() {
+ network = new MockNetwork(ImmutableList.of("my.cordapp.package", "my.other.cordapp.package"));
+ nodeA = network.createPartyNode(null);
+ // We can optionally give the node a name.
+ nodeB = network.createPartyNode(new CordaX500Name("Bank B", "London", "GB"));
+ }
+ }
+
+Registering a node's initiated flows
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Regular Corda nodes automatically register any response flows defined in their installed CorDapps. When using a
+``MockNetwork``, each ``StartedMockNode`` must manually register any responder flows it wishes to use.
+
+Responder flows are registered as follows:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ nodeA.registerInitiatedFlow(ExampleFlow.Acceptor::class.java)
+
+ .. sourcecode:: java
+
+ nodeA.registerInitiatedFlow(ExampleFlow.Acceptor.class);
+
+Running the network
+^^^^^^^^^^^^^^^^^^^
+
+Regular Corda nodes automatically process received messages. When using a ``MockNetwork`` with
+``networkSendManuallyPumped`` set to ``false``, you must manually initiate the processing of received messages.
+
+You manually process received messages as follows:
+
+* ``StartedMockNode.pumpReceive`` to process a single message from the node's queue
+
+* ``MockNetwork.runNetwork`` to process all the messages in every node's queue. This may generate additional messages
+ that must in turn be processed
+
+ * ``network.runNetwork(-1)`` (the default in Kotlin) will exchange messages until there are no further messages to
+ process
+
+Running flows
+^^^^^^^^^^^^^
+
+A ``StartedMockNode`` starts a flow using the ``StartedNodeServices.startFlow`` method. This method returns a future
+representing the output of running the flow.
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ val signedTransactionFuture = nodeA.services.startFlow(IOUFlow(iouValue = 99, otherParty = nodeBParty))
+
+ .. sourcecode:: java
+
+ CordaFuture future = startFlow(a.getServices(), new ExampleFlow.Initiator(1, nodeBParty));
+
+The network must then be manually run before retrieving the future's value:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ val signedTransactionFuture = nodeA.services.startFlow(IOUFlow(iouValue = 99, otherParty = nodeBParty))
+ // Assuming network.networkSendManuallyPumped == false.
+ network.runNetwork()
+ val signedTransaction = future.get();
+
+ .. sourcecode:: java
+
+ CordaFuture future = startFlow(a.getServices(), new ExampleFlow.Initiator(1, nodeBParty));
+ // Assuming network.networkSendManuallyPumped == false.
+ network.runNetwork();
+ SignedTransaction signedTransaction = future.get();
+
+Accessing ``StartedMockNode`` internals
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Creating a node database transaction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Whenever you query a node's database (e.g. to extract information from the node's vault), you must wrap the query in
+a database transaction, as follows:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ nodeA.database.transaction {
+ // Perform query here.
+ }
+
+ .. sourcecode:: java
+
+ node.getDatabase().transaction(tx -> {
+ // Perform query here.
+ }
+
+Querying a node's vault
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Recorded states can be retrieved from the vault of a ``StartedMockNode`` using:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ nodeA.database.transaction {
+ val myStates = nodeA.services.vaultService.queryBy().states
+ }
+
+ .. sourcecode:: java
+
+ node.getDatabase().transaction(tx -> {
+ List myStates = node.getServices().getVaultService().queryBy(MyStateType.class).getStates();
+ }
+
+This allows you to check whether a given state has (or has not) been stored, and whether it has the correct attributes.
+
+
+Examining a node's transaction storage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Recorded transactions can be retrieved from the transaction storage of a ``StartedMockNode`` using:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ val transaction = nodeA.services.validatedTransactions.getTransaction(transaction.id)
+
+ .. sourcecode:: java
+
+ SignedTransaction transaction = nodeA.getServices().getValidatedTransactions().getTransaction(transaction.getId())
+
+This allows you to check whether a given transaction has (or has not) been stored, and whether it has the correct
+attributes.
+
+This allows you to check whether a given state has (or has not) been stored, and whether it has the correct attributes.
+
+Further examples
+^^^^^^^^^^^^^^^^
+
+* See the flow testing tutorial :doc:`here `
+* Further examples are available in the Example CorDapp in
+ `Java `_ and
+ `Kotlin `_
+
+Contract testing
+----------------
+
+The Corda test framework includes the ability to create a test ledger by calling the ``ledger`` function
+on an implementation of the ``ServiceHub`` interface.
+
+MockServices
+^^^^^^^^^^^^
+
+A mock implementation of ``ServiceHub`` is provided in ``MockServices``. This is a minimal ``ServiceHub`` that
+suffices to test contract logic. It has the ability to insert states into the vault, query the vault, and
+construct and check transactions.
+
+.. container:: codeset
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+ :language: kotlin
+ :start-after: DOCSTART 11
+ :end-before: DOCEND 11
+ :dedent: 4
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+ :language: java
+ :start-after: DOCSTART 11
+ :end-before: DOCEND 11
+ :dedent: 4
+
+
+Alternatively, there is a helper constructor which just accepts a list of ``TestIdentity``. The first identity provided is
+the identity of the node whose ``ServiceHub`` is being mocked, and any subsequent identities are identities that the node
+knows about. Only the calling package is scanned for cordapps and a test ``IdentityService`` is created
+for you, using all the given identities.
+
+.. container:: codeset
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+ :language: kotlin
+ :start-after: DOCSTART 12
+ :end-before: DOCEND 12
+ :dedent: 4
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+ :language: java
+ :start-after: DOCSTART 12
+ :end-before: DOCEND 12
+ :dedent: 4
+
+
+Writing tests using a test ledger
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``ServiceHub.ledger`` extension function allows you to create a test ledger. Within the ledger wrapper you can create
+transactions using the ``transaction`` function. Within a transaction you can define the ``input`` and
+``output`` states for the transaction, alongside any commands that are being executed, the ``timeWindow`` in which the
+transaction has been executed, and any ``attachments``, as shown in this example test:
+
+.. container:: codeset
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+ :language: kotlin
+ :start-after: DOCSTART 13
+ :end-before: DOCEND 13
+ :dedent: 4
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+ :language: java
+ :start-after: DOCSTART 13
+ :end-before: DOCEND 13
+ :dedent: 4
+
+Once all the transaction components have been specified, you can run ``verifies()`` to check that the given transaction is valid.
+
+Checking for failure states
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to test for failures, you can use the ``failsWith`` method, or in Kotlin the ``fails with`` helper method, which
+assert that the transaction fails with a specific error. If you just want to assert that the transaction has failed without
+verifying the message, there is also a ``fails`` method.
+
+.. container:: codeset
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+ :language: kotlin
+ :start-after: DOCSTART 4
+ :end-before: DOCEND 4
+ :dedent: 4
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+ :language: java
+ :start-after: DOCSTART 4
+ :end-before: DOCEND 4
+ :dedent: 4
+
+.. note::
+
+ The transaction DSL forces the last line of the test to be either a ``verifies`` or ``fails with`` statement.
+
+Testing multiple scenarios at once
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Within a single transaction block, you can assert several times that the transaction constructed so far either passes or
+fails verification. For example, you could test that a contract fails to verify because it has no output states, and then
+add the relevant output state and check that the contract verifies successfully, as in the following example:
+
+.. container:: codeset
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+ :language: kotlin
+ :start-after: DOCSTART 5
+ :end-before: DOCEND 5
+ :dedent: 4
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+ :language: java
+ :start-after: DOCSTART 5
+ :end-before: DOCEND 5
+ :dedent: 4
+
+You can also use the ``tweak`` function to create a locally scoped transaction that you can make changes to
+and then return to the original, unmodified transaction. As in the following example:
+
+.. container:: codeset
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+ :language: kotlin
+ :start-after: DOCSTART 7
+ :end-before: DOCEND 7
+ :dedent: 4
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+ :language: java
+ :start-after: DOCSTART 7
+ :end-before: DOCEND 7
+ :dedent: 4
+
+
+Chaining transactions
+~~~~~~~~~~~~~~~~~~~~~
+
+The following example shows that within a ``ledger``, you can create more than one ``transaction`` in order to test chains
+of transactions. In addition to ``transaction``, ``unverifiedTransaction`` can be used, as in the example below, to create
+transactions on the ledger without verifying them, for pre-populating the ledger with existing data. When chaining transactions,
+it is important to note that even though a ``transaction`` ``verifies`` successfully, the overall ledger may not be valid. This can
+be verified separately by placing a ``verifies`` or ``fails`` statement within the ``ledger`` block.
+
+.. container:: codeset
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+ :language: kotlin
+ :start-after: DOCSTART 9
+ :end-before: DOCEND 9
+ :dedent: 4
+
+ .. literalinclude:: ../../docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+ :language: java
+ :start-after: DOCSTART 9
+ :end-before: DOCEND 9
+ :dedent: 4
+
+
+Further examples
+^^^^^^^^^^^^^^^^
+
+* See the flow testing tutorial :doc:`here `
+* Further examples are available in the Example CorDapp in
+ `Java `_ and
+ `Kotlin `_
diff --git a/docs/source/conf.py b/docs/source/conf.py
index b34fa914f9..ebf92265fb 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -46,7 +46,7 @@ master_doc = 'index'
# General information about the project.
project = u'R3 Corda'
-copyright = u'2017, R3 Limited'
+copyright = u'2018, R3 Limited'
author = u'R3 DLG'
# The version info for the project you're documenting, acts as replacement for
diff --git a/docs/source/corda-api.rst b/docs/source/corda-api.rst
index aa55bfefcf..f0f803a227 100644
--- a/docs/source/corda-api.rst
+++ b/docs/source/corda-api.rst
@@ -17,6 +17,7 @@ The following are the core APIs that are used in the development of CorDapps:
api-service-hub
api-rpc
api-core-types
+ api-testing
Before reading this page, you should be familiar with the :doc:`key concepts of Corda `.
diff --git a/docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java b/docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
index a18e869631..ff5e91b4ed 100644
--- a/docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
+++ b/docs/source/example-code/src/test/java/net/corda/docs/java/tutorial/testdsl/CommercialPaperTest.java
@@ -21,31 +21,49 @@ import static net.corda.finance.Currencies.DOLLARS;
import static net.corda.finance.Currencies.issuedBy;
import static net.corda.finance.contracts.JavaCommercialPaper.JCP_PROGRAM_ID;
import static net.corda.testing.core.TestConstants.*;
+import static net.corda.testing.node.MockServicesKt.makeTestIdentityService;
import static net.corda.testing.node.NodeTestUtils.ledger;
import static net.corda.testing.node.NodeTestUtils.transaction;
public class CommercialPaperTest {
- private static final TestIdentity ALICE = new TestIdentity(ALICE_NAME, 70L);
- private static final PublicKey BIG_CORP_PUBKEY = generateKeyPair().getPublic();
- private static final TestIdentity BOB = new TestIdentity(BOB_NAME, 80L);
- private static final TestIdentity MEGA_CORP = new TestIdentity(new CordaX500Name("MegaCorp", "London", "GB"));
+ private static final TestIdentity alice = new TestIdentity(ALICE_NAME, 70L);
+ private static final TestIdentity bigCorp = new TestIdentity(new CordaX500Name("BigCorp", "New York", "GB"));
+ private static final TestIdentity bob = new TestIdentity(BOB_NAME, 80L);
+ private static final TestIdentity megaCorp = new TestIdentity(new CordaX500Name("MegaCorp", "London", "GB"));
private final byte[] defaultRef = {123};
- private MockServices ledgerServices;
- @Before
- public void setUp() {
- // When creating the MockServices, you need to specify the packages that will contain the contracts you will use in this test
- // For this test its' Cash and CommercialPaper, bot in the 'net.corda.finance.contracts' package
- // In case you don't specify the 'cordappPackages' argument, the MockServices will be initialised with the Contracts found in the package of the current test
- ledgerServices = new MockServices(singletonList("net.corda.finance.contracts"), MEGA_CORP);
- }
+ // DOCSTART 11
+ private final MockServices ledgerServices = new MockServices(
+ // A list of packages to scan for cordapps
+ singletonList("net.corda.finance.contracts"),
+ // The identity represented by this set of mock services. Defaults to a test identity.
+ // You can also use the alternative parameter initialIdentityName which accepts a
+ // [CordaX500Name]
+ megaCorp,
+ // An implementation of [IdentityService], which contains a list of all identities known
+ // to the node. Use [makeTestIdentityService] which returns an implementation of
+ // [InMemoryIdentityService] with the given identities
+ makeTestIdentityService(megaCorp.getIdentity())
+ );
+ // DOCEND 11
+
+ @SuppressWarnings("unused")
+ // DOCSTART 12
+ private final MockServices simpleLedgerServices = new MockServices(
+ // This is the identity of the node
+ megaCorp,
+ // Other identities the test node knows about
+ bigCorp,
+ alice
+ );
+ // DOCEND 12
// DOCSTART 1
private ICommercialPaperState getPaper() {
return new JavaCommercialPaper.State(
- MEGA_CORP.ref(defaultRef),
- MEGA_CORP.getParty(),
- issuedBy(DOLLARS(1000), MEGA_CORP.ref(defaultRef)),
+ megaCorp.ref(defaultRef),
+ megaCorp.getParty(),
+ issuedBy(DOLLARS(1000), megaCorp.ref(defaultRef)),
TEST_TX_TIME.plus(7, ChronoUnit.DAYS)
);
}
@@ -75,7 +93,7 @@ public class CommercialPaperTest {
ledger(ledgerServices, l -> {
l.transaction(tx -> {
tx.input(JCP_PROGRAM_ID, inState);
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
tx.attachments(JCP_PROGRAM_ID);
return tx.verifies();
});
@@ -91,7 +109,7 @@ public class CommercialPaperTest {
ledger(ledgerServices, l -> {
l.transaction(tx -> {
tx.input(JCP_PROGRAM_ID, inState);
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
tx.attachments(JCP_PROGRAM_ID);
return tx.failsWith("the state is propagated");
});
@@ -102,15 +120,15 @@ public class CommercialPaperTest {
// DOCSTART 5
@Test
- public void simpleCPMoveSuccess() {
+ public void simpleCPMoveSuccessAndFailure() {
ICommercialPaperState inState = getPaper();
ledger(ledgerServices, l -> {
l.transaction(tx -> {
tx.input(JCP_PROGRAM_ID, inState);
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
tx.attachments(JCP_PROGRAM_ID);
tx.failsWith("the state is propagated");
- tx.output(JCP_PROGRAM_ID, "alice's paper", inState.withOwner(ALICE.getParty()));
+ tx.output(JCP_PROGRAM_ID, "alice's paper", inState.withOwner(alice.getParty()));
return tx.verifies();
});
return Unit.INSTANCE;
@@ -118,6 +136,24 @@ public class CommercialPaperTest {
}
// DOCEND 5
+ // DOCSTART 13
+ @Test
+ public void simpleCPMoveSuccess() {
+ ICommercialPaperState inState = getPaper();
+ ledger(ledgerServices, l -> {
+ l.transaction(tx -> {
+ tx.input(JCP_PROGRAM_ID, inState);
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.attachments(JCP_PROGRAM_ID);
+ tx.timeWindow(TEST_TX_TIME);
+ tx.output(JCP_PROGRAM_ID, "alice's paper", inState.withOwner(alice.getParty()));
+ return tx.verifies();
+ });
+ return Unit.INSTANCE;
+ });
+ }
+ // DOCEND 13
+
// DOCSTART 6
@Test
public void simpleIssuanceWithTweak() {
@@ -126,11 +162,11 @@ public class CommercialPaperTest {
tx.output(JCP_PROGRAM_ID, "paper", getPaper()); // Some CP is issued onto the ledger by MegaCorp.
tx.attachments(JCP_PROGRAM_ID);
tx.tweak(tw -> {
- tw.command(BIG_CORP_PUBKEY, new JavaCommercialPaper.Commands.Issue());
+ tw.command(bigCorp.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
tw.timeWindow(TEST_TX_TIME);
return tw.failsWith("output states are issued by a command signer");
});
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
tx.timeWindow(TEST_TX_TIME);
return tx.verifies();
});
@@ -146,11 +182,11 @@ public class CommercialPaperTest {
tx.output(JCP_PROGRAM_ID, "paper", getPaper()); // Some CP is issued onto the ledger by MegaCorp.
tx.attachments(JCP_PROGRAM_ID);
tx.tweak(tw -> {
- tw.command(BIG_CORP_PUBKEY, new JavaCommercialPaper.Commands.Issue());
+ tw.command(bigCorp.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
tw.timeWindow(TEST_TX_TIME);
return tw.failsWith("output states are issued by a command signer");
});
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
tx.timeWindow(TEST_TX_TIME);
return tx.verifies();
});
@@ -160,11 +196,11 @@ public class CommercialPaperTest {
// DOCSTART 8
@Test
public void chainCommercialPaper() {
- PartyAndReference issuer = MEGA_CORP.ref(defaultRef);
+ PartyAndReference issuer = megaCorp.ref(defaultRef);
ledger(ledgerServices, l -> {
l.unverifiedTransaction(tx -> {
tx.output(Cash.PROGRAM_ID, "alice's $900",
- new Cash.State(issuedBy(DOLLARS(900), issuer), ALICE.getParty()));
+ new Cash.State(issuedBy(DOLLARS(900), issuer), alice.getParty()));
tx.attachments(Cash.PROGRAM_ID);
return Unit.INSTANCE;
});
@@ -172,7 +208,7 @@ public class CommercialPaperTest {
// Some CP is issued onto the ledger by MegaCorp.
l.transaction("Issuance", tx -> {
tx.output(JCP_PROGRAM_ID, "paper", getPaper());
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
tx.attachments(JCP_PROGRAM_ID);
tx.timeWindow(TEST_TX_TIME);
return tx.verifies();
@@ -181,11 +217,11 @@ public class CommercialPaperTest {
l.transaction("Trade", tx -> {
tx.input("paper");
tx.input("alice's $900");
- tx.output(Cash.PROGRAM_ID, "borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), MEGA_CORP.getParty()));
+ tx.output(Cash.PROGRAM_ID, "borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), megaCorp.getParty()));
JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
- tx.output(JCP_PROGRAM_ID, "alice's paper", inputPaper.withOwner(ALICE.getParty()));
- tx.command(ALICE.getPublicKey(), new Cash.Commands.Move());
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.output(JCP_PROGRAM_ID, "alice's paper", inputPaper.withOwner(alice.getParty()));
+ tx.command(alice.getPublicKey(), new Cash.Commands.Move());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
return Unit.INSTANCE;
@@ -196,11 +232,11 @@ public class CommercialPaperTest {
// DOCSTART 9
@Test
public void chainCommercialPaperDoubleSpend() {
- PartyAndReference issuer = MEGA_CORP.ref(defaultRef);
+ PartyAndReference issuer = megaCorp.ref(defaultRef);
ledger(ledgerServices, l -> {
l.unverifiedTransaction(tx -> {
tx.output(Cash.PROGRAM_ID, "alice's $900",
- new Cash.State(issuedBy(DOLLARS(900), issuer), ALICE.getParty()));
+ new Cash.State(issuedBy(DOLLARS(900), issuer), alice.getParty()));
tx.attachments(Cash.PROGRAM_ID);
return Unit.INSTANCE;
});
@@ -208,7 +244,7 @@ public class CommercialPaperTest {
// Some CP is issued onto the ledger by MegaCorp.
l.transaction("Issuance", tx -> {
tx.output(Cash.PROGRAM_ID, "paper", getPaper());
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
tx.attachments(JCP_PROGRAM_ID);
tx.timeWindow(TEST_TX_TIME);
return tx.verifies();
@@ -217,11 +253,11 @@ public class CommercialPaperTest {
l.transaction("Trade", tx -> {
tx.input("paper");
tx.input("alice's $900");
- tx.output(Cash.PROGRAM_ID, "borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), MEGA_CORP.getParty()));
+ tx.output(Cash.PROGRAM_ID, "borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), megaCorp.getParty()));
JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
- tx.output(JCP_PROGRAM_ID, "alice's paper", inputPaper.withOwner(ALICE.getParty()));
- tx.command(ALICE.getPublicKey(), new Cash.Commands.Move());
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.output(JCP_PROGRAM_ID, "alice's paper", inputPaper.withOwner(alice.getParty()));
+ tx.command(alice.getPublicKey(), new Cash.Commands.Move());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
@@ -229,8 +265,8 @@ public class CommercialPaperTest {
tx.input("paper");
JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
// We moved a paper to other pubkey.
- tx.output(JCP_PROGRAM_ID, "bob's paper", inputPaper.withOwner(BOB.getParty()));
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.output(JCP_PROGRAM_ID, "bob's paper", inputPaper.withOwner(bob.getParty()));
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
l.fails();
@@ -242,11 +278,11 @@ public class CommercialPaperTest {
// DOCSTART 10
@Test
public void chainCommercialPaperTweak() {
- PartyAndReference issuer = MEGA_CORP.ref(defaultRef);
+ PartyAndReference issuer = megaCorp.ref(defaultRef);
ledger(ledgerServices, l -> {
l.unverifiedTransaction(tx -> {
tx.output(Cash.PROGRAM_ID, "alice's $900",
- new Cash.State(issuedBy(DOLLARS(900), issuer), ALICE.getParty()));
+ new Cash.State(issuedBy(DOLLARS(900), issuer), alice.getParty()));
tx.attachments(Cash.PROGRAM_ID);
return Unit.INSTANCE;
});
@@ -254,7 +290,7 @@ public class CommercialPaperTest {
// Some CP is issued onto the ledger by MegaCorp.
l.transaction("Issuance", tx -> {
tx.output(Cash.PROGRAM_ID, "paper", getPaper());
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Issue());
tx.attachments(JCP_PROGRAM_ID);
tx.timeWindow(TEST_TX_TIME);
return tx.verifies();
@@ -263,11 +299,11 @@ public class CommercialPaperTest {
l.transaction("Trade", tx -> {
tx.input("paper");
tx.input("alice's $900");
- tx.output(Cash.PROGRAM_ID, "borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), MEGA_CORP.getParty()));
+ tx.output(Cash.PROGRAM_ID, "borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), megaCorp.getParty()));
JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
- tx.output(JCP_PROGRAM_ID, "alice's paper", inputPaper.withOwner(ALICE.getParty()));
- tx.command(ALICE.getPublicKey(), new Cash.Commands.Move());
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.output(JCP_PROGRAM_ID, "alice's paper", inputPaper.withOwner(alice.getParty()));
+ tx.command(alice.getPublicKey(), new Cash.Commands.Move());
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
@@ -276,8 +312,8 @@ public class CommercialPaperTest {
tx.input("paper");
JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
// We moved a paper to another pubkey.
- tx.output(JCP_PROGRAM_ID, "bob's paper", inputPaper.withOwner(BOB.getParty()));
- tx.command(MEGA_CORP.getPublicKey(), new JavaCommercialPaper.Commands.Move());
+ tx.output(JCP_PROGRAM_ID, "bob's paper", inputPaper.withOwner(bob.getParty()));
+ tx.command(megaCorp.getPublicKey(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
lw.fails();
diff --git a/docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt b/docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
index a8cd842ac2..e6539a910b 100644
--- a/docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
+++ b/docs/source/example-code/src/test/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt
@@ -1,11 +1,7 @@
package net.corda.docs.tutorial.testdsl
-import com.nhaarman.mockito_kotlin.doReturn
-import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.TransactionVerificationException
-import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.CordaX500Name
-import net.corda.core.node.services.IdentityService
import net.corda.core.utilities.days
import net.corda.finance.DOLLARS
import net.corda.finance.`issued by`
@@ -15,9 +11,9 @@ import net.corda.finance.contracts.ICommercialPaperState
import net.corda.finance.contracts.asset.CASH
import net.corda.finance.contracts.asset.Cash
import net.corda.testing.core.*
-import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockServices
import net.corda.testing.node.ledger
+import net.corda.testing.node.makeTestIdentityService
import net.corda.testing.node.transaction
import org.junit.Rule
import org.junit.Test
@@ -25,32 +21,46 @@ import org.junit.Test
class CommercialPaperTest {
private companion object {
val alice = TestIdentity(ALICE_NAME, 70)
- val BIG_CORP_PUBKEY = generateKeyPair().public
- val BOB = TestIdentity(BOB_NAME, 80).party
- val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
+ val bob = TestIdentity(BOB_NAME, 80)
+ val bigCorp = TestIdentity((CordaX500Name("BigCorp", "New York", "GB")))
+ val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20)
val megaCorp = TestIdentity(CordaX500Name("MegaCorp", "London", "GB"))
- val ALICE get() = alice.party
- val ALICE_PUBKEY get() = alice.publicKey
- val MEGA_CORP get() = megaCorp.party
- val MEGA_CORP_PUBKEY get() = megaCorp.publicKey
}
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
- // When creating the MockServices, you need to specify the packages that will contain the contracts you will use in this test
- // In case you don't specify the 'cordappPackages' argument, the MockServices will be initialised with the Contracts found in the package of the current test
- private val ledgerServices = MockServices(listOf("net.corda.finance.contracts"), MEGA_CORP.name, rigorousMock().also {
- doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY)
- doReturn(null).whenever(it).partyFromKey(BIG_CORP_PUBKEY)
- doReturn(null).whenever(it).partyFromKey(ALICE_PUBKEY)
- })
+ // DOCSTART 11
+ private val ledgerServices = MockServices(
+ // A list of packages to scan for cordapps
+ cordappPackages = listOf("net.corda.finance.contracts"),
+ // The identity represented by this set of mock services. Defaults to a test identity.
+ // You can also use the alternative parameter initialIdentityName which accepts a
+ // [CordaX500Name]
+ initialIdentity = megaCorp,
+ // An implementation of IdentityService, which contains a list of all identities known
+ // to the node. Use [makeTestIdentityService] which returns an implementation of
+ // [InMemoryIdentityService] with the given identities
+ identityService = makeTestIdentityService(megaCorp.identity)
+ )
+ // DOCEND 11
+
+ @Suppress("unused")
+ // DOCSTART 12
+ private val simpleLedgerServices = MockServices(
+ // This is the identity of the node
+ megaCorp,
+ // Other identities the test node knows about
+ bigCorp,
+ alice
+ )
+ // DOCEND 12
// DOCSTART 1
fun getPaper(): ICommercialPaperState = CommercialPaper.State(
- issuance = MEGA_CORP.ref(123),
- owner = MEGA_CORP,
- faceValue = 1000.DOLLARS `issued by` MEGA_CORP.ref(123),
+ issuance = megaCorp.party.ref(123),
+ owner = megaCorp.party,
+ faceValue = 1000.DOLLARS `issued by` megaCorp.party.ref(123),
maturityDate = TEST_TX_TIME + 7.days
)
// DOCEND 1
@@ -60,7 +70,7 @@ class CommercialPaperTest {
@Test(expected = IllegalStateException::class)
fun simpleCP() {
val inState = getPaper()
- ledgerServices.ledger(DUMMY_NOTARY) {
+ ledgerServices.ledger(dummyNotary.party) {
transaction {
attachments(CP_PROGRAM_ID)
input(CP_PROGRAM_ID, inState)
@@ -75,10 +85,10 @@ class CommercialPaperTest {
@Test(expected = TransactionVerificationException.ContractRejection::class)
fun simpleCPMove() {
val inState = getPaper()
- ledgerServices.ledger(DUMMY_NOTARY) {
+ ledgerServices.ledger(dummyNotary.party) {
transaction {
input(CP_PROGRAM_ID, inState)
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
attachments(CP_PROGRAM_ID)
verifies()
}
@@ -90,10 +100,10 @@ class CommercialPaperTest {
@Test
fun simpleCPMoveFails() {
val inState = getPaper()
- ledgerServices.ledger(DUMMY_NOTARY) {
+ ledgerServices.ledger(dummyNotary.party) {
transaction {
input(CP_PROGRAM_ID, inState)
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
attachments(CP_PROGRAM_ID)
`fails with`("the state is propagated")
}
@@ -103,35 +113,52 @@ class CommercialPaperTest {
// DOCSTART 5
@Test
- fun simpleCPMoveSuccess() {
+ fun simpleCPMoveFailureAndSuccess() {
val inState = getPaper()
- ledgerServices.ledger(DUMMY_NOTARY) {
+ ledgerServices.ledger(dummyNotary.party) {
transaction {
input(CP_PROGRAM_ID, inState)
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
attachments(CP_PROGRAM_ID)
`fails with`("the state is propagated")
- output(CP_PROGRAM_ID, "alice's paper", inState.withOwner(ALICE))
+ output(CP_PROGRAM_ID, "alice's paper", inState.withOwner(alice.party))
verifies()
}
}
}
// DOCEND 5
+ // DOCSTART 13
+ @Test
+ fun simpleCPMoveSuccess() {
+ val inState = getPaper()
+ ledgerServices.ledger(dummyNotary.party) {
+ transaction {
+ input(CP_PROGRAM_ID, inState)
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
+ attachments(CP_PROGRAM_ID)
+ timeWindow(TEST_TX_TIME)
+ output(CP_PROGRAM_ID, "alice's paper", inState.withOwner(alice.party))
+ verifies()
+ }
+ }
+ }
+ // DOCEND 13
+
// DOCSTART 6
@Test
fun `simple issuance with tweak`() {
- ledgerServices.ledger(DUMMY_NOTARY) {
+ ledgerServices.ledger(dummyNotary.party) {
transaction {
output(CP_PROGRAM_ID, "paper", getPaper()) // Some CP is issued onto the ledger by MegaCorp.
attachments(CP_PROGRAM_ID)
tweak {
// The wrong pubkey.
- command(BIG_CORP_PUBKEY, CommercialPaper.Commands.Issue())
+ command(bigCorp.publicKey, CommercialPaper.Commands.Issue())
timeWindow(TEST_TX_TIME)
`fails with`("output states are issued by a command signer")
}
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Issue())
timeWindow(TEST_TX_TIME)
verifies()
}
@@ -142,16 +169,16 @@ class CommercialPaperTest {
// DOCSTART 7
@Test
fun `simple issuance with tweak and top level transaction`() {
- ledgerServices.transaction(DUMMY_NOTARY) {
+ ledgerServices.transaction(dummyNotary.party) {
output(CP_PROGRAM_ID, "paper", getPaper()) // Some CP is issued onto the ledger by MegaCorp.
attachments(CP_PROGRAM_ID)
tweak {
// The wrong pubkey.
- command(BIG_CORP_PUBKEY, CommercialPaper.Commands.Issue())
+ command(bigCorp.publicKey, CommercialPaper.Commands.Issue())
timeWindow(TEST_TX_TIME)
`fails with`("output states are issued by a command signer")
}
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Issue())
timeWindow(TEST_TX_TIME)
verifies()
}
@@ -161,17 +188,17 @@ class CommercialPaperTest {
// DOCSTART 8
@Test
fun `chain commercial paper`() {
- val issuer = MEGA_CORP.ref(123)
- ledgerServices.ledger(DUMMY_NOTARY) {
+ val issuer = megaCorp.party.ref(123)
+ ledgerServices.ledger(dummyNotary.party) {
unverifiedTransaction {
attachments(Cash.PROGRAM_ID)
- output(Cash.PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH issuedBy issuer ownedBy ALICE)
+ output(Cash.PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH issuedBy issuer ownedBy alice.party)
}
// Some CP is issued onto the ledger by MegaCorp.
transaction("Issuance") {
output(CP_PROGRAM_ID, "paper", getPaper())
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Issue())
attachments(CP_PROGRAM_ID)
timeWindow(TEST_TX_TIME)
verifies()
@@ -181,10 +208,10 @@ class CommercialPaperTest {
transaction("Trade") {
input("paper")
input("alice's $900")
- output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP)
- output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(ALICE))
- command(ALICE_PUBKEY, Cash.Commands.Move())
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy megaCorp.party)
+ output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(alice.party))
+ command(alice.publicKey, Cash.Commands.Move())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
verifies()
}
}
@@ -194,17 +221,17 @@ class CommercialPaperTest {
// DOCSTART 9
@Test
fun `chain commercial paper double spend`() {
- val issuer = MEGA_CORP.ref(123)
- ledgerServices.ledger(DUMMY_NOTARY) {
+ val issuer = megaCorp.party.ref(123)
+ ledgerServices.ledger(dummyNotary.party) {
unverifiedTransaction {
attachments(Cash.PROGRAM_ID)
- output(Cash.PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH issuedBy issuer ownedBy ALICE)
+ output(Cash.PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH issuedBy issuer ownedBy alice.party)
}
// Some CP is issued onto the ledger by MegaCorp.
transaction("Issuance") {
output(CP_PROGRAM_ID, "paper", getPaper())
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Issue())
attachments(CP_PROGRAM_ID)
timeWindow(TEST_TX_TIME)
verifies()
@@ -213,18 +240,18 @@ class CommercialPaperTest {
transaction("Trade") {
input("paper")
input("alice's $900")
- output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP)
- output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(ALICE))
- command(ALICE_PUBKEY, Cash.Commands.Move())
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy megaCorp.party)
+ output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(alice.party))
+ command(alice.publicKey, Cash.Commands.Move())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
verifies()
}
transaction {
input("paper")
// We moved a paper to another pubkey.
- output(CP_PROGRAM_ID, "bob's paper", "paper".output().withOwner(BOB))
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ output(CP_PROGRAM_ID, "bob's paper", "paper".output().withOwner(bob.party))
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
verifies()
}
@@ -236,17 +263,17 @@ class CommercialPaperTest {
// DOCSTART 10
@Test
fun `chain commercial tweak`() {
- val issuer = MEGA_CORP.ref(123)
- ledgerServices.ledger(DUMMY_NOTARY) {
+ val issuer = megaCorp.party.ref(123)
+ ledgerServices.ledger(dummyNotary.party) {
unverifiedTransaction {
attachments(Cash.PROGRAM_ID)
- output(Cash.PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH issuedBy issuer ownedBy ALICE)
+ output(Cash.PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH issuedBy issuer ownedBy alice.party)
}
// Some CP is issued onto the ledger by MegaCorp.
transaction("Issuance") {
output(CP_PROGRAM_ID, "paper", getPaper())
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Issue())
attachments(CP_PROGRAM_ID)
timeWindow(TEST_TX_TIME)
verifies()
@@ -255,10 +282,10 @@ class CommercialPaperTest {
transaction("Trade") {
input("paper")
input("alice's $900")
- output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP)
- output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(ALICE))
- command(ALICE_PUBKEY, Cash.Commands.Move())
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy megaCorp.party)
+ output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(alice.party))
+ command(alice.publicKey, Cash.Commands.Move())
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
verifies()
}
@@ -266,8 +293,8 @@ class CommercialPaperTest {
transaction {
input("paper")
// We moved a paper to another pubkey.
- output(CP_PROGRAM_ID, "bob's paper", "paper".output().withOwner(BOB))
- command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move())
+ output(CP_PROGRAM_ID, "bob's paper", "paper".output().withOwner(bob.party))
+ command(megaCorp.publicKey, CommercialPaper.Commands.Move())
verifies()
}
fails()