mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-22 13:46:13 +08:00
Redesign ComponentStorage
initialization for clearer tests
This commit is contained in:
parent
f9da72c136
commit
300882ea18
@ -20,6 +20,7 @@ import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||
import net.mamoe.mirai.event.events.BotReloginEvent
|
||||
import net.mamoe.mirai.internal.contact.checkIsGroupImpl
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorageDelegate
|
||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||
import net.mamoe.mirai.internal.network.components.*
|
||||
import net.mamoe.mirai.internal.network.context.SsoProcessorContext
|
||||
@ -109,13 +110,15 @@ internal open class QQAndroidBot constructor(
|
||||
|
||||
|
||||
private val networkLogger: MiraiLogger by lazy { configuration.networkLoggerSupplier(this) }
|
||||
override val components: ComponentStorage by lazy {
|
||||
createDefaultComponents()
|
||||
final override val components: ComponentStorage by lazy {
|
||||
createDefaultComponents().apply {
|
||||
set(StateObserver, stateObserverChain())
|
||||
}
|
||||
}
|
||||
|
||||
fun createDefaultComponents(): ConcurrentComponentStorage {
|
||||
open fun createDefaultComponents(): ConcurrentComponentStorage {
|
||||
return ConcurrentComponentStorage().apply {
|
||||
val components = this // avoid mistakes
|
||||
val components = ComponentStorageDelegate { this@QQAndroidBot.components }
|
||||
|
||||
// There's no need to interrupt a broadcasting event when network handler closed.
|
||||
set(EventDispatcher, EventDispatcherImpl(bot.coroutineContext, logger.subLogger("EventDispatcher")))
|
||||
@ -154,8 +157,6 @@ internal open class QQAndroidBot constructor(
|
||||
OtherClientUpdaterImpl(bot, components, networkLogger.subLogger("OtherClientUpdater"))
|
||||
)
|
||||
set(ConfigPushSyncer, ConfigPushSyncerImpl())
|
||||
|
||||
set(StateObserver, stateObserverChain())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.component
|
||||
|
||||
internal class ComponentStorageDelegate(
|
||||
private val instance: () -> ComponentStorage
|
||||
) : ComponentStorage {
|
||||
override val size: Int get() = instance().size
|
||||
override fun <T : Any> get(key: ComponentKey<T>): T = instance()[key]
|
||||
override fun <T : Any> getOrNull(key: ComponentKey<T>): T? = instance().getOrNull(key)
|
||||
override val keys: Set<ComponentKey<*>> get() = instance().keys
|
||||
override fun toString(): String = instance().toString()
|
||||
}
|
@ -9,10 +9,21 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.component
|
||||
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import net.mamoe.mirai.utils.cast
|
||||
|
||||
internal interface MutableComponentStorage : ComponentStorage {
|
||||
override operator fun <T : Any> get(key: ComponentKey<T>): T
|
||||
operator fun <T : Any> set(key: ComponentKey<T>, value: T)
|
||||
fun <T : Any> remove(key: ComponentKey<T>): T?
|
||||
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
internal fun MutableComponentStorage.setAll(other: ComponentStorage) {
|
||||
for (key in other.keys) {
|
||||
set(key.cast(), other[key])
|
||||
}
|
||||
}
|
||||
|
||||
internal operator fun <T : Any> MutableComponentStorage.set(key: ComponentKey<T>, value: T?) {
|
||||
|
@ -14,6 +14,7 @@ package net.mamoe.mirai.internal
|
||||
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.setAll
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.utils.BotConfiguration
|
||||
import kotlin.contracts.InvocationKind
|
||||
@ -29,7 +30,7 @@ internal class MockBotBuilder(
|
||||
val conf: BotConfiguration = BotConfiguration(),
|
||||
) {
|
||||
var nhProvider: (QQAndroidBot.(bot: QQAndroidBot) -> NetworkHandler)? = null
|
||||
var componentsProvider: (QQAndroidBot.(bot: QQAndroidBot) -> ComponentStorage)? = null
|
||||
var additionalComponentsProvider: (QQAndroidBot.(bot: QQAndroidBot) -> ComponentStorage)? = null
|
||||
|
||||
fun conf(action: BotConfiguration.() -> Unit): MockBotBuilder {
|
||||
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -44,16 +45,20 @@ internal class MockBotBuilder(
|
||||
}
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
internal fun MockBot(conf: MockBotBuilder.() -> Unit = {}) =
|
||||
MockBotBuilder(MockConfiguration.copy()).apply(conf).run {
|
||||
internal fun MockBot(conf: MockBotBuilder.() -> Unit = {}): QQAndroidBot {
|
||||
return MockBotBuilder(MockConfiguration.copy()).apply(conf).run {
|
||||
object : QQAndroidBot(MockAccount, this.conf) {
|
||||
override val components: ComponentStorage by lazy {
|
||||
componentsProvider?.invoke(this, this) ?: EMPTY_COMPONENT_STORAGE
|
||||
override fun createDefaultComponents(): ConcurrentComponentStorage {
|
||||
return super.createDefaultComponents().apply {
|
||||
val componentsProvider = additionalComponentsProvider
|
||||
if (componentsProvider != null) {
|
||||
setAll(componentsProvider(bot, bot))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createNetworkHandler(): NetworkHandler =
|
||||
nhProvider?.invoke(this, this) ?: super.createNetworkHandler()
|
||||
}
|
||||
}
|
||||
|
||||
private val EMPTY_COMPONENT_STORAGE = ConcurrentComponentStorage()
|
||||
}
|
@ -35,7 +35,7 @@ internal abstract class AbstractMockNetworkHandlerTest : AbstractTest() {
|
||||
|
||||
protected val bot: QQAndroidBot = MockBot {
|
||||
nhProvider = { createNetworkHandler() }
|
||||
componentsProvider = { this@AbstractMockNetworkHandlerTest.components }
|
||||
additionalComponentsProvider = { this@AbstractMockNetworkHandlerTest.components }
|
||||
}
|
||||
protected val logger = MiraiLogger.create("test")
|
||||
protected val components = ConcurrentComponentStorage().apply {
|
||||
|
@ -11,11 +11,11 @@ package net.mamoe.mirai.internal.network.framework
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.internal.AbstractBot
|
||||
import net.mamoe.mirai.internal.MockBot
|
||||
import net.mamoe.mirai.internal.MockAccount
|
||||
import net.mamoe.mirai.internal.MockConfiguration
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.withFallback
|
||||
import net.mamoe.mirai.internal.network.component.setAll
|
||||
import net.mamoe.mirai.internal.network.components.*
|
||||
import net.mamoe.mirai.internal.network.context.SsoProcessorContext
|
||||
import net.mamoe.mirai.internal.network.context.SsoProcessorContextImpl
|
||||
@ -24,7 +24,6 @@ import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerContextImpl
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory
|
||||
import net.mamoe.mirai.internal.network.handler.state.StateObserver
|
||||
import net.mamoe.mirai.internal.test.AbstractTest
|
||||
import net.mamoe.mirai.internal.utils.subLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
@ -45,9 +44,12 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
|
||||
abstract val network: NetworkHandler
|
||||
|
||||
var bot: QQAndroidBot by lateinitMutableProperty {
|
||||
MockBot {
|
||||
networkHandlerProvider { createHandler() }
|
||||
componentsProvider = { network.context } // initialized in [createHandler]
|
||||
object : QQAndroidBot(MockAccount, MockConfiguration.copy()) {
|
||||
override fun createDefaultComponents(): ConcurrentComponentStorage =
|
||||
super.createDefaultComponents().apply { setAll(overrideComponents) }
|
||||
|
||||
override fun createNetworkHandler(): NetworkHandler =
|
||||
this@AbstractRealNetworkHandlerTest.createHandler()
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +67,7 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
|
||||
/**
|
||||
* This overrides [QQAndroidBot.components]
|
||||
*/
|
||||
open val defaultComponents = ConcurrentComponentStorage().apply {
|
||||
open val overrideComponents = ConcurrentComponentStorage().apply {
|
||||
set(SsoProcessorContext, SsoProcessorContextImpl(bot))
|
||||
set(SsoProcessor, object : TestSsoProcessor(bot) {
|
||||
override suspend fun login(handler: NetworkHandler) {
|
||||
@ -117,38 +119,9 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
|
||||
// set(StateObserver, bot.run { stateObserverChain() })
|
||||
}
|
||||
|
||||
/**
|
||||
* [additionalComponents] overrides [defaultComponents] and [QQAndroidBot.components]
|
||||
*/
|
||||
open fun createHandler(additionalComponents: ComponentStorage? = null): H {
|
||||
return factory.create(
|
||||
createContext(additionalComponents),
|
||||
address
|
||||
)
|
||||
}
|
||||
|
||||
val address = InetSocketAddress.createUnresolved("localhost", 123)
|
||||
|
||||
open fun createContext(additionalComponents: ComponentStorage? = null): NetworkHandlerContextImpl {
|
||||
// StateObserver
|
||||
val components =
|
||||
additionalComponents.withFallback(defaultComponents).withFallback(bot.createDefaultComponents())
|
||||
val observerComponents = if (
|
||||
additionalComponents?.getOrNull(StateObserver)
|
||||
?: defaultComponents.getOrNull(StateObserver)
|
||||
== null
|
||||
) {
|
||||
ConcurrentComponentStorage().apply {
|
||||
set(StateObserver, bot.run { components.stateObserverChain() })
|
||||
}
|
||||
} else null
|
||||
|
||||
return NetworkHandlerContextImpl(
|
||||
bot,
|
||||
networkLogger,
|
||||
observerComponents.withFallback(components)
|
||||
)
|
||||
}
|
||||
open fun createHandler(): H = factory.create(createContext(), address)
|
||||
open fun createContext(): NetworkHandlerContextImpl = NetworkHandlerContextImpl(bot, networkLogger, bot.components)
|
||||
val address: InetSocketAddress = InetSocketAddress.createUnresolved("localhost", 123)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Assertions
|
||||
|
@ -80,7 +80,7 @@ internal class SelectorNetworkHandlerTest : AbstractRealNetworkHandlerTest<Selec
|
||||
return listOf(Job())
|
||||
}
|
||||
}
|
||||
defaultComponents[HeartbeatScheduler] = heartbeatScheduler
|
||||
overrideComponents[HeartbeatScheduler] = heartbeatScheduler
|
||||
|
||||
bot.login()
|
||||
bot.network.context[EventDispatcher].joinBroadcast()
|
||||
|
@ -95,7 +95,7 @@ internal abstract class AbstractNettyNHTest : AbstractRealNetworkHandlerTest<Tes
|
||||
}
|
||||
|
||||
internal fun AbstractNettyNHTest.setSsoProcessor(action: suspend SsoProcessor.(handler: NetworkHandler) -> Unit) {
|
||||
defaultComponents[SsoProcessor] = object : SsoProcessor by defaultComponents[SsoProcessor] {
|
||||
overrideComponents[SsoProcessor] = object : SsoProcessor by overrideComponents[SsoProcessor] {
|
||||
override suspend fun login(handler: NetworkHandler) = action(handler)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user