Introduce a mock clock, use it to improve the getRecentTransactions unit tests. Fix a seconds/milliseconds confusion pointed out by Andreas. Resolves issue 43.

This commit is contained in:
Mike Hearn
2011-09-18 20:54:23 +00:00
parent a3a4a927af
commit 5f2029e21b
6 changed files with 31 additions and 11 deletions

View File

@@ -71,7 +71,7 @@ public class PeerAddress extends Message {
@Override @Override
public void bitcoinSerializeToStream(OutputStream stream) throws IOException { public void bitcoinSerializeToStream(OutputStream stream) throws IOException {
if (protocolVersion >= 31402) { if (protocolVersion >= 31402) {
int secs = (int)(new Date().getTime() / 1000); int secs = (int)(Utils.now().getTime() / 1000);
uint32ToByteStreamLE(secs, stream); uint32ToByteStreamLE(secs, stream);
} }
uint64ToByteStreamLE(services, stream); // nServices. uint64ToByteStreamLE(services, stream); // nServices.

View File

@@ -149,7 +149,7 @@ public class Transaction extends Message implements Serializable {
*/ */
void addBlockAppearance(StoredBlock block, boolean bestChain) { void addBlockAppearance(StoredBlock block, boolean bestChain) {
if (bestChain && updatedAt == null) { if (bestChain && updatedAt == null) {
updatedAt = new Date(block.getHeader().getTimeSeconds()); updatedAt = new Date(block.getHeader().getTimeSeconds() * 1000);
} }
if (appearsIn == null) { if (appearsIn == null) {
appearsIn = new HashSet<StoredBlock>(); appearsIn = new HashSet<StoredBlock>();
@@ -247,7 +247,7 @@ public class Transaction extends Message implements Serializable {
for (StoredBlock b : appearsIn) { for (StoredBlock b : appearsIn) {
earliestTimeSecs = Math.min(b.getHeader().getTimeSeconds(), earliestTimeSecs); earliestTimeSecs = Math.min(b.getHeader().getTimeSeconds(), earliestTimeSecs);
} }
updatedAt = new Date(earliestTimeSecs); updatedAt = new Date(earliestTimeSecs * 1000);
} }
return updatedAt; return updatedAt;
} }

View File

@@ -24,6 +24,7 @@ import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Date;
/** /**
* A collection of various utility methods that are helpful for working with the BitCoin protocol. * A collection of various utility methods that are helpful for working with the BitCoin protocol.
@@ -238,4 +239,23 @@ public class Utils {
if (size >= 3) bytes[6] = (byte) ((compact >> 0) & 0xFF); if (size >= 3) bytes[6] = (byte) ((compact >> 0) & 0xFF);
return decodeMPI(bytes); return decodeMPI(bytes);
} }
/** If non-null, overrides the return value of now(). */
public static Date mockTime;
/** Advances (or rewinds) the mock clock by the given number of seconds. */
public static Date rollMockClock(int seconds) {
if (mockTime == null)
mockTime = new Date();
mockTime = new Date(mockTime.getTime() + (seconds * 1000));
return mockTime;
}
/** Returns the current time, or a mocked out equivalent. */
public static Date now() {
if (mockTime != null)
return mockTime;
else
return new Date();
}
} }

View File

@@ -431,8 +431,7 @@ public class Wallet implements Serializable {
connectedOutput.markAsSpent(input); connectedOutput.markAsSpent(input);
maybeMoveTxToSpent(connectedTx, "spent tx"); maybeMoveTxToSpent(connectedTx, "spent tx");
} }
// Refresh the timestamp. tx.updatedAt = Utils.now();
tx.updatedAt = new Date();
// Add to the pending pool. It'll be moved out once we receive this transaction on the best chain. // Add to the pending pool. It'll be moved out once we receive this transaction on the best chain.
pending.put(tx.getHash(), tx); pending.put(tx.getHash(), tx);
} }

View File

@@ -65,7 +65,7 @@ public class TestUtils {
public static BlockPair createFakeBlock(NetworkParameters params, BlockStore blockStore, public static BlockPair createFakeBlock(NetworkParameters params, BlockStore blockStore,
Transaction... transactions) { Transaction... transactions) {
return createFakeBlock(params, blockStore, System.currentTimeMillis() / 1000, transactions); return createFakeBlock(params, blockStore, Utils.now().getTime() / 1000, transactions);
} }
public static Block makeSolvedTestBlock(NetworkParameters params, public static Block makeSolvedTestBlock(NetworkParameters params,

View File

@@ -276,15 +276,15 @@ public class WalletTest {
@Test @Test
public void transactionsList() throws Exception { public void transactionsList() throws Exception {
// Check the wallet can give us an ordered list of all received transactions. // Check the wallet can give us an ordered list of all received transactions.
long time = System.currentTimeMillis() / 1000; Utils.rollMockClock(0);
// Receive a coin. // Receive a coin.
Transaction tx1 = createFakeTx(params, Utils.toNanoCoins(1, 0), myAddress); Transaction tx1 = createFakeTx(params, Utils.toNanoCoins(1, 0), myAddress);
StoredBlock b1 = createFakeBlock(params, blockStore, time, tx1).storedBlock; StoredBlock b1 = createFakeBlock(params, blockStore, tx1).storedBlock;
wallet.receive(tx1, b1, BlockChain.NewBlockType.BEST_CHAIN); wallet.receive(tx1, b1, BlockChain.NewBlockType.BEST_CHAIN);
// Receive half a coin 10 minutes later. // Receive half a coin 10 minutes later.
time += 60 * 10; Utils.rollMockClock(60 * 10);
Transaction tx2 = createFakeTx(params, Utils.toNanoCoins(0, 5), myAddress); Transaction tx2 = createFakeTx(params, Utils.toNanoCoins(0, 5), myAddress);
StoredBlock b2 = createFakeBlock(params, blockStore, time, tx1).storedBlock; StoredBlock b2 = createFakeBlock(params, blockStore, tx1).storedBlock;
wallet.receive(tx2, b2, BlockChain.NewBlockType.BEST_CHAIN); wallet.receive(tx2, b2, BlockChain.NewBlockType.BEST_CHAIN);
// Check we got them back in order. // Check we got them back in order.
List<Transaction> transactions = wallet.getTransactionsByTime(); List<Transaction> transactions = wallet.getTransactionsByTime();
@@ -296,7 +296,8 @@ public class WalletTest {
assertEquals(1, transactions.size()); assertEquals(1, transactions.size());
assertEquals(tx2, transactions.get(0)); assertEquals(tx2, transactions.get(0));
// Create a spend. // Create a spend five minutes later.
Utils.rollMockClock(60 * 5);
Transaction tx3 = wallet.createSend(new ECKey().toAddress(params), Utils.toNanoCoins(0, 5)); Transaction tx3 = wallet.createSend(new ECKey().toAddress(params), Utils.toNanoCoins(0, 5));
// Does not appear in list yet. // Does not appear in list yet.
assertEquals(2, wallet.getTransactionsByTime().size()); assertEquals(2, wallet.getTransactionsByTime().size());