438 lines
31 KiB
HTML
438 lines
31 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<link rel="stylesheet" href="../../coverage.css"/> <title> dog_and_duck/quack/picky.clj </title>
|
|
</head>
|
|
<body>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
001 (ns dog-and-duck.quack.picky "Fault-finder for ActivityPub documents.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
002
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
003 Generally, each `-faults` function will return:
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
004 1. `nil` if no faults were found;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
005 2. a sequence of fault objects if faults were found.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
006
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
007 Each fault object shall have the properties:
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
008 1. `:@context` whose value shall be the URL of a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
009 document specifying this vocabulary;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
010 2. `:type` whose value shall be `Fault`;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
011 3. `:severity` whose value shall be one of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
012 `minor`, `should`, `must` or `critical`;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
013 4. `:fault` whose value shall be a unique token
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
014 representing the particular fault type;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
015 5. `:narrative` whose value shall be a natural
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
016 language description of the fault type.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
017
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
018 Note that the reason for the `:fault` property is
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
019 to be able to have a well known place, linked to
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
020 from the @context URL, which allows narratives
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
021 for each fault type to be served in as many
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
022 natural languages as possible.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
023
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
024 The idea further is that it should ultimately be
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
025 possible to serialise a fault report as a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
026 document which in its own right conforms to the
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
027 ActivityStreams spec."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
028 (:require [dog-and-duck.utils.process :refer [pid]]))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
029
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
030 (def ^:const severity
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
031 "Severity of faults found, as follows:
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
032
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
033 1. `:minor` things which I consider to be faults, but which
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
034 don't actually breach the spec;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
035 2. `:should` instances where the spec says something SHOULD
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
036 be done, which isn't;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
037 3. `:must` instances where the spec says something MUST
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
038 be done, which isn't;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
039 4. `:critical` instances where I believe the fault means that
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
040 the object cannot be meaningfully processed."
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
041 #{:minor :should :must :critical})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
042
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
043 (def ^:const severity-filters
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
044 "Hack for implementing a severity hierarchy"
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
045 {:all #{}
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
046 :minor #{:minor}
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
047 :should #{:minor :should}
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
048 :must #{:minor :should :must}
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
049 :critical severity})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
050
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
051 (defn filter-severity
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
052 "Return a list of reports taken from these `reports` where the severity
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
053 of the report is greater than this `severity`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
054 [reports severity]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 11 forms covered">
|
|
055 (assert
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 10 forms covered">
|
|
056 (and
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
057 (coll? reports)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
058 (every? map? reports)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
059 (every? :severity reports)))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
060 (remove
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 7 forms covered">
|
|
061 #((severity-filters severity) (:severity %))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
062 reports))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
063
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
064 (def ^:const activitystreams-context-uri
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
065 "The URI of the context of an ActivityStreams object is expected to be this
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
066 literal string."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
067 "https://www.w3.org/ns/activitystreams")
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
068
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
069 (def ^:const validation-fault-context-uri
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
070 "The URI of the context of a validation fault report object shall be this
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
071 literal string."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
072 "https://simon-brooke.github.io/dog-and-duck/codox/Validation_Faults.html")
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
073
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
074 (defn context?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
075 "Returns `true` iff `x` quacks like an ActivityStreams context, else false.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
076
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
077 A context is either
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
078 1. the URI (actually an IRI) `activitystreams-context-uri`, or
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
079 2. a collection comprising that URI and a map."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
080 [x]
|
|
</span><br/>
|
|
<span class="partial" title="4 out of 6 forms covered">
|
|
081 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
082 (nil? x) false
|
|
</span><br/>
|
|
<span class="covered" title="11 out of 11 forms covered">
|
|
083 (string? x) (and (= x activitystreams-context-uri) true)
|
|
</span><br/>
|
|
<span class="partial" title="19 out of 20 forms covered">
|
|
084 (coll? x) (and (context? (first (remove map? x)))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
085 (= (count x) 2)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
086 true)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
087 :else false))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
088
|
|
</span><br/>
|
|
<span class="partial" title="38 out of 40 forms covered">
|
|
089 (defmacro has-context?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
090 "True if `x` is an ActivityStreams object with a valid context, else `false`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
091 [x]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
092 `(context? ((keyword "@context") ~x)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
093
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
094
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
095
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
096 (defn make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
097 "Return a fault object with these `severity`, `fault` and `narrative` values.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
098
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
099 An ActivityPub object MUST have a globally unique ID. Whether this is
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
100 meaningful depends on whether we persist fault report objects and serve
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
101 them, which at present I have no plans to do."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
102 [severity fault narrative]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 9 forms covered">
|
|
103 (assoc {}
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
104 (keyword "@context") validation-fault-context-uri
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
105 :id (str "https://"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
106 (.. java.net.InetAddress getLocalHost getHostName)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
107 "/fault/"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
108 pid
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
109 ":"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
110 (inst-ms (java.util.Date.)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
111 :type "Fault"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
112 :severity severity
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
113 :fault fault
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
114 :narrative narrative))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
115
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
116 (defn object-faults
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
117 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
118 (remove
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
119 empty?
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
120 (list
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
121 (when-not
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
122 (has-context? x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
123 (make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
124 :should
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
125 :no-context
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
126 "Section 3 of the ActivityPub specification states
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
127 `Implementers SHOULD include the ActivityPub context in
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
128 their object definitions`.")
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 6 forms covered">
|
|
129 (when-not (:type x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
130 (make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
131 :minor
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
132 :no-type
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
133 "The ActivityPub specification states that the `type` field is
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
134 optional, but it is hard to process objects with no known type."))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 7 forms covered">
|
|
135 (when-not (contains? x :id)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
136 (make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
137 :minor
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
138 :no-id-transient
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
139 "The ActivityPub specification allows objects without `id` fields
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
140 only if they are intentionally transient; even so it is preferred
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
141 that the object should have an explicit null id."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
142 ))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
143 ))))
|
|
</span><br/>
|
|
</body>
|
|
</html>
|