diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/Application.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/Application.java index 6937ec6..806eae6 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/Application.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/Application.java @@ -42,6 +42,19 @@ public class Application { public Application(boolean isProduction) { this.isProduction = isProduction; } + + /** + * Constructor used for testing. + * @param localStore - the localStore to use + * @param serverThread - the serverThread to use + * @param transactionSender - the transactionSender to use + */ + protected Application(LocalStore localStore, Thread serverThread, TransactionSender transactionSender) { + this.localStore = localStore; + this.serverThread = serverThread; + this.transactionSender = transactionSender; + this.isProduction = false; + } /** * Initializes the application. diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/LocalStore.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/LocalStore.java index 92ccaf1..31a0d97 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/LocalStore.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/LocalStore.java @@ -21,6 +21,7 @@ * Class to store information related to our own node. */ public class LocalStore { + @Getter private final Application application; @@ -104,13 +105,15 @@ public Transaction getTransactionFromNode(int nodeId, int transactionId) { if (nodeId == Transaction.GENESIS_SENDER) { // It's a genesis transaction Block genesisBlock = this.ownNode.getChain().getGenesisBlock(); - return genesisBlock.getTransactions().get(transactionId); - } - - Node node = getNode(nodeId); - for (Block block : node.getChain().getBlocks()) { - for (Transaction transaction : block.getTransactions()) { - if (transaction.getNumber() == transactionId) return transaction; + if (transactionId < genesisBlock.getTransactions().size()) { + return genesisBlock.getTransactions().get(transactionId); + } + } else { + Node node = getNode(nodeId); + for (Block block : node.getChain().getBlocks()) { + for (Transaction transaction : block.getTransactions()) { + if (transaction.getNumber() == transactionId) return transaction; + } } } @@ -128,17 +131,19 @@ public Transaction getTransactionFromNode(int nodeId, int blockId, int transacti if (nodeId == Transaction.GENESIS_SENDER) { // It's a genesis transaction Block genesisBlock = this.ownNode.getChain().getGenesisBlock(); - return genesisBlock.getTransactions().get(transactionId); - } - - Node node = getNode(nodeId); - try { - Block block = node.getChain().getBlocks().get(blockId); - for (Transaction transaction : block.getTransactions()) { - if (transaction.getNumber() == transactionId) return transaction; + if (transactionId < genesisBlock.getTransactions().size()) { + return genesisBlock.getTransactions().get(transactionId); + } + } else { + Node node = getNode(nodeId); + try { + Block block = node.getChain().getBlocks().get(blockId); + for (Transaction transaction : block.getTransactions()) { + if (transaction.getNumber() == transactionId) return transaction; + } + } catch (IndexOutOfBoundsException ex) { + throw new IllegalStateException("Block with id " + blockId + " from node " + nodeId + " not found."); } - } catch (IndexOutOfBoundsException ex) { - throw new IllegalStateException("Block with id " + blockId + " from node " + nodeId + " not found."); } throw new IllegalStateException("Transaction with id " + transactionId + " in block " + blockId + " from node " + nodeId + " not found."); diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/NodeStateChangeFailedException.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/NodeStateChangeFailedException.java new file mode 100644 index 0000000..c673af5 --- /dev/null +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/NodeStateChangeFailedException.java @@ -0,0 +1,15 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger; + +/** + * Exception for indicating that updating the running state of a node on the tracker failed. + */ +public class NodeStateChangeFailedException extends RuntimeException { + /** + * Constructor + * @param id - the ID of the node for which it failed + * @param running - the running state that it could not be updated to + */ + public NodeStateChangeFailedException(int id, boolean running) { + super("Failed to set the running state of node " + id + "to" + running); + } +} diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java index 64d1479..0153248 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java @@ -32,7 +32,6 @@ * Helper class for interacting with the tracker. */ public final class TrackerHelper { - private volatile static Queue transactionsToBeRegistered = new LinkedList<>(); private static final CloseableHttpClient client = HttpClientBuilder.create().build(); diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/exceptions/NotEnoughMoneyException.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/exceptions/NotEnoughMoneyException.java index 33e046e..5713284 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/exceptions/NotEnoughMoneyException.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/exceptions/NotEnoughMoneyException.java @@ -4,6 +4,7 @@ * Exception for indicating that the user doesn't have enough money. */ public class NotEnoughMoneyException extends RuntimeException { + private static final long serialVersionUID = -5115214404574584898L; /** @@ -13,10 +14,4 @@ public NotEnoughMoneyException() { super(); } - /** - * @param msg - the message - */ - public NotEnoughMoneyException(String msg) { - super(msg); - } } diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Block.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Block.java index dd4a1e3..6c87717 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Block.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Block.java @@ -122,7 +122,7 @@ public BlockAbstract calculateBlockAbstract() { if (!(this.owner instanceof OwnNode)) { throw new UnsupportedOperationException("You cannot calculate the block abstract of a block you do not own!"); } - + // Convert attributes of abstract into an array of bytes, for the signature // Important to keep the order of writings byte[] attrInBytes; @@ -151,10 +151,10 @@ public BlockAbstract calculateBlockAbstract() { * @param localStore - the local store */ public synchronized void commit(LocalStore localStore) { - if (finalized) { + if (this.finalized) { throw new IllegalStateException("This block has already been committed!"); } - + Log.log(Level.FINER, "Committing block " + getNumber(), getOwner().getId()); //Commit to the main chain, and set the last committed block @@ -169,7 +169,7 @@ public synchronized void commit(LocalStore localStore) { prev = prev.getPreviousBlock(); } - finalized = true; + this.finalized = true; } @Override diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockAbstract.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockAbstract.java index 5348157..9cbdb79 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockAbstract.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockAbstract.java @@ -13,6 +13,8 @@ import java.io.Serializable; import java.io.ByteArrayOutputStream; import java.security.SignatureException; +import java.util.Arrays; +import java.util.Objects; import java.util.logging.Level; /** @@ -105,18 +107,36 @@ public boolean checkBlockHash(Block block) { */ public boolean checkSignature(byte[] signatureKey) { try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - outputStream.write(Utils.intToByteArray(this.ownerNodeId)); - outputStream.write(Utils.intToByteArray(this.blockNumber)); - outputStream.write(this.blockHash.getBytes()); - byte[] attrInBytes = outputStream.toByteArray(); + byte[] attrInBytes = BlockAbstract.calculateBytesForSignature(this.ownerNodeId, this.blockNumber, this.blockHash); return Ed25519Key.verify(attrInBytes, this.signature, signatureKey); - } catch (IOException | SignatureException e) { + } catch (SignatureException e) { return false; } } + /** + * Convert attributes of abstract into an array of bytes, for the signature. + * Important to keep the order of writings. + * @param ownerId - id of the owner + * @param blockNumber - number of the block + * @param hash - hash of the block + * @return array of bytes + */ + public static byte[] calculateBytesForSignature(int ownerId, int blockNumber, Sha256Hash hash) { + byte[] attrInBytes; + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + outputStream.write(Utils.intToByteArray(ownerId)); + outputStream.write(Utils.intToByteArray(blockNumber)); + outputStream.write(hash.getBytes()); + attrInBytes = outputStream.toByteArray(); + } catch (IOException ex) { + throw new IllegalStateException("Unable to write to outputstream", ex); + } + + return attrInBytes; + } + private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); } @@ -126,4 +146,32 @@ private void readObject(ObjectInputStream stream) throws IOException, stream.defaultReadObject(); } + @Override + public int hashCode() { + int hash = 7; + hash = 47 * hash + this.ownerNodeId; + hash = 47 * hash + this.blockNumber; + hash = 47 * hash + Objects.hashCode(this.blockHash); + hash = 47 * hash + Arrays.hashCode(this.signature); + hash = 47 * hash + Objects.hashCode(this.abstractHash); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (!(obj instanceof BlockAbstract)) return false; + + BlockAbstract other = (BlockAbstract) obj; + if (ownerNodeId != other.ownerNodeId) return false; + if (blockNumber != other.blockNumber) return false; + if (!blockHash.equals(other.blockHash)) return false; + if (!Arrays.equals(signature, other.signature)) return false; + if (this.abstractHash == null) { + if (other.abstractHash != null) return false; + } else if (other.abstractHash == null || this.abstractHash.equals(other.abstractHash)) return false; + + return true; + } + } diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainView.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainView.java index 675c89a..68d938c 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainView.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainView.java @@ -47,7 +47,7 @@ public ChainView(Chain chain, List updates, boolean trim) { * true if this view is valid, false otherwise */ public boolean isValid() { - if (this.valid != null) return this.valid.booleanValue(); + if (this.valid != null) return this.valid; return checkIntegrity(); } diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519Key.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519Key.java index 4000235..003103e 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519Key.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519Key.java @@ -102,9 +102,11 @@ public boolean verify(byte[] message, byte[] signature) throws SignatureExceptio * @param message - array of bytes of the message * @param privateKey - private ED25519 key * @return signature of the message - * @throws java.lang.Exception - exception while signing + * @throws java.security.SignatureException - invalid signature + * @throws java.security.InvalidKeyException - invalid key + * @throws java.security.NoSuchAlgorithmException - no algorithm found for Ed25519 */ - public static byte[] sign(byte[] message, byte[] privateKey) throws Exception { + public static byte[] sign(byte[] message, byte[] privateKey) throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { // Get seed byte[] seed = Arrays.copyOf(privateKey, 32); // Sign @@ -120,9 +122,11 @@ public static byte[] sign(byte[] message, byte[] privateKey) throws Exception { * Sign an array of bytes with a private key. * @param message - array of bytes of the message * @return signature of the message - * @throws java.lang.Exception - exception while signing + * @throws java.security.SignatureException - invalid signature + * @throws java.security.InvalidKeyException - invalid key + * @throws java.security.NoSuchAlgorithmException - no algorithm found for Ed25519 */ - public byte[] sign(byte[] message) throws Exception { + public byte[] sign(byte[] message) throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { return sign(message, this.privateKey); } diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Node.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Node.java index b207d9e..5ed397e 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Node.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Node.java @@ -1,5 +1,6 @@ package nl.tudelft.blockchain.scaleoutdistributedledger.model; +import java.security.SignatureException; import lombok.Getter; import lombok.Setter; @@ -59,9 +60,9 @@ public Node(int id, byte[] publicKey, String address, int port) { * @param message - message to be verified * @param signature - signature of the message * @return - the signature - * @throws Exception - See {@link Ed25519Key#verify(byte[], byte[], byte[])} + * @throws SignatureException - See {@link Ed25519Key#verify(byte[], byte[], byte[])} */ - public boolean verify(byte[] message, byte[] signature) throws Exception { + public boolean verify(byte[] message, byte[] signature) throws SignatureException { return Ed25519Key.verify(message, signature, this.publicKey); } diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/OwnNode.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/OwnNode.java index 5a671a9..cf853a2 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/OwnNode.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/OwnNode.java @@ -7,6 +7,7 @@ * Class to represent our own node. */ public class OwnNode extends Node { + /** * Only used by the node himself. * @return private key @@ -44,4 +45,5 @@ public byte[] sign(byte[] message) throws Exception { public String toString() { return "(OwnNode) " + super.toString(); } + } diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/.gitignore b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/ApplicationTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/ApplicationTest.java new file mode 100644 index 0000000..b529108 --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/ApplicationTest.java @@ -0,0 +1,96 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger; + +import nl.tudelft.blockchain.scaleoutdistributedledger.mocks.TendermintChainMock; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.OwnNode; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.mainchain.MainChain; +import nl.tudelft.blockchain.scaleoutdistributedledger.simulation.CancellableInfiniteRunnable; +import nl.tudelft.blockchain.scaleoutdistributedledger.simulation.transactionpattern.ITransactionPattern; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +/** + * Class to test {@link Application}. + */ +public class ApplicationTest { + + private Application instance; + private Thread serverMock; + private TransactionSender transactionSenderMock; + private LocalStore localStoreMock; + + /** + * Setup method. + */ + @Before + public void setUp() { + this.localStoreMock = mock(LocalStore.class); + this.serverMock = mock(Thread.class); + this.transactionSenderMock = mock(TransactionSender.class); + + this.instance = new Application(this.localStoreMock, this.serverMock, this.transactionSenderMock); + when(this.localStoreMock.getMainChain()).thenReturn(spy(new TendermintChainMock())); + when(this.localStoreMock.getOwnNode()).thenReturn(new OwnNode(0)); + } + + /** + * Test for {@link Application#kill()}. + */ + @Test + public void testKill() { + this.instance.kill(); + + verify(this.transactionSenderMock, times(1)).shutdownNow(); + verify(this.instance.getMainChain(), times(1)).stop(); + } + + /** + * Test for {@link Application#startTransacting()}. + * @throws java.lang.InterruptedException - interrupted while sleeping + */ + @Test + public void testStartTransacting() throws InterruptedException { + CancellableInfiniteRunnable runnableMock = this.setTransactionPattern(); + + this.instance.startTransacting(); + // Wait for thread to start + verify(runnableMock, timeout(2000).times(1)).run(); + } + + /** + * Test for {@link Application#getMainChain()}. + */ + @Test + public void testGetMainChain() { + MainChain chain = mock(MainChain.class); + when(this.localStoreMock.getMainChain()).thenReturn(chain); + assertEquals(chain, this.instance.getMainChain()); + } + + /** + * Test for {@link Application#finishTransactionSending()}. + * @throws InterruptedException - interrupted while sleeping + */ + @Test + public void testFinishTransactionSending() throws InterruptedException { + this.instance.finishTransactionSending(); + +// verify(this.transactionSenderMock, times(1)).stop(); + verify(this.transactionSenderMock, times(1)).waitUntilDone(); + } + + /** + * Set a transaction pattern. + * @return cancellable infinite runnable + */ + private CancellableInfiniteRunnable setTransactionPattern() { + ITransactionPattern transactionPatternMock = mock(ITransactionPattern.class); + CancellableInfiniteRunnable runnableMock = mock(CancellableInfiniteRunnable.class); + when(transactionPatternMock.getRunnable(any(LocalStore.class))).thenReturn(runnableMock); + this.instance.setTransactionPattern(transactionPatternMock); + return runnableMock; + } + +} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/CommunicationHelperTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/CommunicationHelperTest.java new file mode 100644 index 0000000..32d3a90 --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/CommunicationHelperTest.java @@ -0,0 +1,113 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger; + +import java.util.*; + +import nl.tudelft.blockchain.scaleoutdistributedledger.model.Block; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.Node; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.OwnNode; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.Proof; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.Transaction; +import nl.tudelft.blockchain.scaleoutdistributedledger.test.utils.TestHelper; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import static org.mockito.Mockito.mock; + +/** + * Class to test {@link CommunicationHelper}. + */ +public class CommunicationHelperTest { + + private static int transactionId = 11; + + private Block genesisBlock; + + private OwnNode ownNode; + + private LocalStore localStore; + + private Node bobNode; + + private Node charlieNode; + + /** + * Setup method. + */ + @Before + public void setUp() { + // Setup ownNode + this.ownNode = new OwnNode(0); + this.genesisBlock = TestHelper.generateGenesis(this.ownNode, 10, 1000); + Application application = mock(Application.class); + this.localStore = new LocalStore(this.ownNode, application, this.genesisBlock, false); + // Setup bobNode + this.bobNode = new Node(1); + bobNode.getChain().setGenesisBlock(this.genesisBlock); + // Setup charlie + this.charlieNode = new Node(2); + this.charlieNode.getChain().setGenesisBlock(this.genesisBlock); + } + + /** + * Create a transaction from a genesis block. + * @param sender - node sender + * @param receiver - node receiver + * @param amount - amount of the transaction + * @param remainder - remainder of the transaction + * @return + */ + private Transaction createTransactionFromGenesis(Node sender, Node receiver, long amount, long remainder) { + // Create new block for transaction + List blockList = new ArrayList<>(); + blockList.add(new Block(sender.getChain().getLastBlock().getNumber() + 1, sender, new ArrayList<>())); + sender.getChain().update(blockList, localStore); + // Setup sources + TreeSet sources = new TreeSet<>(); + sources.add(this.genesisBlock.getTransactions().get(sender.getId())); + // Create transaction + Transaction transaction = new Transaction(transactionId++, sender, receiver, amount, remainder, sources); + Block blockOfTransaction = sender.getChain().getLastBlock(); + transaction.setBlockNumber(blockOfTransaction.getNumber()); + blockOfTransaction.addTransaction(transaction); + return transaction; + } + + /** + * Test for {@link CommunicationHelper#receiveTransaction}. + */ + @Test + public void testReceiveTransaction_Valid() { + // Create Transaction and Proof + Transaction transaction = this.createTransactionFromGenesis(this.bobNode, this.ownNode, 100, 900); + Proof proof = new Proof(transaction); + + assertTrue(CommunicationHelper.receiveTransaction(proof, this.localStore)); + assertTrue(this.localStore.getUnspent().contains(transaction)); + } + + /** + * Test for {@link CommunicationHelper#receiveTransaction}. + */ + @Test + public void testReceiveTransaction_InvalidReceiver() { + // Create Transaction and Proof + Transaction transaction = this.createTransactionFromGenesis(this.bobNode, this.charlieNode, 100, 900); + Proof proof = new Proof(transaction); + + assertFalse(CommunicationHelper.receiveTransaction(proof, this.localStore)); + } + + /** + * Test for {@link CommunicationHelper#receiveTransaction}. + */ + @Test + public void testReceiveTransaction_InvalidAmount() { + // Create Transaction and Proof + Transaction transaction = this.createTransactionFromGenesis(this.bobNode, this.ownNode, 9999, 900); + Proof proof = new Proof(transaction); + + assertFalse(CommunicationHelper.receiveTransaction(proof, this.localStore)); + } + +} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/LocalStoreTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/LocalStoreTest.java new file mode 100644 index 0000000..b9cf1f2 --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/LocalStoreTest.java @@ -0,0 +1,75 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger; + +import nl.tudelft.blockchain.scaleoutdistributedledger.model.Block; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.Node; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.OwnNode; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.Transaction; +import nl.tudelft.blockchain.scaleoutdistributedledger.test.utils.TestHelper; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import static org.mockito.Mockito.mock; + +/** + * Class to test {@link LocalStore}. + */ +public class LocalStoreTest { + + private OwnNode ownNode; + + private LocalStore localStore; + + /** + * Setup method. + */ + @Before + public void setUp() { + this.ownNode = new OwnNode(0); + Application application = mock(Application.class); + Block genesisBlock = TestHelper.generateGenesis(ownNode, 10, 1000); + this.localStore = new LocalStore(ownNode, application, genesisBlock, false); + } + + /** + * Test for {@link LocalStore#getTransactionFromNode(int, int)}. + */ + @Test + public void testGetTransactionFromNode_Valid_GenesisSender() { + Transaction transaction = this.localStore.getTransactionFromNode(Transaction.GENESIS_SENDER, 0, 0); + assertEquals(this.ownNode, transaction.getReceiver()); + } + + /** + * Test for {@link LocalStore#getTransactionFromNode(int, int)}. + */ + @Test(expected = IllegalStateException.class) + public void testGetTransactionFromNode_Invalid_GenesisSender() { + this.localStore.getTransactionFromNode(Transaction.GENESIS_SENDER, 0, 99); + } + + /** + * Test for {@link LocalStore#getTransactionFromNode(int, int)}. + */ + @Test + public void testGetTransactionFromNode_Valid_NormalSender() { + Transaction transaction = this.localStore.getTransactionFromNode(0, 0, 0); + assertEquals(this.ownNode, transaction.getReceiver()); + } + + /** + * Test for {@link LocalStore#getTransactionFromNode(int, int)}. + */ + @Test(expected = IllegalStateException.class) + public void testGetTransactionFromNode_Invalid_Block() { + this.localStore.getTransactionFromNode(0, 99, 1); + } + + /** + * Test for {@link LocalStore#getTransactionFromNode(int, int)}. + */ + @Test(expected = IllegalStateException.class) + public void testGetTransactionFromNode_Invalid_Transaction() { + this.localStore.getTransactionFromNode(0, 0, 99); + } + +} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/MessageTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/MessageTest.java index bf108a4..d9799f7 100644 --- a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/MessageTest.java +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/MessageTest.java @@ -12,7 +12,9 @@ * Base class for testing messages. */ public abstract class MessageTest { + protected LocalStore storeSpy; + protected Application appMock; /** @@ -21,8 +23,9 @@ public abstract class MessageTest { @Before public void setUp() { OwnNode ownNode = new OwnNode(0); - appMock = mock(Application.class); - storeSpy = spy(new LocalStore(ownNode, appMock, null, false)); - doNothing().when(storeSpy).updateNodes(); + this.appMock = mock(Application.class); + this.storeSpy = spy(new LocalStore(ownNode, this.appMock, null, false)); + doNothing().when(this.storeSpy).updateNodes(); } + } diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/TransactionPatternMessageTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/TransactionPatternMessageTest.java index 15436a4..54a0d4b 100644 --- a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/TransactionPatternMessageTest.java +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/message/TransactionPatternMessageTest.java @@ -19,9 +19,9 @@ public class TransactionPatternMessageTest extends MessageTest { public void testHandle() { ITransactionPattern pattern = mock(ITransactionPattern.class); TransactionPatternMessage msg = new TransactionPatternMessage(pattern); - msg.handle(storeSpy); + msg.handle(this.storeSpy); - //The correct transaction pattern should be set. + // The correct transaction pattern should be set. verify(appMock, times(1)).setTransactionPattern(same(pattern)); } diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockAbstractTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockAbstractTest.java new file mode 100644 index 0000000..92cbc5f --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockAbstractTest.java @@ -0,0 +1,78 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger.model; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import java.util.ArrayList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; + +/** + * Test for {@link BlockAbstract}. + */ +public class BlockAbstractTest { + + private Ed25519Key key; + + private Block block; + + private BlockAbstract blockAbstract; + + /** + * Setup method. + * @throws java.security.SignatureException - error while signing + * @throws java.security.InvalidKeyException - error while using the key + * @throws java.security.NoSuchAlgorithmException - error while using Ed25519 + */ + @Before + public void setUp() throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { + this.key = new Ed25519Key(); + OwnNode ownNode = new OwnNode(0); + ownNode.setPublicKey(this.key.getPublicKey()); + ownNode.setPrivateKey(this.key.getPrivateKey()); + this.block = new Block(2, ownNode, new ArrayList<>()); + this.blockAbstract = this.block.calculateBlockAbstract(); + } + + /** + * Test for {@link BlockAbstract#fromBytes()}. + */ + @Test + public void testFromBytes_Invalid() { + // Invalid decoding + BlockAbstract newBlockAbstract = BlockAbstract.fromBytes(new byte[0]); + assertEquals(null, newBlockAbstract); + } + + /** + * Test for {@link BlockAbstract#toBytes()}. + */ + @Test + public void testToBytes_Invalid() { + // Encode + byte[] bytes = this.blockAbstract.toBytes(); + // Decode + BlockAbstract newBlockAbstract = BlockAbstract.fromBytes(bytes); + + assertEquals(this.blockAbstract, newBlockAbstract); + } + + /** + * Test for {@link BlockAbstract#checkBlockHash}. + */ + @Test + public void testCheckBlockHash_Valid() { + assertTrue(this.blockAbstract.checkBlockHash(this.block)); + } + + /** + * Test for {@link BlockAbstract#checkSignature(byte[])}. + */ + @Test + public void testCheckSignature_Valid() { + assertTrue(this.blockAbstract.checkSignature(this.key.getPublicKey())); + } + +} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockTest.java index 358359b..5464864 100644 --- a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockTest.java +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/BlockTest.java @@ -2,10 +2,14 @@ import nl.tudelft.blockchain.scaleoutdistributedledger.utils.Utils; import java.io.ByteArrayOutputStream; +import java.security.SignatureException; import static org.junit.Assert.*; import java.util.ArrayList; +import nl.tudelft.blockchain.scaleoutdistributedledger.Application; +import nl.tudelft.blockchain.scaleoutdistributedledger.LocalStore; import org.junit.Before; import org.junit.Test; +import static org.mockito.Mockito.mock; /** * Test class for {@link Block}. @@ -16,16 +20,22 @@ public class BlockTest { private Block block; + private Application application; + + private LocalStore localStore; + /** * Setup method. */ @Before public void setUp() { - this.owner = new OwnNode(24); Ed25519Key keyPair = new Ed25519Key(); + this.owner = new OwnNode(24); this.owner.setPrivateKey(keyPair.getPrivateKey()); this.owner.setPublicKey(keyPair.getPublicKey()); - this.block = new Block(1234, owner, new ArrayList<>()); + this.block = new Block(1234, this.owner, new ArrayList<>()); + this.application = mock(Application.class); + this.localStore = new LocalStore(this.owner, this.application, null, false); } /** @@ -50,38 +60,71 @@ public void testGetHash_Invalid() { /** * Test for {@link Block#calculateBlockAbstract()}. + * @throws java.security.SignatureException - fail to sign */ @Test - public void testCalculateBlockAbstract_Valid() { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - outputStream.write(Utils.intToByteArray(this.block.getOwner().getId())); - outputStream.write(Utils.intToByteArray(this.block.getNumber())); - outputStream.write(this.block.getHash().getBytes()); - byte[] attrInBytes = outputStream.toByteArray(); + public void testCalculateBlockAbstract_Valid() throws SignatureException { + byte[] attrInBytes = BlockAbstract.calculateBytesForSignature(this.owner.getId(), this.block.getNumber(), this.block.getHash()); - assertTrue(this.block.getOwner().verify(attrInBytes, this.block.calculateBlockAbstract().getSignature())); - } catch (Exception ex) { - fail(); - } + assertTrue(this.owner.verify(attrInBytes, this.block.calculateBlockAbstract().getSignature())); } /** * Test for {@link Block#calculateBlockAbstract()}. + * @throws java.security.SignatureException - fail to sign */ @Test - public void testCalculateBlockAbstract_Invalid() { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - outputStream.write(Utils.intToByteArray(this.block.getOwner().getId() + 1)); - outputStream.write(Utils.intToByteArray(this.block.getNumber())); - outputStream.write(this.block.getHash().getBytes()); - byte[] attrInBytes = outputStream.toByteArray(); - - assertFalse(this.block.getOwner().verify(attrInBytes, this.block.calculateBlockAbstract().getSignature())); - } catch (Exception ex) { - fail(); - } + public void testCalculateBlockAbstract_Invalid() throws SignatureException { + byte[] attrInBytes = BlockAbstract.calculateBytesForSignature(this.owner.getId() + 1, this.block.getNumber(), this.block.getHash()); + + assertFalse(this.owner.verify(attrInBytes, this.block.calculateBlockAbstract().getSignature())); + } + + /** + * Test for {@link Block#calculateBlockAbstract()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testCalculateBlockAbstract_Invalid_NotOwnNode() { + Block newBlock = new Block(1234, new Node(1), new ArrayList<>()); + newBlock.calculateBlockAbstract(); } + /** + * Test for {@link Block#commit(LocalStore)}. + */ + @Test + public void testCommit_Valid() { + this.block.commit(this.localStore); + + assertEquals(this.block, this.owner.getChain().getLastCommittedBlock()); + } + + /** + * Test for {@link Block#commit(LocalStore)}. + */ + @Test(expected = IllegalStateException.class) + public void testCommitTwice_Invalid() { + this.block.commit(this.localStore); + this.block.commit(this.localStore); + } + + /** + * Test for {@link Block#genesisCopy()}. + */ + @Test + public void testGenesisCopy_Valid() { + Block geneisBlock = new Block(Block.GENESIS_BLOCK_NUMBER, this.owner, new ArrayList<>()); + Block newGenesisBlock = geneisBlock.genesisCopy(); + + assertEquals(geneisBlock, newGenesisBlock); + } + + /** + * Test for {@link Block#isOnMainChain(LocalStore) ()}. + */ + @Test + public void testIsOnMainChain() { + // Is true because TendermintMock returns always true + assertTrue(this.block.isOnMainChain(this.localStore)); + } } diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainTest.java new file mode 100644 index 0000000..953cb19 --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainTest.java @@ -0,0 +1,75 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger.model; + +import java.util.ArrayList; +import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import nl.tudelft.blockchain.scaleoutdistributedledger.LocalStore; +import org.junit.Before; +import org.junit.Test; +import static org.mockito.Mockito.mock; + +/** + * Test class for {@link Chain}. + */ +public class ChainTest { + + private OwnNode ownNode; + + private Node node; + + private Chain chain; + + private LocalStore localStore; + + /** + * Setup method. + */ + @Before + public void setUp() { + this.ownNode = new OwnNode(0); + this.localStore = new LocalStore(this.ownNode, null, null, false); + this.node = mock(Node.class); + this.chain = new Chain(this.node); + } + + /** + * Test for {@link Chainw#update()}. + */ + @Test + public void testUpdate_EmptyUpdate() { + List updateList = new ArrayList<>(); + this.chain.update(updateList, localStore); + + assertTrue(this.chain.getBlocks().isEmpty()); + } + + /** + * Test for {@link Chainw#update()}. + */ + @Test + public void testUpdate_EmptyChain() { + List updateList = new ArrayList<>(); + updateList.add(new Block(0, this.node, new ArrayList<>())); + this.chain.update(updateList, localStore); + + assertEquals(updateList, this.chain.getBlocks()); + } + + /** + * Test for {@link Chainw#update()}. + */ + @Test + public void testUpdate_NotEmptyChain() { + List updateList = new ArrayList<>(); + updateList.add(new Block(0, this.node, new ArrayList<>())); + this.chain.update(updateList, localStore); + updateList.add(new Block(1, this.node, new ArrayList<>())); + updateList.add(new Block(2, this.node, new ArrayList<>())); + this.chain.update(updateList, localStore); + + assertEquals(updateList, this.chain.getBlocks()); + } + +} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainViewTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainViewTest.java index ef9b444..e1e270f 100644 --- a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainViewTest.java +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ChainViewTest.java @@ -27,8 +27,8 @@ public class ChainViewTest { */ @Before public void setUp() { - blocks = new AppendOnlyArrayList(); - updatedBlocks = new ArrayList(); + blocks = new AppendOnlyArrayList<>(); + updatedBlocks = new ArrayList<>(); nodeMock = mock(Node.class); chainMock = mock(Chain.class); @@ -48,7 +48,7 @@ public void setUp() { * the block that was added */ protected Block addBlock(int nr, boolean toChain) { - Block block = new Block(nr, nodeMock, new ArrayList()); + Block block = new Block(nr, nodeMock, new ArrayList<>()); if (toChain) { blocks.add(block); @@ -84,6 +84,17 @@ public void testIsValid_EmptyUpdate() { assertTrue(chainview.isValid()); } + /** + * Test for {@link ChainView#isValid()}. + */ + @Test + public void testIsValid_EmptyChain() { + addBlock(0, false); + addBlock(1, false); + + assertTrue(this.chainview.isValid()); + } + /** * Test for {@link ChainView#isValid()}. */ @@ -183,6 +194,20 @@ public void testGetBlock_UpdatePart() { assertEquals(2, chainview.getBlock(2).getNumber()); } + /** + * Test for {@link ChainView#getBlock(int)}. + */ + @Test(expected = IllegalStateException.class) + public void testGetBlock_Exception() { + addBlock(0, true); + addBlock(1, true); + addBlock(2, false); + addBlock(4, false); + chainview.isValid(); + + this.chainview.getBlock(4); + } + /** * Test for {@link ChainView#size()}. */ @@ -280,4 +305,111 @@ public void testListIteratorPreviousIndex() { assertEquals(0, it.previous().getNumber()); assertEquals(-1, it.previousIndex()); } + + /** + * Test for {@link ChainView#listIterator(int)}. + */ + @Test + public void testListIterator_EmptyChainAndUpdate() { + ListIterator it = chainview.listIterator(0); + + assertFalse(it.hasPrevious()); + assertFalse(it.hasNext()); + } + + /** + * Test for {@link ChainView#listIterator(int)}. + */ + @Test + public void testListIteratorHasNext() { + addBlock(0, true); + addBlock(1, false); + addBlock(2, false); + chainview.isValid(); + + ListIterator it = chainview.listIterator(0); + assertTrue(it.hasNext()); + it.next(); // Get 0 + it.next(); // Get 1 + assertTrue(it.hasNext()); + } + + /** + * Test for {@link ChainView#listIterator(int)}. + */ + @Test + public void testListIteratorHasNext_FromChainToUpdate() { + addBlock(0, true); + addBlock(1, false); + addBlock(2, false); + chainview.isValid(); + + ListIterator it = chainview.listIterator(1); + it.next(); // Get 1 + assertTrue(it.hasNext()); + } + + /** + * Test for {@link ChainView#listIterator(int)}. + */ + @Test + public void testListIteratorHasPrevious() { + addBlock(0, true); + addBlock(1, false); + chainview.isValid(); + + ListIterator it = chainview.listIterator(0); + assertFalse(it.hasPrevious()); + it.next(); // Get 0 + it.next(); // Get 1 + assertFalse(it.hasNext()); + assertTrue(it.hasPrevious()); + } + + /** + * Test for {@link ChainView#listIterator(int)}. + */ + @Test + public void testListIteratorOneBlock() { + addBlock(0, false); + chainview.isValid(); + + ListIterator it = chainview.listIterator(1); + assertFalse(it.hasNext()); + } + + /** + * Test for {@link ChainView#resetValidation()}. + */ + @Test + public void testResetValidation() { + addBlock(0, true); + addBlock(1, true); + addBlock(2, false); + chainview.isValid(); + + // Is valid + assertTrue(this.chainview.isValid()); + // Make invalid + addBlock(4, false); + // Check "valid" cached + assertTrue(this.chainview.isValid()); + // Reset validation + this.chainview.resetValidation(); + // It's now really invalid + assertFalse(this.chainview.isValid()); + } + + /** + * Test for {@link ChainView#isRedundant()}. + */ + @Test + public void testResetIsRedundant_Valid() { + addBlock(0, true); + addBlock(1, true); + chainview.isValid(); + + assertTrue(this.chainview.isRedundant()); + } + } diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519KeyTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519KeyTest.java new file mode 100644 index 0000000..504ace8 --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519KeyTest.java @@ -0,0 +1,144 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger.model; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import static org.junit.Assert.*; + +import org.junit.Test; +import nl.tudelft.blockchain.scaleoutdistributedledger.utils.Utils; +import org.junit.Before; + +/** + * Test class for {@link Ed25519Key}. + */ +public class Ed25519KeyTest { + + private Ed25519Key validKey; + + private Ed25519Key invalidKey; + + /** + * Setup method. + */ + @Before + public void setUp() { + byte[] validPub = Utils.hexStringToBytes("BE8933DFF1600C026E34718F1785A4CDEAB90C35698B394E38B6947AE91DE116"); + byte[] validPriv = Utils.hexStringToBytes("547AA07C7A8CE16C5CB2A40C6C26D15B0A32960410A9F1EA6E50B636F1AB389" + + "ABE8933DFF1600C026E34718F1785A4CDEAB90C35698B394E38B6947AE91DE116"); + this.validKey = new Ed25519Key(validPriv, validPub); + + byte[] invalidPriv = Utils.hexStringToBytes("0000A07C7A8CE16C5CB2A40C6C26D15B0A32960410A9F1EA6E50B636F1AB389" + + "ABE8933DFF1600C026E34718F1785A4CDEAB90C35698B394E38B6947AE91DE116"); + this.invalidKey = new Ed25519Key(invalidPriv, validPub); + } + + /** + * Test for {@link Ed25519Key#sign(byte[], byte[])}. + */ + @Test + public void testSign_Valid() { + byte[] message = "testing message".getBytes(); + + try { + byte[] signature = Ed25519Key.sign(message, this.validKey.getPrivateKey()); + boolean valid = Ed25519Key.verify(message, signature, this.validKey.getPublicKey()); + + assertTrue(valid); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException ex) { + fail(); + } + } + + /** + * Test for {@link Ed25519Key#sign(byte[], byte[])}. + */ + @Test + public void testSign_Invalid() { + byte[] message = "testing message".getBytes(); + + try { + byte[] signature = Ed25519Key.sign(message, this.invalidKey.getPrivateKey()); + boolean valid = Ed25519Key.verify(message, signature, this.invalidKey.getPublicKey()); + + assertFalse(valid); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException ex) { + fail(); + } + } + + /** + * Test for {@link Ed25519Key#generateKeys()}. + */ + @Test + public void testGenerateKeys_Valid() { + Ed25519Key keyPair = new Ed25519Key(); + byte[] pub = keyPair.getPublicKey(); + byte[] priv = keyPair.getPrivateKey(); + byte[] message = "testing message".getBytes(); + + try { + byte[] signature = Ed25519Key.sign(message, priv); + boolean valid = Ed25519Key.verify(message, signature, pub); + + assertTrue(valid); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException ex) { + fail(); + } + } + + /** + * Test for {@link Ed25519Key#sign()} and {@link Ed25519Key#verify()}. + */ + @Test + public void testSignVerify_Valid() { + Ed25519Key keyPair = new Ed25519Key(); + byte[] message = "testing message".getBytes(); + + try { + byte[] signature = keyPair.sign(message); + boolean valid = keyPair.verify(message, signature); + + assertTrue(valid); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException ex) { + fail(); + } + } + + /** + * Test for {@link Ed25519Key#verify(byte[], byte[], byte[]) ()}. + */ + @Test + public void testVerify_Invalid() { + byte[] message = "testing message".getBytes(); + byte[] signature = new byte[10]; + + try { + Ed25519Key.verify(message, signature, this.validKey.getPublicKey()); + + fail(); + } catch (SignatureException ex) { + // Good + } + } + + /** + * Test for {@link Ed25519Key#equals()}. + */ + @Test + public void testEquals_Valid() { + Ed25519Key keyPair = new Ed25519Key(); + Ed25519Key newKeyPair = new Ed25519Key(keyPair.getPrivateKey(), keyPair.getPublicKey()); + + assertEquals(keyPair, newKeyPair); + } + + /** + * Test for {@link Ed25519Key#hashCode() ()}. + */ + @Test + public void testHashCode() { + assertNotEquals(this.validKey.hashCode(), this.invalidKey.hashCode()); + } + +} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519Test.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519Test.java deleted file mode 100644 index 3d40a73..0000000 --- a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Ed25519Test.java +++ /dev/null @@ -1,74 +0,0 @@ -package nl.tudelft.blockchain.scaleoutdistributedledger.model; - -import static org.junit.Assert.*; - -import org.junit.Test; -import nl.tudelft.blockchain.scaleoutdistributedledger.utils.Utils; - -/** - * Test class for {@link Ed25519Key}. - */ -public class Ed25519Test { - - /** - * Test for {@link Ed25519Key#sign(byte[], byte[])}. - */ - @Test - public void testSign_Valid() { - byte[] pub = Utils.hexStringToBytes("BE8933DFF1600C026E34718F1785A4CDEAB90C35698B394E38B6947AE91DE116"); - byte[] priv = Utils.hexStringToBytes("547AA07C7A8CE16C5CB2A40C6C26D15B0A32960410A9F1EA6E50B636F1AB389" - + "ABE8933DFF1600C026E34718F1785A4CDEAB90C35698B394E38B6947AE91DE116"); - - byte[] message = "testing message".getBytes(); - - try { - byte[] signature = Ed25519Key.sign(message, priv); - boolean valid = Ed25519Key.verify(message, signature, pub); - - assertTrue(valid); - } catch (Exception ex) { - fail(); - } - } - - /** - * Test for {@link Ed25519Key#sign(byte[], byte[])}. - */ - @Test - public void testSign_Invalid() { - byte[] pub = Utils.hexStringToBytes("BE8933DFF1600C026E34718F1785A4CDEAB90C35698B394E38B6947AE91DE116"); - byte[] priv = Utils.hexStringToBytes("0000A07C7A8CE16C5CB2A40C6C26D15B0A32960410A9F1EA6E50B636F1AB389" - + "ABE8933DFF1600C026E34718F1785A4CDEAB90C35698B394E38B6947AE91DE116"); - - byte[] message = "testing message".getBytes(); - - try { - byte[] signature = Ed25519Key.sign(message, priv); - boolean valid = Ed25519Key.verify(message, signature, pub); - - assertFalse(valid); - } catch (Exception ex) { - fail(); - } - } - - /** - * Test for {@link Ed25519Key#generateKeys()}. - */ - @Test - public void testGenerateKeys() { - Ed25519Key keyPair = new Ed25519Key(); - byte[] pub = keyPair.getPublicKey(); - byte[] priv = keyPair.getPrivateKey(); - byte[] message = "testing message".getBytes(); - - try { - byte[] signature = Ed25519Key.sign(message, priv); - boolean valid = Ed25519Key.verify(message, signature, pub); - - assertTrue(valid); - } catch (Exception ex) { - fail(); - } - } -} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/NodeTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/NodeTest.java new file mode 100644 index 0000000..c63dcdb --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/NodeTest.java @@ -0,0 +1,29 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger.model; + +import java.util.ArrayList; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * Class to test {@link Node}. + */ +public class NodeTest { + + /** + * Test for {@link Node#updateMetaKnowledge(Proof) }. + */ + @Test + public void testUpdateMetaKnowledge() { + Ed25519Key key = new Ed25519Key(); + Node node = new Node(1, key.getPublicKey(), "127.0.0.1", 1234); + Node otherNode = new Node(2); + Proof proof = new Proof(null); + proof.addBlock(new Block(1, otherNode, new ArrayList<>())); + proof.addBlock(new Block(2, otherNode, new ArrayList<>())); + proof.addBlock(new Block(3, otherNode, new ArrayList<>())); + node.updateMetaKnowledge(proof); + + assertEquals(3, node.getMetaKnowledge().get(otherNode.getId()).intValue()); + } + +} diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ProofTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ProofTest.java index d38a4ab..4df057b 100644 --- a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ProofTest.java +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/ProofTest.java @@ -26,6 +26,8 @@ public class ProofTest { private Application appMock; private Block genesisBlock; + private Proof proof; + /** * @throws Exception - Will not occur. */ diff --git a/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Sha256HashTest.java b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Sha256HashTest.java new file mode 100644 index 0000000..1f5d43c --- /dev/null +++ b/src/test/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/Sha256HashTest.java @@ -0,0 +1,66 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger.model; + +import nl.tudelft.blockchain.scaleoutdistributedledger.utils.Utils; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import org.junit.Test; + +/** + * Class to test {@link Sha256Hash}. + */ +public class Sha256HashTest { + + /** + * Test for {@link Sha256Hash#Sha256Hash(java.lang.String) }. + */ + @Test + public void testConstuctorMessage() { + Sha256Hash hash = new Sha256Hash("hello"); + String expectedStr = "2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E73043362938B9824"; + + assertEquals(expectedStr, hash.toString().toUpperCase()); + } + + /** + * Test for {@link Sha256Hash#Sha256Hash(byte[]) }. + */ + @Test + public void testConstructorBytes() { + Sha256Hash hash = new Sha256Hash(Utils.hexStringToBytes("ABBA")); + + assertNotEquals("ABBA", hash.toString()); + } + + /** + * Test for {@link Sha256Hash#withHash(byte[])}. + */ + @Test + public void testWith() { + Sha256Hash hash = Sha256Hash.withHash(Utils.hexStringToBytes("ABBA")); + + assertNotEquals("ABBA", hash.toString()); + } + + /** + * Test for {@link Sha256Hash#equals(java.lang.Object)}. + */ + @Test + public void testEquals() { + Sha256Hash hash = new Sha256Hash("hello"); + Sha256Hash otherHash = new Sha256Hash("hello"); + + assertEquals(hash, otherHash); + } + + /** + * Test for {@link Sha256Hash#equals(java.lang.Object)}. + */ + @Test + public void testHashCode() { + Sha256Hash hash = new Sha256Hash("hello"); + Sha256Hash otherHash = new Sha256Hash("hello2"); + + assertNotEquals(hash.hashCode(), otherHash.hashCode()); + } + +}