diff --git a/mailbox-core/build.gradle b/mailbox-core/build.gradle index 303a1eddbf1bb02f4de758db24b8a9acc22c02b8..fc34695fd31e37055694ca56685ac3531d10e0f6 100644 --- a/mailbox-core/build.gradle +++ b/mailbox-core/build.gradle @@ -24,10 +24,15 @@ dependencies { implementation "io.ktor:ktor-server-netty:$ktorVersion" api "org.slf4j:slf4j-api:1.7.32" + testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version" testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version" testImplementation "org.junit.jupiter:junit-jupiter-engine:$junit_version" testImplementation "io.mockk:mockk:$mockk_version" + testImplementation "ch.qos.logback:logback-classic:1.2.5" + testImplementation "io.ktor:ktor-client-cio:$ktorVersion" + testImplementation "com.google.dagger:hilt-core:$hilt_version" + kaptTest "com.google.dagger:dagger-compiler:$hilt_version" } test { @@ -37,4 +42,14 @@ test { } } +// At the moment for non-Android projects we need to explicitly mark the code generated by kapt +// as 'generated source code' for correct highlighting and resolve in IDE. +idea { + module { + sourceDirs += file('build/generated/source/kapt/main') + testSourceDirs += file('build/generated/source/kapt/test') + generatedSourceDirs += file('build/generated/source/kapt/main') + } +} + apply from: "${rootProject.rootDir}/gradle/ktlint.gradle" diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt index 335367f3a458d93bb0aec78acd685c1db9adb53b..158843242ca549aacf661383ccd146a5ceede6f7 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt @@ -4,9 +4,6 @@ import io.ktor.application.install import io.ktor.features.CallLogging import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import org.briarproject.mailbox.core.lifecycle.Service import org.slf4j.LoggerFactory.getLogger import javax.inject.Inject @@ -16,7 +13,7 @@ import javax.inject.Singleton class WebServerManager @Inject constructor() : Service { internal companion object { - private const val PORT = 8888 + internal const val PORT = 8000 private val LOG = getLogger(WebServerManager::class.java) } @@ -28,12 +25,9 @@ class WebServerManager @Inject constructor() : Service { } override fun startService() { - // hangs if not starting inside a coroutine - GlobalScope.launch(Dispatchers.IO) { - LOG.info("starting") - server.start(wait = true) - LOG.info("started") - } + LOG.info("starting") + server.start() + LOG.info("started") } override fun stopService() { diff --git a/mailbox-core/src/main/resources/logback.xml b/mailbox-core/src/main/resources/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..945c218bb1ab715b006497a8900d0954aeb3a5a4 --- /dev/null +++ b/mailbox-core/src/main/resources/logback.xml @@ -0,0 +1,12 @@ +<configuration> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + <root level="trace"> + <appender-ref ref="STDOUT"/> + </root> + <logger name="org.eclipse.jetty" level="INFO"/> + <logger name="io.netty" level="INFO"/> +</configuration> diff --git a/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestComponent.kt b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestComponent.kt new file mode 100644 index 0000000000000000000000000000000000000000..b41ac5c317e00b69e523b35112fb64ca5ee01b89 --- /dev/null +++ b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestComponent.kt @@ -0,0 +1,16 @@ +package org.briarproject.mailbox.core + +import dagger.Component +import org.briarproject.mailbox.core.lifecycle.LifecycleManager +import javax.inject.Singleton + +@Singleton +@Component( + modules = [ + TestModule::class, + ] +) +interface TestComponent { + fun injectCoreEagerSingletons(): CoreEagerSingletons + fun getLifecycleManager(): LifecycleManager +} diff --git a/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestModule.kt b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..739283752583549163e7f64425f993acf3faa181 --- /dev/null +++ b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestModule.kt @@ -0,0 +1,26 @@ +package org.briarproject.mailbox.core + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import org.briarproject.mailbox.core.db.DatabaseModule +import org.briarproject.mailbox.core.lifecycle.LifecycleModule +import org.briarproject.mailbox.core.server.WebServerModule +import org.briarproject.mailbox.core.system.Clock +import javax.inject.Singleton + +@Module( + includes = [ + LifecycleModule::class, + DatabaseModule::class, + WebServerModule::class, + // no Tor module + ] +) +@InstallIn(SingletonComponent::class) +internal class TestModule { + @Singleton + @Provides + fun provideClock() = Clock { System.currentTimeMillis() } +} diff --git a/mailbox-core/src/test/java/org/briarproject/mailbox/core/server/WebServerIntegrationTest.kt b/mailbox-core/src/test/java/org/briarproject/mailbox/core/server/WebServerIntegrationTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..f6d922246405b4bb3f4daa4d4e73c4eb235746c3 --- /dev/null +++ b/mailbox-core/src/test/java/org/briarproject/mailbox/core/server/WebServerIntegrationTest.kt @@ -0,0 +1,54 @@ +package org.briarproject.mailbox.core.server + +import io.ktor.client.HttpClient +import io.ktor.client.engine.cio.CIO +import io.ktor.client.request.get +import io.ktor.client.statement.HttpResponse +import io.ktor.client.statement.readText +import kotlinx.coroutines.runBlocking +import org.briarproject.mailbox.core.DaggerTestComponent +import org.briarproject.mailbox.core.server.WebServerManager.Companion.PORT +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.TestInstance.Lifecycle +import kotlin.test.assertEquals + +@TestInstance(Lifecycle.PER_CLASS) +class WebServerIntegrationTest { + + private val testComponent = DaggerTestComponent.builder().build() + private val lifecycleManager = testComponent.getLifecycleManager() + private val httpClient = HttpClient(CIO) { + expectSuccess = false // prevents exceptions on non-success responses + } + private val baseUrl = "http://127.0.0.1:$PORT" + + @BeforeAll + fun setUp() { + testComponent.injectCoreEagerSingletons() + lifecycleManager.startServices() + lifecycleManager.waitForStartup() + } + + @AfterAll + fun tearDown() { + lifecycleManager.stopServices() + lifecycleManager.waitForShutdown() + } + + @Test + fun routeRespondsWithHelloWorldString(): Unit = runBlocking { + val response: HttpResponse = httpClient.get("$baseUrl/") + assertEquals(200, response.status.value) + assertEquals("Hello world!", response.readText()) + } + + @Test + fun routeNotFound(): Unit = runBlocking { + val response: HttpResponse = httpClient.get("$baseUrl/404") + assertEquals(404, response.status.value) + } + +}