1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-16 01:12:05 +01:00

Some more refactoring and test fixing

This commit is contained in:
Paul Schaub 2023-07-09 11:55:53 +02:00
parent 73f0976857
commit 7ee0a41a6a
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
37 changed files with 386 additions and 397 deletions

View file

@ -7,7 +7,7 @@ package org.pgpainless.wot.cli.subcommands
import org.pgpainless.wot.api.AuthenticateAPI import org.pgpainless.wot.api.AuthenticateAPI
import org.pgpainless.wot.cli.WotCLI import org.pgpainless.wot.cli.WotCLI
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.Path import org.pgpainless.wot.query.Path
import picocli.CommandLine import picocli.CommandLine
import picocli.CommandLine.Command import picocli.CommandLine.Command
import picocli.CommandLine.Parameters import picocli.CommandLine.Parameters

View file

@ -3,6 +3,8 @@ package org.pgpainless.wot.cli.subcommands
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.pgpainless.wot.api.AuthenticateAPI import org.pgpainless.wot.api.AuthenticateAPI
import org.pgpainless.wot.network.* import org.pgpainless.wot.network.*
import org.pgpainless.wot.query.Path
import org.pgpainless.wot.query.Paths
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -29,7 +31,7 @@ class AuthenticateCmdTest {
Pair("Justus Winter <justus@sequoia-pgp.org>", RevocationState.notRevoked()) Pair("Justus Winter <justus@sequoia-pgp.org>", RevocationState.notRevoked())
) )
) )
val edge = Edge( val edgeComponent = EdgeComponent(
neal, neal,
justus, justus,
"Justus Winter <justus@sequoia-pgp.org>", "Justus Winter <justus@sequoia-pgp.org>",
@ -39,7 +41,7 @@ class AuthenticateCmdTest {
120, 120,
Depth.limited(0), Depth.limited(0),
RegexSet.wildcard()) RegexSet.wildcard())
paths.add(Path(neal, mutableListOf(edge), Depth.auto(0)), 120) paths.add(Path(neal, mutableListOf(edgeComponent), Depth.auto(0)), 120)
val testResult = AuthenticateAPI.Result( val testResult = AuthenticateAPI.Result(
Fingerprint("CBCD8F030588653EEDD7E2659B7DD433F254904A"), Fingerprint("CBCD8F030588653EEDD7E2659B7DD433F254904A"),
"Justus Winter <justus@sequoia-pgp.org>", "Justus Winter <justus@sequoia-pgp.org>",

View file

@ -158,7 +158,7 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
processDelegation(targetPrimaryKey, target, delegation) processDelegation(targetPrimaryKey, target, delegation)
} }
// Edge Signatures by X on Y over user-ID U // EdgeComponent Signatures by X on Y over user-ID U
val userIds = targetPrimaryKey.userIDs val userIds = targetPrimaryKey.userIDs
while (userIds.hasNext()) { while (userIds.hasNext()) {
val userId = userIds.next() val userId = userIds.next()

View file

@ -7,7 +7,7 @@ package org.pgpainless.wot.util
import org.bouncycastle.openpgp.PGPSignature import org.bouncycastle.openpgp.PGPSignature
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil
import org.pgpainless.wot.network.Node import org.pgpainless.wot.network.Node
import org.pgpainless.wot.network.Edge import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Depth import org.pgpainless.wot.network.Depth
import org.pgpainless.wot.network.RegexSet import org.pgpainless.wot.network.RegexSet
import org.pgpainless.wot.network.RegexSet.Companion.fromExpressionList import org.pgpainless.wot.network.RegexSet.Companion.fromExpressionList
@ -18,7 +18,7 @@ class CertificationFactory {
@JvmStatic @JvmStatic
fun fromDelegation(issuer: Node, fun fromDelegation(issuer: Node,
target: Node, target: Node,
signature: PGPSignature): Edge { signature: PGPSignature): EdgeComponent {
return fromSignature(issuer, target, null, signature) return fromSignature(issuer, target, null, signature)
} }
@ -26,7 +26,7 @@ class CertificationFactory {
fun fromCertification(issuer: Node, fun fromCertification(issuer: Node,
target: Node, target: Node,
targetUserId: String, targetUserId: String,
signature: PGPSignature): Edge { signature: PGPSignature): EdgeComponent {
return fromSignature(issuer, target, targetUserId, signature) return fromSignature(issuer, target, targetUserId, signature)
} }
@ -34,8 +34,8 @@ class CertificationFactory {
fun fromSignature(issuer: Node, fun fromSignature(issuer: Node,
target: Node, target: Node,
targetUserId: String?, targetUserId: String?,
signature: PGPSignature): Edge { signature: PGPSignature): EdgeComponent {
return Edge( return EdgeComponent(
issuer, issuer,
target, target,
targetUserId, targetUserId,

View file

@ -7,7 +7,7 @@ package org.pgpainless.wot
import org.bouncycastle.openpgp.PGPPublicKeyRing import org.bouncycastle.openpgp.PGPPublicKeyRing
import org.pgpainless.key.OpenPgpFingerprint import org.pgpainless.key.OpenPgpFingerprint
import org.pgpainless.wot.network.EdgeSet import org.pgpainless.wot.network.Edge
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.Network import org.pgpainless.wot.network.Network
import org.pgpainless.wot.testfixtures.TestCertificateStores import org.pgpainless.wot.testfixtures.TestCertificateStores
@ -55,7 +55,7 @@ class WebOfTrustTest {
} }
} }
val fooBankCaEdges = network.edgeSet[fooBankCa]!! val fooBankCaEdges = network.edges[fooBankCa]!!
assertEquals(2, fooBankCaEdges.size) assertEquals(2, fooBankCaEdges.size)
val fbc2fbe = getEdgeFromTo(network, fooBankCa, fooBankEmployee) val fbc2fbe = getEdgeFromTo(network, fooBankCa, fooBankEmployee)
@ -80,8 +80,8 @@ class WebOfTrustTest {
val network = WebOfTrust(certD).buildNetwork() val network = WebOfTrust(certD).buildNetwork()
assertTrue { network.nodes.isEmpty() } assertTrue { network.nodes.isEmpty() }
assertTrue { network.edgeSet.isEmpty() } assertTrue { network.edges.isEmpty() }
assertTrue { network.reverseEdgeSet.isEmpty() } assertTrue { network.reverseEdges.isEmpty() }
} }
@Test @Test
@ -94,7 +94,7 @@ class WebOfTrustTest {
private fun assertHasIssuerAndTarget( private fun assertHasIssuerAndTarget(
certifications: EdgeSet, certifications: Edge,
issuer: Fingerprint, issuer: Fingerprint,
target: Fingerprint) { target: Fingerprint) {
assertEquals(issuer, certifications.issuer.fingerprint) assertEquals(issuer, certifications.issuer.fingerprint)
@ -119,13 +119,13 @@ class WebOfTrustTest {
assertNull(reverseEdge, "Expected no reverse edge on $target from $issuer but got $reverseEdge") assertNull(reverseEdge, "Expected no reverse edge on $target from $issuer but got $reverseEdge")
} }
private fun getEdgeFromTo(network: Network, issuer: Fingerprint, target: Fingerprint): EdgeSet? { private fun getEdgeFromTo(network: Network, issuer: Fingerprint, target: Fingerprint): Edge? {
val edges = network.edgeSet[issuer] ?: return null val edges = network.edges[issuer] ?: return null
return edges.find { target == it.target.fingerprint } return edges.find { target == it.target.fingerprint }
} }
private fun getReverseEdgeFromTo(network: Network, issuer: Fingerprint, target: Fingerprint): EdgeSet? { private fun getReverseEdgeFromTo(network: Network, issuer: Fingerprint, target: Fingerprint): Edge? {
val revEdges = network.reverseEdgeSet[target] ?: return null val revEdges = network.reverseEdges[target] ?: return null
return revEdges.find { issuer == it.issuer.fingerprint } return revEdges.find { issuer == it.issuer.fingerprint }
} }
} }

View file

@ -7,7 +7,7 @@ import org.pgpainless.wot.query.Roots
import org.pgpainless.wot.query.filter.IdempotentCertificationFilter import org.pgpainless.wot.query.filter.IdempotentCertificationFilter
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.Network import org.pgpainless.wot.network.Network
import org.pgpainless.wot.network.Path import org.pgpainless.wot.query.Path
import org.pgpainless.wot.query.Root import org.pgpainless.wot.query.Root
import java.io.File import java.io.File

View file

@ -5,7 +5,7 @@
package org.pgpainless.wot.api package org.pgpainless.wot.api
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.Paths import org.pgpainless.wot.query.Paths
/** /**
* Authenticate a binding. * Authenticate a binding.

View file

@ -5,7 +5,7 @@
package org.pgpainless.wot.api package org.pgpainless.wot.api
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.Paths import org.pgpainless.wot.query.Paths
interface IdentifyAPI { interface IdentifyAPI {

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.api package org.pgpainless.wot.api
import org.pgpainless.wot.network.Paths import org.pgpainless.wot.query.Paths
interface ListAPI { interface ListAPI {

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.api package org.pgpainless.wot.api
import org.pgpainless.wot.network.Paths import org.pgpainless.wot.query.Paths
interface LookupAPI { interface LookupAPI {

View file

@ -4,56 +4,110 @@
package org.pgpainless.wot.network package org.pgpainless.wot.network
import java.util.*
/** /**
* A [Edge] is a signature issued by one certificate over a datum on another target certificate. * An [Edge] comprises a set of signatures ([EdgeComponent]) made by the same issuer, on the same target certificate.
* Such a datum could be either a user-id, or the primary key of the target certificate.
* *
* @param issuer synopsis of the certificate that issued the [Edge] * @param issuer synopsis of the certificate that issued the [Certifications][EdgeComponent]
* @param target synopsis of the certificate that is target of this [Edge] * @param target synopsis of the certificate that is targeted by the [Certifications][EdgeComponent]
* @param userId optional user-id. If this is null, the [Edge] is made over the primary key of the target. * @param components [Map] keyed by user-ids, whose values are [Lists][List] of
* @param creationTime creation time of the [Edge] * [EdgeComponents][EdgeComponent] that are calculated over the key user-id. Note, that the key can also be null for
* @param expirationTime optional expiration time of the [Edge] * [EdgeComponents][EdgeComponent] over the targets primary key.
* @param exportable if false, the certification is marked as "not exportable"
* @param trustAmount amount of trust the issuer places in the binding
* @param trustDepth degree to which the issuer trusts the target as trusted introducer
* @param regexes regular expressions for user-ids which the target is allowed to introduce
*/ */
data class Edge( class Edge(
val issuer: Node, val issuer: Node,
val target: Node, val target: Node,
val userId: String?, components: Map<String?, List<EdgeComponent>>) {
val creationTime: Date,
val expirationTime: Date?,
val exportable: Boolean,
val trustAmount: Int,
val trustDepth: Depth,
val regexes: RegexSet
) {
/** init {
* Construct a [Edge] with default values. The result is non-expiring, will be exportable and has a components.forEach { (_, certifications) ->
* trust amount of 120, a depth of 0 and a wildcard regex. certifications.forEach {
* add(it)
* @param issuer synopsis of the certificate that issued the [Edge] }
* @param target synopsis of the certificate that is target of this [Edge]
* @param targetUserId optional user-id. If this is null, the [Edge] is made over the primary key of the target.
* @param creationTime creation time of the [Edge]
*/
constructor(
issuer: Node,
target: Node,
targetUserId: String? = null,
creationTime: Date) :
this(issuer, target, targetUserId, creationTime, null, true, 120, Depth.limited(0), RegexSet.wildcard())
override fun toString(): String {
return if (trustDepth.limit == 0)
"${issuer.fingerprint} certifies binding: $userId <-> ${target.fingerprint} [$trustAmount]"
else {
val scope = if (regexes.regexStrings.isEmpty()) "" else ", scope: $regexes"
"${issuer.fingerprint} delegates to ${target.fingerprint} [$trustAmount, depth $trustDepth$scope]"
} }
} }
private val _certifications: MutableMap<String?, MutableList<EdgeComponent>> = mutableMapOf()
val components: Map<String?, List<EdgeComponent>>
get() = _certifications.toMutableMap()
companion object {
/**
* Create an empty [Edge].
*
* @param issuer origin of the [Edge].
* @param target targeted of the [Edge].
*/
@JvmStatic
fun empty(issuer: Node, target: Node): Edge {
return Edge(issuer, target, HashMap())
}
/**
* Create a [Edge] from a single [EdgeComponent].
*
* @param edgeComponent edgeComponent
*/
@JvmStatic
fun fromCertification(edgeComponent: EdgeComponent): Edge {
val set = empty(edgeComponent.issuer, edgeComponent.target)
set.add(edgeComponent)
return set
}
}
/**
* Merge the given [Edge] into this.
* This method copies all [EdgeComponents][EdgeComponent] from the other [Edge] into [components].
*
* @param other [Edge] with the same issuer and target as this object.
*/
fun merge(other: Edge) {
if (other == this) {
return
}
require(issuer.fingerprint == other.issuer.fingerprint) { "Issuer fingerprint mismatch." }
require(target.fingerprint == other.target.fingerprint) { "Target fingerprint mismatch." }
for (userId in other.components.keys) {
for (certification in other.components[userId]!!) {
add(certification)
}
}
}
/**
* Add a single [EdgeComponent] into this objects [components].
* Adding multiple [EdgeComponents][EdgeComponent] for the same datum, but with different creation times results in
* only the most recent [EdgeComponent(s)][EdgeComponent] to be preserved.
*
* @param edgeComponent [EdgeComponent] with the same issuer fingerprint and target fingerprint as this object.
*/
fun add(edgeComponent: EdgeComponent) {
require(issuer.fingerprint == edgeComponent.issuer.fingerprint) { "Issuer fingerprint mismatch." }
require(target.fingerprint == edgeComponent.target.fingerprint) { "Target fingerprint mismatch." }
val certificationsForUserId = _certifications.getOrPut(edgeComponent.userId) { mutableListOf() }
if (certificationsForUserId.isEmpty()) {
certificationsForUserId.add(edgeComponent)
return
}
val existing = certificationsForUserId[0]
// if existing is older than this edgeComponent
if (existing.creationTime.before(edgeComponent.creationTime)) {
// throw away older certifications
certificationsForUserId.clear()
}
// If this edgeComponent is newest (or equally old!)
if (!existing.creationTime.after(edgeComponent.creationTime)) {
certificationsForUserId.add(edgeComponent)
}
// else this edgeComponent is older, so don't add it
}
override fun toString(): String {
return components.map { it.value }.flatten().joinToString("\n")
}
} }

View file

@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.network
import java.util.*
/**
* An [EdgeComponent] represents a signature issued by one certificate over a datum on another target certificate.
* Such a datum could be either a user-id, or the primary key of the target certificate.
*
* @param issuer certificate that issued the signature
* @param target certificate that is target of this signature
* @param userId optional user-id. If this is null, the signature is made over the primary key of the target.
* @param creationTime creation time of the signature
* @param expirationTime optional expiration time of the signature
* @param exportable if false, the signtaure is marked as "not exportable"
* @param trustAmount amount of trust the issuer places in the binding
* @param trustDepth degree to which the issuer trusts the target as trusted introducer
* @param regexes regular expressions for user-ids which the target is allowed to introduce
*/
data class EdgeComponent(
val issuer: Node,
val target: Node,
val userId: String?,
val creationTime: Date,
val expirationTime: Date?,
val exportable: Boolean,
val trustAmount: Int,
val trustDepth: Depth,
val regexes: RegexSet
) {
/**
* Construct an [EdgeComponent] with default values. The result is non-expiring, will be exportable and has a
* trust amount of 120, a depth of 0 and a wildcard regex.
*
* @param issuer certificate that issued the signature
* @param target certificate that is target of this signature
* @param targetUserId optional user-id. If this is null, the signature is made over the primary key of the target.
* @param creationTime creation time of the signature
*/
constructor(
issuer: Node,
target: Node,
targetUserId: String? = null,
creationTime: Date) :
this(issuer, target, targetUserId, creationTime, null, true, 120, Depth.limited(0), RegexSet.wildcard())
override fun toString(): String {
return if (trustDepth.limit == 0)
"${issuer.fingerprint} certifies binding: $userId <-> ${target.fingerprint} [$trustAmount]"
else {
val scope = if (regexes.regexStrings.isEmpty()) "" else ", scope: $regexes"
"${issuer.fingerprint} delegates to ${target.fingerprint} [$trustAmount, depth $trustDepth$scope]"
}
}
}

View file

@ -1,115 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.network
/**
* A [EdgeSet] is a set of [Certifications][Edge] made by the same issuer, on the same
* target certificate.
* In some sense, a [EdgeSet] can be considered an edge in the web of trust.
*
* @param issuer synopsis of the certificate that issued the [Certifications][Edge]
* @param target synopsis of the certificate that is targeted by the [Certifications][Edge]
* @param certifications [Map] keyed by user-ids, whose values are [Lists][List] of
* [Certifications][Edge] that are calculated over the key user-id. Note, that the key can also be null for
* [Certifications][Edge] over the targets primary key.
*/
class EdgeSet(
val issuer: Node,
val target: Node,
certifications: Map<String?, List<Edge>>) {
init {
certifications.forEach { (_, certifications) ->
certifications.forEach {
add(it)
}
}
}
private val _certifications: MutableMap<String?, MutableList<Edge>> = mutableMapOf()
val certifications: Map<String?, List<Edge>>
get() = _certifications.toMutableMap()
companion object {
/**
* Create an empty [EdgeSet].
*
* @param issuer the certificate that issued the [Certifications][Edge].
* @param target the certificate that is targeted by the [Certifications][Edge].
*/
@JvmStatic
fun empty(issuer: Node, target: Node): EdgeSet {
return EdgeSet(issuer, target, HashMap())
}
/**
* Create a [EdgeSet] from a single [Edge].
*
* @param edge edge
*/
@JvmStatic
fun fromCertification(edge: Edge): EdgeSet {
val set = empty(edge.issuer, edge.target)
set.add(edge)
return set
}
}
/**
* Merge the given [EdgeSet] into this.
* This method copies all [Certifications][Edge] from the other [EdgeSet] into [certifications].
*
* @param other [EdgeSet] with the same issuer fingerprint and target fingerprint as this object.
*/
fun merge(other: EdgeSet) {
if (other == this) {
return
}
require(issuer.fingerprint == other.issuer.fingerprint) { "Issuer fingerprint mismatch." }
require(target.fingerprint == other.target.fingerprint) { "Target fingerprint mismatch." }
for (userId in other.certifications.keys) {
for (certification in other.certifications[userId]!!) {
add(certification)
}
}
}
/**
* Add a single [Edge] into this objects [certifications].
* Adding multiple [Certifications][Edge] for the same datum, but with different creation times results in
* only the most recent [Edge(s)][Edge] to be preserved.
*
* @param edge [Edge] with the same issuer fingerprint and target fingerprint as this object.
*/
fun add(edge: Edge) {
require(issuer.fingerprint == edge.issuer.fingerprint) { "Issuer fingerprint mismatch." }
require(target.fingerprint == edge.target.fingerprint) { "Target fingerprint mismatch." }
val certificationsForUserId = _certifications.getOrPut(edge.userId) { mutableListOf() }
if (certificationsForUserId.isEmpty()) {
certificationsForUserId.add(edge)
return
}
val existing = certificationsForUserId[0]
// if existing is older than this edge
if (existing.creationTime.before(edge.creationTime)) {
// throw away older certifications
certificationsForUserId.clear()
}
// If this edge is newest (or equally old!)
if (!existing.creationTime.after(edge.creationTime)) {
certificationsForUserId.add(edge)
}
// else this edge is older, so don't add it
}
override fun toString(): String {
return certifications.map { it.value }.flatten().joinToString("\n")
}
}

View file

@ -5,20 +5,20 @@
package org.pgpainless.wot.network package org.pgpainless.wot.network
/** /**
* A network consists of nodes, and edgeSet between them. * A network consists of nodes, and edges between them.
* For the Web of Trust, nodes consist of [CertSynopses][Node], while the edgeSet between the nodes are * In the Web-of-Trust, a [Node] corresponds to a certificate, while an [Edge] comprises all [EdgeComponents][EdgeComponent]
* [CertificationSets][EdgeSet]. * (certifications) between two certificates, separated by their datum (e.g. the certified user-id).
* *
* @constructor creates a new network * @constructor creates a new network
* @param nodes contains a [Map] of [Node] keyed by their [Fingerprint] * @param nodes associate [Nodes][Node] with their [Fingerprint]
* @param edgeSet [Map] keyed by the [fingerprint][Fingerprint] of an issuer, whose values are [Lists][List] containing all edgeSet originating from the issuer. * @param edges map of [Edges][Edge] keyed by their issuers [Fingerprint]
* @param reverseEdgeSet [Map] keyed by the [fingerprint][Fingerprint] of a target, whose values are [Lists][List] containing all edgeSet pointing to the target * @param reverseEdges map of [Edges][Edge] keyed by their targets [Fingerprint]
* @param referenceTime reference time at which the [Network] was built * @param referenceTime reference time at which the [Network] was built
*/ */
class Network( class Network(
val nodes: Map<Fingerprint, Node>, val nodes: Map<Fingerprint, Node>,
val edgeSet: Map<Fingerprint, List<EdgeSet>>, val edges: Map<Fingerprint, List<Edge>>,
val reverseEdgeSet: Map<Fingerprint, List<EdgeSet>>, val reverseEdges: Map<Fingerprint, List<Edge>>,
val referenceTime: ReferenceTime) { val referenceTime: ReferenceTime) {
companion object { companion object {
@ -34,31 +34,31 @@ class Network(
} }
/** /**
* The total number of edgeSet on the network. * The total number of edges on the network.
* *
* @return number of edgeSet * @return number of edges
*/ */
val numberOfEdges: Int val numberOfEdges: Int
get() { get() {
return edgeSet.values.sumOf { it.size } return edges.values.sumOf { it.size }
} }
/** /**
* The total number of signatures the network comprises. * The total number of individual [EdgeComponents][EdgeComponent] the network comprises.
*/ */
val numberOfSignatures: Int val numberOfSignatures: Int
get() { get() {
return edgeSet.values return edges.values
.flatten() .flatten()
.flatMap { it.certifications.values } .flatMap { it.components.values }
.sumOf { it.size } .sumOf { it.size }
} }
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder() val sb = StringBuilder()
sb.append("Network with ${nodes.size} nodes, $numberOfEdges edgeSet:\n") sb.append("Network with ${nodes.size} nodes, $numberOfEdges edges:\n")
for (issuer in nodes.keys) { for (issuer in nodes.keys) {
val outEdges = edgeSet[issuer] ?: continue val outEdges = edges[issuer] ?: continue
for (edge in outEdges) { for (edge in outEdges) {
sb.appendLine(edge) sb.appendLine(edge)
} }
@ -68,7 +68,7 @@ class Network(
class Builder internal constructor() { class Builder internal constructor() {
val nodes: MutableMap<Fingerprint, Node> = mutableMapOf() val nodes: MutableMap<Fingerprint, Node> = mutableMapOf()
private val protoEdgeSet: MutableMap<Pair<Fingerprint, Fingerprint>, EdgeSet> = mutableMapOf() private val protoEdgeSet: MutableMap<Pair<Fingerprint, Fingerprint>, Edge> = mutableMapOf()
private var referenceTime: ReferenceTime = ReferenceTime.now() private var referenceTime: ReferenceTime = ReferenceTime.now()
fun addNode(node: Node): Builder { fun addNode(node: Node): Builder {
@ -80,10 +80,10 @@ class Network(
return nodes[fingerprint] return nodes[fingerprint]
} }
fun addEdge(edge: Edge): Builder { fun addEdge(edgeComponent: EdgeComponent): Builder {
protoEdgeSet.getOrPut(Pair(edge.issuer.fingerprint, edge.target.fingerprint)) { protoEdgeSet.getOrPut(Pair(edgeComponent.issuer.fingerprint, edgeComponent.target.fingerprint)) {
EdgeSet.empty(edge.issuer, edge.target) Edge.empty(edgeComponent.issuer, edgeComponent.target)
}.add(edge) }.add(edgeComponent)
return this return this
} }
@ -93,8 +93,8 @@ class Network(
} }
fun build(): Network { fun build(): Network {
val edgeSet = mutableMapOf<Fingerprint, MutableList<EdgeSet>>() val edgeSet = mutableMapOf<Fingerprint, MutableList<Edge>>()
val revEdgeSet = mutableMapOf<Fingerprint, MutableList<EdgeSet>>() val revEdgeSet = mutableMapOf<Fingerprint, MutableList<Edge>>()
protoEdgeSet.forEach { (pair, certificationSet) -> protoEdgeSet.forEach { (pair, certificationSet) ->
edgeSet.getOrPut(pair.first) { edgeSet.getOrPut(pair.first) {

View file

@ -2,21 +2,24 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.network package org.pgpainless.wot.query
import org.pgpainless.wot.network.Depth
import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Node
import kotlin.math.min import kotlin.math.min
/** /**
* A [Path] comprises a root [Node], a list of edgeSet ([Certifications][Edge]), as well as a * A [Path] comprises a root [Node], a list of edges (selected [EdgeComponents][EdgeComponent]), as well as a
* residual depth. * residual depth.
* *
* @param root root of the path * @param root root of the path
* @param edges list of edgeSet from the root to the target * @param edges list of edges from the root to the target
* @param residualDepth residual depth that is decreased each time another edge is appended * @param residualDepth residual depth that is decreased each time another edge is appended
*/ */
class Path( class Path(
val root: Node, val root: Node,
private val edges: MutableList<Edge>, private val edges: MutableList<EdgeComponent>,
var residualDepth: Depth var residualDepth: Depth
) { ) {
@ -27,7 +30,7 @@ class Path(
* @param root trust root * @param root trust root
*/ */
constructor(root: Node) : this( constructor(root: Node) : this(
root, mutableListOf<Edge>(), Depth.unconstrained()) root, mutableListOf<EdgeComponent>(), Depth.unconstrained())
/** /**
* Current target of the path. * Current target of the path.
@ -43,14 +46,14 @@ class Path(
} }
/** /**
* List of [CertSynopses][Node] (nodes) of the path. * List of [Nodes][Node] on the path.
* The first entry is the [root]. The other entries are the targets of the edgeSet. * The first entry is the [root]. The other entries are the targets of the edges.
*/ */
val certificates: List<Node> val certificates: List<Node>
get() { get() {
val certs: MutableList<Node> = mutableListOf(root) val certs: MutableList<Node> = mutableListOf(root)
for (certification in edges) { for (edge in edges) {
certs.add(certification.target) certs.add(edge.target)
} }
return certs return certs
} }
@ -63,9 +66,9 @@ class Path(
get() = edges.size + 1 get() = edges.size + 1
/** /**
* List of edgeSet. * List of edge components.
*/ */
val certifications: List<Edge> val certifications: List<EdgeComponent>
get() = edges.toList() get() = edges.toList()
/** /**
@ -88,10 +91,10 @@ class Path(
* *
* @throws IllegalArgumentException if the target at the end of the path is not equal to the issuer of the edge. * @throws IllegalArgumentException if the target at the end of the path is not equal to the issuer of the edge.
* @throws IllegalArgumentException if the path runs out of residual depth * @throws IllegalArgumentException if the path runs out of residual depth
* @throws IllegalArgumentException if the addition of the [Edge] would result in a cyclic path * @throws IllegalArgumentException if the addition of the [EdgeComponent] would result in a cyclic path
*/ */
fun append(aEdge: Edge) { fun append(component: EdgeComponent) {
require(target.fingerprint == aEdge.issuer.fingerprint) { require(target.fingerprint == component.issuer.fingerprint) {
"Cannot append edge to path: Path's tail is not issuer of the edge." "Cannot append edge to path: Path's tail is not issuer of the edge."
} }
require(residualDepth.isUnconstrained() || residualDepth.limit!! > 0) { require(residualDepth.isUnconstrained() || residualDepth.limit!! > 0) {
@ -99,26 +102,26 @@ class Path(
} }
// root is c's target -> illegal cycle // root is c's target -> illegal cycle
var cyclic = root.fingerprint == aEdge.target.fingerprint var cyclic = root.fingerprint == component.target.fingerprint
for ((i, edge) in edges.withIndex()) { for ((i, edge) in edges.withIndex()) {
if (cyclic) { if (cyclic) {
break break
} }
// existing edge points to c's target -> illegal cycle // existing edge points to c's target -> illegal cycle
if (aEdge.target.fingerprint == edge.target.fingerprint) { if (component.target.fingerprint == edge.target.fingerprint) {
cyclic = if (edges.lastIndex != i) { cyclic = if (edges.lastIndex != i) {
// Cycle in the middle of the ~~street~~ path // Cycle in the middle of the ~~street~~ path
true true
} else { } else {
// Not a cycle, if we point to a different user-id // Not a cycle, if we point to a different user-id
aEdge.userId == edge.userId component.userId == edge.userId
} }
} }
} }
require(!cyclic) { "Adding the edge to the path would create a cycle." } require(!cyclic) { "Adding the edge to the path would create a cycle." }
residualDepth = aEdge.trustDepth.min(residualDepth.decrease(1)) residualDepth = component.trustDepth.min(residualDepth.decrease(1))
edges.add(aEdge) edges.add(component)
} }
override fun toString(): String { override fun toString(): String {

View file

@ -2,7 +2,7 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.network package org.pgpainless.wot.query
/** /**
* List of individual [Paths][Path]. * List of individual [Paths][Path].

View file

@ -48,7 +48,7 @@ internal class Cost(
// We perform a Dijkstra in reserve from the target towards the roots. // We perform a Dijkstra in reserve from the target towards the roots.
internal data class ForwardPointer( internal data class ForwardPointer(
// If null, then the target. // If null, then the target.
val next: Edge? val next: EdgeComponent?
) )
class Query( class Query(
@ -174,7 +174,7 @@ class Query(
/// ///
/// # Algorithm /// # Algorithm
/// ///
/// This algorithm reverses the edgeSet in the network and then /// This algorithm reverses the edges in the network and then
/// executes a variant of [Dijkstra's shortest path algorithm]. /// executes a variant of [Dijkstra's shortest path algorithm].
/// The algorithm sets the initial node to be the target and works /// The algorithm sets the initial node to be the target and works
/// outwards. Consider the following network: /// outwards. Consider the following network:
@ -362,7 +362,7 @@ class Query(
var depth: Int = if (selfSigned) 1 else 0 var depth: Int = if (selfSigned) 1 else 0
while (fp.next != null) { while (fp.next != null) {
val c: Edge = fp.next!! // FIXME val c: EdgeComponent = fp.next!! // FIXME
val a = c.trustAmount val a = c.trustAmount
val d = c.trustDepth val d = c.trustDepth
@ -430,8 +430,8 @@ class Query(
// Get signeeFp // Get signeeFp
// Not limiting by required_depth, because 'network' doesn't expose an interface for this // Not limiting by required_depth, because 'network' doesn't expose an interface for this
val edges: List<EdgeSet> = val edges: List<Edge> =
network.reverseEdgeSet[signeeFpr].orEmpty() // "certifications_of" network.reverseEdges[signeeFpr].orEmpty() // "certifications_of"
if (edges.isEmpty()) { if (edges.isEmpty()) {
// Nothing certified it. The path is a dead end. // Nothing certified it. The path is a dead end.
@ -446,7 +446,7 @@ class Query(
for (certification in edges for (certification in edges
.map { cs -> .map { cs ->
cs.certifications cs.components
.map { it.value }.flatten() .map { it.value }.flatten()
}.flatten()) { }.flatten()) {
@ -472,7 +472,7 @@ class Query(
if (fv.amount == 0) { if (fv.amount == 0) {
logger.debug(" Edge amount is 0, skipping") logger.debug(" EdgeComponent amount is 0, skipping")
continue; continue;
} }
@ -481,20 +481,20 @@ class Query(
&& certification.userId != targetUserid) { && certification.userId != targetUserid) {
assert(signeeFp.next == null) assert(signeeFp.next == null)
logger.debug(" Edge certifies target, but for the wrong user id (want: {}, got: {})", logger.debug(" EdgeComponent certifies target, but for the wrong user id (want: {}, got: {})",
targetUserid, certification.userId) targetUserid, certification.userId)
continue; continue;
} }
if (fv.depth < Depth.auto(signeeFpCost.depth)) { if (fv.depth < Depth.auto(signeeFpCost.depth)) {
logger.debug(" Edge does not have enough depth ({}, needed: {}), skipping", fv.depth, signeeFpCost.depth) logger.debug(" EdgeComponent does not have enough depth ({}, needed: {}), skipping", fv.depth, signeeFpCost.depth)
continue; continue;
} }
val re = fv.regexps val re = fv.regexps
if ((re != null) && !re.matches(targetUserid)) { if ((re != null) && !re.matches(targetUserid)) {
logger.debug(" Edge's re does not match target User ID, skipping.") logger.debug(" EdgeComponent's re does not match target User ID, skipping.")
continue; continue;
} }
@ -538,7 +538,7 @@ class Query(
cn?.target ?: "target", currentFpCost.amount, currentFpCost.depth) cn?.target ?: "target", currentFpCost.amount, currentFpCost.depth)
// We prefer a shorter path (in terms of // We prefer a shorter path (in terms of
// edgeSet) as this allows us to reach more of // edges) as this allows us to reach more of
// the graph. // the graph.
// //
// If the path length is equal, we prefer the // If the path length is equal, we prefer the
@ -615,7 +615,7 @@ class Query(
// //
// XXX: Self-signatures should be first class and not // XXX: Self-signatures should be first class and not
// synthesized like this on the fly. // synthesized like this on the fly.
val selfsig = Edge( val selfsig = EdgeComponent(
target, target, targetUserid, target, target, targetUserid,
// FIXME! Use userid binding signature by default, reference time only as fallback: // FIXME! Use userid binding signature by default, reference time only as fallback:
@ -651,7 +651,7 @@ class Query(
var amount = 120; var amount = 120;
// nodes[0] is the root; nodes[nodes.len() - 1] is the target. // nodes[0] is the root; nodes[nodes.len() - 1] is the target.
val nodes: MutableList<Edge> = mutableListOf(); val nodes: MutableList<EdgeComponent> = mutableListOf();
while (true) { while (true) {
val c = fp.next ?: break val c = fp.next ?: break
@ -673,7 +673,7 @@ class Query(
if (selfSigned) { if (selfSigned) {
val tail = nodes.last() val tail = nodes.last()
if (tail.userId != targetUserid) { if (tail.userId != targetUserid) {
val selfsig = Edge(target, target, targetUserid, Date()); val selfsig = EdgeComponent(target, target, targetUserid, Date());
nodes.add(selfsig); nodes.add(selfsig);
} }
} }
@ -725,7 +725,7 @@ class Query(
// .unwrap_or("<missing User ID>".into()); // .unwrap_or("<missing User ID>".into());
// t!(" <{}, {}>: {}", // t!(" <{}, {}>: {}",
// fpr, userid, // fpr, userid,
// format!("{} trust amount (max: {}), {} edgeSet", // format!("{} trust amount (max: {}), {} edges",
// amount, path.amount(), // amount, path.amount(),
// path.len() - 1)); // path.len() - 1));
// } // }

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.query.filter package org.pgpainless.wot.query.filter
import org.pgpainless.wot.network.Edge import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
class CapCertificateFilter() : CertificationFilter { class CapCertificateFilter() : CertificationFilter {
@ -12,7 +12,7 @@ class CapCertificateFilter() : CertificationFilter {
// A certificate's trust amount will be limited to this amount. // A certificate's trust amount will be limited to this amount.
private val caps: HashMap<Fingerprint, Int> = hashMapOf() private val caps: HashMap<Fingerprint, Int> = hashMapOf()
override fun cost(c: Edge, values: FilterValues, ignoreRegexps: Boolean): Boolean { override fun cost(c: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
caps[c.issuer.fingerprint]?.let { caps[c.issuer.fingerprint]?.let {
if (it < values.amount) { if (it < values.amount) {
values.amount = it values.amount = it

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.query.filter package org.pgpainless.wot.query.filter
import org.pgpainless.wot.network.Edge import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Depth import org.pgpainless.wot.network.Depth
import org.pgpainless.wot.network.RegexSet import org.pgpainless.wot.network.RegexSet
@ -33,7 +33,7 @@ interface CertificationFilter {
* *
* If the function returns `false`, the certification should be skipped. * If the function returns `false`, the certification should be skipped.
*/ */
fun cost(c: Edge, values: FilterValues, ignoreRegexps: Boolean): Boolean { fun cost(c: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
return true return true
} }

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.query.filter package org.pgpainless.wot.query.filter
import org.pgpainless.wot.network.Edge import org.pgpainless.wot.network.EdgeComponent
/** /**
* A filter that chains multiple filters together. * A filter that chains multiple filters together.
@ -15,7 +15,7 @@ import org.pgpainless.wot.network.Edge
*/ */
class ChainFilter(val filters: MutableList<CertificationFilter>) : CertificationFilter { class ChainFilter(val filters: MutableList<CertificationFilter>) : CertificationFilter {
override fun cost(c: Edge, values: FilterValues, ignoreRegexps: Boolean): Boolean { override fun cost(c: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
// If any inner filter returns `false`, immediately return false // If any inner filter returns `false`, immediately return false
return !this.filters.any { !it.cost(c, values, ignoreRegexps) } return !this.filters.any { !it.cost(c, values, ignoreRegexps) }

View file

@ -4,15 +4,15 @@
package org.pgpainless.wot.query.filter package org.pgpainless.wot.query.filter
import org.pgpainless.wot.network.Edge import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.Path import org.pgpainless.wot.query.Path
class SuppressCertificationFilter() : CertificationFilter { class SuppressCertificationFilter() : CertificationFilter {
// A certification's trust amount will be suppressed by this amount. // A certification's trust amount will be suppressed by this amount.
private val amount: HashMap<Pair<Fingerprint, Fingerprint>, Int> = hashMapOf() private val amount: HashMap<Pair<Fingerprint, Fingerprint>, Int> = hashMapOf()
override fun cost(c: Edge, values: FilterValues, ignoreRegexps: Boolean): Boolean { override fun cost(c: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
amount[Pair(c.issuer.fingerprint, c.issuer.fingerprint)]?.let { suppress -> amount[Pair(c.issuer.fingerprint, c.issuer.fingerprint)]?.let { suppress ->
values.amount = if (values.amount > suppress) { values.amount = if (values.amount > suppress) {
values.amount - suppress values.amount - suppress

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.query.filter package org.pgpainless.wot.query.filter
import org.pgpainless.wot.network.Edge import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint
/** /**
@ -14,7 +14,7 @@ class SuppressIssuerFilter() : CertificationFilter {
// A certification's trust amount will be suppressed by this amount. // A certification's trust amount will be suppressed by this amount.
private val amount: HashMap<Fingerprint, Int> = hashMapOf() private val amount: HashMap<Fingerprint, Int> = hashMapOf()
override fun cost(c: Edge, values: FilterValues, ignoreRegexps: Boolean): Boolean { override fun cost(c: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
amount[c.issuer.fingerprint]?.let { suppress -> amount[c.issuer.fingerprint]?.let { suppress ->
values.amount = if (values.amount > suppress) { values.amount = if (values.amount > suppress) {
values.amount - suppress values.amount - suppress

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.query.filter package org.pgpainless.wot.query.filter
import org.pgpainless.wot.network.Edge import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Depth import org.pgpainless.wot.network.Depth
/** /**
@ -16,7 +16,7 @@ import org.pgpainless.wot.network.Depth
* This filter can be used to view a network as a 'certification network'. * This filter can be used to view a network as a 'certification network'.
*/ */
class TrustedIntroducerFilter : CertificationFilter { class TrustedIntroducerFilter : CertificationFilter {
override fun cost(c: Edge, values: FilterValues, ignoreRegexps: Boolean): Boolean { override fun cost(c: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
values.depth = Depth.unconstrained() values.depth = Depth.unconstrained()
if (!ignoreRegexps) { if (!ignoreRegexps) {
values.regexps = null values.regexps = null

View file

@ -1,26 +0,0 @@
package org.pgpainless.wot.dijkstra.sq
import org.pgpainless.wot.network.RegexSet
import kotlin.test.Test
class RegexSetTest {
@Test
fun simpleMatch() {
val stringList: List<String> = listOf("<[^>]+[@.]foobank\\.com>$")
val rs = RegexSet.fromExpressionList(stringList);
assert(rs.matches("Foo Bank Employee <employee@foobank.com>"))
assert(rs.matches("<employee@foobank.com>"))
}
@Test
fun simpleNonMatch() {
val stringList: List<String> = listOf("<[^>]+[@.]foobank\\.com>$")
val rs = RegexSet.fromExpressionList(stringList);
assert(!rs.matches("Bar Bank Employee <employee@barbank.com>"))
assert(!rs.matches("<employee@barbank.com>"))
}
}

View file

@ -2,7 +2,7 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows

View file

@ -1,14 +1,10 @@
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.pgpainless.wot.network.Node
import org.pgpainless.wot.network.Edge
import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.RevocationState
import java.util.* import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
class EdgeTest { class EdgeComponentTest {
private val alice = Node( private val alice = Node(
Fingerprint("A"), Fingerprint("A"),
@ -28,21 +24,21 @@ class EdgeTest {
@Test @Test
fun `verify result of toString() on certification`() { fun `verify result of toString() on certification`() {
val edge = Edge(alice, bob, "Bob <bob@example.org>", Date()) val edgeComponent = EdgeComponent(alice, bob, "Bob <bob@example.org>", Date())
assertEquals("A certifies binding: Bob <bob@example.org> <-> B [120]", assertEquals("A certifies binding: Bob <bob@example.org> <-> B [120]",
edge.toString()) edgeComponent.toString())
} }
@Test @Test
fun `verify result of toString() on delegation`() { fun `verify result of toString() on delegation`() {
val delegation = Edge(alice, bob, null, Date()) val delegation = EdgeComponent(alice, bob, null, Date())
assertEquals("A certifies binding: null <-> B [120]", assertEquals("A certifies binding: null <-> B [120]",
delegation.toString()) delegation.toString())
} }
@Test @Test
fun `verify result of toString() on delegation with userId-less issuer`() { fun `verify result of toString() on delegation with userId-less issuer`() {
val delegation = Edge(charlie, bob, null, Date()) val delegation = EdgeComponent(charlie, bob, null, Date())
assertEquals("C certifies binding: null <-> B [120]", assertEquals("C certifies binding: null <-> B [120]",
delegation.toString()) delegation.toString())
} }

View file

@ -2,106 +2,105 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import org.pgpainless.wot.network.*
import java.util.* import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertTrue
class EdgeSetTest { class EdgeTest {
private val alice = Node(Fingerprint("A"), null, RevocationState.notRevoked(), mapOf()) private val alice = Node(Fingerprint("A"), null, RevocationState.notRevoked(), mapOf())
private val bob = Node(Fingerprint("B"), null, RevocationState.notRevoked(), mapOf()) private val bob = Node(Fingerprint("B"), null, RevocationState.notRevoked(), mapOf())
private val charlie = Node(Fingerprint("C"), null, RevocationState.notRevoked(), mapOf()) private val charlie = Node(Fingerprint("C"), null, RevocationState.notRevoked(), mapOf())
private val aliceSignsBob = Edge(alice, bob, null, Date()) private val aliceSignsBob = EdgeComponent(alice, bob, null, Date())
private val aliceSignsBobUserId = Edge(alice, bob, "Bob <bob@example.org>", Date()) private val aliceSignsBobUserId = EdgeComponent(alice, bob, "Bob <bob@example.org>", Date())
private val aliceSignsCharlie = Edge(alice, charlie, null, Date()) private val aliceSignsCharlie = EdgeComponent(alice, charlie, null, Date())
private val charlieSignsBob = Edge(charlie, bob, null, Date()) private val charlieSignsBob = EdgeComponent(charlie, bob, null, Date())
@Test @Test
fun `verify that properties of an empty CertificationSet are also empty`() { fun `verify that properties of an empty CertificationSet are also empty`() {
val empty = EdgeSet.empty(alice, bob) val empty = Edge.empty(alice, bob)
assert(empty.certifications.isEmpty()) assert(empty.components.isEmpty())
assertEquals(alice, empty.issuer) assertEquals(alice, empty.issuer)
assertEquals(bob, empty.target) assertEquals(bob, empty.target)
} }
@Test @Test
fun `verify that add()ing Certification objects works if issuer and target match that of the CertificationSet`() { fun `verify that add()ing Certification objects works if issuer and target match that of the CertificationSet`() {
val set = EdgeSet.empty(alice, bob) val set = Edge.empty(alice, bob)
set.add(aliceSignsBob) set.add(aliceSignsBob)
assertTrue { assertTrue {
set.certifications.values.any { set.components.values.any {
it.contains(aliceSignsBob) it.contains(aliceSignsBob)
} }
} }
set.add(aliceSignsBobUserId) set.add(aliceSignsBobUserId)
assertTrue { assertTrue {
set.certifications["Bob <bob@example.org>"]!!.contains(aliceSignsBobUserId) set.components["Bob <bob@example.org>"]!!.contains(aliceSignsBobUserId)
} }
} }
@Test @Test
fun `verify that add()ing another Certification object fails if the issuer mismatches`() { fun `verify that add()ing another Certification object fails if the issuer mismatches`() {
val set = EdgeSet.empty(alice, bob) val set = Edge.empty(alice, bob)
assertThrows<IllegalArgumentException> { set.add(charlieSignsBob) } assertThrows<IllegalArgumentException> { set.add(charlieSignsBob) }
} }
@Test @Test
fun `verify that add()ing another Certification object fails if the target mismatches`() { fun `verify that add()ing another Certification object fails if the target mismatches`() {
val set = EdgeSet.empty(alice, bob) val set = Edge.empty(alice, bob)
assertThrows<IllegalArgumentException> { set.add(aliceSignsCharlie) } assertThrows<IllegalArgumentException> { set.add(aliceSignsCharlie) }
} }
@Test @Test
fun `verify that merge()ing another CertificationSet works if issuer and target match that of the CertificationSet`() { fun `verify that merge()ing another CertificationSet works if issuer and target match that of the CertificationSet`() {
val set = EdgeSet.fromCertification(aliceSignsBob) val set = Edge.fromCertification(aliceSignsBob)
val others = EdgeSet.fromCertification(aliceSignsBobUserId) val others = Edge.fromCertification(aliceSignsBobUserId)
set.merge(others) set.merge(others)
assertEquals(2, set.certifications.size) assertEquals(2, set.components.size)
assertTrue { set.certifications[null]!!.contains(aliceSignsBob) } assertTrue { set.components[null]!!.contains(aliceSignsBob) }
assertTrue { set.certifications["Bob <bob@example.org>"]!!.contains(aliceSignsBobUserId) } assertTrue { set.components["Bob <bob@example.org>"]!!.contains(aliceSignsBobUserId) }
} }
@Test @Test
fun `verify that merge()ing another CertificationSet with mismatched issuer fails`() { fun `verify that merge()ing another CertificationSet with mismatched issuer fails`() {
val set = EdgeSet.fromCertification(aliceSignsBob) val set = Edge.fromCertification(aliceSignsBob)
val issuerMismatch = EdgeSet.fromCertification(charlieSignsBob) val issuerMismatch = Edge.fromCertification(charlieSignsBob)
assertThrows<IllegalArgumentException> { set.merge(issuerMismatch) } assertThrows<IllegalArgumentException> { set.merge(issuerMismatch) }
} }
@Test @Test
fun `verify that merge()ing another CertificationSet with mismatched target fails`() { fun `verify that merge()ing another CertificationSet with mismatched target fails`() {
val set = EdgeSet.fromCertification(aliceSignsBob) val set = Edge.fromCertification(aliceSignsBob)
val targetMismatch = EdgeSet.fromCertification(aliceSignsCharlie) val targetMismatch = Edge.fromCertification(aliceSignsCharlie)
assertThrows<IllegalArgumentException> { set.merge(targetMismatch) } assertThrows<IllegalArgumentException> { set.merge(targetMismatch) }
} }
@Test @Test
fun `verify that merge()ing a CertificationSet with itself is idempotent`() { fun `verify that merge()ing a CertificationSet with itself is idempotent`() {
val set = EdgeSet.fromCertification(aliceSignsBob) val set = Edge.fromCertification(aliceSignsBob)
assertEquals(1, set.certifications.size) assertEquals(1, set.components.size)
set.merge(set) set.merge(set)
assertEquals(1, set.certifications.size) assertEquals(1, set.components.size)
} }
@Test @Test
fun `verify that toString() of an empty CertificationSet is the empty string`() { fun `verify that toString() of an empty CertificationSet is the empty string`() {
val empty = EdgeSet.empty(alice, bob) val empty = Edge.empty(alice, bob)
assertEquals("", empty.toString()) assertEquals("", empty.toString())
} }
@Test @Test
fun `verify that toString() of a CertificationSet with two Certifications matches our expectations`() { fun `verify that toString() of a CertificationSet with two Certifications matches our expectations`() {
val twoCerts = EdgeSet.fromCertification(aliceSignsBob) val twoCerts = Edge.fromCertification(aliceSignsBob)
twoCerts.add(aliceSignsBobUserId) twoCerts.add(aliceSignsBobUserId)
assertEquals("A certifies binding: null <-> B [120]\n" + assertEquals("A certifies binding: null <-> B [120]\n" +
@ -112,22 +111,22 @@ class EdgeSetTest {
fun `verify that for multiple Certifications over the same datum, only the most recent certifications are preserved`() { fun `verify that for multiple Certifications over the same datum, only the most recent certifications are preserved`() {
val now = Date() val now = Date()
val fiveSecondsBefore = Date(now.time - 5000) val fiveSecondsBefore = Date(now.time - 5000)
val old = Edge(alice, bob, "Bob <bob@example.org>", fiveSecondsBefore) val old = EdgeComponent(alice, bob, "Bob <bob@example.org>", fiveSecondsBefore)
val new = Edge(alice, bob, "Bob <bob@example.org>", now) val new = EdgeComponent(alice, bob, "Bob <bob@example.org>", now)
val new2 = Edge(alice, bob, "Bob <bob@example.org>", now, null, true, 44, Depth.auto(10), RegexSet.wildcard()) val new2 = EdgeComponent(alice, bob, "Bob <bob@example.org>", now, null, true, 44, Depth.auto(10), RegexSet.wildcard())
var set = EdgeSet(alice, bob, mapOf()) var set = Edge(alice, bob, mapOf())
set.add(old) set.add(old)
assertEquals(listOf(old), set.certifications["Bob <bob@example.org>"]) assertEquals(listOf(old), set.components["Bob <bob@example.org>"])
set.add(new) set.add(new)
assertEquals(listOf(new), set.certifications["Bob <bob@example.org>"]) assertEquals(listOf(new), set.components["Bob <bob@example.org>"])
set.add(new2) set.add(new2)
assertEquals(listOf(new, new2), set.certifications["Bob <bob@example.org>"]) assertEquals(listOf(new, new2), set.components["Bob <bob@example.org>"])
set.add(old) set.add(old)
assertEquals(listOf(new, new2), set.certifications["Bob <bob@example.org>"]) assertEquals(listOf(new, new2), set.components["Bob <bob@example.org>"])
} }
} }

View file

@ -1,4 +1,4 @@
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.pgpainless.wot.network.Fingerprint import org.pgpainless.wot.network.Fingerprint

View file

@ -2,9 +2,8 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.pgpainless.wot.network.*
import java.util.* import java.util.*
/** /**
@ -15,46 +14,46 @@ interface NetworkDSL {
/** /**
* Create [Node] from [String] fingerprint. * Create [Node] from [String] fingerprint.
*/ */
fun CertSynopsis(fingerprint: String): Node = fun Node(fingerprint: String): Node =
Node(Fingerprint(fingerprint), null, RevocationState.notRevoked(), mapOf()) Node(Fingerprint(fingerprint), null, RevocationState.notRevoked(), mapOf())
/** /**
* Create [Node] from [String] fingerprint and non-revoked [userId]. * Create [Node] from [String] fingerprint and non-revoked [userId].
*/ */
fun CertSynopsis(fingerprint: String, userId: String): Node = Node( fun Node(fingerprint: String, userId: String): Node = Node(
Fingerprint(fingerprint), null, RevocationState.notRevoked(), mapOf(userId to RevocationState.notRevoked())) Fingerprint(fingerprint), null, RevocationState.notRevoked(), mapOf(userId to RevocationState.notRevoked()))
fun CertSynopsis(original: Node, userId: String): Node = Node( fun Node(original: Node, userId: String): Node = Node(
original.fingerprint, original.expirationTime, original.revocationState, original.userIds.plus(userId to RevocationState.notRevoked()) original.fingerprint, original.expirationTime, original.revocationState, original.userIds.plus(userId to RevocationState.notRevoked())
) )
/** /**
* Create [Edge] from two [Node] nodes. * Create [EdgeComponent] from two [Node] nodes.
*/ */
fun Certification(issuer: Node, target: Node): Edge = fun Edge(issuer: Node, target: Node): EdgeComponent =
Edge(issuer, target, null, Date()) EdgeComponent(issuer, target, null, Date())
/** /**
* Create [Edge] from two [Node] nodes and a target [userId]. * Create [EdgeComponent] from two [Node] nodes and a target [userId].
*/ */
fun Certification(issuer: Node, target: Node, userId: String): Edge = fun Edge(issuer: Node, target: Node, userId: String): EdgeComponent =
Edge(issuer, target, userId, Date()) EdgeComponent(issuer, target, userId, Date())
fun Certification(issuer: Node, target: Node, amount: Int, depth: Depth): Edge = fun Edge(issuer: Node, target: Node, amount: Int, depth: Depth): EdgeComponent =
Edge(issuer, target, null, Date(), null, true, amount, depth, RegexSet.wildcard()) EdgeComponent(issuer, target, null, Date(), null, true, amount, depth, RegexSet.wildcard())
/** /**
* Add a single [Node] built from a [String] fingerprint to the builder. * Add a single [Node] built from a [String] fingerprint to the builder.
*/ */
fun Network.Builder.addNode(fingerprint: String): Network.Builder { fun Network.Builder.addNode(fingerprint: String): Network.Builder {
return addNode(CertSynopsis(fingerprint)) return addNode(Node(fingerprint))
} }
/** /**
* Add a single [Node] built from a [String] fingerprint and [userId] to the builder. * Add a single [Node] built from a [String] fingerprint and [userId] to the builder.
*/ */
fun Network.Builder.addNode(fingerprint: String, userId: String): Network.Builder { fun Network.Builder.addNode(fingerprint: String, userId: String): Network.Builder {
return addNode(CertSynopsis(fingerprint, userId)) return addNode(Node(fingerprint, userId))
} }
/** /**
@ -74,7 +73,7 @@ interface NetworkDSL {
fun Network.Builder.addEdge(issuer: String, target: String): Network.Builder { fun Network.Builder.addEdge(issuer: String, target: String): Network.Builder {
val issuerNode = nodes[Fingerprint(issuer)]!! val issuerNode = nodes[Fingerprint(issuer)]!!
val targetNode = nodes[Fingerprint(target)]!! val targetNode = nodes[Fingerprint(target)]!!
return addEdge(Certification(issuerNode, targetNode)) return addEdge(Edge(issuerNode, targetNode))
} }
/** /**
@ -85,7 +84,7 @@ interface NetworkDSL {
fun Network.Builder.addEdge(issuer: String, target: String, userId: String): Network.Builder { fun Network.Builder.addEdge(issuer: String, target: String, userId: String): Network.Builder {
val issuerNode = nodes[Fingerprint(issuer)]!! val issuerNode = nodes[Fingerprint(issuer)]!!
val targetNode = nodes[Fingerprint(target)]!! val targetNode = nodes[Fingerprint(target)]!!
return addEdge(Certification(issuerNode, targetNode, userId)) return addEdge(Edge(issuerNode, targetNode, userId))
} }
/** /**
@ -93,9 +92,9 @@ interface NetworkDSL {
* a new node for them to the builder. * a new node for them to the builder.
*/ */
fun Network.Builder.buildEdge(issuer: String, target: String): Network.Builder { fun Network.Builder.buildEdge(issuer: String, target: String): Network.Builder {
val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { CertSynopsis(issuer) } val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { Node(issuer) }
val targetNode = nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target) } val targetNode = nodes.getOrPut(Fingerprint(target)) { Node(target) }
return addEdge(Certification(issuerNode, targetNode)) return addEdge(Edge(issuerNode, targetNode))
} }
/** /**
@ -105,51 +104,51 @@ interface NetworkDSL {
* the [userId] inserted. * the [userId] inserted.
*/ */
fun Network.Builder.buildEdge(issuer: String, target: String, userId: String): Network.Builder { fun Network.Builder.buildEdge(issuer: String, target: String, userId: String): Network.Builder {
val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { CertSynopsis(issuer)} val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { Node(issuer)}
val targetNode = CertSynopsis(nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target, userId) }, userId) val targetNode = Node(nodes.getOrPut(Fingerprint(target)) { Node(target, userId) }, userId)
return addEdge(Certification(issuerNode, targetNode, userId)) return addEdge(Edge(issuerNode, targetNode, userId))
} }
fun Network.Builder.buildEdge(issuer: String, target: String, amount: Int, depth: Int): Network.Builder { fun Network.Builder.buildEdge(issuer: String, target: String, amount: Int, depth: Int): Network.Builder {
val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { CertSynopsis(issuer) } val issuerNode = nodes.getOrPut(Fingerprint(issuer)) { Node(issuer) }
val targetNode = nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target) } val targetNode = nodes.getOrPut(Fingerprint(target)) { Node(target) }
return addEdge(Edge(issuerNode, targetNode, null, Date(), null, true, amount, Depth.auto(depth), RegexSet.wildcard())) return addEdge(EdgeComponent(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 { 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 issuerNode = nodes.getOrPut(Fingerprint(issuer)) { Node(issuer) }
val targetNode = nodes.getOrPut(Fingerprint(target)) { CertSynopsis(target) } val targetNode = nodes.getOrPut(Fingerprint(target)) { Node(target) }
return addEdge(Edge(issuerNode, targetNode, null, Date(), null, true, amount, Depth.auto(depth), regexSet)) return addEdge(EdgeComponent(issuerNode, targetNode, null, Date(), null, true, amount, Depth.auto(depth), regexSet))
} }
/** /**
* Set the reference time of the builder to now. * Set the reference time of the builder to now.
*/ */
fun Network.Builder.now(): Network.Builder { fun Network.Builder.now(): Network.Builder {
return setReferenceTime(org.pgpainless.wot.network.ReferenceTime.now()) return setReferenceTime(ReferenceTime.now())
} }
fun Network.getEdgesFor(issuer: Fingerprint, target: Fingerprint): EdgeSet? { fun Network.getEdgesFor(issuer: Fingerprint, target: Fingerprint): Edge? {
return edgeSet[issuer]?.find { it.target.fingerprint == target } return edges[issuer]?.find { it.target.fingerprint == target }
} }
fun Network.getEdgesFor(issuer: String, target: String): EdgeSet? { fun Network.getEdgesFor(issuer: String, target: String): Edge? {
return getEdgesFor(Fingerprint(issuer), Fingerprint(target)) return getEdgesFor(Fingerprint(issuer), Fingerprint(target))
} }
fun Network.getEdgeFor(issuer: Fingerprint, target: Fingerprint): List<Edge>? { fun Network.getEdgeFor(issuer: Fingerprint, target: Fingerprint): List<EdgeComponent>? {
return getEdgeFor(issuer, target, null) return getEdgeFor(issuer, target, null)
} }
fun Network.getEdgeFor(issuer: Fingerprint, target: Fingerprint, userId: String?): List<Edge>? { fun Network.getEdgeFor(issuer: Fingerprint, target: Fingerprint, userId: String?): List<EdgeComponent>? {
return getEdgesFor(issuer, target)?.certifications?.get(userId) return getEdgesFor(issuer, target)?.components?.get(userId)
} }
fun Network.getEdgeFor(issuer: String, target: String): List<Edge>? { fun Network.getEdgeFor(issuer: String, target: String): List<EdgeComponent>? {
return getEdgeFor(issuer, target, null) return getEdgeFor(issuer, target, null)
} }
fun Network.getEdgeFor(issuer: String, target: String, userId: String?): List<Edge>? { fun Network.getEdgeFor(issuer: String, target: String, userId: String?): List<EdgeComponent>? {
return getEdgeFor(Fingerprint(issuer), Fingerprint(target), userId) return getEdgeFor(Fingerprint(issuer), Fingerprint(target), userId)
} }

View file

@ -2,13 +2,11 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.network.Network.Companion.empty import org.pgpainless.wot.network.Network.Companion.empty
import org.pgpainless.wot.network.ReferenceTime.Companion.now import org.pgpainless.wot.network.ReferenceTime.Companion.now
import org.pgpainless.wot.network.RegexSet
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -19,8 +17,8 @@ class NetworkTest: NetworkDSL {
val referenceTime = now() val referenceTime = now()
val network = empty(referenceTime) val network = empty(referenceTime)
assert(network.nodes.isEmpty()) assert(network.nodes.isEmpty())
assert(network.edgeSet.isEmpty()) assert(network.edges.isEmpty())
assert(network.reverseEdgeSet.isEmpty()) assert(network.reverseEdges.isEmpty())
assertEquals(referenceTime, network.referenceTime) assertEquals(referenceTime, network.referenceTime)
assertEquals(0, network.numberOfEdges) assertEquals(0, network.numberOfEdges)
assertEquals(0, network.numberOfSignatures) assertEquals(0, network.numberOfSignatures)
@ -57,7 +55,7 @@ class NetworkTest: NetworkDSL {
buildEdge("A", "C", "Charlie <charlie@example.org>") buildEdge("A", "C", "Charlie <charlie@example.org>")
} }
assertEquals("Network with 3 nodes, 2 edgeSet:\n" + assertEquals("Network with 3 nodes, 2 edges:\n" +
"A certifies binding: null <-> B [120]\n" + "A certifies binding: null <-> B [120]\n" +
"A certifies binding: Charlie <charlie@example.org> <-> C [120]\n", "A certifies binding: Charlie <charlie@example.org> <-> C [120]\n",
network.toString()) network.toString())

View file

@ -2,7 +2,7 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -11,19 +11,19 @@ class NodeTest: NetworkDSL {
@Test @Test
fun `Fingerprint 'A' toString`() { fun `Fingerprint 'A' toString`() {
val node = CertSynopsis("A") val node = Node("A")
assertEquals("A", node.toString()) assertEquals("A", node.toString())
} }
@Test @Test
fun `Fingerprint 'a' toString`() { fun `Fingerprint 'a' toString`() {
val node = CertSynopsis("a") val node = Node("a")
assertEquals("A", node.toString()) assertEquals("A", node.toString())
} }
@Test @Test
fun `Fingerprint 'A' and UserID toString`() { fun `Fingerprint 'A' and UserID toString`() {
val node = CertSynopsis("A", "Alice <alice@example.org>") val node = Node("A", "Alice <alice@example.org>")
assertEquals("A (Alice <alice@example.org>)", node.toString()) assertEquals("A (Alice <alice@example.org>)", node.toString())
} }
} }

View file

@ -1,6 +1,7 @@
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.pgpainless.wot.network.NetworkDSL
import org.pgpainless.wot.network.RegexSet import org.pgpainless.wot.network.RegexSet
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -10,6 +11,26 @@ class RegexSetTest: NetworkDSL {
private val exampleComRegex = "<[^>]+[@.]example\\.com>\$" private val exampleComRegex = "<[^>]+[@.]example\\.com>\$"
private val pgpainlessOrgRegex = "<[^>]+[@.]pgpainless\\.org>\$" private val pgpainlessOrgRegex = "<[^>]+[@.]pgpainless\\.org>\$"
@Test
fun simpleMatch() {
val stringList: List<String> = listOf("<[^>]+[@.]foobank\\.com>$")
val rs = RegexSet.fromExpressionList(stringList);
assert(rs.matches("Foo Bank Employee <employee@foobank.com>"))
assert(rs.matches("<employee@foobank.com>"))
}
@Test
fun simpleNonMatch() {
val stringList: List<String> = listOf("<[^>]+[@.]foobank\\.com>$")
val rs = RegexSet.fromExpressionList(stringList);
assert(!rs.matches("Bar Bank Employee <employee@barbank.com>"))
assert(!rs.matches("<employee@barbank.com>"))
}
@Test @Test
fun `verify that the wildcard RegexSet matches anything`() { fun `verify that the wildcard RegexSet matches anything`() {
val wildcard = RegexSet.wildcard() val wildcard = RegexSet.wildcard()

View file

@ -1,4 +1,4 @@
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.network
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.pgpainless.wot.network.ReferenceTime import org.pgpainless.wot.network.ReferenceTime

View file

@ -2,7 +2,7 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.query
import org.pgpainless.wot.query.Cost import org.pgpainless.wot.query.Cost
import kotlin.test.Test import kotlin.test.Test

View file

@ -1,28 +1,29 @@
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.query
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import org.pgpainless.wot.network.Depth import org.pgpainless.wot.network.Depth
import org.pgpainless.wot.network.Path import org.pgpainless.wot.network.NetworkDSL
import org.pgpainless.wot.query.Path
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertTrue
class PathTest: NetworkDSL { class PathTest: NetworkDSL {
private val root = CertSynopsis("aabbccddeeAABBCCDDEEaabbccddeeAABBCCDDEE") private val root = Node("aabbccddeeAABBCCDDEEaabbccddeeAABBCCDDEE")
private val alice = CertSynopsis("0000000000000000000000000000000000000000") private val alice = Node("0000000000000000000000000000000000000000")
private val bob = CertSynopsis("1111111111111111111111111111111111111111") private val bob = Node("1111111111111111111111111111111111111111")
// Root -(255, 255)-> Alice // Root -(255, 255)-> Alice
private val root_alice__fully_trusted = Certification(root, alice, 255, Depth.unconstrained()) private val root_alice__fully_trusted = Edge(root, alice, 255, Depth.unconstrained())
// Root -(60,0)-> Alice // Root -(60,0)-> Alice
private val root_alice__marginally_trusted = Certification(root, alice, 60, Depth.limited(0)) private val root_alice__marginally_trusted = Edge(root, alice, 60, Depth.limited(0))
// Alice -(255,255)-> Root // Alice -(255,255)-> Root
private val alice_root = Certification(alice, root, 255, Depth.unconstrained()) private val alice_root = Edge(alice, root, 255, Depth.unconstrained())
// Alice -(120, 1)-> Bob // Alice -(120, 1)-> Bob
private val alice_bob = Certification(alice, bob) private val alice_bob = Edge(alice, bob)
// Root -> Root // Root -> Root
private val root_root = Certification(root, root, 120, Depth.limited(1)) private val root_root = Edge(root, root, 120, Depth.limited(1))
@Test @Test
fun `verify that an empty Path is properly initialized`() { fun `verify that an empty Path is properly initialized`() {

View file

@ -1,19 +1,18 @@
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.query
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import org.pgpainless.wot.network.Depth import org.pgpainless.wot.network.Depth
import org.pgpainless.wot.network.Path import org.pgpainless.wot.network.NetworkDSL
import org.pgpainless.wot.network.Paths
import kotlin.test.assertEquals import kotlin.test.assertEquals
class PathsTest: NetworkDSL { class PathsTest: NetworkDSL {
private val alice = CertSynopsis("0000000000000000000000000000000000000000") private val alice = Node("0000000000000000000000000000000000000000")
private val bob = CertSynopsis("1111111111111111111111111111111111111111") private val bob = Node("1111111111111111111111111111111111111111")
private val alice_bob_1 = Certification(alice, bob, 140, Depth.unconstrained()) private val alice_bob_1 = Edge(alice, bob, 140, Depth.unconstrained())
private val alice_bob_2 = Certification(alice, bob, 160, Depth.limited(1)) private val alice_bob_2 = Edge(alice, bob, 160, Depth.limited(1))
@Test @Test
fun `verify that an empty Paths object has an amount of zero`() { fun `verify that an empty Paths object has an amount of zero`() {

View file

@ -1,6 +1,5 @@
package org.pgpainless.wot.dijkstra package org.pgpainless.wot.query
import org.pgpainless.wot.query.PairPriorityQueue
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals