🔀 Merge “refactoring/no-negative-identity-filter”
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 13 Dec 2022 20:49:45 +0000 (21:49 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 13 Dec 2022 20:49:45 +0000 (21:49 +0100)
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.kt
src/main/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilter.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/Trust.kt
src/test/kotlin/net/pterodactylus/sone/freenet/wot/Identities.kt
src/test/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilterTest.kt [new file with mode: 0644]

index 829affc..eac1fa9 100644 (file)
@@ -49,6 +49,7 @@ class IdentityManagerImpl @Inject constructor(
 
        private val currentOwnIdentities = mutableSetOf<OwnIdentity>()
        private val strictFiltering = AtomicBoolean(false)
+       private val noNegativeIdentityFilter = NoNegativeIdentityFilter()
 
        override val isConnected: Boolean
                get() = notThrowing { webOfTrustConnector.ping() }
@@ -87,22 +88,7 @@ class IdentityManagerImpl @Inject constructor(
 
        private fun Map<OwnIdentity, Set<Identity>>.applyStrictFiltering() =
                        if (strictFiltering.get()) {
-                               val identitiesWithTrust = values.flatten()
-                                               .groupBy { it.id }
-                                               .mapValues { (_, identities) ->
-                                                       identities.reduce { accIdentity, identity ->
-                                                               identity.trust.forEach { (ownIdentity: OwnIdentity?, trust: Trust?) ->
-                                                                       accIdentity.setTrust(ownIdentity, trust)
-                                                               }
-                                                               accIdentity
-                                                       }
-                                               }
-
-                               mapValues { (_, trustedIdentities) ->
-                                       trustedIdentities.filter { trustedIdentity ->
-                                               identitiesWithTrust[trustedIdentity.id]!!.trust.all { it.value.hasZeroOrPositiveTrust() }
-                                       }
-                               }
+                               noNegativeIdentityFilter.filter(this)
                        } else {
                                this
                        }
@@ -128,10 +114,3 @@ private fun notThrowing(action: () -> Unit): Boolean =
                } catch (e: Exception) {
                        false
                }
-
-private fun Trust.hasZeroOrPositiveTrust() =
-               if (explicit == null) {
-                       implicit == null || implicit >= 0
-               } else {
-                       explicit >= 0
-               }
diff --git a/src/main/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilter.kt b/src/main/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilter.kt
new file mode 100644 (file)
index 0000000..44468f2
--- /dev/null
@@ -0,0 +1,37 @@
+package net.pterodactylus.sone.freenet.wot
+
+/**
+ * Filter for identities that retains only those remote identities that do
+ * not have a single negative trust value (explicit or implicit) from any own
+ * identity.
+ */
+class NoNegativeIdentityFilter {
+
+       fun filter(identities: Map<OwnIdentity, Set<Identity>>) =
+               identities.run {
+                       val identitiesWithTrust = values.flatten()
+                               .groupBy { it.id }
+                               .mapValues { (_, identities) ->
+                                       identities.reduce { accIdentity, identity ->
+                                               identity.trust.forEach { (ownIdentity: OwnIdentity?, trust: Trust?) ->
+                                                       accIdentity.setTrust(ownIdentity, trust)
+                                               }
+                                               accIdentity
+                                       }
+                               }
+
+                       mapValues { (_, trustedIdentities) ->
+                               trustedIdentities.filter { trustedIdentity ->
+                                       identitiesWithTrust[trustedIdentity.id]!!.trust.all { it.value.hasZeroOrPositiveTrust() }
+                               }
+                       }
+               }
+
+}
+
+private fun Trust.hasZeroOrPositiveTrust() =
+               if (explicit == null) {
+                       implicit == null || implicit >= 0
+               } else {
+                       explicit >= 0
+               }
index 779dd20..f54cfc3 100644 (file)
@@ -21,3 +21,6 @@ package net.pterodactylus.sone.freenet.wot
  * Container class for trust in the web of trust.
  */
 data class Trust(val explicit: Int?, val implicit: Int?, val distance: Int?)
+
+fun trustExplicitely(value: Int) = Trust(explicit = value, implicit = null, distance = 1)
+fun trustImplicitely(value: Int, distance: Int = 2) = Trust(explicit = null, implicit = value, distance)
index d699bb2..0583132 100644 (file)
 
 package net.pterodactylus.sone.freenet.wot
 
-fun createOwnIdentity(id: String, contexts: Set<String>, vararg properties: Pair<String, String>): OwnIdentity {
+fun createOwnIdentity(id: String, contexts: Set<String> = emptySet(), vararg properties: Pair<String, String> = emptyArray()): OwnIdentity {
        val ownIdentity = DefaultOwnIdentity(id, "Nickname$id", "Request$id", "Insert$id")
        setContextsAndPropertiesOnIdentity(ownIdentity, contexts, mapOf(*properties))
        return ownIdentity
 }
 
-fun createIdentity(id: String, contexts: Set<String>, vararg properties: Pair<String, String>): Identity {
+fun createIdentity(id: String, contexts: Set<String> = emptySet(), vararg properties: Pair<String, String> = emptyArray()): Identity {
        val identity = DefaultIdentity(id, "Nickname$id", "Request$id")
        setContextsAndPropertiesOnIdentity(identity, contexts, mapOf(*properties))
        return identity
diff --git a/src/test/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilterTest.kt b/src/test/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilterTest.kt
new file mode 100644 (file)
index 0000000..05c627c
--- /dev/null
@@ -0,0 +1,87 @@
+package net.pterodactylus.sone.freenet.wot
+
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.containsInAnyOrder
+import org.hamcrest.Matchers.empty
+import org.junit.Test
+
+class NoNegativeIdentityFilterTest {
+
+       @Test
+       fun `filter retains all identities with an explicit trust larger than or equal to 0`() {
+               val allIdentities = mapOf(
+                       ownIdentity1.trust(identityA to trustExplicitely(50), identityB to trustExplicitely(0), identityC to trustExplicitely(-50))
+               )
+               val filteredIdentities = filter.filter(allIdentities)
+               assertThat(filteredIdentities[ownIdentity1]!!, containsInAnyOrder(identityA, identityB))
+       }
+
+       @Test
+       fun `filter retains all identities with an implicit trust larger than or equal to 0`() {
+               val allIdentities = mapOf(
+                       ownIdentity1.trust(identityA to trustImplicitely(50), identityB to trustImplicitely(0), identityC to trustImplicitely(-50))
+               )
+               val filteredIdentities = filter.filter(allIdentities)
+               assertThat(filteredIdentities[ownIdentity1]!!, containsInAnyOrder(identityA, identityB))
+       }
+
+       @Test
+       fun `filter retains all identities with an explicit trust larger than or equal to 0 from all local identities that know that remote identity`() {
+               val allIdentities = mapOf(
+                       ownIdentity1.trust(identityA to trustExplicitely(50), identityB to trustExplicitely(0)),
+                       ownIdentity2.trust(identityA to trustExplicitely(50), identityC to trustExplicitely(0))
+               )
+               val filteredIdentities = filter.filter(allIdentities)
+               assertThat(filteredIdentities[ownIdentity1]!!, containsInAnyOrder(identityA, identityB))
+               assertThat(filteredIdentities[ownIdentity2]!!, containsInAnyOrder(identityA, identityC))
+       }
+
+       @Test
+       fun `filter retains all identities with an implicit trust larger than or equal to 0 from all local identities that know that remote identity`() {
+               val allIdentities = mapOf(
+                       ownIdentity1.trust(identityA to trustImplicitely(50), identityB to trustImplicitely(0)),
+                       ownIdentity2.trust(identityA to trustImplicitely(50), identityC to trustImplicitely(0))
+               )
+               val filteredIdentities = filter.filter(allIdentities)
+               assertThat(filteredIdentities[ownIdentity1]!!, containsInAnyOrder(identityA, identityB))
+               assertThat(filteredIdentities[ownIdentity2]!!, containsInAnyOrder(identityA, identityC))
+       }
+
+       @Test
+       fun `strict filter removes all identities that have an explicit negative value for any of the local identities`() {
+               val allIdentities = mapOf(
+                       ownIdentity1.trust(identityA to trustExplicitely(50), identityB to trustExplicitely(50)),
+                       ownIdentity2.trust(identityB to trustExplicitely(-50))
+               )
+               val filteredIdentities = filter.filter(allIdentities)
+               assertThat(filteredIdentities[ownIdentity1]!!, containsInAnyOrder(identityA))
+               assertThat(filteredIdentities[ownIdentity2]!!, empty())
+       }
+
+       @Test
+       fun `strict filter removes all identities that have an implicit negative value for any of the local identities`() {
+               val allIdentities = mapOf(
+                       ownIdentity1.trust(identityA to trustExplicitely(50), identityB to trustExplicitely(50)),
+                       ownIdentity2.trust(identityB to trustImplicitely(-50))
+               )
+               val filteredIdentities = filter.filter(allIdentities)
+               assertThat(filteredIdentities[ownIdentity1]!!, containsInAnyOrder(identityA))
+               assertThat(filteredIdentities[ownIdentity2]!!, empty())
+       }
+
+       private val filter = NoNegativeIdentityFilter()
+       private val ownIdentity1 = createOwnIdentity("1")
+       private val ownIdentity2 = createOwnIdentity("2")
+       private val identityA = createIdentity("A")
+       private val identityB = createIdentity("B")
+       private val identityC = createIdentity("C")
+
+}
+
+private fun OwnIdentity.trust(vararg identityTrust: Pair<Identity, Trust>) =
+       this to identityTrust.map { (identity, trust) -> identity.copy().setTrust(this, trust) }.toSet()
+
+private fun Identity.copy() = DefaultIdentity(id, nickname, requestUri).apply {
+       contexts = this@copy.contexts
+       properties = this@copy.properties
+}