From: David ‘Bombe’ Roden Date: Tue, 13 Dec 2022 20:49:45 +0000 (+0100) Subject: 🔀 Merge “refactoring/no-negative-identity-filter” X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=23e09dfc13a0cc6dfc7d7b8cc09c78acc6984ec7;hp=e1507b16a50ac9b8b497e7d151b2889c1736ee9c;p=Sone.git 🔀 Merge “refactoring/no-negative-identity-filter” --- diff --git a/src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.kt b/src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.kt index 829affc..eac1fa9 100644 --- a/src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.kt +++ b/src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.kt @@ -49,6 +49,7 @@ class IdentityManagerImpl @Inject constructor( private val currentOwnIdentities = mutableSetOf() 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>.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 index 0000000..44468f2 --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilter.kt @@ -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>) = + 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 + } diff --git a/src/main/kotlin/net/pterodactylus/sone/freenet/wot/Trust.kt b/src/main/kotlin/net/pterodactylus/sone/freenet/wot/Trust.kt index 779dd20..f54cfc3 100644 --- a/src/main/kotlin/net/pterodactylus/sone/freenet/wot/Trust.kt +++ b/src/main/kotlin/net/pterodactylus/sone/freenet/wot/Trust.kt @@ -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) diff --git a/src/test/kotlin/net/pterodactylus/sone/freenet/wot/Identities.kt b/src/test/kotlin/net/pterodactylus/sone/freenet/wot/Identities.kt index d699bb2..0583132 100644 --- a/src/test/kotlin/net/pterodactylus/sone/freenet/wot/Identities.kt +++ b/src/test/kotlin/net/pterodactylus/sone/freenet/wot/Identities.kt @@ -17,13 +17,13 @@ package net.pterodactylus.sone.freenet.wot -fun createOwnIdentity(id: String, contexts: Set, vararg properties: Pair): OwnIdentity { +fun createOwnIdentity(id: String, contexts: Set = emptySet(), vararg properties: Pair = 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, vararg properties: Pair): Identity { +fun createIdentity(id: String, contexts: Set = emptySet(), vararg properties: Pair = 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 index 0000000..05c627c --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/sone/freenet/wot/NoNegativeIdentityFilterTest.kt @@ -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) = + 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 +}