Compare commits

...

106 Commits

Author SHA1 Message Date
akwizgran
347c2f22c1 Bump version numbers for beta release. 2018-01-29 16:48:21 +00:00
Torsten Grote
a8ea191ffb Merge branch '1007-samsung-transition-npe-fix' into 'maintenance-0.16'
Backport: Another attempt at fixing an infamous Samsung activity transition NPE

See merge request akwizgran/briar!678
2018-01-29 14:53:46 +00:00
Torsten Grote
2a4c22757b Another attempt at fixing an infamous Samsung activity transition NPE 2018-01-29 12:36:21 -02:00
Torsten Grote
28ebbbc7d1 Backport translation updates
New translations: br, nl, he, sv, cs, ja
2018-01-29 10:45:12 -02:00
akwizgran
5e7d08f05d Merge branch 'change-password-activity' into 'maintenance-0.16'
Backport: ChangePasswordActivity should extend BriarActivity

See merge request akwizgran/briar!673
2018-01-23 17:36:18 +00:00
akwizgran
ea005748dc Merge branch 'tor-plugin-detect-connectivity-loss' into 'maintenance-0.16'
Backport: Tor plugin should detect connectivity loss

See merge request akwizgran/briar!672
2018-01-23 17:29:28 +00:00
akwizgran
b021bfab5e ChangePasswordActivity should extend BriarActivity. 2018-01-23 17:22:43 +00:00
akwizgran
29cd105a1d Use scheduler service to schedule connectivity checks. 2018-01-23 17:16:59 +00:00
akwizgran
be2e68e96c Listen for a wider range of connectivity-related events. 2018-01-23 17:15:53 +00:00
akwizgran
9dd3f81bb7 Use Tor's OR connection events to detect lost connectivity. 2018-01-23 17:15:53 +00:00
akwizgran
5d918591d4 Merge branch '1145-avoid-unnecessary-db-queries' into 'maintenance-0.16'
Backport: Avoid unnecessary DB queries when starting clients

See merge request akwizgran/briar!669
2018-01-16 15:33:14 +00:00
akwizgran
f1c027fa4d Avoid unnecessary DB queries when starting clients. 2018-01-16 15:23:31 +00:00
akwizgran
d2d3ccf68d Merge branch 'prefer-project-modules' into 'maintenance-0.16'
Backport: Prefer project modules over prebuilt dependencies

See merge request akwizgran/briar!668
2018-01-12 17:55:05 +00:00
akwizgran
f4efed54d5 Prefer project modules over prebuilt dependencies. 2018-01-12 17:35:59 +00:00
akwizgran
459538e40c Bump version numbers for beta release. 2017-12-22 14:43:03 +00:00
akwizgran
183f501761 Merge branch '1132-upgrade-tor-0.2.9.14' into 'maintenance-0.16'
Beta: Upgrade Tor to 0.2.9.14, GeoIP to 2017-11-06

See merge request akwizgran/briar!657
2017-12-22 14:10:52 +00:00
akwizgran
65ee5f539b Upgrade Tor to 0.2.9.14, GeoIP to 2017-11-06. 2017-12-22 13:52:45 +00:00
akwizgran
604339326c Merge branch '1129-send-on-ctrl-enter' into 'maintenance-0.16'
Beta: Send message on ctrl + enter

See merge request akwizgran/briar!656
2017-12-22 11:49:55 +00:00
sbkaf
0acec1343f send message on ctrl + enter 2017-12-22 11:32:15 +00:00
akwizgran
0434756bbd Merge branch '1133-extend-expiry-period' into 'maintenance-0.16'
Extend expiry date, show extension notification

See merge request akwizgran/briar!655
2017-12-22 11:23:40 +00:00
akwizgran
e233433140 Extend expiry date, show extension notification. 2017-12-22 10:58:11 +00:00
akwizgran
c63f285f53 Bumped version numbers for beta release. 2017-12-07 14:13:11 +00:00
akwizgran
0800188718 Merge branch '1112-screen-filter-crash' into 'maintenance-0.16'
Beta: Don't show screen filter dialog after onSaveInstanceState().

See merge request !650
2017-12-07 13:29:27 +00:00
akwizgran
6188e48beb Don't show screen filter dialog after onSaveInstanceState(). 2017-12-07 13:07:07 +00:00
akwizgran
5726e29b56 Merge branch '1088-huawei-whitelisting' into 'maintenance-0.16'
Beta: Add button for Huawei's power manager to setup wizard

See merge request !648
2017-12-07 13:05:34 +00:00
Torsten Grote
5d70399de0 Add button for Huawei's power manager to setup wizard 2017-12-05 15:26:14 -02:00
akwizgran
73202dde5e Merge branch '1127-notification-channels' into 'maintenance-0.16'
Beta: Use channels for all notifications

See merge request !647
2017-12-05 17:03:37 +00:00
akwizgran
a98ac8233c Sort order of channel IDs affects UI of Settings app. 2017-12-05 16:49:31 +00:00
akwizgran
bee3e244fc Use channels for all notifications. 2017-12-05 16:49:31 +00:00
akwizgran
da25999a15 Merge branch '1120-crash-removing-shutdown-hook' into 'maintenance-0.16'
Beta: Don't remove shutdown hook when closing DB

See merge request !645
2017-12-05 14:58:56 +00:00
akwizgran
62049df342 Don't remove shutdown hook when closing DB. 2017-12-05 14:46:07 +00:00
akwizgran
024e5aa90f Bumped version numbers for beta release. 2017-12-04 14:43:27 +00:00
akwizgran
6d791481d5 Merge branch '1007-samsung-transition-npe-beta' into 'maintenance-0.16'
Beta: Don't set scene transition for Samsung devices running Android 7.0

See merge request !641
2017-12-04 14:35:39 +00:00
Torsten Grote
0a807d0893 Don't set scene transition for Samsung devices running Android 7.0 2017-12-04 10:58:20 -02:00
akwizgran
23596bbdd4 Merge branch origin/maintenance-0.16 into maintenance-0.16 2017-12-01 17:19:42 +00:00
Torsten Grote
fe79954138 Merge branch 'briar-beta-app-name' into 'maintenance-0.16'
Change app name for beta debug builds

See merge request !636
2017-12-01 16:43:45 +00:00
akwizgran
9902c023ca Bump version number for beta release. 2017-12-01 16:30:18 +00:00
akwizgran
e8baee6734 Specify 7 characters for Git revision.
(cherry picked from commit f0d8532)
2017-12-01 16:29:45 +00:00
akwizgran
a8dc029e56 Change app name for beta debug builds. 2017-12-01 16:21:20 +00:00
akwizgran
74e3fee7aa Merge branch '1124-notification-channel-crash-beta' into 'maintenance-0.16'
Beta: Use NotificationChannel for foreground service to avoid crash on Android 8.1

See merge request !635
2017-12-01 16:00:53 +00:00
Torsten Grote
05aac696b7 Use NotificationChannel for foreground service to avoid crash on Android 8.1
This also seems to address #1075 at least on an emulator
2017-12-01 13:47:02 -02:00
akwizgran
48918f4727 Bumped version numbers for beta release. 2017-11-30 13:35:43 +00:00
akwizgran
303b5bd395 Merge branch 'target-sdk-26' into 'master'
Target API version 26, upgrade support library

See merge request !626
2017-11-29 17:38:12 +00:00
akwizgran
97733a52c8 Updated translations. 2017-11-23 17:03:15 +00:00
akwizgran
89dcbec599 Upgrade Gradle plugin to 3.0.1. 2017-11-23 17:01:16 +00:00
akwizgran
6497809fe1 Merge branch '1103-dont-ask-again-doze' into 'master'
Show Doze Mode Warning with Don't Ask Again Option

Closes #1103

See merge request !625
2017-11-23 16:23:39 +00:00
akwizgran
9f3a63d8c4 Don't unregister receiver unless it was registered. 2017-11-22 11:37:58 +00:00
akwizgran
748fa77d94 Move doze receiver out of BriarService. 2017-11-22 11:07:28 +00:00
Torsten Grote
4ca86ee4eb Address review comments 2017-11-21 16:01:07 -02:00
Torsten Grote
ec2f372933 Remember that app entered doze mode and inform user when returning 2017-11-21 15:55:00 -02:00
Torsten Grote
4267800db2 Allow Account Creation without Doze White-listing 2017-11-21 15:55:00 -02:00
Torsten Grote
bb8cb9bcbb Show Doze Dialog only after startup and provide "don't ask again" option 2017-11-21 15:54:59 -02:00
akwizgran
d5b9e15ee1 Bump compileSdkVersion to match support library. 2017-11-21 17:33:40 +00:00
akwizgran
43ee3246f6 Remove redundant casts from findViewById. 2017-11-21 17:29:21 +00:00
akwizgran
b56724dee5 Set target SDK version to 26, upgrade support library. 2017-11-21 17:29:21 +00:00
akwizgran
92748ac872 Accept build tools license for CI. 2017-11-21 17:28:11 +00:00
akwizgran
b89686c287 Merge branch 'upgrade-gradle-witness' into 'master'
Upgrade Gradle Witness

See merge request !623
2017-11-21 17:11:06 +00:00
akwizgran
a34692630b Use testImplementation for Mockito. 2017-11-21 17:03:38 +00:00
akwizgran
735208562a Use java-library plugin for Java modules. 2017-11-21 16:35:08 +00:00
akwizgran
49826fdc56 Use new Gradle configurations for Android modules. 2017-11-21 16:35:08 +00:00
akwizgran
e8c54a609c Upgrade Gradle Witness. 2017-11-21 16:35:03 +00:00
akwizgran
ece2c51358 A few more Java 8 changes in merged code. 2017-11-21 16:21:15 +00:00
akwizgran
3ec8af4661 Merge branch 'use-java-8-language-features' into 'master'
Use java 8 language features

See merge request !621
2017-11-21 15:22:52 +00:00
Torsten Grote
77a08596fe Merge branch '764-bdf-list-dictionary-not-thread-safe' into 'master'
BdfList and BdfDictionary don't need to be thread-safe

Closes #764

See merge request !614
2017-11-21 13:00:23 +00:00
akwizgran
879f699b2b A few more lambdas. 2017-11-21 10:51:37 -02:00
akwizgran
d7383a3361 Effectively final. 2017-11-21 10:51:35 -02:00
akwizgran
a5b321a93b Multi-catch. 2017-11-21 10:49:10 -02:00
akwizgran
5fa6b0ca1c Lambdas. 2017-11-21 10:49:08 -02:00
akwizgran
27328afe3c Diamond operators. 2017-11-21 10:45:47 -02:00
Torsten Grote
2d26af1ae2 Merge branch 'java-8-language-features' into 'master'
Support Java 8 language features

See merge request !620
2017-11-21 12:09:27 +00:00
Torsten Grote
6db8f33e8f Merge branch 'log-network-usage' into 'master'
Log network usage at shutdown

See merge request !616
2017-11-21 11:45:42 +00:00
akwizgran
d6a7e6d52c Resolve merge conflicts.
# Conflicts:
#   briar-android/build.gradle
#   briar-android/src/test/java/org/briarproject/briar/android/login/SetupActivityTest.java
2017-11-21 10:27:31 +00:00
akwizgran
df99b3b666 Merge branch '1085-startup-wizard' into 'master'
Setup Wizard that asks for Doze Mode exception

Closes #1085 and #1018

See merge request !603
2017-11-21 09:40:10 +00:00
akwizgran
0f1c9f4fe2 Refactored tests for account setup and changing password. 2017-11-20 14:11:31 -02:00
Torsten Grote
5dcd5f79dc Test PasswordFragment account creation individually 2017-11-20 11:52:06 -02:00
Torsten Grote
8a81171739 Setup Wizard that asks for Doze Mode exception
Keep checking if we are whitelisted and request it if not
2017-11-20 11:52:05 -02:00
akwizgran
1c4f20f76f Merge branch 'simply-build-gradle' into 'master'
Simply bramble-androids's build.gradle

See merge request !622
2017-11-17 16:11:00 +00:00
goapunk
f84fa588f6 simply bramble-androids's build.gradle
Signed-off-by: goapunk <noobie@goapunks.net>
2017-11-17 16:43:07 +01:00
akwizgran
e30e34f342 Include java.lang.invoke classes in bootstrap classpath. 2017-11-16 15:26:05 +00:00
akwizgran
fc93ced067 Download the Android support repository for CI. 2017-11-16 12:54:57 +00:00
akwizgran
bb7df72d31 Compile against OpenJDK 6 standard library for CI. 2017-11-16 12:54:50 +00:00
akwizgran
f8425658e4 Support Java 8 language features in Java modules. 2017-11-16 11:46:35 +00:00
akwizgran
53c8cf09b6 Support Java 8 language features in Android modules. 2017-11-16 11:46:34 +00:00
akwizgran
9f29bf4949 Upgrade Gradle and Android Gradle plugin 2017-11-16 11:46:32 +00:00
akwizgran
98e2adf794 Fix Dagger setup, remove android-apt plugin. 2017-11-16 11:46:02 +00:00
Torsten Grote
2a43e0b0ed Merge branch '545-simple-db-indexes' into 'master'
Add some simple indexes to the DB

See merge request !618
2017-11-09 12:10:07 +00:00
akwizgran
773ae73820 Updated translations. 2017-11-09 12:05:21 +00:00
akwizgran
009db57bc5 Merge branch '482-delete-old-transport-property-updates' into 'master'
Delete old transport property updates

Closes #482

See merge request !617
2017-11-09 11:59:00 +00:00
akwizgran
5e98126e77 Completely remove old local updates from the database. 2017-11-09 10:58:51 +00:00
akwizgran
bd7ebfd83a Unit tests for TransportPropertyManagerImpl. 2017-11-08 16:44:26 +00:00
akwizgran
10f41ef157 Log network usage at shutdown. 2017-11-08 14:46:56 +00:00
akwizgran
1dd4960109 Transactions that delete old updates must be read-write. 2017-11-08 14:23:30 +00:00
akwizgran
75413b6c86 Delete old transport property updates.
Some of this code is only needed for backward compatibility - it can be removed when we break compatibility for 1.0.
2017-11-08 09:47:59 +00:00
akwizgran
b2180582a7 BdfList and BdfDictionary don't need to be thread-safe.
Same goes for Metadata.
2017-11-06 15:20:21 +00:00
akwizgran
8211ce7ae3 Add some simple indexes to the DB. 2017-11-03 15:06:34 +00:00
akwizgran
e6b1597fa7 Upgraded Gradle to 3.5. 2017-10-26 18:07:20 +01:00
akwizgran
8937d3cd9c Updated translations. 2017-10-24 17:01:11 +01:00
akwizgran
51f320d147 Merge branch '992-wake-lock-tag' into 'master'
Change wake lock tag

Closes #992 and #1087

See merge request !612
2017-10-24 13:36:26 +00:00
goapunk
e402a894bb Change wake lock tag
Signed-off-by: goapunk <noobie@goapunks.net>
2017-10-24 13:45:27 +02:00
Torsten Grote
9b577f1219 Merge branch 'remove-location-permission' into 'master'
Remove unused location permission

See merge request !611
2017-10-18 16:31:56 +00:00
akwizgran
220f678403 Removed unused location permission. 2017-10-18 14:05:11 +01:00
akwizgran
4173fc4daa Merge branch '1045-preference-divider' into 'master'
Don't use a custom widget to separate preference categories

Closes #1045

See merge request !609
2017-10-17 17:03:13 +00:00
Torsten Grote
c6756d2145 Merge branch 'gradle-plugin-2.3.3' into 'master'
Upgrade Gradle plugin and build tools

See merge request !610
2017-10-17 16:14:53 +00:00
akwizgran
6731f6eeb5 Added checksum for Gradle download. 2017-10-17 17:01:46 +01:00
akwizgran
6f7f8b40e3 Upgraded Gradle plugin and build tools. 2017-10-17 15:31:28 +01:00
akwizgran
4fe4c298d7 Don't use a custom widget to separate preference categories. 2017-10-11 17:35:05 +01:00
340 changed files with 9593 additions and 7268 deletions

View File

@@ -6,8 +6,18 @@ cache:
- .gradle/caches - .gradle/caches
before_script: before_script:
- set -e
- export GRADLE_USER_HOME=$PWD/.gradle - export GRADLE_USER_HOME=$PWD/.gradle
- echo y | /opt/android-sdk/tools/bin/sdkmanager "build-tools;23.0.3" # Accept the license for the Android build tools
- echo y | /opt/android-sdk/tools/bin/sdkmanager "build-tools;26.0.2"
# Download OpenJDK 6 so we can compile against its standard library
- JDK_FILE=openjdk-6-jre-headless_6b38-1.13.10-1~deb7u1_amd64.deb
- if [ ! -d openjdk ]
- then
- wget -q http://ftp.uk.debian.org/debian/pool/main/o/openjdk-6/$JDK_FILE
- dpkg-deb -x $JDK_FILE openjdk
- fi
- export JAVA_6_HOME=$PWD/openjdk/usr/lib/jvm/java-6-openjdk-amd64
test: test:
script: script:

View File

@@ -6,99 +6,90 @@ apply plugin: 'witness'
apply plugin: 'de.undercouch.download' apply plugin: 'de.undercouch.download'
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "23.0.3" buildToolsVersion '26.0.2'
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 22 targetSdkVersion 26
versionCode 1611 versionCode 1617
versionName "0.16.11" versionName "0.16.17"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_8
} }
} }
dependencies { dependencies {
compile project(':bramble-core') implementation project(path: ':bramble-core', configuration: 'default')
compile fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
provided 'javax.annotation:jsr250-api:1.0'
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
compileOnly 'javax.annotation:jsr250-api:1.0'
} }
def torBinaryDir = 'src/main/res/raw' dependencyVerification {
verify = [
task downloadTorGeoIp(type: Download) { 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
src 'https://briarproject.org/build/geoip-2017-09-06.zip' 'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
dest "$torBinaryDir/geoip.zip" 'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
onlyIfNewer true 'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128-runtime.jar:e357a0f1d573c2f702a273992b1b6cb661734f66311854efb3778a888515c5b5',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128.jar:47b4bec6df11a1118da3953da8b9fa1e7079d6fec857faa1a3cf912e53a6fd4e',
'org.jacoco:org.jacoco.ant:0.7.4.201502262128:org.jacoco.ant-0.7.4.201502262128.jar:013ce2a68ba57a3c59215ae0dec4df3498c078062a38c3b94c841fc14450f283',
'org.jacoco:org.jacoco.core:0.7.4.201502262128:org.jacoco.core-0.7.4.201502262128.jar:ec4c74554312fac5116350164786f91b35c9e082fa4ea598bfa42b5db05d7abb',
'org.jacoco:org.jacoco.report:0.7.4.201502262128:org.jacoco.report-0.7.4.201502262128.jar:7a3554c605e088e7e323b1084656243f0444fa353e2f2dee1f1a4204eb64ff09',
'org.ow2.asm:asm-debug-all:5.0.1:asm-debug-all-5.0.1.jar:4734de5b515a454b0096db6971fb068e5f70e6f10bbee2b3bd2fdfe5d978ed57',
]
} }
task downloadTorBinaryArm(type: Download) { ext.torBinaryDir = 'src/main/res/raw'
src 'https://briarproject.org/build/tor-0.2.9.12-arm.zip' ext.torVersion = '0.2.9.14'
dest "$torBinaryDir/tor_arm.zip" ext.geoipVersion = '2017-11-06'
onlyIfNewer true ext.torDownloadUrl = 'https://briarproject.org/build/'
def torBinaries = [
"tor_arm" : '1710ea6c47b7f4c1a88bdf4858c7893837635db10e8866854eed8d61629f50e8',
"tor_arm_pie": '974e6949507db8fa2ea45231817c2c3677ed4ccf5488a2252317d744b0be1917',
"tor_x86" : '3a5e45b3f051fcda9353b098b7086e762ffe7ba9242f7d7c8bf6523faaa8b1e9',
"tor_x86_pie": 'd1d96d8ce1a4b68accf04850185780d10cd5563d3552f7e1f040f8ca32cb4e51',
"geoip" : '8239b98374493529a29096e45fc5877d4d6fdad0146ad8380b291f90d61484ea'
]
def downloadBinary(name) {
return tasks.create("downloadBinary${name}", Download) {
src "${torDownloadUrl}${name}.zip"
.replace('tor_', "tor-${torVersion}-")
.replace('geoip', "geoip-${geoipVersion}")
.replaceAll('_', '-')
dest "${torBinaryDir}/${name}.zip"
onlyIfNewer true
}
} }
task downloadTorBinaryArmPie(type: Download) { def verifyBinary(name, chksum) {
src 'https://briarproject.org/build/tor-0.2.9.12-arm-pie.zip' return tasks.create([
dest "$torBinaryDir/tor_arm_pie.zip" name : "verifyBinary${name}",
onlyIfNewer true type : Verify,
} dependsOn: downloadBinary(name)]) {
src "${torBinaryDir}/${name}.zip"
task downloadTorBinaryX86(type: Download) { algorithm 'SHA-256'
src 'https://briarproject.org/build/tor-0.2.9.12-x86.zip' checksum chksum
dest "$torBinaryDir/tor_x86.zip" }
onlyIfNewer true
}
task downloadTorBinaryX86Pie(type: Download) {
src 'https://briarproject.org/build/tor-0.2.9.12-x86-pie.zip'
dest "$torBinaryDir/tor_x86_pie.zip"
onlyIfNewer true
}
task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
src "$torBinaryDir/geoip.zip"
algorithm 'SHA-256'
checksum 'fe49d3adb86d3c512373101422a017dbb86c85a570524663f09dd8ce143a24f3'
}
task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
src "$torBinaryDir/tor_arm.zip"
algorithm 'SHA-256'
checksum '8ed0b347ffed1d6a4d2fd14495118eb92be83e9cc06e057e15220dc288b31688'
}
task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
src "$torBinaryDir/tor_arm_pie.zip"
algorithm 'SHA-256'
checksum '64403262511c29f462ca5e7c7621bfc3c944898364d1d5ad35a016bb8a034283'
}
task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
src "$torBinaryDir/tor_x86.zip"
algorithm 'SHA-256'
checksum '61e014607a2079bcf1646289c67bff6372b1aded6e1d8d83d7791efda9a4d5ab'
}
task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
src "$torBinaryDir/tor_x86_pie.zip"
algorithm 'SHA-256'
checksum '18fbc98356697dd0895836ab46d5c9877d1c539193464f7db1e82a65adaaf288'
} }
project.afterEvaluate { project.afterEvaluate {
preBuild.dependsOn { torBinaries.every { key, value ->
[ preBuild.dependsOn.add(verifyBinary(key, value))
'verifyTorGeoIp',
'verifyTorBinaryArm',
'verifyTorBinaryArmPie',
'verifyTorBinaryX86',
'verifyTorBinaryX86Pie'
]
} }
} }

View File

@@ -11,8 +11,6 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_LOGS"/> <uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Since API 23, this is needed to add contacts via Bluetooth -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application <application
android:allowBackup="false" android:allowBackup="false"

View File

@@ -13,6 +13,7 @@ import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.reporting.DevReporter; import org.briarproject.bramble.api.reporting.DevReporter;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.Scheduler;
import org.briarproject.bramble.plugin.droidtooth.DroidtoothPluginFactory; import org.briarproject.bramble.plugin.droidtooth.DroidtoothPluginFactory;
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory; import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
import org.briarproject.bramble.plugin.tor.TorPluginFactory; import org.briarproject.bramble.plugin.tor.TorPluginFactory;
@@ -22,6 +23,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import javax.net.SocketFactory; import javax.net.SocketFactory;
@@ -33,6 +35,7 @@ public class AndroidPluginModule {
@Provides @Provides
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor, PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
@Scheduler ScheduledExecutorService scheduler,
AndroidExecutor androidExecutor, SecureRandom random, AndroidExecutor androidExecutor, SecureRandom random,
SocketFactory torSocketFactory, BackoffFactory backoffFactory, SocketFactory torSocketFactory, BackoffFactory backoffFactory,
Application app, LocationUtils locationUtils, DevReporter reporter, Application app, LocationUtils locationUtils, DevReporter reporter,
@@ -40,12 +43,12 @@ public class AndroidPluginModule {
Context appContext = app.getApplicationContext(); Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor, DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
androidExecutor, appContext, random, eventBus, backoffFactory); androidExecutor, appContext, random, eventBus, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext, DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, scheduler,
locationUtils, reporter, eventBus, torSocketFactory, appContext, locationUtils, reporter, eventBus,
backoffFactory); torSocketFactory, backoffFactory);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
backoffFactory, appContext); backoffFactory, appContext);
final Collection<DuplexPluginFactory> duplex = Collection<DuplexPluginFactory> duplex =
Arrays.asList(bluetooth, tor, lan); Arrays.asList(bluetooth, tor, lan);
@NotNullByDefault @NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() { PluginConfig pluginConfig = new PluginConfig() {

View File

@@ -124,12 +124,7 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
// with a message queue, so submit it to the AndroidExecutor // with a message queue, so submit it to the AndroidExecutor
try { try {
adapter = androidExecutor.runOnBackgroundThread( adapter = androidExecutor.runOnBackgroundThread(
new Callable<BluetoothAdapter>() { BluetoothAdapter::getDefaultAdapter).get();
@Override
public BluetoothAdapter call() throws Exception {
return BluetoothAdapter.getDefaultAdapter();
}
}).get();
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
LOG.warning("Interrupted while getting BluetoothAdapter"); LOG.warning("Interrupted while getting BluetoothAdapter");
@@ -162,40 +157,36 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
} }
private void bind() { private void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!isRunning()) return;
public void run() { String address = AndroidUtils.getBluetoothAddress(appContext,
if (!isRunning()) return; adapter);
String address = AndroidUtils.getBluetoothAddress(appContext, if (LOG.isLoggable(INFO))
adapter); LOG.info("Local address " + scrubMacAddress(address));
if (LOG.isLoggable(INFO)) if (!StringUtils.isNullOrEmpty(address)) {
LOG.info("Local address " + scrubMacAddress(address)); // Advertise the Bluetooth address to contacts
if (!StringUtils.isNullOrEmpty(address)) { TransportProperties p = new TransportProperties();
// Advertise the Bluetooth address to contacts p.put(PROP_ADDRESS, address);
TransportProperties p = new TransportProperties(); callback.mergeLocalProperties(p);
p.put(PROP_ADDRESS, address);
callback.mergeLocalProperties(p);
}
// Bind a server socket to accept connections from contacts
BluetoothServerSocket ss;
try {
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
"RFCOMM", getUuid());
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
return;
}
if (!isRunning()) {
tryToClose(ss);
return;
}
LOG.info("Socket bound");
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections();
} }
// Bind a server socket to accept connections from contacts
BluetoothServerSocket ss;
try {
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
"RFCOMM", getUuid());
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return;
}
if (!isRunning()) {
tryToClose(ss);
return;
}
LOG.info("Socket bound");
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections();
}); });
} }
@@ -294,21 +285,18 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
Map<ContactId, TransportProperties> remote = Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties(); callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) { for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
final ContactId c = e.getKey(); ContactId c = e.getKey();
if (connected.contains(c)) continue; if (connected.contains(c)) continue;
final String address = e.getValue().get(PROP_ADDRESS); String address = e.getValue().get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) continue; if (StringUtils.isNullOrEmpty(address)) continue;
final String uuid = e.getValue().get(PROP_UUID); String uuid = e.getValue().get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) continue; if (StringUtils.isNullOrEmpty(uuid)) continue;
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { BluetoothSocket s = connect(address, uuid);
if (!running) return; if (s != null) {
BluetoothSocket s = connect(address, uuid); backoff.reset();
if (s != null) { callback.outgoingConnectionCreated(c, wrapSocket(s));
backoff.reset();
callback.outgoingConnectionCreated(c, wrapSocket(s));
}
} }
}); });
} }
@@ -438,21 +426,11 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
} }
private void enableAdapterAsync() { private void enableAdapterAsync() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::enableAdapter);
@Override
public void run() {
enableAdapter();
}
});
} }
private void disableAdapterAsync() { private void disableAdapterAsync() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::disableAdapter);
@Override
public void run() {
disableAdapter();
}
});
} }
private class BluetoothStateReceiver extends BroadcastReceiver { private class BluetoothStateReceiver extends BroadcastReceiver {
@@ -490,16 +468,13 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
@Override @Override
public Callable<KeyAgreementConnection> listen() { public Callable<KeyAgreementConnection> listen() {
return new Callable<KeyAgreementConnection>() { return () -> {
@Override BluetoothSocket s = ss.accept();
public KeyAgreementConnection call() throws IOException { if (LOG.isLoggable(INFO))
BluetoothSocket s = ss.accept(); LOG.info(ID.getString() + ": Incoming connection");
if (LOG.isLoggable(INFO)) return new KeyAgreementConnection(
LOG.info(ID.getString() + ": Incoming connection"); new DroidtoothTransportConnection(
return new KeyAgreementConnection( DroidtoothPlugin.this, s), ID);
new DroidtoothTransportConnection(
DroidtoothPlugin.this, s), ID);
}
}; };
} }

View File

@@ -59,7 +59,12 @@ import java.util.Map.Entry;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
@@ -70,10 +75,15 @@ import javax.net.SocketFactory;
import static android.content.Context.CONNECTIVITY_SERVICE; import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.MODE_PRIVATE; import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.POWER_SERVICE; import static android.content.Context.POWER_SERVICE;
import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_SCREEN_ON;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK; import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS; import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
@@ -102,6 +112,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
Logger.getLogger(TorPlugin.class.getName()); Logger.getLogger(TorPlugin.class.getName());
private final Executor ioExecutor; private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final DevReporter reporter; private final DevReporter reporter;
@@ -114,6 +125,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final File torDirectory, torFile, geoIpFile, configFile; private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile; private final File doneFile, cookieFile;
private final PowerManager.WakeLock wakeLock; private final PowerManager.WakeLock wakeLock;
private final Lock connectionStatusLock;
private final AtomicReference<Future<?>> connectivityCheck =
new AtomicReference<>();
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false; private volatile boolean running = false;
@@ -122,12 +136,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private volatile TorControlConnection controlConnection = null; private volatile TorControlConnection controlConnection = null;
private volatile BroadcastReceiver networkStateReceiver = null; private volatile BroadcastReceiver networkStateReceiver = null;
TorPlugin(Executor ioExecutor, Context appContext, TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
LocationUtils locationUtils, DevReporter reporter, Context appContext, LocationUtils locationUtils,
SocketFactory torSocketFactory, Backoff backoff, DevReporter reporter, SocketFactory torSocketFactory,
DuplexPluginCallback callback, String architecture, int maxLatency, Backoff backoff, DuplexPluginCallback callback,
int maxIdleTime) { String architecture, int maxLatency, int maxIdleTime) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.reporter = reporter; this.reporter = reporter;
@@ -149,8 +164,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
cookieFile = new File(torDirectory, ".tor/control_auth_cookie"); cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
Object o = appContext.getSystemService(POWER_SERVICE); Object o = appContext.getSystemService(POWER_SERVICE);
PowerManager pm = (PowerManager) o; PowerManager pm = (PowerManager) o;
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin"); // This tag will prevent Huawei's powermanager from killing us.
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "LocationManagerService");
wakeLock.setReferenceCounted(false); wakeLock.setReferenceCounted(false);
connectionStatusLock = new ReentrantLock();
} }
@Override @Override
@@ -203,11 +220,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
Scanner stdout = new Scanner(torProcess.getInputStream()); Scanner stdout = new Scanner(torProcess.getInputStream());
Scanner stderr = new Scanner(torProcess.getErrorStream()); Scanner stderr = new Scanner(torProcess.getErrorStream());
while (stdout.hasNextLine() || stderr.hasNextLine()){ while (stdout.hasNextLine() || stderr.hasNextLine()) {
if(stdout.hasNextLine()) { if (stdout.hasNextLine()) {
LOG.info(stdout.nextLine()); LOG.info(stdout.nextLine());
} }
if(stderr.hasNextLine()){ if (stderr.hasNextLine()) {
LOG.info(stderr.nextLine()); LOG.info(stderr.nextLine());
} }
} }
@@ -256,7 +273,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
// Register to receive network status events // Register to receive network status events
networkStateReceiver = new NetworkStateReceiver(); networkStateReceiver = new NetworkStateReceiver();
IntentFilter filter = new IntentFilter(CONNECTIVITY_ACTION); IntentFilter filter = new IntentFilter();
filter.addAction(CONNECTIVITY_ACTION);
filter.addAction(ACTION_SCREEN_ON);
filter.addAction(ACTION_SCREEN_OFF);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
appContext.registerReceiver(networkStateReceiver, filter); appContext.registerReceiver(networkStateReceiver, filter);
// Bind a server socket to receive incoming hidden service connections // Bind a server socket to receive incoming hidden service connections
bind(); bind();
@@ -369,57 +390,45 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
private void sendDevReports() { private void sendDevReports() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override // TODO: Trigger this with a TransportEnabledEvent
public void run() { File reportDir = AndroidUtils.getReportDir(appContext);
// TODO: Trigger this with a TransportEnabledEvent reporter.sendReports(reportDir);
File reportDir = AndroidUtils.getReportDir(appContext);
reporter.sendReports(reportDir);
}
}); });
} }
private void bind() { private void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override // If there's already a port number stored in config, reuse it
public void run() { String portString = callback.getSettings().get(PREF_TOR_PORT);
// If there's already a port number stored in config, reuse it int port;
String portString = callback.getSettings().get(PREF_TOR_PORT); if (StringUtils.isNullOrEmpty(portString)) port = 0;
int port; else port = Integer.parseInt(portString);
if (StringUtils.isNullOrEmpty(portString)) port = 0; // Bind a server socket to receive connections from Tor
else port = Integer.parseInt(portString); ServerSocket ss = null;
// Bind a server socket to receive connections from Tor try {
ServerSocket ss = null; ss = new ServerSocket();
try { ss.bind(new InetSocketAddress("127.0.0.1", port));
ss = new ServerSocket(); } catch (IOException e) {
ss.bind(new InetSocketAddress("127.0.0.1", port)); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (IOException e) { tryToClose(ss);
if (LOG.isLoggable(WARNING)) return;
LOG.log(WARNING, e.toString(), e);
tryToClose(ss);
return;
}
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
// Store the port number
final String localPort = String.valueOf(ss.getLocalPort());
Settings s = new Settings();
s.put(PREF_TOR_PORT, localPort);
callback.mergeSettings(s);
// Create a hidden service if necessary
ioExecutor.execute(new Runnable() {
@Override
public void run() {
publishHiddenService(localPort);
}
});
backoff.reset();
// Accept incoming hidden service connections from Tor
acceptContactConnections(ss);
} }
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
// Store the port number
String localPort = String.valueOf(ss.getLocalPort());
Settings s = new Settings();
s.put(PREF_TOR_PORT, localPort);
callback.mergeSettings(s);
// Create a hidden service if necessary
ioExecutor.execute(() -> publishHiddenService(localPort));
backoff.reset();
// Accept incoming hidden service connections from Tor
acceptContactConnections(ss);
}); });
} }
@@ -547,17 +556,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
} }
private void connectAndCallBack(final ContactId c, private void connectAndCallBack(ContactId c, TransportProperties p) {
final TransportProperties p) { ioExecutor.execute(() -> {
ioExecutor.execute(new Runnable() { if (!isRunning()) return;
@Override DuplexTransportConnection d = createConnection(p);
public void run() { if (d != null) {
if (!isRunning()) return; backoff.reset();
DuplexTransportConnection d = createConnection(p); callback.outgoingConnectionCreated(c, d);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
}
} }
}); });
} }
@@ -633,6 +638,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public void orConnStatus(String status, String orName) { public void orConnStatus(String status, String orName) {
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status); if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
if (status.equals("CLOSED") || status.equals("FAILED"))
updateConnectionStatus(); // Check whether we've lost connectivity
} }
@Override @Override
@@ -672,7 +679,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
@Override @Override
public void onEvent(int event, String path) { public void onEvent(int event, @Nullable String path) {
stopWatching(); stopWatching();
latch.countDown(); latch.countDown();
} }
@@ -690,60 +697,75 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
private void updateConnectionStatus() { private void updateConnectionStatus() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { try {
if (!running) return; connectionStatusLock.lock();
updateConnectionStatusLocked();
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE); } finally {
ConnectivityManager cm = (ConnectivityManager) o; connectionStatusLock.unlock();
NetworkInfo net = cm.getActiveNetworkInfo();
boolean online = net != null && net.isConnected();
boolean wifi = online && net.getType() == TYPE_WIFI;
String country = locationUtils.getCurrentCountry();
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
country);
Settings s = callback.getSettings();
int network = s.getInt(PREF_TOR_NETWORK,
PREF_TOR_NETWORK_ALWAYS);
if (LOG.isLoggable(INFO)) {
LOG.info("Online: " + online + ", wifi: " + wifi);
if ("".equals(country)) LOG.info("Country code unknown");
else LOG.info("Country code: " + country);
}
try {
if (!online) {
LOG.info("Disabling network, device is offline");
enableNetwork(false);
} else if (blocked) {
LOG.info("Disabling network, country is blocked");
enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_NEVER
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
LOG.info("Disabling network due to data setting");
enableNetwork(false);
} else {
LOG.info("Enabling network");
enableNetwork(true);
}
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
} }
}); });
} }
// Locking: connectionStatusLock
private void updateConnectionStatusLocked() {
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
ConnectivityManager cm = (ConnectivityManager) o;
NetworkInfo net = cm.getActiveNetworkInfo();
boolean online = net != null && net.isConnected();
boolean wifi = online && net.getType() == TYPE_WIFI;
String country = locationUtils.getCurrentCountry();
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
country);
Settings s = callback.getSettings();
int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
if (LOG.isLoggable(INFO)) {
LOG.info("Online: " + online + ", wifi: " + wifi);
if ("".equals(country)) LOG.info("Country code unknown");
else LOG.info("Country code: " + country);
}
try {
if (!online) {
LOG.info("Disabling network, device is offline");
enableNetwork(false);
} else if (blocked) {
LOG.info("Disabling network, country is blocked");
enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_NEVER
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
LOG.info("Disabling network due to data setting");
enableNetwork(false);
} else {
LOG.info("Enabling network");
enableNetwork(true);
}
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
private void scheduleConnectionStatusUpdate() {
Future<?> newConnectivityCheck =
scheduler.schedule(this::updateConnectionStatus, 1, MINUTES);
Future<?> oldConnectivityCheck =
connectivityCheck.getAndSet(newConnectivityCheck);
if (oldConnectivityCheck != null) oldConnectivityCheck.cancel(false);
}
private class NetworkStateReceiver extends BroadcastReceiver { private class NetworkStateReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context ctx, Intent i) { public void onReceive(Context ctx, Intent i) {
if (!running) return; if (!running) return;
if (CONNECTIVITY_ACTION.equals(i.getAction())) { String action = i.getAction();
LOG.info("Detected connectivity change"); if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
updateConnectionStatus(); updateConnectionStatus();
if (ACTION_SCREEN_ON.equals(action)
|| ACTION_SCREEN_OFF.equals(action)) {
scheduleConnectionStatusUpdate();
} }
} }
} }

View File

@@ -17,6 +17,7 @@ import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.AndroidUtils;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
@@ -36,6 +37,7 @@ public class TorPluginFactory implements DuplexPluginFactory {
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final DevReporter reporter; private final DevReporter reporter;
@@ -43,11 +45,13 @@ public class TorPluginFactory implements DuplexPluginFactory {
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
private final BackoffFactory backoffFactory; private final BackoffFactory backoffFactory;
public TorPluginFactory(Executor ioExecutor, Context appContext, public TorPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler, Context appContext,
LocationUtils locationUtils, DevReporter reporter, LocationUtils locationUtils, DevReporter reporter,
EventBus eventBus, SocketFactory torSocketFactory, EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory) { BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.reporter = reporter; this.reporter = reporter;
@@ -89,9 +93,9 @@ public class TorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils, TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext,
reporter, torSocketFactory, backoff, callback, architecture, locationUtils, reporter, torSocketFactory, backoff, callback,
MAX_LATENCY, MAX_IDLE_TIME); architecture, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -27,14 +27,11 @@ class AndroidExecutorImpl implements AndroidExecutor {
@Inject @Inject
AndroidExecutorImpl(Application app) { AndroidExecutorImpl(Application app) {
uiHandler = new Handler(app.getApplicationContext().getMainLooper()); uiHandler = new Handler(app.getApplicationContext().getMainLooper());
loop = new Runnable() { loop = () -> {
@Override Looper.prepare();
public void run() { backgroundHandler = new Handler();
Looper.prepare(); startLatch.countDown();
backgroundHandler = new Handler(); Looper.loop();
startLatch.countDown();
Looper.loop();
}
}; };
} }

View File

@@ -1,30 +1,39 @@
apply plugin: 'java' apply plugin: 'java-library'
sourceCompatibility = 1.6 sourceCompatibility = 1.8
targetCompatibility = 1.6 targetCompatibility = 1.8
apply plugin: 'witness' apply plugin: 'witness'
dependencies { dependencies {
compile "com.google.dagger:dagger:2.0.2" implementation "com.google.dagger:dagger:2.0.2"
compile 'com.google.dagger:dagger-compiler:2.0.2' implementation 'com.google.code.findbugs:jsr305:3.0.2'
compile 'com.google.code.findbugs:jsr305:3.0.2'
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testCompile "org.jmock:jmock:2.8.2" testImplementation "org.jmock:jmock:2.8.2"
testCompile "org.jmock:jmock-junit4:2.8.2" testImplementation "org.jmock:jmock-junit4:2.8.2"
testCompile "org.jmock:jmock-legacy:2.8.2" testImplementation "org.jmock:jmock-legacy:2.8.2"
testCompile "org.hamcrest:hamcrest-library:1.3" testImplementation "org.hamcrest:hamcrest-library:1.3"
testCompile "org.hamcrest:hamcrest-core:1.3" testImplementation "org.hamcrest:hamcrest-core:1.3"
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
] ]
} }
@@ -39,3 +48,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
artifacts { artifacts {
testOutput jarTest testOutput jarTest
} }
// If a Java 6 JRE is available, check we're not using any Java 7 or 8 APIs
tasks.withType(JavaCompile) {
useJava6StandardLibrary(it)
}

View File

@@ -23,7 +23,7 @@ public class BdfMessageContext {
} }
public BdfMessageContext(BdfDictionary dictionary) { public BdfMessageContext(BdfDictionary dictionary) {
this(dictionary, Collections.<MessageId>emptyList()); this(dictionary, Collections.emptyList());
} }
public BdfDictionary getDictionary() { public BdfDictionary getDictionary() {

View File

@@ -4,11 +4,14 @@ import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.Map.Entry;
import java.util.TreeMap;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
public class BdfDictionary extends ConcurrentSkipListMap<String, Object> { @NotThreadSafe
public class BdfDictionary extends TreeMap<String, Object> {
public static final Object NULL_VALUE = new Object(); public static final Object NULL_VALUE = new Object();

View File

@@ -3,15 +3,17 @@ package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.Bytes; import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Vector;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
public class BdfList extends Vector<Object> { @NotThreadSafe
public class BdfList extends ArrayList<Object> {
/** /**
* Factory method for constructing lists inline. * Factory method for constructing lists inline.

View File

@@ -122,8 +122,9 @@ public interface DatabaseComponent {
throws DbException; throws DbException;
/** /**
* Deletes the message with the given ID. The message ID and any other * Deletes the message with the given ID. Unlike
* associated data are not deleted. * {@link #removeMessage(Transaction, MessageId)}, the message ID and any
* other associated data are not deleted.
*/ */
void deleteMessage(Transaction txn, MessageId m) throws DbException; void deleteMessage(Transaction txn, MessageId m) throws DbException;
@@ -452,6 +453,11 @@ public interface DatabaseComponent {
*/ */
void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException; void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException;
/**
* Removes a message (and all associated state) from the database.
*/
void removeMessage(Transaction txn, MessageId m) throws DbException;
/** /**
* Removes a transport (and all associated state) from the database. * Removes a transport (and all associated state) from the database.
*/ */

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.api.db; package org.briarproject.bramble.api.db;
import java.util.Hashtable; import java.util.TreeMap;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.NotThreadSafe;
@ThreadSafe @NotThreadSafe
public class Metadata extends Hashtable<String, byte[]> { public class Metadata extends TreeMap<String, byte[]> {
/** /**
* Special value to indicate that a key is being removed. * Special value to indicate that a key is being removed.

View File

@@ -45,7 +45,7 @@ public class Transaction {
* committed. * committed.
*/ */
public void attach(Event e) { public void attach(Event e) {
if (events == null) events = new ArrayList<Event>(); if (events == null) events = new ArrayList<>();
events.add(e); events.add(e);
} }

View File

@@ -33,7 +33,7 @@ public interface TransportPropertyManager {
/** /**
* Returns the local transport properties for all transports. * Returns the local transport properties for all transports.
* <br/> * <br/>
* Read-Only * TODO: Transaction can be read-only when code is simplified
*/ */
Map<TransportId, TransportProperties> getLocalProperties(Transaction txn) Map<TransportId, TransportProperties> getLocalProperties(Transaction txn)
throws DbException; throws DbException;

View File

@@ -22,7 +22,7 @@ public class MessageContext {
} }
public MessageContext(Metadata metadata) { public MessageContext(Metadata metadata) {
this(metadata, Collections.<MessageId>emptyList()); this(metadata, Collections.emptyList());
} }
public Metadata getMetadata() { public Metadata getMetadata() {

View File

@@ -3,8 +3,7 @@ package org.briarproject.bramble.test;
import org.jmock.Mockery; import org.jmock.Mockery;
import org.junit.After; import org.junit.After;
public abstract class BrambleMockTestCase extends public abstract class BrambleMockTestCase extends BrambleTestCase {
BrambleTestCase {
protected final Mockery context = new Mockery(); protected final Mockery context = new Mockery();

View File

@@ -8,12 +8,9 @@ public abstract class BrambleTestCase {
public BrambleTestCase() { public BrambleTestCase() {
// Ensure exceptions thrown on worker threads cause tests to fail // Ensure exceptions thrown on worker threads cause tests to fail
UncaughtExceptionHandler fail = new UncaughtExceptionHandler() { UncaughtExceptionHandler fail = (thread, throwable) -> {
@Override throwable.printStackTrace();
public void uncaughtException(Thread thread, Throwable throwable) { fail();
throwable.printStackTrace();
fail();
}
}; };
Thread.setDefaultUncaughtExceptionHandler(fail); Thread.setDefaultUncaughtExceptionHandler(fail);
} }

View File

@@ -2,12 +2,27 @@ package org.briarproject.bramble.test;
import org.briarproject.bramble.api.UniqueId; import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
import java.io.File; import java.io.File;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
public class TestUtils { public class TestUtils {
private static final AtomicInteger nextTestDir = private static final AtomicInteger nextTestDir =
@@ -38,4 +53,50 @@ public class TestUtils {
return new SecretKey(getRandomBytes(SecretKey.LENGTH)); return new SecretKey(getRandomBytes(SecretKey.LENGTH));
} }
public static LocalAuthor getLocalAuthor() {
return getLocalAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH));
}
public static LocalAuthor getLocalAuthor(int nameLength) {
AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
long created = System.currentTimeMillis();
return new LocalAuthor(id, name, publicKey, privateKey, created);
}
public static Author getAuthor() {
return getAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH));
}
public static Author getAuthor(int nameLength) {
AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new Author(id, name, publicKey);
}
public static Group getGroup(ClientId clientId) {
int descriptorLength = 1 + random.nextInt(MAX_GROUP_DESCRIPTOR_LENGTH);
return getGroup(clientId, descriptorLength);
}
public static Group getGroup(ClientId clientId, int descriptorLength) {
GroupId groupId = new GroupId(getRandomId());
byte[] descriptor = getRandomBytes(descriptorLength);
return new Group(groupId, clientId, descriptor);
}
public static Message getMessage(GroupId groupId) {
int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH);
return getMessage(groupId, MESSAGE_HEADER_LENGTH + bodyLength);
}
public static Message getMessage(GroupId groupId, int rawLength) {
MessageId id = new MessageId(getRandomId());
byte[] raw = getRandomBytes(rawLength);
long timestamp = System.currentTimeMillis();
return new Message(id, groupId, timestamp, raw);
}
} }

View File

@@ -1,28 +1,54 @@
plugins { apply plugin: 'java-library'
id 'java' sourceCompatibility = 1.8
id 'net.ltgt.apt' version '0.9' targetCompatibility = 1.8
id 'idea'
}
sourceCompatibility = 1.6
targetCompatibility = 1.6
apply plugin: 'net.ltgt.apt'
apply plugin: 'idea'
apply plugin: 'witness' apply plugin: 'witness'
dependencies { dependencies {
compile project(':bramble-api') implementation project(path: ':bramble-api', configuration: 'default')
compile 'com.madgag.spongycastle:core:1.58.0.0' implementation 'com.madgag.spongycastle:core:1.58.0.0'
compile 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6 implementation 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
compile 'org.bitlet:weupnp:0.1.4' implementation 'org.bitlet:weupnp:0.1.4'
testCompile project(path: ':bramble-api', configuration: 'testOutput') apt 'com.google.dagger:dagger-compiler:2.0.2'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
testApt 'com.google.dagger:dagger-compiler:2.0.2'
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'com.madgag.spongycastle:core:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.h2database:h2:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'org.bitlet:weupnp:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb', 'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
] ]
} }
@@ -37,3 +63,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
artifacts { artifacts {
testOutput jarTest testOutput jarTest
} }
// If a Java 6 JRE is available, check we're not using any Java 7 or 8 APIs
tasks.withType(JavaCompile) {
useJava6StandardLibrary(it)
}

View File

@@ -24,7 +24,7 @@ public class PoliteExecutor implements Executor {
private final Object lock = new Object(); private final Object lock = new Object();
@GuardedBy("lock") @GuardedBy("lock")
private final Queue<Runnable> queue = new LinkedList<Runnable>(); private final Queue<Runnable> queue = new LinkedList<>();
private final Executor delegate; private final Executor delegate;
private final int maxConcurrentTasks; private final int maxConcurrentTasks;
private final Logger log; private final Logger log;
@@ -48,20 +48,17 @@ public class PoliteExecutor implements Executor {
} }
@Override @Override
public void execute(final Runnable r) { public void execute(Runnable r) {
final long submitted = System.currentTimeMillis(); long submitted = System.currentTimeMillis();
Runnable wrapped = new Runnable() { Runnable wrapped = () -> {
@Override if (log.isLoggable(LOG_LEVEL)) {
public void run() { long queued = System.currentTimeMillis() - submitted;
if (log.isLoggable(LOG_LEVEL)) { log.log(LOG_LEVEL, "Queue time " + queued + " ms");
long queued = System.currentTimeMillis() - submitted; }
log.log(LOG_LEVEL, "Queue time " + queued + " ms"); try {
} r.run();
try { } finally {
r.run(); scheduleNext();
} finally {
scheduleNext();
}
} }
}; };
synchronized (lock) { synchronized (lock) {

View File

@@ -28,19 +28,16 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
} }
@Override @Override
public void execute(final Runnable r) { public void execute(Runnable r) {
if (log.isLoggable(LOG_LEVEL)) { if (log.isLoggable(LOG_LEVEL)) {
final long submitted = System.currentTimeMillis(); long submitted = System.currentTimeMillis();
super.execute(new Runnable() { super.execute(() -> {
@Override long started = System.currentTimeMillis();
public void run() { long queued = started - submitted;
long started = System.currentTimeMillis(); log.log(LOG_LEVEL, "Queue time " + queued + " ms");
long queued = started - submitted; r.run();
log.log(LOG_LEVEL, "Queue time " + queued + " ms"); long executing = System.currentTimeMillis() - started;
r.run(); log.log(LOG_LEVEL, "Execution time " + executing + " ms");
long executing = System.currentTimeMillis() - started;
log.log(LOG_LEVEL, "Execution time " + executing + " ms");
}
}); });
} else { } else {
super.execute(r); super.execute(r);

View File

@@ -201,8 +201,7 @@ class ClientHelperImpl implements ClientHelper {
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary( public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
Transaction txn, GroupId g) throws DbException, FormatException { Transaction txn, GroupId g) throws DbException, FormatException {
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g); Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g);
Map<MessageId, BdfDictionary> parsed = Map<MessageId, BdfDictionary> parsed = new HashMap<>(raw.size());
new HashMap<MessageId, BdfDictionary>(raw.size());
for (Entry<MessageId, Metadata> e : raw.entrySet()) for (Entry<MessageId, Metadata> e : raw.entrySet())
parsed.put(e.getKey(), metadataParser.parse(e.getValue())); parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
return parsed; return parsed;
@@ -229,8 +228,7 @@ class ClientHelperImpl implements ClientHelper {
FormatException { FormatException {
Metadata metadata = metadataEncoder.encode(query); Metadata metadata = metadataEncoder.encode(query);
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g, metadata); Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g, metadata);
Map<MessageId, BdfDictionary> parsed = Map<MessageId, BdfDictionary> parsed = new HashMap<>(raw.size());
new HashMap<MessageId, BdfDictionary>(raw.size());
for (Entry<MessageId, Metadata> e : raw.entrySet()) for (Entry<MessageId, Metadata> e : raw.entrySet())
parsed.put(e.getKey(), metadataParser.parse(e.getValue())); parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
return parsed; return parsed;

View File

@@ -184,12 +184,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
// Close the outgoing stream and expect EOF on the incoming stream // Close the outgoing stream and expect EOF on the incoming stream
w.close(); w.close();
if (!r.eof()) LOG.warning("Unexpected data at end of connection"); if (!r.eof()) LOG.warning("Unexpected data at end of connection");
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException | IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
listener.contactExchangeFailed();
tryToClose(conn, true);
return;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
listener.contactExchangeFailed(); listener.contactExchangeFailed();
tryToClose(conn, true); tryToClose(conn, true);
@@ -276,8 +271,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private Map<TransportId, TransportProperties> receiveTransportProperties( private Map<TransportId, TransportProperties> receiveTransportProperties(
BdfReader r) throws IOException { BdfReader r) throws IOException {
Map<TransportId, TransportProperties> remote = Map<TransportId, TransportProperties> remote = new HashMap<>();
new HashMap<TransportId, TransportProperties>();
r.readListStart(); r.readListStart();
while (!r.hasListEnd()) { while (!r.hasListEnd()) {
r.readListStart(); r.readListStart();

View File

@@ -34,8 +34,8 @@ class ContactManagerImpl implements ContactManager {
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) { ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
this.db = db; this.db = db;
this.keyManager = keyManager; this.keyManager = keyManager;
addHooks = new CopyOnWriteArrayList<AddContactHook>(); addHooks = new CopyOnWriteArrayList<>();
removeHooks = new CopyOnWriteArrayList<RemoveContactHook>(); removeHooks = new CopyOnWriteArrayList<>();
} }
@Override @Override
@@ -125,7 +125,7 @@ class ContactManagerImpl implements ContactManager {
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
} }
List<Contact> active = new ArrayList<Contact>(contacts.size()); List<Contact> active = new ArrayList<>(contacts.size());
for (Contact c : contacts) if (c.isActive()) active.add(c); for (Contact c : contacts) if (c.isActive()) active.add(c);
return active; return active;
} }

View File

@@ -602,8 +602,8 @@ class CryptoComponentImpl implements CryptoComponent {
// Package access for testing // Package access for testing
int chooseIterationCount(int targetMillis) { int chooseIterationCount(int targetMillis) {
List<Long> quickSamples = new ArrayList<Long>(PBKDF_SAMPLES); List<Long> quickSamples = new ArrayList<>(PBKDF_SAMPLES);
List<Long> slowSamples = new ArrayList<Long>(PBKDF_SAMPLES); List<Long> slowSamples = new ArrayList<>(PBKDF_SAMPLES);
long iterationNanos = 0, initNanos = 0; long iterationNanos = 0, initNanos = 0;
while (iterationNanos <= 0 || initNanos <= 0) { while (iterationNanos <= 0 || initNanos <= 0) {
// Sample the running time with one iteration and two iterations // Sample the running time with one iteration and two iterations

View File

@@ -48,7 +48,7 @@ public class CryptoModule {
public CryptoModule() { public CryptoModule() {
// Use an unbounded queue // Use an unbounded queue
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(); BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy(); new ThreadPoolExecutor.DiscardPolicy();

View File

@@ -16,7 +16,7 @@ class PasswordStrengthEstimatorImpl implements PasswordStrengthEstimator {
@Override @Override
public float estimateStrength(String password) { public float estimateStrength(String password) {
HashSet<Character> unique = new HashSet<Character>(); HashSet<Character> unique = new HashSet<>();
int length = password.length(); int length = password.length();
for (int i = 0; i < length; i++) unique.add(password.charAt(i)); for (int i = 0; i < length; i++) unique.add(password.charAt(i));
return Math.min(1, (float) unique.size() / STRONG_UNIQUE_CHARS); return Math.min(1, (float) unique.size() / STRONG_UNIQUE_CHARS);

View File

@@ -90,8 +90,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
private final ReentrantReadWriteLock lock = private final ReentrantReadWriteLock lock =
new ReentrantReadWriteLock(true); new ReentrantReadWriteLock(true);
private volatile int shutdownHandle = -1;
@Inject @Inject
DatabaseComponentImpl(Database<T> db, Class<T> txnClass, EventBus eventBus, DatabaseComponentImpl(Database<T> db, Class<T> txnClass, EventBus eventBus,
ShutdownManager shutdown) { ShutdownManager shutdown) {
@@ -103,26 +101,20 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override @Override
public boolean open() throws DbException { public boolean open() throws DbException {
Runnable shutdownHook = new Runnable() {
@Override
public void run() {
try {
close();
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
}
};
boolean reopened = db.open(); boolean reopened = db.open();
shutdownHandle = shutdown.addShutdownHook(shutdownHook); shutdown.addShutdownHook(() -> {
try {
close();
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
});
return reopened; return reopened;
} }
@Override @Override
public void close() throws DbException { public void close() throws DbException {
if (closed.getAndSet(true)) return; if (closed.getAndSet(true)) return;
shutdown.removeShutdownHook(shutdownHandle);
db.close(); db.close();
} }
@@ -141,11 +133,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
try { try {
return new Transaction(db.startTransaction(), readOnly); return new Transaction(db.startTransaction(), readOnly);
} catch (DbException e) { } catch (DbException | RuntimeException e) {
if (readOnly) lock.readLock().unlock();
else lock.writeLock().unlock();
throw e;
} catch (RuntimeException e) {
if (readOnly) lock.readLock().unlock(); if (readOnly) lock.readLock().unlock();
else lock.writeLock().unlock(); else lock.writeLock().unlock();
throw e; throw e;
@@ -331,7 +319,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> ids = db.getMessagesToSend(txn, c, maxLength); Collection<MessageId> ids = db.getMessagesToSend(txn, c, maxLength);
List<byte[]> messages = new ArrayList<byte[]>(ids.size()); List<byte[]> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) { for (MessageId m : ids) {
messages.add(db.getRawMessage(txn, m)); messages.add(db.getRawMessage(txn, m));
db.updateExpiryTime(txn, c, m, maxLatency); db.updateExpiryTime(txn, c, m, maxLatency);
@@ -381,7 +369,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> ids = db.getRequestedMessagesToSend(txn, c, Collection<MessageId> ids = db.getRequestedMessagesToSend(txn, c,
maxLength); maxLength);
List<byte[]> messages = new ArrayList<byte[]>(ids.size()); List<byte[]> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) { for (MessageId m : ids) {
messages.add(db.getRawMessage(txn, m)); messages.add(db.getRawMessage(txn, m));
db.updateExpiryTime(txn, c, m, maxLatency); db.updateExpiryTime(txn, c, m, maxLatency);
@@ -661,7 +649,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> acked = new ArrayList<MessageId>(); Collection<MessageId> acked = new ArrayList<>();
for (MessageId m : a.getMessageIds()) { for (MessageId m : a.getMessageIds()) {
if (db.containsVisibleMessage(txn, c, m)) { if (db.containsVisibleMessage(txn, c, m)) {
db.raiseSeenFlag(txn, c, m); db.raiseSeenFlag(txn, c, m);
@@ -770,6 +758,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
transaction.attach(new LocalAuthorRemovedEvent(a)); transaction.attach(new LocalAuthorRemovedEvent(a));
} }
@Override
public void removeMessage(Transaction transaction, MessageId m)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
db.removeMessage(txn, m);
}
@Override @Override
public void removeTransport(Transaction transaction, TransportId t) public void removeTransport(Transaction transaction, TransportId t)
throws DbException { throws DbException {
@@ -886,8 +884,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
Map<ContactId, TransportKeys> keys) throws DbException { Map<ContactId, TransportKeys> keys) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
Map<ContactId, TransportKeys> filtered = Map<ContactId, TransportKeys> filtered = new HashMap<>();
new HashMap<ContactId, TransportKeys>();
for (Entry<ContactId, TransportKeys> e : keys.entrySet()) { for (Entry<ContactId, TransportKeys> e : keys.entrySet()) {
ContactId c = e.getKey(); ContactId c = e.getKey();
TransportKeys k = e.getValue(); TransportKeys k = e.getValue();

View File

@@ -32,7 +32,7 @@ public class DatabaseExecutorModule {
public DatabaseExecutorModule() { public DatabaseExecutorModule() {
// Use an unbounded queue // Use an unbounded queue
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(); BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy(); new ThreadPoolExecutor.DiscardPolicy();

View File

@@ -26,7 +26,7 @@ public class DatabaseModule {
@Singleton @Singleton
DatabaseComponent provideDatabaseComponent(Database<Connection> db, DatabaseComponent provideDatabaseComponent(Database<Connection> db,
EventBus eventBus, ShutdownManager shutdown) { EventBus eventBus, ShutdownManager shutdown) {
return new DatabaseComponentImpl<Connection>(db, Connection.class, return new DatabaseComponentImpl<>(db, Connection.class, eventBus,
eventBus, shutdown); shutdown);
} }
} }

View File

@@ -232,6 +232,30 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " REFERENCES transports (transportId)" + " REFERENCES transports (transportId)"
+ " ON DELETE CASCADE)"; + " ON DELETE CASCADE)";
private static final String INDEX_CONTACTS_BY_AUTHOR_ID =
"CREATE INDEX IF NOT EXISTS contactsByAuthorId"
+ " ON contacts (authorId)";
private static final String INDEX_MESSAGES_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS messagesByGroupId"
+ " ON messages (groupId)";
private static final String INDEX_OFFERS_BY_CONTACT_ID =
"CREATE INDEX IF NOT EXISTS offersByContactId"
+ " ON offers (contactId)";
private static final String INDEX_GROUPS_BY_CLIENT_ID =
"CREATE INDEX IF NOT EXISTS groupsByClientId"
+ " ON groups (clientId)";
private static final String INDEX_MESSAGE_METADATA_BY_MESSAGE_ID =
"CREATE INDEX IF NOT EXISTS messageMetadataByMessageId"
+ " ON messageMetadata (messageId)";
private static final String INDEX_GROUP_METADATA_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS groupMetadataByGroupId"
+ " ON groupMetadata (groupId)";
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(JdbcDatabase.class.getName()); Logger.getLogger(JdbcDatabase.class.getName());
@@ -239,8 +263,8 @@ abstract class JdbcDatabase implements Database<Connection> {
private final String hashType, binaryType, counterType, secretType; private final String hashType, binaryType, counterType, secretType;
private final Clock clock; private final Clock clock;
private final LinkedList<Connection> connections = // Locking: connectionsLock
new LinkedList<Connection>(); // Locking: connectionsLock private final LinkedList<Connection> connections = new LinkedList<>();
private int openConnections = 0; // Locking: connectionsLock private int openConnections = 0; // Locking: connectionsLock
private boolean closed = false; // Locking: connectionsLock private boolean closed = false; // Locking: connectionsLock
@@ -267,7 +291,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new DbException(e); throw new DbException(e);
} }
// Open the database and create the tables if necessary // Open the database and create the tables and indexes if necessary
Connection txn = startTransaction(); Connection txn = startTransaction();
try { try {
if (reopen) { if (reopen) {
@@ -276,6 +300,7 @@ abstract class JdbcDatabase implements Database<Connection> {
createTables(txn); createTables(txn);
storeSchemaVersion(txn); storeSchemaVersion(txn);
} }
createIndexes(txn);
commitTransaction(txn); commitTransaction(txn);
} catch (DbException e) { } catch (DbException e) {
abortTransaction(txn); abortTransaction(txn);
@@ -340,6 +365,23 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
private void createIndexes(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
s.executeUpdate(INDEX_CONTACTS_BY_AUTHOR_ID);
s.executeUpdate(INDEX_MESSAGES_BY_GROUP_ID);
s.executeUpdate(INDEX_OFFERS_BY_CONTACT_ID);
s.executeUpdate(INDEX_GROUPS_BY_CLIENT_ID);
s.executeUpdate(INDEX_MESSAGE_METADATA_BY_MESSAGE_ID);
s.executeUpdate(INDEX_GROUP_METADATA_BY_GROUP_ID);
s.close();
} catch (SQLException e) {
tryToClose(s);
throw new DbException(e);
}
}
private String insertTypeNames(String s) { private String insertTypeNames(String s) {
s = s.replaceAll("HASH", hashType); s = s.replaceAll("HASH", hashType);
s = s.replaceAll("BINARY", binaryType); s = s.replaceAll("BINARY", binaryType);
@@ -993,7 +1035,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " FROM contacts"; + " FROM contacts";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<Contact> contacts = new ArrayList<Contact>(); List<Contact> contacts = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
ContactId contactId = new ContactId(rs.getInt(1)); ContactId contactId = new ContactId(rs.getInt(1));
AuthorId authorId = new AuthorId(rs.getBytes(2)); AuthorId authorId = new AuthorId(rs.getBytes(2));
@@ -1027,7 +1069,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, local.getBytes()); ps.setBytes(1, local.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<ContactId> ids = new ArrayList<ContactId>(); List<ContactId> ids = new ArrayList<>();
while (rs.next()) ids.add(new ContactId(rs.getInt(1))); while (rs.next()) ids.add(new ContactId(rs.getInt(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1052,7 +1094,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, remote.getBytes()); ps.setBytes(1, remote.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<Contact> contacts = new ArrayList<Contact>(); List<Contact> contacts = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
ContactId c = new ContactId(rs.getInt(1)); ContactId c = new ContactId(rs.getInt(1));
String name = rs.getString(2); String name = rs.getString(2);
@@ -1108,7 +1150,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, c.getString()); ps.setString(1, c.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<Group> groups = new ArrayList<Group>(); List<Group> groups = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
byte[] descriptor = rs.getBytes(2); byte[] descriptor = rs.getBytes(2);
@@ -1161,7 +1203,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes()); ps.setBytes(1, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<ContactId> visible = new ArrayList<ContactId>(); List<ContactId> visible = new ArrayList<>();
while (rs.next()) visible.add(new ContactId(rs.getInt(1))); while (rs.next()) visible.add(new ContactId(rs.getInt(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1213,7 +1255,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " FROM localAuthors"; + " FROM localAuthors";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<LocalAuthor> authors = new ArrayList<LocalAuthor>(); List<LocalAuthor> authors = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
AuthorId authorId = new AuthorId(rs.getBytes(1)); AuthorId authorId = new AuthorId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
@@ -1243,7 +1285,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes()); ps.setBytes(1, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1266,7 +1308,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, state.getValue()); ps.setInt(1, state.getValue());
ps.setBytes(2, g.getBytes()); ps.setBytes(2, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1301,7 +1343,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setString(3, e.getKey()); ps.setString(3, e.getKey());
ps.setBytes(4, e.getValue()); ps.setBytes(4, e.getValue());
rs = ps.executeQuery(); rs = ps.executeQuery();
Set<MessageId> ids = new HashSet<MessageId>(); Set<MessageId> ids = new HashSet<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1335,7 +1377,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, DELIVERED.getValue()); ps.setInt(1, DELIVERED.getValue());
ps.setBytes(2, g.getBytes()); ps.setBytes(2, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<MessageId, Metadata> all = new HashMap<MessageId, Metadata>(); Map<MessageId, Metadata> all = new HashMap<>();
Metadata metadata = null; Metadata metadata = null;
MessageId lastMessageId = null; MessageId lastMessageId = null;
while (rs.next()) { while (rs.next()) {
@@ -1364,8 +1406,7 @@ abstract class JdbcDatabase implements Database<Connection> {
Collection<MessageId> matches = getMessageIds(txn, g, query); Collection<MessageId> matches = getMessageIds(txn, g, query);
if (matches.isEmpty()) return Collections.emptyMap(); if (matches.isEmpty()) return Collections.emptyMap();
// Retrieve the metadata for each match // Retrieve the metadata for each match
Map<MessageId, Metadata> all = new HashMap<MessageId, Metadata>( Map<MessageId, Metadata> all = new HashMap<>(matches.size());
matches.size());
for (MessageId m : matches) all.put(m, getMessageMetadata(txn, m)); for (MessageId m : matches) all.put(m, getMessageMetadata(txn, m));
return all; return all;
} }
@@ -1463,7 +1504,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setBytes(1, g.getBytes()); ps.setBytes(1, g.getBytes());
ps.setInt(2, c.getInt()); ps.setInt(2, c.getInt());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageStatus> statuses = new ArrayList<MessageStatus>(); List<MessageStatus> statuses = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
MessageId messageId = new MessageId(rs.getBytes(1)); MessageId messageId = new MessageId(rs.getBytes(1));
boolean sent = rs.getBoolean(2); boolean sent = rs.getBoolean(2);
@@ -1522,7 +1563,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBytes(1, m.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<MessageId, State> dependencies = new HashMap<MessageId, State>(); Map<MessageId, State> dependencies = new HashMap<>();
while (rs.next()) { while (rs.next()) {
MessageId dependency = new MessageId(rs.getBytes(1)); MessageId dependency = new MessageId(rs.getBytes(1));
State state = State.fromValue(rs.getInt(2)); State state = State.fromValue(rs.getInt(2));
@@ -1560,7 +1601,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBytes(1, m.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<MessageId, State> dependents = new HashMap<MessageId, State>(); Map<MessageId, State> dependents = new HashMap<>();
while (rs.next()) { while (rs.next()) {
MessageId dependent = new MessageId(rs.getBytes(1)); MessageId dependent = new MessageId(rs.getBytes(1));
State state = State.fromValue(rs.getInt(2)); State state = State.fromValue(rs.getInt(2));
@@ -1612,7 +1653,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setInt(2, maxMessages); ps.setInt(2, maxMessages);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1648,7 +1689,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setLong(3, now); ps.setLong(3, now);
ps.setInt(4, maxMessages); ps.setInt(4, maxMessages);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1673,7 +1714,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setInt(2, maxMessages); ps.setInt(2, maxMessages);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1708,7 +1749,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(2, DELIVERED.getValue()); ps.setInt(2, DELIVERED.getValue());
ps.setLong(3, now); ps.setLong(3, now);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
int total = 0; int total = 0;
while (rs.next()) { while (rs.next()) {
int length = rs.getInt(1); int length = rs.getInt(1);
@@ -1750,7 +1791,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, state.getValue()); ps.setInt(1, state.getValue());
ps.setString(2, c.getString()); ps.setString(2, c.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1780,7 +1821,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, c.getString()); ps.setString(1, c.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1839,7 +1880,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(2, DELIVERED.getValue()); ps.setInt(2, DELIVERED.getValue());
ps.setLong(3, now); ps.setLong(3, now);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
int total = 0; int total = 0;
while (rs.next()) { while (rs.next()) {
int length = rs.getInt(1); int length = rs.getInt(1);
@@ -1893,7 +1934,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, t.getString()); ps.setString(1, t.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<IncomingKeys> inKeys = new ArrayList<IncomingKeys>(); List<IncomingKeys> inKeys = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
long rotationPeriod = rs.getLong(1); long rotationPeriod = rs.getLong(1);
SecretKey tagKey = new SecretKey(rs.getBytes(2)); SecretKey tagKey = new SecretKey(rs.getBytes(2));
@@ -1913,8 +1954,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, t.getString()); ps.setString(1, t.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<ContactId, TransportKeys> keys = Map<ContactId, TransportKeys> keys = new HashMap<>();
new HashMap<ContactId, TransportKeys>();
for (int i = 0; rs.next(); i++) { for (int i = 0; rs.next(); i++) {
// There should be three times as many incoming keys // There should be three times as many incoming keys
if (inKeys.size() < (i + 1) * 3) throw new DbStateException(); if (inKeys.size() < (i + 1) * 3) throw new DbStateException();
@@ -2032,8 +2072,8 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
// Determine which keys are being removed // Determine which keys are being removed
List<String> removed = new ArrayList<String>(); List<String> removed = new ArrayList<>();
Map<String, byte[]> retained = new HashMap<String, byte[]>(); Map<String, byte[]> retained = new HashMap<>();
for (Entry<String, byte[]> e : meta.entrySet()) { for (Entry<String, byte[]> e : meta.entrySet()) {
if (e.getValue() == REMOVE) removed.add(e.getKey()); if (e.getValue() == REMOVE) removed.add(e.getKey());
else retained.put(e.getKey(), e.getValue()); else retained.put(e.getKey(), e.getValue());

View File

@@ -15,7 +15,7 @@ import javax.annotation.concurrent.ThreadSafe;
class EventBusImpl implements EventBus { class EventBusImpl implements EventBus {
private final Collection<EventListener> listeners = private final Collection<EventListener> listeners =
new CopyOnWriteArrayList<EventListener>(); new CopyOnWriteArrayList<>();
@Override @Override
public void addListener(EventListener l) { public void addListener(EventListener l) {

View File

@@ -50,10 +50,9 @@ class KeyAgreementConnector {
private final PluginManager pluginManager; private final PluginManager pluginManager;
private final CompletionService<KeyAgreementConnection> connect; private final CompletionService<KeyAgreementConnection> connect;
private final List<KeyAgreementListener> listeners = private final List<KeyAgreementListener> listeners = new ArrayList<>();
new ArrayList<KeyAgreementListener>();
private final List<Future<KeyAgreementConnection>> pending = private final List<Future<KeyAgreementConnection>> pending =
new ArrayList<Future<KeyAgreementConnection>>(); new ArrayList<>();
private volatile boolean connecting = false; private volatile boolean connecting = false;
private volatile boolean alice = false; private volatile boolean alice = false;
@@ -65,8 +64,7 @@ class KeyAgreementConnector {
this.clock = clock; this.clock = clock;
this.crypto = crypto; this.crypto = crypto;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
connect = new ExecutorCompletionService<KeyAgreementConnection>( connect = new ExecutorCompletionService<>(ioExecutor);
ioExecutor);
} }
public Payload listen(KeyPair localKeyPair) { public Payload listen(KeyPair localKeyPair) {
@@ -75,8 +73,7 @@ class KeyAgreementConnector {
byte[] commitment = crypto.deriveKeyCommitment( byte[] commitment = crypto.deriveKeyCommitment(
localKeyPair.getPublic().getEncoded()); localKeyPair.getPublic().getEncoded());
// Start all listeners and collect their descriptors // Start all listeners and collect their descriptors
List<TransportDescriptor> descriptors = List<TransportDescriptor> descriptors = new ArrayList<>();
new ArrayList<TransportDescriptor>();
for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) { for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {
KeyAgreementListener l = KeyAgreementListener l =
plugin.createKeyAgreementListener(commitment); plugin.createKeyAgreementListener(commitment);
@@ -132,10 +129,7 @@ class KeyAgreementConnector {
LOG.info("Interrupted while waiting for connection"); LOG.info("Interrupted while waiting for connection");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return null; return null;
} catch (ExecutionException e) { } catch (ExecutionException | IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return null;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return null; return null;
} finally { } finally {

View File

@@ -51,8 +51,7 @@ class PayloadParserImpl implements PayloadParser {
byte[] commitment = payload.getRaw(1); byte[] commitment = payload.getRaw(1);
if (commitment.length != COMMIT_LENGTH) throw new FormatException(); if (commitment.length != COMMIT_LENGTH) throw new FormatException();
// Remaining elements: transport descriptors // Remaining elements: transport descriptors
List<TransportDescriptor> recognised = List<TransportDescriptor> recognised = new ArrayList<>();
new ArrayList<TransportDescriptor>();
for (int i = 2; i < payload.size(); i++) { for (int i = 2; i < payload.size(); i++) {
BdfList descriptor = payload.getList(i); BdfList descriptor = payload.getList(i);
long transportId = descriptor.getLong(0); long transportId = descriptor.getLong(0);

View File

@@ -63,9 +63,9 @@ class LifecycleManagerImpl implements LifecycleManager {
this.crypto = crypto; this.crypto = crypto;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
this.identityManager = identityManager; this.identityManager = identityManager;
services = new CopyOnWriteArrayList<Service>(); services = new CopyOnWriteArrayList<>();
clients = new CopyOnWriteArrayList<Client>(); clients = new CopyOnWriteArrayList<>();
executors = new CopyOnWriteArrayList<ExecutorService>(); executors = new CopyOnWriteArrayList<>();
} }
@Override @Override
@@ -88,7 +88,7 @@ class LifecycleManagerImpl implements LifecycleManager {
executors.add(e); executors.add(e);
} }
private LocalAuthor createLocalAuthor(final String nickname) { private LocalAuthor createLocalAuthor(String nickname) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
KeyPair keyPair = crypto.generateSignatureKeyPair(); KeyPair keyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded(); byte[] publicKey = keyPair.getPublic().getEncoded();
@@ -203,9 +203,7 @@ class LifecycleManagerImpl implements LifecycleManager {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Closing database took " + duration + " ms"); LOG.info("Closing database took " + duration + " ms");
shutdownLatch.countDown(); shutdownLatch.countDown();
} catch (DbException e) { } catch (DbException | ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} finally { } finally {
startStopSemaphore.release(); startStopSemaphore.release();

View File

@@ -37,7 +37,7 @@ public class LifecycleModule {
public LifecycleModule() { public LifecycleModule() {
// The thread pool is unbounded, so use direct handoff // The thread pool is unbounded, so use direct handoff
BlockingQueue<Runnable> queue = new SynchronousQueue<Runnable>(); BlockingQueue<Runnable> queue = new SynchronousQueue<>();
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy(); new ThreadPoolExecutor.DiscardPolicy();

View File

@@ -21,7 +21,7 @@ class ShutdownManagerImpl implements ShutdownManager {
private int nextHandle = 0; private int nextHandle = 0;
ShutdownManagerImpl() { ShutdownManagerImpl() {
hooks = new HashMap<Integer, Thread>(); hooks = new HashMap<>();
} }
@Override @Override

View File

@@ -134,11 +134,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false);
return;
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false); disposeReader(true, false);
return; return;
@@ -249,11 +245,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false);
return;
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false); disposeReader(true, false);
return; return;
@@ -266,12 +258,7 @@ class ConnectionManagerImpl implements ConnectionManager {
contactId = ctx.getContactId(); contactId = ctx.getContactId();
connectionRegistry.registerConnection(contactId, transportId, true); connectionRegistry.registerConnection(contactId, transportId, true);
// Start the outgoing session on another thread // Start the outgoing session on another thread
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::runOutgoingSession);
@Override
public void run() {
runOutgoingSession();
}
});
try { try {
// Create and run the incoming session // Create and run the incoming session
incomingSession = createIncomingSession(ctx, reader); incomingSession = createIncomingSession(ctx, reader);
@@ -368,12 +355,7 @@ class ConnectionManagerImpl implements ConnectionManager {
return; return;
} }
// Start the incoming session on another thread // Start the incoming session on another thread
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::runIncomingSession);
@Override
public void run() {
runIncomingSession();
}
});
try { try {
// Create and run the outgoing session // Create and run the outgoing session
outgoingSession = createDuplexOutgoingSession(ctx, writer); outgoingSession = createDuplexOutgoingSession(ctx, writer);
@@ -391,11 +373,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false);
return;
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false); disposeReader(true, false);
return; return;

View File

@@ -42,8 +42,8 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
@Inject @Inject
ConnectionRegistryImpl(EventBus eventBus) { ConnectionRegistryImpl(EventBus eventBus) {
this.eventBus = eventBus; this.eventBus = eventBus;
connections = new HashMap<TransportId, Map<ContactId, Integer>>(); connections = new HashMap<>();
contactCounts = new HashMap<ContactId, Integer>(); contactCounts = new HashMap<>();
} }
@Override @Override
@@ -58,7 +58,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
try { try {
Map<ContactId, Integer> m = connections.get(t); Map<ContactId, Integer> m = connections.get(t);
if (m == null) { if (m == null) {
m = new HashMap<ContactId, Integer>(); m = new HashMap<>();
connections.put(t, m); connections.put(t, m);
} }
Integer count = m.get(c); Integer count = m.get(c);
@@ -124,7 +124,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
try { try {
Map<ContactId, Integer> m = connections.get(t); Map<ContactId, Integer> m = connections.get(t);
if (m == null) return Collections.emptyList(); if (m == null) return Collections.emptyList();
List<ContactId> ids = new ArrayList<ContactId>(m.keySet()); List<ContactId> ids = new ArrayList<>(m.keySet());
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info(ids.size() + " contacts connected"); LOG.info(ids.size() + " contacts connected");
return ids; return ids;

View File

@@ -82,10 +82,10 @@ class PluginManagerImpl implements PluginManager, Service {
this.settingsManager = settingsManager; this.settingsManager = settingsManager;
this.transportPropertyManager = transportPropertyManager; this.transportPropertyManager = transportPropertyManager;
this.uiCallback = uiCallback; this.uiCallback = uiCallback;
plugins = new ConcurrentHashMap<TransportId, Plugin>(); plugins = new ConcurrentHashMap<>();
simplexPlugins = new CopyOnWriteArrayList<SimplexPlugin>(); simplexPlugins = new CopyOnWriteArrayList<>();
duplexPlugins = new CopyOnWriteArrayList<DuplexPlugin>(); duplexPlugins = new CopyOnWriteArrayList<>();
startLatches = new ConcurrentHashMap<TransportId, CountDownLatch>(); startLatches = new ConcurrentHashMap<>();
} }
@Override @Override
@@ -156,17 +156,17 @@ class PluginManagerImpl implements PluginManager, Service {
@Override @Override
public Collection<SimplexPlugin> getSimplexPlugins() { public Collection<SimplexPlugin> getSimplexPlugins() {
return new ArrayList<SimplexPlugin>(simplexPlugins); return new ArrayList<>(simplexPlugins);
} }
@Override @Override
public Collection<DuplexPlugin> getDuplexPlugins() { public Collection<DuplexPlugin> getDuplexPlugins() {
return new ArrayList<DuplexPlugin>(duplexPlugins); return new ArrayList<>(duplexPlugins);
} }
@Override @Override
public Collection<DuplexPlugin> getKeyAgreementPlugins() { public Collection<DuplexPlugin> getKeyAgreementPlugins() {
List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>(); List<DuplexPlugin> supported = new ArrayList<>();
for (DuplexPlugin d : duplexPlugins) for (DuplexPlugin d : duplexPlugins)
if (d.supportsKeyAgreement()) supported.add(d); if (d.supportsKeyAgreement()) supported.add(d);
return supported; return supported;

View File

@@ -66,7 +66,7 @@ class Poller implements EventListener {
this.random = random; this.random = random;
this.clock = clock; this.clock = clock;
lock = new ReentrantLock(); lock = new ReentrantLock();
tasks = new HashMap<TransportId, PollTask>(); tasks = new HashMap<>();
} }
@Override @Override
@@ -111,30 +111,24 @@ class Poller implements EventListener {
connectToContact(c, (DuplexPlugin) p); connectToContact(c, (DuplexPlugin) p);
} }
private void connectToContact(final ContactId c, final SimplexPlugin p) { private void connectToContact(ContactId c, SimplexPlugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override TransportId t = p.getId();
public void run() { if (!connectionRegistry.isConnected(c, t)) {
TransportId t = p.getId(); TransportConnectionWriter w = p.createWriter(c);
if (!connectionRegistry.isConnected(c, t)) { if (w != null)
TransportConnectionWriter w = p.createWriter(c); connectionManager.manageOutgoingConnection(c, t, w);
if (w != null)
connectionManager.manageOutgoingConnection(c, t, w);
}
} }
}); });
} }
private void connectToContact(final ContactId c, final DuplexPlugin p) { private void connectToContact(ContactId c, DuplexPlugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override TransportId t = p.getId();
public void run() { if (!connectionRegistry.isConnected(c, t)) {
TransportId t = p.getId(); DuplexTransportConnection d = p.createConnection(c);
if (!connectionRegistry.isConnected(c, t)) { if (d != null)
DuplexTransportConnection d = p.createConnection(c); connectionManager.manageOutgoingConnection(c, t, d);
if (d != null)
connectionManager.manageOutgoingConnection(c, t, d);
}
} }
}); });
} }
@@ -159,14 +153,10 @@ class Poller implements EventListener {
try { try {
PollTask scheduled = tasks.get(t); PollTask scheduled = tasks.get(t);
if (scheduled == null || due < scheduled.due) { if (scheduled == null || due < scheduled.due) {
final PollTask task = new PollTask(p, due, randomiseNext); PollTask task = new PollTask(p, due, randomiseNext);
tasks.put(t, task); tasks.put(t, task);
scheduler.schedule(new Runnable() { scheduler.schedule(
@Override () -> ioExecutor.execute(task), delay, MILLISECONDS);
public void run() {
ioExecutor.execute(task);
}
}, delay, MILLISECONDS);
} }
} finally { } finally {
lock.unlock(); lock.unlock();
@@ -174,7 +164,7 @@ class Poller implements EventListener {
} }
@IoExecutor @IoExecutor
private void poll(final Plugin p) { private void poll(Plugin p) {
TransportId t = p.getId(); TransportId t = p.getId();
if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t); if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t);
p.poll(connectionRegistry.getConnectedContacts(t)); p.poll(connectionRegistry.getConnectedContacts(t));

View File

@@ -108,7 +108,7 @@ abstract class FilePlugin implements SimplexPlugin {
} }
} }
protected void createReaderFromFile(final File f) { protected void createReaderFromFile(File f) {
if (!running) return; if (!running) return;
ioExecutor.execute(new ReaderCreator(f)); ioExecutor.execute(new ReaderCreator(f));
} }

View File

@@ -63,7 +63,7 @@ class LanTcpPlugin extends TcpPlugin {
TransportProperties p = callback.getLocalProperties(); TransportProperties p = callback.getLocalProperties();
String oldIpPorts = p.get(PROP_IP_PORTS); String oldIpPorts = p.get(PROP_IP_PORTS);
List<InetSocketAddress> olds = parseSocketAddresses(oldIpPorts); List<InetSocketAddress> olds = parseSocketAddresses(oldIpPorts);
List<InetSocketAddress> locals = new LinkedList<InetSocketAddress>(); List<InetSocketAddress> locals = new LinkedList<>();
for (InetAddress local : getLocalIpAddresses()) { for (InetAddress local : getLocalIpAddresses()) {
if (isAcceptableAddress(local)) { if (isAcceptableAddress(local)) {
// If this is the old address, try to use the same port // If this is the old address, try to use the same port
@@ -82,7 +82,7 @@ class LanTcpPlugin extends TcpPlugin {
private List<InetSocketAddress> parseSocketAddresses(String ipPorts) { private List<InetSocketAddress> parseSocketAddresses(String ipPorts) {
if (StringUtils.isNullOrEmpty(ipPorts)) return Collections.emptyList(); if (StringUtils.isNullOrEmpty(ipPorts)) return Collections.emptyList();
String[] split = ipPorts.split(SEPARATOR); String[] split = ipPorts.split(SEPARATOR);
List<InetSocketAddress> addresses = new ArrayList<InetSocketAddress>(); List<InetSocketAddress> addresses = new ArrayList<>();
for (String ipPort : split) { for (String ipPort : split) {
InetSocketAddress a = parseSocketAddress(ipPort); InetSocketAddress a = parseSocketAddress(ipPort);
if (a != null) addresses.add(a); if (a != null) addresses.add(a);
@@ -95,7 +95,7 @@ class LanTcpPlugin extends TcpPlugin {
String ipPort = getIpPortString(a); String ipPort = getIpPortString(a);
// Get the list of recently used addresses // Get the list of recently used addresses
String setting = callback.getSettings().get(PREF_LAN_IP_PORTS); String setting = callback.getSettings().get(PREF_LAN_IP_PORTS);
List<String> recent = new ArrayList<String>(); List<String> recent = new ArrayList<>();
if (!StringUtils.isNullOrEmpty(setting)) if (!StringUtils.isNullOrEmpty(setting))
Collections.addAll(recent, setting.split(SEPARATOR)); Collections.addAll(recent, setting.split(SEPARATOR));
// Is the address already in the list? // Is the address already in the list?
@@ -111,7 +111,7 @@ class LanTcpPlugin extends TcpPlugin {
recent = recent.subList(0, MAX_ADDRESSES); recent = recent.subList(0, MAX_ADDRESSES);
setting = StringUtils.join(recent, SEPARATOR); setting = StringUtils.join(recent, SEPARATOR);
// Update the list of addresses shared with contacts // Update the list of addresses shared with contacts
List<String> shared = new ArrayList<String>(recent); List<String> shared = new ArrayList<>(recent);
Collections.sort(shared); Collections.sort(shared);
String property = StringUtils.join(shared, SEPARATOR); String property = StringUtils.join(shared, SEPARATOR);
TransportProperties properties = new TransportProperties(); TransportProperties properties = new TransportProperties();
@@ -260,16 +260,12 @@ class LanTcpPlugin extends TcpPlugin {
@Override @Override
public Callable<KeyAgreementConnection> listen() { public Callable<KeyAgreementConnection> listen() {
return new Callable<KeyAgreementConnection>() { return () -> {
@Override Socket s = ss.accept();
public KeyAgreementConnection call() throws IOException { if (LOG.isLoggable(INFO))
Socket s = ss.accept(); LOG.info(ID.getString() + ": Incoming connection");
if (LOG.isLoggable(INFO)) return new KeyAgreementConnection(
LOG.info(ID.getString() + ": Incoming connection"); new TcpTransportConnection(LanTcpPlugin.this, s), ID);
return new KeyAgreementConnection(
new TcpTransportConnection(LanTcpPlugin.this, s),
ID);
}
}; };
} }

View File

@@ -37,7 +37,7 @@ class PortMapperImpl implements PortMapper {
} }
@Override @Override
public MappingResult map(final int port) { public MappingResult map(int port) {
if (!started.getAndSet(true)) start(); if (!started.getAndSet(true)) start();
if (gateway == null) return null; if (gateway == null) return null;
InetAddress internal = gateway.getLocalAddress(); InetAddress internal = gateway.getLocalAddress();
@@ -50,12 +50,7 @@ class PortMapperImpl implements PortMapper {
succeeded = gateway.addPortMapping(port, port, succeeded = gateway.addPortMapping(port, port,
getHostAddress(internal), "TCP", "TCP"); getHostAddress(internal), "TCP", "TCP");
if (succeeded) { if (succeeded) {
shutdownManager.addShutdownHook(new Runnable() { shutdownManager.addShutdownHook(() -> deleteMapping(port));
@Override
public void run() {
deleteMapping(port);
}
});
} }
String externalString = gateway.getExternalIPAddress(); String externalString = gateway.getExternalIPAddress();
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
@@ -63,9 +58,7 @@ class PortMapperImpl implements PortMapper {
"External address " + scrubInetAddress(externalString)); "External address " + scrubInetAddress(externalString));
if (externalString != null) if (externalString != null)
external = InetAddress.getByName(externalString); external = InetAddress.getByName(externalString);
} catch (IOException e) { } catch (IOException | SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
return new MappingResult(internal, external, port, succeeded); return new MappingResult(internal, external, port, succeeded);
@@ -82,11 +75,7 @@ class PortMapperImpl implements PortMapper {
GatewayDiscover d = new GatewayDiscover(); GatewayDiscover d = new GatewayDiscover();
try { try {
d.discover(); d.discover();
} catch (IOException e) { } catch (IOException | SAXException | ParserConfigurationException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (ParserConfigurationException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
gateway = d.getValidGateway(); gateway = d.getValidGateway();
@@ -97,9 +86,7 @@ class PortMapperImpl implements PortMapper {
gateway.deletePortMapping(port, "TCP"); gateway.deletePortMapping(port, "TCP");
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Deleted mapping for port " + port); LOG.info("Deleted mapping for port " + port);
} catch (IOException e) { } catch (IOException | SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
} }

View File

@@ -110,41 +110,37 @@ abstract class TcpPlugin implements DuplexPlugin {
} }
protected void bind() { protected void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { ServerSocket ss = null;
if (!running) return; for (InetSocketAddress addr : getLocalSocketAddresses()) {
ServerSocket ss = null; try {
for (InetSocketAddress addr : getLocalSocketAddresses()) { ss = new ServerSocket();
try { ss.bind(addr);
ss = new ServerSocket(); break;
ss.bind(addr); } catch (IOException e) {
break; if (LOG.isLoggable(INFO))
} catch (IOException e) { LOG.info("Failed to bind " + scrubSocketAddress(addr));
if (LOG.isLoggable(INFO))
LOG.info("Failed to bind " +
scrubSocketAddress(addr));
tryToClose(ss);
}
}
if (ss == null || !ss.isBound()) {
LOG.info("Could not bind server socket");
return;
}
if (!running) {
tryToClose(ss); tryToClose(ss);
return;
} }
socket = ss;
backoff.reset();
InetSocketAddress local =
(InetSocketAddress) ss.getLocalSocketAddress();
setLocalSocketAddress(local);
if (LOG.isLoggable(INFO))
LOG.info("Listening on " + scrubSocketAddress(local));
callback.transportEnabled();
acceptContactConnections();
} }
if (ss == null || !ss.isBound()) {
LOG.info("Could not bind server socket");
return;
}
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
backoff.reset();
InetSocketAddress local =
(InetSocketAddress) ss.getLocalSocketAddress();
setLocalSocketAddress(local);
if (LOG.isLoggable(INFO))
LOG.info("Listening on " + scrubSocketAddress(local));
callback.transportEnabled();
acceptContactConnections();
}); });
} }
@@ -218,17 +214,13 @@ abstract class TcpPlugin implements DuplexPlugin {
} }
} }
private void connectAndCallBack(final ContactId c, private void connectAndCallBack(ContactId c, TransportProperties p) {
final TransportProperties p) { ioExecutor.execute(() -> {
ioExecutor.execute(new Runnable() { if (!isRunning()) return;
@Override DuplexTransportConnection d = createConnection(p);
public void run() { if (d != null) {
if (!isRunning()) return; backoff.reset();
DuplexTransportConnection d = createConnection(p); callback.outgoingConnectionCreated(c, d);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
}
} }
}); });
} }
@@ -317,7 +309,7 @@ abstract class TcpPlugin implements DuplexPlugin {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return Collections.emptyList(); return Collections.emptyList();
} }
List<InetAddress> addrs = new ArrayList<InetAddress>(); List<InetAddress> addrs = new ArrayList<>();
for (NetworkInterface iface : ifaces) for (NetworkInterface iface : ifaces)
addrs.addAll(Collections.list(iface.getInetAddresses())); addrs.addAll(Collections.list(iface.getInetAddresses()));
return addrs; return addrs;

View File

@@ -43,7 +43,7 @@ class WanTcpPlugin extends TcpPlugin {
// Use the same address and port as last time if available // Use the same address and port as last time if available
TransportProperties p = callback.getLocalProperties(); TransportProperties p = callback.getLocalProperties();
InetSocketAddress old = parseSocketAddress(p.get(PROP_IP_PORT)); InetSocketAddress old = parseSocketAddress(p.get(PROP_IP_PORT));
List<InetSocketAddress> addrs = new LinkedList<InetSocketAddress>(); List<InetSocketAddress> addrs = new LinkedList<>();
for (InetAddress a : getLocalIpAddresses()) { for (InetAddress a : getLocalIpAddresses()) {
if (isAcceptableAddress(a)) { if (isAcceptableAddress(a)) {
// If this is the old address, try to use the same port // If this is the old address, try to use the same port

View File

@@ -40,9 +40,12 @@ public class PropertiesModule {
@Provides @Provides
@Singleton @Singleton
TransportPropertyManager getTransportPropertyManager( TransportPropertyManager getTransportPropertyManager(
LifecycleManager lifecycleManager, ContactManager contactManager, LifecycleManager lifecycleManager,
ValidationManager validationManager, ContactManager contactManager,
TransportPropertyManagerImpl transportPropertyManager) { TransportPropertyManagerImpl transportPropertyManager) {
lifecycleManager.registerClient(transportPropertyManager); lifecycleManager.registerClient(transportPropertyManager);
validationManager.registerIncomingMessageHook(CLIENT_ID,
transportPropertyManager);
contactManager.registerAddContactHook(transportPropertyManager); contactManager.registerAddContactHook(transportPropertyManager);
contactManager.registerRemoveContactHook(transportPropertyManager); contactManager.registerRemoveContactHook(transportPropertyManager);
return transportPropertyManager; return transportPropertyManager;

View File

@@ -9,8 +9,10 @@ import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook; import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
@@ -19,8 +21,10 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.Client; import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import java.util.HashMap; import java.util.HashMap;
@@ -36,20 +40,22 @@ import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class TransportPropertyManagerImpl implements TransportPropertyManager, class TransportPropertyManagerImpl implements TransportPropertyManager,
Client, AddContactHook, RemoveContactHook { Client, AddContactHook, RemoveContactHook, IncomingMessageHook {
private final DatabaseComponent db; private final DatabaseComponent db;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final MetadataParser metadataParser;
private final ContactGroupFactory contactGroupFactory; private final ContactGroupFactory contactGroupFactory;
private final Clock clock; private final Clock clock;
private final Group localGroup; private final Group localGroup;
@Inject @Inject
TransportPropertyManagerImpl(DatabaseComponent db, TransportPropertyManagerImpl(DatabaseComponent db,
ClientHelper clientHelper, ContactGroupFactory contactGroupFactory, ClientHelper clientHelper, MetadataParser metadataParser,
Clock clock) { ContactGroupFactory contactGroupFactory, Clock clock) {
this.db = db; this.db = db;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.metadataParser = metadataParser;
this.contactGroupFactory = contactGroupFactory; this.contactGroupFactory = contactGroupFactory;
this.clock = clock; this.clock = clock;
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID); localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID);
@@ -57,6 +63,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void createLocalState(Transaction txn) throws DbException {
if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup); db.addGroup(txn, localGroup);
// Ensure we've set things up for any pre-existing contacts // Ensure we've set things up for any pre-existing contacts
for (Contact c : db.getContacts(txn)) addingContact(txn, c); for (Contact c : db.getContacts(txn)) addingContact(txn, c);
@@ -84,6 +91,31 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
db.removeGroup(txn, getContactGroup(c)); db.removeGroup(txn, getContactGroup(c));
} }
@Override
public boolean incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException {
try {
// Find the latest update for this transport, if any
BdfDictionary d = metadataParser.parse(meta);
TransportId t = new TransportId(d.getString("transportId"));
LatestUpdate latest = findLatest(txn, m.getGroupId(), t, false);
if (latest != null) {
if (d.getLong("version") > latest.version) {
// This update is newer - delete the previous update
db.deleteMessage(txn, latest.messageId);
db.deleteMessageMetadata(txn, latest.messageId);
} else {
// We've already received a newer update - delete this one
db.deleteMessage(txn, m.getId());
db.deleteMessageMetadata(txn, m.getId());
}
}
} catch (FormatException e) {
throw new InvalidMessageException(e);
}
return false;
}
@Override @Override
public void addRemoteProperties(Transaction txn, ContactId c, public void addRemoteProperties(Transaction txn, ContactId c,
Map<TransportId, TransportProperties> props) throws DbException { Map<TransportId, TransportProperties> props) throws DbException {
@@ -98,7 +130,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public Map<TransportId, TransportProperties> getLocalProperties() public Map<TransportId, TransportProperties> getLocalProperties()
throws DbException { throws DbException {
Map<TransportId, TransportProperties> local; Map<TransportId, TransportProperties> local;
Transaction txn = db.startTransaction(true); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(false);
try { try {
local = getLocalProperties(txn); local = getLocalProperties(txn);
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -112,11 +145,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public Map<TransportId, TransportProperties> getLocalProperties( public Map<TransportId, TransportProperties> getLocalProperties(
Transaction txn) throws DbException { Transaction txn) throws DbException {
try { try {
Map<TransportId, TransportProperties> local = Map<TransportId, TransportProperties> local = new HashMap<>();
new HashMap<TransportId, TransportProperties>();
// Find the latest local update for each transport // Find the latest local update for each transport
Map<TransportId, LatestUpdate> latest = findLatest(txn, Map<TransportId, LatestUpdate> latest = findLatestLocal(txn);
localGroup.getId(), true);
// Retrieve and parse the latest local properties // Retrieve and parse the latest local properties
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) { for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
BdfList message = clientHelper.getMessageAsList(txn, BdfList message = clientHelper.getMessageAsList(txn,
@@ -135,7 +166,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
throws DbException { throws DbException {
try { try {
TransportProperties p = null; TransportProperties p = null;
Transaction txn = db.startTransaction(true); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(false);
try { try {
// Find the latest local update // Find the latest local update
LatestUpdate latest = findLatest(txn, localGroup.getId(), t, LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
@@ -160,9 +192,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override @Override
public Map<ContactId, TransportProperties> getRemoteProperties( public Map<ContactId, TransportProperties> getRemoteProperties(
TransportId t) throws DbException { TransportId t) throws DbException {
Map<ContactId, TransportProperties> remote = Map<ContactId, TransportProperties> remote = new HashMap<>();
new HashMap<ContactId, TransportProperties>(); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(false);
try { try {
for (Contact c : db.getContacts(txn)) for (Contact c : db.getContacts(txn))
remote.put(c.getId(), getRemoteProperties(txn, c, t)); remote.put(c.getId(), getRemoteProperties(txn, c, t));
@@ -196,7 +228,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public TransportProperties getRemoteProperties(ContactId c, TransportId t) public TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException { throws DbException {
TransportProperties p; TransportProperties p;
Transaction txn = db.startTransaction(true); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(false);
try { try {
p = getRemoteProperties(txn, db.getContact(txn, c), t); p = getRemoteProperties(txn, db.getContact(txn, c), t);
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -234,6 +267,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
long version = latest == null ? 1 : latest.version + 1; long version = latest == null ? 1 : latest.version + 1;
storeMessage(txn, localGroup.getId(), t, merged, version, storeMessage(txn, localGroup.getId(), t, merged, version,
true, false); true, false);
// Delete the previous update, if any
if (latest != null)
db.removeMessage(txn, latest.messageId);
// Store the merged properties in each contact's group // Store the merged properties in each contact's group
for (Contact c : db.getContacts(txn)) { for (Contact c : db.getContacts(txn)) {
Group g = getContactGroup(c); Group g = getContactGroup(c);
@@ -241,6 +277,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
version = latest == null ? 1 : latest.version + 1; version = latest == null ? 1 : latest.version + 1;
storeMessage(txn, g.getId(), t, merged, version, storeMessage(txn, g.getId(), t, merged, version,
true, true); true, true);
// Delete the previous update, if any
if (latest != null)
db.removeMessage(txn, latest.messageId);
} }
} }
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -278,20 +317,26 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
return BdfList.of(t.getString(), version, p); return BdfList.of(t.getString(), version, p);
} }
private Map<TransportId, LatestUpdate> findLatest(Transaction txn, private Map<TransportId, LatestUpdate> findLatestLocal(Transaction txn)
GroupId g, boolean local) throws DbException, FormatException { throws DbException, FormatException {
Map<TransportId, LatestUpdate> latestUpdates = // TODO: This can be simplified before 1.0
new HashMap<TransportId, LatestUpdate>(); Map<TransportId, LatestUpdate> latestUpdates = new HashMap<>();
Map<MessageId, BdfDictionary> metadata = Map<MessageId, BdfDictionary> metadata = clientHelper
clientHelper.getMessageMetadataAsDictionary(txn, g); .getMessageMetadataAsDictionary(txn, localGroup.getId());
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) { for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
BdfDictionary meta = e.getValue(); BdfDictionary meta = e.getValue();
if (meta.getBoolean("local") == local) { TransportId t = new TransportId(meta.getString("transportId"));
TransportId t = new TransportId(meta.getString("transportId")); long version = meta.getLong("version");
long version = meta.getLong("version"); LatestUpdate latest = latestUpdates.get(t);
LatestUpdate latest = latestUpdates.get(t); if (latest == null) {
if (latest == null || version > latest.version) latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
latestUpdates.put(t, new LatestUpdate(e.getKey(), version)); } else if (version > latest.version) {
// This update is newer - delete the previous one
db.removeMessage(txn, latest.messageId);
latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
} else {
// We've already found a newer update - delete this one
db.removeMessage(txn, e.getKey());
} }
} }
return latestUpdates; return latestUpdates;
@@ -300,6 +345,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Nullable @Nullable
private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t, private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t,
boolean local) throws DbException, FormatException { boolean local) throws DbException, FormatException {
// TODO: This can be simplified before 1.0
LatestUpdate latest = null; LatestUpdate latest = null;
Map<MessageId, BdfDictionary> metadata = Map<MessageId, BdfDictionary> metadata =
clientHelper.getMessageMetadataAsDictionary(txn, g); clientHelper.getMessageMetadataAsDictionary(txn, g);
@@ -308,8 +354,26 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
if (meta.getString("transportId").equals(t.getString()) if (meta.getString("transportId").equals(t.getString())
&& meta.getBoolean("local") == local) { && meta.getBoolean("local") == local) {
long version = meta.getLong("version"); long version = meta.getLong("version");
if (latest == null || version > latest.version) if (latest == null) {
latest = new LatestUpdate(e.getKey(), version); latest = new LatestUpdate(e.getKey(), version);
} else if (version > latest.version) {
// This update is newer - delete the previous one
if (local) {
db.removeMessage(txn, latest.messageId);
} else {
db.deleteMessage(txn, latest.messageId);
db.deleteMessageMetadata(txn, latest.messageId);
}
latest = new LatestUpdate(e.getKey(), version);
} else {
// We've already found a newer update - delete this one
if (local) {
db.removeMessage(txn, e.getKey());
} else {
db.deleteMessage(txn, e.getKey());
db.deleteMessageMetadata(txn, e.getKey());
}
}
} }
} }
return latest; return latest;

View File

@@ -41,7 +41,7 @@ class Receiver implements ReadHandler {
Receiver(Clock clock, Sender sender) { Receiver(Clock clock, Sender sender) {
this.sender = sender; this.sender = sender;
this.clock = clock; this.clock = clock;
dataFrames = new TreeSet<Data>(new SequenceNumberComparator()); dataFrames = new TreeSet<>(new SequenceNumberComparator());
} }
Data read() throws IOException, InterruptedException { Data read() throws IOException, InterruptedException {

View File

@@ -42,48 +42,44 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
this.executor = executor; this.executor = executor;
this.clock = clock; this.clock = clock;
this.writeHandler = writeHandler; this.writeHandler = writeHandler;
writes = new LinkedBlockingQueue<byte[]>(); writes = new LinkedBlockingQueue<>();
} }
@Override @Override
public void start() { public void start() {
SlipEncoder encoder = new SlipEncoder(this); SlipEncoder encoder = new SlipEncoder(this);
final Sender sender = new Sender(clock, encoder); Sender sender = new Sender(clock, encoder);
receiver = new Receiver(clock, sender); receiver = new Receiver(clock, sender);
decoder = new SlipDecoder(receiver, Data.MAX_LENGTH); decoder = new SlipDecoder(receiver, Data.MAX_LENGTH);
inputStream = new ReceiverInputStream(receiver); inputStream = new ReceiverInputStream(receiver);
outputStream = new SenderOutputStream(sender); outputStream = new SenderOutputStream(sender);
running = true; running = true;
executor.execute(new Runnable() { executor.execute(() -> {
@Override long now = clock.currentTimeMillis();
public void run() { long next = now + TICK_INTERVAL;
long now = clock.currentTimeMillis(); try {
long next = now + TICK_INTERVAL; while (running) {
try { byte[] b = null;
while (running) { while (now < next && b == null) {
byte[] b = null; b = writes.poll(next - now, MILLISECONDS);
while (now < next && b == null) { if (!running) return;
b = writes.poll(next - now, MILLISECONDS); now = clock.currentTimeMillis();
if (!running) return; }
now = clock.currentTimeMillis(); if (b == null) {
} sender.tick();
if (b == null) { while (next <= now) next += TICK_INTERVAL;
sender.tick(); } else {
while (next <= now) next += TICK_INTERVAL; if (b.length == 0) return; // Poison pill
} else { writeHandler.handleWrite(b);
if (b.length == 0) return; // Poison pill
writeHandler.handleWrite(b);
}
} }
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting to write");
Thread.currentThread().interrupt();
running = false;
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
running = false;
} }
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting to write");
Thread.currentThread().interrupt();
running = false;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
running = false;
} }
}); });
} }

View File

@@ -46,7 +46,7 @@ class Sender {
Sender(Clock clock, WriteHandler writeHandler) { Sender(Clock clock, WriteHandler writeHandler) {
this.clock = clock; this.clock = clock;
this.writeHandler = writeHandler; this.writeHandler = writeHandler;
outstanding = new LinkedList<Outstanding>(); outstanding = new LinkedList<>();
} }
void sendAck(long sequenceNumber, int windowSize) throws IOException { void sendAck(long sequenceNumber, int windowSize) throws IOException {
@@ -136,7 +136,7 @@ class Sender {
if (now - o.lastTransmitted > rto) { if (now - o.lastTransmitted > rto) {
it.remove(); it.remove();
if (retransmit == null) if (retransmit == null)
retransmit = new ArrayList<Outstanding>(); retransmit = new ArrayList<>();
retransmit.add(o); retransmit.add(o);
// Update the retransmission timeout // Update the retransmission timeout
rto <<= 1; rto <<= 1;

View File

@@ -54,12 +54,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(DuplexOutgoingSession.class.getName()); Logger.getLogger(DuplexOutgoingSession.class.getName());
private static final ThrowingRunnable<IOException> CLOSE = private static final ThrowingRunnable<IOException> CLOSE = () -> {};
new ThrowingRunnable<IOException>() {
@Override
public void run() {
}
};
private final DatabaseComponent db; private final DatabaseComponent db;
private final Executor dbExecutor; private final Executor dbExecutor;
@@ -83,7 +78,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime; this.maxIdleTime = maxIdleTime;
this.recordWriter = recordWriter; this.recordWriter = recordWriter;
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>(); writerTasks = new LinkedBlockingQueue<>();
} }
@IoExecutor @IoExecutor

View File

@@ -116,7 +116,7 @@ class RecordReaderImpl implements RecordReader {
private List<MessageId> readMessageIds() throws IOException { private List<MessageId> readMessageIds() throws IOException {
if (payloadLength == 0) throw new FormatException(); if (payloadLength == 0) throw new FormatException();
if (payloadLength % UniqueId.LENGTH != 0) throw new FormatException(); if (payloadLength % UniqueId.LENGTH != 0) throw new FormatException();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
for (int off = 0; off < payloadLength; off += UniqueId.LENGTH) { for (int off = 0; off < payloadLength; off += UniqueId.LENGTH) {
byte[] id = new byte[UniqueId.LENGTH]; byte[] id = new byte[UniqueId.LENGTH];
System.arraycopy(payload, off, id, 0, UniqueId.LENGTH); System.arraycopy(payload, off, id, 0, UniqueId.LENGTH);

View File

@@ -43,12 +43,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SimplexOutgoingSession.class.getName()); Logger.getLogger(SimplexOutgoingSession.class.getName());
private static final ThrowingRunnable<IOException> CLOSE = private static final ThrowingRunnable<IOException> CLOSE = () -> {};
new ThrowingRunnable<IOException>() {
@Override
public void run() {
}
};
private final DatabaseComponent db; private final DatabaseComponent db;
private final Executor dbExecutor; private final Executor dbExecutor;
@@ -71,7 +66,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.recordWriter = recordWriter; this.recordWriter = recordWriter;
outstandingQueries = new AtomicInteger(2); // One per type of record outstandingQueries = new AtomicInteger(2); // One per type of record
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>(); writerTasks = new LinkedBlockingQueue<>();
} }
@IoExecutor @IoExecutor

View File

@@ -64,8 +64,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
this.dbExecutor = dbExecutor; this.dbExecutor = dbExecutor;
this.validationExecutor = validationExecutor; this.validationExecutor = validationExecutor;
this.messageFactory = messageFactory; this.messageFactory = messageFactory;
validators = new ConcurrentHashMap<ClientId, MessageValidator>(); validators = new ConcurrentHashMap<>();
hooks = new ConcurrentHashMap<ClientId, IncomingMessageHook>(); hooks = new ConcurrentHashMap<>();
} }
@Override @Override
@@ -93,19 +93,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
hooks.put(c, hook); hooks.put(c, hook);
} }
private void validateOutstandingMessagesAsync(final ClientId c) { private void validateOutstandingMessagesAsync(ClientId c) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> validateOutstandingMessages(c));
@Override
public void run() {
validateOutstandingMessages(c);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void validateOutstandingMessages(ClientId c) { private void validateOutstandingMessages(ClientId c) {
try { try {
Queue<MessageId> unvalidated = new LinkedList<MessageId>(); Queue<MessageId> unvalidated = new LinkedList<>();
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);
try { try {
unvalidated.addAll(db.getMessagesToValidate(txn, c)); unvalidated.addAll(db.getMessagesToValidate(txn, c));
@@ -119,14 +114,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void validateNextMessageAsync(final Queue<MessageId> unvalidated) { private void validateNextMessageAsync(Queue<MessageId> unvalidated) {
if (unvalidated.isEmpty()) return; if (unvalidated.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> validateNextMessage(unvalidated));
@Override
public void run() {
validateNextMessage(unvalidated);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -158,19 +148,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void deliverOutstandingMessagesAsync(final ClientId c) { private void deliverOutstandingMessagesAsync(ClientId c) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> deliverOutstandingMessages(c));
@Override
public void run() {
deliverOutstandingMessages(c);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void deliverOutstandingMessages(ClientId c) { private void deliverOutstandingMessages(ClientId c) {
try { try {
Queue<MessageId> pending = new LinkedList<MessageId>(); Queue<MessageId> pending = new LinkedList<>();
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);
try { try {
pending.addAll(db.getPendingMessages(txn, c)); pending.addAll(db.getPendingMessages(txn, c));
@@ -184,15 +169,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void deliverNextPendingMessageAsync( private void deliverNextPendingMessageAsync(Queue<MessageId> pending) {
final Queue<MessageId> pending) {
if (pending.isEmpty()) return; if (pending.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> deliverNextPendingMessage(pending));
@Override
public void run() {
deliverNextPendingMessage(pending);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -229,8 +208,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
pending.addAll(getPendingDependents(txn, id)); pending.addAll(getPendingDependents(txn, id));
if (result.share) { if (result.share) {
db.setMessageShared(txn, id); db.setMessageShared(txn, id);
toShare = new LinkedList<MessageId>( toShare = new LinkedList<>(states.keySet());
states.keySet());
} }
} else { } else {
invalidate = getDependentsToInvalidate(txn, id); invalidate = getDependentsToInvalidate(txn, id);
@@ -255,13 +233,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void validateMessageAsync(final Message m, final Group g) { private void validateMessageAsync(Message m, Group g) {
validationExecutor.execute(new Runnable() { validationExecutor.execute(() -> validateMessage(m, g));
@Override
public void run() {
validateMessage(m, g);
}
});
} }
@ValidationExecutor @ValidationExecutor
@@ -277,21 +250,16 @@ class ValidationManagerImpl implements ValidationManager, Service,
} catch (InvalidMessageException e) { } catch (InvalidMessageException e) {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.log(INFO, e.toString(), e); LOG.log(INFO, e.toString(), e);
Queue<MessageId> invalidate = new LinkedList<MessageId>(); Queue<MessageId> invalidate = new LinkedList<>();
invalidate.add(m.getId()); invalidate.add(m.getId());
invalidateNextMessageAsync(invalidate); invalidateNextMessageAsync(invalidate);
} }
} }
} }
private void storeMessageContextAsync(final Message m, final ClientId c, private void storeMessageContextAsync(Message m, ClientId c,
final MessageContext result) { MessageContext result) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> storeMessageContext(m, c, result));
@Override
public void run() {
storeMessageContext(m, c, result);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -331,8 +299,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
pending = getPendingDependents(txn, id); pending = getPendingDependents(txn, id);
if (result.share) { if (result.share) {
db.setMessageShared(txn, id); db.setMessageShared(txn, id);
toShare = toShare = new LinkedList<>(dependencies);
new LinkedList<MessageId>(dependencies);
} }
} else { } else {
invalidate = getDependentsToInvalidate(txn, id); invalidate = getDependentsToInvalidate(txn, id);
@@ -378,7 +345,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
@DatabaseExecutor @DatabaseExecutor
private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m) private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m)
throws DbException { throws DbException {
Queue<MessageId> pending = new LinkedList<MessageId>(); Queue<MessageId> pending = new LinkedList<>();
Map<MessageId, State> states = db.getMessageDependents(txn, m); Map<MessageId, State> states = db.getMessageDependents(txn, m);
for (Entry<MessageId, State> e : states.entrySet()) { for (Entry<MessageId, State> e : states.entrySet()) {
if (e.getValue() == PENDING) pending.add(e.getKey()); if (e.getValue() == PENDING) pending.add(e.getKey());
@@ -386,19 +353,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
return pending; return pending;
} }
private void shareOutstandingMessagesAsync(final ClientId c) { private void shareOutstandingMessagesAsync(ClientId c) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> shareOutstandingMessages(c));
@Override
public void run() {
shareOutstandingMessages(c);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void shareOutstandingMessages(ClientId c) { private void shareOutstandingMessages(ClientId c) {
try { try {
Queue<MessageId> toShare = new LinkedList<MessageId>(); Queue<MessageId> toShare = new LinkedList<>();
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);
try { try {
toShare.addAll(db.getMessagesToShare(txn, c)); toShare.addAll(db.getMessagesToShare(txn, c));
@@ -418,14 +380,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
* This method should only be called for messages that have all their * This method should only be called for messages that have all their
* dependencies delivered and have been delivered themselves. * dependencies delivered and have been delivered themselves.
*/ */
private void shareNextMessageAsync(final Queue<MessageId> toShare) { private void shareNextMessageAsync(Queue<MessageId> toShare) {
if (toShare.isEmpty()) return; if (toShare.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> shareNextMessage(toShare));
@Override
public void run() {
shareNextMessage(toShare);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -452,14 +409,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void invalidateNextMessageAsync(final Queue<MessageId> invalidate) { private void invalidateNextMessageAsync(Queue<MessageId> invalidate) {
if (invalidate.isEmpty()) return; if (invalidate.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> invalidateNextMessage(invalidate));
@Override
public void run() {
invalidateNextMessage(invalidate);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -496,7 +448,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
@DatabaseExecutor @DatabaseExecutor
private Queue<MessageId> getDependentsToInvalidate(Transaction txn, private Queue<MessageId> getDependentsToInvalidate(Transaction txn,
MessageId m) throws DbException { MessageId m) throws DbException {
Queue<MessageId> invalidate = new LinkedList<MessageId>(); Queue<MessageId> invalidate = new LinkedList<>();
Map<MessageId, State> states = db.getMessageDependents(txn, m); Map<MessageId, State> states = db.getMessageDependents(txn, m);
for (Entry<MessageId, State> e : states.entrySet()) { for (Entry<MessageId, State> e : states.entrySet()) {
if (e.getValue() != INVALID) invalidate.add(e.getKey()); if (e.getValue() != INVALID) invalidate.add(e.getKey());
@@ -514,17 +466,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void loadGroupAndValidateAsync(final Message m) { private void loadGroupAndValidateAsync(Message m) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> loadGroupAndValidate(m));
@Override
public void run() {
loadGroupAndValidate(m);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void loadGroupAndValidate(final Message m) { private void loadGroupAndValidate(Message m) {
try { try {
Group g; Group g;
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);

View File

@@ -58,15 +58,14 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
this.pluginConfig = pluginConfig; this.pluginConfig = pluginConfig;
this.transportKeyManagerFactory = transportKeyManagerFactory; this.transportKeyManagerFactory = transportKeyManagerFactory;
// Use a ConcurrentHashMap as a thread-safe set // Use a ConcurrentHashMap as a thread-safe set
activeContacts = new ConcurrentHashMap<ContactId, Boolean>(); activeContacts = new ConcurrentHashMap<>();
managers = new ConcurrentHashMap<TransportId, TransportKeyManager>(); managers = new ConcurrentHashMap<>();
} }
@Override @Override
public void startService() throws ServiceException { public void startService() throws ServiceException {
if (used.getAndSet(true)) throw new IllegalStateException(); if (used.getAndSet(true)) throw new IllegalStateException();
Map<TransportId, Integer> transports = Map<TransportId, Integer> transports = new HashMap<>();
new HashMap<TransportId, Integer>();
for (SimplexPluginFactory f : pluginConfig.getSimplexFactories()) for (SimplexPluginFactory f : pluginConfig.getSimplexFactories())
transports.put(f.getId(), f.getMaxLatency()); transports.put(f.getId(), f.getMaxLatency());
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories()) for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
@@ -156,14 +155,10 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
} }
} }
private void removeContact(final ContactId c) { private void removeContact(ContactId c) {
activeContacts.remove(c); activeContacts.remove(c);
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> {
@Override for (TransportKeyManager m : managers.values()) m.removeContact(c);
public void run() {
for (TransportKeyManager m : managers.values())
m.removeContact(c);
}
}); });
} }
} }

View File

@@ -45,7 +45,7 @@ class ReorderingWindow {
} }
List<Long> getUnseen() { List<Long> getUnseen() {
List<Long> unseen = new ArrayList<Long>(seen.length); List<Long> unseen = new ArrayList<>(seen.length);
for (int i = 0; i < seen.length; i++) for (int i = 0; i < seen.length; i++)
if (!seen[i]) unseen.add(base + i); if (!seen[i]) unseen.add(base + i);
return unseen; return unseen;
@@ -69,8 +69,8 @@ class ReorderingWindow {
return new Change(added, removed); return new Change(added, removed);
} }
// Record the elements that will be added and removed // Record the elements that will be added and removed
List<Long> added = new ArrayList<Long>(slide); List<Long> added = new ArrayList<>(slide);
List<Long> removed = new ArrayList<Long>(slide); List<Long> removed = new ArrayList<>(slide);
for (int i = 0; i < slide; i++) { for (int i = 0; i < slide; i++) {
if (!seen[i]) removed.add(base + i); if (!seen[i]) removed.add(base + i);
added.add(base + seen.length + i); added.add(base + seen.length + i);

View File

@@ -65,9 +65,9 @@ class TransportKeyManagerImpl implements TransportKeyManager {
this.transportId = transportId; this.transportId = transportId;
rotationPeriodLength = maxLatency + MAX_CLOCK_DIFFERENCE; rotationPeriodLength = maxLatency + MAX_CLOCK_DIFFERENCE;
lock = new ReentrantLock(); lock = new ReentrantLock();
inContexts = new HashMap<Bytes, TagContext>(); inContexts = new HashMap<>();
outContexts = new HashMap<ContactId, MutableOutgoingKeys>(); outContexts = new HashMap<>();
keys = new HashMap<ContactId, MutableTransportKeys>(); keys = new HashMap<>();
} }
@Override @Override
@@ -134,32 +134,22 @@ class TransportKeyManagerImpl implements TransportKeyManager {
} }
private void scheduleKeyRotation(long now) { private void scheduleKeyRotation(long now) {
Runnable task = new Runnable() {
@Override
public void run() {
rotateKeys();
}
};
long delay = rotationPeriodLength - now % rotationPeriodLength; long delay = rotationPeriodLength - now % rotationPeriodLength;
scheduler.schedule(task, delay, MILLISECONDS); scheduler.schedule((Runnable) this::rotateKeys, delay, MILLISECONDS);
} }
private void rotateKeys() { private void rotateKeys() {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> {
@Override try {
public void run() { Transaction txn = db.startTransaction(false);
try { try {
Transaction txn = db.startTransaction(false); rotateKeys(txn);
try { db.commitTransaction(txn);
rotateKeys(txn); } finally {
db.commitTransaction(txn); db.endTransaction(txn);
} finally {
db.endTransaction(txn);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
} }
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
}); });
} }
@@ -272,8 +262,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
lock.lock(); lock.lock();
try { try {
// Rotate the keys to the current rotation period // Rotate the keys to the current rotation period
Map<ContactId, TransportKeys> snapshot = Map<ContactId, TransportKeys> snapshot = new HashMap<>();
new HashMap<ContactId, TransportKeys>();
for (Entry<ContactId, MutableTransportKeys> e : keys.entrySet()) for (Entry<ContactId, MutableTransportKeys> e : keys.entrySet())
snapshot.put(e.getKey(), e.getValue().snapshot()); snapshot.put(e.getKey(), e.getValue().snapshot());
RotationResult rotationResult = rotateKeys(snapshot, now); RotationResult rotationResult = rotateKeys(snapshot, now);
@@ -311,8 +300,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
private final Map<ContactId, TransportKeys> current, rotated; private final Map<ContactId, TransportKeys> current, rotated;
private RotationResult() { private RotationResult() {
current = new HashMap<ContactId, TransportKeys>(); current = new HashMap<>();
rotated = new HashMap<ContactId, TransportKeys>(); rotated = new HashMap<>();
} }
} }
} }

View File

@@ -24,16 +24,13 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newSingleThreadExecutor(); Executor delegate = Executors.newSingleThreadExecutor();
// Allow all the tasks to be delegated straight away // Allow all the tasks to be delegated straight away
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch latch = new CountDownLatch(TASKS); CountDownLatch latch = new CountDownLatch(TASKS);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override list.add(result);
public void run() { latch.countDown();
list.add(result);
latch.countDown();
}
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish
@@ -49,16 +46,13 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newSingleThreadExecutor(); Executor delegate = Executors.newSingleThreadExecutor();
// Allow two tasks to be delegated at a time // Allow two tasks to be delegated at a time
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 2); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 2);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch latch = new CountDownLatch(TASKS); CountDownLatch latch = new CountDownLatch(TASKS);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override list.add(result);
public void run() { latch.countDown();
list.add(result);
latch.countDown();
}
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish
@@ -73,23 +67,20 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newCachedThreadPool(); Executor delegate = Executors.newCachedThreadPool();
// Allow all the tasks to be delegated straight away // Allow all the tasks to be delegated straight away
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch[] latches = new CountDownLatch[TASKS]; CountDownLatch[] latches = new CountDownLatch[TASKS];
for (int i = 0; i < TASKS; i++) latches[i] = new CountDownLatch(1); for (int i = 0; i < TASKS; i++) latches[i] = new CountDownLatch(1);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override try {
public void run() { // Each task waits for the next task, if any, to finish
try { if (result < TASKS - 1) latches[result + 1].await();
// Each task waits for the next task, if any, to finish list.add(result);
if (result < TASKS - 1) latches[result + 1].await(); } catch (InterruptedException e) {
list.add(result); fail();
} catch (InterruptedException e) {
fail();
}
latches[result].countDown();
} }
latches[result].countDown();
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish
@@ -104,22 +95,19 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newCachedThreadPool(); Executor delegate = Executors.newCachedThreadPool();
// Allow one task to be delegated at a time // Allow one task to be delegated at a time
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 1); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 1);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch latch = new CountDownLatch(TASKS); CountDownLatch latch = new CountDownLatch(TASKS);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override try {
public void run() { // Each task runs faster than the previous task
try { Thread.sleep(TASKS - result);
// Each task runs faster than the previous task list.add(result);
Thread.sleep(TASKS - result); } catch (InterruptedException e) {
list.add(result); fail();
} catch (InterruptedException e) {
fail();
}
latch.countDown();
} }
latch.countDown();
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish

View File

@@ -83,9 +83,9 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
@Test(expected = InvalidMessageException.class) @Test(expected = InvalidMessageException.class)
public void testRejectsTooShortMessage() throws Exception { public void testRejectsTooShortMessage() throws Exception {
final byte[] invalidRaw = new byte[MESSAGE_HEADER_LENGTH]; byte[] invalidRaw = new byte[MESSAGE_HEADER_LENGTH];
// Use a mock message so the length of the raw message can be invalid // Use a mock message so the length of the raw message can be invalid
final Message invalidMessage = context.mock(Message.class); Message invalidMessage = context.mock(Message.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(invalidMessage).getTimestamp(); oneOf(invalidMessage).getTimestamp();
@@ -101,8 +101,8 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
@Test @Test
public void testAcceptsMinLengthMessage() throws Exception { public void testAcceptsMinLengthMessage() throws Exception {
final byte[] shortRaw = new byte[MESSAGE_HEADER_LENGTH + 1]; byte[] shortRaw = new byte[MESSAGE_HEADER_LENGTH + 1];
final Message shortMessage = Message shortMessage =
new Message(messageId, groupId, timestamp, shortRaw); new Message(messageId, groupId, timestamp, shortRaw);
context.checking(new Expectations() {{ context.checking(new Expectations() {{

View File

@@ -76,8 +76,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testAddLocalMessage() throws Exception { public void testAddLocalMessage() throws Exception {
final boolean shared = true; boolean shared = true;
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -95,7 +95,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testCreateMessage() throws Exception { public void testCreateMessage() throws Exception {
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageFactory).createMessage(groupId, timestamp, bytes); oneOf(messageFactory).createMessage(groupId, timestamp, bytes);
@@ -107,7 +107,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageAsList() throws Exception { public void testGetMessageAsList() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
expectToList(true); expectToList(true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -125,7 +125,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetGroupMetadataAsDictionary() throws Exception { public void testGetGroupMetadataAsDictionary() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -145,7 +145,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageMetadataAsDictionary() throws Exception { public void testGetMessageMetadataAsDictionary() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -165,10 +165,9 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageMetadataAsDictionaryMap() throws Exception { public void testGetMessageMetadataAsDictionaryMap() throws Exception {
final Map<MessageId, BdfDictionary> map = Map<MessageId, BdfDictionary> map = new HashMap<>();
new HashMap<MessageId, BdfDictionary>();
map.put(messageId, dictionary); map.put(messageId, dictionary);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -188,14 +187,13 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageMetadataAsDictionaryQuery() throws Exception { public void testGetMessageMetadataAsDictionaryQuery() throws Exception {
final Map<MessageId, BdfDictionary> map = Map<MessageId, BdfDictionary> map = new HashMap<>();
new HashMap<MessageId, BdfDictionary>();
map.put(messageId, dictionary); map.put(messageId, dictionary);
final BdfDictionary query = BdfDictionary query =
BdfDictionary.of(new BdfEntry("query", "me")); BdfDictionary.of(new BdfEntry("query", "me"));
final Metadata queryMetadata = new Metadata(); Metadata queryMetadata = new Metadata();
queryMetadata.put("query", getRandomBytes(42)); queryMetadata.put("query", getRandomBytes(42));
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -217,7 +215,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testMergeGroupMetadata() throws Exception { public void testMergeGroupMetadata() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -235,7 +233,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testMergeMessageMetadata() throws Exception { public void testMergeMessageMetadata() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -282,10 +280,10 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testSign() throws Exception { public void testSign() throws Exception {
final byte[] privateKey = getRandomBytes(42); byte[] privateKey = getRandomBytes(42);
final byte[] signed = getRandomBytes(42); byte[] signed = getRandomBytes(42);
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(cryptoComponent).sign(label, bytes, privateKey); oneOf(cryptoComponent).sign(label, bytes, privateKey);
will(returnValue(signed)); will(returnValue(signed));
@@ -297,8 +295,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testVerifySignature() throws Exception { public void testVerifySignature() throws Exception {
final byte[] publicKey = getRandomBytes(42); byte[] publicKey = getRandomBytes(42);
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage); oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
@@ -311,8 +309,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testVerifyWrongSignature() throws Exception { public void testVerifyWrongSignature() throws Exception {
final byte[] publicKey = getRandomBytes(42); byte[] publicKey = getRandomBytes(42);
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage); oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
@@ -329,8 +327,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
} }
} }
private byte[] expectToByteArray(final BdfList list) throws Exception { private byte[] expectToByteArray(BdfList list) throws Exception {
final BdfWriter bdfWriter = context.mock(BdfWriter.class); BdfWriter bdfWriter = context.mock(BdfWriter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(bdfWriterFactory) oneOf(bdfWriterFactory)
@@ -341,8 +339,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
return new byte[0]; return new byte[0];
} }
private void expectToList(final boolean eof) throws Exception { private void expectToList(boolean eof) throws Exception {
final BdfReader bdfReader = context.mock(BdfReader.class); BdfReader bdfReader = context.mock(BdfReader.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(bdfReaderFactory) oneOf(bdfReaderFactory)

View File

@@ -46,10 +46,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testAddContact() throws Exception { public void testAddContact() throws Exception {
final SecretKey master = getSecretKey(); SecretKey master = getSecretKey();
final long timestamp = 42; long timestamp = 42;
final boolean alice = true; boolean alice = true;
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -64,14 +64,13 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
assertEquals(contactId, contactManager assertEquals(contactId, contactManager.addContact(remote, local,
.addContact(remote, local, master, timestamp, alice, verified, master, timestamp, alice, verified, active));
active));
} }
@Test @Test
public void testGetContact() throws Exception { public void testGetContact() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -86,8 +85,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetContactByAuthor() throws Exception { public void testGetContactByAuthor() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Collection<Contact> contacts = Collections.singleton(contact); Collection<Contact> contacts = Collections.singleton(contact);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -102,7 +101,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test(expected = NoSuchContactException.class) @Test(expected = NoSuchContactException.class)
public void testGetContactByUnknownAuthor() throws Exception { public void testGetContactByUnknownAuthor() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -116,8 +115,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test(expected = NoSuchContactException.class) @Test(expected = NoSuchContactException.class)
public void testGetContactByUnknownLocalAuthor() throws Exception { public void testGetContactByUnknownLocalAuthor() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Collection<Contact> contacts = Collections.singleton(contact); Collection<Contact> contacts = Collections.singleton(contact);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -132,10 +131,9 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testActiveContacts() throws Exception { public void testActiveContacts() throws Exception {
Collection<Contact> activeContacts = Collections.singletonList(contact); Collection<Contact> activeContacts = Collections.singletonList(contact);
final Collection<Contact> contacts = Collection<Contact> contacts = new ArrayList<>(activeContacts);
new ArrayList<Contact>(activeContacts);
contacts.add(new Contact(new ContactId(3), remote, local, true, false)); contacts.add(new Contact(new ContactId(3), remote, local, true, false));
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -150,7 +148,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testRemoveContact() throws Exception { public void testRemoveContact() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
will(returnValue(txn)); will(returnValue(txn));
@@ -166,7 +164,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testSetContactActive() throws Exception { public void testSetContactActive() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).setContactActive(txn, contactId, active); oneOf(db).setContactActive(txn, contactId, active);
}}); }});
@@ -176,7 +174,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testContactExists() throws Exception { public void testContactExists() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));

View File

@@ -69,7 +69,7 @@ public class EllipticCurvePerformanceTest {
ECPublicKeyParameters public2 = ECPublicKeyParameters public2 =
(ECPublicKeyParameters) keyPair2.getPublic(); (ECPublicKeyParameters) keyPair2.getPublic();
// Time some ECDH key agreements // Time some ECDH key agreements
List<Long> samples = new ArrayList<Long>(); List<Long> samples = new ArrayList<>();
for (int i = 0; i < SAMPLES; i++) { for (int i = 0; i < SAMPLES; i++) {
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement(); ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
long start = System.nanoTime(); long start = System.nanoTime();
@@ -79,7 +79,7 @@ public class EllipticCurvePerformanceTest {
} }
long agreementMedian = median(samples); long agreementMedian = median(samples);
// Time some signatures // Time some signatures
List<byte[]> signatures = new ArrayList<byte[]>(); List<byte[]> signatures = new ArrayList<>();
samples.clear(); samples.clear();
for (int i = 0; i < SAMPLES; i++) { for (int i = 0; i < SAMPLES; i++) {
Digest digest = new Blake2sDigest(); Digest digest = new Blake2sDigest();

View File

@@ -145,7 +145,7 @@ public class KeyDerivationTest extends BrambleTestCase {
} }
private void assertAllDifferent(TransportKeys... transportKeys) { private void assertAllDifferent(TransportKeys... transportKeys) {
List<SecretKey> secretKeys = new ArrayList<SecretKey>(); List<SecretKey> secretKeys = new ArrayList<>();
for (TransportKeys k : transportKeys) { for (TransportKeys k : transportKeys) {
secretKeys.add(k.getPreviousIncomingKeys().getTagKey()); secretKeys.add(k.getPreviousIncomingKeys().getTagKey());
secretKeys.add(k.getPreviousIncomingKeys().getHeaderKey()); secretKeys.add(k.getPreviousIncomingKeys().getHeaderKey());
@@ -160,7 +160,7 @@ public class KeyDerivationTest extends BrambleTestCase {
} }
private void assertAllDifferent(List<SecretKey> keys) { private void assertAllDifferent(List<SecretKey> keys) {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (SecretKey k : keys) assertTrue(set.add(new Bytes(k.getBytes()))); for (SecretKey k : keys) assertTrue(set.add(new Bytes(k.getBytes())));
} }
} }

View File

@@ -28,7 +28,7 @@ public class TagEncodingTest extends BrambleTestCase {
@Test @Test
public void testKeyAffectsTag() throws Exception { public void testKeyAffectsTag() throws Exception {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
byte[] tag = new byte[TAG_LENGTH]; byte[] tag = new byte[TAG_LENGTH];
SecretKey tagKey = TestUtils.getSecretKey(); SecretKey tagKey = TestUtils.getSecretKey();
@@ -39,7 +39,7 @@ public class TagEncodingTest extends BrambleTestCase {
@Test @Test
public void testProtocolVersionAffectsTag() throws Exception { public void testProtocolVersionAffectsTag() throws Exception {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
byte[] tag = new byte[TAG_LENGTH]; byte[] tag = new byte[TAG_LENGTH];
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION + i, streamNumber); crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION + i, streamNumber);
@@ -49,7 +49,7 @@ public class TagEncodingTest extends BrambleTestCase {
@Test @Test
public void testStreamNumberAffectsTag() throws Exception { public void testStreamNumberAffectsTag() throws Exception {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
byte[] tag = new byte[TAG_LENGTH]; byte[] tag = new byte[TAG_LENGTH];
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber + i); crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber + i);

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.data; package org.briarproject.bramble.data;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -155,7 +154,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testWriteList() throws IOException { public void testWriteList() throws IOException {
List<Object> l = new ArrayList<Object>(); List<Object> l = new ArrayList<>();
for (int i = 0; i < 3; i++) l.add(i); for (int i = 0; i < 3; i++) l.add(i);
w.writeList(l); w.writeList(l);
// LIST tag, elements as integers, END tag // LIST tag, elements as integers, END tag
@@ -164,7 +163,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testListCanContainNull() throws IOException { public void testListCanContainNull() throws IOException {
List<Object> l = new ArrayList<Object>(); List<Object> l = new ArrayList<>();
l.add(1); l.add(1);
l.add(null); l.add(null);
l.add(NULL_VALUE); l.add(NULL_VALUE);
@@ -177,7 +176,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testWriteDictionary() throws IOException { public void testWriteDictionary() throws IOException {
// Use LinkedHashMap to get predictable iteration order // Use LinkedHashMap to get predictable iteration order
Map<String, Object> m = new LinkedHashMap<String, Object>(); Map<String, Object> m = new LinkedHashMap<>();
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i); for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
w.writeDictionary(m); w.writeDictionary(m);
// DICTIONARY tag, keys as strings and values as integers, END tag // DICTIONARY tag, keys as strings and values as integers, END tag
@@ -216,12 +215,12 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testWriteNestedDictionariesAndLists() throws IOException { public void testWriteNestedDictionariesAndLists() throws IOException {
Map<String, Object> inner = new LinkedHashMap<String, Object>(); Map<String, Object> inner = new LinkedHashMap<>();
inner.put("bar", new byte[0]); inner.put("bar", new byte[0]);
List<Object> list = new ArrayList<Object>(); List<Object> list = new ArrayList<>();
list.add(1); list.add(1);
list.add(inner); list.add(inner);
Map<String, Object> outer = new LinkedHashMap<String, Object>(); Map<String, Object> outer = new LinkedHashMap<>();
outer.put("foo", list); outer.put("foo", list);
w.writeDictionary(outer); w.writeDictionary(outer);
// DICTIONARY tag, "foo" as string, LIST tag, 1 as integer, // DICTIONARY tag, "foo" as string, LIST tag, 1 as integer,

View File

@@ -99,7 +99,7 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
@Test @Test
public void testList() throws FormatException { public void testList() throws FormatException {
List<Long> l = new ArrayList<Long>(4); List<Long> l = new ArrayList<>(4);
l.add(42L); l.add(42L);
l.add(1337L); l.add(1337L);
l.add(Long.MIN_VALUE); l.add(Long.MIN_VALUE);
@@ -114,7 +114,7 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
@Test @Test
public void testDictionary() throws FormatException { public void testDictionary() throws FormatException {
Map<String, Boolean> m = new HashMap<String, Boolean>(); Map<String, Boolean> m = new HashMap<>();
m.put("1", true); m.put("1", true);
m.put("2", false); m.put("2", false);
@@ -130,19 +130,19 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
@Test @Test
public void testComplexDictionary() throws FormatException { public void testComplexDictionary() throws FormatException {
Map<String, List> m = new HashMap<String, List>(); Map<String, List> m = new HashMap<>();
List<String> one = new ArrayList<String>(3); List<String> one = new ArrayList<>(3);
one.add("\uFDD0"); one.add("\uFDD0");
one.add("\uFDD1"); one.add("\uFDD1");
one.add("\uFDD2"); one.add("\uFDD2");
m.put("One", one); m.put("One", one);
List<String> two = new ArrayList<String>(2); List<String> two = new ArrayList<>(2);
two.add("\u0080"); two.add("\u0080");
two.add("\uD800\uDC00"); two.add("\uD800\uDC00");
m.put("Two", two); m.put("Two", two);
d.put("test", m); d.put("test", m);
Map<String, Boolean> m2 = new HashMap<String, Boolean>(); Map<String, Boolean> m2 = new HashMap<>();
m2.put("should be true", true); m2.put("should be true", true);
d.put("another test", m2); d.put("another test", m2);

View File

@@ -323,7 +323,7 @@ public class BasicH2Test extends BrambleTestCase {
private List<String> getNames() throws SQLException { private List<String> getNames() throws SQLException {
String sql = "SELECT name FROM foo ORDER BY uniqueId"; String sql = "SELECT name FROM foo ORDER BY uniqueId";
List<String> names = new ArrayList<String>(); List<String> names = new ArrayList<>();
try { try {
PreparedStatement ps = connection.prepareStatement(sql); PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery(); ResultSet rs = ps.executeQuery();

View File

@@ -47,11 +47,10 @@ import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
import org.briarproject.bramble.api.transport.IncomingKeys; import org.briarproject.bramble.api.transport.IncomingKeys;
import org.briarproject.bramble.api.transport.OutgoingKeys; import org.briarproject.bramble.api.transport.OutgoingKeys;
import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.api.transport.TransportKeys;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
@@ -74,7 +73,13 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
public class DatabaseComponentImplTest extends BrambleTestCase { public class DatabaseComponentImplTest extends BrambleMockTestCase {
@SuppressWarnings("unchecked")
private final Database<Object> database = context.mock(Database.class);
private final ShutdownManager shutdown =
context.mock(ShutdownManager.class);
private final EventBus eventBus = context.mock(EventBus.class);
private final Object txn = new Object(); private final Object txn = new Object();
private final ClientId clientId; private final ClientId clientId;
@@ -120,18 +125,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
private DatabaseComponent createDatabaseComponent(Database<Object> database, private DatabaseComponent createDatabaseComponent(Database<Object> database,
EventBus eventBus, ShutdownManager shutdown) { EventBus eventBus, ShutdownManager shutdown) {
return new DatabaseComponentImpl<Object>(database, Object.class, return new DatabaseComponentImpl<>(database, Object.class, eventBus,
eventBus, shutdown); shutdown);
} }
@Test @Test
@SuppressWarnings("unchecked")
public void testSimpleCalls() throws Exception { public void testSimpleCalls() throws Exception {
final int shutdownHandle = 12345; int shutdownHandle = 12345;
Mockery context = new Mockery();
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// open() // open()
oneOf(database).open(); oneOf(database).open();
@@ -194,7 +194,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
// endTransaction() // endTransaction()
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
// close() // close()
oneOf(shutdown).removeShutdownHook(shutdownHandle);
oneOf(database).close(); oneOf(database).close();
}}); }});
DatabaseComponent db = createDatabaseComponent(database, eventBus, DatabaseComponent db = createDatabaseComponent(database, eventBus,
@@ -221,18 +220,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
db.close(); db.close();
context.assertIsSatisfied();
} }
@Test @Test
public void testLocalMessagesAreNotStoredUnlessGroupExists() public void testLocalMessagesAreNotStoredUnlessGroupExists()
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -252,17 +244,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testAddLocalMessage() throws Exception { public void testAddLocalMessage() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -294,18 +279,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testVariousMethodsThrowExceptionIfContactIsMissing() public void testVariousMethodsThrowExceptionIfContactIsMissing()
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the contact is in the DB (which it's not) // Check whether the contact is in the DB (which it's not)
exactly(18).of(database).startTransaction(); exactly(18).of(database).startTransaction();
@@ -500,18 +478,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testVariousMethodsThrowExceptionIfLocalAuthorIsMissing() public void testVariousMethodsThrowExceptionIfLocalAuthorIsMissing()
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the pseudonym is in the DB (which it's not) // Check whether the pseudonym is in the DB (which it's not)
exactly(3).of(database).startTransaction(); exactly(3).of(database).startTransaction();
@@ -552,18 +523,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testVariousMethodsThrowExceptionIfGroupIsMissing() public void testVariousMethodsThrowExceptionIfGroupIsMissing()
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the group is in the DB (which it's not) // Check whether the group is in the DB (which it's not)
exactly(8).of(database).startTransaction(); exactly(8).of(database).startTransaction();
@@ -657,18 +621,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testVariousMethodsThrowExceptionIfMessageIsMissing() public void testVariousMethodsThrowExceptionIfMessageIsMissing()
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the message is in the DB (which it's not) // Check whether the message is in the DB (which it's not)
exactly(11).of(database).startTransaction(); exactly(11).of(database).startTransaction();
@@ -792,18 +749,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testVariousMethodsThrowExceptionIfTransportIsMissing() public void testVariousMethodsThrowExceptionIfTransportIsMissing()
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// startTransaction() // startTransaction()
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -890,19 +840,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testGenerateAck() throws Exception { public void testGenerateAck() throws Exception {
final Collection<MessageId> messagesToAck = Arrays.asList(messageId, Collection<MessageId> messagesToAck = Arrays.asList(messageId,
messageId1); messageId1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -925,20 +868,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testGenerateBatch() throws Exception { public void testGenerateBatch() throws Exception {
final byte[] raw1 = new byte[size]; byte[] raw1 = new byte[size];
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
final Collection<byte[]> messages = Arrays.asList(raw, raw1); Collection<byte[]> messages = Arrays.asList(raw, raw1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -969,19 +905,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testGenerateOffer() throws Exception { public void testGenerateOffer() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1007,19 +936,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testGenerateRequest() throws Exception { public void testGenerateRequest() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1042,20 +964,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testGenerateRequestedBatch() throws Exception { public void testGenerateRequestedBatch() throws Exception {
final byte[] raw1 = new byte[size]; byte[] raw1 = new byte[size];
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
final Collection<byte[]> messages = Arrays.asList(raw, raw1); Collection<byte[]> messages = Arrays.asList(raw, raw1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1087,17 +1002,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testReceiveAck() throws Exception { public void testReceiveAck() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1120,17 +1028,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testReceiveMessage() throws Exception { public void testReceiveMessage() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1175,17 +1076,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testReceiveDuplicateMessage() throws Exception { public void testReceiveDuplicateMessage() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1212,17 +1106,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testReceiveMessageWithoutVisibleGroup() throws Exception { public void testReceiveMessageWithoutVisibleGroup() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1242,20 +1129,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testReceiveOffer() throws Exception { public void testReceiveOffer() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final MessageId messageId2 = new MessageId(TestUtils.getRandomId()); MessageId messageId2 = new MessageId(TestUtils.getRandomId());
final MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(TestUtils.getRandomId());
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1296,17 +1176,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testReceiveRequest() throws Exception { public void testReceiveRequest() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1330,17 +1203,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testChangingVisibilityCallsListeners() throws Exception { public void testChangingVisibilityCallsListeners() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1370,18 +1236,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testNotChangingVisibilityDoesNotCallListeners() public void testNotChangingVisibilityDoesNotCallListeners()
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1403,20 +1262,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testTransportKeys() throws Exception { public void testTransportKeys() throws Exception {
final TransportKeys transportKeys = createTransportKeys(); TransportKeys transportKeys = createTransportKeys();
final Map<ContactId, TransportKeys> keys = Collections.singletonMap( Map<ContactId, TransportKeys> keys = Collections.singletonMap(
contactId, transportKeys); contactId, transportKeys);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// startTransaction() // startTransaction()
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -1446,8 +1298,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
private TransportKeys createTransportKeys() { private TransportKeys createTransportKeys() {
@@ -1472,19 +1322,14 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testMergeSettings() throws Exception { public void testMergeSettings() throws Exception {
final Settings before = new Settings(); Settings before = new Settings();
before.put("foo", "bar"); before.put("foo", "bar");
before.put("baz", "bam"); before.put("baz", "bam");
final Settings update = new Settings(); Settings update = new Settings();
update.put("baz", "qux"); update.put("baz", "qux");
final Settings merged = new Settings(); Settings merged = new Settings();
merged.put("foo", "bar"); merged.put("foo", "bar");
merged.put("baz", "qux"); merged.put("baz", "qux");
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// startTransaction() // startTransaction()
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -1514,8 +1359,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
@@ -1545,12 +1388,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
private void testCannotStartTransactionDuringTransaction( private void testCannotStartTransactionDuringTransaction(
boolean firstTxnReadOnly, boolean secondTxnReadOnly) boolean firstTxnReadOnly, boolean secondTxnReadOnly)
throws Exception { throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1560,22 +1397,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
shutdown); shutdown);
assertNotNull(db.startTransaction(firstTxnReadOnly)); assertNotNull(db.startTransaction(firstTxnReadOnly));
try { db.startTransaction(secondTxnReadOnly);
db.startTransaction(secondTxnReadOnly); fail();
fail();
} finally {
context.assertIsSatisfied();
}
} }
@Test @Test
public void testCannotAddLocalIdentityAsContact() throws Exception { public void testCannotAddLocalIdentityAsContact() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1599,18 +1426,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
public void testCannotAddDuplicateContact() throws Exception { public void testCannotAddDuplicateContact() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1636,19 +1455,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
context.assertIsSatisfied();
} }
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testMessageDependencies() throws Exception { public void testMessageDependencies() throws Exception {
final int shutdownHandle = 12345; int shutdownHandle = 12345;
Mockery context = new Mockery(); MessageId messageId2 = new MessageId(TestUtils.getRandomId());
final Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class);
final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// open() // open()
oneOf(database).open(); oneOf(database).open();
@@ -1693,7 +1506,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
// endTransaction() // endTransaction()
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
// close() // close()
oneOf(shutdown).removeShutdownHook(shutdownHandle);
oneOf(database).close(); oneOf(database).close();
}}); }});
DatabaseComponent db = createDatabaseComponent(database, eventBus, DatabaseComponent db = createDatabaseComponent(database, eventBus,
@@ -1703,7 +1515,7 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
Transaction transaction = db.startTransaction(false); Transaction transaction = db.startTransaction(false);
try { try {
db.addLocalMessage(transaction, message, metadata, true); db.addLocalMessage(transaction, message, metadata, true);
Collection<MessageId> dependencies = new ArrayList<MessageId>(2); Collection<MessageId> dependencies = new ArrayList<>(2);
dependencies.add(messageId1); dependencies.add(messageId1);
dependencies.add(messageId2); dependencies.add(messageId2);
db.addMessageDependencies(transaction, message, dependencies); db.addMessageDependencies(transaction, message, dependencies);
@@ -1714,7 +1526,5 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
db.endTransaction(transaction); db.endTransaction(transaction);
} }
db.close(); db.close();
context.assertIsSatisfied();
} }
} }

View File

@@ -464,28 +464,25 @@ public class H2DatabaseTest extends BrambleTestCase {
@Test @Test
public void testCloseWaitsForCommit() throws Exception { public void testCloseWaitsForCommit() throws Exception {
final CountDownLatch closing = new CountDownLatch(1); CountDownLatch closing = new CountDownLatch(1);
final CountDownLatch closed = new CountDownLatch(1); CountDownLatch closed = new CountDownLatch(1);
final AtomicBoolean transactionFinished = new AtomicBoolean(false); AtomicBoolean transactionFinished = new AtomicBoolean(false);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
final Database<Connection> db = open(false); Database<Connection> db = open(false);
// Start a transaction // Start a transaction
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// In another thread, close the database // In another thread, close the database
Thread close = new Thread() { Thread close = new Thread(() -> {
@Override try {
public void run() { closing.countDown();
try { db.close();
closing.countDown(); if (!transactionFinished.get()) error.set(true);
db.close(); closed.countDown();
if (!transactionFinished.get()) error.set(true); } catch (Exception e) {
closed.countDown(); error.set(true);
} catch (Exception e) {
error.set(true);
}
} }
}; });
close.start(); close.start();
closing.await(); closing.await();
// Do whatever the transaction needs to do // Do whatever the transaction needs to do
@@ -501,28 +498,25 @@ public class H2DatabaseTest extends BrambleTestCase {
@Test @Test
public void testCloseWaitsForAbort() throws Exception { public void testCloseWaitsForAbort() throws Exception {
final CountDownLatch closing = new CountDownLatch(1); CountDownLatch closing = new CountDownLatch(1);
final CountDownLatch closed = new CountDownLatch(1); CountDownLatch closed = new CountDownLatch(1);
final AtomicBoolean transactionFinished = new AtomicBoolean(false); AtomicBoolean transactionFinished = new AtomicBoolean(false);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
final Database<Connection> db = open(false); Database<Connection> db = open(false);
// Start a transaction // Start a transaction
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// In another thread, close the database // In another thread, close the database
Thread close = new Thread() { Thread close = new Thread(() -> {
@Override try {
public void run() { closing.countDown();
try { db.close();
closing.countDown(); if (!transactionFinished.get()) error.set(true);
db.close(); closed.countDown();
if (!transactionFinished.get()) error.set(true); } catch (Exception e) {
closed.countDown(); error.set(true);
} catch (Exception e) {
error.set(true);
}
} }
}; });
close.start(); close.start();
closing.await(); closing.await();
// Do whatever the transaction needs to do // Do whatever the transaction needs to do
@@ -870,7 +864,7 @@ public class H2DatabaseTest extends BrambleTestCase {
assertEquals(0, db.countOfferedMessages(txn, contactId)); assertEquals(0, db.countOfferedMessages(txn, contactId));
// Add some offered messages and count them // Add some offered messages and count them
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
MessageId m = new MessageId(TestUtils.getRandomId()); MessageId m = new MessageId(TestUtils.getRandomId());
db.addOfferedMessage(txn, contactId, m); db.addOfferedMessage(txn, contactId, m);

View File

@@ -17,56 +17,50 @@ public class LockFairnessTest extends BrambleTestCase {
@Test @Test
public void testReadersCanShareTheLock() throws Exception { public void testReadersCanShareTheLock() throws Exception {
// Use a fair lock // Use a fair lock
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
final CountDownLatch firstReaderHasLock = new CountDownLatch(1); CountDownLatch firstReaderHasLock = new CountDownLatch(1);
final CountDownLatch firstReaderHasFinished = new CountDownLatch(1); CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
final CountDownLatch secondReaderHasLock = new CountDownLatch(1); CountDownLatch secondReaderHasLock = new CountDownLatch(1);
final CountDownLatch secondReaderHasFinished = new CountDownLatch(1); CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
// First reader // First reader
Thread first = new Thread() { Thread first = new Thread(() -> {
@Override try {
public void run() { // Acquire the lock
lock.readLock().lock();
try { try {
// Acquire the lock // Allow the second reader to acquire the lock
lock.readLock().lock(); firstReaderHasLock.countDown();
try { // Wait for the second reader to acquire the lock
// Allow the second reader to acquire the lock assertTrue(secondReaderHasLock.await(10, SECONDS));
firstReaderHasLock.countDown(); } finally {
// Wait for the second reader to acquire the lock // Release the lock
assertTrue(secondReaderHasLock.await(10, SECONDS)); lock.readLock().unlock();
} finally {
// Release the lock
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
firstReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; firstReaderHasFinished.countDown();
});
first.start(); first.start();
// Second reader // Second reader
Thread second = new Thread() { Thread second = new Thread(() -> {
@Override try {
public void run() { // Wait for the first reader to acquire the lock
assertTrue(firstReaderHasLock.await(10, SECONDS));
// Acquire the lock
lock.readLock().lock();
try { try {
// Wait for the first reader to acquire the lock // Allow the first reader to release the lock
assertTrue(firstReaderHasLock.await(10, SECONDS)); secondReaderHasLock.countDown();
// Acquire the lock } finally {
lock.readLock().lock(); // Release the lock
try { lock.readLock().unlock();
// Allow the first reader to release the lock
secondReaderHasLock.countDown();
} finally {
// Release the lock
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
secondReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; secondReaderHasFinished.countDown();
});
second.start(); second.start();
// Wait for both readers to finish // Wait for both readers to finish
assertTrue(firstReaderHasFinished.await(10, SECONDS)); assertTrue(firstReaderHasFinished.await(10, SECONDS));
@@ -76,86 +70,77 @@ public class LockFairnessTest extends BrambleTestCase {
@Test @Test
public void testWritersDoNotStarve() throws Exception { public void testWritersDoNotStarve() throws Exception {
// Use a fair lock // Use a fair lock
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
final CountDownLatch firstReaderHasLock = new CountDownLatch(1); CountDownLatch firstReaderHasLock = new CountDownLatch(1);
final CountDownLatch firstReaderHasFinished = new CountDownLatch(1); CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
final CountDownLatch secondReaderHasFinished = new CountDownLatch(1); CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
final CountDownLatch writerHasFinished = new CountDownLatch(1); CountDownLatch writerHasFinished = new CountDownLatch(1);
final AtomicBoolean secondReaderHasHeldLock = new AtomicBoolean(false); AtomicBoolean secondReaderHasHeldLock = new AtomicBoolean(false);
final AtomicBoolean writerHasHeldLock = new AtomicBoolean(false); AtomicBoolean writerHasHeldLock = new AtomicBoolean(false);
// First reader // First reader
Thread first = new Thread() { Thread first = new Thread(() -> {
@Override try {
public void run() { // Acquire the lock
lock.readLock().lock();
try { try {
// Acquire the lock // Allow the other threads to acquire the lock
lock.readLock().lock(); firstReaderHasLock.countDown();
try { // Wait for both other threads to wait for the lock
// Allow the other threads to acquire the lock while (lock.getQueueLength() < 2) Thread.sleep(10);
firstReaderHasLock.countDown(); // No other thread should have acquired the lock
// Wait for both other threads to wait for the lock assertFalse(secondReaderHasHeldLock.get());
while (lock.getQueueLength() < 2) Thread.sleep(10); assertFalse(writerHasHeldLock.get());
// No other thread should have acquired the lock } finally {
assertFalse(secondReaderHasHeldLock.get()); // Release the lock
assertFalse(writerHasHeldLock.get()); lock.readLock().unlock();
} finally {
// Release the lock
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
firstReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; firstReaderHasFinished.countDown();
});
first.start(); first.start();
// Writer // Writer
Thread writer = new Thread() { Thread writer = new Thread(() -> {
@Override try {
public void run() { // Wait for the first reader to acquire the lock
assertTrue(firstReaderHasLock.await(10, SECONDS));
// Acquire the lock
lock.writeLock().lock();
try { try {
// Wait for the first reader to acquire the lock writerHasHeldLock.set(true);
assertTrue(firstReaderHasLock.await(10, SECONDS)); // The second reader should not overtake the writer
// Acquire the lock assertFalse(secondReaderHasHeldLock.get());
lock.writeLock().lock(); } finally {
try { lock.writeLock().unlock();
writerHasHeldLock.set(true);
// The second reader should not overtake the writer
assertFalse(secondReaderHasHeldLock.get());
} finally {
lock.writeLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
writerHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; writerHasFinished.countDown();
});
writer.start(); writer.start();
// Second reader // Second reader
Thread second = new Thread() { Thread second = new Thread(() -> {
@Override try {
public void run() { // Wait for the first reader to acquire the lock
assertTrue(firstReaderHasLock.await(10, SECONDS));
// Wait for the writer to wait for the lock
while (lock.getQueueLength() < 1) Thread.sleep(10);
// Acquire the lock
lock.readLock().lock();
try { try {
// Wait for the first reader to acquire the lock secondReaderHasHeldLock.set(true);
assertTrue(firstReaderHasLock.await(10, SECONDS)); // The second reader should not overtake the writer
// Wait for the writer to wait for the lock assertTrue(writerHasHeldLock.get());
while (lock.getQueueLength() < 1) Thread.sleep(10); } finally {
// Acquire the lock lock.readLock().unlock();
lock.readLock().lock();
try {
secondReaderHasHeldLock.set(true);
// The second reader should not overtake the writer
assertTrue(writerHasHeldLock.get());
} finally {
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
secondReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; secondReaderHasFinished.countDown();
});
second.start(); second.start();
// Wait for all the threads to finish // Wait for all the threads to finish
assertTrue(firstReaderHasFinished.await(10, SECONDS)); assertTrue(firstReaderHasFinished.await(10, SECONDS));

View File

@@ -80,8 +80,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetAuthorStatus() throws DbException { public void testGetAuthorStatus() throws DbException {
final AuthorId authorId = new AuthorId(TestUtils.getRandomId()); AuthorId authorId = new AuthorId(TestUtils.getRandomId());
final Collection<Contact> contacts = new ArrayList<Contact>(); Collection<Contact> contacts = new ArrayList<>();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -125,8 +125,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
identityManager.getAuthorStatus(localAuthor.getId())); identityManager.getAuthorStatus(localAuthor.getId()));
} }
private void checkAuthorStatusContext(final AuthorId authorId, private void checkAuthorStatusContext(AuthorId authorId,
final Collection<Contact> contacts) throws DbException { Collection<Contact> contacts) throws DbException {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));

View File

@@ -65,11 +65,11 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test @Test
public void testAliceProtocol() throws Exception { public void testAliceProtocol() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(BOB_COMMIT, null); Payload theirPayload = new Payload(BOB_COMMIT, null);
final Payload ourPayload = new Payload(ALICE_COMMIT, null); Payload ourPayload = new Payload(ALICE_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
final SecretKey masterSecret = TestUtils.getSecretKey(); SecretKey masterSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -129,11 +129,11 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test @Test
public void testBobProtocol() throws Exception { public void testBobProtocol() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(ALICE_COMMIT, null); Payload theirPayload = new Payload(ALICE_COMMIT, null);
final Payload ourPayload = new Payload(BOB_COMMIT, null); Payload ourPayload = new Payload(BOB_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
final SecretKey masterSecret = TestUtils.getSecretKey(); SecretKey masterSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -192,9 +192,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testAliceProtocolAbortOnBadKey() throws Exception { public void testAliceProtocolAbortOnBadKey() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(BOB_COMMIT, null); Payload theirPayload = new Payload(BOB_COMMIT, null);
final Payload ourPayload = new Payload(ALICE_COMMIT, null); Payload ourPayload = new Payload(ALICE_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -233,9 +233,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testBobProtocolAbortOnBadKey() throws Exception { public void testBobProtocolAbortOnBadKey() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(ALICE_COMMIT, null); Payload theirPayload = new Payload(ALICE_COMMIT, null);
final Payload ourPayload = new Payload(BOB_COMMIT, null); Payload ourPayload = new Payload(BOB_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -270,10 +270,10 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testAliceProtocolAbortOnBadConfirm() throws Exception { public void testAliceProtocolAbortOnBadConfirm() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(BOB_COMMIT, null); Payload theirPayload = new Payload(BOB_COMMIT, null);
final Payload ourPayload = new Payload(ALICE_COMMIT, null); Payload ourPayload = new Payload(ALICE_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -335,10 +335,10 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testBobProtocolAbortOnBadConfirm() throws Exception { public void testBobProtocolAbortOnBadConfirm() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(ALICE_COMMIT, null); Payload theirPayload = new Payload(ALICE_COMMIT, null);
final Payload ourPayload = new Payload(BOB_COMMIT, null); Payload ourPayload = new Payload(BOB_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,

View File

@@ -15,13 +15,9 @@ public class ShutdownManagerImplTest extends BrambleTestCase {
@Test @Test
public void testAddAndRemove() { public void testAddAndRemove() {
ShutdownManager s = createShutdownManager(); ShutdownManager s = createShutdownManager();
Set<Integer> handles = new HashSet<Integer>(); Set<Integer> handles = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
int handle = s.addShutdownHook(new Runnable() { int handle = s.addShutdownHook(() -> {});
@Override
public void run() {
}
});
// The handles should all be distinct // The handles should all be distinct
assertTrue(handles.add(handle)); assertTrue(handles.add(handle));
} }

View File

@@ -35,7 +35,7 @@ public class ConnectionRegistryImplTest extends BrambleTestCase {
@Test @Test
public void testRegisterAndUnregister() { public void testRegisterAndUnregister() {
Mockery context = new Mockery(); Mockery context = new Mockery();
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
exactly(5).of(eventBus).broadcast(with(any( exactly(5).of(eventBus).broadcast(with(any(
ConnectionOpenedEvent.class))); ConnectionOpenedEvent.class)));

View File

@@ -30,36 +30,36 @@ public class PluginManagerImplTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor ioExecutor = Executors.newSingleThreadExecutor(); Executor ioExecutor = Executors.newSingleThreadExecutor();
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
final PluginConfig pluginConfig = context.mock(PluginConfig.class); PluginConfig pluginConfig = context.mock(PluginConfig.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final SettingsManager settingsManager = SettingsManager settingsManager =
context.mock(SettingsManager.class); context.mock(SettingsManager.class);
final TransportPropertyManager transportPropertyManager = TransportPropertyManager transportPropertyManager =
context.mock(TransportPropertyManager.class); context.mock(TransportPropertyManager.class);
final UiCallback uiCallback = context.mock(UiCallback.class); UiCallback uiCallback = context.mock(UiCallback.class);
// Two simplex plugin factories: both create plugins, one fails to start // Two simplex plugin factories: both create plugins, one fails to start
final SimplexPluginFactory simplexFactory = SimplexPluginFactory simplexFactory =
context.mock(SimplexPluginFactory.class); context.mock(SimplexPluginFactory.class);
final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class); SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
final TransportId simplexId = new TransportId("simplex"); TransportId simplexId = new TransportId("simplex");
final SimplexPluginFactory simplexFailFactory = SimplexPluginFactory simplexFailFactory =
context.mock(SimplexPluginFactory.class, "simplexFailFactory"); context.mock(SimplexPluginFactory.class, "simplexFailFactory");
final SimplexPlugin simplexFailPlugin = SimplexPlugin simplexFailPlugin =
context.mock(SimplexPlugin.class, "simplexFailPlugin"); context.mock(SimplexPlugin.class, "simplexFailPlugin");
final TransportId simplexFailId = new TransportId("simplex1"); TransportId simplexFailId = new TransportId("simplex1");
// Two duplex plugin factories: one creates a plugin, the other fails // Two duplex plugin factories: one creates a plugin, the other fails
final DuplexPluginFactory duplexFactory = DuplexPluginFactory duplexFactory =
context.mock(DuplexPluginFactory.class); context.mock(DuplexPluginFactory.class);
final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class); DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
final TransportId duplexId = new TransportId("duplex"); TransportId duplexId = new TransportId("duplex");
final DuplexPluginFactory duplexFailFactory = DuplexPluginFactory duplexFailFactory =
context.mock(DuplexPluginFactory.class, "duplexFailFactory"); context.mock(DuplexPluginFactory.class, "duplexFailFactory");
final TransportId duplexFailId = new TransportId("duplex1"); TransportId duplexFailId = new TransportId("duplex1");
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(simplexPlugin).getId(); allowing(simplexPlugin).getId();

View File

@@ -42,35 +42,35 @@ public class PollerTest extends BrambleTestCase {
public void testConnectOnContactStatusChanged() throws Exception { public void testConnectOnContactStatusChanged() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
// Two simplex plugins: one supports polling, the other doesn't // Two simplex plugins: one supports polling, the other doesn't
final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class); SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
final SimplexPlugin simplexPlugin1 = SimplexPlugin simplexPlugin1 =
context.mock(SimplexPlugin.class, "simplexPlugin1"); context.mock(SimplexPlugin.class, "simplexPlugin1");
final TransportId simplexId1 = new TransportId("simplex1"); TransportId simplexId1 = new TransportId("simplex1");
final List<SimplexPlugin> simplexPlugins = Arrays.asList(simplexPlugin, List<SimplexPlugin> simplexPlugins = Arrays.asList(simplexPlugin,
simplexPlugin1); simplexPlugin1);
final TransportConnectionWriter simplexWriter = TransportConnectionWriter simplexWriter =
context.mock(TransportConnectionWriter.class); context.mock(TransportConnectionWriter.class);
// Two duplex plugins: one supports polling, the other doesn't // Two duplex plugins: one supports polling, the other doesn't
final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class); DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
final TransportId duplexId = new TransportId("duplex"); TransportId duplexId = new TransportId("duplex");
final DuplexPlugin duplexPlugin1 = DuplexPlugin duplexPlugin1 =
context.mock(DuplexPlugin.class, "duplexPlugin1"); context.mock(DuplexPlugin.class, "duplexPlugin1");
final List<DuplexPlugin> duplexPlugins = Arrays.asList(duplexPlugin, List<DuplexPlugin> duplexPlugins = Arrays.asList(duplexPlugin,
duplexPlugin1); duplexPlugin1);
final DuplexTransportConnection duplexConnection = DuplexTransportConnection duplexConnection =
context.mock(DuplexTransportConnection.class); context.mock(DuplexTransportConnection.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -129,20 +129,20 @@ public class PollerTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final DuplexPlugin plugin = context.mock(DuplexPlugin.class); DuplexPlugin plugin = context.mock(DuplexPlugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
final DuplexTransportConnection duplexConnection = DuplexTransportConnection duplexConnection =
context.mock(DuplexTransportConnection.class); context.mock(DuplexTransportConnection.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -194,19 +194,19 @@ public class PollerTest extends BrambleTestCase {
public void testRescheduleOnConnectionOpened() throws Exception { public void testRescheduleOnConnectionOpened() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final DuplexPlugin plugin = context.mock(DuplexPlugin.class); DuplexPlugin plugin = context.mock(DuplexPlugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(plugin).getId(); allowing(plugin).getId();
@@ -239,19 +239,19 @@ public class PollerTest extends BrambleTestCase {
public void testRescheduleDoesNotReplaceEarlierTask() throws Exception { public void testRescheduleDoesNotReplaceEarlierTask() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final DuplexPlugin plugin = context.mock(DuplexPlugin.class); DuplexPlugin plugin = context.mock(DuplexPlugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(plugin).getId(); allowing(plugin).getId();
@@ -299,20 +299,20 @@ public class PollerTest extends BrambleTestCase {
public void testPollOnTransportEnabled() throws Exception { public void testPollOnTransportEnabled() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final Plugin plugin = context.mock(Plugin.class); Plugin plugin = context.mock(Plugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
final List<ContactId> connected = Collections.singletonList(contactId); List<ContactId> connected = Collections.singletonList(contactId);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(plugin).getId(); allowing(plugin).getId();

View File

@@ -145,11 +145,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
assertEquals(2, split.length); assertEquals(2, split.length);
String addrString = split[0]; String addrString = split[0];
// Listen on the same interface as the plugin // Listen on the same interface as the plugin
final ServerSocket ss = new ServerSocket(); ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress(addrString, 0), 10); ss.bind(new InetSocketAddress(addrString, 0), 10);
int port = ss.getLocalPort(); int port = ss.getLocalPort();
final CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
new Thread() { new Thread() {
@Override @Override
public void run() { public void run() {
@@ -194,8 +194,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]); plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]);
assertNotNull(kal); assertNotNull(kal);
Callable<KeyAgreementConnection> c = kal.listen(); Callable<KeyAgreementConnection> c = kal.listen();
FutureTask<KeyAgreementConnection> f = FutureTask<KeyAgreementConnection> f = new FutureTask<>(c);
new FutureTask<KeyAgreementConnection>(c);
new Thread(f).start(); new Thread(f).start();
// The plugin should have bound a socket and stored the port number // The plugin should have bound a socket and stored the port number
BdfList descriptor = kal.getDescriptor(); BdfList descriptor = kal.getDescriptor();
@@ -240,10 +239,10 @@ public class LanTcpPluginTest extends BrambleTestCase {
assertEquals(2, split.length); assertEquals(2, split.length);
String addrString = split[0]; String addrString = split[0];
// Listen on the same interface as the plugin // Listen on the same interface as the plugin
final ServerSocket ss = new ServerSocket(); ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress(addrString, 0), 10); ss.bind(new InetSocketAddress(addrString, 0), 10);
final CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
new Thread() { new Thread() {
@Override @Override
public void run() { public void run() {
@@ -291,7 +290,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
private static class Callback implements DuplexPluginCallback { private static class Callback implements DuplexPluginCallback {
private final Map<ContactId, TransportProperties> remote = private final Map<ContactId, TransportProperties> remote =
new Hashtable<ContactId, TransportProperties>(); new Hashtable<>();
private final CountDownLatch propertiesLatch = new CountDownLatch(1); private final CountDownLatch propertiesLatch = new CountDownLatch(1);
private final CountDownLatch connectionsLatch = new CountDownLatch(1); private final CountDownLatch connectionsLatch = new CountDownLatch(1);
private final TransportProperties local = new TransportProperties(); private final TransportProperties local = new TransportProperties();

View File

@@ -0,0 +1,723 @@
package org.briarproject.bramble.properties;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final MetadataParser metadataParser =
context.mock(MetadataParser.class);
private final ContactGroupFactory contactGroupFactory =
context.mock(ContactGroupFactory.class);
private final Clock clock = context.mock(Clock.class);
private final Group localGroup = getGroup();
private final LocalAuthor localAuthor = getLocalAuthor();
private final BdfDictionary fooPropertiesDict = BdfDictionary.of(
new BdfEntry("fooKey1", "fooValue1"),
new BdfEntry("fooKey2", "fooValue2")
);
private final BdfDictionary barPropertiesDict = BdfDictionary.of(
new BdfEntry("barKey1", "barValue1"),
new BdfEntry("barKey2", "barValue2")
);
private final TransportProperties fooProperties, barProperties;
private int nextContactId = 0;
public TransportPropertyManagerImplTest() throws Exception {
fooProperties = new TransportProperties();
for (String key : fooPropertiesDict.keySet())
fooProperties.put(key, fooPropertiesDict.getString(key));
barProperties = new TransportProperties();
for (String key : barPropertiesDict.keySet())
barProperties.put(key, barPropertiesDict.getString(key));
}
private TransportPropertyManagerImpl createInstance() {
context.checking(new Expectations() {{
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID);
will(returnValue(localGroup));
}});
return new TransportPropertyManagerImpl(db, clientHelper,
metadataParser, contactGroupFactory, clock);
}
@Test
public void testCreatesGroupsAtStartup() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact1 = getContact(true);
Contact contact2 = getContact(true);
List<Contact> contacts = Arrays.asList(contact1, contact2);
Group contactGroup1 = getGroup(), contactGroup2 = getGroup();
context.checking(new Expectations() {{
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(false));
oneOf(db).addGroup(txn, localGroup);
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// The first contact's group has already been set up
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact1);
will(returnValue(contactGroup1));
oneOf(db).containsGroup(txn, contactGroup1.getId());
will(returnValue(true));
// The second contact's group hasn't been set up
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact2);
will(returnValue(contactGroup2));
oneOf(db).containsGroup(txn, contactGroup2.getId());
will(returnValue(false));
oneOf(db).addGroup(txn, contactGroup2);
oneOf(db).setGroupVisibility(txn, contact2.getId(),
contactGroup2.getId(), SHARED);
}});
// Copy the latest local properties into the group
expectGetLocalProperties(txn);
expectStoreMessage(txn, contactGroup2.getId(), "foo", fooPropertiesDict,
1, true, true);
expectStoreMessage(txn, contactGroup2.getId(), "bar", barPropertiesDict,
1, true, true);
TransportPropertyManagerImpl t = createInstance();
t.createLocalState(txn);
}
@Test
public void testDoesNotCreateGroupsAtStartupIfAlreadyCreated()
throws Exception {
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(true));
}});
TransportPropertyManagerImpl t = createInstance();
t.createLocalState(txn);
}
@Test
public void testCreatesContactGroupWhenAddingContact() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
context.checking(new Expectations() {{
// Create the group and share it with the contact
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(db).containsGroup(txn, contactGroup.getId());
will(returnValue(false));
oneOf(db).addGroup(txn, contactGroup);
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroup.getId(), SHARED);
}});
// Copy the latest local properties into the group
expectGetLocalProperties(txn);
expectStoreMessage(txn, contactGroup.getId(), "foo", fooPropertiesDict,
1, true, true);
expectStoreMessage(txn, contactGroup.getId(), "bar", barPropertiesDict,
1, true, true);
TransportPropertyManagerImpl t = createInstance();
t.addingContact(txn, contact);
}
@Test
public void testRemovesGroupWhenRemovingContact() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
context.checking(new Expectations() {{
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(db).removeGroup(txn, contactGroup);
}});
TransportPropertyManagerImpl t = createInstance();
t.removingContact(txn, contact);
}
@Test
public void testDoesNotDeleteAnythingWhenFirstUpdateIsDelivered()
throws Exception {
Transaction txn = new Transaction(null, false);
GroupId contactGroupId = new GroupId(getRandomId());
long timestamp = 123456789;
Message message = getMessage(contactGroupId, timestamp);
Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 2),
new BdfEntry("local", false)
);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// A remote update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
// A local update for the same transport should be ignored
MessageId localUpdateId = new MessageId(getRandomId());
messageMetadata.put(localUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
context.checking(new Expectations() {{
oneOf(metadataParser).parse(meta);
will(returnValue(metaDictionary));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
will(returnValue(messageMetadata));
}});
TransportPropertyManagerImpl t = createInstance();
assertFalse(t.incomingMessage(txn, message, meta));
}
@Test
public void testDeletesOlderUpdatesWhenUpdateIsDelivered()
throws Exception {
Transaction txn = new Transaction(null, false);
GroupId contactGroupId = new GroupId(getRandomId());
long timestamp = 123456789;
Message message = getMessage(contactGroupId, timestamp);
Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 4),
new BdfEntry("local", false)
);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// Old remote updates for the same transport should be deleted
MessageId fooVersion2 = new MessageId(getRandomId());
messageMetadata.put(fooVersion2, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 2),
new BdfEntry("local", false)
));
MessageId fooVersion1 = new MessageId(getRandomId());
messageMetadata.put(fooVersion1, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
MessageId fooVersion3 = new MessageId(getRandomId());
messageMetadata.put(fooVersion3, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 3),
new BdfEntry("local", false)
));
context.checking(new Expectations() {{
oneOf(metadataParser).parse(meta);
will(returnValue(metaDictionary));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
will(returnValue(messageMetadata));
// Versions 1-3 should be deleted
oneOf(db).deleteMessage(txn, fooVersion1);
oneOf(db).deleteMessageMetadata(txn, fooVersion1);
oneOf(db).deleteMessage(txn, fooVersion2);
oneOf(db).deleteMessageMetadata(txn, fooVersion2);
oneOf(db).deleteMessage(txn, fooVersion3);
oneOf(db).deleteMessageMetadata(txn, fooVersion3);
}});
TransportPropertyManagerImpl t = createInstance();
assertFalse(t.incomingMessage(txn, message, meta));
}
@Test
public void testDeletesObsoleteUpdateWhenDelivered() throws Exception {
Transaction txn = new Transaction(null, false);
GroupId contactGroupId = new GroupId(getRandomId());
long timestamp = 123456789;
Message message = getMessage(contactGroupId, timestamp);
Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 3),
new BdfEntry("local", false)
);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// Old remote updates for the same transport should be deleted
MessageId fooVersion2 = new MessageId(getRandomId());
messageMetadata.put(fooVersion2, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 2),
new BdfEntry("local", false)
));
MessageId fooVersion1 = new MessageId(getRandomId());
messageMetadata.put(fooVersion1, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
// A newer remote update for the same transport should not be deleted
MessageId fooVersion4 = new MessageId(getRandomId());
messageMetadata.put(fooVersion4, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 4),
new BdfEntry("local", false)
));
context.checking(new Expectations() {{
oneOf(metadataParser).parse(meta);
will(returnValue(metaDictionary));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
will(returnValue(messageMetadata));
// Versions 1 and 2 should be deleted, version 4 should not
oneOf(db).deleteMessage(txn, fooVersion1);
oneOf(db).deleteMessageMetadata(txn, fooVersion1);
oneOf(db).deleteMessage(txn, fooVersion2);
oneOf(db).deleteMessageMetadata(txn, fooVersion2);
// The update being delivered (version 3) should be deleted
oneOf(db).deleteMessage(txn, message.getId());
oneOf(db).deleteMessageMetadata(txn, message.getId());
}});
TransportPropertyManagerImpl t = createInstance();
assertFalse(t.incomingMessage(txn, message, meta));
}
@Test
public void testStoresRemotePropertiesWithVersion0() throws Exception {
Contact contact = getContact(true);
Group contactGroup = getGroup();
Transaction txn = new Transaction(null, false);
Map<TransportId, TransportProperties> properties =
new LinkedHashMap<>();
properties.put(new TransportId("foo"), fooProperties);
properties.put(new TransportId("bar"), barProperties);
context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
}});
expectStoreMessage(txn, contactGroup.getId(), "foo", fooPropertiesDict,
0, false, false);
expectStoreMessage(txn, contactGroup.getId(), "bar", barPropertiesDict,
0, false, false);
TransportPropertyManagerImpl t = createInstance();
t.addRemoteProperties(txn, contact.getId(), properties);
}
@Test
public void testReturnsLatestLocalProperties() throws Exception {
Transaction txn = new Transaction(null, false);
expectGetLocalProperties(txn);
TransportPropertyManagerImpl t = createInstance();
Map<TransportId, TransportProperties> local = t.getLocalProperties(txn);
assertEquals(2, local.size());
assertEquals(fooProperties, local.get(new TransportId("foo")));
assertEquals(barProperties, local.get(new TransportId("bar")));
}
@Test
public void testReturnsEmptyPropertiesIfNoLocalPropertiesAreFound()
throws Exception {
Transaction txn = new Transaction(null, false);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// A local update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
assertEquals(0, t.getLocalProperties(new TransportId("foo")).size());
}
@Test
public void testReturnsLocalProperties() throws Exception {
Transaction txn = new Transaction(null, false);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// A local update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
// A local update for the right transport should be returned
MessageId fooUpdateId = new MessageId(getRandomId());
messageMetadata.put(fooUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
will(returnValue(fooUpdate));
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
assertEquals(fooProperties,
t.getLocalProperties(new TransportId("foo")));
}
@Test
public void testReturnsRemotePropertiesOrEmptyProperties()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact1 = getContact(false);
Contact contact2 = getContact(true);
Contact contact3 = getContact(true);
List<Contact> contacts =
Arrays.asList(contact1, contact2, contact3);
Group contactGroup2 = getGroup();
Group contactGroup3 = getGroup();
Map<MessageId, BdfDictionary> messageMetadata3 =
new LinkedHashMap<>();
// A remote update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata3.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
// A local update for the right transport should be ignored
MessageId localUpdateId = new MessageId(getRandomId());
messageMetadata3.put(localUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
// A remote update for the right transport should be returned
MessageId fooUpdateId = new MessageId(getRandomId());
messageMetadata3.put(fooUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// First contact: skipped because not active
// Second contact: no updates
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact2);
will(returnValue(contactGroup2));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup2.getId());
will(returnValue(Collections.emptyMap()));
// Third contact: returns an update
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact3);
will(returnValue(contactGroup3));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup3.getId());
will(returnValue(messageMetadata3));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
will(returnValue(fooUpdate));
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
Map<ContactId, TransportProperties> properties =
t.getRemoteProperties(new TransportId("foo"));
assertEquals(3, properties.size());
assertEquals(0, properties.get(contact1.getId()).size());
assertEquals(0, properties.get(contact2.getId()).size());
assertEquals(fooProperties, properties.get(contact3.getId()));
}
@Test
public void testMergingUnchangedPropertiesDoesNotCreateUpdate()
throws Exception {
Transaction txn = new Transaction(null, false);
MessageId updateId = new MessageId(getRandomId());
Map<MessageId, BdfDictionary> messageMetadata =
Collections.singletonMap(updateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
BdfList update = BdfList.of("foo", 1, fooPropertiesDict);
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
// Merge the new properties with the existing properties
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, updateId);
will(returnValue(update));
// Properties are unchanged so we're done
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
}
@Test
public void testMergingNewPropertiesCreatesUpdate() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
// There are no existing properties to merge with
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(Collections.emptyMap()));
// Store the new properties in the local group, version 1
expectStoreMessage(txn, localGroup.getId(), "foo",
fooPropertiesDict, 1, true, false);
// Store the new properties in each contact's group, version 1
oneOf(db).getContacts(txn);
will(returnValue(Collections.singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(Collections.emptyMap()));
expectStoreMessage(txn, contactGroup.getId(), "foo",
fooPropertiesDict, 1, true, true);
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
}
@Test
public void testMergingUpdatedPropertiesCreatesUpdate() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
BdfDictionary oldMetadata = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
);
MessageId localGroupUpdateId = new MessageId(getRandomId());
Map<MessageId, BdfDictionary> localGroupMessageMetadata =
Collections.singletonMap(localGroupUpdateId, oldMetadata);
MessageId contactGroupUpdateId = new MessageId(getRandomId());
Map<MessageId, BdfDictionary> contactGroupMessageMetadata =
Collections.singletonMap(contactGroupUpdateId, oldMetadata);
BdfList oldUpdate = BdfList.of("foo", 1, BdfDictionary.of(
new BdfEntry("fooKey1", "oldFooValue1")
));
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
// Merge the new properties with the existing properties
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(localGroupMessageMetadata));
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId);
will(returnValue(oldUpdate));
// Store the merged properties in the local group, version 2
expectStoreMessage(txn, localGroup.getId(), "foo",
fooPropertiesDict, 2, true, false);
// Delete the previous update
oneOf(db).removeMessage(txn, localGroupUpdateId);
// Store the merged properties in each contact's group, version 2
oneOf(db).getContacts(txn);
will(returnValue(Collections.singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(contactGroupMessageMetadata));
expectStoreMessage(txn, contactGroup.getId(), "foo",
fooPropertiesDict, 2, true, true);
// Delete the previous update
oneOf(db).removeMessage(txn, contactGroupUpdateId);
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
}
private Group getGroup() {
GroupId g = new GroupId(getRandomId());
byte[] descriptor = getRandomBytes(MAX_GROUP_DESCRIPTOR_LENGTH);
return new Group(g, CLIENT_ID, descriptor);
}
private LocalAuthor getLocalAuthor() {
AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
long created = System.currentTimeMillis();
return new LocalAuthor(id, name, publicKey, privateKey, created);
}
private Contact getContact(boolean active) {
ContactId c = new ContactId(nextContactId++);
AuthorId a = new AuthorId(getRandomId());
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new Contact(c, new Author(a, name, publicKey),
localAuthor.getId(), true, active);
}
private Message getMessage(GroupId g, long timestamp) {
MessageId messageId = new MessageId(getRandomId());
byte[] raw = getRandomBytes(MAX_MESSAGE_BODY_LENGTH);
return new Message(messageId, g, timestamp, raw);
}
private void expectGetLocalProperties(Transaction txn)
throws Exception {
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// The only update for transport "foo" should be returned
MessageId fooVersion999 = new MessageId(getRandomId());
messageMetadata.put(fooVersion999, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 999)
));
// An old update for transport "bar" should be deleted
MessageId barVersion2 = new MessageId(getRandomId());
messageMetadata.put(barVersion2, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 2)
));
// An even older update for transport "bar" should be deleted
MessageId barVersion1 = new MessageId(getRandomId());
messageMetadata.put(barVersion1, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1)
));
// The latest update for transport "bar" should be returned
MessageId barVersion3 = new MessageId(getRandomId());
messageMetadata.put(barVersion3, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 3)
));
BdfList fooUpdate = BdfList.of("foo", 999, fooPropertiesDict);
BdfList barUpdate = BdfList.of("bar", 3, barPropertiesDict);
context.checking(new Expectations() {{
// Find the latest local update for each transport
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(db).removeMessage(txn, barVersion1);
oneOf(db).removeMessage(txn, barVersion2);
// Retrieve and parse the latest local properties
oneOf(clientHelper).getMessageAsList(txn, fooVersion999);
will(returnValue(fooUpdate));
oneOf(clientHelper).getMessageAsList(txn, barVersion3);
will(returnValue(barUpdate));
}});
}
private void expectStoreMessage(Transaction txn, GroupId g,
String transportId, BdfDictionary properties, long version,
boolean local, boolean shared) throws Exception {
long timestamp = 123456789;
BdfList body = BdfList.of(transportId, version, properties);
Message message = getMessage(g, timestamp);
BdfDictionary meta = BdfDictionary.of(
new BdfEntry("transportId", transportId),
new BdfEntry("version", version),
new BdfEntry("local", local)
);
context.checking(new Expectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(timestamp));
oneOf(clientHelper).createMessage(g, timestamp, body);
will(returnValue(message));
oneOf(clientHelper).addLocalMessage(txn, message, meta, shared);
}});
}
}

View File

@@ -6,10 +6,10 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.sync.Ack; import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.ImmediateExecutor; import org.briarproject.bramble.test.ImmediateExecutor;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery; import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
@@ -44,10 +44,10 @@ public class SimplexOutgoingSessionTest extends BrambleTestCase {
@Test @Test
public void testNothingToSend() throws Exception { public void testNothingToSend() throws Exception {
final SimplexOutgoingSession session = new SimplexOutgoingSession(db, SimplexOutgoingSession session = new SimplexOutgoingSession(db,
dbExecutor, eventBus, contactId, maxLatency, recordWriter); dbExecutor, eventBus, contactId, maxLatency, recordWriter);
final Transaction noAckTxn = new Transaction(null, false); Transaction noAckTxn = new Transaction(null, false);
final Transaction noMsgTxn = new Transaction(null, false); Transaction noMsgTxn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Add listener // Add listener
@@ -80,14 +80,14 @@ public class SimplexOutgoingSessionTest extends BrambleTestCase {
@Test @Test
public void testSomethingToSend() throws Exception { public void testSomethingToSend() throws Exception {
final Ack ack = new Ack(Collections.singletonList(messageId)); Ack ack = new Ack(Collections.singletonList(messageId));
final byte[] raw = new byte[1234]; byte[] raw = new byte[1234];
final SimplexOutgoingSession session = new SimplexOutgoingSession(db, SimplexOutgoingSession session = new SimplexOutgoingSession(db,
dbExecutor, eventBus, contactId, maxLatency, recordWriter); dbExecutor, eventBus, contactId, maxLatency, recordWriter);
final Transaction ackTxn = new Transaction(null, false); Transaction ackTxn = new Transaction(null, false);
final Transaction noAckTxn = new Transaction(null, false); Transaction noAckTxn = new Transaction(null, false);
final Transaction msgTxn = new Transaction(null, false); Transaction msgTxn = new Transaction(null, false);
final Transaction noMsgTxn = new Transaction(null, false); Transaction noMsgTxn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Add listener // Add listener

View File

@@ -92,9 +92,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testStartAndStop() throws Exception { public void testStartAndStop() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// validateOutstandingMessages() // validateOutstandingMessages()
@@ -126,13 +126,13 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesAreValidatedAtStartup() throws Exception { public void testMessagesAreValidatedAtStartup() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, true); Transaction txn3 = new Transaction(null, true);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
final Transaction txn5 = new Transaction(null, true); Transaction txn5 = new Transaction(null, true);
final Transaction txn6 = new Transaction(null, true); Transaction txn6 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -217,11 +217,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testPendingMessagesAreDeliveredAtStartup() throws Exception { public void testPendingMessagesAreDeliveredAtStartup() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, true); Transaction txn4 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -303,11 +303,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesAreSharedAtStartup() throws Exception { public void testMessagesAreSharedAtStartup() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// No messages to validate // No messages to validate
@@ -355,9 +355,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testIncomingMessagesAreShared() throws Exception { public void testIncomingMessagesAreShared() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -405,12 +405,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testValidationContinuesAfterNoSuchMessageException() public void testValidationContinuesAfterNoSuchMessageException()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, true); Transaction txn4 = new Transaction(null, true);
final Transaction txn5 = new Transaction(null, true); Transaction txn5 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -476,12 +476,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testValidationContinuesAfterNoSuchGroupException() public void testValidationContinuesAfterNoSuchGroupException()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, true); Transaction txn4 = new Transaction(null, true);
final Transaction txn5 = new Transaction(null, true); Transaction txn5 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -551,8 +551,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testNonLocalMessagesAreValidatedWhenAdded() throws Exception { public void testNonLocalMessagesAreValidatedWhenAdded() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -591,8 +591,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesWithUndeliveredDependenciesArePending() public void testMessagesWithUndeliveredDependenciesArePending()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -624,8 +624,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesWithDeliveredDependenciesGetDelivered() public void testMessagesWithDeliveredDependenciesGetDelivered()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -663,9 +663,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesWithInvalidDependenciesAreInvalid() public void testMessagesWithInvalidDependenciesAreInvalid()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -716,19 +716,18 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testRecursiveInvalidation() throws Exception { public void testRecursiveInvalidation() throws Exception {
final MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(TestUtils.getRandomId());
final MessageId messageId4 = new MessageId(TestUtils.getRandomId()); MessageId messageId4 = new MessageId(TestUtils.getRandomId());
final Map<MessageId, State> twoDependents = Map<MessageId, State> twoDependents = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependents.put(messageId1, PENDING); twoDependents.put(messageId1, PENDING);
twoDependents.put(messageId2, PENDING); twoDependents.put(messageId2, PENDING);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
final Transaction txn5 = new Transaction(null, false); Transaction txn5 = new Transaction(null, false);
final Transaction txn6 = new Transaction(null, false); Transaction txn6 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -820,27 +819,25 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testPendingDependentsGetDelivered() throws Exception { public void testPendingDependentsGetDelivered() throws Exception {
final MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(TestUtils.getRandomId());
final MessageId messageId4 = new MessageId(TestUtils.getRandomId()); MessageId messageId4 = new MessageId(TestUtils.getRandomId());
final Message message3 = new Message(messageId3, groupId, timestamp, Message message3 = new Message(messageId3, groupId, timestamp,
raw); raw);
final Message message4 = new Message(messageId4, groupId, timestamp, Message message4 = new Message(messageId4, groupId, timestamp,
raw); raw);
final Map<MessageId, State> twoDependents = Map<MessageId, State> twoDependents = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependents.put(messageId1, PENDING); twoDependents.put(messageId1, PENDING);
twoDependents.put(messageId2, PENDING); twoDependents.put(messageId2, PENDING);
final Map<MessageId, State> twoDependencies = Map<MessageId, State> twoDependencies = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependencies.put(messageId1, DELIVERED); twoDependencies.put(messageId1, DELIVERED);
twoDependencies.put(messageId2, DELIVERED); twoDependencies.put(messageId2, DELIVERED);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
final Transaction txn5 = new Transaction(null, false); Transaction txn5 = new Transaction(null, false);
final Transaction txn6 = new Transaction(null, false); Transaction txn6 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -979,13 +976,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testOnlyReadyPendingDependentsGetDelivered() throws Exception { public void testOnlyReadyPendingDependentsGetDelivered() throws Exception {
final Map<MessageId, State> twoDependencies = Map<MessageId, State> twoDependencies = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependencies.put(messageId, DELIVERED); twoDependencies.put(messageId, DELIVERED);
twoDependencies.put(messageId2, UNKNOWN); twoDependencies.put(messageId2, UNKNOWN);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group

View File

@@ -38,7 +38,7 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
System.err.println("WARNING: Skipping test, can't run on this OS"); System.err.println("WARNING: Skipping test, can't run on this OS");
return; return;
} }
Set<Bytes> seeds = new HashSet<Bytes>(); Set<Bytes> seeds = new HashSet<>();
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(); LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi();
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
byte[] seed = engine.engineGenerateSeed(SEED_BYTES); byte[] seed = engine.engineGenerateSeed(SEED_BYTES);

View File

@@ -58,21 +58,21 @@ public class KeyManagerImplTest extends BrambleTestCase {
@Before @Before
public void testStartService() throws Exception { public void testStartService() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
AuthorId remoteAuthorId = new AuthorId(getRandomId()); AuthorId remoteAuthorId = new AuthorId(getRandomId());
Author remoteAuthor = new Author(remoteAuthorId, "author", Author remoteAuthor = new Author(remoteAuthorId, "author",
getRandomBytes(42)); getRandomBytes(42));
AuthorId localAuthorId = new AuthorId(getRandomId()); AuthorId localAuthorId = new AuthorId(getRandomId());
final Collection<Contact> contacts = new ArrayList<Contact>(); Collection<Contact> contacts = new ArrayList<>();
contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true, contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true,
true)); true));
contacts.add(new Contact(inactiveContactId, remoteAuthor, localAuthorId, contacts.add(new Contact(inactiveContactId, remoteAuthor, localAuthorId,
true, false)); true, false));
final SimplexPluginFactory pluginFactory = SimplexPluginFactory pluginFactory =
context.mock(SimplexPluginFactory.class); context.mock(SimplexPluginFactory.class);
final Collection<SimplexPluginFactory> factories = Collections Collection<SimplexPluginFactory> factories = Collections
.singletonList(pluginFactory); .singletonList(pluginFactory);
final int maxLatency = 1337; int maxLatency = 1337;
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(pluginConfig).getSimplexFactories(); oneOf(pluginConfig).getSimplexFactories();
@@ -100,9 +100,9 @@ public class KeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testAddContact() throws Exception { public void testAddContact() throws Exception {
final SecretKey secretKey = getSecretKey(); SecretKey secretKey = getSecretKey();
final long timestamp = 42L; long timestamp = 42L;
final boolean alice = true; boolean alice = true;
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(transportKeyManager) oneOf(transportKeyManager)

View File

@@ -14,7 +14,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testEmptyFramesAreSkipped() throws Exception { public void testEmptyFramesAreSkipped() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(0)); // Empty frame will(returnValue(0)); // Empty frame
@@ -37,7 +37,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testEmptyFramesAreSkippedWithBuffer() throws Exception { public void testEmptyFramesAreSkippedWithBuffer() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(0)); // Empty frame will(returnValue(0)); // Empty frame
@@ -63,7 +63,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testMultipleReadsPerFrame() throws Exception { public void testMultipleReadsPerFrame() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame
@@ -85,7 +85,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testMultipleReadsPerFrameWithOffsets() throws Exception { public void testMultipleReadsPerFrameWithOffsets() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame

View File

@@ -14,7 +14,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testCloseWithoutWritingWritesFinalFrame() throws Exception { public void testCloseWithoutWritingWritesFinalFrame() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write an empty final frame // Write an empty final frame
oneOf(encrypter).writeFrame(with(any(byte[].class)), with(0), oneOf(encrypter).writeFrame(with(any(byte[].class)), with(0),
@@ -31,7 +31,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
public void testFlushWithoutBufferedDataWritesFrameAndFlushes() public void testFlushWithoutBufferedDataWritesFrameAndFlushes()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write a non-final frame with an empty payload // Write a non-final frame with an empty payload
@@ -58,7 +58,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
public void testFlushWithBufferedDataWritesFrameAndFlushes() public void testFlushWithBufferedDataWritesFrameAndFlushes()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write a non-final frame with one payload byte // Write a non-final frame with one payload byte
@@ -85,7 +85,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testSingleByteWritesWriteFullFrame() throws Exception { public void testSingleByteWritesWriteFullFrame() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write a full non-final frame // Write a full non-final frame
@@ -109,7 +109,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testMultiByteWritesWriteFullFrames() throws Exception { public void testMultiByteWritesWriteFullFrames() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write two full non-final frames // Write two full non-final frames
@@ -140,7 +140,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testLargeMultiByteWriteWritesFullFrames() throws Exception { public void testLargeMultiByteWriteWritesFullFrames() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write two full non-final frames // Write two full non-final frames

View File

@@ -56,21 +56,20 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testKeysAreRotatedAtStartup() throws Exception { public void testKeysAreRotatedAtStartup() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final Map<ContactId, TransportKeys> loaded = Map<ContactId, TransportKeys> loaded = new LinkedHashMap<>();
new LinkedHashMap<ContactId, TransportKeys>(); TransportKeys shouldRotate = createTransportKeys(900, 0);
final TransportKeys shouldRotate = createTransportKeys(900, 0); TransportKeys shouldNotRotate = createTransportKeys(1000, 0);
final TransportKeys shouldNotRotate = createTransportKeys(1000, 0);
loaded.put(contactId, shouldRotate); loaded.put(contactId, shouldRotate);
loaded.put(contactId1, shouldNotRotate); loaded.put(contactId1, shouldNotRotate);
final TransportKeys rotated = createTransportKeys(1000, 0); TransportKeys rotated = createTransportKeys(1000, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get the current time (1 ms after start of rotation period 1000) // Get the current time (1 ms after start of rotation period 1000)
@@ -109,17 +108,17 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testKeysAreRotatedWhenAddingContact() throws Exception { public void testKeysAreRotatedWhenAddingContact() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
final TransportKeys transportKeys = createTransportKeys(999, 0); TransportKeys transportKeys = createTransportKeys(999, 0);
final TransportKeys rotated = createTransportKeys(1000, 0); TransportKeys rotated = createTransportKeys(1000, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 999, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 999,
@@ -156,14 +155,14 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
public void testOutgoingStreamContextIsNullIfContactIsNotFound() public void testOutgoingStreamContextIsNullIfContactIsNotFound()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
TransportKeyManager TransportKeyManager
transportKeyManager = new TransportKeyManagerImpl(db, transportKeyManager = new TransportKeyManagerImpl(db,
@@ -177,18 +176,18 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
public void testOutgoingStreamContextIsNullIfStreamCounterIsExhausted() public void testOutgoingStreamContextIsNullIfStreamCounterIsExhausted()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
// The stream counter has been exhausted // The stream counter has been exhausted
final TransportKeys transportKeys = createTransportKeys(1000, TransportKeys transportKeys = createTransportKeys(1000,
MAX_32_BIT_UNSIGNED + 1); MAX_32_BIT_UNSIGNED + 1);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -225,18 +224,18 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testOutgoingStreamCounterIsIncremented() throws Exception { public void testOutgoingStreamCounterIsIncremented() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
// The stream counter can be used one more time before being exhausted // The stream counter can be used one more time before being exhausted
final TransportKeys transportKeys = createTransportKeys(1000, TransportKeys transportKeys = createTransportKeys(1000,
MAX_32_BIT_UNSIGNED); MAX_32_BIT_UNSIGNED);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -286,16 +285,16 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
public void testIncomingStreamContextIsNullIfTagIsNotFound() public void testIncomingStreamContextIsNullIfTagIsNotFound()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
final TransportKeys transportKeys = createTransportKeys(1000, 0); TransportKeys transportKeys = createTransportKeys(1000, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -333,18 +332,18 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testTagIsNotRecognisedTwice() throws Exception { public void testTagIsNotRecognisedTwice() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
final TransportKeys transportKeys = createTransportKeys(1000, 0); TransportKeys transportKeys = createTransportKeys(1000, 0);
// Keep a copy of the tags // Keep a copy of the tags
final List<byte[]> tags = new ArrayList<byte[]>(); List<byte[]> tags = new ArrayList<>();
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -403,19 +402,19 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testKeysAreRotatedToCurrentPeriod() throws Exception { public void testKeysAreRotatedToCurrentPeriod() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final TransportKeys transportKeys = createTransportKeys(1000, 0); TransportKeys transportKeys = createTransportKeys(1000, 0);
final Map<ContactId, TransportKeys> loaded = Map<ContactId, TransportKeys> loaded =
Collections.singletonMap(contactId, transportKeys); Collections.singletonMap(contactId, transportKeys);
final TransportKeys rotated = createTransportKeys(1001, 0); TransportKeys rotated = createTransportKeys(1001, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get the current time (the start of rotation period 1000) // Get the current time (the start of rotation period 1000)

View File

@@ -1,22 +1,55 @@
apply plugin: 'java' apply plugin: 'java-library'
sourceCompatibility = 1.7 sourceCompatibility = 1.8
targetCompatibility = 1.7 targetCompatibility = 1.8
apply plugin: 'net.ltgt.apt'
apply plugin: 'idea'
apply plugin: 'witness' apply plugin: 'witness'
dependencies { dependencies {
compile project(':bramble-core') implementation project(path: ':bramble-core', configuration: 'default')
compile fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
compile 'net.java.dev.jna:jna:4.4.0' implementation 'net.java.dev.jna:jna:4.4.0'
compile 'net.java.dev.jna:jna-platform:4.4.0' implementation 'net.java.dev.jna:jna-platform:4.4.0'
testCompile project(path: ':bramble-core', configuration: 'testOutput') apt 'com.google.dagger:dagger-compiler:2.0.2'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'net.java.dev.jna:jna:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'net.java.dev.jna:jna-platform:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
] ]
} }

View File

@@ -110,20 +110,16 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
public void run() { public void run() {
try { try {
// Load user32.dll // Load user32.dll
final User32 user32 = (User32) Native.loadLibrary("user32", User32 user32 = (User32) Native.loadLibrary("user32",
User32.class, options); User32.class, options);
// Create a callback to handle the WM_QUERYENDSESSION message // Create a callback to handle the WM_QUERYENDSESSION message
WindowProc proc = new WindowProc() { WindowProc proc = (hwnd, msg, wp, lp) -> {
@Override if (msg == WM_QUERYENDSESSION) {
public LRESULT callback(HWND hwnd, int msg, WPARAM wp, // It's safe to delay returning from this message
LPARAM lp) { runShutdownHooks();
if (msg == WM_QUERYENDSESSION) {
// It's safe to delay returning from this message
runShutdownHooks();
}
// Pass the message to the default window procedure
return user32.DefWindowProc(hwnd, msg, wp, lp);
} }
// Pass the message to the default window procedure
return user32.DefWindowProc(hwnd, msg, wp, lp);
}; };
// Create a native window // Create a native window
HWND hwnd = user32.CreateWindowEx(0, "STATIC", "", WS_MINIMIZE, HWND hwnd = user32.CreateWindowEx(0, "STATIC", "", WS_MINIMIZE,

View File

@@ -41,9 +41,9 @@ public class DesktopPluginModule extends PluginModule {
backoffFactory, shutdownManager); backoffFactory, shutdownManager);
SimplexPluginFactory removable = SimplexPluginFactory removable =
new RemovableDrivePluginFactory(ioExecutor); new RemovableDrivePluginFactory(ioExecutor);
final Collection<SimplexPluginFactory> simplex = Collection<SimplexPluginFactory> simplex =
Collections.singletonList(removable); Collections.singletonList(removable);
final Collection<DuplexPluginFactory> duplex = Collection<DuplexPluginFactory> duplex =
Arrays.asList(bluetooth, modem, lan, wan); Arrays.asList(bluetooth, modem, lan, wan);
@NotNullByDefault @NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() { PluginConfig pluginConfig = new PluginConfig() {

View File

@@ -108,33 +108,30 @@ class BluetoothPlugin implements DuplexPlugin {
} }
private void bind() { private void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { // Advertise the Bluetooth address to contacts
if (!running) return; TransportProperties p = new TransportProperties();
// Advertise the Bluetooth address to contacts p.put(PROP_ADDRESS, localDevice.getBluetoothAddress());
TransportProperties p = new TransportProperties(); callback.mergeLocalProperties(p);
p.put(PROP_ADDRESS, localDevice.getBluetoothAddress()); // Bind a server socket to accept connections from contacts
callback.mergeLocalProperties(p); String url = makeUrl("localhost", getUuid());
// Bind a server socket to accept connections from contacts StreamConnectionNotifier ss;
String url = makeUrl("localhost", getUuid()); try {
StreamConnectionNotifier ss; ss = (StreamConnectionNotifier) Connector.open(url);
try { } catch (IOException e) {
ss = (StreamConnectionNotifier) Connector.open(url); if (LOG.isLoggable(WARNING))
} catch (IOException e) { LOG.log(WARNING, e.toString(), e);
if (LOG.isLoggable(WARNING)) return;
LOG.log(WARNING, e.toString(), e);
return;
}
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections(ss);
} }
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections(ss);
}); });
} }
@@ -207,33 +204,31 @@ class BluetoothPlugin implements DuplexPlugin {
} }
@Override @Override
public void poll(final Collection<ContactId> connected) { public void poll(Collection<ContactId> connected) {
if (!running) return; if (!running) return;
backoff.increment(); backoff.increment();
// Try to connect to known devices in parallel // Try to connect to known devices in parallel
Map<ContactId, TransportProperties> remote = Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties(); callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) { for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
final ContactId c = e.getKey(); ContactId c = e.getKey();
if (connected.contains(c)) continue; if (connected.contains(c)) continue;
final String address = e.getValue().get(PROP_ADDRESS); String address = e.getValue().get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) continue; if (StringUtils.isNullOrEmpty(address)) continue;
final String uuid = e.getValue().get(PROP_UUID); String uuid = e.getValue().get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) continue; if (StringUtils.isNullOrEmpty(uuid)) continue;
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { StreamConnection s = connect(makeUrl(address, uuid));
if (!running) return; if (s != null) {
StreamConnection s = connect(makeUrl(address, uuid)); backoff.reset();
if (s != null) { callback.outgoingConnectionCreated(c, wrapSocket(s));
backoff.reset();
callback.outgoingConnectionCreated(c, wrapSocket(s));
}
} }
}); });
} }
} }
@Nullable
private StreamConnection connect(String url) { private StreamConnection connect(String url) {
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + url); if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + url);
try { try {
@@ -275,7 +270,7 @@ class BluetoothPlugin implements DuplexPlugin {
// Make the device discoverable if possible // Make the device discoverable if possible
makeDeviceDiscoverable(); makeDeviceDiscoverable();
// Bind a server socket for receiving key agreementconnections // Bind a server socket for receiving key agreementconnections
final StreamConnectionNotifier ss; StreamConnectionNotifier ss;
try { try {
ss = (StreamConnectionNotifier) Connector.open(url); ss = (StreamConnectionNotifier) Connector.open(url);
} catch (IOException e) { } catch (IOException e) {
@@ -341,16 +336,13 @@ class BluetoothPlugin implements DuplexPlugin {
@Override @Override
public Callable<KeyAgreementConnection> listen() { public Callable<KeyAgreementConnection> listen() {
return new Callable<KeyAgreementConnection>() { return () -> {
@Override StreamConnection s = ss.acceptAndOpen();
public KeyAgreementConnection call() throws Exception { if (LOG.isLoggable(INFO))
StreamConnection s = ss.acceptAndOpen(); LOG.info(ID.getString() + ": Incoming connection");
if (LOG.isLoggable(INFO)) return new KeyAgreementConnection(
LOG.info(ID.getString() + ": Incoming connection"); new BluetoothTransportConnection(
return new KeyAgreementConnection( BluetoothPlugin.this, s), ID);
new BluetoothTransportConnection(
BluetoothPlugin.this, s), ID);
}
}; };
} }

View File

@@ -13,6 +13,8 @@ import java.util.List;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nullable;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor, abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor,
@@ -34,13 +36,12 @@ JNotifyListener {
protected abstract String[] getPathsToWatch(); protected abstract String[] getPathsToWatch();
@Nullable
private static Throwable tryLoad() { private static Throwable tryLoad() {
try { try {
Class.forName("net.contentobjects.jnotify.JNotify"); Class.forName("net.contentobjects.jnotify.JNotify");
return null; return null;
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError | ClassNotFoundException e) {
return e;
} catch (ClassNotFoundException e) {
return e; return e;
} }
} }

View File

@@ -390,15 +390,12 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
lock.unlock(); lock.unlock();
} }
} else if (s.equals("RING")) { } else if (s.equals("RING")) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override try {
public void run() { answer();
try { } catch (IOException e) {
answer(); if (LOG.isLoggable(WARNING))
} catch (IOException e) { LOG.log(WARNING, e.toString(), e);
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
} }
}); });
} }

View File

@@ -26,10 +26,10 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
@Test @Test
public void testOneCallbackPerFile() throws Exception { public void testOneCallbackPerFile() throws Exception {
// Create a finder that returns no files the first time, then two files // Create a finder that returns no files the first time, then two files
final File file1 = new File("foo"); File file1 = new File("foo");
final File file2 = new File("bar"); File file2 = new File("bar");
@NotNullByDefault @NotNullByDefault
final RemovableDriveFinder finder = new RemovableDriveFinder() { RemovableDriveFinder finder = new RemovableDriveFinder() {
private AtomicBoolean firstCall = new AtomicBoolean(true); private AtomicBoolean firstCall = new AtomicBoolean(true);
@@ -40,8 +40,8 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create a callback that waits for two files // Create a callback that waits for two files
final CountDownLatch latch = new CountDownLatch(2); CountDownLatch latch = new CountDownLatch(2);
final List<File> detected = new ArrayList<>(); List<File> detected = new ArrayList<>();
@NotNullByDefault @NotNullByDefault
Callback callback = new Callback() { Callback callback = new Callback() {
@@ -57,7 +57,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create the monitor and start it // Create the monitor and start it
final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor( RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
Executors.newCachedThreadPool(), finder, 1); Executors.newCachedThreadPool(), finder, 1);
monitor.start(callback); monitor.start(callback);
// Wait for the monitor to detect the files // Wait for the monitor to detect the files
@@ -72,7 +72,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
@Test @Test
public void testExceptionCallback() throws Exception { public void testExceptionCallback() throws Exception {
// Create a finder that throws an exception the second time it's polled // Create a finder that throws an exception the second time it's polled
final RemovableDriveFinder finder = new RemovableDriveFinder() { RemovableDriveFinder finder = new RemovableDriveFinder() {
private AtomicBoolean firstCall = new AtomicBoolean(true); private AtomicBoolean firstCall = new AtomicBoolean(true);
@@ -83,7 +83,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create a callback that waits for an exception // Create a callback that waits for an exception
final CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@NotNullByDefault @NotNullByDefault
Callback callback = new Callback() { Callback callback = new Callback() {
@@ -98,7 +98,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create the monitor and start it // Create the monitor and start it
final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor( RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
Executors.newCachedThreadPool(), finder, 1); Executors.newCachedThreadPool(), finder, 1);
monitor.start(callback); monitor.start(callback);
assertTrue(latch.await(10, SECONDS)); assertTrue(latch.await(10, SECONDS));

View File

@@ -41,17 +41,17 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfNoDrivesAreFound() throws Exception { public void testWriterIsNullIfNoDrivesAreFound() throws Exception {
final List<File> drives = Collections.emptyList(); List<File> drives = Collections.emptyList();
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -71,21 +71,21 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfNoDriveIsChosen() throws Exception { public void testWriterIsNullIfNoDriveIsChosen() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -110,21 +110,21 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfOutputDirDoesNotExist() throws Exception { public void testWriterIsNullIfOutputDirDoesNotExist() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -149,9 +149,9 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfOutputDirIsAFile() throws Exception { public void testWriterIsNullIfOutputDirIsAFile() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
// Create drive1 as a file rather than a directory // Create drive1 as a file rather than a directory
@@ -160,12 +160,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -190,9 +190,9 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNotNullIfOutputDirIsADir() throws Exception { public void testWriterIsNotNullIfOutputDirIsADir() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
// Create drive1 as a directory // Create drive1 as a directory
@@ -201,12 +201,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -234,9 +234,9 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWritingToWriter() throws Exception { public void testWritingToWriter() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
// Create drive1 as a directory // Create drive1 as a directory
@@ -245,12 +245,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -292,12 +292,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -318,12 +318,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor, RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
@@ -344,11 +344,11 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{

View File

@@ -61,10 +61,10 @@ public class UnixRemovableDriveMonitorTest extends BrambleTestCase {
return; return;
} }
// Create a callback that will wait for two files before stopping // Create a callback that will wait for two files before stopping
final List<File> detected = new ArrayList<>(); List<File> detected = new ArrayList<>();
final CountDownLatch latch = new CountDownLatch(2); CountDownLatch latch = new CountDownLatch(2);
@NotNullByDefault @NotNullByDefault
final Callback callback = new Callback() { Callback callback = new Callback() {
@Override @Override
public void driveInserted(File f) { public void driveInserted(File f) {
@@ -99,7 +99,7 @@ public class UnixRemovableDriveMonitorTest extends BrambleTestCase {
TestUtils.deleteTestDirectory(testDir); TestUtils.deleteTestDirectory(testDir);
} }
private RemovableDriveMonitor createMonitor(final File dir) { private RemovableDriveMonitor createMonitor(File dir) {
@NotNullByDefault @NotNullByDefault
RemovableDriveMonitor monitor = new UnixRemovableDriveMonitor() { RemovableDriveMonitor monitor = new UnixRemovableDriveMonitor() {
@Override @Override

View File

@@ -21,12 +21,12 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testModemCreation() throws Exception { public void testModemCreation() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, null, 0); serialPortList, null, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo", "bar", "baz" })); will(returnValue(new String[] { "foo", "bar", "baz" }));
@@ -53,20 +53,20 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testCreateConnection() throws Exception { public void testCreateConnection() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final DuplexPluginCallback callback = DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class); context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0); serialPortList, callback, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
final TransportProperties remote = new TransportProperties(); TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER); remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234); ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
@@ -92,20 +92,20 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testCreateConnectionWhenDialReturnsFalse() throws Exception { public void testCreateConnectionWhenDialReturnsFalse() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final DuplexPluginCallback callback = DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class); context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0); serialPortList, callback, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
final TransportProperties remote = new TransportProperties(); TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER); remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234); ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
@@ -131,20 +131,20 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testCreateConnectionWhenDialThrowsException() throws Exception { public void testCreateConnectionWhenDialThrowsException() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final DuplexPluginCallback callback = DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class); context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0); serialPortList, callback, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
final TransportProperties remote = new TransportProperties(); TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER); remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234); ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();

View File

@@ -1,60 +1,171 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'witness' apply plugin: 'witness'
configurations.all {
resolutionStrategy.preferProjectModules()
}
dependencies { dependencies {
def supportVersion = '23.2.1' implementation project(path: ':briar-core', configuration: 'default')
compile project(':briar-core') implementation project(path: ':bramble-core', configuration: 'default')
compile project(':bramble-android') implementation project(path: ':bramble-android', configuration: 'default')
compile "com.android.support:support-v4:$supportVersion"
compile("com.android.support:appcompat-v7:$supportVersion") { def supportVersion = '27.0.1'
implementation "com.android.support:support-v4:$supportVersion"
implementation("com.android.support:appcompat-v7:$supportVersion") {
exclude module: 'support-v4' exclude module: 'support-v4'
} }
compile("com.android.support:preference-v14:$supportVersion") { implementation("com.android.support:preference-v14:$supportVersion") {
exclude module: 'support-v4' exclude module: 'support-v4'
} }
compile("com.android.support:design:$supportVersion") { implementation("com.android.support:design:$supportVersion") {
exclude module: 'support-v4' exclude module: 'support-v4'
exclude module: 'recyclerview-v7' exclude module: 'recyclerview-v7'
} }
compile "com.android.support:cardview-v7:$supportVersion" implementation "com.android.support:cardview-v7:$supportVersion"
compile "com.android.support:support-annotations:$supportVersion" implementation "com.android.support:support-annotations:$supportVersion"
compile('ch.acra:acra:4.8.5') { implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta3'
implementation('ch.acra:acra:4.8.5') {
exclude module: 'support-v4' exclude module: 'support-v4'
exclude module: 'support-annotations' exclude module: 'support-annotations'
} }
compile 'info.guardianproject.panic:panic:0.5' implementation 'info.guardianproject.panic:panic:0.5'
compile 'info.guardianproject.trustedintents:trustedintents:0.2' implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
compile 'de.hdodenhof:circleimageview:2.1.0' implementation 'de.hdodenhof:circleimageview:2.1.0'
compile 'com.google.zxing:core:3.3.0' implementation 'com.google.zxing:core:3.3.0'
compile 'com.jpardogo.materialtabstrip:library:1.1.0' implementation 'com.jpardogo.materialtabstrip:library:1.1.0'
compile 'com.github.bumptech.glide:glide:3.8.0' implementation 'com.github.bumptech.glide:glide:3.8.0'
compile 'uk.co.samuelwall:material-tap-target-prompt:1.9.2' implementation 'uk.co.samuelwall:material-tap-target-prompt:2.1.0'
provided 'javax.annotation:jsr250-api:1.0' annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
testCompile project(path: ':bramble-core', configuration: 'testOutput') compileOnly 'javax.annotation:jsr250-api:1.0'
testCompile 'org.robolectric:robolectric:3.0'
testCompile 'org.mockito:mockito-core:2.8.9' testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation 'org.robolectric:robolectric:3.5.1'
testImplementation 'org.robolectric:shadows-support-v4:3.0'
testImplementation 'org.mockito:mockito-core:2.8.9'
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'ch.acra:acra:afd5b28934d5166b55f261c85685ad59e8a4ebe9ca1960906afaa8c76d8dc9eb', 'android.arch.core:common:1.0.0:common-1.0.0.jar:5192934cd73df32e2c15722ed7fc488dde90baaec9ae030010dd1a80fb4e74e1',
'info.guardianproject.panic:panic:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2', 'android.arch.lifecycle:common:1.0.0:common-1.0.0.jar:86bf301a20ad0cd0a391e22a52e6fbf90575c096ff83233fa9fd0d52b3219121',
'info.guardianproject.trustedintents:trustedintents:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e', 'android.arch.lifecycle:runtime:1.0.0:runtime-1.0.0.aar:e4e34e5d02bd102e8d39ddbc29f9ead8a15a61e367993d02238196ac48509ad8',
'de.hdodenhof:circleimageview:bcbc588e19e6dcf8c120b1957776bfe229efba5d2fbe5da7156372eeacf65503', 'backport-util-concurrent:backport-util-concurrent:3.1:backport-util-concurrent-3.1.jar:f5759b7fcdfc83a525a036deedcbd32e5b536b625ebc282426f16ca137eb5902',
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.jpardogo.materialtabstrip:library:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311', 'ch.acra:acra:4.8.5:acra-4.8.5.aar:afd5b28934d5166b55f261c85685ad59e8a4ebe9ca1960906afaa8c76d8dc9eb',
'com.github.bumptech.glide:glide:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655', 'classworlds:classworlds:1.1-alpha-2:classworlds-1.1-alpha-2.jar:2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3',
'uk.co.samuelwall:material-tap-target-prompt:5d4951124366bc5c52e57beaa294db7611f0aa2a8d80e0163e1383e1966ba5b2', 'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
'com.android.support:appcompat-v7:00f9d93acacd6731f309724054bf51492814b4b2869f16d7d5c0038dcb8c9a0d', 'com.android.support.constraint:constraint-layout-solver:1.1.0-beta3:constraint-layout-solver-1.1.0-beta3.jar:c9084108415046c423983bdff8cf04c8e9a5bed41b8d5329f3764c08312ee3dd',
'com.android.support:preference-v14:44881bb46094e86d0bc2426f205419674a5b4eb514b44b5a4659b5de29f71eb7', 'com.android.support.constraint:constraint-layout:1.1.0-beta3:constraint-layout-1.1.0-beta3.aar:1754a6bd135feae485aa2ebf9e170f0f3d3282b392f8aa3067d0ed668839db79',
'com.android.support:design:003e0c0bea0a6891f8b2bc43f20ae7af2a49a17363e5bb10df5ee0bae12fa686', 'com.android.support:animated-vector-drawable:27.0.1:animated-vector-drawable-27.0.1.aar:365050110411c86c7eec86101b49ab53557ffe6667f60b19055f1d35c38a577b',
'com.android.support:cardview-v7:4595f1c4a28cfa083b6c0920ad4d49e1c2ca4b8302a955e548f68eb63b74931b', 'com.android.support:appcompat-v7:27.0.1:appcompat-v7-27.0.1.aar:1402c29a49db30346c21a7d40634461765b3ab826f5dd95bc4dcc76787b21851',
'com.android.support:animated-vector-drawable:06d1963b85aa917099d7757e6a7b3e4dc06889413dc747f625ae8683606db3a1', 'com.android.support:cardview-v7:27.0.1:cardview-v7-27.0.1.aar:43fccd44086c51eaa9d78be2fcf0dfea1556c8876a6fd325ea8d24e860054202',
'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1', 'com.android.support:design:27.0.1:design-27.0.1.aar:0e7c694bd5385e82d193e33b7289f769ce6ff05e277443daf5bffc3d852ef448',
'com.android.support:recyclerview-v7:44040a888e23e0c93162a3377cfe06751080e3c22d369ab0d4301ef60d63b0fe', 'com.android.support:preference-v14:27.0.1:preference-v14-27.0.1.aar:beed3ee97ae0d2541bd0adac6c84bb7d7b7580399f24e8efb9bc624161b164df',
'com.android.support:preference-v7:775101bd07bd052e455761c5c5d9523d7ad59f2f320e3e8cbde241fd6b1d6025', 'com.android.support:preference-v7:27.0.1:preference-v7-27.0.1.aar:d87ba6ae7c834fd68ef09cbc0f064975627ba14189dbef639c34080691366da9',
'com.android.support:recyclerview-v7:27.0.1:recyclerview-v7-27.0.1.aar:99ae2863287df800f239617d09cafc58b95f7a5365db32e3761394fa01ab12c9',
'com.android.support:support-annotations:27.0.1:support-annotations-27.0.1.jar:240912b779fe7413bdd97c94ac2a92d1fb29bd53c4d50c6982e5942b01278ac0',
'com.android.support:support-compat:27.0.1:support-compat-27.0.1.aar:70dfd92561421e5ae113dfc4045fc94c90caca9912839b3d08c793aa391aedcc',
'com.android.support:support-core-ui:27.0.1:support-core-ui-27.0.1.aar:91614f829f8a6f1fc2d28efc58ea2735212225ab02cdf768b3dd9af72371d5f0',
'com.android.support:support-core-utils:27.0.1:support-core-utils-27.0.1.aar:b33c5a5d67b8bfa6c8829875661779279157bf23e6042179820eaf1745034a72',
'com.android.support:support-fragment:27.0.1:support-fragment-27.0.1.aar:05a859783ae4a285c6d5c9865e1242b86f5bfb69a30455ca6c8495f24c09d9ed',
'com.android.support:support-media-compat:27.0.1:support-media-compat-27.0.1.aar:bc1c0252c1d071a1676fd280a792cf0717833fb3afd0ef73070ddc51ef921ad7',
'com.android.support:support-v4:27.0.1:support-v4-27.0.1.aar:afd802f1926475f40c5b6b42855c9a626a854298908dafdb455deb6dab2640f2',
'com.android.support:support-vector-drawable:27.0.1:support-vector-drawable-27.0.1.aar:67154ea191f735496502214bc6da6195738829a8e9d59e8042a1e030a2c7f19c',
'com.android.support:transition:27.0.1:transition-27.0.1.aar:8a46d152391bd1598d1778ae889b3aeaff77a17d0caaa29446df6e26a28c4e4b',
'com.github.bumptech.glide:glide:3.8.0:glide-3.8.0.jar:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655',
'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.1:accessibility-test-framework-2.1.jar:7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.guava:guava:20.0:guava-20.0.jar:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8',
'com.google.protobuf:protobuf-java:2.6.1:protobuf-java-2.6.1.jar:55aa554843983f431df5616112cf688d38aa17c132357afd1c109435bfdac4e6',
'com.google.zxing:core:3.3.0:core-3.3.0.jar:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
'com.jpardogo.materialtabstrip:library:1.1.0:library-1.1.0.aar:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'com.rometools:rome-utils:1.7.3:rome-utils-1.7.3.jar:f774a80e7e1bc9db5426b62333ab362537f901636cd0812dc84cb5ee2668acf9',
'com.rometools:rome:1.7.3:rome-1.7.3.jar:077367bf8fa01b211c9da712c2aa862724195773c5693fd4d97d61d6457e96c6',
'com.squareup.okhttp3:okhttp:3.8.0:okhttp-3.8.0.jar:19e1db51787716ff0046fa19e408fb34ed32a6274baa0c07475bf724b4eb6800',
'com.squareup.okio:okio:1.13.0:okio-1.13.0.jar:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
'com.thoughtworks.xstream:xstream:1.4.8:xstream-1.4.8.jar:a219a1abf948400b669d08be73a6f9209fb720d237e5ff74c223bffe5f9df93d',
'de.hdodenhof:circleimageview:2.1.0:circleimageview-2.1.0.aar:bcbc588e19e6dcf8c120b1957776bfe229efba5d2fbe5da7156372eeacf65503',
'info.guardianproject.panic:panic:0.5:panic-0.5.jar:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
'info.guardianproject.trustedintents:trustedintents:0.2:trustedintents-0.2.jar:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'nekohtml:nekohtml:1.9.6.2:nekohtml-1.9.6.2.jar:fdff6cfa9ed9cc911c842a5d2395f209ec621ef1239d46810e9e495809d3ae09',
'nekohtml:xercesMinimal:1.9.6.2:xercesMinimal-1.9.6.2.jar:95b8b357d19f63797dd7d67622fd3f18374d64acbc6584faba1c7759a31e8438',
'net.bytebuddy:byte-buddy-agent:1.6.14:byte-buddy-agent-1.6.14.jar:c141a2d6809c3eeff4a43d25992826abccebdd4b793af3e7a5f346e88ae73a33',
'net.bytebuddy:byte-buddy:1.6.14:byte-buddy-1.6.14.jar:917758b3c651e278a15a029ba1d42dbf802d8b0e1fe2aa4b81c5750c64f461c1',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.maven.wagon:wagon-file:1.0-beta-6:wagon-file-1.0-beta-6.jar:7298feeb36ff14dd933c38e62585fb9973fea32fb3c4bc5379428cb1aac5dd3c',
'org.apache.maven.wagon:wagon-http-lightweight:1.0-beta-6:wagon-http-lightweight-1.0-beta-6.jar:be214032de23c6b520b79c1ccdb160948e0c67ed7c11984b7ec4ca5537867b4e',
'org.apache.maven.wagon:wagon-http-shared:1.0-beta-6:wagon-http-shared-1.0-beta-6.jar:f095c882716d49269a806685dcb256fa6a36389b2713ac56bb758bf8693565a2',
'org.apache.maven.wagon:wagon-provider-api:1.0-beta-6:wagon-provider-api-1.0-beta-6.jar:e116f32edcb77067289a3148143f2c0c97b27cf9a1342f8108ee37dec4868861',
'org.apache.maven:maven-ant-tasks:2.1.3:maven-ant-tasks-2.1.3.jar:f16b5ea711dfe0323454b880180aa832420ec039936e4aa75fb978748634808a',
'org.apache.maven:maven-artifact-manager:2.2.1:maven-artifact-manager-2.2.1.jar:d1e247c4ed3952385fd704ac9db2a222247cfe7d20508b4f3c76b90f857952ed',
'org.apache.maven:maven-artifact:2.2.1:maven-artifact-2.2.1.jar:d53062ffe8677a4f5e1ad3a1d1fa37ed600fab39166d39be7ed204635c5f839b',
'org.apache.maven:maven-error-diagnostics:2.2.1:maven-error-diagnostics-2.2.1.jar:b3005544708f8583e455c22b09a4940596a057108bccdadb9db4d8e048091fed',
'org.apache.maven:maven-model:2.2.1:maven-model-2.2.1.jar:153b32f474fd676ec36ad807c508885005139140fc92168bb76bf6be31f8efb8',
'org.apache.maven:maven-plugin-registry:2.2.1:maven-plugin-registry-2.2.1.jar:4ad0673155d7e0e5cf6d13689802d8d507f38e5ea00a6d2fb92aef206108213d',
'org.apache.maven:maven-profile:2.2.1:maven-profile-2.2.1.jar:ecaffef655fea6b138f0855a12f7dbb59fc0d6bffb5c1bfd31803cccb49ea08c',
'org.apache.maven:maven-project:2.2.1:maven-project-2.2.1.jar:24ddb65b7a6c3befb6267ce5f739f237c84eba99389265c30df67c3dd8396a40',
'org.apache.maven:maven-repository-metadata:2.2.1:maven-repository-metadata-2.2.1.jar:5fe283f47b0e7f7d95a4252af3fa7a0db4d8f080cd9df308608c0472b8f168a1',
'org.apache.maven:maven-settings:2.2.1:maven-settings-2.2.1.jar:9a9f556713a404e770c9dbdaed7eb086078014c989291960c76fdde6db4192f7',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.bouncycastle:bcprov-jdk15on:1.52:bcprov-jdk15on-1.52.jar:0dc4d181e4d347893c2ddbd2e6cd5d7287fc651c03648fa64b2341c7366b1773',
'org.codehaus.plexus:plexus-container-default:1.0-alpha-9-stable-1:plexus-container-default-1.0-alpha-9-stable-1.jar:7c758612888782ccfe376823aee7cdcc7e0cdafb097f7ef50295a0b0c3a16edf',
'org.codehaus.plexus:plexus-interpolation:1.11:plexus-interpolation-1.11.jar:fd9507feb858fa620d1b4aa4b7039fdea1a77e09d3fd28cfbddfff468d9d8c28',
'org.codehaus.plexus:plexus-utils:1.5.15:plexus-utils-1.5.15.jar:2ca121831e597b4d8f2cb22d17c5c041fc23a7777ceb6bfbdd4dfb34bbe7d997',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128-runtime.jar:e357a0f1d573c2f702a273992b1b6cb661734f66311854efb3778a888515c5b5',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128.jar:47b4bec6df11a1118da3953da8b9fa1e7079d6fec857faa1a3cf912e53a6fd4e',
'org.jacoco:org.jacoco.ant:0.7.4.201502262128:org.jacoco.ant-0.7.4.201502262128.jar:013ce2a68ba57a3c59215ae0dec4df3498c078062a38c3b94c841fc14450f283',
'org.jacoco:org.jacoco.core:0.7.4.201502262128:org.jacoco.core-0.7.4.201502262128.jar:ec4c74554312fac5116350164786f91b35c9e082fa4ea598bfa42b5db05d7abb',
'org.jacoco:org.jacoco.report:0.7.4.201502262128:org.jacoco.report-0.7.4.201502262128.jar:7a3554c605e088e7e323b1084656243f0444fa353e2f2dee1f1a4204eb64ff09',
'org.jdom:jdom2:2.0.6:jdom2-2.0.6.jar:1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jsoup:jsoup:1.10.3:jsoup-1.10.3.jar:a0784e793d7f518eb1defb47b428da011cd483c5da32d49c569bf491e4f1579a',
'org.mockito:mockito-core:2.8.9:mockito-core-2.8.9.jar:a2bb9b8b40d81bb02ccb84259524c0f4911f73c6577bfc7ddd940b8fc729b6e6',
'org.objenesis:objenesis:2.5:objenesis-2.5.jar:293328e1b0d31ed30bb89fca542b6c52fac00989bb0e62eb9d98d630c4dd6b7c',
'org.ow2.asm:asm-commons:5.0.1:asm-commons-5.0.1.jar:fb1cb7fa27d892712ced8fbf8d027eb5052ecd3999dba1ba47824357accb40e7',
'org.ow2.asm:asm-debug-all:5.0.1:asm-debug-all-5.0.1.jar:4734de5b515a454b0096db6971fb068e5f70e6f10bbee2b3bd2fdfe5d978ed57',
'org.ow2.asm:asm-tree:5.0.1:asm-tree-5.0.1.jar:ff2aceed10da9930a44f6c8f81c6372d5e55eb59c4e0ea9d37f77dfd765fa9fa',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.robolectric:annotations:3.5.1:annotations-3.5.1.jar:14db0f7d2299c5400ff7764bb37b4fa80306582d8965fdf6999091723e2384ce',
'org.robolectric:junit:3.5.1:junit-3.5.1.jar:b2e81b7d5a22755f2ea76aa9bbbd4359d61c4cb9577193ccfbb8f97378ed293b',
'org.robolectric:resources:3.5.1:resources-3.5.1.jar:22a5564590c8bfd8df7efb2b0c7d9942b46a0beb59ba38899d59c1270f293b1c',
'org.robolectric:robolectric:3.5.1:robolectric-3.5.1.jar:603cf898f93b854f18021fab452aca3fe482368eeb2e720988ae82212ebcf4b6',
'org.robolectric:sandbox:3.5.1:sandbox-3.5.1.jar:beff8c3c1e840e0f7f78aadef170f347bae349f098babfc176765f499a4bcbb5',
'org.robolectric:shadowapi:3.5.1:shadowapi-3.5.1.jar:6d574f9ae0922791eb8f06979f0010997d4b862c7aec96d485ae797ddfc13278',
'org.robolectric:shadows-framework:3.5.1:shadows-framework-3.5.1.jar:597b54cc1a494799d783921c6ac04352f33e94fca8e00f299d4ca192db79e3fc',
'org.robolectric:shadows-support-v4:3.0:shadows-support-v4-3.0.jar:66bcc3257b037d72998e860d67b1bc58215b7eeac8ad860fcc3e613332d88619',
'org.robolectric:utils:3.5.1:utils-3.5.1.jar:d7d77326867e6d903156ebb18c244819b26aebe3aa82a1c57081081a0b6c4f63',
'org.slf4j:slf4j-api:1.7.16:slf4j-api-1.7.16.jar:e56288031f5e60652c06e7bb6e9fa410a61231ab54890f7b708fc6adc4107c5b',
'uk.co.samuelwall:material-tap-target-prompt:2.1.0:material-tap-target-prompt-2.1.0.aar:6df17e7c371f9264bfe440506f91205dd47566869c1528891943a04a26c96a94',
'xmlpull:xmlpull:1.1.3.1:xmlpull-1.1.3.1.jar:34e08ee62116071cbb69c0ed70d15a7a5b208d62798c59f2120bb8929324cb63',
'xpp3:xpp3_min:1.1.4c:xpp3_min-1.1.4c.jar:bfc90e9e32d0eab1f397fb974b5f150a815188382ac41f372a7149d5bc178008',
] ]
} }
@@ -62,7 +173,7 @@ def getGitHash = { ->
def stdout = new ByteArrayOutputStream() def stdout = new ByteArrayOutputStream()
try { try {
exec { exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD' commandLine 'git', 'rev-parse', '--short=7', 'HEAD'
standardOutput = stdout standardOutput = stdout
} }
return stdout.toString().trim() return stdout.toString().trim()
@@ -72,14 +183,14 @@ def getGitHash = { ->
} }
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "23.0.3" buildToolsVersion '26.0.2'
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 22 targetSdkVersion 26
versionCode 1611 versionCode 1617
versionName "0.16.11" versionName "0.16.17"
applicationId "org.briarproject.briar.beta" applicationId "org.briarproject.briar.beta"
resValue "string", "app_package", "org.briarproject.briar.beta" resValue "string", "app_package", "org.briarproject.briar.beta"
resValue "string", "app_name", "Briar Beta" resValue "string", "app_name", "Briar Beta"
@@ -90,7 +201,7 @@ android {
debug { debug {
applicationIdSuffix ".debug" applicationIdSuffix ".debug"
resValue "string", "app_package", "org.briarproject.briar.beta.debug" resValue "string", "app_package", "org.briarproject.briar.beta.debug"
resValue "string", "app_name", "Briar Debug" resValue "string", "app_name", "Briar Beta Debug"
shrinkResources false shrinkResources false
minifyEnabled true minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
@@ -103,8 +214,14 @@ android {
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_8
}
testOptions {
unitTests {
includeAndroidResources = true
}
} }
aaptOptions { aaptOptions {

View File

@@ -15,6 +15,7 @@
<uses-permission android:name="android.permission.READ_LOGS"/> <uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<application <application
android:name="org.briarproject.briar.android.BriarApplicationImpl" android:name="org.briarproject.briar.android.BriarApplicationImpl"

Some files were not shown because too many files have changed in this diff Show More