mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
[headless] Add first integration test for ContactController
This commit is contained in:
@@ -30,6 +30,9 @@ dependencies {
|
||||
testRuntime "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||
testImplementation "io.mockk:mockk:1.8.12"
|
||||
testImplementation "org.skyscreamer:jsonassert:1.5.0"
|
||||
testImplementation 'khttp:khttp:0.1.0'
|
||||
|
||||
kaptTest 'com.google.dagger:dagger-compiler:2.19'
|
||||
}
|
||||
|
||||
jar {
|
||||
@@ -48,6 +51,7 @@ jar {
|
||||
idea {
|
||||
module {
|
||||
sourceDirs += file('build/generated/source/kapt/main')
|
||||
testSourceDirs += file('build/generated/source/kapt/test')
|
||||
generatedSourceDirs += file('build/generated/source/kapt/main')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,22 @@ import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
interface BriarService {
|
||||
fun start()
|
||||
fun stop()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
internal class BriarService
|
||||
internal class BriarServiceImpl
|
||||
@Inject
|
||||
constructor(
|
||||
private val accountManager: AccountManager,
|
||||
private val lifecycleManager: LifecycleManager,
|
||||
private val passwordStrengthEstimator: PasswordStrengthEstimator
|
||||
) {
|
||||
) : BriarService {
|
||||
|
||||
fun start() {
|
||||
override fun start() {
|
||||
if (!accountManager.accountExists()) {
|
||||
createAccount()
|
||||
} else {
|
||||
@@ -38,7 +43,7 @@ constructor(
|
||||
lifecycleManager.startServices(dbKey)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
override fun stop() {
|
||||
lifecycleManager.stopServices()
|
||||
lifecycleManager.waitForShutdown()
|
||||
}
|
||||
|
||||
@@ -56,6 +56,10 @@ import javax.net.SocketFactory
|
||||
)
|
||||
internal class HeadlessModule(private val appDir: File) {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideBriarService(briarService: BriarServiceImpl): BriarService = briarService
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideDatabaseConfig(): DatabaseConfig {
|
||||
@@ -71,30 +75,21 @@ internal class HeadlessModule(private val appDir: File) {
|
||||
locationUtils: LocationUtils, eventBus: EventBus, resourceProvider: ResourceProvider,
|
||||
circumventionProvider: CircumventionProvider, batteryManager: BatteryManager, clock: Clock
|
||||
): PluginConfig {
|
||||
val torDirectory = File(appDir, "tor")
|
||||
val duplex: List<DuplexPluginFactory>
|
||||
if (isLinux() || isMac()) {
|
||||
val duplex: List<DuplexPluginFactory> = if (isLinux() || isMac()) {
|
||||
val torDirectory = File(appDir, "tor")
|
||||
val tor = UnixTorPluginFactory(
|
||||
ioExecutor, networkManager, locationUtils, eventBus, torSocketFactory,
|
||||
backoffFactory, resourceProvider, circumventionProvider, batteryManager, clock,
|
||||
torDirectory
|
||||
)
|
||||
duplex = listOf(tor)
|
||||
listOf(tor)
|
||||
} else {
|
||||
duplex = emptyList()
|
||||
emptyList()
|
||||
}
|
||||
return object : PluginConfig {
|
||||
override fun getDuplexFactories(): Collection<DuplexPluginFactory> {
|
||||
return duplex
|
||||
}
|
||||
|
||||
override fun getSimplexFactories(): Collection<SimplexPluginFactory> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override fun shouldPoll(): Boolean {
|
||||
return true
|
||||
}
|
||||
override fun getDuplexFactories(): Collection<DuplexPluginFactory> = duplex
|
||||
override fun getSimplexFactories(): Collection<SimplexPluginFactory> = emptyList()
|
||||
override fun shouldPoll(): Boolean = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,21 +99,14 @@ internal class HeadlessModule(private val appDir: File) {
|
||||
return object : DevConfig {
|
||||
override fun getDevPublicKey(): PublicKey {
|
||||
try {
|
||||
return crypto.messageKeyParser
|
||||
.parsePublicKey(fromHexString(DEV_PUBLIC_KEY_HEX))
|
||||
return crypto.messageKeyParser.parsePublicKey(fromHexString(DEV_PUBLIC_KEY_HEX))
|
||||
} catch (e: GeneralSecurityException) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getDevOnionAddress(): String {
|
||||
return DEV_ONION_ADDRESS
|
||||
}
|
||||
|
||||
override fun getReportDir(): File {
|
||||
return File(appDir, "reportDir")
|
||||
}
|
||||
override fun getDevOnionAddress(): String = DEV_ONION_ADDRESS
|
||||
override fun getReportDir(): File = File(appDir, "reportDir")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ constructor(
|
||||
private val logger = getLogger(Router::javaClass.name)
|
||||
private val stopped = AtomicBoolean(false)
|
||||
|
||||
fun start(authToken: String, port: Int, debug: Boolean) {
|
||||
internal fun start(authToken: String, port: Int, debug: Boolean) : Javalin {
|
||||
briarService.start()
|
||||
getRuntime().addShutdownHook(Thread(this::stop))
|
||||
|
||||
@@ -104,7 +104,7 @@ constructor(
|
||||
webSocketController.sessions.remove(session)
|
||||
}
|
||||
}
|
||||
app.start()
|
||||
return app.start()
|
||||
}
|
||||
|
||||
private fun serverStopped() {
|
||||
@@ -112,7 +112,7 @@ constructor(
|
||||
exit(1)
|
||||
}
|
||||
|
||||
private fun stop() {
|
||||
internal fun stop() {
|
||||
if (!stopped.getAndSet(true)) {
|
||||
briarService.stop()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.briarproject.briar.headless
|
||||
|
||||
import dagger.Component
|
||||
import org.briarproject.bramble.BrambleCoreEagerSingletons
|
||||
import org.briarproject.bramble.BrambleCoreModule
|
||||
import org.briarproject.bramble.account.AccountModule
|
||||
import org.briarproject.bramble.test.TestSecureRandomModule
|
||||
import org.briarproject.briar.BriarCoreEagerSingletons
|
||||
import org.briarproject.briar.BriarCoreModule
|
||||
import org.briarproject.briar.api.test.TestDataCreator
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Component(
|
||||
modules = [
|
||||
BrambleCoreModule::class,
|
||||
BriarCoreModule::class,
|
||||
TestSecureRandomModule::class,
|
||||
AccountModule::class,
|
||||
HeadlessTestModule::class
|
||||
]
|
||||
)
|
||||
@Singleton
|
||||
internal interface BriarHeadlessTestApp : BrambleCoreEagerSingletons, BriarCoreEagerSingletons {
|
||||
fun getRouter(): Router
|
||||
|
||||
fun getTestDataCreator(): TestDataCreator
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.briarproject.briar.headless
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
const val user = "user"
|
||||
const val pass = "pass"
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
internal class BriarTestServiceImpl
|
||||
@Inject
|
||||
constructor(
|
||||
private val accountManager: AccountManager,
|
||||
private val lifecycleManager: LifecycleManager
|
||||
) : BriarService {
|
||||
|
||||
override fun start() {
|
||||
if (accountManager.accountExists()) {
|
||||
accountManager.deleteAccount()
|
||||
}
|
||||
accountManager.createAccount(user, pass)
|
||||
if (!accountManager.signIn(pass)) {
|
||||
throw java.lang.AssertionError("Password invalid")
|
||||
}
|
||||
val dbKey = accountManager.databaseKey ?: throw AssertionError()
|
||||
lifecycleManager.startServices(dbKey)
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
lifecycleManager.stopServices()
|
||||
lifecycleManager.waitForShutdown()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.briarproject.briar.headless
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import org.briarproject.bramble.api.crypto.PublicKey
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory
|
||||
import org.briarproject.bramble.api.reporting.DevConfig
|
||||
import org.briarproject.bramble.network.JavaNetworkModule
|
||||
import org.briarproject.bramble.plugin.tor.CircumventionModule
|
||||
import org.briarproject.bramble.system.JavaSystemModule
|
||||
import org.briarproject.briar.headless.blogs.HeadlessBlogModule
|
||||
import org.briarproject.briar.headless.contact.HeadlessContactModule
|
||||
import org.briarproject.briar.headless.event.HeadlessEventModule
|
||||
import org.briarproject.briar.headless.forums.HeadlessForumModule
|
||||
import org.briarproject.briar.headless.messaging.HeadlessMessagingModule
|
||||
import java.io.File
|
||||
import java.util.Collections.emptyList
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module(
|
||||
includes = [
|
||||
JavaNetworkModule::class,
|
||||
JavaSystemModule::class,
|
||||
CircumventionModule::class,
|
||||
HeadlessBlogModule::class,
|
||||
HeadlessContactModule::class,
|
||||
HeadlessEventModule::class,
|
||||
HeadlessForumModule::class,
|
||||
HeadlessMessagingModule::class
|
||||
]
|
||||
)
|
||||
internal class HeadlessTestModule(private val appDir: File) {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideBriarService(briarService: BriarTestServiceImpl): BriarService =
|
||||
briarService
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideDatabaseConfig(): DatabaseConfig {
|
||||
val dbDir = File(appDir, "db")
|
||||
val keyDir = File(appDir, "key")
|
||||
return HeadlessDatabaseConfig(dbDir, keyDir)
|
||||
}
|
||||
|
||||
@Provides
|
||||
internal fun providePluginConfig(): PluginConfig {
|
||||
return object : PluginConfig {
|
||||
override fun getDuplexFactories(): Collection<DuplexPluginFactory> = emptyList()
|
||||
override fun getSimplexFactories(): Collection<SimplexPluginFactory> = emptyList()
|
||||
override fun shouldPoll(): Boolean = false
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideDevConfig(): DevConfig = object : DevConfig {
|
||||
override fun getDevPublicKey(): PublicKey = throw NotImplementedError()
|
||||
override fun getDevOnionAddress(): String = throw NotImplementedError()
|
||||
override fun getReportDir(): File = throw NotImplementedError()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideObjectMapper() = ObjectMapper()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.briarproject.briar.headless
|
||||
|
||||
import io.javalin.Javalin
|
||||
import io.javalin.core.util.Header.AUTHORIZATION
|
||||
import khttp.responses.Response
|
||||
import org.briarproject.bramble.BrambleCoreModule
|
||||
import org.briarproject.briar.BriarCoreModule
|
||||
import org.briarproject.briar.api.test.TestDataCreator
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import java.io.File
|
||||
|
||||
const val port = 8000
|
||||
const val url = "http://127.0.0.1:$port/v1"
|
||||
const val token = "authToken"
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
abstract class IntegrationTest {
|
||||
|
||||
private val dataDir = File("tmp")
|
||||
|
||||
protected lateinit var api: Javalin
|
||||
protected lateinit var testDataCreator: TestDataCreator
|
||||
private lateinit var router: Router
|
||||
|
||||
@BeforeAll
|
||||
fun setUp() {
|
||||
val app = DaggerBriarHeadlessTestApp.builder()
|
||||
.headlessTestModule(HeadlessTestModule(dataDir))
|
||||
.build()
|
||||
BrambleCoreModule.initEagerSingletons(app)
|
||||
BriarCoreModule.initEagerSingletons(app)
|
||||
router = app.getRouter()
|
||||
testDataCreator = app.getTestDataCreator()
|
||||
|
||||
api = router.start(token, port, false)
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
fun tearDown() {
|
||||
router.stop()
|
||||
dataDir.deleteRecursively()
|
||||
}
|
||||
|
||||
protected fun get(url: String) : Response {
|
||||
return khttp.get(url, getAuthTokenHeader(token))
|
||||
}
|
||||
|
||||
protected fun getWithWrongToken(url: String) : Response {
|
||||
return khttp.get(url, getAuthTokenHeader("wrongToken"))
|
||||
}
|
||||
|
||||
protected fun delete(url: String) : Response {
|
||||
return khttp.delete(url, getAuthTokenHeader(token))
|
||||
}
|
||||
|
||||
protected fun deleteWithWrongToken(url: String) : Response {
|
||||
return khttp.delete(url, getAuthTokenHeader("wrongToken"))
|
||||
}
|
||||
|
||||
private fun getAuthTokenHeader(token: String) = mapOf(Pair(AUTHORIZATION, "Bearer $token"))
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.briarproject.briar.headless.contact
|
||||
|
||||
import org.briarproject.briar.headless.IntegrationTest
|
||||
import org.briarproject.briar.headless.url
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ContactControllerIntegrationTest: IntegrationTest() {
|
||||
|
||||
@Test
|
||||
fun `list of contacts need authentication token`() {
|
||||
val response = getWithWrongToken("$url/contacts")
|
||||
assertEquals(401, response.statusCode)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns list of contacts`() {
|
||||
// retrieve empty list of contacts
|
||||
var response = get("$url/contacts")
|
||||
assertEquals(200, response.statusCode)
|
||||
assertEquals(0, response.jsonArray.length())
|
||||
|
||||
// add one test contact
|
||||
val testContactName= "testContactName"
|
||||
testDataCreator.addContact(testContactName)
|
||||
|
||||
// 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)
|
||||
val author = contact.getJSONObject("author")
|
||||
assertEquals(testContactName, author.getString("name"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `deleting contact need authentication token`() {
|
||||
val response = deleteWithWrongToken("$url/contacts/1")
|
||||
assertEquals(401, response.statusCode)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `deleting real and non-existing contact`() {
|
||||
var response = delete("$url/contacts/1")
|
||||
assertEquals(200, response.statusCode)
|
||||
|
||||
response = delete("$url/contacts/1")
|
||||
assertEquals(404, response.statusCode)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user