diff --git a/src/smeagol/formatting.clj b/src/smeagol/formatting.clj index 6a874c8..814d634 100644 --- a/src/smeagol/formatting.clj +++ b/src/smeagol/formatting.clj @@ -6,6 +6,7 @@ [cemerick.url :refer (url url-encode url-decode)] [clj-yaml.core :as yaml] [markdown.core :as md] + [smeagol.test :as test] [smeagol.configuration :refer [config]])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -100,6 +101,12 @@ (str "
```" (.trim text) "\n```")) +(defn process-test + "Takes at least 3 lines assuming first is a fn name, last is output, rest inside are arguments" + [^String text ^Integer index] + (test/process text index)) + + (defn get-first-token "Return the first space-separated token of this `string`." [^String string] diff --git a/src/smeagol/sample.clj b/src/smeagol/sample.clj new file mode 100644 index 0000000..2ad8b71 --- /dev/null +++ b/src/smeagol/sample.clj @@ -0,0 +1,4 @@ +(ns smeagol.sample) + +(defn pow [x] + (int (Math/pow x 2))) diff --git a/src/smeagol/test.clj b/src/smeagol/test.clj new file mode 100644 index 0000000..0a288d2 --- /dev/null +++ b/src/smeagol/test.clj @@ -0,0 +1,58 @@ +(ns smeagol.test + (:require [clojure.string :as s] + [clojure.edn :as edn])) + +(defn- execute [{:keys [fn in]}] + (try (let [result (apply fn in)] + {:result result}) + (catch Exception e + {:error (.getMessage e)}))) + +(defn do-test [{:keys [fn in out] :as params}] + (let [{:keys [error result]} (execute params)] + (if error + {:result :error :error error} + (if (= result out) + {:result :ok} + {:result :failure :expected out :actual result})))) + +(defn- parse-value [^String line] + (try + (let [value (edn/read-string line)] + {:line line :value value}) + (catch Exception e + {:line line :error (.getMessage e)}))) + + +(defn- parse-values [texts] + (reduce (fn [acc text] + (let [{:keys [value error] :as parsed} (parse-value text)] + (if error + (reduced parsed) + (update-in acc [:values] conj value)))) + {:values []} + texts)) + + +(defn parse [^String text] + (let [lines (s/split-lines text)] + (if (-> lines count (>= 3)) + (let [[sym & rest] lines] + (if-let [fn (-> sym s/trim symbol resolve)] ;; TODO: require ns + (let [{:keys [values error line] :as x} (parse-values rest)] + (if error + {:error (str "Failed parsing line: " line " due: " error)} + (let [out (last values) + in (butlast values)] + {:fn fn :out out :in in :text text}))) + {:error (str "No test found with name: " (pr-str sym)) :text text})) + {:error (str "There shoud be at least 3 lines (test name, input, output), given: " (count lines)) + :text text}))) + + +(defn process [^String text ^Integer index] + (let [{:keys [error] :as params} (parse text)] + (if error + (str "
" (pr-str params) "
" text "") + (let [{:keys [result] :as test-result} (do-test params)] + (str "
" (pr-str test-result) "
" text "")))))