diff --git a/briar-headless/build.gradle b/briar-headless/build.gradle index efff4722b08b349bc1403c3f02eba69b5a244caf..704bb1b01dbcf9caead97332931e17e197b56a02 100644 --- a/briar-headless/build.gradle +++ b/briar-headless/build.gradle @@ -37,9 +37,9 @@ dependencies { testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" - testImplementation 'io.mockk:mockk:1.10.4' + testImplementation 'io.mockk:mockk:1.12.4' testImplementation 'org.skyscreamer:jsonassert:1.5.0' - testImplementation 'khttp:khttp:0.1.0' + testImplementation "com.squareup.okhttp3:okhttp:4.10.0" kaptTest "com.google.dagger:dagger-compiler:$daggerVersion" } diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/IntegrationTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/IntegrationTest.kt index ac26ea72dfa5890176a9b50a3e19da3fe799b5b2..3c66aac4f4d58790aab4abf1ef95fd651dce02c6 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/IntegrationTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/IntegrationTest.kt @@ -2,7 +2,11 @@ package org.briarproject.briar.headless import io.javalin.Javalin import io.javalin.core.util.Header.AUTHORIZATION -import khttp.responses.Response +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response import org.briarproject.bramble.BrambleCoreEagerSingletons import org.briarproject.bramble.api.crypto.CryptoComponent import org.briarproject.briar.BriarCoreEagerSingletons @@ -22,6 +26,7 @@ abstract class IntegrationTest { private val dataDir = File("tmp") + private val client: OkHttpClient = OkHttpClient() protected lateinit var api: Javalin protected lateinit var crypto: CryptoComponent protected lateinit var testDataCreator: TestDataCreator @@ -48,34 +53,55 @@ abstract class IntegrationTest { dataDir.deleteRecursively() } - protected fun get(url: String): Response { - return khttp.get(url, getAuthTokenHeader(token)) + protected fun get(url: String, authToken: String = token): Response { + val request: Request = Request.Builder() + .url(url) + .header(AUTHORIZATION, "Bearer $authToken") + .build() + return client.newCall(request).execute() } protected fun getWithWrongToken(url: String): Response { - return khttp.get(url, getAuthTokenHeader("wrongToken")) + return get(url, "wrongToken") } - protected fun post(url: String, data: String): Response { - return khttp.post(url, getAuthTokenHeader(token), data = data) + protected fun post(url: String, data: String, authToken: String = token): Response { + val json = "application/json; charset=utf-8".toMediaType() + val body = data.toRequestBody(json) + val request: Request = Request.Builder() + .url(url) + .header(AUTHORIZATION, "Bearer $authToken") + .post(body) + .build() + return client.newCall(request).execute() } protected fun postWithWrongToken(url: String): Response { - return khttp.post(url, getAuthTokenHeader("wrongToken"), data = "") + return post(url, data = "", authToken = "wrongToken") } - protected fun delete(url: String): Response { - return khttp.delete(url, getAuthTokenHeader(token)) + protected fun delete(url: String, authToken: String = token): Response { + val request: Request = Request.Builder() + .url(url) + .header(AUTHORIZATION, "Bearer $authToken") + .delete() + .build() + return client.newCall(request).execute() } - protected fun delete(url: String, data: String): Response { - return khttp.delete(url, getAuthTokenHeader(token), data = data) + protected fun delete(url: String, data: String, authToken: String = token): Response { + val json = "application/json; charset=utf-8".toMediaType() + val body = data.toRequestBody(json) + val request: Request = Request.Builder() + .url(url) + .header(AUTHORIZATION, "Bearer $authToken") + .delete(body) + .build() + return client.newCall(request).execute() } protected fun deleteWithWrongToken(url: String): Response { - return khttp.delete(url, getAuthTokenHeader("wrongToken")) + return delete(url, authToken = "wrongToken") } - private fun getAuthTokenHeader(token: String) = mapOf(Pair(AUTHORIZATION, "Bearer $token")) - } diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerIntegrationTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerIntegrationTest.kt index 9c4cfcc2a172330cb8f73fcfa28a9c3fe28b4973..2e1e345b7da762c2822a43b7f0b094e47cf61c20 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerIntegrationTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerIntegrationTest.kt @@ -1,26 +1,39 @@ package org.briarproject.briar.headless.contact +import okhttp3.Response import org.briarproject.bramble.api.contact.HandshakeLinkConstants.BASE32_LINK_BYTES import org.briarproject.briar.headless.IntegrationTest import org.briarproject.briar.headless.url import org.briarproject.briar.test.BriarTestUtils.getRealHandshakeLink +import org.json.JSONArray +import org.json.JSONObject import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class ContactControllerIntegrationTest : IntegrationTest() { + /** + * Can only be called once. + */ + private val Response.jsonArray: JSONArray get() = JSONArray(body?.use { it.string() }) + + /** + * Can only be called once. + */ + private val Response.jsonObject: JSONObject get() = JSONObject(body?.use { it.string() }) + @Test fun `returning list of contacts needs authentication token`() { val response = getWithWrongToken("$url/contacts") - assertEquals(401, response.statusCode) + assertEquals(401, response.code) } @Test fun `returns list of contacts`() { // retrieve empty list of contacts var response = get("$url/contacts") - assertEquals(200, response.statusCode) + assertEquals(200, response.code) assertEquals(0, response.jsonArray.length()) // add one test contact @@ -29,9 +42,10 @@ class ContactControllerIntegrationTest : IntegrationTest() { // retrieve list with one test contact response = get("$url/contacts") - assertEquals(200, response.statusCode) - assertEquals(1, response.jsonArray.length()) - val contact = response.jsonArray.getJSONObject(0) + assertEquals(200, response.code) + val jsonArray = response.jsonArray + assertEquals(1, jsonArray.length()) + val contact = jsonArray.getJSONObject(0) val author = contact.getJSONObject("author") assertEquals(testContactName, author.getString("name")) } @@ -39,7 +53,7 @@ class ContactControllerIntegrationTest : IntegrationTest() { @Test fun `returns own handshake link`() { val response = get("$url/contacts/add/link") - assertEquals(200, response.statusCode) + assertEquals(200, response.code) val link = response.jsonObject.getString("link") assertTrue(link.startsWith("briar://")) assertEquals(BASE32_LINK_BYTES + 8, link.length) @@ -48,14 +62,14 @@ class ContactControllerIntegrationTest : IntegrationTest() { @Test fun `returning own handshake link needs authentication token`() { val response = getWithWrongToken("$url/contacts/add/link") - assertEquals(401, response.statusCode) + assertEquals(401, response.code) } @Test fun `returns list of pending contacts`() { // retrieve empty list of pending contacts var response = get("$url/contacts/add/pending") - assertEquals(200, response.statusCode) + assertEquals(200, response.code) assertEquals(0, response.jsonArray.length()) // add one pending contact @@ -65,37 +79,38 @@ class ContactControllerIntegrationTest : IntegrationTest() { "alias": "$alias" }""" response = post("$url/contacts/add/pending", json) - assertEquals(200, response.statusCode) + assertEquals(200, response.code) // get added contact as only list item response = get("$url/contacts/add/pending") - assertEquals(200, response.statusCode) - assertEquals(1, response.jsonArray.length()) - val jsonObject = response.jsonArray.getJSONObject(0) + assertEquals(200, response.code) + val jsonArray = response.jsonArray + assertEquals(1, jsonArray.length()) + val jsonObject = jsonArray.getJSONObject(0) assertEquals(alias, jsonObject.getJSONObject("pendingContact").getString("alias")) // remove pending contact again val idString = jsonObject.getJSONObject("pendingContact").getString("pendingContactId") val deleteJson = """{"pendingContactId": "$idString"}""" - response = delete("$url/contacts/add/pending", deleteJson) - assertEquals(200, response.statusCode) + response = delete("$url/contacts/add/pending", data = deleteJson) + assertEquals(200, response.code) // list of pending contacts should be empty now response = get("$url/contacts/add/pending") - assertEquals(200, response.statusCode) + assertEquals(200, response.code) assertEquals(0, response.jsonArray.length()) } @Test fun `returning list of pending contacts needs authentication token`() { val response = getWithWrongToken("$url/contacts/add/pending") - assertEquals(401, response.statusCode) + assertEquals(401, response.code) } @Test fun `adding a pending contact needs authentication token`() { val response = postWithWrongToken("$url/contacts/add/pending") - assertEquals(401, response.statusCode) + assertEquals(401, response.code) } @Test @@ -106,7 +121,7 @@ class ContactControllerIntegrationTest : IntegrationTest() { "alias": "$alias" }""" val response = post("$url/contacts/add/pending", json) - assertEquals(400, response.statusCode) + assertEquals(400, response.code) assertEquals("INVALID_LINK", response.jsonObject.getString("error")) } @@ -118,7 +133,7 @@ class ContactControllerIntegrationTest : IntegrationTest() { "alias": "$alias" }""" val response = post("$url/contacts/add/pending", json) - assertEquals(400, response.statusCode) + assertEquals(400, response.code) assertEquals("INVALID_PUBLIC_KEY", response.jsonObject.getString("error")) } @@ -130,36 +145,37 @@ class ContactControllerIntegrationTest : IntegrationTest() { "alias": "$alias" }""" var response = post("$url/contacts/add/pending", json) - assertEquals(200, response.statusCode) + assertEquals(200, response.code) val pendingContactId = response.jsonObject.getString("pendingContactId") response = post("$url/contacts/add/pending", json) - assertEquals(403, response.statusCode) - assertEquals("PENDING_EXISTS", response.jsonObject.getString("error")) - assertEquals(pendingContactId, response.jsonObject.getString("pendingContactId")) - assertEquals(alias, response.jsonObject.getString("pendingContactAlias")) + assertEquals(403, response.code) + val jsonObject = response.jsonObject + assertEquals("PENDING_EXISTS", jsonObject.getString("error")) + assertEquals(pendingContactId, jsonObject.getString("pendingContactId")) + assertEquals(alias, jsonObject.getString("pendingContactAlias")) } @Test fun `removing a pending contact needs authentication token`() { val response = deleteWithWrongToken("$url/contacts/add/pending") - assertEquals(401, response.statusCode) + assertEquals(401, response.code) } @Test fun `deleting a contact needs authentication token`() { val response = deleteWithWrongToken("$url/contacts/1") - assertEquals(401, response.statusCode) + assertEquals(401, response.code) } @Test fun `deleting real and non-existing contact`() { var response = delete("$url/contacts/1") - assertEquals(200, response.statusCode) + assertEquals(200, response.code) response = delete("$url/contacts/1") - assertEquals(404, response.statusCode) + assertEquals(404, response.code) } } diff --git a/briar-headless/witness.gradle b/briar-headless/witness.gradle index 9c7063f5cd8a9f04d08018cbb8977ff963a19f6d..2d45f588162c186875a487c9902841031b0968fd 100644 --- a/briar-headless/witness.gradle +++ b/briar-headless/witness.gradle @@ -16,22 +16,24 @@ dependencyVerification { 'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6', + 'com.squareup.okhttp3:okhttp:4.10.0:okhttp-4.10.0.jar:7580f14fa1691206e37081ad3f92063b1603b328da0bb316f2fef02e0562e7ec', + 'com.squareup.okio:okio-jvm:3.0.0:okio-jvm-3.0.0.jar:be64a0cc1f28ea9cd5c970dd7e7557af72c808d738c495b397bf897c9921e907', + 'com.squareup.okio:okio:3.0.0:okio-metadata-3.0.0.jar:dcbe63ed43b2c90c325e9e6a0863e2e7605980bff5e728c6de1088be5574979e', 'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90', 'com.vaadin.external.google:android-json:0.0.20131108.vaadin1:android-json-0.0.20131108.vaadin1.jar:dfb7bae2f404cfe0b72b4d23944698cb716b7665171812a0a4d0f5926c0fac79', 'io.javalin:javalin:3.5.0:javalin-3.5.0.jar:6618f99ad4c241eefcaf3a02c85adc52ec346c9710e8eb5a3f1a916e3d7acec4', - 'io.mockk:mockk-agent-api:1.10.4:mockk-agent-api-1.10.4.jar:8deb59189b48d5870a746f954ca681424040544812c7ae295f3bef87a9499cfe', - 'io.mockk:mockk-agent-common:1.10.4:mockk-agent-common-1.10.4.jar:13b81a3297a3c15ed9f62b838aaede20347018f07c30cad2ca74a4dd99786f8f', - 'io.mockk:mockk-agent-jvm:1.10.4:mockk-agent-jvm-1.10.4.jar:51eb22de58c44f140384e61878e8c0da0fcf80c60a139d28ef7b027ea4bc2042', - 'io.mockk:mockk-common:1.10.4:mockk-common-1.10.4.jar:aaf3cc99442100767dc72776f250113f992facfb43bf6ba9a5282d1c8aaecd00', - 'io.mockk:mockk-dsl-jvm:1.10.4:mockk-dsl-jvm-1.10.4.jar:2432e2d0dfd31c3cb33e12137b8c712358cb0c4cddbd27b5bd6c55db2068e1a1', - 'io.mockk:mockk-dsl:1.10.4:mockk-dsl-1.10.4.jar:b97d750bebfd7da92a020f5417deface710c58802a78a8fff68661f77eaa3037', - 'io.mockk:mockk:1.10.4:mockk-1.10.4.jar:e26d4eb8c9c0c5ac00acb9bfeedfe0feb10055bf7e80db57539936413ea38f7c', + 'io.mockk:mockk-agent-api:1.12.4:mockk-agent-api-1.12.4.jar:6eb3407b1f88c0c0ced9636f82874100786b74b3b06c4354c4d85229779fdec8', + 'io.mockk:mockk-agent-common:1.12.4:mockk-agent-common-1.12.4.jar:427d071ec7a85f105c152a51a89738d8ee52954130e5c09500837dfbe3549329', + 'io.mockk:mockk-agent-jvm:1.12.4:mockk-agent-jvm-1.12.4.jar:840c11f2e0a14d35e229c2b6018273f4623c7f619ebf9701164bb9c2db99c098', + 'io.mockk:mockk-common:1.12.4:mockk-common-1.12.4.jar:16f1ba4738535458cb91fa1a759794f6618a6f9f1ae1d149e79b48cc06ea5e7b', + 'io.mockk:mockk-dsl-jvm:1.12.4:mockk-dsl-jvm-1.12.4.jar:faee4b52def68fa182f89d23c2a45f2246ef88b6b1ba98346aa85f57e5ed630f', + 'io.mockk:mockk-dsl:1.12.4:mockk-dsl-1.12.4.jar:7fc96f9ed5118c915a3890ba2e4090c9b283ae7bdc37ab83885415bdf77650e4', + 'io.mockk:mockk:1.12.4:mockk-1.12.4.jar:2c34a3690b958a3cf38b82d0f4910dc9992fb078dce6f56d71498293557bf805', 'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.servlet:javax.servlet-api:3.1.0:javax.servlet-api-3.1.0.jar:af456b2dd41c4e82cf54f3e743bc678973d9fe35bd4d3071fa05c7e5333b8482', - 'khttp:khttp:0.1.0:khttp-0.1.0.jar:48ab3bd22e461f2c2e74e3446d8f9568e24aab157f61fdc85ded6c0bfbe9a926', - 'net.bytebuddy:byte-buddy-agent:1.10.14:byte-buddy-agent-1.10.14.jar:30272167eceb1cb68fa84730a12d1abfd1daed6ae0c19fdefee47a9a9a0cfd33', - 'net.bytebuddy:byte-buddy:1.10.14:byte-buddy-1.10.14.jar:0e6b935bfcb3e451d525956acad53ec86ff916d714abdbd32b3d2039771896f8', + 'net.bytebuddy:byte-buddy-agent:1.12.6:byte-buddy-agent-1.12.6.jar:9b29421fe4650b75fc3ed53590f914c54f932e334b3506cc00296dff73024183', + 'net.bytebuddy:byte-buddy:1.12.6:byte-buddy-1.12.6.jar:211918dc24f0fdef4335ce8af40ef5616e15e818b962a21146397c7701eb75a7', 'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'org.apiguardian:apiguardian-api:1.1.0:apiguardian-api-1.1.0.jar:a9aae9ff8ae3e17a2a18f79175e82b16267c246fbbd3ca9dfbbb290b08dcfdd4', @@ -57,7 +59,7 @@ dependencyVerification { 'org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10:kotlin-compiler-embeddable-1.7.10.jar:470ba8941794f818a34b0a8f387ee27e44268e95a108322d18d9749ae345e22b', 'org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10:kotlin-daemon-embeddable-1.7.10.jar:77c5f3ab1ed653a899e96835937a9daf3a46e496fdfa6915ff6d20b2953619a4', 'org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10:kotlin-klib-commonizer-embeddable-1.7.10.jar:1c2550f1e7ec4d1590aacddd7852b90a4cf05de6e66cee31ad747c8dc0834e33', - 'org.jetbrains.kotlin:kotlin-reflect:1.4.20:kotlin-reflect-1.4.20.jar:3b7c82def79fb96c4579d40a47e37dec872f9f8209ee0da3ce828c39dba612e1', + 'org.jetbrains.kotlin:kotlin-reflect:1.6.0:kotlin-reflect-1.6.0.jar:c6161884209221db7f5ddb031bb480a3c46bb90d5b65d7cc0167b149aaa9c494', 'org.jetbrains.kotlin:kotlin-reflect:1.7.10:kotlin-reflect-1.7.10.jar:187c5e5a588a6ed18c3a41b54df138a5944121bdb396be1c3fa4abee67397955', 'org.jetbrains.kotlin:kotlin-script-runtime:1.7.10:kotlin-script-runtime-1.7.10.jar:84bfc2aa4eec6768113930cdaef8b5b9f59ac4138fbca3b11300fff4d076950c', 'org.jetbrains.kotlin:kotlin-scripting-common:1.7.10:kotlin-scripting-common-1.7.10.jar:c3a346f38a3d6e242f2316c5a7a4a6b526f2cc42b44ebd40654a0f885cbc4940', @@ -69,13 +71,12 @@ dependencyVerification { 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10:kotlin-stdlib-jdk8-1.7.10.jar:8aafdd60c94f454c92e5066d266a5ed53ecc63c78f623b3fd9db56fea4032873', 'org.jetbrains.kotlin:kotlin-stdlib:1.7.10:kotlin-stdlib-1.7.10.jar:e771fe74250a943e8f6346713201ff1d8cb95c3a5d1a91a22b65a9e04f6a8901', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', - 'org.json:json:20150729:json-20150729.jar:38c21b9c3d6d24919cd15d027d20afab0a019ac9205f7ed9083b32bdd42a2353', 'org.junit.jupiter:junit-jupiter-api:5.5.2:junit-jupiter-api-5.5.2.jar:249a2fdbd3931987c0298d00ca08ed248496e0fc11e0463c08c4f82e0cc79b1c', 'org.junit.jupiter:junit-jupiter-engine:5.5.2:junit-jupiter-engine-5.5.2.jar:6d777da9876e2ef7a0336e8f098f8d74a5a64f810aa3a4a2f5f3b766ce97837b', 'org.junit.jupiter:junit-jupiter-params:5.5.2:junit-jupiter-params-5.5.2.jar:fd49c7fd9d0f7f1e5b5f6982254cee79177fa2e76a37fdee0466e64f975567b5', 'org.junit.platform:junit-platform-commons:1.5.2:junit-platform-commons-1.5.2.jar:fc44afdfc0f20c85e71a66e7943281aef3bc1e0fd62d2d69a36cb6901e682c10', 'org.junit.platform:junit-platform-engine:1.5.2:junit-platform-engine-1.5.2.jar:ff20ba4ad8c00ef17baef9c55512f9c02d9a68740f7f1ac01a9a6aa0239931f8', - 'org.objenesis:objenesis:3.1:objenesis-3.1.jar:cdb3d038c188de6f46ffd5cd930be2d5e5dba59c53b26437995d534e3db2fb80', + 'org.objenesis:objenesis:3.2:objenesis-3.2.jar:03d960bd5aef03c653eb000413ada15eb77cdd2b8e4448886edf5692805e35f3', 'org.opentest4j:opentest4j:1.2.0:opentest4j-1.2.0.jar:58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2', 'org.skyscreamer:jsonassert:1.5.0:jsonassert-1.5.0.jar:a310bc79c3f4744e2b2e993702fcebaf3696fec0063643ffdc6b49a8fb03ef39', 'org.slf4j:slf4j-api:1.7.30:slf4j-api-1.7.30.jar:cdba07964d1bb40a0761485c6b1e8c2f8fd9eb1d19c53928ac0d7f9510105c57',