mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 04:17:59 +01:00
Diabetes levels of DSL and sugar
This commit is contained in:
parent
fce8634e4e
commit
dc5d6fca51
6 changed files with 254 additions and 22 deletions
|
@ -20,12 +20,6 @@ data class CertSynopsis(
|
||||||
val revocationState: RevocationState = RevocationState.notRevoked(),
|
val revocationState: RevocationState = RevocationState.notRevoked(),
|
||||||
val userIds : Map<String, RevocationState> = mapOf()) {
|
val userIds : Map<String, RevocationState> = mapOf()) {
|
||||||
|
|
||||||
constructor(fingerprint: String,
|
|
||||||
expirationTime: Date? = null,
|
|
||||||
revocationState: RevocationState = RevocationState.notRevoked(),
|
|
||||||
userIds: Map<String, RevocationState> = mapOf()):
|
|
||||||
this(Fingerprint(fingerprint), expirationTime, revocationState, userIds)
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return if (userIds.isEmpty()) {
|
return if (userIds.isEmpty()) {
|
||||||
"$fingerprint"
|
"$fingerprint"
|
||||||
|
|
|
@ -44,7 +44,7 @@ data class Certification(
|
||||||
constructor(
|
constructor(
|
||||||
issuer: CertSynopsis,
|
issuer: CertSynopsis,
|
||||||
target: CertSynopsis,
|
target: CertSynopsis,
|
||||||
targetUserId: String?,
|
targetUserId: String? = null,
|
||||||
creationTime: Date) :
|
creationTime: Date) :
|
||||||
this(issuer, target, targetUserId, creationTime, null, true, 120, Depth.limited(0), RegexSet.wildcard())
|
this(issuer, target, targetUserId, creationTime, null, true, 120, Depth.limited(0), RegexSet.wildcard())
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ class Network(
|
||||||
}
|
}
|
||||||
|
|
||||||
class Builder internal constructor() {
|
class Builder internal constructor() {
|
||||||
private val nodes: MutableMap<Fingerprint, CertSynopsis> = mutableMapOf()
|
val nodes: MutableMap<Fingerprint, CertSynopsis> = mutableMapOf()
|
||||||
private val protoEdges: MutableMap<Pair<Fingerprint, Fingerprint>, CertificationSet> = mutableMapOf()
|
private val protoEdges: MutableMap<Pair<Fingerprint, Fingerprint>, CertificationSet> = mutableMapOf()
|
||||||
private var referenceTime: ReferenceTime = ReferenceTime.now()
|
private var referenceTime: ReferenceTime = ReferenceTime.now()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.wot.dijkstra
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class CertSynopsisTest: NetworkDSL {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Fingerprint 'A' toString`() {
|
||||||
|
val node = CertSynopsis("A")
|
||||||
|
assertEquals("A", node.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Fingerprint 'a' toString`() {
|
||||||
|
val node = CertSynopsis("a")
|
||||||
|
assertEquals("A", node.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Fingerprint 'A' and UserID toString`() {
|
||||||
|
val node = CertSynopsis("A", "Alice <alice@example.org>")
|
||||||
|
assertEquals("A (Alice <alice@example.org>)", node.toString())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.wot.dijkstra
|
||||||
|
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tons of useful DSL for [Network]-related testing.
|
||||||
|
*/
|
||||||
|
interface NetworkDSL {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [CertSynopsis] from [String] fingerprint.
|
||||||
|
*/
|
||||||
|
fun CertSynopsis(fingerprint: String): CertSynopsis =
|
||||||
|
CertSynopsis(Fingerprint(fingerprint), null, RevocationState.notRevoked(), mapOf())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [CertSynopsis] from [String] fingerprint and non-revoked [userId].
|
||||||
|
*/
|
||||||
|
fun CertSynopsis(fingerprint: String, userId: String): CertSynopsis = CertSynopsis(
|
||||||
|
Fingerprint(fingerprint), null, RevocationState.notRevoked(), mapOf(userId to RevocationState.notRevoked()))
|
||||||
|
|
||||||
|
fun CertSynopsis(original: CertSynopsis, userId: String): CertSynopsis = CertSynopsis(
|
||||||
|
original.fingerprint, original.expirationTime, original.revocationState, original.userIds.plus(userId to RevocationState.notRevoked())
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [Certification] from two [CertSynopsis] nodes.
|
||||||
|
*/
|
||||||
|
fun Certification(issuer: CertSynopsis, target: CertSynopsis): Certification =
|
||||||
|
Certification(issuer, target, null, Date())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [Certification] from two [CertSynopsis] nodes and a target [userId].
|
||||||
|
*/
|
||||||
|
fun Certification(issuer: CertSynopsis, target: CertSynopsis, userId: String): Certification =
|
||||||
|
Certification(issuer, target, userId, Date())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a single [CertSynopsis] built from a [String] fingerprint to the builder.
|
||||||
|
*/
|
||||||
|
fun Network.Builder.addNode(fingerprint: String): Network.Builder {
|
||||||
|
return addNode(CertSynopsis(fingerprint))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a single [CertSynopsis] built from a [String] fingerprint and [userId] to the builder.
|
||||||
|
*/
|
||||||
|
fun Network.Builder.addNode(fingerprint: String, userId: String): Network.Builder {
|
||||||
|
return addNode(CertSynopsis(fingerprint, userId))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add multiple [CertSynopsis] nodes built from [String] fingerprints to the builder.
|
||||||
|
*/
|
||||||
|
fun Network.Builder.addNodes(vararg fingerprints: String) {
|
||||||
|
for (fingerprint in fingerprints) {
|
||||||
|
addNode(fingerprint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an edge between the [CertSynopsis] with fingerprint [issuer] and
|
||||||
|
* the [CertSynopsis] with fingerprint [target].
|
||||||
|
* If either the issuer or target node doesn't exist, throw an [IllegalArgumentException].
|
||||||
|
*/
|
||||||
|
fun Network.Builder.addEdge(issuer: String, target: String): Network.Builder {
|
||||||
|
val issuerNode = nodes[Fingerprint(issuer)]!!
|
||||||
|
val targetNode = nodes[Fingerprint(target)]!!
|
||||||
|
return addEdge(Certification(issuerNode, targetNode))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an edge for [userId] between the [CertSynopsis] with fingerprint [issuer] and
|
||||||
|
* the [CertSynopsis] with fingerprint [target].
|
||||||
|
* If either the issuer or target node doesn't exist, throw an [IllegalArgumentException].
|
||||||
|
*/
|
||||||
|
fun Network.Builder.addEdge(issuer: String, target: String, userId: String): Network.Builder {
|
||||||
|
val issuerNode = nodes[Fingerprint(issuer)]!!
|
||||||
|
val targetNode = nodes[Fingerprint(target)]!!
|
||||||
|
return addEdge(Certification(issuerNode, targetNode, userId))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an edge between the issuer and target node. If either of them doesn't exist, add
|
||||||
|
* a new node for them to the builder.
|
||||||
|
*/
|
||||||
|
fun Network.Builder.buildEdge(issuer: String, target: String): Network.Builder {
|
||||||
|
val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { CertSynopsis(issuer) }
|
||||||
|
val targetNode = nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target) }
|
||||||
|
return addEdge(Certification(issuerNode, targetNode))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an edge for [userId] between the issuer and the target node. If either of them doesn't
|
||||||
|
* exist, add a new node.
|
||||||
|
* If the target node exists, but doesn't carry the [userId], replace it with a copy with
|
||||||
|
* the [userId] inserted.
|
||||||
|
*/
|
||||||
|
fun Network.Builder.buildEdge(issuer: String, target: String, userId: String): Network.Builder {
|
||||||
|
val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { CertSynopsis(issuer)}
|
||||||
|
val targetNode = CertSynopsis(nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target, userId) }, userId)
|
||||||
|
return addEdge(Certification(issuerNode, targetNode, userId))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.Builder.buildEdge(issuer: String, target: String, amount: Int, depth: Int): Network.Builder {
|
||||||
|
val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { CertSynopsis(issuer) }
|
||||||
|
val targetNode = nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target) }
|
||||||
|
return addEdge(Certification(issuerNode, targetNode, null, Date(), null, true, amount, Depth.auto(depth), RegexSet.wildcard()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.Builder.buildEdge(issuer: String, target: String, amount: Int, depth: Int, regexSet: RegexSet): Network.Builder {
|
||||||
|
val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { CertSynopsis(issuer) }
|
||||||
|
val targetNode = nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target) }
|
||||||
|
return addEdge(Certification(issuerNode, targetNode, null, Date(), null, true, amount, Depth.auto(depth), regexSet))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the reference time of the builder to now.
|
||||||
|
*/
|
||||||
|
fun Network.Builder.now(): Network.Builder {
|
||||||
|
return setReferenceTime(ReferenceTime.now())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.getEdgesFor(issuer: Fingerprint, target: Fingerprint): CertificationSet? {
|
||||||
|
return edges[issuer]?.find { it.target.fingerprint == target }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.getEdgesFor(issuer: String, target: String): CertificationSet? {
|
||||||
|
return getEdgesFor(Fingerprint(issuer), Fingerprint(target))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.getEdgeFor(issuer: Fingerprint, target: Fingerprint): List<Certification>? {
|
||||||
|
return getEdgeFor(issuer, target, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.getEdgeFor(issuer: Fingerprint, target: Fingerprint, userId: String?): List<Certification>? {
|
||||||
|
return getEdgesFor(issuer, target)?.certifications?.get(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.getEdgeFor(issuer: String, target: String): List<Certification>? {
|
||||||
|
return getEdgeFor(issuer, target, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Network.getEdgeFor(issuer: String, target: String, userId: String?): List<Certification>? {
|
||||||
|
return getEdgeFor(Fingerprint(issuer), Fingerprint(target), userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lambda with Receiver.
|
||||||
|
*
|
||||||
|
* @see <a href="https://betterprogramming.pub/test-data-creation-using-the-power-of-kotlin-dsl-9526a1fad05b"/>
|
||||||
|
*/
|
||||||
|
fun buildNetwork(builderAction: Network.Builder.() -> Unit): Network {
|
||||||
|
val builder = Network.builder()
|
||||||
|
builder.builderAction()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,15 +5,14 @@
|
||||||
package org.pgpainless.wot.dijkstra
|
package org.pgpainless.wot.dijkstra
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.pgpainless.wot.dijkstra.sq.CertSynopsis
|
import org.pgpainless.wot.dijkstra.sq.Fingerprint
|
||||||
import org.pgpainless.wot.dijkstra.sq.Certification
|
|
||||||
import org.pgpainless.wot.dijkstra.sq.Network
|
|
||||||
import org.pgpainless.wot.dijkstra.sq.Network.Companion.empty
|
import org.pgpainless.wot.dijkstra.sq.Network.Companion.empty
|
||||||
import org.pgpainless.wot.dijkstra.sq.ReferenceTime.Companion.now
|
import org.pgpainless.wot.dijkstra.sq.ReferenceTime.Companion.now
|
||||||
import java.util.Date
|
import org.pgpainless.wot.dijkstra.sq.RegexSet
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class NetworkTest {
|
class NetworkTest: NetworkDSL {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEmptyNetworkIsEmpty() {
|
fun testEmptyNetworkIsEmpty() {
|
||||||
|
@ -27,19 +26,66 @@ class NetworkTest {
|
||||||
assertEquals(0, network.numberOfSignatures)
|
assertEquals(0, network.numberOfSignatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `verify that setting referenceTime works`() {
|
||||||
|
val ref = now()
|
||||||
|
val network = buildNetwork {
|
||||||
|
setReferenceTime(ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(ref, network.referenceTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `verify that adding a single node works`() {
|
||||||
|
val network = buildNetwork { addNode("A") }
|
||||||
|
|
||||||
|
assertEquals(1, network.nodes.size)
|
||||||
|
assertTrue { network.nodes.containsKey(Fingerprint("A")) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `verify that adding multiple, non-connected nodes works`() {
|
||||||
|
val network = buildNetwork { addNodes("A", "B", "C", "D") }
|
||||||
|
assertEquals(4, network.nodes.size)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSimpleNetwork() {
|
fun testSimpleNetwork() {
|
||||||
val alice = CertSynopsis("A")
|
val network = buildNetwork {
|
||||||
val bob = CertSynopsis("B")
|
buildEdge("A", "B")
|
||||||
|
buildEdge("A", "C", "Charlie <charlie@example.org>")
|
||||||
|
}
|
||||||
|
|
||||||
val edge = Certification(alice, bob, null, Date())
|
assertEquals("Network with 3 nodes, 2 edges:\n" +
|
||||||
|
"A certifies binding: null <-> B [120]\n" +
|
||||||
|
"A certifies binding: Charlie <charlie@example.org> <-> C [120]\n",
|
||||||
|
network.toString())
|
||||||
|
}
|
||||||
|
|
||||||
val network = Network.builder()
|
@Test
|
||||||
.addNode(alice)
|
fun `verify that network with 2 edges between 2 nodes keeps edges`() {
|
||||||
.addNode(bob)
|
val network = buildNetwork {
|
||||||
.addEdge(edge)
|
buildEdge("A", "B")
|
||||||
.build()
|
buildEdge("A", "B", "Bob")
|
||||||
|
}
|
||||||
|
|
||||||
println(network)
|
assertEquals(2, network.numberOfSignatures)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `play with depths, amounts and regexes`() {
|
||||||
|
val network = buildNetwork {
|
||||||
|
buildEdge("A", "B", 120, 10)
|
||||||
|
buildEdge("B", "C", 60, 5, RegexSet.fromExpression("*"))
|
||||||
|
buildEdge("A", "C", 10, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(3, network.nodes.size)
|
||||||
|
assertEquals(3, network.numberOfEdges)
|
||||||
|
assertEquals(3, network.numberOfSignatures)
|
||||||
|
|
||||||
|
assertEquals(120, network.getEdgeFor("A", "B")!!.first().trustAmount)
|
||||||
|
assertEquals(10, network.getEdgeFor("A", "B")!!.first().trustDepth.value())
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue