1 package net.pterodactylus.sone.main
3 import com.google.common.eventbus.*
4 import com.google.inject.*
5 import freenet.client.async.*
6 import freenet.l10n.BaseL10n.LANGUAGE.*
8 import freenet.pluginmanager.*
9 import net.pterodactylus.sone.core.*
10 import net.pterodactylus.sone.core.event.*
11 import net.pterodactylus.sone.fcp.*
12 import net.pterodactylus.sone.freenet.wot.*
13 import net.pterodactylus.sone.test.*
14 import net.pterodactylus.sone.web.*
15 import net.pterodactylus.sone.web.notification.*
16 import org.hamcrest.MatcherAssert.*
17 import org.hamcrest.Matchers.*
18 import org.junit.experimental.categories.*
19 import org.mockito.Mockito.*
21 import java.util.concurrent.atomic.*
25 * Unit test for [SonePlugin].
28 @Category(NotParallel::class)
29 class SonePluginTest {
31 private var sonePlugin = SonePlugin { injector }
32 private val pluginRespirator = deepMock<PluginRespirator>()
33 private val node = deepMock<Node>()
34 private val clientCore = deepMock<NodeClientCore>()
35 private val uskManager = deepMock<USKManager>()
38 setField(node, "clientCore", clientCore)
39 whenever(pluginRespirator.node).thenReturn(node)
40 setField(clientCore, "uskManager", uskManager)
41 setField(clientCore, "clientContext", mock<ClientContext>())
45 fun `sone plugin can be started`() {
46 sonePlugin.setLanguage(ENGLISH)
47 sonePlugin.runPlugin(pluginRespirator)
51 fun `core can be created`() {
52 val injector: Injector = runSonePluginWithRealInjector()
53 assertThat(injector.getInstance<Core>(), notNullValue())
57 fun `fcp interface can be created`() {
58 val injector: Injector = runSonePluginWithRealInjector()
59 assertThat(injector.getInstance<FcpInterface>(), notNullValue())
63 fun `web interface can be created`() {
64 val injector: Injector = runSonePluginWithRealInjector()
65 assertThat(injector.getInstance<WebInterface>(), notNullValue())
69 fun `web of trust connector can be created`() {
70 val injector: Injector = runSonePluginWithRealInjector()
71 assertThat(injector.getInstance<WebOfTrustConnector>(), notNullValue())
75 fun `notification handler can be created`() {
76 val injector: Injector = runSonePluginWithRealInjector()
77 assertThat(injector.getInstance<NotificationHandler>(), notNullValue())
80 private fun runSonePluginWithRealInjector(injectorConsumer: (Injector) -> Unit = {}): Injector {
81 lateinit var injector: Injector
82 sonePlugin = SonePlugin {
83 Guice.createInjector(*it).also {
88 sonePlugin.setLanguage(ENGLISH)
89 sonePlugin.runPlugin(pluginRespirator)
94 fun `core is being started`() {
95 sonePlugin.runPlugin(pluginRespirator)
96 val core = injector.getInstance<Core>()
101 fun `notification handler is being requested`() {
102 sonePlugin.runPlugin(pluginRespirator)
103 assertThat(getInjected(NotificationHandler::class.java), notNullValue())
107 fun `ticker shutdown is being requested`() {
108 sonePlugin.runPlugin(pluginRespirator)
109 assertThat(getInjected(TickerShutdown::class.java), notNullValue())
112 private class FirstStartListener(private val firstStartReceived: AtomicBoolean) {
114 fun firstStart(@Suppress("UNUSED_PARAMETER") firstStart: FirstStart) {
115 firstStartReceived.set(true)
120 fun `first-start event is sent to event bus when first start is true`() {
121 File("sone.properties").delete()
122 val firstStartReceived = AtomicBoolean()
123 runSonePluginWithRealInjector {
124 val eventBus = it.getInstance(EventBus::class.java)
125 eventBus.register(FirstStartListener(firstStartReceived))
127 assertThat(firstStartReceived.get(), equalTo(true))
131 fun `first-start event is not sent to event bus when first start is false`() {
132 File("sone.properties").deleteAfter {
134 val firstStartReceived = AtomicBoolean()
135 runSonePluginWithRealInjector {
136 val eventBus = it.getInstance(EventBus::class.java)
137 eventBus.register(FirstStartListener(firstStartReceived))
139 assertThat(firstStartReceived.get(), equalTo(false))
143 private class ConfigNotReadListener(private val configNotReadReceiver: AtomicBoolean) {
145 fun configNotRead(@Suppress("UNUSED_PARAMETER") configNotRead: ConfigNotRead) {
146 configNotReadReceiver.set(true)
151 fun `config-not-read event is sent to event bus when config file is invalid`() {
152 File("sone.properties").deleteAfter {
154 val configNotReadReceived = AtomicBoolean()
155 runSonePluginWithRealInjector {
156 val eventBus = it.getInstance(EventBus::class.java)
157 eventBus.register(ConfigNotReadListener(configNotReadReceived))
159 assertThat(configNotReadReceived.get(), equalTo(true))
164 fun `config-not-read event is not sent to event bus when config file does not exist`() {
165 File("sone.properties").delete()
166 val configNotReadReceived = AtomicBoolean()
167 runSonePluginWithRealInjector {
168 val eventBus = it.getInstance(EventBus::class.java)
169 eventBus.register(ConfigNotReadListener(configNotReadReceived))
171 assertThat(configNotReadReceived.get(), equalTo(false))
175 fun `config-not-read event is not sent to event bus when config file is valid`() {
176 File("sone.properties").deleteAfter {
177 writeText("# comment")
178 val configNotReadReceived = AtomicBoolean()
179 runSonePluginWithRealInjector {
180 val eventBus = it.getInstance(EventBus::class.java)
181 eventBus.register(ConfigNotReadListener(configNotReadReceived))
183 assertThat(configNotReadReceived.get(), equalTo(false))
187 private class StartupListener(private val startupReceived: () -> Unit) {
189 fun startup(@Suppress("UNUSED_PARAMETER") startup: Startup) {
195 fun `startup event is sent to event bus`() {
196 val startupReceived = AtomicBoolean()
197 runSonePluginWithRealInjector {
198 val eventBus = it.getInstance(EventBus::class.java)
199 eventBus.register(StartupListener { startupReceived.set(true) })
201 assertThat(startupReceived.get(), equalTo(true))
204 private class ShutdownListener(private val shutdownReceived: () -> Unit) {
206 fun shutdown(@Suppress("UNUSED_PARAMETER") shutdown: Shutdown) {
212 fun `shutdown event is sent to event bus on terminate`() {
213 val shutdownReceived = AtomicBoolean()
214 runSonePluginWithRealInjector {
215 val eventBus = it.getInstance(EventBus::class.java)
216 eventBus.register(ShutdownListener { shutdownReceived.set(true) })
218 sonePlugin.terminate()
219 assertThat(shutdownReceived.get(), equalTo(true))
222 private fun <T> getInjected(clazz: Class<T>, annotation: Annotation? = null): T? =
223 injected[TypeLiteral.get(clazz) to annotation] as? T
225 private val injected =
226 mutableMapOf<Pair<TypeLiteral<*>, Annotation?>, Any>()
228 private val injector = mock<Injector>().apply {
229 fun mockValue(clazz: Class<*>) = false.takeIf { clazz.name == java.lang.Boolean::class.java.name } ?: mock(clazz)
230 whenever(getInstance(any<Key<*>>())).then {
231 injected.getOrPut((it.getArgument(0) as Key<*>).let { it.typeLiteral to it.annotation }) {
232 it.getArgument<Key<*>>(0).typeLiteral.type.typeName.toClass().let(::mockValue)
235 whenever(getInstance(any<Class<*>>())).then {
236 injected.getOrPut(TypeLiteral.get(it.getArgument(0) as Class<*>) to null) {
237 it.getArgument<Class<*>>(0).let(::mockValue)
244 private fun String.toClass(): Class<*> = SonePlugin::class.java.classLoader.loadClass(this)
246 private fun File.deleteAfter(action: File.() -> Unit) = try {