🚧 Provide preferences based on JDBC preferences
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 6 Apr 2025 09:47:04 +0000 (11:47 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 6 Apr 2025 16:20:08 +0000 (18:20 +0200)
src/main/java/net/pterodactylus/sone/main/SonePlugin.java
src/main/kotlin/net/pterodactylus/sone/main/SoneModule.kt
src/test/kotlin/net/pterodactylus/sone/main/SoneModuleTest.kt

index d0b07e6..a0c8489 100644 (file)
@@ -239,8 +239,9 @@ public class SonePlugin implements FredPlugin, FredPluginFCP, FredPluginL10n, Fr
                AbstractModule soneModule = new SoneModule(this, new EventBus());
                Module webInterfaceModule = new WebInterfaceModule();
                Module notificationHandlerModule = new NotificationHandlerModule();
+               Module databaseModule = new DatabaseModule();
 
-               return createInjector(freenetModule, soneModule, webInterfaceModule, notificationHandlerModule);
+               return createInjector(freenetModule, soneModule, webInterfaceModule, notificationHandlerModule, databaseModule);
        }
 
        @VisibleForTesting
index 5087479..72bff60 100644 (file)
@@ -23,6 +23,13 @@ import java.util.concurrent.Executors.*
 import java.util.logging.Logger
 import jakarta.inject.*
 import jakarta.inject.Singleton
