495 lines
38 KiB
HTML
495 lines
38 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
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
005 1. `nil` if no faults were found;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
006 2. a sequence of fault objects if faults were found.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
007
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
008 Each fault object shall have the properties:
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
009
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
010 1. `:@context` whose value shall be the URL of a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
011 document specifying this vocabulary;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
012 2. `:type` whose value shall be `Fault`;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
013 3. `:severity` whose value shall be one of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
014 `minor`, `should`, `must` or `critical`;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
015 4. `:fault` whose value shall be a unique token
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
016 representing the particular fault type;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
017 5. `:narrative` whose value shall be a natural
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
018 language description of the fault type.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
019
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
020 Note that the reason for the `:fault` property is
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
021 to be able to have a well known place, linked to
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
022 from the @context URL, which allows narratives
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
023 for each fault type to be served in as many
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
024 natural languages as possible.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
025
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
026 The idea further is that it should ultimately be
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
027 possible to serialise a fault report as a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
028 document which in its own right conforms to the
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
029 ActivityStreams spec."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
030 (:require [dog-and-duck.quack.fault-messages :refer [messages]]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
031 [dog-and-duck.utils.process :refer [pid]])
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
032 (:import [java.net URI URISyntaxException]))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
033
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
034 (def ^:const severity
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
035 "Severity of faults found, as follows:
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
036
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
037 1. `:minor` things which I consider to be faults, but which
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
038 don't actually breach the spec;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
039 2. `:should` instances where the spec says something SHOULD
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
040 be done, which isn't;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
041 3. `:must` instances where the spec says something MUST
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
042 be done, which isn't;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
043 4. `:critical` instances where I believe the fault means that
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
044 the object cannot be meaningfully processed."
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
045 #{:minor :should :must :critical})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
046
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
047 (def ^:const severity-filters
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
048 "Hack for implementing a severity hierarchy"
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
049 {:all #{}
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
050 :minor #{:minor}
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
051 :should #{:minor :should}
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
052 :must #{:minor :should :must}
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
053 :critical severity})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
054
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
055 (defn filter-severity
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
056 "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">
|
|
057 of the report is greater than this `severity`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
058 [reports severity]
|
|
</span><br/>
|
|
<span class="partial" title="2 out of 11 forms covered">
|
|
059 (assert
|
|
</span><br/>
|
|
<span class="partial" title="8 out of 10 forms covered">
|
|
060 (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
061 (coll? reports)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
062 (every? map? reports)
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
063 (every? :severity reports)))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
064 (remove
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
065 #((severity-filters severity) (:severity %))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
066 reports))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
067
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
068 (def ^:const activitystreams-context-uri
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
069 "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">
|
|
070 literal string."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
071 "https://www.w3.org/ns/activitystreams")
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
072
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
073 (def ^:const validation-fault-context-uri
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
074 "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">
|
|
075 literal string."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
076 "https://simon-brooke.github.io/dog-and-duck/codox/Validation_Faults.html")
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
077
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
078 (defn context?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
079 "Returns `true` iff `x` quacks like an ActivityStreams context, else false.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
080
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
081 A context is either
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
082 1. the URI (actually an IRI) `activitystreams-context-uri`, or
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
083 2. a collection comprising that URI and a map."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
084 [x]
|
|
</span><br/>
|
|
<span class="partial" title="4 out of 6 forms covered">
|
|
085 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
086 (nil? x) false
|
|
</span><br/>
|
|
<span class="covered" title="11 out of 11 forms covered">
|
|
087 (string? x) (and (= x activitystreams-context-uri) true)
|
|
</span><br/>
|
|
<span class="partial" title="19 out of 20 forms covered">
|
|
088 (coll? x) (and (context? (first (remove map? x)))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
089 (= (count x) 2)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
090 true)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
091 :else false))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
092
|
|
</span><br/>
|
|
<span class="covered" title="40 out of 40 forms covered">
|
|
093 (defmacro has-context?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
094 "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">
|
|
095 [x]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
096 `(context? ((keyword "@context") ~x)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
097
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
098 (defn make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
099 "Return a fault object with these `severity`, `fault` and `narrative` values.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
100
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
101 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">
|
|
102 meaningful depends on whether we persist fault report objects and serve
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
103 them, which at present I have no plans to do."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
104 ;; TODO: should not pass in the narrative; instead should use the :fault value
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
105 ;; to look up the narrative in a resource file.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
106 [severity fault]
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
107 (assoc {}
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
108 (keyword "@context") validation-fault-context-uri
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
109 :id (str "https://"
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
110 (.. java.net.InetAddress getLocalHost getHostName)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
111 "/fault/"
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
112 pid
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
113 ":"
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
114 (inst-ms (java.util.Date.)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
115 :type "Fault"
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
116 :severity severity
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
117 :fault fault
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
118 :narrative (messages fault)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
119
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
120 (defn object-faults
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
121 "Return a list of faults found in object `x`, or `nil` if none are."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
122 [x]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
123 (let [faults (remove
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
124 empty?
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
125 (list
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
126 (when-not (map? x)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
127 (make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
128 :critical
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
129 :not-an-object))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
130 (when-not
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
131 (has-context? x)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
132 (make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
133 :should
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
134 :no-context))
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
135 (when-not (:type x)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 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-type))
|
|
</span><br/>
|
|
<span class="covered" title="14 out of 14 forms covered">
|
|
139 (when-not (and (map? x) (contains? x :id))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
140 (make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
141 :minor
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
142 :no-id-transient))))]
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
143 (if (empty? faults) nil faults)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
144
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
145 (defn persistent-object-faults
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
146 "Return a list of faults found in persistent object `x`, or `nil` if none are."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
147 [x]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
148 (let [faults (concat
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
149 (object-faults x)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
150 (remove empty?
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
151 (list
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
152 (if (contains? x :id)
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
153 (try (let [id (URI. (:id x))]
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
154 (when-not (= (.getScheme id) "https")
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
155 (make-fault-object :should :id-not-https)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
156 (catch URISyntaxException _
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
157 (make-fault-object :must :id-not-uri))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
158 (catch NullPointerException _
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
159 (make-fault-object :must :null-id-persistent)))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
160 (make-fault-object :must :no-id-persistent)))))]
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
161 (if (empty? faults) nil faults)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
162
|
|
</span><br/>
|
|
</body>
|
|
</html>
|