|
1 | 1 | (ns org.ajoberstar.jovial.engine |
2 | 2 | (:refer-clojure :exclude [descriptor]) |
3 | | - (:require [clojure.main :as main] |
4 | | - [clojure.set :as set] |
5 | | - [clojure.string :as string]) |
6 | | - (:import [org.ajoberstar.jovial ClojureNamespaceDescriptor ClojureVarDescriptor] |
| 3 | + (:require [clojure.java.io :as io] |
| 4 | + [clojure.main :as main] |
| 5 | + [clojure.string :as string] |
| 6 | + [clojure.tools.namespace.file :as ns-file] |
| 7 | + [clojure.tools.namespace.find :as ns-find] |
| 8 | + [clojure.tools.namespace.parse :as ns-parse]) |
| 9 | + (:import [java.io File] |
| 10 | + [java.nio.file Paths] |
| 11 | + [org.ajoberstar.jovial ClojureNamespaceDescriptor ClojureVarDescriptor] |
7 | 12 | [org.junit.platform.engine |
8 | 13 | DiscoverySelector EngineDiscoveryListener EngineDiscoveryRequest ExecutionRequest |
9 | 14 | SelectorResolutionResult TestTag UniqueId UniqueId$Segment] |
10 | 15 | [org.junit.platform.engine.discovery |
11 | | - UniqueIdSelector FileSelector |
12 | | - ClasspathResourceSelector ClasspathRootSelector ClassSelector] |
| 16 | + ClasspathResourceSelector ClasspathRootSelector ClassSelector UniqueIdSelector] |
13 | 17 | [org.junit.platform.engine.support.descriptor |
14 | | - EngineDescriptor ClasspathResourceSource ClassSource FileSource])) |
| 18 | + EngineDescriptor ClasspathResourceSource ClassSource])) |
15 | 19 |
|
16 | 20 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
17 | 21 | ;; Specification of an Engine |
|
48 | 52 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
49 | 53 | ;; Discovery Selector Support |
50 | 54 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
51 | | -(def ^:dynamic *all-vars* nil) |
52 | | - |
53 | | -(defn all-vars [] |
54 | | - (let [fqsym (fn [namespace] |
55 | | - (fn [[sym _]] (symbol (name (ns-name namespace)) (name sym)))) |
56 | | - nssyms (fn [namespace] |
57 | | - (map (fqsym namespace) (ns-publics namespace)))] |
58 | | - (into #{} (mapcat nssyms) (all-ns)))) |
59 | | - |
60 | 55 | (defrecord TestCandidate [source sym]) |
61 | 56 |
|
62 | | -(defn select-new-vars [source loader] |
63 | | - (let [before @*all-vars*] |
64 | | - (try |
65 | | - (loader) |
66 | | - (let [after (reset! *all-vars* (all-vars)) |
67 | | - loaded-vars (set/difference after before)] |
68 | | - (map #(->TestCandidate source %) loaded-vars)) |
69 | | - (catch Exception e |
70 | | - (println "Failure loading source" source ": " (-> e Throwable->map main/ex-triage main/ex-str)) |
71 | | - nil)))) |
| 57 | +(defn ns-vars [ns] |
| 58 | + (let [ns-str (name (ns-name ns))] |
| 59 | + (map (fn [[sym _]] |
| 60 | + (symbol ns-str (name sym))) |
| 61 | + (ns-publics ns)))) |
| 62 | + |
| 63 | +(defn select-new-vars [source ns-sym] |
| 64 | + (try |
| 65 | + (require ns-sym) |
| 66 | + (map #(->TestCandidate source %) (ns-vars (find-ns ns-sym))) |
| 67 | + (catch Exception e |
| 68 | + (println "Failure loading source" source ": " (-> e Throwable->map main/ex-triage main/ex-str)) |
| 69 | + nil))) |
72 | 70 |
|
73 | 71 | (defprotocol Selector |
74 | 72 | (-select [this] |
|
77 | 75 | (extend-protocol Selector |
78 | 76 | UniqueIdSelector |
79 | 77 | (-select [this] |
80 | | - (let [{:keys [namespace name]} (id->map (.getUniqueId this))] |
81 | | - (when (and namespace name) |
82 | | - (->TestCandidate nil (symbol namespace name))))) |
| 78 | + (let [{:keys [namespace name]} (id->map (.getUniqueId this)) |
| 79 | + ns-sym (symbol namespace) |
| 80 | + var-sym (when name (symbol namespace name)) |
| 81 | + result (select-new-vars nil ns-sym)] |
| 82 | + (if var-sym |
| 83 | + (filter #(= var-sym (:sym %)) result) |
| 84 | + result))) |
83 | 85 |
|
84 | | - FileSelector |
85 | | - (-select [this] |
86 | | - (let [path (str (.getPath this)) |
87 | | - source (FileSource/from (.getFile this))] |
88 | | - (println "File selector path:" path) |
89 | | - (println "File selector source:" source) |
90 | | - (when (or (string/ends-with? path ".clj") |
91 | | - (string/ends-with? path ".cljc")) |
92 | | - (println "Loading file") |
93 | | - (select-new-vars source (fn [] (load-file path)))))) |
94 | | - |
95 | | - ClasspathResourceSelector |
96 | | - (-select [this] |
97 | | - (let [name (.getClasspathResourceName this) |
98 | | - source (ClasspathResourceSource/from name)] |
99 | | - (when (or (string/ends-with? name ".clj") |
100 | | - (string/ends-with? name ".cljc")) |
101 | | - (select-new-vars source (fn [] (load name)))))) |
102 | 86 | ClassSelector |
103 | 87 | (-select [this] |
104 | 88 | (let [name (.getClassName this) |
|
108 | 92 | ns-sym (symbol ns-name) |
109 | 93 | source (ClassSource/from name)] |
110 | 94 | (when (string/ends-with? name "__init") |
111 | | - (select-new-vars source (fn [] (require ns-sym))))))) |
| 95 | + (select-new-vars source ns-sym)))) |
| 96 | + |
| 97 | + ClasspathResourceSelector |
| 98 | + (-select [this] |
| 99 | + (let [name (.getClasspathResourceName this) |
| 100 | + url (io/resource name) |
| 101 | + ns-decl (ns-file/read-file-ns-decl url) |
| 102 | + ns-sym (ns-parse/name-from-ns-decl ns-decl) |
| 103 | + source (ClasspathResourceSource/from name)] |
| 104 | + (select-new-vars source ns-sym))) |
| 105 | + |
| 106 | + ClasspathRootSelector |
| 107 | + (-select [this] |
| 108 | + (let [uri (.getClasspathRoot this) |
| 109 | + path (Paths/get uri)] |
| 110 | + (mapcat (fn [source] |
| 111 | + (let [ns-decl (ns-file/read-file-ns-decl source) |
| 112 | + ns-sym (ns-parse/name-from-ns-decl ns-decl) |
| 113 | + rel-path (.relativize path (.toPath ^File source)) |
| 114 | + source (ClasspathResourceSource/from (str "/" rel-path))] |
| 115 | + (select-new-vars source ns-sym))) |
| 116 | + (ns-find/find-sources-in-dir (.toFile path)))))) |
112 | 117 |
|
113 | 118 | (defn try-select [^EngineDiscoveryListener listener id selector] |
114 | | - (println "Evaluating selector:" selector) |
115 | 119 | (if (satisfies? Selector selector) |
116 | 120 | (try |
117 | 121 | (let [result (-select selector)] |
118 | | - (println "Resolved selector:" selector) |
119 | 122 | (.selectorProcessed listener id selector (SelectorResolutionResult/resolved)) |
120 | 123 | result) |
121 | 124 | (catch Exception e |
122 | | - (println "Failed selector:" selector) |
123 | 125 | (.selectorProcessed listener id selector (SelectorResolutionResult/failed e)))) |
124 | | - (do |
125 | | - (println "Unresolved selector:" selector) |
126 | | - (.selectorProcessed listener id selector (SelectorResolutionResult/unresolved))))) |
| 126 | + (.selectorProcessed listener id selector (SelectorResolutionResult/unresolved)))) |
127 | 127 |
|
128 | 128 | (defn select [^EngineDiscoveryRequest request ^UniqueId id] |
129 | | - (binding [*all-vars* (atom (all-vars))] |
130 | | - (let [listener (.getDiscoveryListener request) |
131 | | - selectors (.getSelectorsByType request DiscoverySelector)] |
132 | | - (loop [result [] |
133 | | - head (first selectors) |
134 | | - tail (rest selectors)] |
135 | | - (let [candidates (try-select listener id head)] |
136 | | - (if tail |
137 | | - (recur (concat result candidates) (first tail) (rest tail)) |
138 | | - (concat result candidates))))))) |
| 129 | + (let [listener (.getDiscoveryListener request) |
| 130 | + selectors (.getSelectorsByType request DiscoverySelector)] |
| 131 | + (loop [result [] |
| 132 | + head (first selectors) |
| 133 | + tail (rest selectors)] |
| 134 | + (let [candidates (try-select listener id head)] |
| 135 | + (if (seq tail) |
| 136 | + (recur (concat result candidates) (first tail) (rest tail)) |
| 137 | + (concat result candidates)))))) |
139 | 138 |
|
140 | 139 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
141 | 140 | ;; Discovery Descriptor Support |
|
145 | 144 | var (find-var sym)] |
146 | 145 | (ClojureVarDescriptor. var-id var source (tags var)))) |
147 | 146 |
|
148 | | -(defn- ns->descriptor [^UniqueId parent-id [ns-sym candidates]] |
149 | | - (let [ns-id (.append parent-id "namespace" (name ns-sym)) |
| 147 | +(defn- ns->descriptor [^UniqueId parent-id [ns-str candidates]] |
| 148 | + (let [ns-id (.append parent-id "namespace" ns-str) |
150 | 149 | source (->> candidates |
151 | 150 | (group-by :source) |
152 | 151 | (apply max-key second) |
153 | 152 | first) |
154 | | - ns (find-ns ns-sym) |
| 153 | + ns (find-ns (symbol ns-str)) |
155 | 154 | ns-desc (ClojureNamespaceDescriptor. ns-id ns source (tags ns))] |
156 | 155 | (doseq [var-desc (map #(var->descriptor ns-id %) candidates)] |
157 | 156 | (.addChild ns-desc var-desc)) |
|
161 | 160 | (let [engine-desc (EngineDescriptor. root-id (id engine)) |
162 | 161 | ns-descs (->> candidates |
163 | 162 | (group-by (comp namespace :sym)) |
164 | | - (map #(ns->descriptor id %)))] |
| 163 | + (map #(ns->descriptor root-id %)))] |
165 | 164 | (doseq [ns-desc ns-descs] |
166 | 165 | (.addChild engine-desc ns-desc)) |
167 | 166 | engine-desc)) |
0 commit comments