mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-05-15 13:02:20 -04:00
use tomp2p master branch
This commit is contained in:
parent
79a52a6e38
commit
d943ee0918
14 changed files with 40 additions and 952 deletions
16
README.md
16
README.md
|
@ -1,26 +1,26 @@
|
||||||
# bitsquare.io
|
# bitsquare.io
|
||||||
|
|
||||||
Bitsquare is a P2P Fiat-BTC Exchange, extensible to a generic P2P trading platform (include commodities and cryptocurrencies)
|
Bitsquare is a P2P Fiat-BTC Exchange.
|
||||||
|
|
||||||
The project use Java 8 and Maven.
|
The project use Java 8 and Maven.
|
||||||
We use the bitcoinj library and TomP2P for DHT and messaging.
|
We use the bitcoinj library and TomP2P for DHT and direct messaging.
|
||||||
|
|
||||||
|
For local testing it is best to use the regtest mode from Bitcoin qt clients.
|
||||||
If you want to use the RegTest mode you need to set regtest=1 in the bitcoin.config file inside the bitcoin data directory (https://en.bitcoin.it/wiki/Running_Bitcoin).
|
If you want to use the RegTest mode you need to set regtest=1 in the bitcoin.config file inside the bitcoin data directory (https://en.bitcoin.it/wiki/Running_Bitcoin).
|
||||||
Then you can generate coins on demand with the Bitcoin qt client with that command in the console: setgenerate true 101 (101 only for the first start because the coin maturity of 100 blocks).
|
Then you can generate coins on demand with the Bitcoin qt client with that command in the console: setgenerate true 101 (101 only for the first start because the coin maturity of 100 blocks).
|
||||||
See: https://bitcoinj.github.io/testing
|
More information about how to use regtest mode can be found here: https://bitcoinj.github.io/testing
|
||||||
|
Take care if you have real bitcoin in your Bitcoin qt wallet (backup and copy first your data directory).
|
||||||
You can change the network mode in the guice module: BitSquareModule.java
|
You can change the network mode in the guice module: BitSquareModule.java
|
||||||
|
Testnet should also work, but was not tested a while now as for developing regtest is much more convenient.
|
||||||
|
Please don't use main net with real money, as the software is under heavy development and you can easily lose your funds.
|
||||||
|
|
||||||
We use a fork of the actual TomP2P master branch: https://github.com/ManfredKarrer/TomP2P
|
We use a fork of the actual TomP2P master branch: https://github.com/bitsquare/TomP2P
|
||||||
You need to check that out as well and deploy it to the local maven repository:
|
You need to check that out as well and deploy it to the local maven repository:
|
||||||
mvn clean install -DskipTests
|
mvn clean install -DskipTests
|
||||||
|
|
||||||
|
|
||||||
### Resources:
|
### Resources:
|
||||||
* Web: http://bitsquare.io
|
* Web: http://bitsquare.io
|
||||||
* Whitepaper: https://docs.google.com/document/d/1d3EiWZdaM89-P6MVhS53unXv2-pDpSFsN3W4kCGXKgY/edit?pli=1
|
|
||||||
* Overview: http://bitsquare.io/images/overview.png
|
|
||||||
* Discussion: https://bitcointalk.org/index.php?topic=647457
|
|
||||||
* Video of POC prototype: https://www.youtube.com/watch?v=ByfnzJzi0bo
|
|
||||||
|
|
||||||
|
|
||||||
### Screenshots of basic the use cases:
|
### Screenshots of basic the use cases:
|
||||||
|
|
52
pom.xml
52
pom.xml
|
@ -6,23 +6,14 @@
|
||||||
|
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<artifactId>bitsquare</artifactId>
|
<artifactId>bitsquare</artifactId>
|
||||||
<version>0.01-SNAPSHOT</version>
|
<version>0.1-SNAPSHOT</version>
|
||||||
<name>BitSquare</name>
|
<name>BitSquare</name>
|
||||||
<description>A P2P Fiat-Bitcoin Exchange</description>
|
<description>The P2P Fiat-Bitcoin Exchange</description>
|
||||||
<url>https://www.bitsquare.io</url>
|
<url>http://www.bitsquare.io</url>
|
||||||
|
|
||||||
<organization>
|
<organization>
|
||||||
<name>bitsquare.io</name>
|
<name>bitsquare.io</name>
|
||||||
</organization>
|
</organization>
|
||||||
<!--
|
|
||||||
<parent>
|
|
||||||
<groupId>com.google</groupId>
|
|
||||||
<artifactId>bitcoinj-parent</artifactId>
|
|
||||||
<version>0.12-SNAPSHOT</version>
|
|
||||||
<relativePath>libs/bitcoinj/pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
<license>
|
<license>
|
||||||
|
@ -53,13 +44,11 @@
|
||||||
<snapshots/>
|
<snapshots/>
|
||||||
<url>https://oss.sonatype.org/content/groups/public</url>
|
<url>https://oss.sonatype.org/content/groups/public</url>
|
||||||
</repository>
|
</repository>
|
||||||
<!-- bitcoin-j repo -->
|
|
||||||
<repository>
|
<repository>
|
||||||
<id>bitcoinj-release</id>
|
<id>bitcoinj-release</id>
|
||||||
<releases/>
|
<releases/>
|
||||||
<url>http://distribution.bitcoinj.googlecode.com/git/releases</url>
|
<url>http://distribution.bitcoinj.googlecode.com/git/releases</url>
|
||||||
</repository>
|
</repository>
|
||||||
<!-- zxing repo -->
|
|
||||||
<repository>
|
<repository>
|
||||||
<id>mvn-adamgent</id>
|
<id>mvn-adamgent</id>
|
||||||
<url>http://mvn-adamgent.googlecode.com/svn/maven/release</url>
|
<url>http://mvn-adamgent.googlecode.com/svn/maven/release</url>
|
||||||
|
@ -73,7 +62,6 @@
|
||||||
|
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<!-- TODO Maven build not working yet... -->
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>bitsquare</finalName>
|
<finalName>bitsquare</finalName>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -113,13 +101,11 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.twdata.maven</groupId>
|
<groupId>org.twdata.maven</groupId>
|
||||||
<artifactId>mojo-executor</artifactId>
|
<artifactId>mojo-executor</artifactId>
|
||||||
<version>2.1.0</version>
|
<version>2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,13 +117,11 @@
|
||||||
<version>0.11.3</version>
|
<version>0.11.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.tomp2p</groupId>
|
<groupId>net.tomp2p</groupId>
|
||||||
<artifactId>tomp2p-all</artifactId>
|
<artifactId>tomp2p-all</artifactId>
|
||||||
<version>5.0-Alpha24-SNAPSHOT</version>
|
<version>5.0-Alpha24-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
-->
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
|
@ -151,13 +135,7 @@
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>1.7.7</version>
|
<version>1.7.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-simple</artifactId>
|
|
||||||
<version>1.7.7</version>
|
|
||||||
</dependency>
|
|
||||||
-->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-core</artifactId>
|
<artifactId>logback-core</artifactId>
|
||||||
|
@ -170,7 +148,6 @@
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.inject</groupId>
|
<groupId>com.google.inject</groupId>
|
||||||
<artifactId>guice</artifactId>
|
<artifactId>guice</artifactId>
|
||||||
|
@ -219,14 +196,6 @@
|
||||||
<artifactId>jcip-annotations</artifactId>
|
<artifactId>jcip-annotations</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.sf.proguard</groupId>
|
|
||||||
<artifactId>proguard</artifactId>
|
|
||||||
<version>4.4</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains</groupId>
|
<groupId>org.jetbrains</groupId>
|
||||||
|
@ -235,17 +204,6 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<reporting>
|
|
||||||
<plugins>
|
|
||||||
<!-- Generate cross-referenced HTML source code listing -->
|
|
||||||
<!-- <plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jxr-plugin</artifactId>
|
|
||||||
<version>2.1</version>
|
|
||||||
</plugin> -->
|
|
||||||
</plugins>
|
|
||||||
</reporting>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class P2PNode
|
||||||
useDiscStorage(useDiskStorage);
|
useDiscStorage(useDiskStorage);
|
||||||
setupTimerForIPCheck();
|
setupTimerForIPCheck();
|
||||||
|
|
||||||
FutureCallback<PeerDHT> localCallback = new FutureCallback<PeerDHT>()
|
/* FutureCallback<PeerDHT> localCallback = new FutureCallback<PeerDHT>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@Nullable PeerDHT result)
|
public void onSuccess(@Nullable PeerDHT result)
|
||||||
|
@ -126,13 +126,18 @@ public class P2PNode
|
||||||
log.error(t.toString());
|
log.error(t.toString());
|
||||||
callback.onFailure(t);
|
callback.onFailure(t);
|
||||||
}
|
}
|
||||||
};
|
}; */
|
||||||
|
|
||||||
bootstrapToLocalhostThread = runBootstrapThread(localCallback, new SeedNodeAddress(defaultStaticSeedNodeAddresses));
|
ListenableFuture<PeerDHT> bootstrapComplete = bootstrap(new SeedNodeAddress(defaultStaticSeedNodeAddresses));
|
||||||
bootstrapToServerThread = runBootstrapThread(localCallback, new SeedNodeAddress(SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN));
|
Futures.addCallback(bootstrapComplete, callback);
|
||||||
|
|
||||||
|
// bootstrapToLocalhostThread = runBootstrapThread(localCallback, new SeedNodeAddress(defaultStaticSeedNodeAddresses));
|
||||||
|
// bootstrapToServerThread = runBootstrapThread(localCallback, new SeedNodeAddress(SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bootstrapThreadCompleted()
|
// TODO: start multiple threads for bootstrapping, so we can get it done faster.
|
||||||
|
|
||||||
|
/* public void bootstrapThreadCompleted()
|
||||||
{
|
{
|
||||||
if (bootstrapToLocalhostThread != null)
|
if (bootstrapToLocalhostThread != null)
|
||||||
bootstrapToLocalhostThread.interrupt();
|
bootstrapToLocalhostThread.interrupt();
|
||||||
|
@ -155,7 +160,7 @@ public class P2PNode
|
||||||
});
|
});
|
||||||
bootstrapThread.start();
|
bootstrapThread.start();
|
||||||
return bootstrapThread;
|
return bootstrapThread;
|
||||||
}
|
} */
|
||||||
|
|
||||||
public void shutDown()
|
public void shutDown()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
package lighthouse.protocol;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class LHUtils
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LHUtils.class);
|
|
||||||
|
|
||||||
public static List<Path> listDir(Path dir) throws IOException
|
|
||||||
{
|
|
||||||
List<Path> contents = new LinkedList<>();
|
|
||||||
try (Stream<Path> list = Files.list(dir))
|
|
||||||
{
|
|
||||||
list.forEach(contents::add);
|
|
||||||
}
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
//region Generic Java 8 enhancements
|
|
||||||
public interface UncheckedRun<T>
|
|
||||||
{
|
|
||||||
public T run() throws Throwable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface UncheckedRunnable
|
|
||||||
{
|
|
||||||
public void run() throws Throwable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T unchecked(UncheckedRun<T> run)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return run.run();
|
|
||||||
} catch (Throwable throwable)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(throwable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void uncheck(UncheckedRunnable run)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
run.run();
|
|
||||||
} catch (Throwable throwable)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(throwable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ignoreAndLog(UncheckedRunnable runnable)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
runnable.run();
|
|
||||||
} catch (Throwable t)
|
|
||||||
{
|
|
||||||
log.error("Ignoring error", t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T ignoredAndLogged(UncheckedRun<T> runnable)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return runnable.run();
|
|
||||||
} catch (Throwable t)
|
|
||||||
{
|
|
||||||
log.error("Ignoring error", t);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T, E extends Throwable> T checkedGet(Future<T> future) throws E
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return future.get();
|
|
||||||
} catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (ExecutionException e)
|
|
||||||
{
|
|
||||||
throw (E) e.getCause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean didThrow(UncheckedRun run)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
run.run();
|
|
||||||
return false;
|
|
||||||
} catch (Throwable throwable)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean didThrow(UncheckedRunnable run)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
run.run();
|
|
||||||
return false;
|
|
||||||
} catch (Throwable throwable)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T stopwatched(String description, UncheckedRun<T> run)
|
|
||||||
{
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
T result = unchecked(run::run);
|
|
||||||
log.info("{}: {}ms", description, System.currentTimeMillis() - now);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void stopwatch(String description, UncheckedRunnable run)
|
|
||||||
{
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
uncheck(run::run);
|
|
||||||
log.info("{}: {}ms", description, System.currentTimeMillis() - now);
|
|
||||||
}
|
|
||||||
|
|
||||||
//endregion
|
|
||||||
}
|
|
|
@ -1,171 +0,0 @@
|
||||||
package lighthouse.threading;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.Uninterruptibles;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import lighthouse.protocol.LHUtils;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An extended executor interface that supports thread affinity assertions and short circuiting.
|
|
||||||
*/
|
|
||||||
public interface AffinityExecutor extends Executor
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns true if the current thread is equal to the thread this executor is backed by.
|
|
||||||
*/
|
|
||||||
public boolean isOnThread();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throws an IllegalStateException if the current thread is equal to the thread this executor is backed by.
|
|
||||||
*/
|
|
||||||
public void checkOnThread();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If isOnThread() then runnable is invoked immediately, otherwise the closure is queued onto the backing thread.
|
|
||||||
*/
|
|
||||||
public void executeASAP(LHUtils.UncheckedRunnable runnable);
|
|
||||||
|
|
||||||
public abstract static class BaseAffinityExecutor implements AffinityExecutor
|
|
||||||
{
|
|
||||||
protected final Thread.UncaughtExceptionHandler exceptionHandler;
|
|
||||||
|
|
||||||
protected BaseAffinityExecutor()
|
|
||||||
{
|
|
||||||
exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public abstract boolean isOnThread();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkOnThread()
|
|
||||||
{
|
|
||||||
checkState(isOnThread(), "On wrong thread: %s", Thread.currentThread());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void executeASAP(LHUtils.UncheckedRunnable runnable)
|
|
||||||
{
|
|
||||||
final Runnable command = () -> {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
runnable.run();
|
|
||||||
} catch (Throwable throwable)
|
|
||||||
{
|
|
||||||
exceptionHandler.uncaughtException(Thread.currentThread(), throwable);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (isOnThread())
|
|
||||||
command.run();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
execute(command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must comply with the Executor definition w.r.t. exceptions here.
|
|
||||||
@Override
|
|
||||||
public abstract void execute(Runnable command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AffinityExecutor UI_THREAD = new BaseAffinityExecutor()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean isOnThread()
|
|
||||||
{
|
|
||||||
return Platform.isFxApplicationThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable command)
|
|
||||||
{
|
|
||||||
Platform.runLater(command);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static AffinityExecutor SAME_THREAD = new BaseAffinityExecutor()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean isOnThread()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable command)
|
|
||||||
{
|
|
||||||
command.run();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static class ServiceAffinityExecutor extends BaseAffinityExecutor
|
|
||||||
{
|
|
||||||
protected AtomicReference<Thread> whichThread = new AtomicReference<>(null);
|
|
||||||
private final Thread.UncaughtExceptionHandler handler = Thread.currentThread().getUncaughtExceptionHandler();
|
|
||||||
public final ScheduledExecutorService service;
|
|
||||||
|
|
||||||
public ServiceAffinityExecutor(String threadName)
|
|
||||||
{
|
|
||||||
service = Executors.newSingleThreadScheduledExecutor(runnable -> {
|
|
||||||
Thread thread = new Thread(runnable);
|
|
||||||
thread.setDaemon(true);
|
|
||||||
thread.setName(threadName);
|
|
||||||
thread.setUncaughtExceptionHandler(handler);
|
|
||||||
whichThread.set(thread);
|
|
||||||
return thread;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOnThread()
|
|
||||||
{
|
|
||||||
return Thread.currentThread() == whichThread.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable command)
|
|
||||||
{
|
|
||||||
service.execute(command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An executor useful for unit tests: allows the current thread to block until a command arrives from another
|
|
||||||
* thread, which is then executed. Inbound closures/commands stack up until they are cleared by looping.
|
|
||||||
*/
|
|
||||||
public static class Gate extends BaseAffinityExecutor
|
|
||||||
{
|
|
||||||
private final Thread thisThread = Thread.currentThread();
|
|
||||||
private final LinkedBlockingQueue<Runnable> commandQ = new LinkedBlockingQueue<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOnThread()
|
|
||||||
{
|
|
||||||
return Thread.currentThread() == thisThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable command)
|
|
||||||
{
|
|
||||||
Uninterruptibles.putUninterruptibly(commandQ, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void waitAndRun()
|
|
||||||
{
|
|
||||||
final Runnable runnable = Uninterruptibles.takeUninterruptibly(commandQ);
|
|
||||||
System.err.println("Gate running " + runnable);
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTaskQueueSize()
|
|
||||||
{
|
|
||||||
return commandQ.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
package lighthouse.threading;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import javafx.collections.ListChangeListener;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import javafx.collections.ObservableListBase;
|
|
||||||
import javafx.collections.WeakListChangeListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This list is created by dynamically concatenating all the source lists together.
|
|
||||||
*/
|
|
||||||
public class ConcatenatingList<T> extends ObservableListBase<T> implements ObservableList<T>
|
|
||||||
{
|
|
||||||
private List<ObservableList<T>> sources = new ArrayList<>();
|
|
||||||
private ListChangeListener<T> listener = this::sourceChanged;
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
public ConcatenatingList(ObservableList<T>... source)
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
for (ObservableList<T> s : source)
|
|
||||||
{
|
|
||||||
sources.add(s);
|
|
||||||
s.addListener(new WeakListChangeListener<T>(listener));
|
|
||||||
}
|
|
||||||
if (sources.isEmpty())
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int calculateOffset(ObservableList<? extends T> source)
|
|
||||||
{
|
|
||||||
int cursor = 0;
|
|
||||||
for (ObservableList<T> ts : sources)
|
|
||||||
{
|
|
||||||
if (ts == source) return cursor;
|
|
||||||
cursor += ts.size();
|
|
||||||
}
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sourceChanged(ListChangeListener.Change<? extends T> c)
|
|
||||||
{
|
|
||||||
ObservableList<? extends T> source = c.getList();
|
|
||||||
int offset = calculateOffset(source);
|
|
||||||
beginChange();
|
|
||||||
while (c.next())
|
|
||||||
{
|
|
||||||
if (c.wasPermutated())
|
|
||||||
{
|
|
||||||
int[] perm = new int[c.getTo() - c.getFrom()];
|
|
||||||
for (int i = c.getFrom(); i < c.getTo(); i++)
|
|
||||||
perm[i - c.getFrom()] = c.getPermutation(i) + offset;
|
|
||||||
nextPermutation(c.getFrom() + offset, c.getTo() + offset, perm);
|
|
||||||
}
|
|
||||||
else if (c.wasUpdated())
|
|
||||||
{
|
|
||||||
for (int i = c.getFrom(); i < c.getTo(); i++)
|
|
||||||
{
|
|
||||||
nextUpdate(i + offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (c.wasRemoved())
|
|
||||||
{
|
|
||||||
// Removed should come first to properly handle replacements, then add.
|
|
||||||
nextRemove(c.getFrom() + offset, c.getRemoved());
|
|
||||||
}
|
|
||||||
if (c.wasAdded())
|
|
||||||
{
|
|
||||||
nextAdd(c.getFrom() + offset, c.getTo() + offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T get(int index)
|
|
||||||
{
|
|
||||||
for (ObservableList<T> source : sources)
|
|
||||||
{
|
|
||||||
if (index < source.size())
|
|
||||||
{
|
|
||||||
return source.get(index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index -= source.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size()
|
|
||||||
{
|
|
||||||
return sources.stream().mapToInt(List::size).sum();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
package lighthouse.threading;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javafx.collections.ListChangeListener;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import javafx.collections.transformation.TransformationList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps elements of type F to E with change listeners working as expected.
|
|
||||||
*/
|
|
||||||
public class MappedList<E, F> extends TransformationList<E, F>
|
|
||||||
{
|
|
||||||
private final Function<F, E> mapper;
|
|
||||||
private final ArrayList<E> mapped;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new MappedList list wrapped around the source list.
|
|
||||||
* Each element will have the given function applied to it, such that the list is cast through the mapper.
|
|
||||||
*/
|
|
||||||
public MappedList(ObservableList<? extends F> source, Function<F, E> mapper)
|
|
||||||
{
|
|
||||||
super(source);
|
|
||||||
this.mapper = mapper;
|
|
||||||
this.mapped = new ArrayList<>(source.size());
|
|
||||||
mapAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mapAll()
|
|
||||||
{
|
|
||||||
mapped.clear();
|
|
||||||
for (F val : getSource())
|
|
||||||
mapped.add(mapper.apply(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void sourceChanged(ListChangeListener.Change<? extends F> c)
|
|
||||||
{
|
|
||||||
// Is all this stuff right for every case? Probably it doesn't matter for this app.
|
|
||||||
beginChange();
|
|
||||||
while (c.next())
|
|
||||||
{
|
|
||||||
if (c.wasPermutated())
|
|
||||||
{
|
|
||||||
int[] perm = new int[c.getTo() - c.getFrom()];
|
|
||||||
for (int i = c.getFrom(); i < c.getTo(); i++)
|
|
||||||
perm[i - c.getFrom()] = c.getPermutation(i);
|
|
||||||
nextPermutation(c.getFrom(), c.getTo(), perm);
|
|
||||||
}
|
|
||||||
else if (c.wasUpdated())
|
|
||||||
{
|
|
||||||
for (int i = c.getFrom(); i < c.getTo(); i++)
|
|
||||||
{
|
|
||||||
remapIndex(i);
|
|
||||||
nextUpdate(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (c.wasRemoved())
|
|
||||||
{
|
|
||||||
// Removed should come first to properly handle replacements, then add.
|
|
||||||
List<E> removed = mapped.subList(c.getFrom(), c.getFrom() + c.getRemovedSize());
|
|
||||||
ArrayList<E> duped = new ArrayList<>(removed);
|
|
||||||
removed.clear();
|
|
||||||
nextRemove(c.getFrom(), duped);
|
|
||||||
}
|
|
||||||
if (c.wasAdded())
|
|
||||||
{
|
|
||||||
for (int i = c.getFrom(); i < c.getTo(); i++)
|
|
||||||
{
|
|
||||||
mapped.addAll(c.getFrom(), c.getAddedSubList().stream().map(mapper).collect(Collectors.toList()));
|
|
||||||
remapIndex(i);
|
|
||||||
}
|
|
||||||
nextAdd(c.getFrom(), c.getTo());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void remapIndex(int i)
|
|
||||||
{
|
|
||||||
if (i >= mapped.size())
|
|
||||||
{
|
|
||||||
for (int j = mapped.size(); j <= i; j++)
|
|
||||||
{
|
|
||||||
mapped.add(mapper.apply(getSource().get(j)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mapped.set(i, mapper.apply(getSource().get(i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourceIndex(int index)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public E get(int index)
|
|
||||||
{
|
|
||||||
return mapped.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size()
|
|
||||||
{
|
|
||||||
return mapped.size();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
package lighthouse.threading;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import javafx.beans.InvalidationListener;
|
|
||||||
import javafx.beans.Observable;
|
|
||||||
import javafx.collections.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An attempt to make multi-threading and observable/reactive UI programming work together inside JavaFX without too
|
|
||||||
* many headaches. This class allows you to register change listeners on the target Observable which will be
|
|
||||||
* run with the given {@link java.util.concurrent.Executor}. In this way an observable collection which is updated by
|
|
||||||
* one thread can be observed from another thread without needing to use explicit locks or explicit marshalling.
|
|
||||||
*/
|
|
||||||
public class MarshallingObservers
|
|
||||||
{
|
|
||||||
public static InvalidationListener addListener(Observable observable, InvalidationListener listener, Executor executor)
|
|
||||||
{
|
|
||||||
InvalidationListener l = x -> executor.execute(() -> listener.invalidated(x));
|
|
||||||
observable.addListener(l);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> ListChangeListener<T> addListener(ObservableList<T> observable, ListChangeListener<T> listener, Executor executor)
|
|
||||||
{
|
|
||||||
ListChangeListener<T> l = (ListChangeListener.Change<? extends T> c) -> executor.execute(() -> listener.onChanged(c));
|
|
||||||
observable.addListener(l);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> SetChangeListener<T> addListener(ObservableSet<T> observable, SetChangeListener<T> listener, Executor executor)
|
|
||||||
{
|
|
||||||
SetChangeListener<T> l = (SetChangeListener.Change<? extends T> c) -> executor.execute(() -> listener.onChanged(c));
|
|
||||||
observable.addListener(l);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> MapChangeListener<K, V> addListener(ObservableMap<K, V> observable, MapChangeListener<K, V> listener, Executor executor)
|
|
||||||
{
|
|
||||||
MapChangeListener<K, V> l = (MapChangeListener.Change<? extends K, ? extends V> c) -> executor.execute(() -> listener.onChanged(c));
|
|
||||||
observable.addListener(l);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,195 +0,0 @@
|
||||||
package lighthouse.threading;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import javafx.beans.WeakListener;
|
|
||||||
import javafx.collections.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility functions that mirror changes from one list into another list. JavaFX already provides this functionality
|
|
||||||
* of course under the name "content binding"; a mirror is a content binding that relays changes into other threads
|
|
||||||
* first. Thus you can have an ObservableList which is updated in one thread, but still bound to directly in the UI
|
|
||||||
* thread, without needing to worry about cross-thread interference.
|
|
||||||
*/
|
|
||||||
public class ObservableMirrors
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates an unmodifiable list that asynchronously follows changes in mirrored, with changes applied using
|
|
||||||
* the given executor. This should only be called on the thread that owns the list to be mirrored, as the contents
|
|
||||||
* will be read.
|
|
||||||
*/
|
|
||||||
public static <T> ObservableList<T> mirrorList(ObservableList<T> mirrored, AffinityExecutor runChangesIn)
|
|
||||||
{
|
|
||||||
ObservableList<T> result = FXCollections.observableArrayList();
|
|
||||||
result.setAll(mirrored);
|
|
||||||
mirrored.addListener(new ListMirror<T>(result, runChangesIn));
|
|
||||||
return FXCollections.unmodifiableObservableList(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ListMirror<E> implements ListChangeListener<E>, WeakListener
|
|
||||||
{
|
|
||||||
private final WeakReference<ObservableList<E>> targetList;
|
|
||||||
private final AffinityExecutor runChangesIn;
|
|
||||||
|
|
||||||
public ListMirror(ObservableList<E> list, AffinityExecutor runChangesIn)
|
|
||||||
{
|
|
||||||
this.targetList = new WeakReference<>(list);
|
|
||||||
this.runChangesIn = runChangesIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onChanged(Change<? extends E> change)
|
|
||||||
{
|
|
||||||
final List<E> list = targetList.get();
|
|
||||||
if (list == null)
|
|
||||||
{
|
|
||||||
change.getList().removeListener(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we're already in the right thread this will just run the change immediately, as per normal.
|
|
||||||
runChangesIn.executeASAP(() -> {
|
|
||||||
while (change.next())
|
|
||||||
{
|
|
||||||
if (change.wasPermutated())
|
|
||||||
{
|
|
||||||
list.subList(change.getFrom(), change.getTo()).clear();
|
|
||||||
list.addAll(change.getFrom(), change.getList().subList(change.getFrom(), change.getTo()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (change.wasRemoved())
|
|
||||||
{
|
|
||||||
list.subList(change.getFrom(), change.getFrom() + change.getRemovedSize()).clear();
|
|
||||||
}
|
|
||||||
if (change.wasAdded())
|
|
||||||
{
|
|
||||||
list.addAll(change.getFrom(), change.getAddedSubList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean wasGarbageCollected()
|
|
||||||
{
|
|
||||||
return targetList.get() == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we really need these?
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
final List<E> list = targetList.get();
|
|
||||||
return (list == null) ? 0 : list.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (this == obj)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<E> list1 = targetList.get();
|
|
||||||
if (list1 == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj instanceof ListMirror)
|
|
||||||
{
|
|
||||||
final ListMirror<?> other = (ListMirror<?>) obj;
|
|
||||||
final List<?> list2 = other.targetList.get();
|
|
||||||
return list1 == list2;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an unmodifiable list that asynchronously follows changes in mirrored, with changes applied using
|
|
||||||
* the given executor. This should only be called on the thread that owns the list to be mirrored, as the contents
|
|
||||||
* will be read.
|
|
||||||
*/
|
|
||||||
public static <T> ObservableSet<T> mirrorSet(ObservableSet<T> mirrored, AffinityExecutor runChangesIn)
|
|
||||||
{
|
|
||||||
@SuppressWarnings("unchecked") ObservableSet<T> result = FXCollections.observableSet();
|
|
||||||
result.addAll(mirrored);
|
|
||||||
mirrored.addListener(new SetMirror<T>(result, runChangesIn));
|
|
||||||
return FXCollections.unmodifiableObservableSet(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class SetMirror<E> implements SetChangeListener<E>, WeakListener
|
|
||||||
{
|
|
||||||
private final WeakReference<ObservableSet<E>> targetSet;
|
|
||||||
private final AffinityExecutor runChangesIn;
|
|
||||||
|
|
||||||
public SetMirror(ObservableSet<E> set, AffinityExecutor runChangesIn)
|
|
||||||
{
|
|
||||||
this.targetSet = new WeakReference<>(set);
|
|
||||||
this.runChangesIn = runChangesIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onChanged(final Change<? extends E> change)
|
|
||||||
{
|
|
||||||
final ObservableSet<E> set = targetSet.get();
|
|
||||||
if (set == null)
|
|
||||||
{
|
|
||||||
change.getSet().removeListener(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we're already in the right thread this will just run the change immediately, as per normal.
|
|
||||||
runChangesIn.executeASAP(() -> {
|
|
||||||
if (change.wasAdded())
|
|
||||||
set.add(change.getElementAdded());
|
|
||||||
if (change.wasRemoved())
|
|
||||||
set.remove(change.getElementRemoved());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean wasGarbageCollected()
|
|
||||||
{
|
|
||||||
return targetSet.get() == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
final ObservableSet<E> set = targetSet.get();
|
|
||||||
return (set == null) ? 0 : set.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (this == obj)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Set<E> set1 = targetSet.get();
|
|
||||||
if (set1 == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj instanceof SetMirror)
|
|
||||||
{
|
|
||||||
final SetMirror<?> other = (SetMirror<?>) obj;
|
|
||||||
final Set<?> list2 = other.targetSet.get();
|
|
||||||
return set1 == list2;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@ package io.bitsquare;
|
||||||
import io.bitsquare.btc.BtcValidatorTest;
|
import io.bitsquare.btc.BtcValidatorTest;
|
||||||
import io.bitsquare.gui.util.BitSquareConverterTest;
|
import io.bitsquare.gui.util.BitSquareConverterTest;
|
||||||
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
||||||
|
import io.bitsquare.msg.P2PNodeTest;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Suite;
|
import org.junit.runners.Suite;
|
||||||
|
|
||||||
|
@ -11,6 +12,7 @@ import org.junit.runners.Suite;
|
||||||
BtcValidatorTest.class,
|
BtcValidatorTest.class,
|
||||||
BitSquareConverterTest.class,
|
BitSquareConverterTest.class,
|
||||||
BitSquareValidatorTest.class,
|
BitSquareValidatorTest.class,
|
||||||
|
P2PNodeTest.class
|
||||||
})
|
})
|
||||||
|
|
||||||
public class BitSquareTestSuite
|
public class BitSquareTestSuite
|
||||||
|
|
|
@ -17,13 +17,13 @@ public class BitSquareConverterTest
|
||||||
assertEquals(1, BitSquareConverter.stringToDouble("1.0"), 0);
|
assertEquals(1, BitSquareConverter.stringToDouble("1.0"), 0);
|
||||||
assertEquals(1, BitSquareConverter.stringToDouble("1,0"), 0);
|
assertEquals(1, BitSquareConverter.stringToDouble("1,0"), 0);
|
||||||
|
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(null), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble(null), 0);
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble(""), 0);
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble(""), 0);
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("."), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble("."), 0);
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(","), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble(","), 0);
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("a"), 0);
|
assertEquals(0, BitSquareConverter.stringToDouble("a"), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import net.tomp2p.connection.Ports;
|
||||||
import net.tomp2p.dht.FutureGet;
|
import net.tomp2p.dht.FutureGet;
|
||||||
import net.tomp2p.dht.FuturePut;
|
import net.tomp2p.dht.FuturePut;
|
||||||
import net.tomp2p.dht.FutureRemove;
|
import net.tomp2p.dht.FutureRemove;
|
||||||
|
@ -29,7 +30,7 @@ public class P2PNodeTest
|
||||||
@Test
|
@Test
|
||||||
public void testSendData() throws Exception
|
public void testSendData() throws Exception
|
||||||
{
|
{
|
||||||
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
|
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, new Ports().tcpPort());
|
||||||
PeerDHT master = peers[0];
|
PeerDHT master = peers[0];
|
||||||
PeerDHT client = peers[1];
|
PeerDHT client = peers[1];
|
||||||
PeerDHT otherPeer = peers[2];
|
PeerDHT otherPeer = peers[2];
|
||||||
|
@ -66,12 +67,14 @@ public class P2PNodeTest
|
||||||
assertTrue(futureDirect.isSuccess());
|
assertTrue(futureDirect.isSuccess());
|
||||||
// we return true from objectDataReply
|
// we return true from objectDataReply
|
||||||
assertTrue((Boolean) futureDirect.object());
|
assertTrue((Boolean) futureDirect.object());
|
||||||
|
|
||||||
|
master.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProtectedPutGet() throws Exception
|
public void testProtectedPutGet() throws Exception
|
||||||
{
|
{
|
||||||
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
|
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, new Ports().tcpPort());
|
||||||
PeerDHT master = peers[0];
|
PeerDHT master = peers[0];
|
||||||
PeerDHT client = peers[1];
|
PeerDHT client = peers[1];
|
||||||
PeerDHT otherPeer = peers[2];
|
PeerDHT otherPeer = peers[2];
|
||||||
|
@ -157,7 +160,7 @@ public class P2PNodeTest
|
||||||
@Test
|
@Test
|
||||||
public void testAddToListGetList() throws Exception
|
public void testAddToListGetList() throws Exception
|
||||||
{
|
{
|
||||||
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
|
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, new Ports().tcpPort());
|
||||||
PeerDHT master = peers[0];
|
PeerDHT master = peers[0];
|
||||||
PeerDHT client = peers[1];
|
PeerDHT client = peers[1];
|
||||||
PeerDHT otherPeer = peers[2];
|
PeerDHT otherPeer = peers[2];
|
||||||
|
@ -367,7 +370,6 @@ public class P2PNodeTest
|
||||||
assertTrue(foundData3);
|
assertTrue(foundData3);
|
||||||
assertEquals(2, futureGet.dataMap().values().size());
|
assertEquals(2, futureGet.dataMap().values().size());
|
||||||
|
|
||||||
|
|
||||||
master.shutdown();
|
master.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
package lighthouse.threading;
|
|
||||||
|
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
|
|
||||||
public class ConcatenatingListTest
|
|
||||||
{
|
|
||||||
@Test
|
|
||||||
public void basic() throws Exception
|
|
||||||
{
|
|
||||||
ObservableList<String> a = FXCollections.observableArrayList();
|
|
||||||
ObservableList<String> b = FXCollections.observableArrayList();
|
|
||||||
ConcatenatingList<String> concat = new ConcatenatingList<>(a, b);
|
|
||||||
assertEquals(0, concat.size());
|
|
||||||
a.add("1");
|
|
||||||
assertEquals(1, concat.size());
|
|
||||||
assertEquals("1", concat.get(0));
|
|
||||||
b.add("2");
|
|
||||||
assertEquals(2, concat.size());
|
|
||||||
assertEquals("2", concat.get(1));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
package lighthouse.threading;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.collections.ListChangeListener;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
public class MappedListTest
|
|
||||||
{
|
|
||||||
private ObservableList<String> inputs;
|
|
||||||
private ObservableList<String> outputs;
|
|
||||||
private Queue<ListChangeListener.Change<? extends String>> changes;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup()
|
|
||||||
{
|
|
||||||
inputs = FXCollections.observableArrayList();
|
|
||||||
outputs = new MappedList<>(inputs, str -> "Hello " + str);
|
|
||||||
changes = new LinkedList<>();
|
|
||||||
outputs.addListener(changes::add);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void add() throws Exception
|
|
||||||
{
|
|
||||||
assertEquals(0, outputs.size());
|
|
||||||
inputs.add("Mike");
|
|
||||||
ListChangeListener.Change<? extends String> change = getChange();
|
|
||||||
assertTrue(change.wasAdded());
|
|
||||||
assertEquals("Hello Mike", change.getAddedSubList().get(0));
|
|
||||||
assertEquals(1, outputs.size());
|
|
||||||
assertEquals("Hello Mike", outputs.get(0));
|
|
||||||
inputs.remove(0);
|
|
||||||
assertEquals(0, outputs.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ListChangeListener.Change<? extends String> getChange()
|
|
||||||
{
|
|
||||||
ListChangeListener.Change<? extends String> change = changes.poll();
|
|
||||||
change.next();
|
|
||||||
return change;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void remove()
|
|
||||||
{
|
|
||||||
inputs.add("Mike");
|
|
||||||
inputs.add("Dave");
|
|
||||||
inputs.add("Katniss");
|
|
||||||
getChange();
|
|
||||||
getChange();
|
|
||||||
getChange();
|
|
||||||
assertEquals("Hello Mike", outputs.get(0));
|
|
||||||
assertEquals("Hello Dave", outputs.get(1));
|
|
||||||
assertEquals("Hello Katniss", outputs.get(2));
|
|
||||||
inputs.remove(0);
|
|
||||||
ListChangeListener.Change<? extends String> change = getChange();
|
|
||||||
assertTrue(change.wasRemoved());
|
|
||||||
assertEquals(2, outputs.size());
|
|
||||||
assertEquals(1, change.getRemovedSize());
|
|
||||||
assertEquals("Hello Mike", change.getRemoved().get(0));
|
|
||||||
assertEquals("Hello Dave", outputs.get(0));
|
|
||||||
|
|
||||||
inputs.remove(1);
|
|
||||||
assertEquals(1, outputs.size());
|
|
||||||
assertEquals("Hello Dave", outputs.get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void replace() throws Exception
|
|
||||||
{
|
|
||||||
inputs.add("Mike");
|
|
||||||
inputs.add("Dave");
|
|
||||||
getChange();
|
|
||||||
getChange();
|
|
||||||
inputs.set(0, "Bob");
|
|
||||||
assertEquals("Hello Bob", outputs.get(0));
|
|
||||||
ListChangeListener.Change<? extends String> change = getChange();
|
|
||||||
assertTrue(change.wasReplaced());
|
|
||||||
assertEquals("Hello Mike", change.getRemoved().get(0));
|
|
||||||
assertEquals("Hello Bob", change.getAddedSubList().get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Could also test permutation here if I could figure out how to actually apply one!
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue