Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Commit

Permalink
Clique acceptance tests (#290)
Browse files Browse the repository at this point in the history
  • Loading branch information
jframe authored Nov 29, 2018
1 parent 24b8d73 commit ab744a9
Show file tree
Hide file tree
Showing 59 changed files with 1,740 additions and 114 deletions.
2 changes: 2 additions & 0 deletions acceptance-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependencies {
testImplementation project(':ethereum:blockcreation')
testImplementation project(':ethereum:jsonrpc')
testImplementation project(':pantheon')
testImplementation project(':config')
testImplementation project(':consensus:clique')
testImplementation project(':util')
testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.tests.acceptance.clique;

import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;

import java.io.IOException;

import org.junit.Test;

public class CliqueDiscardRpcAcceptanceTest extends AcceptanceTestBase {

@Test
public void shouldDiscardVotes() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final PantheonNode minerNode1 =
pantheon.createCliqueNodeWithValidators("miner1", initialValidators);
final PantheonNode minerNode2 =
pantheon.createCliqueNodeWithValidators("miner2", initialValidators);
final PantheonNode minerNode3 =
pantheon.createCliqueNodeWithValidators("miner3", initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);

minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode2));
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode2));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode1.execute(cliqueTransactions.createDiscardProposal(minerNode2));
minerNode1.execute(cliqueTransactions.createDiscardProposal(minerNode3));

minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 2));

cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
minerNode1.verify(clique.noProposals());
minerNode2.verify(
clique.proposalsEqual().removeProposal(minerNode2).addProposal(minerNode3).build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.tests.acceptance.clique;

import static tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST;

import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;

import org.junit.Before;
import org.junit.Test;

public class CliqueGetSignersRpcTest extends AcceptanceTestBase {
private PantheonNode minerNode1;
private PantheonNode minerNode2;
private PantheonNode minerNode3;
private PantheonNode[] allNodes;
private PantheonNode[] initialNodes;

@Before
public void setUp() throws Exception {
final String[] validators = {"miner1", "miner2"};
minerNode1 = pantheon.createCliqueNodeWithValidators("miner1", validators);
minerNode2 = pantheon.createCliqueNodeWithValidators("miner2", validators);
minerNode3 = pantheon.createCliqueNodeWithValidators("miner3", validators);
initialNodes = new PantheonNode[] {minerNode1, minerNode2};
allNodes = new PantheonNode[] {minerNode1, minerNode2, minerNode3};
cluster.start(allNodes);
}

@Test
public void shouldBeAbleToGetValidatorsForBlockNumber() {
cluster.verify(clique.validatorsAtBlockEqual("0x0", initialNodes));
cluster.waitUntil(wait.chainHeadIsAt(1));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3));

cluster.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
cluster.verify(clique.validatorsAtBlockEqual("0x2", initialNodes));

minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
cluster.verify(clique.validatorsAtBlockEqual("0x3", allNodes));
cluster.verify(clique.validatorsAtBlockEqual(LATEST, allNodes));
}

@Test
public void shouldBeAbleToGetValidatorsForBlockHash() {
cluster.verify(clique.validatorsAtBlockHashFromBlockNumberEqual(minerNode1, 0, initialNodes));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3));

minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
cluster.verify(clique.validatorsAtBlockHashFromBlockNumberEqual(minerNode1, 1, initialNodes));

minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
cluster.verify(clique.validatorsAtBlockHashFromBlockNumberEqual(minerNode1, 3, allNodes));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.tests.acceptance.clique;

import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;

import java.io.IOException;

import org.junit.Test;

public class CliqueMiningAcceptanceTest extends AcceptanceTestBase {

@Test
public void shouldMineTransactionsOnSingleNode() throws IOException {
final PantheonNode minerNode = pantheon.createCliqueNode("miner1");
cluster.start(minerNode);

final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");

minerNode.execute(transactions.createTransfer(sender, 50));
cluster.verify(sender.balanceEquals(50));

minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 1));
cluster.verify(receiver.balanceEquals(1));

minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 2));
cluster.verify(receiver.balanceEquals(3));
}

@Test
public void shouldMineTransactionsOnMultipleNodes() throws IOException {
final PantheonNode minerNode1 = pantheon.createCliqueNode("miner1");
final PantheonNode minerNode2 = pantheon.createCliqueNode("miner2");
final PantheonNode minerNode3 = pantheon.createCliqueNode("miner3");
cluster.start(minerNode1, minerNode2, minerNode3);

final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");

minerNode1.execute(transactions.createTransfer(sender, 50));
cluster.verify(sender.balanceEquals(50));

minerNode2.execute(transactions.createIncrementalTransfers(sender, receiver, 1));
cluster.verify(receiver.balanceEquals(1));

minerNode3.execute(transactions.createIncrementalTransfers(sender, receiver, 2));
cluster.verify(receiver.balanceEquals(3));
}

