Add tests for saving Sone following times
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 6 Feb 2018 17:20:56 +0000 (18:20 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Wed, 7 Feb 2018 05:46:46 +0000 (06:46 +0100)
src/main/java/net/pterodactylus/sone/database/memory/ConfigurationLoader.java
src/test/kotlin/net/pterodactylus/sone/database/memory/ConfigurationLoaderTest.kt

index 0f55575..bb82ee2 100644 (file)
@@ -3,10 +3,16 @@ package net.pterodactylus.sone.database.memory;
 import static java.util.logging.Level.WARNING;
 
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.logging.Logger;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import net.pterodactylus.util.config.Configuration;
 import net.pterodactylus.util.config.ConfigurationException;
 
@@ -44,6 +50,50 @@ public class ConfigurationLoader {
                return loadIds("Bookmarks/Post");
        }
 
+       @Nullable
+       public synchronized Long getSoneFollowingTime(@Nonnull String soneId) {
+               return loadSoneFollowingTimes().get(soneId);
+       }
+
+       public synchronized void removeSoneFollowingTime(@Nonnull String soneId) {
+               Map<String, Long> soneFollowingTimes = loadSoneFollowingTimes();
+               soneFollowingTimes.remove(soneId);
+               storeSoneFollowingTimes(soneFollowingTimes);
+       }
+
+       public synchronized void setSoneFollowingTime(@Nonnull String soneId, long time) {
+               Map<String, Long> soneFollowingTimes = loadSoneFollowingTimes();
+               soneFollowingTimes.put(soneId, time);
+               storeSoneFollowingTimes(soneFollowingTimes);
+       }
+
+       private synchronized Map<String, Long> loadSoneFollowingTimes() {
+               Map<String, Long> soneFollowingTimes = new HashMap<>();
+               int soneCounter = 0;
+               while (true) {
+                       String soneId = configuration.getStringValue("SoneFollowingTimes/" + soneCounter + "/Sone").getValue(null);
+                       if (soneId == null) {
+                               break;
+                       }
+                       soneFollowingTimes.put(soneId, configuration.getLongValue("SoneFollowingTimes/" + soneCounter++ + "/Time").getValue(Long.MAX_VALUE));
+               }
+               return soneFollowingTimes;
+       }
+
+       private synchronized void storeSoneFollowingTimes(Map<String, Long> soneFollowingTimes) {
+               int soneCounter = 0;
+               try {
+                       for (Entry<String, Long> soneFollowingTime : soneFollowingTimes.entrySet()) {
+                               configuration.getStringValue("SoneFollowingTimes/" + soneCounter + "/Sone").setValue(soneFollowingTime.getKey());
+                               configuration.getLongValue("SoneFollowingTimes/" + soneCounter + "/Time").setValue(soneFollowingTime.getValue());
+                               ++soneCounter;
+                       }
+                       configuration.getStringValue("SoneFollowingTimes/" + soneCounter + "/Sone").setValue(null);
+               } catch (ConfigurationException ce1) {
+                       logger.log(WARNING, "Could not save Sone following times!", ce1);
+               }
+       }
+
        private Set<String> loadIds(String prefix) {
                Set<String> ids = new HashSet<String>();
                int idCounter = 0;
index f0a1d10..b2da512 100644 (file)
@@ -7,6 +7,7 @@ import net.pterodactylus.util.config.Configuration
 import net.pterodactylus.util.config.Value
 import org.hamcrest.MatcherAssert.assertThat
 import org.hamcrest.Matchers.containsInAnyOrder
+import org.hamcrest.Matchers.equalTo
 import org.hamcrest.Matchers.nullValue
 import org.junit.Test
 
@@ -25,6 +26,11 @@ class ConfigurationLoaderTest {
                                whenever(configuration.getStringValue(attribute)).thenReturn(this)
                        }
 
+       private fun setupLongValue(attribute: String, value: Long? = null): Value<Long?> =
+                       from(value).apply {
+                               whenever(configuration.getLongValue(attribute)).thenReturn(this)
+                       }
+
        @Test
        fun `loader can load known posts`() {
                setupStringValue("KnownPosts/0/ID", "Post2")
@@ -64,4 +70,43 @@ class ConfigurationLoaderTest {
                assertThat(post3.value, nullValue())
        }
 
+       @Test
+       fun `loader can load Sone following times`() {
+               setupStringValue("SoneFollowingTimes/0/Sone", "Sone1")
+               setupLongValue("SoneFollowingTimes/0/Time", 1000L)
+               setupStringValue("SoneFollowingTimes/1/Sone", "Sone2")
+               setupLongValue("SoneFollowingTimes/1/Time", 2000L)
+               setupStringValue("SoneFollowingTimes/2/Sone")
+               assertThat(configurationLoader.getSoneFollowingTime("Sone1"), equalTo(1000L))
+               assertThat(configurationLoader.getSoneFollowingTime("Sone2"), equalTo(2000L))
+               assertThat(configurationLoader.getSoneFollowingTime("Sone3"), nullValue())
+       }
+
+       @Test
+       fun `loader can overwrite existing Sone following time`() {
+               val sone1Id = setupStringValue("SoneFollowingTimes/0/Sone", "Sone1")
+               val sone1Time = setupLongValue("SoneFollowingTimes/0/Time", 1000L)
+               val sone2Id = setupStringValue("SoneFollowingTimes/1/Sone", "Sone2")
+               val sone2Time = setupLongValue("SoneFollowingTimes/1/Time", 2000L)
+               setupStringValue("SoneFollowingTimes/2/Sone")
+               configurationLoader.setSoneFollowingTime("Sone1", 3000L)
+               assertThat(listOf(sone1Id.value to sone1Time.value, sone2Id.value to sone2Time.value), containsInAnyOrder<Pair<String?, Long?>>(
+                               "Sone1" to 3000L,
+                               "Sone2" to 2000L
+               ))
+       }
+
+       @Test
+       fun `loader can remove Sone following time`() {
+               val sone1Id = setupStringValue("SoneFollowingTimes/0/Sone", "Sone1")
+               val sone1Time = setupLongValue("SoneFollowingTimes/0/Time", 1000L)
+               val sone2Id = setupStringValue("SoneFollowingTimes/1/Sone", "Sone2")
+               val sone2Time = setupLongValue("SoneFollowingTimes/1/Time", 2000L)
+               setupStringValue("SoneFollowingTimes/2/Sone")
+               configurationLoader.removeSoneFollowingTime("Sone1")
+               assertThat(sone1Id.value, equalTo("Sone2"))
+               assertThat(sone1Time.value, equalTo(2000L))
+               assertThat(sone2Id.value, nullValue())
+       }
+
 }