mirror of
https://github.com/Qortal/AT.git
synced 2025-01-30 19:02:14 +00:00
Improved test support:
* pom.xml now builds JavaDoc, sources and test JARs * more descriptive output from test classes to aid debugging * actually add/collate AT-generated transactions to test blockchain for analysis * test block period changed from 10 minutes to 1 minute * 'quiet' logger aded that doesn't emit DEBUG log entries
This commit is contained in:
parent
0a16696352
commit
e522fb312d
55
Java/pom.xml
55
Java/pom.xml
@ -6,16 +6,20 @@
|
|||||||
<artifactId>AT</artifactId>
|
<artifactId>AT</artifactId>
|
||||||
<version>1.4.0</version>
|
<version>1.4.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<skipTests>false</skipTests>
|
<skipTests>false</skipTests>
|
||||||
|
|
||||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||||
|
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
|
||||||
<maven-javadoc-plugin.version>3.3.1</maven-javadoc-plugin.version>
|
<maven-javadoc-plugin.version>3.3.1</maven-javadoc-plugin.version>
|
||||||
<maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
|
<maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
|
||||||
|
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
|
||||||
|
|
||||||
<bouncycastle.version>1.64</bouncycastle.version>
|
<bouncycastle.version>1.64</bouncycastle.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src/main/java</sourceDirectory>
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||||
@ -37,6 +41,19 @@
|
|||||||
<skipTests>${skipTests}</skipTests>
|
<skipTests>${skipTests}</skipTests>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>${maven-source-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
@ -50,9 +67,47 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>${maven-jar-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>test-jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>${maven-source-plugin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>${maven-javadoc-plugin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>${maven-jar-plugin.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.ciyam.at;
|
package org.ciyam.at;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
public interface AtLoggerFactory {
|
public interface AtLoggerFactory {
|
||||||
|
|
||||||
AtLogger create(final Class<?> loggerName);
|
AtLogger create(final Class<?> loggerName);
|
||||||
|
@ -1070,7 +1070,11 @@ public enum OpCode {
|
|||||||
|
|
||||||
public byte[] compile(Object... args) throws CompilationException {
|
public byte[] compile(Object... args) throws CompilationException {
|
||||||
if (args.length != this.params.length)
|
if (args.length != this.params.length)
|
||||||
throw new IllegalArgumentException(String.format("%s requires %d args, only %d passed", this.name(), this.params.length, args.length));
|
throw new IllegalArgumentException(String.format("%s requires %d arg%s, but %d passed",
|
||||||
|
this.name(),
|
||||||
|
this.params.length,
|
||||||
|
this.params.length != 1 ? "s" : "",
|
||||||
|
args.length));
|
||||||
|
|
||||||
ByteBuffer byteBuffer = ByteBuffer.allocate(32); // 32 should easily be enough
|
ByteBuffer byteBuffer = ByteBuffer.allocate(32); // 32 should easily be enough
|
||||||
|
|
||||||
|
@ -86,13 +86,27 @@ public class BlockchainFunctionCodeTests extends ExecutableTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPutPreviousBlockHashIntoA() throws ExecutionException {
|
public void testPutPreviousBlockHashIntoA() throws ExecutionException {
|
||||||
int previousBlockHeight = TestAPI.DEFAULT_INITIAL_BLOCK_HEIGHT - 1;
|
// Generate some blocks containing transactions (but none to AT)
|
||||||
|
TestBlock newBlock = api.generateBlockWithNonAtTransactions();
|
||||||
|
api.addBlockToChain(newBlock);
|
||||||
|
api.bumpCurrentBlockHeight();
|
||||||
|
|
||||||
|
newBlock = api.generateBlockWithNonAtTransactions();
|
||||||
|
api.addBlockToChain(newBlock);
|
||||||
|
api.bumpCurrentBlockHeight();
|
||||||
|
|
||||||
|
// Generate a block containing transaction to AT
|
||||||
|
newBlock = api.generateBlockWithAtTransaction();
|
||||||
|
api.addBlockToChain(newBlock);
|
||||||
|
int previousBlockHeight = api.getCurrentBlockHeight();
|
||||||
|
api.bumpCurrentBlockHeight();
|
||||||
|
|
||||||
codeByteBuffer.put(OpCode.EXT_FUN.value).putShort(FunctionCode.PUT_PREVIOUS_BLOCK_HASH_INTO_A.value);
|
codeByteBuffer.put(OpCode.EXT_FUN.value).putShort(FunctionCode.PUT_PREVIOUS_BLOCK_HASH_INTO_A.value);
|
||||||
codeByteBuffer.put(OpCode.FIN_IMD.value);
|
codeByteBuffer.put(OpCode.FIN_IMD.value);
|
||||||
|
|
||||||
execute(true);
|
execute(true);
|
||||||
|
|
||||||
|
// previousBlockHeight - 1 because index into blockchain starts at 0, whereas block heights start at 1
|
||||||
byte[] expectedBlockHash = api.blockchain.get(previousBlockHeight - 1).blockHash;
|
byte[] expectedBlockHash = api.blockchain.get(previousBlockHeight - 1).blockHash;
|
||||||
|
|
||||||
byte[] aBytes = api.getA(state);
|
byte[] aBytes = api.getA(state);
|
||||||
|
@ -96,6 +96,9 @@ public abstract class ExecutableTest {
|
|||||||
System.out.println("New balance: " + TestAPI.prettyAmount(newBalance));
|
System.out.println("New balance: " + TestAPI.prettyAmount(newBalance));
|
||||||
api.setCurrentBalance(newBalance);
|
api.setCurrentBalance(newBalance);
|
||||||
|
|
||||||
|
// Add block, possibly containing AT-created transactions, to chain to at least provide block hashes
|
||||||
|
api.addCurrentBlockToChain();
|
||||||
|
|
||||||
// Bump block height
|
// Bump block height
|
||||||
api.bumpCurrentBlockHeight();
|
api.bumpCurrentBlockHeight();
|
||||||
|
|
||||||
|
37
Java/src/test/java/org/ciyam/at/test/QuietTestLogger.java
Normal file
37
Java/src/test/java/org/ciyam/at/test/QuietTestLogger.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package org.ciyam.at.test;
|
||||||
|
|
||||||
|
import org.ciyam.at.AtLogger;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class QuietTestLogger implements AtLogger {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String message) {
|
||||||
|
System.err.println("ERROR: " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(Supplier<String> messageSupplier) {
|
||||||
|
System.err.println("ERROR: " + messageSupplier.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(Supplier<String> messageSupplier) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void echo(String message) {
|
||||||
|
System.err.println("ECHO: " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void echo(Supplier<String> messageSupplier) {
|
||||||
|
System.err.println("ECHO: " + messageSupplier.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.ciyam.at.test;
|
||||||
|
|
||||||
|
import org.ciyam.at.AtLogger;
|
||||||
|
import org.ciyam.at.AtLoggerFactory;
|
||||||
|
|
||||||
|
public class QuietTestLoggerFactory implements AtLoggerFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AtLogger create(Class<?> loggerName) {
|
||||||
|
return new QuietTestLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,7 +19,7 @@ import org.ciyam.at.Timestamp;
|
|||||||
public class TestAPI extends API {
|
public class TestAPI extends API {
|
||||||
|
|
||||||
/** Average period between blocks, in seconds. */
|
/** Average period between blocks, in seconds. */
|
||||||
public static final int BLOCK_PERIOD = 10 * 60;
|
public static final int BLOCK_PERIOD = 60;
|
||||||
/** Maximum number of steps before auto-sleep. */
|
/** Maximum number of steps before auto-sleep. */
|
||||||
public static final int MAX_STEPS_PER_ROUND = 500;
|
public static final int MAX_STEPS_PER_ROUND = 500;
|
||||||
/** Op-code step multiplier for calling functions. */
|
/** Op-code step multiplier for calling functions. */
|
||||||
@ -102,29 +102,27 @@ public class TestAPI extends API {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TestBlock> blockchain;
|
public List<TestBlock> blockchain = new ArrayList<>();
|
||||||
public Map<String, TestAccount> accounts;
|
public Map<String, TestAccount> accounts = new HashMap<>();
|
||||||
public Map<String, TestTransaction> transactions;
|
public Map<String, TestTransaction> transactions = new HashMap<>();
|
||||||
|
public List<TestTransaction> atTransactions = new ArrayList<>();
|
||||||
|
|
||||||
|
private TestBlock currentBlock = new TestBlock();
|
||||||
private int currentBlockHeight;
|
private int currentBlockHeight;
|
||||||
|
|
||||||
public TestAPI() {
|
public TestAPI() {
|
||||||
this.currentBlockHeight = DEFAULT_INITIAL_BLOCK_HEIGHT;
|
this.currentBlockHeight = DEFAULT_INITIAL_BLOCK_HEIGHT;
|
||||||
|
|
||||||
// Fill block chain from block 1 to initial height with empty blocks
|
// Fill block chain from block 1 to initial height with empty blocks
|
||||||
blockchain = new ArrayList<>();
|
|
||||||
for (int h = 1; h <= this.currentBlockHeight; ++h)
|
for (int h = 1; h <= this.currentBlockHeight; ++h)
|
||||||
blockchain.add(new TestBlock());
|
blockchain.add(new TestBlock());
|
||||||
|
|
||||||
// Set up test accounts
|
// Set up test accounts
|
||||||
accounts = new HashMap<>();
|
|
||||||
new TestAccount(AT_CREATOR_ADDRESS, 1000000L).addToMap(accounts);
|
new TestAccount(AT_CREATOR_ADDRESS, 1000000L).addToMap(accounts);
|
||||||
new TestAccount(AT_ADDRESS, DEFAULT_INITIAL_BALANCE).addToMap(accounts);
|
new TestAccount(AT_ADDRESS, DEFAULT_INITIAL_BALANCE).addToMap(accounts);
|
||||||
new TestAccount("Initiator", 100000L).addToMap(accounts);
|
new TestAccount("Initiator", 100000L).addToMap(accounts);
|
||||||
new TestAccount("Responder", 200000L).addToMap(accounts);
|
new TestAccount("Responder", 200000L).addToMap(accounts);
|
||||||
new TestAccount("Bystander", 300000L).addToMap(accounts);
|
new TestAccount("Bystander", 300000L).addToMap(accounts);
|
||||||
|
|
||||||
transactions = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] encodeAddress(String address) {
|
public static byte[] encodeAddress(String address) {
|
||||||
@ -153,6 +151,15 @@ public class TestAPI extends API {
|
|||||||
this.currentBlockHeight = blockHeight;
|
this.currentBlockHeight = blockHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addTransactionToCurrentBlock(TestTransaction testTransaction) {
|
||||||
|
currentBlock.transactions.add(testTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCurrentBlockToChain() {
|
||||||
|
addBlockToChain(currentBlock);
|
||||||
|
currentBlock = new TestBlock();
|
||||||
|
}
|
||||||
|
|
||||||
public TestBlock addBlockToChain(TestBlock newBlock) {
|
public TestBlock addBlockToChain(TestBlock newBlock) {
|
||||||
blockchain.add(newBlock);
|
blockchain.add(newBlock);
|
||||||
final int blockHeight = blockchain.size();
|
final int blockHeight = blockchain.size();
|
||||||
@ -165,6 +172,10 @@ public class TestAPI extends API {
|
|||||||
|
|
||||||
// Add to transactions map
|
// Add to transactions map
|
||||||
transactions.put(stringifyHash(transaction.txHash), transaction);
|
transactions.put(stringifyHash(transaction.txHash), transaction);
|
||||||
|
|
||||||
|
// Transaction sent/received by AT? Add to AT transactions list
|
||||||
|
if (transaction.sender.equals(AT_ADDRESS) || transaction.recipient.equals(AT_ADDRESS))
|
||||||
|
atTransactions.add(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newBlock;
|
return newBlock;
|
||||||
@ -288,7 +299,11 @@ public class TestAPI extends API {
|
|||||||
|
|
||||||
if (transaction.recipient.equals("AT")) {
|
if (transaction.recipient.equals("AT")) {
|
||||||
// Found a transaction
|
// Found a transaction
|
||||||
System.out.println("Found transaction at height " + blockHeight + " sequence " + transactionSequence);
|
System.out.println(String.format("Found transaction at height %d, sequence %d: %s from %s",
|
||||||
|
blockHeight,
|
||||||
|
transactionSequence,
|
||||||
|
transaction.txType.name(),
|
||||||
|
transaction.sender));
|
||||||
|
|
||||||
// Generate pseudo-hash of transaction
|
// Generate pseudo-hash of transaction
|
||||||
this.setA(state, transaction.txHash);
|
this.setA(state, transaction.txHash);
|
||||||
@ -392,12 +407,29 @@ public class TestAPI extends API {
|
|||||||
if (recipient == null)
|
if (recipient == null)
|
||||||
throw new IllegalStateException("Refusing to pay to unknown account: " + address);
|
throw new IllegalStateException("Refusing to pay to unknown account: " + address);
|
||||||
|
|
||||||
|
if (amount < 0)
|
||||||
|
throw new IllegalStateException(String.format("Refusing to pay negative amount: %s", amount));
|
||||||
|
|
||||||
|
if (amount == 0) {
|
||||||
|
System.out.println(String.format("Skipping zero-amount payment to account %s", address));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
recipient.balance += amount;
|
recipient.balance += amount;
|
||||||
System.out.println(String.format("Paid %s to '%s', their balance now: %s", prettyAmount(amount), recipient.address, prettyAmount(recipient.balance)));
|
System.out.println(String.format("Paid %s to '%s', their balance now: %s", prettyAmount(amount), recipient.address, prettyAmount(recipient.balance)));
|
||||||
|
|
||||||
final long previousBalance = state.getCurrentBalance();
|
final long previousBalance = state.getCurrentBalance();
|
||||||
final long newBalance = previousBalance - amount;
|
final long newBalance = previousBalance - amount;
|
||||||
System.out.println(String.format("AT balance was %s, now: %s", prettyAmount(previousBalance), prettyAmount(newBalance)));
|
System.out.println(String.format("AT balance was %s, now: %s", prettyAmount(previousBalance), prettyAmount(newBalance)));
|
||||||
|
|
||||||
|
// Add suitable transaction to currentBlock
|
||||||
|
|
||||||
|
// Generate tx hash
|
||||||
|
byte[] txHash = new byte[32];
|
||||||
|
RANDOM.nextBytes(txHash);
|
||||||
|
|
||||||
|
TestTransaction testTransaction = new TestTransaction(txHash, AT_ADDRESS, recipient.address, amount);
|
||||||
|
addTransactionToCurrentBlock(testTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -409,7 +441,17 @@ public class TestAPI extends API {
|
|||||||
if (recipient == null)
|
if (recipient == null)
|
||||||
throw new IllegalStateException("Refusing to send message to unknown account: " + address);
|
throw new IllegalStateException("Refusing to send message to unknown account: " + address);
|
||||||
|
|
||||||
recipient.messages.add(this.getA(state));
|
byte[] message = this.getA(state);
|
||||||
|
recipient.messages.add(message);
|
||||||
|
|
||||||
|
// Add suitable transaction to currentBlock
|
||||||
|
|
||||||
|
// Generate tx hash
|
||||||
|
byte[] txHash = new byte[32];
|
||||||
|
RANDOM.nextBytes(txHash);
|
||||||
|
|
||||||
|
TestTransaction testTransaction = new TestTransaction(txHash, AT_ADDRESS, recipient.address, message);
|
||||||
|
addTransactionToCurrentBlock(testTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user