@Test
public void shouldStallMiningWhenInsufficientValidators() throws IOException {
final PantheonNode minerNode1 = pantheon.createCliqueNode("miner1");
final PantheonNode minerNode2 = pantheon.createCliqueNode("miner2");
final PantheonNode minerNode3 = pantheon.createCliqueNode("miner3");
cluster.start(minerNode1, minerNode2, minerNode3);

cluster.stopNode(minerNode2);
cluster.stopNode(minerNode3);
minerNode1.verify(net.awaitPeerCount(0));
minerNode1.verify(clique.noNewBlockCreated(minerNode1));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.tests.acceptance.clique;

import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;

import java.io.IOException;

import org.junit.Test;

public class CliqueProposalRpcAcceptanceTest extends AcceptanceTestBase {

@Test
public void shouldReturnProposals() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final PantheonNode minerNode1 =
pantheon.createCliqueNodeWithValidators("miner1", initialValidators);
final PantheonNode minerNode2 =
pantheon.createCliqueNodeWithValidators("miner2", initialValidators);
final PantheonNode minerNode3 =
pantheon.createCliqueNodeWithValidators("miner3", initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);

cluster.verify(clique.noProposals());
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode2));
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode3));

minerNode1.verify(
clique.proposalsEqual().addProposal(minerNode3).removeProposal(minerNode2).build());
minerNode2.verify(clique.proposalsEqual().removeProposal(minerNode3).build());
minerNode3.verify(clique.noProposals());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.tests.acceptance.clique;

import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique.ExpectNonceVote.CLIQUE_NONCE_VOTE;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.waitcondition.WaitCondition;

import java.io.IOException;

import org.junit.Test;

public class CliqueProposeRpcAcceptanceTest extends AcceptanceTestBase {

@Test
public void shouldAddValidators() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final PantheonNode minerNode1 =
pantheon.createCliqueNodeWithValidators("miner1", initialValidators);
final PantheonNode minerNode2 =
pantheon.createCliqueNodeWithValidators("miner2", initialValidators);
final PantheonNode minerNode3 =
pantheon.createCliqueNodeWithValidators("miner3", initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);

cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
final WaitCondition cliqueValidatorsChanged = wait.cliqueValidatorsChanged(minerNode1);
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3));
cluster.waitUntil(cliqueValidatorsChanged);
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
}

@Test
public void shouldRemoveValidators() throws IOException {
final String[] initialValidators = {"miner1", "miner2", "miner3"};
final PantheonNode minerNode1 =
pantheon.createCliqueNodeWithValidators("miner1", initialValidators);
final PantheonNode minerNode2 =
pantheon.createCliqueNodeWithValidators("miner2", initialValidators);
final PantheonNode minerNode3 =
pantheon.createCliqueNodeWithValidators("miner3", initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);

cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
final WaitCondition cliqueValidatorsChanged = wait.cliqueValidatorsChanged(minerNode1);
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode3));
cluster.waitUntil(cliqueValidatorsChanged);
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
}

@Test
public void shouldNotAddValidatorWhenInsufficientVotes() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final PantheonNode minerNode1 =
pantheon.createCliqueNodeWithValidators("miner1", initialValidators);
final PantheonNode minerNode2 =
pantheon.createCliqueNodeWithValidators("miner2", initialValidators);
final PantheonNode minerNode3 =
pantheon.createCliqueNodeWithValidators("miner3", initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);

cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
}

@Test
public void shouldNotRemoveValidatorWhenInsufficientVotes() throws IOException {
final PantheonNode minerNode1 = pantheon.createCliqueNode("miner1");
final PantheonNode minerNode2 = pantheon.createCliqueNode("miner2");
final PantheonNode minerNode3 = pantheon.createCliqueNode("miner3");
cluster.start(minerNode1, minerNode2, minerNode3);

cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode3));
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
}

@Test
public void shouldIncludeVoteInBlockHeader() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final PantheonNode minerNode1 =
pantheon.createCliqueNodeWithValidators("miner1", initialValidators);
final PantheonNode minerNode2 =
pantheon.createCliqueNodeWithValidators("miner2", initialValidators);
final PantheonNode minerNode3 =
pantheon.createCliqueNodeWithValidators("miner3", initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);

minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
minerNode1.verify(blockchain.beneficiaryEquals(minerNode3));
minerNode1.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.AUTH));

minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode2));
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1));
minerNode1.verify(blockchain.beneficiaryEquals(minerNode2));
minerNode1.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.DROP));
}
}
Loading

0 comments on commit ab744a9

Please sign in to comment.