Eric Kok
8 years ago
17 changed files with 570 additions and 4 deletions
@ -0,0 +1,14 @@ |
|||||||
|
apply plugin: 'java' |
||||||
|
|
||||||
|
dependencies { |
||||||
|
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' |
||||||
|
compile 'com.squareup.okhttp3:logging-interceptor:3.5.0' |
||||||
|
compile 'com.github.erickok:retrofit-xmlrpc:master-SNAPSHOT' |
||||||
|
compile 'com.burgstaller:okhttp-digest:1.10' |
||||||
|
|
||||||
|
testCompile 'junit:junit:4.12' |
||||||
|
testCompile 'com.google.truth:truth:0.31' |
||||||
|
} |
||||||
|
|
||||||
|
sourceCompatibility = "1.7" |
||||||
|
targetCompatibility = "1.7" |
@ -0,0 +1,45 @@ |
|||||||
|
package org.transdroid.connect; |
||||||
|
|
||||||
|
import com.burgstaller.okhttp.digest.Credentials; |
||||||
|
|
||||||
|
import org.transdroid.connect.clients.Client; |
||||||
|
import org.transdroid.connect.clients.ClientSpec; |
||||||
|
import org.transdroid.connect.util.StringUtil; |
||||||
|
|
||||||
|
public final class Configuration { |
||||||
|
|
||||||
|
private final Client client; |
||||||
|
private final String baseUrl; |
||||||
|
private final String endpoint; |
||||||
|
private final Credentials credentials; |
||||||
|
private final boolean loggingEnabled; |
||||||
|
|
||||||
|
public Configuration(Client client, String baseUrl, String endpoint, String user, String password, boolean loggingEnabled) { |
||||||
|
this.client = client; |
||||||
|
this.baseUrl = baseUrl; |
||||||
|
this.endpoint = endpoint; |
||||||
|
this.credentials = (!StringUtil.isEmpty(user) && password != null) ? new Credentials(user, password) : null; |
||||||
|
this.loggingEnabled = loggingEnabled; |
||||||
|
} |
||||||
|
|
||||||
|
public String baseUrl() { |
||||||
|
return baseUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String endpoint() { |
||||||
|
return endpoint; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean loggingEnabled() { |
||||||
|
return loggingEnabled; |
||||||
|
} |
||||||
|
|
||||||
|
public Credentials credentials() { |
||||||
|
return credentials; |
||||||
|
} |
||||||
|
|
||||||
|
public ClientSpec create() { |
||||||
|
return client.create(this); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package org.transdroid.connect.clients; |
||||||
|
|
||||||
|
import org.transdroid.connect.Configuration; |
||||||
|
import org.transdroid.connect.clients.rtorrent.Rtorrent; |
||||||
|
|
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
public enum Client { |
||||||
|
|
||||||
|
RTORRENT { |
||||||
|
@Override |
||||||
|
public ClientSpec create(Configuration configuration) { |
||||||
|
return new Rtorrent(configuration); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
Set<Feature> features() { |
||||||
|
return Rtorrent.FEATURES; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public abstract ClientSpec create(Configuration configuration); |
||||||
|
|
||||||
|
abstract Set<Feature> features(); |
||||||
|
|
||||||
|
public boolean supports(Feature feature) { |
||||||
|
return features().contains(feature); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package org.transdroid.connect.clients; |
||||||
|
|
||||||
|
import org.transdroid.connect.model.Torrent; |
||||||
|
|
||||||
|
import io.reactivex.Flowable; |
||||||
|
|
||||||
|
public interface ClientSpec { |
||||||
|
|
||||||
|
Flowable<String> clientVersion(); |
||||||
|
|
||||||
|
Flowable<Torrent> torrents(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
package org.transdroid.connect.clients; |
||||||
|
|
||||||
|
public enum Feature { |
||||||
|
|
||||||
|
VERSION, |
||||||
|
STARTING, |
||||||
|
STOPPING, |
||||||
|
RESUMING, |
||||||
|
PAUSING |
||||||
|
|
||||||
|
} |
@ -0,0 +1,143 @@ |
|||||||
|
package org.transdroid.connect.clients.rtorrent; |
||||||
|
|
||||||
|
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; |
||||||
|
|
||||||
|
import org.transdroid.connect.Configuration; |
||||||
|
import org.transdroid.connect.clients.ClientSpec; |
||||||
|
import org.transdroid.connect.clients.Feature; |
||||||
|
import org.transdroid.connect.model.Torrent; |
||||||
|
import org.transdroid.connect.model.TorrentStatus; |
||||||
|
import org.transdroid.connect.util.OkHttpBuilder; |
||||||
|
import org.transdroid.connect.util.RxUtil; |
||||||
|
|
||||||
|
import java.util.Date; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import io.reactivex.Flowable; |
||||||
|
import io.reactivex.functions.Function; |
||||||
|
import nl.nl2312.xmlrpc.Nothing; |
||||||
|
import nl.nl2312.xmlrpc.XmlRpcConverterFactory; |
||||||
|
import retrofit2.Retrofit; |
||||||
|
|
||||||
|
public final class Rtorrent implements ClientSpec { |
||||||
|
|
||||||
|
public static final Set<Feature> FEATURES = new HashSet<>(); |
||||||
|
|
||||||
|
{ |
||||||
|
FEATURES.add(Feature.VERSION); |
||||||
|
FEATURES.add(Feature.STARTING); |
||||||
|
FEATURES.add(Feature.STOPPING); |
||||||
|
FEATURES.add(Feature.RESUMING); |
||||||
|
FEATURES.add(Feature.PAUSING); |
||||||
|
} |
||||||
|
|
||||||
|
private final Configuration configuration; |
||||||
|
private final Service service; |
||||||
|
|
||||||
|
public Rtorrent(Configuration configuration) { |
||||||
|
this.configuration = configuration; |
||||||
|
Retrofit retrofit = new Retrofit.Builder() |
||||||
|
.baseUrl(configuration.baseUrl()) |
||||||
|
.client(new OkHttpBuilder(configuration).build()) |
||||||
|
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) |
||||||
|
.addConverterFactory(XmlRpcConverterFactory.create()) |
||||||
|
.build(); |
||||||
|
this.service = retrofit.create(Service.class); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Flowable<String> clientVersion() { |
||||||
|
return service.clientVersion(configuration.endpoint(), Nothing.NOTHING); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Flowable<Torrent> torrents() { |
||||||
|
return service.torrents( |
||||||
|
configuration.endpoint(), |
||||||
|
"", |
||||||
|
"main", |
||||||
|
"d.hash=", |
||||||
|
"d.name=", |
||||||
|
"d.state=", |
||||||
|
"d.down.rate=", |
||||||
|
"d.up.rate=", |
||||||
|
"d.peers_connected=", |
||||||
|
"d.peers_not_connected=", |
||||||
|
"d.bytes_done=", |
||||||
|
"d.up.total=", |
||||||
|
"d.size_bytes=", |
||||||
|
"d.left_bytes=", |
||||||
|
"d.creation_date=", |
||||||
|
"d.complete=", |
||||||
|
"d.is_active=", |
||||||
|
"d.is_hash_checking=", |
||||||
|
"d.base_path=", |
||||||
|
"d.base_filename=", |
||||||
|
"d.message=", |
||||||
|
"d.custom=addtime", |
||||||
|
"d.custom=seedingtime", |
||||||
|
"d.custom1=", |
||||||
|
"d.peers_complete=", |
||||||
|
"d.peers_accounted=") |
||||||
|
.compose(RxUtil.<TorrentSpec>asList()) |
||||||
|
.map(new Function<TorrentSpec, Torrent>() { |
||||||
|
@Override |
||||||
|
public Torrent apply(TorrentSpec torrentSpec) throws Exception { |
||||||
|
return new Torrent( |
||||||
|
torrentSpec.hash.hashCode(), |
||||||
|
torrentSpec.hash, |
||||||
|
torrentSpec.name, |
||||||
|
torrentStatus(torrentSpec.state, torrentSpec.isComplete, torrentSpec.isActive, torrentSpec.isHashChecking), |
||||||
|
torrentSpec.basePath.substring(0, torrentSpec.basePath.indexOf(torrentSpec.baseFilename)), |
||||||
|
(int) torrentSpec.downloadRate, |
||||||
|
(int) torrentSpec.uploadRate, |
||||||
|
(int) torrentSpec.seedersConnected, |
||||||
|
(int) (torrentSpec.peersConnected + torrentSpec.peersNotConnected), |
||||||
|
(int) torrentSpec.leechersConnected, |
||||||
|
(int) (torrentSpec.peersConnected + torrentSpec.peersNotConnected), |
||||||
|
torrentSpec.downloadRate > 0 ? (torrentSpec.bytesleft / torrentSpec.downloadRate) : Torrent.UNKNOWN, |
||||||
|
torrentSpec.bytesDone, |
||||||
|
torrentSpec.bytesUploaded, |
||||||
|
torrentSpec.bytesTotal, |
||||||
|
torrentSpec.bytesDone / torrentSpec.bytesTotal, |
||||||
|
0F, |
||||||
|
torrentSpec.label, |
||||||
|
torrentTimeAdded(torrentSpec.timeAdded, torrentSpec.timeCreated), |
||||||
|
torrentTimeFinished(torrentSpec.timeFinished), |
||||||
|
torrentSpec.errorMessage |
||||||
|
); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private TorrentStatus torrentStatus(long state, long complete, long active, long checking) { |
||||||
|
if (state == 0) { |
||||||
|
return TorrentStatus.QUEUED; |
||||||
|
} else if (active == 1) { |
||||||
|
if (complete == 1) { |
||||||
|
return TorrentStatus.SEEDING; |
||||||
|
} else { |
||||||
|
return TorrentStatus.DOWNLOADING; |
||||||
|
} |
||||||
|
} else if (checking == 1) { |
||||||
|
return TorrentStatus.CHECKING; |
||||||
|
} else { |
||||||
|
return TorrentStatus.PAUSED; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Date torrentTimeAdded(String timeAdded, long timeCreated) { |
||||||
|
if (timeAdded != null || timeAdded.trim().length() != 0) { |
||||||
|
return new Date(Long.parseLong(timeAdded.trim()) * 1000L); |
||||||
|
} |
||||||
|
return new Date(timeCreated * 1000L); |
||||||
|
} |
||||||
|
|
||||||
|
private Date torrentTimeFinished(String timeFinished) { |
||||||
|
if (timeFinished == null || timeFinished.trim().length() == 0) |
||||||
|
return null; |
||||||
|
return new Date(Long.parseLong(timeFinished.trim()) * 1000L); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package org.transdroid.connect.clients.rtorrent; |
||||||
|
|
||||||
|
import io.reactivex.Flowable; |
||||||
|
import nl.nl2312.xmlrpc.Nothing; |
||||||
|
import nl.nl2312.xmlrpc.XmlRpc; |
||||||
|
import retrofit2.http.Body; |
||||||
|
import retrofit2.http.POST; |
||||||
|
import retrofit2.http.Path; |
||||||
|
|
||||||
|
interface Service { |
||||||
|
|
||||||
|
@XmlRpc("system.client_version") |
||||||
|
@POST("{endpoint}") |
||||||
|
Flowable<String> clientVersion(@Path("endpoint") String endpoint, @Body Nothing nothing); |
||||||
|
|
||||||
|
@XmlRpc("d.multicall2") |
||||||
|
@POST("{endpoint}") |
||||||
|
Flowable<TorrentSpec[]> torrents(@Path("endpoint") String endpoint, @Body String... fields); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
package org.transdroid.connect.clients.rtorrent; |
||||||
|
|
||||||
|
public final class TorrentSpec { |
||||||
|
|
||||||
|
public String hash; |
||||||
|
public String name; |
||||||
|
public long state; |
||||||
|
public long downloadRate; |
||||||
|
public long uploadRate; |
||||||
|
public long peersConnected; |
||||||
|
public long peersNotConnected; |
||||||
|
public long bytesDone; |
||||||
|
public long bytesUploaded; |
||||||
|
public long bytesTotal; |
||||||
|
public long bytesleft; |
||||||
|
public long timeCreated; |
||||||
|
public long isComplete; |
||||||
|
public long isActive; |
||||||
|
public long isHashChecking; |
||||||
|
public String basePath; |
||||||
|
public String baseFilename; |
||||||
|
public String errorMessage; |
||||||
|
public String timeAdded; |
||||||
|
public String timeFinished; |
||||||
|
public String label; |
||||||
|
public long seedersConnected; |
||||||
|
public long leechersConnected; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
package org.transdroid.connect.model; |
||||||
|
|
||||||
|
import java.util.Calendar; |
||||||
|
import java.util.Date; |
||||||
|
|
||||||
|
public final class Torrent { |
||||||
|
|
||||||
|
public static final long UNKNOWN = -1L; |
||||||
|
|
||||||
|
private final long id; |
||||||
|
private final String hash; |
||||||
|
private final String name; |
||||||
|
private final TorrentStatus statusCode; |
||||||
|
private final String locationDir; |
||||||
|
|
||||||
|
private final int rateDownload; |
||||||
|
private final int rateUpload; |
||||||
|
private final int seedersConnected; |
||||||
|
private final int seedersKnown; |
||||||
|
private final int leechersConnected; |
||||||
|
private final int leechersKnown; |
||||||
|
private final long eta; |
||||||
|
|
||||||
|
private final long downloadedEver; |
||||||
|
private final long uploadedEver; |
||||||
|
private final long totalSize; |
||||||
|
private final float partDone; |
||||||
|
private final float available; |
||||||
|
private final String label; |
||||||
|
|
||||||
|
private final Date dateAdded; |
||||||
|
private final Date dateDone; |
||||||
|
private final String error; |
||||||
|
|
||||||
|
public Torrent(long id, |
||||||
|
String hash, |
||||||
|
String name, |
||||||
|
TorrentStatus statusCode, |
||||||
|
String locationDir, |
||||||
|
int rateDownload, |
||||||
|
int rateUpload, |
||||||
|
int seedersConnected, |
||||||
|
int seedersKnown, |
||||||
|
int leechersConnected, |
||||||
|
int leechersKnown, |
||||||
|
long eta, |
||||||
|
long downloadedEver, |
||||||
|
long uploadedEver, |
||||||
|
long totalSize, |
||||||
|
float partDone, |
||||||
|
float available, |
||||||
|
String label, |
||||||
|
Date dateAdded, |
||||||
|
Date realDateDone, |
||||||
|
String error) { |
||||||
|
|
||||||
|
this.id = id; |
||||||
|
this.hash = hash; |
||||||
|
this.name = name; |
||||||
|
this.statusCode = statusCode; |
||||||
|
this.locationDir = locationDir; |
||||||
|
|
||||||
|
this.rateDownload = rateDownload; |
||||||
|
this.rateUpload = rateUpload; |
||||||
|
this.seedersConnected = seedersConnected; |
||||||
|
this.seedersKnown = seedersKnown; |
||||||
|
this.leechersConnected = leechersConnected; |
||||||
|
this.leechersKnown = leechersKnown; |
||||||
|
this.eta = eta; |
||||||
|
|
||||||
|
this.downloadedEver = downloadedEver; |
||||||
|
this.uploadedEver = uploadedEver; |
||||||
|
this.totalSize = totalSize; |
||||||
|
this.partDone = partDone; |
||||||
|
this.available = available; |
||||||
|
this.label = label; |
||||||
|
|
||||||
|
this.dateAdded = dateAdded; |
||||||
|
if (realDateDone != null) { |
||||||
|
this.dateDone = realDateDone; |
||||||
|
} else { |
||||||
|
if (this.partDone == 1) { |
||||||
|
// Finished but no finished date: set so move to bottom of list
|
||||||
|
Calendar cal = Calendar.getInstance(); |
||||||
|
cal.clear(); |
||||||
|
cal.set(1900, Calendar.DECEMBER, 31); |
||||||
|
this.dateDone = cal.getTime(); |
||||||
|
} else if (eta == -1 || eta == -2) { |
||||||
|
// UNknown eta: move to the top of the list
|
||||||
|
this.dateDone = new Date(Long.MAX_VALUE); |
||||||
|
} else { |
||||||
|
Calendar cal = Calendar.getInstance(); |
||||||
|
cal.add(Calendar.SECOND, (int) eta); |
||||||
|
this.dateDone = cal.getTime(); |
||||||
|
} |
||||||
|
} |
||||||
|
this.error = error; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package org.transdroid.connect.model; |
||||||
|
|
||||||
|
public enum TorrentStatus { |
||||||
|
|
||||||
|
WAITING, |
||||||
|
CHECKING, |
||||||
|
DOWNLOADING, |
||||||
|
SEEDING, |
||||||
|
PAUSED, |
||||||
|
QUEUED, |
||||||
|
ERROR, |
||||||
|
UNKNOWN; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
package org.transdroid.connect.util; |
||||||
|
|
||||||
|
import com.burgstaller.okhttp.AuthenticationCacheInterceptor; |
||||||
|
import com.burgstaller.okhttp.CachingAuthenticatorDecorator; |
||||||
|
import com.burgstaller.okhttp.DispatchingAuthenticator; |
||||||
|
import com.burgstaller.okhttp.basic.BasicAuthenticator; |
||||||
|
import com.burgstaller.okhttp.digest.CachingAuthenticator; |
||||||
|
import com.burgstaller.okhttp.digest.DigestAuthenticator; |
||||||
|
|
||||||
|
import org.transdroid.connect.Configuration; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
import okhttp3.OkHttpClient; |
||||||
|
import okhttp3.logging.HttpLoggingInterceptor; |
||||||
|
|
||||||
|
public final class OkHttpBuilder { |
||||||
|
|
||||||
|
private final Configuration configuration; |
||||||
|
|
||||||
|
public OkHttpBuilder(Configuration configuration) { |
||||||
|
this.configuration = configuration; |
||||||
|
} |
||||||
|
|
||||||
|
public OkHttpClient build() { |
||||||
|
OkHttpClient.Builder okhttp = new OkHttpClient.Builder(); |
||||||
|
|
||||||
|
if (configuration.loggingEnabled()) { |
||||||
|
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); |
||||||
|
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); |
||||||
|
okhttp.addInterceptor(loggingInterceptor); |
||||||
|
} |
||||||
|
if (configuration.credentials() != null) { |
||||||
|
BasicAuthenticator basicAuthenticator = new BasicAuthenticator(configuration.credentials()); |
||||||
|
DigestAuthenticator digestAuthenticator = new DigestAuthenticator(configuration.credentials()); |
||||||
|
DispatchingAuthenticator authenticator = new DispatchingAuthenticator.Builder() |
||||||
|
.with("digest", digestAuthenticator) |
||||||
|
.with("basic", basicAuthenticator) |
||||||
|
.build(); |
||||||
|
|
||||||
|
Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>(); |
||||||
|
okhttp.authenticator(new CachingAuthenticatorDecorator(authenticator, authCache)); |
||||||
|
okhttp.addInterceptor(new AuthenticationCacheInterceptor(authCache)); |
||||||
|
} |
||||||
|
|
||||||
|
return okhttp.build(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
package org.transdroid.connect.util; |
||||||
|
|
||||||
|
import org.reactivestreams.Publisher; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
import io.reactivex.Flowable; |
||||||
|
import io.reactivex.FlowableTransformer; |
||||||
|
import io.reactivex.functions.Function; |
||||||
|
|
||||||
|
public final class RxUtil { |
||||||
|
|
||||||
|
private RxUtil() {} |
||||||
|
|
||||||
|
public static <T> FlowableTransformer<T[], T> asList() { |
||||||
|
return new FlowableTransformer<T[], T>() { |
||||||
|
@Override |
||||||
|
public Publisher<T> apply(Flowable<T[]> upstream) { |
||||||
|
return upstream.flatMapIterable(new Function<T[], Iterable<T>>() { |
||||||
|
@Override |
||||||
|
public Iterable<T> apply(T[] ts) throws Exception { |
||||||
|
return Arrays.asList(ts); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
package org.transdroid.connect.util; |
||||||
|
|
||||||
|
public final class StringUtil { |
||||||
|
|
||||||
|
private StringUtil() {} |
||||||
|
|
||||||
|
public static boolean isEmpty(String string) { |
||||||
|
return string == null || string.equals(""); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
package org.transdroid.connect.clients.rtorrent; |
||||||
|
|
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
import org.transdroid.connect.Configuration; |
||||||
|
import org.transdroid.connect.clients.Client; |
||||||
|
import org.transdroid.connect.clients.ClientSpec; |
||||||
|
import org.transdroid.connect.clients.Feature; |
||||||
|
import org.transdroid.connect.model.Torrent; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import io.reactivex.functions.Predicate; |
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat; |
||||||
|
|
||||||
|
public final class RtorrentTest { |
||||||
|
|
||||||
|
private ClientSpec rtorrent; |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() { |
||||||
|
Configuration configuration = new Configuration(Client.RTORRENT, "http://localhost:8008/", "RPC2", null, null, true); |
||||||
|
rtorrent = configuration.create(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void features() { |
||||||
|
assertThat(Client.RTORRENT.supports(Feature.VERSION)).isTrue(); |
||||||
|
assertThat(Client.RTORRENT.supports(Feature.STARTING)).isTrue(); |
||||||
|
assertThat(Client.RTORRENT.supports(Feature.STOPPING)).isTrue(); |
||||||
|
assertThat(Client.RTORRENT.supports(Feature.RESUMING)).isTrue(); |
||||||
|
assertThat(Client.RTORRENT.supports(Feature.PAUSING)).isTrue(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void clientVersion() throws IOException { |
||||||
|
rtorrent.clientVersion() |
||||||
|
.test() |
||||||
|
.assertValue("0.9.6"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void torrents() throws IOException { |
||||||
|
rtorrent.torrents() |
||||||
|
.toList() |
||||||
|
.test() |
||||||
|
.assertValue(new Predicate<List<Torrent>>() { |
||||||
|
@Override |
||||||
|
public boolean test(List<Torrent> torrents) throws Exception { |
||||||
|
return torrents.size() > 0; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,6 +1,6 @@ |
|||||||
#Wed Jan 20 12:20:00 CET 2016 |
#Sat Jan 21 11:09:39 CET 2017 |
||||||
distributionBase=GRADLE_USER_HOME |
distributionBase=GRADLE_USER_HOME |
||||||
distributionPath=wrapper/dists |
distributionPath=wrapper/dists |
||||||
zipStoreBase=GRADLE_USER_HOME |
zipStoreBase=GRADLE_USER_HOME |
||||||
zipStorePath=wrapper/dists |
zipStorePath=wrapper/dists |
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip |
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip |
||||||
|
Loading…
Reference in new issue