core, integration-test: migrate usage of Guava Stopwatch to java.time API

This commit is contained in:
Andreas Schildbach 2023-03-01 13:01:02 +01:00
parent 64dbdd9fcd
commit 2eb7278d04
9 changed files with 58 additions and 38 deletions

View File

@ -18,6 +18,8 @@ package org.bitcoinj.base.internal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@ -91,6 +93,20 @@ public class TimeUtils {
return currentTimeMillis() / 1000;
}
/**
* Returns the current time as an Instant, or a mocked out equivalent.
*/
public static Instant currentTime() {
return Instant.ofEpochMilli(currentTimeMillis());
}
/**
* Returns elapsed time between given start and current time as a Duration.
*/
public static Duration elapsedTime(Instant start) {
return Duration.between(start, currentTime());
}
/**
* Formats a given date+time value to an ISO 8601 string.
* @param dateTime value to format, as a Date

View File

@ -18,7 +18,6 @@
package org.bitcoinj.core;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Stopwatch;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
@ -69,6 +68,7 @@ import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.Socket;
import java.net.SocketAddress;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -1062,7 +1062,7 @@ public class PeerGroup implements TransactionBroadcaster {
checkState(!lock.isHeldByCurrentThread());
int maxPeersToDiscoverCount = this.vMaxPeersToDiscoverCount;
long peerDiscoveryTimeoutMillis = this.vPeerDiscoveryTimeoutMillis;
final Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
final List<PeerAddress> addressList = new LinkedList<>();
for (PeerDiscovery peerDiscovery : peerDiscoverers /* COW */) {
List<InetSocketAddress> addresses;
@ -1084,9 +1084,8 @@ public class PeerGroup implements TransactionBroadcaster {
registration.executor.execute(() -> registration.listener.onPeersDiscovered(peersDiscoveredSet));
}
}
watch.stop();
log.info("Peer discovery took {} and returned {} items from {} discoverers", watch, addressList.size(),
peerDiscoverers.size());
log.info("Peer discovery took {} ms and returned {} items from {} discoverers",
TimeUtils.elapsedTime(start).toMillis(), addressList.size(), peerDiscoverers.size());
return addressList.size();
}
@ -1169,7 +1168,7 @@ public class PeerGroup implements TransactionBroadcaster {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
log.info("Stopping ...");
Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
// The log output this creates can be useful.
setDownloadPeer(null);
// Blocking close of all sockets.
@ -1179,7 +1178,7 @@ public class PeerGroup implements TransactionBroadcaster {
peerDiscovery.shutdown();
}
vRunning = false;
log.info("Stopped, took {}.", watch);
log.info("Stopped, took {} ms.", TimeUtils.elapsedTime(start).toMillis());
} catch (Throwable e) {
log.error("Exception when shutting down", e); // The executor swallows exceptions :(
}
@ -1191,11 +1190,11 @@ public class PeerGroup implements TransactionBroadcaster {
/** Does a blocking stop */
public void stop() {
try {
Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
stopAsync();
log.info("Awaiting PeerGroup shutdown ...");
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
log.info("... took {}", watch);
log.info("... took {} ms", TimeUtils.elapsedTime(start).toMillis());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}

View File

@ -17,8 +17,8 @@
package org.bitcoinj.crypto;
import com.google.common.base.Stopwatch;
import com.google.protobuf.ByteString;
import org.bitcoinj.base.internal.TimeUtils;
import org.bitcoinj.wallet.Protos;
import org.bitcoinj.wallet.Protos.ScryptParameters;
import org.bitcoinj.wallet.Protos.Wallet.EncryptionType;
@ -34,6 +34,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.Arrays;
import java.util.Objects;
@ -151,10 +152,9 @@ public class KeyCrypterScrypt implements KeyCrypter {
log.warn("You are using a ScryptParameters with no salt. Your encryption may be vulnerable to a dictionary attack.");
}
final Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
byte[] keyBytes = SCrypt.generate(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH);
watch.stop();
log.info("Deriving key took {} for {}.", watch, scryptParametersString());
log.info("Deriving key took {} ms for {}.", TimeUtils.elapsedTime(start).toMillis(), scryptParametersString());
return new KeyParameter(keyBytes);
} catch (Exception e) {
throw new KeyCrypterException("Could not generate key from password and salt.", e);

View File

@ -17,9 +17,9 @@
package org.bitcoinj.crypto;
import com.google.common.base.Stopwatch;
import org.bitcoinj.base.Sha256Hash;
import org.bitcoinj.base.internal.PlatformUtils;
import org.bitcoinj.base.internal.TimeUtils;
import org.bitcoinj.base.utils.StreamUtils;
import org.bitcoinj.base.internal.InternalUtils;
import org.slf4j.Logger;
@ -32,6 +32,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -136,10 +137,9 @@ public class MnemonicCode {
String pass = InternalUtils.SPACE_JOINER.join(words);
String salt = "mnemonic" + passphrase;
final Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
byte[] seed = PBKDF2SHA512.derive(pass, salt, PBKDF2_ROUNDS, 64);
watch.stop();
log.info("PBKDF2 took {}", watch);
log.info("PBKDF2 took {} ms", TimeUtils.elapsedTime(start).toMillis());
return seed;
}

View File

@ -17,8 +17,8 @@
package org.bitcoinj.params;
import com.google.common.base.Stopwatch;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.internal.TimeUtils;
import org.bitcoinj.base.utils.ByteUtils;
import org.bitcoinj.core.BitcoinSerializer;
import org.bitcoinj.core.Block;
@ -36,6 +36,10 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalUnit;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkState;
@ -174,7 +178,7 @@ public abstract class BitcoinNetworkParams extends NetworkParameters {
// We need to find a block far back in the chain. It's OK that this is expensive because it only occurs every
// two weeks after the initial block chain download.
final Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
Sha256Hash hash = prev.getHash();
StoredBlock cursor = null;
final int interval = this.getInterval();
@ -189,9 +193,9 @@ public abstract class BitcoinNetworkParams extends NetworkParameters {
}
checkState(cursor != null && isDifficultyTransitionPoint(cursor.getHeight() - 1),
"Didn't arrive at a transition point.");
watch.stop();
if (watch.elapsed(TimeUnit.MILLISECONDS) > 50)
log.info("Difficulty transition traversal took {}", watch);
Duration elapsed = TimeUtils.elapsedTime(start);
if (elapsed.toMillis() > 50)
log.info("Difficulty transition traversal took {} ms", elapsed.toMillis());
Block blockIntervalAgo = cursor.getHeader();
int timespan = (int) (prev.getTimeSeconds() - blockIntervalAgo.getTimeSeconds());

View File

@ -17,7 +17,6 @@
package org.bitcoinj.wallet;
import com.google.common.base.MoreObjects;
import com.google.common.base.Stopwatch;
import com.google.protobuf.ByteString;
import org.bitcoinj.base.Network;
import org.bitcoinj.base.ScriptType;
@ -50,6 +49,7 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@ -1242,13 +1242,12 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
log.info("{} keys needed for {} = {} issued + {} lookahead size + {} lookahead threshold - {} num children",
limit, parent.getPathAsString(), issued, lookaheadSize, lookaheadThreshold, numChildren);
final Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
List<DeterministicKey> result = HDKeyDerivation.generate(parent, numChildren)
.limit(limit)
.map(DeterministicKey::dropPrivateBytes)
.collect(StreamUtils.toUnmodifiableList());
watch.stop();
log.info("Took {}", watch);
log.info("Took {} ms", TimeUtils.elapsedTime(start).toMillis());
return result;
}

View File

@ -17,7 +17,6 @@
package org.bitcoinj.wallet;
import com.google.common.base.Stopwatch;
import org.bitcoinj.base.internal.TimeUtils;
import org.bitcoinj.utils.ContextPropagatingThreadFactory;
import org.slf4j.Logger;
@ -27,6 +26,9 @@ import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Time;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledThreadPoolExecutor;
@ -130,7 +132,7 @@ public class WalletFiles {
}
private void saveNowInternal() throws IOException {
final Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
File directory = file.getAbsoluteFile().getParentFile();
if (!directory.exists()) {
throw new FileNotFoundException(directory.getPath() + " (wallet directory not found)");
@ -142,8 +144,7 @@ public class WalletFiles {
wallet.saveToFile(temp, file);
if (listener != null)
listener.onAfterAutoSave(file);
watch.stop();
log.info("Save completed in {}", watch);
log.info("Save completed in {} ms", TimeUtils.elapsedTime(start).toMillis());
}
/** Queues up a save in the background. Useful for not very important wallet changes. */

View File

@ -17,7 +17,6 @@
package org.bitcoinj.store;
import com.google.common.base.Stopwatch;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.ScriptType;
import org.bitcoinj.base.Address;
@ -37,6 +36,8 @@ import org.junit.Test;
import java.io.File;
import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
@ -146,7 +147,7 @@ public class SPVBlockStoreTest {
final int ITERATIONS = 100000;
final long THRESHOLD_MS = 2000;
SPVBlockStore store = new SPVBlockStore(TESTNET, blockStoreFile);
Stopwatch watch = Stopwatch.createStarted();
Instant start = TimeUtils.currentTime();
for (int i = 0; i < ITERATIONS; i++) {
// Using i as the nonce so that the block hashes are different.
Block block = new Block(TESTNET, 0, Sha256Hash.ZERO_HASH, Sha256Hash.ZERO_HASH, 0, 0, i,
@ -155,8 +156,9 @@ public class SPVBlockStoreTest {
store.put(b);
store.setChainHead(b);
}
assertTrue("took " + watch + " for " + ITERATIONS + " iterations",
watch.elapsed(TimeUnit.MILLISECONDS) < THRESHOLD_MS);
Duration elapsed = TimeUtils.elapsedTime(start);
assertTrue("took " + elapsed.toMillis() + " ms for " + ITERATIONS + " iterations",
elapsed.toMillis() < THRESHOLD_MS);
store.close();
}

View File

@ -17,7 +17,6 @@
package org.bitcoinj.core;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import org.bitcoinj.base.Address;
import org.bitcoinj.base.Coin;
@ -48,6 +47,7 @@ import java.net.BindException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -532,7 +532,7 @@ public class PeerGroupTest extends TestWithPeerGroup {
peerGroup.addConnectedEventListener(Threading.SAME_THREAD, (peer, peerCount) -> peerConnectedFuture.complete(null));
peerGroup.addDisconnectedEventListener(Threading.SAME_THREAD, (peer, peerCount) -> peerDisconnectedFuture.complete(null));
// connect to peer but don't do handshake
final Stopwatch watch = Stopwatch.createStarted(); // before connection so we don't get elapsed < timeout
Instant start = TimeUtils.currentTime(); // before connection so we don't get elapsed < timeout
connectPeerWithoutVersionExchange(0);
// wait for disconnect (plus a bit more, in case test server is overloaded)
try {
@ -541,9 +541,8 @@ public class PeerGroupTest extends TestWithPeerGroup {
// the checks below suffice for this case too
}
// check things after disconnect
watch.stop();
assertFalse(peerConnectedFuture.isDone()); // should never have connected
assertTrue(watch.elapsed(TimeUnit.MILLISECONDS) >= timeout); // should not disconnect before timeout
assertTrue(TimeUtils.elapsedTime(start).toMillis() >= timeout); // should not disconnect before timeout
assertTrue(peerDisconnectedFuture.isDone()); // but should disconnect eventually
}