+import javax.sql.DataSource
+import net.pterodactylus.sone.core.Preferences
+import net.pterodactylus.sone.core.validated
+import net.pterodactylus.sone.core.withDefaults
+import net.pterodactylus.sone.core.withEvents
+import net.pterodactylus.sone.database.h2.JdbcPreferences
+import org.jooq.SQLDialect
 
 open class SoneModule(private val sonePlugin: SonePlugin, private val eventBus: EventBus) : AbstractModule() {
 
@@ -82,6 +89,14 @@ open class SoneModule(private val sonePlugin: SonePlugin, private val eventBus:
        fun getNotificationTicker(): ScheduledExecutorService =
                        newSingleThreadScheduledExecutor()
 
+       @Provides
+       @Singleton
+       fun getPreferences(jdbcPreferences: JdbcPreferences, eventBus: EventBus): Preferences =
+               jdbcPreferences
+                       .withDefaults()
+                       .withEvents(eventBus)
+                       .validated()
+
        private val logger: Logger = Logger.getLogger(javaClass.name)
 
 }
index 01d1285..0a7f0c7 100644 (file)
@@ -1,31 +1,54 @@
 package net.pterodactylus.sone.main
 
-import com.codahale.metrics.*
-import com.google.common.base.*
-import com.google.common.eventbus.*
-import com.google.inject.Guice.*
+import com.codahale.metrics.MetricRegistry
+import com.google.common.base.Optional
+import com.google.common.eventbus.EventBus
+import com.google.common.eventbus.Subscribe
+import com.google.inject.Guice.createInjector
 import com.google.inject.Injector
-import com.google.inject.name.Names.*
+import com.google.inject.name.Names.named
 import freenet.clients.http.SessionManager
-import freenet.l10n.*
-import net.pterodactylus.sone.core.*
-import net.pterodactylus.sone.database.*
-import net.pterodactylus.sone.database.memory.*
-import net.pterodactylus.sone.freenet.*
-import net.pterodactylus.sone.freenet.plugin.*
-import net.pterodactylus.sone.freenet.wot.*
-import net.pterodactylus.sone.test.*
+import freenet.l10n.PluginL10n
+import java.io.File
+import java.util.concurrent.ScheduledExecutorService
+import java.util.concurrent.atomic.AtomicBoolean
+import java.util.concurrent.atomic.AtomicReference
+import kotlin.test.AfterTest
+import kotlin.test.Test
+import net.pterodactylus.sone.core.Core
+import net.pterodactylus.sone.core.FreenetInterface
+import net.pterodactylus.sone.core.Preferences
+import net.pterodactylus.sone.core.SoneUriCreator
+import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent
+import net.pterodactylus.sone.database.Database
+import net.pterodactylus.sone.database.h2.JdbcPreferences
+import net.pterodactylus.sone.database.memory.MemoryDatabase
+import net.pterodactylus.sone.fcp.event.FcpInterfaceDeactivatedEvent
+import net.pterodactylus.sone.freenet.Translation
+import net.pterodactylus.sone.freenet.plugin.PluginConnector
+import net.pterodactylus.sone.freenet.plugin.PluginRespiratorFacade
+import net.pterodactylus.sone.freenet.wot.Context
+import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector
+import net.pterodactylus.sone.test.NotParallel
+import net.pterodactylus.sone.test.assertThrows
+import net.pterodactylus.sone.test.deepMock
+import net.pterodactylus.sone.test.getInstance
+import net.pterodactylus.sone.test.isProvidedByDeepMock
+import net.pterodactylus.sone.test.isProvidedByMock
+import net.pterodactylus.sone.test.mock
+import net.pterodactylus.sone.test.verifySingletonInstance
+import net.pterodactylus.sone.test.whenever
 import net.pterodactylus.sone.web.SessionProvider
-import net.pterodactylus.util.config.*
+import net.pterodactylus.util.config.Configuration
 import net.pterodactylus.util.version.Version
-import org.hamcrest.MatcherAssert.*
-import org.hamcrest.Matchers.*
-import org.junit.experimental.categories.*
-import org.mockito.Mockito.*
-import java.io.*
-import java.util.concurrent.*
-import java.util.concurrent.atomic.*
-import kotlin.test.*
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.equalTo
+import org.hamcrest.Matchers.instanceOf
+import org.hamcrest.Matchers.notNullValue
+import org.hamcrest.Matchers.nullValue
+import org.hamcrest.Matchers.sameInstance
+import org.junit.experimental.categories.Category
+import org.mockito.Mockito.verify
 
 const val versionString = "v80"
 
@@ -143,6 +166,54 @@ class SoneModuleTest {
        }
 
        @Test
+       fun `preferences are bound correctly`() {
+               injector.getInstance<Preferences>()
+       }
+
+       @Test
+       fun `preferences are bound as singleton`() {
+               injector.verifySingletonInstance<Preferences>()
+       }
+
+       @Test
+       fun `preferences are using default values`() {
+               val jdbcPreferences: JdbcPreferences = injector.getInstance<JdbcPreferences>()
+               whenever(jdbcPreferences.postsPerPage).thenReturn(null)
+               assertThat(injector.getInstance<Preferences>().postsPerPage, notNullValue())
+       }
+
+       @Test
+       fun `preferences are validated`() {
+               assertThrows<IllegalArgumentException> { injector.getInstance<Preferences>().postsPerPage = -1 }
+       }
+
+       @Test
+       fun `preferences are connected to event bus`() {
+               val called = AtomicBoolean(false)
+               injector.getInstance<EventBus>().register(object {
+                       @Subscribe
+                       fun onFcpInterfaceDeactivated(event: FcpInterfaceDeactivatedEvent) {
+                               called.set(true)
+                       }
+               })
+               injector.getInstance<Preferences>().fcpInterfaceActive = false
+               assertThat(called.get(), equalTo(true))
+       }
+
+       @Test
+       fun `preferences do not send an event if an invalid value was set`() {
+               val called = AtomicBoolean(false)
+               injector.getInstance<EventBus>().register(object {
+                       @Subscribe
+                       fun onInsertionDelayChanged(event: InsertionDelayChangedEvent) {
+                               called.set(true)
+                       }
+               })
+               assertThrows<IllegalArgumentException> { injector.getInstance<Preferences>().insertionDelay = -1 }
+               assertThat(called.get(), equalTo(false))
+       }
+
+       @Test
        fun `database is bound correctly`() {
                assertThat(injector.getInstance<Database>(), instanceOf(MemoryDatabase::class.java))
        }
@@ -171,6 +242,7 @@ class SoneModuleTest {
 
        class TestObject {
                val ref: AtomicReference<Any?> = AtomicReference()
+
                @Subscribe
                fun testEvent(event: Any?) {
                        ref.set(event)
@@ -200,13 +272,14 @@ class SoneModuleTest {
        }
 
        private fun createInjector(eventBus: EventBus = EventBus()): Injector =
-                       createInjector(
-                                       SoneModule(sonePlugin, eventBus),
-                                       FreenetInterface::class.isProvidedByDeepMock(),
-                                       PluginRespiratorFacade::class.isProvidedByDeepMock(),
-                                       PluginConnector::class.isProvidedByDeepMock(),
-                                       SessionManager::class.isProvidedByMock()
-                       )
+               createInjector(
+                       SoneModule(sonePlugin, eventBus),
+                       JdbcPreferences::class.isProvidedByMock(),
+                       FreenetInterface::class.isProvidedByDeepMock(),
+                       PluginRespiratorFacade::class.isProvidedByDeepMock(),
+                       PluginConnector::class.isProvidedByDeepMock(),
+                       SessionManager::class.isProvidedByMock()
+               )
 
        @Test
        fun `metrics registry is created as singleton`() {