From dd57413d27491965d940b1cdacc60b3e7951eaea Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Thu, 15 Oct 2020 10:55:22 +0200 Subject: [PATCH] [#2] Tests --- script/test | 12 ++- src/babashka/pods/impl.clj | 15 ++-- test-pod/pod/test_pod.clj | 137 ++++++++++++++++++-------------- test-resources/test_program.clj | 6 +- 4 files changed, 102 insertions(+), 68 deletions(-) diff --git a/script/test b/script/test index e50850e..bf2bad3 100755 --- a/script/test +++ b/script/test @@ -1,11 +1,21 @@ #!/usr/bin/env bash +export BABASHKA_POD_TEST_FORMAT +export BABASHKA_POD_TEST_SOCKET + # format = edn +BABASHKA_POD_TEST_FORMAT=edn clojure -A:test -n babashka.pods.jvm-test clojure -A:sci:test -n babashka.pods.sci-test # format = json -export BABASHKA_POD_TEST_FORMAT BABASHKA_POD_TEST_FORMAT=json clojure -A:test -n babashka.pods.jvm-test clojure -A:sci:test -n babashka.pods.sci-test + +# socket = true +unset BABASHKA_POD_TEST_FORMAT +BABASHKA_POD_TEST_SOCKET=true +clojure -A:test -n babashka.pods.jvm-test +clojure -A:sci:test -n babashka.pods.sci-test + diff --git a/src/babashka/pods/impl.clj b/src/babashka/pods/impl.clj index 422bfe8..dd85394 100644 --- a/src/babashka/pods/impl.clj +++ b/src/babashka/pods/impl.clj @@ -242,11 +242,12 @@ (.inheritIO pb) (.redirectError pb java.lang.ProcessBuilder$Redirect/INHERIT)) _ (doto (.environment pb) - (.put "BABASHKA_POD" "true")) + (.put "BABASHKA_POD" "true") + (.put "BABASHKA_POD_SOCKET" (some-> socket str))) p (.start pb) port-file (when socket (port-file (.pid p))) socket-port (when socket (read-port port-file)) - [stdin stdout] + [socket stdin stdout] (if socket (let [^Socket socket (loop [] @@ -255,9 +256,10 @@ nil))] sock (recur)))] - [(.getOutputStream socket) + [socket + (.getOutputStream socket) (PushbackInputStream. (.getInputStream socket))]) - [(.getOutputStream p) (java.io.PushbackInputStream. (.getInputStream p))]) + [nil (.getOutputStream p) (java.io.PushbackInputStream. (.getInputStream p))]) _ (write stdin {"op" "describe" "id" (next-id)}) reply (read stdout) @@ -276,7 +278,10 @@ :err *err* :remove-ns remove-ns :readers readers} - _ (add-shutdown-hook! #(destroy pod)) + _ (add-shutdown-hook! #(do + (when socket + (close-socket socket)) + (destroy pod))) pod-namespaces (get reply "namespaces") pod-id (or (when-let [ns (first pod-namespaces)] (get-string ns "name")) diff --git a/test-pod/pod/test_pod.clj b/test-pod/pod/test_pod.clj index 5bb84d5..b813444 100644 --- a/test-pod/pod/test_pod.clj +++ b/test-pod/pod/test_pod.clj @@ -4,7 +4,8 @@ [cheshire.core :as cheshire] [clojure.edn :as edn] [clojure.java.io :as io]) - (:import [java.io PushbackInputStream]) + (:import [java.io PushbackInputStream] + [java.net ServerSocket]) (:gen-class)) (def debug? false) @@ -14,17 +15,15 @@ (binding [*out* (io/writer "/tmp/log.txt" :append true)] (apply println args)))) -(def stdin (PushbackInputStream. System/in)) - -(defn write [v] - (bencode/write-bencode System/out v) - (.flush System/out)) +(defn write [stream v] + (bencode/write-bencode stream v) + (flush)) (defn read-string [^"[B" v] (String. v)) -(defn read [] - (bencode/read-bencode stdin)) +(defn read [stream] + (bencode/read-bencode stream)) (def dependents (for [i (range 10)] @@ -43,10 +42,26 @@ pr-str) read-fn (if (identical? :json format) #(cheshire/parse-string % true) - edn/read-string)] + edn/read-string) + socket (= "true" (System/getenv "BABASHKA_POD_SOCKET")) + [in out] (if socket + (let [server (ServerSocket. 0) + port (.getLocalPort server) + pid (.pid (java.lang.ProcessHandle/current)) + port-file (io/file (str ".babashka-pod-" pid ".port")) + _ (.addShutdownHook (Runtime/getRuntime) + (Thread. (fn [] (.delete port-file)))) + _ (spit port-file + (str port "\n")) + socket (.accept server) + in (PushbackInputStream. (.getInputStream socket)) + out (.getOutputStream socket)] + [in out]) + [(PushbackInputStream. System/in) + System/out])] (try (loop [] - (let [message (try (read) + (let [message (try (read in) (catch java.io.EOFException _ ::EOF))] (when-not (identical? ::EOF message) @@ -55,42 +70,42 @@ op (keyword op)] (case op :describe - (do (write {"format" (if (= format :json) - "json" - "edn") - "readers" {"my/tag" "identity" - ;; NOTE: this function is defined later, - ;; which should be supported - "my/other-tag" "pod.test-pod/read-other-tag"} - "namespaces" - [{"name" "pod.test-pod" - "vars" (into [{"name" "add-sync"} - {"name" "range-stream" - "async" "true"} - {"name" "assoc"} - {"name" "error"} - {"name" "print"} - {"name" "print-err"} - {"name" "return-nil"} - {"name" "do-twice" - "code" "(defmacro do-twice [x] `(do ~x ~x))"} - {"name" "fn-call" - "code" "(defn fn-call [f x] (f x))"} - {"name" "reader-tag"} - ;; returns thing with other tag - {"name" "other-tag"} - ;; reads thing with other tag - {"name" "read-other-tag" - "code" "(defn read-other-tag [x] [x x])"}] - dependents)} - {"name" "pod.test-pod.loaded" - "defer" "true"} - {"name" "pod.test-pod.loaded2" - "defer" "true"} - {"name" "pod.test-pod.only-code" - "vars" [{"name" "foo" - "code" "(defn foo [] 1)"}]}] - "ops" {"shutdown" {}}}) + (do (write out {"format" (if (= format :json) + "json" + "edn") + "readers" {"my/tag" "identity" + ;; NOTE: this function is defined later, + ;; which should be supported + "my/other-tag" "pod.test-pod/read-other-tag"} + "namespaces" + [{"name" "pod.test-pod" + "vars" (into [{"name" "add-sync"} + {"name" "range-stream" + "async" "true"} + {"name" "assoc"} + {"name" "error"} + {"name" "print"} + {"name" "print-err"} + {"name" "return-nil"} + {"name" "do-twice" + "code" "(defmacro do-twice [x] `(do ~x ~x))"} + {"name" "fn-call" + "code" "(defn fn-call [f x] (f x))"} + {"name" "reader-tag"} + ;; returns thing with other tag + {"name" "other-tag"} + ;; reads thing with other tag + {"name" "read-other-tag" + "code" "(defn read-other-tag [x] [x x])"}] + dependents)} + {"name" "pod.test-pod.loaded" + "defer" "true"} + {"name" "pod.test-pod.loaded2" + "defer" "true"} + {"name" "pod.test-pod.only-code" + "vars" [{"name" "foo" + "code" "(defn foo [] 1)"}]}] + "ops" {"shutdown" {}}}) (recur)) :invoke (let [var (-> (get message "var") read-string @@ -104,12 +119,12 @@ (case var pod.test-pod/add-sync (try (let [ret (apply + args)] - (write + (write out {"value" (write-fn ret) "id" id "status" ["done"]})) (catch Exception e - (write + (write out {"ex-data" (write-fn {:args args}) "ex-message" (.getMessage e) "status" ["done" "error"] @@ -117,50 +132,50 @@ pod.test-pod/range-stream (let [rng (apply range args)] (doseq [v rng] - (write + (write out {"value" (write-fn v) "id" id}) (Thread/sleep 100)) - (write + (write out {"status" ["done"] "id" id})) pod.test-pod/assoc - (write + (write out {"value" (write-fn (apply assoc args)) "status" ["done"] "id" id}) pod.test-pod/error - (write + (write out {"ex-data" (write-fn {:args args}) "ex-message" (str "Illegal arguments") "status" ["done" "error"] "id" id}) pod.test-pod/print - (do (write + (do (write out {"out" (pr-str args) "id" id}) - (write + (write out {"status" ["done"] "id" id})) pod.test-pod/print-err - (do (write + (do (write out {"err" (pr-str args) "id" id}) - (write + (write out {"status" ["done"] "id" id})) pod.test-pod/return-nil - (write + (write out {"status" ["done"] "id" id "value" (write-fn nil)}) pod.test-pod/reader-tag - (write + (write out {"status" ["done"] "id" id "value" "#my/tag[1 2 3]"}) pod.test-pod/other-tag - (write + (write out {"status" ["done"] "id" id "value" "#my/other-tag[1]"})) @@ -173,14 +188,14 @@ read-string)] (case ns pod.test-pod.loaded - (write + (write out {"status" ["done"] "id" id "name" "pod.test-pod.loaded" "vars" [{"name" "loaded" "code" "(defn loaded [x] (inc x))"}]}) pod.test-pod.loaded2 - (write + (write out {"status" ["done"] "id" id "name" "pod.test-pod.loaded2" diff --git a/test-resources/test_program.clj b/test-resources/test_program.clj index a6a534f..938edd7 100644 --- a/test-resources/test_program.clj +++ b/test-resources/test_program.clj @@ -3,8 +3,12 @@ (def fmt (or (System/getenv "BABASHKA_POD_TEST_FORMAT") "edn")) +(def socket (System/getenv "BABASHKA_POD_TEST_SOCKET")) + (def pod-id (:pod/id (pods/load-pod (cond-> ["clojure" "-A:test-pod"] - (= "json" fmt) (conj "--json"))))) + (= "json" fmt) (conj "--json")) + {:socket (boolean socket)}))) + (require '[pod.test-pod :as pod]) (def pod-ns-name (ns-name (find-ns 'pod.test-pod)))