CORE-14586: Utxo Example Contract Tests (#51)
* CORE-14586: Utxo Example Contract Tests * CORE-14586: Use beta builds rather than alpha builds * CORE-14586: Add signing constraint
This commit is contained in:
parent
7b3144001d
commit
20e3dd38b3
@ -55,6 +55,7 @@ dependencies {
|
|||||||
testImplementation "org.mockito:mockito-core:$mockitoVersion"
|
testImplementation "org.mockito:mockito-core:$mockitoVersion"
|
||||||
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
||||||
testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion"
|
testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion"
|
||||||
|
testImplementation "com.r3.corda.ledger.utxo:contract-testing:$contractTestingVersion"
|
||||||
}
|
}
|
||||||
|
|
||||||
// The CordApp section.
|
// The CordApp section.
|
||||||
|
@ -13,37 +13,54 @@ public class ChatContract implements Contract {
|
|||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(ChatContract.class);
|
private final static Logger log = LoggerFactory.getLogger(ChatContract.class);
|
||||||
|
|
||||||
|
// Use constants to hold the error messages
|
||||||
|
// This allows the tests to use them, meaning if they are updated you won't need to fix tests just because the wording was updated
|
||||||
|
static final String REQUIRE_SINGLE_COMMAND = "Require a single command.";
|
||||||
|
static final String UNKNOWN_COMMAND = "Unsupported command";
|
||||||
|
static final String OUTPUT_STATE_SHOULD_ONLY_HAVE_TWO_PARTICIPANTS = "The output state should have two and only two participants.";
|
||||||
|
static final String TRANSACTION_SHOULD_BE_SIGNED_BY_ALL_PARTICIPANTS = "The transaction should have been signed by both participants.";
|
||||||
|
|
||||||
|
static final String CREATE_COMMAND_SHOULD_HAVE_NO_INPUT_STATES = "When command is Create there should be no input states.";
|
||||||
|
static final String CREATE_COMMAND_SHOULD_HAVE_ONLY_ONE_OUTPUT_STATE = "When command is Create there should be one and only one output state.";
|
||||||
|
|
||||||
|
static final String UPDATE_COMMAND_SHOULD_HAVE_ONLY_ONE_INPUT_STATE = "When command is Update there should be one and only one input state.";
|
||||||
|
static final String UPDATE_COMMAND_SHOULD_HAVE_ONLY_ONE_OUTPUT_STATE = "When command is Update there should be one and only one output state.";
|
||||||
|
static final String UPDATE_COMMAND_ID_SHOULD_NOT_CHANGE = "When command is Update id must not change.";
|
||||||
|
static final String UPDATE_COMMAND_CHATNAME_SHOULD_NOT_CHANGE = "When command is Update chatName must not change.";
|
||||||
|
static final String UPDATE_COMMAND_PARTICIPANTS_SHOULD_NOT_CHANGE = "When command is Update participants must not change.";
|
||||||
|
|
||||||
public static class Create implements Command { }
|
public static class Create implements Command { }
|
||||||
public static class Update implements Command { }
|
public static class Update implements Command { }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void verify(UtxoLedgerTransaction transaction) {
|
public void verify(UtxoLedgerTransaction transaction) {
|
||||||
|
|
||||||
requireThat( transaction.getCommands().size() == 1, "Require a single command.");
|
requireThat( transaction.getCommands().size() == 1, REQUIRE_SINGLE_COMMAND);
|
||||||
Command command = transaction.getCommands().get(0);
|
Command command = transaction.getCommands().get(0);
|
||||||
|
|
||||||
ChatState output = transaction.getOutputStates(ChatState.class).get(0);
|
ChatState output = transaction.getOutputStates(ChatState.class).get(0);
|
||||||
|
|
||||||
requireThat(output.getParticipants().size() == 2, "The output state should have two and only two participants.");
|
requireThat(output.getParticipants().size() == 2, OUTPUT_STATE_SHOULD_ONLY_HAVE_TWO_PARTICIPANTS);
|
||||||
|
requireThat(transaction.getSignatories().containsAll(output.getParticipants()), TRANSACTION_SHOULD_BE_SIGNED_BY_ALL_PARTICIPANTS);
|
||||||
|
|
||||||
if(command.getClass() == Create.class) {
|
if(command.getClass() == Create.class) {
|
||||||
requireThat(transaction.getInputContractStates().isEmpty(), "When command is Create there should be no input states.");
|
requireThat(transaction.getInputContractStates().isEmpty(), CREATE_COMMAND_SHOULD_HAVE_NO_INPUT_STATES);
|
||||||
requireThat(transaction.getOutputContractStates().size() == 1, "When command is Create there should be one and only one output state.");
|
requireThat(transaction.getOutputContractStates().size() == 1, CREATE_COMMAND_SHOULD_HAVE_ONLY_ONE_OUTPUT_STATE);
|
||||||
}
|
}
|
||||||
else if(command.getClass() == Update.class) {
|
else if(command.getClass() == Update.class) {
|
||||||
requireThat(transaction.getInputContractStates().size() == 1, "When command is Update there should be one and only one input state.");
|
requireThat(transaction.getInputContractStates().size() == 1, UPDATE_COMMAND_SHOULD_HAVE_ONLY_ONE_INPUT_STATE);
|
||||||
requireThat(transaction.getOutputContractStates().size() == 1, "When command is Update there should be one and only one output state.");
|
requireThat(transaction.getOutputContractStates().size() == 1, UPDATE_COMMAND_SHOULD_HAVE_ONLY_ONE_OUTPUT_STATE);
|
||||||
|
|
||||||
ChatState input = transaction.getInputStates(ChatState.class).get(0);
|
ChatState input = transaction.getInputStates(ChatState.class).get(0);
|
||||||
requireThat(input.getId().equals(output.getId()), "When command is Update id must not change.");
|
requireThat(input.getId().equals(output.getId()), UPDATE_COMMAND_ID_SHOULD_NOT_CHANGE);
|
||||||
requireThat(input.getChatName().equals(output.getChatName()), "When command is Update chatName must not change.");
|
requireThat(input.getChatName().equals(output.getChatName()), UPDATE_COMMAND_CHATNAME_SHOULD_NOT_CHANGE);
|
||||||
requireThat(
|
requireThat(
|
||||||
input.getParticipants().containsAll(output.getParticipants()) &&
|
input.getParticipants().containsAll(output.getParticipants()) &&
|
||||||
output.getParticipants().containsAll(input.getParticipants()),
|
output.getParticipants().containsAll(input.getParticipants()),
|
||||||
"When command is Update participants must not change.");
|
UPDATE_COMMAND_PARTICIPANTS_SHOULD_NOT_CHANGE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new CordaRuntimeException("Unsupported command");
|
throw new CordaRuntimeException(UNKNOWN_COMMAND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,158 @@
|
|||||||
|
package com.r3.developers.csdetemplate.utxoexample.contracts;
|
||||||
|
|
||||||
|
import com.r3.corda.ledger.utxo.testing.ContractTest;
|
||||||
|
import com.r3.developers.csdetemplate.utxoexample.states.ChatState;
|
||||||
|
import net.corda.v5.ledger.utxo.Command;
|
||||||
|
import net.corda.v5.ledger.utxo.StateAndRef;
|
||||||
|
import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.r3.developers.csdetemplate.utxoexample.contracts.ChatContract.*;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
|
||||||
|
public class ChatContractCreateCommandTest extends ContractTest {
|
||||||
|
|
||||||
|
protected ChatState outputChatState = new ChatState(
|
||||||
|
UUID.randomUUID(),
|
||||||
|
"aliceChatName",
|
||||||
|
aliceName,
|
||||||
|
"aliceChatMessage",
|
||||||
|
List.of(aliceKey, bobKey)
|
||||||
|
);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void happyPath() {
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.addSignatories(outputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertVerifies(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void missingCommand() {
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + REQUIRE_SINGLE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotAcceptUnknownCommand() {
|
||||||
|
class MyDummyCommand implements Command {
|
||||||
|
}
|
||||||
|
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addCommand(new MyDummyCommand())
|
||||||
|
.addSignatories(outputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
|
||||||
|
assertFailsWith(transaction, UNKNOWN_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void outputStateCannotHaveZeroParticipants() {
|
||||||
|
ChatState state = new ChatState(
|
||||||
|
UUID.randomUUID(),
|
||||||
|
"myChatName",
|
||||||
|
aliceName,
|
||||||
|
"myChatMessage",
|
||||||
|
emptyList()
|
||||||
|
);
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(state)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + OUTPUT_STATE_SHOULD_ONLY_HAVE_TWO_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void outputStateCannotHaveOneParticipant() {
|
||||||
|
ChatState state = new ChatState(
|
||||||
|
UUID.randomUUID(),
|
||||||
|
"myChatName",
|
||||||
|
aliceName,
|
||||||
|
"myChatMessage",
|
||||||
|
List.of(aliceKey)
|
||||||
|
);
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(state)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + OUTPUT_STATE_SHOULD_ONLY_HAVE_TWO_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void outputStateCannotHaveThreeParticipants() {
|
||||||
|
ChatState state = new ChatState(
|
||||||
|
UUID.randomUUID(),
|
||||||
|
"myChatName",
|
||||||
|
aliceName,
|
||||||
|
"myChatMessage",
|
||||||
|
List.of(aliceKey, bobKey, charlieKey)
|
||||||
|
);
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(state)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + OUTPUT_STATE_SHOULD_ONLY_HAVE_TWO_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void outputStateMustBeSigned() {
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + TRANSACTION_SHOULD_BE_SIGNED_BY_ALL_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void outputStateCannotBeSignedByOnlyOneParticipant() {
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.addSignatories(outputChatState.participants.get(0))
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + TRANSACTION_SHOULD_BE_SIGNED_BY_ALL_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotIncludeInputState() {
|
||||||
|
happyPath(); // generate an existing state to search for
|
||||||
|
StateAndRef<ChatState> existingState = getLedgerService().findUnconsumedStatesByType(ChatState.class).get(0); // doesn't matter which as this will fail validation
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.addSignatories(outputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + CREATE_COMMAND_SHOULD_HAVE_NO_INPUT_STATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotHaveTwoOutputStates() {
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.addSignatories(outputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + CREATE_COMMAND_SHOULD_HAVE_ONLY_ONE_OUTPUT_STATE);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,174 @@
|
|||||||
|
package com.r3.developers.csdetemplate.utxoexample.contracts;
|
||||||
|
|
||||||
|
import com.r3.corda.ledger.utxo.testing.ContractTest;
|
||||||
|
import com.r3.developers.csdetemplate.utxoexample.states.ChatState;
|
||||||
|
import net.corda.v5.ledger.utxo.StateAndRef;
|
||||||
|
import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.r3.developers.csdetemplate.utxoexample.contracts.ChatContract.*;
|
||||||
|
|
||||||
|
public class ChatContractUpdateCommandTest extends ContractTest {
|
||||||
|
|
||||||
|
private StateAndRef<ChatState> createInitialChatState() {
|
||||||
|
ChatState outputChatState = new ChatContractCreateCommandTest().outputChatState;
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(outputChatState)
|
||||||
|
.addCommand(new ChatContract.Create())
|
||||||
|
.addSignatories(outputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
transaction.toLedgerTransaction();
|
||||||
|
return (StateAndRef<ChatState>) transaction.getOutputStateAndRefs().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void happyPath() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState updatedOutputChatState = existingState.getState().getContractState().updateMessage(bobName, "bobResponse");
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertVerifies(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotHaveNoInputState() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState updatedOutputChatState = existingState.getState().getContractState().updateMessage(bobName, "bobResponse");
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + UPDATE_COMMAND_SHOULD_HAVE_ONLY_ONE_INPUT_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotHaveTwoInputStates() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState updatedOutputChatState = existingState.getState().getContractState().updateMessage(bobName, "bobResponse");
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + UPDATE_COMMAND_SHOULD_HAVE_ONLY_ONE_INPUT_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotHaveTwoOutputStates() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState updatedOutputChatState = existingState.getState().getContractState().updateMessage(bobName, "bobResponse");
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + UPDATE_COMMAND_SHOULD_HAVE_ONLY_ONE_OUTPUT_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void idShouldNotChange() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState esDetails = existingState.getState().getContractState();
|
||||||
|
ChatState updatedOutputChatState = new ChatState(
|
||||||
|
UUID.randomUUID(),
|
||||||
|
esDetails.getChatName(),
|
||||||
|
bobName,
|
||||||
|
"bobResponse",
|
||||||
|
esDetails.getParticipants()
|
||||||
|
);
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + UPDATE_COMMAND_ID_SHOULD_NOT_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void chatNameShouldNotChange() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState esDetails = existingState.getState().getContractState();
|
||||||
|
ChatState updatedOutputChatState = new ChatState(
|
||||||
|
esDetails.getId(),
|
||||||
|
"newName",
|
||||||
|
bobName,
|
||||||
|
"bobResponse",
|
||||||
|
esDetails.getParticipants()
|
||||||
|
);
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + UPDATE_COMMAND_CHATNAME_SHOULD_NOT_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void participantsShouldNotChange() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState esDetails = existingState.getState().getContractState();
|
||||||
|
ChatState updatedOutputChatState = new ChatState(
|
||||||
|
esDetails.getId(),
|
||||||
|
esDetails.getChatName(),
|
||||||
|
bobName,
|
||||||
|
"bobResponse",
|
||||||
|
List.of(bobKey, charlieKey)
|
||||||
|
);
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants)
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + UPDATE_COMMAND_PARTICIPANTS_SHOULD_NOT_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void outputStateMustBeSigned() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState updatedOutputChatState = existingState.getState().getContractState().updateMessage(bobName, "bobResponse");
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + TRANSACTION_SHOULD_BE_SIGNED_BY_ALL_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void outputStateCannotBeSignedByOnlyOneParticipant() {
|
||||||
|
StateAndRef<ChatState> existingState = createInitialChatState();
|
||||||
|
ChatState updatedOutputChatState = existingState.getState().getContractState().updateMessage(bobName, "bobResponse");
|
||||||
|
UtxoSignedTransaction transaction = getLedgerService()
|
||||||
|
.createTransactionBuilder()
|
||||||
|
.addInputState(existingState.getRef())
|
||||||
|
.addOutputState(updatedOutputChatState)
|
||||||
|
.addCommand(new ChatContract.Update())
|
||||||
|
.addSignatories(updatedOutputChatState.participants.get(0))
|
||||||
|
.toSignedTransaction();
|
||||||
|
assertFailsWith(transaction, "Failed requirement: " + TRANSACTION_SHOULD_BE_SIGNED_BY_ALL_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ junitVersion = 5.8.2
|
|||||||
mockitoKotlinVersion=4.0.0
|
mockitoKotlinVersion=4.0.0
|
||||||
mockitoVersion=4.6.1
|
mockitoVersion=4.6.1
|
||||||
hamcrestVersion=2.2
|
hamcrestVersion=2.2
|
||||||
|
contractTestingVersion=0.9.0-beta-+
|
||||||
|
|
||||||
# Specify the maximum amount of time allowed for the CPI upload
|
# Specify the maximum amount of time allowed for the CPI upload
|
||||||
# As your CorDapp grows you might need to increase this
|
# As your CorDapp grows you might need to increase this
|
||||||
|
Loading…
Reference in New Issue
Block a user