diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/ConnectedClientTest.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/ConnectedClientTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..868bda7c0d6a098738dc52c9916fa722b7c7614a --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/ConnectedClientTest.kt @@ -0,0 +1,76 @@ +/* + * libquassel + * Copyright (c) 2024 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https: //mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.client + +import de.justjanne.bitflags.of +import de.justjanne.libquassel.connection.ChannelConnection +import de.justjanne.libquassel.connection.ClientHandshakeHandler +import de.justjanne.libquassel.connection.ClientSessionHandler +import de.justjanne.libquassel.connection.MagicHandler +import de.justjanne.libquassel.di.DaggerConnectedClientComponent +import de.justjanne.libquassel.protocol.connection.ClientHeader +import de.justjanne.libquassel.protocol.connection.ProtocolFeature +import de.justjanne.libquassel.protocol.connection.ProtocolMeta +import de.justjanne.libquassel.protocol.connection.ProtocolVersion +import de.justjanne.libquassel.protocol.features.FeatureSet +import de.justjanne.libquassel.protocol.io.CoroutineChannel +import de.justjanne.libquassel.protocol.models.HandshakeMessage +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout +import org.junit.jupiter.api.Test +import java.net.InetSocketAddress +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +class ConnectedClientTest { + @Test + fun testConnection() = runBlocking { + val channel = CoroutineChannel() + withTimeout(500.milliseconds) { + channel.connect(InetSocketAddress("decentralised.chat", 4242), keepAlive = true) + } + val connection = ChannelConnection(channel) + val connectionSetup = withTimeout(500.milliseconds) { + MagicHandler( + ClientHeader( + features = ProtocolFeature.of(ProtocolFeature.Compression, ProtocolFeature.TLS), + versions = listOf(ProtocolMeta(ProtocolVersion.Datastream, 0u)) + ), + ).handle(connection) + }.getOrThrow() + val handshake = withTimeout(500.milliseconds) { + ClientHandshakeHandler( + HandshakeMessage.ClientInit(clientVersion = "", buildDate = "", featureSet = FeatureSet.none()), + HandshakeMessage.ClientLogin(Const.user, Const.pass), + ).handle(connection) + }.getOrThrow() + val di = DaggerConnectedClientComponent.builder() + .connection(connection) + .featureSet(handshake.clientInitAck.featureSet) + .build() + val sessionHandler = ClientSessionHandler(handshake, di.sync(), di.rpc(), di.db().buffer()) + launch { + sessionHandler.handle(connection) + } + withTimeout(20.seconds) { + sessionHandler.toInit.first { it != null && it.isEmpty() } + } + val bufferInfo = handshake.sessionInit.bufferInfos.first { it.bufferName == "#quassel-test" } + di.api().rpc.sendInput(bufferInfo, "/PRINT Test from libquassel?") + delay(1.seconds) + channel.close() + println(di.db().alias().getAll()) + println(di.db().buffer().getAll()) + println(di.db().message().getAll()) + } +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/DatabaseTest.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/DatabaseTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..b3e97035764dcba661776c5e9b92bd34a5d7add8 --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/DatabaseTest.kt @@ -0,0 +1,56 @@ +/* + * libquassel + * Copyright (c) 2024 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https: //mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.client + +import androidx.room.Room +import androidx.sqlite.driver.bundled.BundledSQLiteDriver +import de.justjanne.libquassel.persistence.AliasEntity +import de.justjanne.libquassel.persistence.AppDatabase +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Test +import kotlin.time.Duration.Companion.milliseconds + +class DatabaseTest { + @Test + fun testDb() = runBlocking { + val db = Room.inMemoryDatabaseBuilder<AppDatabase>() + .setDriver(BundledSQLiteDriver()) + .setQueryCoroutineContext(Dispatchers.IO) + .build() + + val aliasRepo = db.alias() + val job = CoroutineScope(Dispatchers.Default).launch { + aliasRepo.collectAll().collectLatest { + println("alias list changed: $it") + } + } + delay(10.milliseconds) + aliasRepo.insert( + AliasEntity(0, "foo", "bar"), + ) + delay(10.milliseconds) + aliasRepo.insert( + AliasEntity(1, "bar", "baz"), + ) + delay(10.milliseconds) + aliasRepo.insert( + AliasEntity(0, "foo", "foo"), + AliasEntity(2, "baz", "foo"), + ) + delay(10.milliseconds) + job.cancelAndJoin() + } +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/OfflineClientTest.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/OfflineClientTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..755ffb12f4ecf1fff3fd44a63e8dd3ef2a19049b --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/OfflineClientTest.kt @@ -0,0 +1,56 @@ +/* + * libquassel + * Copyright (c) 2024 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https: //mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.client + +import de.justjanne.libquassel.di.DaggerOfflineClientComponent +import de.justjanne.libquassel.protocol.api.ObjectName +import de.justjanne.libquassel.protocol.exceptions.RpcInvocationFailedException +import de.justjanne.libquassel.protocol.models.ids.BufferId +import de.justjanne.libquassel.protocol.models.ids.MsgId +import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.variant.QVariant_ +import de.justjanne.libquassel.protocol.variant.qVariant +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Test +import kotlin.test.assertFails +import kotlin.test.assertFailsWith + +class OfflineClientTest { + @Test + fun test() = runBlocking { + val client = DaggerOfflineClientComponent.builder().build() + client.sync().invoke( + "AliasManager", + ObjectName(""), + "update", + listOf(qVariant(emptyMap<String, QVariant_>(), QtType.QVariantMap)) + ) + assertFailsWith<RpcInvocationFailedException.UnknownMethodException> { + client.sync().invoke( + "AliasManager", + ObjectName(""), + "unknown", + listOf(qVariant(emptyMap<String, QVariant_>(), QtType.QVariantMap)) + ) + } + assertFails { + client.sync().invoke("AliasManager", ObjectName(""), "update", emptyList()) + } + client.api().aliasManager.requestUpdate(emptyMap()) + client.api().aliasManager.addAlias("name", "expansion") + client.api().backlogManager.requestBacklog(BufferId(-1)) + client.api().bufferSyncer.requestSetLastSeenMsg(BufferId(1), MsgId(1337)) + client.api().bufferViewConfig.requestSetBufferViewName(ObjectName("1"), "test") + client.api().bufferViewManager.requestDeleteBufferView(1) + client.api().certManager.requestUpdate(ObjectName(""), emptyMap()) + client.api().highlightRuleManager.requestRemoveHighlightRule(5) + client.api().identity.requestUpdate(ObjectName(""), emptyMap()) + } +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/QuasselApiTest.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/QuasselApiTest.kt deleted file mode 100644 index f8650bb512d99947fc25c62d67c9bff07c086e97..0000000000000000000000000000000000000000 --- a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/QuasselApiTest.kt +++ /dev/null @@ -1,342 +0,0 @@ -/* - * libquassel - * Copyright (c) 2024 Janne Mareike Koschinski - * - * This Source Code Form is subject to the terms of the Mozilla Public License, - * v. 2.0. If a copy of the MPL was not distributed with this file, You can - * obtain one at https: //mozilla.org/MPL/2.0/. - */ - -package de.justjanne.libquassel.client - -import androidx.room.Room -import androidx.sqlite.driver.bundled.BundledSQLiteDriver -import dagger.Binds -import dagger.BindsInstance -import dagger.Component -import dagger.Module -import dagger.Provides -import de.justjanne.bitflags.of -import de.justjanne.libquassel.backend.AliasManagerPersister -import de.justjanne.libquassel.backend.BacklogManagerPersister -import de.justjanne.libquassel.backend.BufferSyncerPersister -import de.justjanne.libquassel.backend.BufferViewConfigPersister -import de.justjanne.libquassel.backend.BufferViewManagerPersister -import de.justjanne.libquassel.backend.CertManagerPersister -import de.justjanne.libquassel.backend.CoreInfoPersister -import de.justjanne.libquassel.backend.HighlightRuleManagerPersister -import de.justjanne.libquassel.backend.IdentityPersister -import de.justjanne.libquassel.backend.IgnoreListManagerPersister -import de.justjanne.libquassel.backend.IrcChannelPersister -import de.justjanne.libquassel.backend.IrcListHelperPersister -import de.justjanne.libquassel.backend.IrcUserPersister -import de.justjanne.libquassel.backend.NetworkConfigPersister -import de.justjanne.libquassel.backend.NetworkPersister -import de.justjanne.libquassel.backend.RpcPersister -import de.justjanne.libquassel.connection.ChannelConnection -import de.justjanne.libquassel.connection.ClientHandshakeHandler -import de.justjanne.libquassel.connection.ClientSessionHandler -import de.justjanne.libquassel.connection.Connection -import de.justjanne.libquassel.connection.MagicHandler -import de.justjanne.libquassel.persistence.AliasEntity -import de.justjanne.libquassel.persistence.AppDatabase -import de.justjanne.libquassel.protocol.api.ObjectName -import de.justjanne.libquassel.protocol.api.client.AliasManagerClientApi -import de.justjanne.libquassel.protocol.api.client.BacklogManagerClientApi -import de.justjanne.libquassel.protocol.api.client.BufferSyncerClientApi -import de.justjanne.libquassel.protocol.api.client.BufferViewConfigClientApi -import de.justjanne.libquassel.protocol.api.client.BufferViewManagerClientApi -import de.justjanne.libquassel.protocol.api.client.CertManagerClientApi -import de.justjanne.libquassel.protocol.api.client.CoreInfoClientApi -import de.justjanne.libquassel.protocol.api.client.HighlightRuleManagerClientApi -import de.justjanne.libquassel.protocol.api.client.IdentityClientApi -import de.justjanne.libquassel.protocol.api.client.IgnoreListManagerClientApi -import de.justjanne.libquassel.protocol.api.client.IrcChannelClientApi -import de.justjanne.libquassel.protocol.api.client.IrcListHelperClientApi -import de.justjanne.libquassel.protocol.api.client.IrcUserClientApi -import de.justjanne.libquassel.protocol.api.client.NetworkClientApi -import de.justjanne.libquassel.protocol.api.client.NetworkConfigClientApi -import de.justjanne.libquassel.protocol.api.client.RpcClientApi -import de.justjanne.libquassel.protocol.api.dispatcher.ClientDispatcherModule -import de.justjanne.libquassel.protocol.api.dispatcher.RpcDispatcher -import de.justjanne.libquassel.protocol.api.dispatcher.SyncHandler -import de.justjanne.libquassel.protocol.api.proxy.ClientProxyModule -import de.justjanne.libquassel.protocol.api.proxy.Proxy -import de.justjanne.libquassel.protocol.api.server.AliasManagerServerApi -import de.justjanne.libquassel.protocol.api.server.BacklogManagerServerApi -import de.justjanne.libquassel.protocol.api.server.BufferSyncerServerApi -import de.justjanne.libquassel.protocol.api.server.BufferViewConfigServerApi -import de.justjanne.libquassel.protocol.api.server.BufferViewManagerServerApi -import de.justjanne.libquassel.protocol.api.server.CertManagerServerApi -import de.justjanne.libquassel.protocol.api.server.HighlightRuleManagerServerApi -import de.justjanne.libquassel.protocol.api.server.IdentityServerApi -import de.justjanne.libquassel.protocol.api.server.IgnoreListManagerServerApi -import de.justjanne.libquassel.protocol.api.server.IrcListHelperServerApi -import de.justjanne.libquassel.protocol.api.server.NetworkConfigServerApi -import de.justjanne.libquassel.protocol.api.server.NetworkServerApi -import de.justjanne.libquassel.protocol.api.server.RpcServerApi -import de.justjanne.libquassel.protocol.connection.ClientHeader -import de.justjanne.libquassel.protocol.connection.ProtocolFeature -import de.justjanne.libquassel.protocol.connection.ProtocolMeta -import de.justjanne.libquassel.protocol.connection.ProtocolVersion -import de.justjanne.libquassel.protocol.exceptions.RpcInvocationFailedException -import de.justjanne.libquassel.protocol.features.FeatureSet -import de.justjanne.libquassel.protocol.io.CoroutineChannel -import de.justjanne.libquassel.protocol.models.HandshakeMessage -import de.justjanne.libquassel.protocol.models.SignalProxyMessage -import de.justjanne.libquassel.protocol.models.ids.BufferId -import de.justjanne.libquassel.protocol.models.ids.MsgId -import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.serializers.SignalProxyMessageSerializer -import de.justjanne.libquassel.protocol.variant.QVariantList -import de.justjanne.libquassel.protocol.variant.QVariant_ -import de.justjanne.libquassel.protocol.variant.qVariant -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout -import org.junit.jupiter.api.Test -import java.net.InetSocketAddress -import javax.inject.Inject -import javax.inject.Singleton -import kotlin.test.assertFails -import kotlin.test.assertFailsWith -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.seconds - -@Singleton -class ProxyImpl @Inject constructor( - private val connection: Connection, - private val featureSet: FeatureSet, -) : Proxy { - override suspend fun sync(className: String, objectName: ObjectName, function: String, params: QVariantList) { - val message = SignalProxyMessage.Sync(className, objectName.objectName, function, params) - println("Send: $message") - connection.send(true) { - SignalProxyMessageSerializer.serialize(it, message, featureSet) - } - println("Sent: $message") - } - - override suspend fun rpc(function: String, params: QVariantList) { - val message = SignalProxyMessage.Rpc(function, params) - println("Send: $message") - connection.send(true) { - SignalProxyMessageSerializer.serialize(it, message, featureSet) - } - println("Sent: $message") - } -} - -@Singleton -class OfflineProxyImpl @Inject constructor() : Proxy { - override suspend fun sync(className: String, objectName: ObjectName, function: String, params: QVariantList) { - val message = SignalProxyMessage.Sync(className, objectName.objectName, function, params) - println("Send: $message") - } - - override suspend fun rpc(function: String, params: QVariantList) { - val message = SignalProxyMessage.Rpc(function, params) - println("Send: $message") - } -} - -@Module -interface ClientModule { - @Binds fun bindAliasManagerPersister(impl: AliasManagerPersister): AliasManagerClientApi - @Binds fun bindBacklogManagerPersister(impl: BacklogManagerPersister): BacklogManagerClientApi - @Binds fun bindBufferSyncerPersister(impl: BufferSyncerPersister): BufferSyncerClientApi - @Binds fun bindBufferViewConfigPersister(impl: BufferViewConfigPersister): BufferViewConfigClientApi - @Binds fun bindBufferViewManagerPersister(impl: BufferViewManagerPersister): BufferViewManagerClientApi - @Binds fun bindCertManagerPersister(impl: CertManagerPersister): CertManagerClientApi - @Binds fun bindCoreInfoPersister(impl: CoreInfoPersister): CoreInfoClientApi - @Binds fun bindHighlightRuleManagerPersister(impl: HighlightRuleManagerPersister): HighlightRuleManagerClientApi - @Binds fun bindIdentityPersister(impl: IdentityPersister): IdentityClientApi - @Binds fun bindIgnoreListManagerPersister(impl: IgnoreListManagerPersister): IgnoreListManagerClientApi - @Binds fun bindIrcChannelPersister(impl: IrcChannelPersister): IrcChannelClientApi - @Binds fun bindIrcListHelperPersister(impl: IrcListHelperPersister): IrcListHelperClientApi - @Binds fun bindIrcUserPersister(impl: IrcUserPersister): IrcUserClientApi - @Binds fun bindNetworkConfigPersister(impl: NetworkConfigPersister): NetworkConfigClientApi - @Binds fun bindNetworkPersister(impl: NetworkPersister): NetworkClientApi - @Binds fun bindRpcPersister(impl: RpcPersister): RpcClientApi -} - -@Module -interface OnlineClientModule { - @Binds fun bindProxy(impl: ProxyImpl): Proxy -} - -@Module -interface OfflineClientModule { - @Binds fun bindProxy(impl: OfflineProxyImpl): Proxy -} - -@Module -class DatabaseModule { - @Singleton - @Provides - fun database(): AppDatabase = - Room.inMemoryDatabaseBuilder<AppDatabase>() - .setDriver(BundledSQLiteDriver()) - .setQueryCoroutineContext(Dispatchers.IO) - .build() - - @Provides - fun provideAliasRepository(database: AppDatabase) = database.alias() - @Provides - fun provideBufferRepository(database: AppDatabase) = database.buffer() - @Provides - fun provideMessageRepository(database: AppDatabase) = database.message() -} - -@Singleton -class QuasselApiClient @Inject constructor( - val aliasManager: AliasManagerServerApi, - val backlogManager: BacklogManagerServerApi, - val bufferSyncer: BufferSyncerServerApi, - val bufferViewConfig: BufferViewConfigServerApi, - val bufferViewManager: BufferViewManagerServerApi, - val certManager: CertManagerServerApi, - val highlightRuleManager: HighlightRuleManagerServerApi, - val identity: IdentityServerApi, - val ignoreListManager: IgnoreListManagerServerApi, - val ircListHelper: IrcListHelperServerApi, - val network: NetworkServerApi, - val networkConfig: NetworkConfigServerApi, - val rpc: RpcServerApi, -) - -@Singleton -@Component(modules = [ClientModule::class, OnlineClientModule::class, DatabaseModule::class, ClientDispatcherModule::class, ClientProxyModule::class]) -interface ClientComponent { - fun db(): AppDatabase - fun sync(): SyncHandler - fun rpc(): RpcDispatcher - fun api(): QuasselApiClient - - @Component.Builder - interface Builder { - fun build(): ClientComponent - @BindsInstance fun connection(connection: Connection): Builder - @BindsInstance fun featureSet(featureSet: FeatureSet): Builder - } -} - -@Singleton -@Component(modules = [ClientModule::class, OfflineClientModule::class, DatabaseModule::class, ClientDispatcherModule::class, ClientProxyModule::class]) -interface OfflineClientComponent { - fun db(): AppDatabase - fun sync(): SyncHandler - fun rpc(): RpcDispatcher - fun api(): QuasselApiClient -} - -class QuasselApiTest { - @Test - fun test() = runBlocking { - val client = DaggerOfflineClientComponent.builder().build() - client.sync().invoke( - "AliasManager", - ObjectName(""), - "update", - listOf(qVariant(emptyMap<String, QVariant_>(), QtType.QVariantMap)) - ) - assertFailsWith<RpcInvocationFailedException.UnknownMethodException> { - client.sync().invoke( - "AliasManager", - ObjectName(""), - "unknown", - listOf(qVariant(emptyMap<String, QVariant_>(), QtType.QVariantMap)) - ) - } - assertFails { - client.sync().invoke("AliasManager", ObjectName(""), "update", emptyList()) - } - client.api().aliasManager.requestUpdate(emptyMap()) - client.api().aliasManager.addAlias("name", "expansion") - client.api().backlogManager.requestBacklog(BufferId(-1)) - client.api().bufferSyncer.requestSetLastSeenMsg(BufferId(1), MsgId(1337)) - client.api().bufferViewConfig.requestSetBufferViewName(ObjectName("1"), "test") - client.api().bufferViewManager.requestDeleteBufferView(1) - client.api().certManager.requestUpdate(ObjectName(""), emptyMap()) - client.api().highlightRuleManager.requestRemoveHighlightRule(5) - client.api().identity.requestUpdate(ObjectName(""), emptyMap()) - } - - @Test - fun testDb() = runBlocking { - val db = Room.inMemoryDatabaseBuilder<AppDatabase>() - .setDriver(BundledSQLiteDriver()) - .setQueryCoroutineContext(Dispatchers.IO) - .build() - - val aliasRepo = db.alias() - val job = CoroutineScope(Dispatchers.Default).launch { - aliasRepo.collectAll().collectLatest { - println("alias list changed: $it") - } - } - delay(10.milliseconds) - aliasRepo.insert( - AliasEntity(0, "foo", "bar"), - ) - delay(10.milliseconds) - aliasRepo.insert( - AliasEntity(1, "bar", "baz"), - ) - delay(10.milliseconds) - aliasRepo.insert( - AliasEntity(0, "foo", "foo"), - AliasEntity(2, "baz", "foo"), - ) - delay(10.milliseconds) - job.cancelAndJoin() - } - - @Test - fun testConnection() = runBlocking { - val channel = CoroutineChannel() - withTimeout(500.milliseconds) { - channel.connect(InetSocketAddress("decentralised.chat", 4242), keepAlive = true) - } - val connection = ChannelConnection(channel) - val connectionSetup = withTimeout(500.milliseconds) { - MagicHandler( - ClientHeader( - features = ProtocolFeature.of(ProtocolFeature.Compression, ProtocolFeature.TLS), - versions = listOf(ProtocolMeta(ProtocolVersion.Datastream, 0u)) - ), - ).handle(connection) - }.getOrThrow() - val handshake = withTimeout(500.milliseconds) { - ClientHandshakeHandler( - HandshakeMessage.ClientInit(clientVersion = "", buildDate = "", featureSet = FeatureSet.none()), - HandshakeMessage.ClientLogin(Const.user, Const.pass), - ).handle(connection) - }.getOrThrow() - val di = DaggerClientComponent.builder() - .connection(connection) - .featureSet(handshake.clientInitAck.featureSet) - .build() - val sessionHandler = ClientSessionHandler(handshake, di.sync(), di.rpc(), di.db().buffer()) - launch { - sessionHandler.handle(connection) - } - withTimeout(20.seconds) { - sessionHandler.toInit.first { it != null && it.isEmpty() } - } - val bufferInfo = handshake.sessionInit.bufferInfos.first { it.bufferName == "#quassel-test" } - di.api().rpc.sendInput(bufferInfo, "/PRINT Test from libquassel?") - delay(1.seconds) - channel.close() - println(di.db().alias().getAll()) - println(di.db().buffer().getAll()) - println(di.db().message().getAll()) - Unit - } -} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ClientModule.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ClientModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..6b5f8e599ca483f66625f763aebb90843a6edff4 --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ClientModule.kt @@ -0,0 +1,81 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import dagger.Binds +import dagger.Module +import de.justjanne.libquassel.backend.AliasManagerPersister +import de.justjanne.libquassel.backend.BacklogManagerPersister +import de.justjanne.libquassel.backend.BufferSyncerPersister +import de.justjanne.libquassel.backend.BufferViewConfigPersister +import de.justjanne.libquassel.backend.BufferViewManagerPersister +import de.justjanne.libquassel.backend.CertManagerPersister +import de.justjanne.libquassel.backend.CoreInfoPersister +import de.justjanne.libquassel.backend.HighlightRuleManagerPersister +import de.justjanne.libquassel.backend.IdentityPersister +import de.justjanne.libquassel.backend.IgnoreListManagerPersister +import de.justjanne.libquassel.backend.IrcChannelPersister +import de.justjanne.libquassel.backend.IrcListHelperPersister +import de.justjanne.libquassel.backend.IrcUserPersister +import de.justjanne.libquassel.backend.NetworkConfigPersister +import de.justjanne.libquassel.backend.NetworkPersister +import de.justjanne.libquassel.backend.RpcPersister +import de.justjanne.libquassel.protocol.api.client.AliasManagerClientApi +import de.justjanne.libquassel.protocol.api.client.BacklogManagerClientApi +import de.justjanne.libquassel.protocol.api.client.BufferSyncerClientApi +import de.justjanne.libquassel.protocol.api.client.BufferViewConfigClientApi +import de.justjanne.libquassel.protocol.api.client.BufferViewManagerClientApi +import de.justjanne.libquassel.protocol.api.client.CertManagerClientApi +import de.justjanne.libquassel.protocol.api.client.CoreInfoClientApi +import de.justjanne.libquassel.protocol.api.client.HighlightRuleManagerClientApi +import de.justjanne.libquassel.protocol.api.client.IdentityClientApi +import de.justjanne.libquassel.protocol.api.client.IgnoreListManagerClientApi +import de.justjanne.libquassel.protocol.api.client.IrcChannelClientApi +import de.justjanne.libquassel.protocol.api.client.IrcListHelperClientApi +import de.justjanne.libquassel.protocol.api.client.IrcUserClientApi +import de.justjanne.libquassel.protocol.api.client.NetworkClientApi +import de.justjanne.libquassel.protocol.api.client.NetworkConfigClientApi +import de.justjanne.libquassel.protocol.api.client.RpcClientApi + +@Module +interface ClientModule { + @Binds + fun bindAliasManagerPersister(impl: AliasManagerPersister): AliasManagerClientApi + @Binds + fun bindBacklogManagerPersister(impl: BacklogManagerPersister): BacklogManagerClientApi + @Binds + fun bindBufferSyncerPersister(impl: BufferSyncerPersister): BufferSyncerClientApi + @Binds + fun bindBufferViewConfigPersister(impl: BufferViewConfigPersister): BufferViewConfigClientApi + @Binds + fun bindBufferViewManagerPersister(impl: BufferViewManagerPersister): BufferViewManagerClientApi + @Binds + fun bindCertManagerPersister(impl: CertManagerPersister): CertManagerClientApi + @Binds + fun bindCoreInfoPersister(impl: CoreInfoPersister): CoreInfoClientApi + @Binds + fun bindHighlightRuleManagerPersister(impl: HighlightRuleManagerPersister): HighlightRuleManagerClientApi + @Binds + fun bindIdentityPersister(impl: IdentityPersister): IdentityClientApi + @Binds + fun bindIgnoreListManagerPersister(impl: IgnoreListManagerPersister): IgnoreListManagerClientApi + @Binds + fun bindIrcChannelPersister(impl: IrcChannelPersister): IrcChannelClientApi + @Binds + fun bindIrcListHelperPersister(impl: IrcListHelperPersister): IrcListHelperClientApi + @Binds + fun bindIrcUserPersister(impl: IrcUserPersister): IrcUserClientApi + @Binds + fun bindNetworkConfigPersister(impl: NetworkConfigPersister): NetworkConfigClientApi + @Binds + fun bindNetworkPersister(impl: NetworkPersister): NetworkClientApi + @Binds + fun bindRpcPersister(impl: RpcPersister): RpcClientApi +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedClientComponent.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedClientComponent.kt new file mode 100644 index 0000000000000000000000000000000000000000..17dd48f71ef898e079338e5632fa3c74a920161c --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedClientComponent.kt @@ -0,0 +1,39 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import dagger.BindsInstance +import dagger.Component +import de.justjanne.libquassel.connection.Connection +import de.justjanne.libquassel.persistence.AppDatabase +import de.justjanne.libquassel.protocol.api.dispatcher.ClientDispatcherModule +import de.justjanne.libquassel.protocol.api.dispatcher.RpcDispatcher +import de.justjanne.libquassel.protocol.api.dispatcher.SyncHandler +import de.justjanne.libquassel.protocol.api.proxy.ClientProxyModule +import de.justjanne.libquassel.protocol.features.FeatureSet +import javax.inject.Singleton + +@Singleton +@Component(modules = [ClientModule::class, ConnectedClientModule::class, DatabaseModule::class, ClientDispatcherModule::class, ClientProxyModule::class]) +interface ConnectedClientComponent { + fun db(): AppDatabase + fun sync(): SyncHandler + fun rpc(): RpcDispatcher + fun api(): QuasselApiClient + + @Component.Builder + interface Builder { + fun build(): ConnectedClientComponent + @BindsInstance + fun connection(connection: Connection): Builder + @BindsInstance + fun featureSet(featureSet: FeatureSet): Builder + } +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedClientModule.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedClientModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..506ecf046ffd3e7af7c6c4e00488c47a9d55e064 --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedClientModule.kt @@ -0,0 +1,20 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import dagger.Binds +import dagger.Module +import de.justjanne.libquassel.protocol.api.proxy.Proxy + +@Module +interface ConnectedClientModule { + @Binds + fun bindProxy(impl: ConnectedProxyImpl): Proxy +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedProxyImpl.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedProxyImpl.kt new file mode 100644 index 0000000000000000000000000000000000000000..7205ee95e153139dd05ae874ce6741e2f02ab37f --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/ConnectedProxyImpl.kt @@ -0,0 +1,44 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import de.justjanne.libquassel.connection.Connection +import de.justjanne.libquassel.protocol.api.ObjectName +import de.justjanne.libquassel.protocol.api.proxy.Proxy +import de.justjanne.libquassel.protocol.features.FeatureSet +import de.justjanne.libquassel.protocol.models.SignalProxyMessage +import de.justjanne.libquassel.protocol.serializers.SignalProxyMessageSerializer +import de.justjanne.libquassel.protocol.variant.QVariantList +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ConnectedProxyImpl @Inject constructor( + private val connection: Connection, + private val featureSet: FeatureSet, +) : Proxy { + override suspend fun sync(className: String, objectName: ObjectName, function: String, params: QVariantList) { + val message = SignalProxyMessage.Sync(className, objectName.objectName, function, params) + println("Send: $message") + connection.send(true) { + SignalProxyMessageSerializer.serialize(it, message, featureSet) + } + println("Sent: $message") + } + + override suspend fun rpc(function: String, params: QVariantList) { + val message = SignalProxyMessage.Rpc(function, params) + println("Send: $message") + connection.send(true) { + SignalProxyMessageSerializer.serialize(it, message, featureSet) + } + println("Sent: $message") + } +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/DatabaseModule.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/DatabaseModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..acc77c487e1df387cdb10e7cee5e3c400b18de2c --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/DatabaseModule.kt @@ -0,0 +1,36 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import androidx.room.Room +import androidx.sqlite.driver.bundled.BundledSQLiteDriver +import dagger.Module +import dagger.Provides +import de.justjanne.libquassel.persistence.AppDatabase +import kotlinx.coroutines.Dispatchers +import javax.inject.Singleton + +@Module +class DatabaseModule { + @Singleton + @Provides + fun database(): AppDatabase = + Room.inMemoryDatabaseBuilder<AppDatabase>() + .setDriver(BundledSQLiteDriver()) + .setQueryCoroutineContext(Dispatchers.IO) + .build() + + @Provides + fun provideAliasRepository(database: AppDatabase) = database.alias() + @Provides + fun provideBufferRepository(database: AppDatabase) = database.buffer() + @Provides + fun provideMessageRepository(database: AppDatabase) = database.message() +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineClientComponent.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineClientComponent.kt new file mode 100644 index 0000000000000000000000000000000000000000..7f97123b3ac3aa0b68ad42ec474ce6616304d967 --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineClientComponent.kt @@ -0,0 +1,27 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import dagger.Component +import de.justjanne.libquassel.persistence.AppDatabase +import de.justjanne.libquassel.protocol.api.dispatcher.ClientDispatcherModule +import de.justjanne.libquassel.protocol.api.dispatcher.RpcDispatcher +import de.justjanne.libquassel.protocol.api.dispatcher.SyncHandler +import de.justjanne.libquassel.protocol.api.proxy.ClientProxyModule +import javax.inject.Singleton + +@Singleton +@Component(modules = [ClientModule::class, OfflineClientModule::class, DatabaseModule::class, ClientDispatcherModule::class, ClientProxyModule::class]) +interface OfflineClientComponent { + fun db(): AppDatabase + fun sync(): SyncHandler + fun rpc(): RpcDispatcher + fun api(): QuasselApiClient +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineClientModule.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineClientModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..425a1f1d2b3c36c5171d7ab4620a6fc275d8a20e --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineClientModule.kt @@ -0,0 +1,20 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import dagger.Binds +import dagger.Module +import de.justjanne.libquassel.protocol.api.proxy.Proxy + +@Module +interface OfflineClientModule { + @Binds + fun bindProxy(impl: OfflineProxyImpl): Proxy +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineProxyImpl.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineProxyImpl.kt new file mode 100644 index 0000000000000000000000000000000000000000..5f8f9916db6551e66a5a1ad256b3b24efdebabb0 --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/OfflineProxyImpl.kt @@ -0,0 +1,30 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import de.justjanne.libquassel.protocol.api.ObjectName +import de.justjanne.libquassel.protocol.api.proxy.Proxy +import de.justjanne.libquassel.protocol.models.SignalProxyMessage +import de.justjanne.libquassel.protocol.variant.QVariantList +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class OfflineProxyImpl @Inject constructor() : Proxy { + override suspend fun sync(className: String, objectName: ObjectName, function: String, params: QVariantList) { + val message = SignalProxyMessage.Sync(className, objectName.objectName, function, params) + println("Send: $message") + } + + override suspend fun rpc(function: String, params: QVariantList) { + val message = SignalProxyMessage.Rpc(function, params) + println("Send: $message") + } +} diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/QuasselApiClient.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/QuasselApiClient.kt new file mode 100644 index 0000000000000000000000000000000000000000..493b6d2c76e3ab17e380c805e9af841061a55e13 --- /dev/null +++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/di/QuasselApiClient.kt @@ -0,0 +1,43 @@ +/* + * libquassel + * Copyright (c) 2025 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.di + +import de.justjanne.libquassel.protocol.api.server.AliasManagerServerApi +import de.justjanne.libquassel.protocol.api.server.BacklogManagerServerApi +import de.justjanne.libquassel.protocol.api.server.BufferSyncerServerApi +import de.justjanne.libquassel.protocol.api.server.BufferViewConfigServerApi +import de.justjanne.libquassel.protocol.api.server.BufferViewManagerServerApi +import de.justjanne.libquassel.protocol.api.server.CertManagerServerApi +import de.justjanne.libquassel.protocol.api.server.HighlightRuleManagerServerApi +import de.justjanne.libquassel.protocol.api.server.IdentityServerApi +import de.justjanne.libquassel.protocol.api.server.IgnoreListManagerServerApi +import de.justjanne.libquassel.protocol.api.server.IrcListHelperServerApi +import de.justjanne.libquassel.protocol.api.server.NetworkConfigServerApi +import de.justjanne.libquassel.protocol.api.server.NetworkServerApi +import de.justjanne.libquassel.protocol.api.server.RpcServerApi +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class QuasselApiClient @Inject constructor( + val aliasManager: AliasManagerServerApi, + val backlogManager: BacklogManagerServerApi, + val bufferSyncer: BufferSyncerServerApi, + val bufferViewConfig: BufferViewConfigServerApi, + val bufferViewManager: BufferViewManagerServerApi, + val certManager: CertManagerServerApi, + val highlightRuleManager: HighlightRuleManagerServerApi, + val identity: IdentityServerApi, + val ignoreListManager: IgnoreListManagerServerApi, + val ircListHelper: IrcListHelperServerApi, + val network: NetworkServerApi, + val networkConfig: NetworkConfigServerApi, + val rpc: RpcServerApi, +)