From 65ff597f58cedf10e0a823065e2c2b2ede579ccb Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 14 Jul 2023 21:08:13 +0200 Subject: [PATCH] Depth: change internal representation and API, implement Comparable --- .../org/pgpainless/wot/network/Depth.kt | 61 +++++++++---------- .../pgpainless/wot/network/EdgeComponent.kt | 6 +- .../kotlin/org/pgpainless/wot/query/Path.kt | 2 +- .../org/pgpainless/wot/network/DepthTest.kt | 40 +++++++----- 4 files changed, 57 insertions(+), 52 deletions(-) diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/Depth.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/Depth.kt index 6864c760..f277153d 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/Depth.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/Depth.kt @@ -7,16 +7,16 @@ package org.pgpainless.wot.network /** * Depth of a trust signature. */ -class Depth private constructor(val limit: Int?) : Comparable { +class Depth private constructor(private val limit: Int) : Comparable { + + // Uses a byte for internal representation, like in the OpenPGP "Trust Signature" subpacket companion object { /** * The target is trusted to an unlimited degree. */ @JvmStatic - fun unconstrained() : Depth { - return Depth(null) - } + fun unconstrained() = Depth(255) /** * The target is trusted to a limited degree. @@ -34,40 +34,35 @@ class Depth private constructor(val limit: Int?) : Comparable { */ @JvmStatic fun auto(limit: Int): Depth { - return if (limit == 255) { - unconstrained() - } else { - limited(limit) + require(limit in 0..255) { + "Trust depth MUST be a value between 0 and 255." } + return Depth(limit) } } /** * Return true, if the [Depth] is unconstrained. */ - fun isUnconstrained() : Boolean { - return limit == null - } + fun isUnconstrained() = limit == 255 /** * The value of this Depth, as used in OpenPGP. * * Unlimited is 255. */ - fun value(): Int { - return limit ?: 255 - } + fun value() = limit /** - * Decrease the trust depth by one and return the result. + * Decrease the trust depth by `value` and return the result. * If the [Depth] is unconstrained, the result will still be unconstrained. * @throws IllegalArgumentException if the [Depth] cannot be decreased any further */ - fun decrease(value : Int) : Depth { + fun decrease(value: Int): Depth { return if (isUnconstrained()) { unconstrained() } else { - if (limit!! >= value) { + if (limit >= value) { limited(limit - value) } else { throw IllegalArgumentException("Depth cannot be decreased.") @@ -78,20 +73,20 @@ class Depth private constructor(val limit: Int?) : Comparable { /** * Return the minimum [Depth] of this and the other [Depth]. */ - fun min(other: Depth) : Depth { - return if (compareTo(other) <= 0) { - this - } else { + fun min(other: Depth): Depth { + return if (limit > other.limit) { other + } else { + this } } - override fun compareTo(other: Depth): Int { - return when (Pair(isUnconstrained(), other.isUnconstrained())) { - Pair(true, true) -> 0 - Pair(true, false) -> 1 - Pair(false, true) -> -1 - else -> limit!!.compareTo(other.limit!!) + override fun compareTo(other: Int): Int { + return if (isUnconstrained()) { + // If this is unconstrained, it is bigger than `other` + 1 + } else { + limit.compareTo(other) } } @@ -103,11 +98,13 @@ class Depth private constructor(val limit: Int?) : Comparable { return limit == other.limit } - override fun toString() : String { - return if (isUnconstrained()) { "unconstrained" } else { limit!!.toString() } + override fun toString(): String { + return if (isUnconstrained()) { + "unconstrained" + } else { + limit.toString() + } } - override fun hashCode(): Int { - return limit ?: 0 // TODO: 255? - } + override fun hashCode() = limit } \ No newline at end of file diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/EdgeComponent.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/EdgeComponent.kt index 9727e8da..d439a964 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/EdgeComponent.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/network/EdgeComponent.kt @@ -33,11 +33,11 @@ data class EdgeComponent( ) { override fun toString(): String { - return if (trustDepth.limit == 0) - "${issuer.fingerprint} certifies binding: $userId <-> ${target.fingerprint} [$trustAmount]" - else { + return if (trustDepth > 0) { val scope = if (regexes.regexStrings.isEmpty()) "" else ", scope: $regexes" "${issuer.fingerprint} delegates to ${target.fingerprint} [$trustAmount, depth $trustDepth$scope]" + } else { + "${issuer.fingerprint} certifies binding: $userId <-> ${target.fingerprint} [$trustAmount]" } } } \ No newline at end of file diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/query/Path.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/query/Path.kt index 777f710c..caaf2e1f 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/query/Path.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/query/Path.kt @@ -97,7 +97,7 @@ class Path( require(target.fingerprint == nComponent.issuer.fingerprint) { "Cannot append edge to path: Path's tail is not issuer of the edge." } - require(residualDepth.isUnconstrained() || residualDepth.limit!! > 0) { + require(residualDepth > 0) { "Not enough depth." } diff --git a/wot-dijkstra/src/test/kotlin/org/pgpainless/wot/network/DepthTest.kt b/wot-dijkstra/src/test/kotlin/org/pgpainless/wot/network/DepthTest.kt index 855fc604..e0ae3652 100644 --- a/wot-dijkstra/src/test/kotlin/org/pgpainless/wot/network/DepthTest.kt +++ b/wot-dijkstra/src/test/kotlin/org/pgpainless/wot/network/DepthTest.kt @@ -9,7 +9,10 @@ import org.junit.jupiter.api.assertThrows import org.pgpainless.wot.network.Depth.Companion.auto import org.pgpainless.wot.network.Depth.Companion.limited import org.pgpainless.wot.network.Depth.Companion.unconstrained -import kotlin.test.* +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNotNull +import kotlin.test.assertTrue class DepthTest { @@ -22,14 +25,15 @@ class DepthTest { @Test fun `verify Depth#unconstrained() has null depth`() { val depth = unconstrained() - assertNull(depth.limit) + assert(depth.isUnconstrained()) + assertEquals(depth.value(), 255) } @Test fun `verify Depth#limited(2) initializes properly`() { val limited = limited(2) - assertNotNull(limited.limit) - assertEquals(2, limited.limit) + assert(!limited.isUnconstrained()) + assertEquals(2, limited.value()) } @Test @@ -50,7 +54,7 @@ class DepthTest { val limited = limited(3) val decreased = limited.decrease(2) assertFalse(decreased.isUnconstrained()) - assertEquals(1, decreased.limit) + assertEquals(1, decreased.value()) } @Test @@ -63,17 +67,21 @@ class DepthTest { @Test fun `verify proper function of compareTo()`() { val unlimited = unconstrained() - val unlimited2 = unconstrained() val depth2 = limited(2) - val depth2_ = limited(2) val depth5 = limited(5) - assertEquals(0, unlimited.compareTo(unlimited2)) - assertTrue(unlimited.compareTo(depth2) > 0) - assertTrue(unlimited.compareTo(depth5) > 0) - assertTrue(depth2.compareTo(unlimited) < 0) - assertTrue(depth2.compareTo(depth5) < 0) - assertTrue(depth5.compareTo(depth2) > 0) - assertEquals(0, depth2.compareTo(depth2_)) + assertTrue(unlimited > 0) + assertTrue(unlimited > 255) + assertTrue(unlimited > 256) + + assertTrue(depth2 > 0) + assertTrue(depth2 > 1) + assertFalse(depth2 > 2) + assertFalse(depth2 > 256) + + assertTrue(depth5 > 1) + assertTrue(depth5 > 4) + assertFalse(depth5 > 5) + assertFalse(depth5 > 256) } @Test @@ -108,7 +116,7 @@ class DepthTest { @Test fun `verify that Depth#auto(255) yields an unconstrained Depth`() { assertTrue { auto(255).isUnconstrained() } - assertNull(auto(255).limit) + assertEquals(auto(255).value(), 255) } @Test @@ -117,7 +125,7 @@ class DepthTest { assertFalse { auto(120).isUnconstrained() } assertFalse { auto(254).isUnconstrained() } - assertNotNull(auto(42).limit) + assertNotNull(auto(42).value()) } @Test