🚧 Add event for first start of Sone
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Wed, 11 Dec 2019 15:44:24 +0000 (16:44 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Wed, 11 Dec 2019 15:59:27 +0000 (16:59 +0100)
src/main/java/net/pterodactylus/sone/main/SonePlugin.java
src/main/kotlin/net/pterodactylus/sone/core/event/FirstStart.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/main/SonePluginTest.kt

index b79df7c..4fd40f5 100644 (file)
@@ -23,6 +23,7 @@ import java.util.logging.Logger;
 import java.util.logging.*;
 
 import net.pterodactylus.sone.core.*;
+import net.pterodactylus.sone.core.event.*;
 import net.pterodactylus.sone.fcp.*;
 import net.pterodactylus.sone.freenet.wot.*;
 import net.pterodactylus.sone.web.*;
@@ -209,6 +210,11 @@ public class SonePlugin implements FredPlugin, FredPluginFCP, FredPluginL10n, Fr
                webInterface.start();
                webInterface.setFirstStart(injector.getInstance(Key.get(Boolean.class, Names.named("FirstStart"))));
                webInterface.setNewConfig(injector.getInstance(Key.get(Boolean.class, Names.named("NewConfig"))));
+
+               /* first start? */
+               if (injector.getInstance(Key.get(Boolean.class, Names.named("FirstStart")))) {
+                       injector.getInstance(EventBus.class).post(new FirstStart());
+               }
        }
 
        @VisibleForTesting
diff --git a/src/main/kotlin/net/pterodactylus/sone/core/event/FirstStart.kt b/src/main/kotlin/net/pterodactylus/sone/core/event/FirstStart.kt
new file mode 100644 (file)
index 0000000..4ff81f3
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * Sone - FirstStart.kt - Copyright Â© 2019 David â€˜Bombe’ Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.core.event
+
+/**
+ * Event that signals that Sone was started for the first time. This event
+ * will only be triggered once, on startup.
+ */
+class FirstStart
index 23c679b..677823c 100644 (file)
@@ -1,11 +1,13 @@
 package net.pterodactylus.sone.main
 
+import com.google.common.eventbus.*
 import com.google.inject.*
 import freenet.client.async.*
 import freenet.l10n.BaseL10n.LANGUAGE.*
 import freenet.node.*
 import freenet.pluginmanager.*
 import net.pterodactylus.sone.core.*
+import net.pterodactylus.sone.core.event.*
 import net.pterodactylus.sone.fcp.*
 import net.pterodactylus.sone.freenet.wot.*
 import net.pterodactylus.sone.test.*
@@ -14,6 +16,8 @@ import net.pterodactylus.sone.web.notification.*
 import org.hamcrest.MatcherAssert.*
 import org.hamcrest.Matchers.*
 import org.mockito.Mockito.*
+import java.io.*
+import java.util.concurrent.atomic.*
 import kotlin.test.*
 
 /**
@@ -70,11 +74,12 @@ class SonePluginTest {
                assertThat(injector.getInstance<NotificationHandler>(), notNullValue())
        }
 
-       private fun runSonePluginWithRealInjector(): Injector {
+       private fun runSonePluginWithRealInjector(injectorConsumer: (Injector) -> Unit = {}): Injector {
                lateinit var injector: Injector
                val sonePlugin = SonePlugin {
                        Guice.createInjector(*it).also {
                                injector = it
+                               injectorConsumer(it)
                        }
                }
                sonePlugin.setLanguage(ENGLISH)
@@ -95,6 +100,42 @@ class SonePluginTest {
                assertThat(getInjected(NotificationHandler::class.java), notNullValue())
        }
 
+       @Test
+       fun `first-start event is sent to event bus when first start is true`() {
+               File("sone.properties").delete()
+               val firstStartReceived = AtomicBoolean()
+               runSonePluginWithRealInjector {
+                       val eventBus = it.getInstance(EventBus::class.java)
+                       eventBus.register(object : Any() {
+                               @Subscribe
+                               fun firstStart(firstStart: FirstStart) {
+                                       firstStartReceived.set(true)
+                               }
+                       })
+               }
+               sonePlugin.runPlugin(pluginRespirator)
+               assertThat(firstStartReceived.get(), equalTo(true))
+       }
+
+       @Test
+       fun `first-start event is not sent to event bus when first start is false`() {
+               File("sone.properties").deleteAfter {
+                       writeText("# empty")
+                       val firstStartReceived = AtomicBoolean()
+                       runSonePluginWithRealInjector {
+                               val eventBus = it.getInstance(EventBus::class.java)
+                               eventBus.register(object : Any() {
+                                       @Subscribe
+                                       fun firstStart(firstStart: FirstStart) {
+                                               firstStartReceived.set(true)
+                                       }
+                               })
+                       }
+                       sonePlugin.runPlugin(pluginRespirator)
+                       assertThat(firstStartReceived.get(), equalTo(false))
+               }
+       }
+
        private fun <T> getInjected(clazz: Class<T>, annotation: Annotation? = null): T? =
                        injected[TypeLiteral.get(clazz) to annotation] as? T
 
@@ -118,3 +159,9 @@ class SonePluginTest {
 }
 
 private fun String.toClass(): Class<*> = SonePlugin::class.java.classLoader.loadClass(this)
+
+private fun File.deleteAfter(action: File.() -> Unit) = try {
+       action(this)
+} finally {
+       this.delete()
+}