diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..c711408 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,35 @@ +version: 2 +jobs: + build: + working_directory: ~/tensor + environment: + CIRCLE_ARTIFACTS: /tmp/circleci-artifacts + CIRCLE_TEST_REPORTS: /tmp/circleci-test-results + docker: + - image: circleci/clojure:lein-2.8.1 + environment: + LEIN_ROOT: nbd + JVM_OPTS: -Xmx3200m + steps: + - checkout + - run: mkdir -p {{ .Environment.CIRCLE_ARTIFACTS }} {{ .Environment.CIRCLE_TEST_REPORTS }} + - restore_cache: + key: tensor-{{ checksum "project.clj" }} + - run: lein deps + - save_cache: + paths: + - ~/.m2 + key: tensor-{{ checksum "project.clj" }} + - run: |- + lein trampoline test + lein do cloverage -o ${CIRCLE_ARTIFACTS} --coveralls, coveralls ${CIRCLE_ARTIFACTS}/coveralls.json + # Teardown + # If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each + # Save test results + - store_test_results: + path: /tmp/circleci-test-results + # Save artifacts + - store_artifacts: + path: /tmp/circleci-artifacts + - store_artifacts: + path: /tmp/circleci-test-results diff --git a/project.clj b/project.clj index 1fd20af..6d3285f 100644 --- a/project.clj +++ b/project.clj @@ -3,12 +3,12 @@ :url "https://github.com/dlobue/tensor" :license {:name "Apache License 2.0" :url "http://www.apache.org/licenses/LICENSE-2.0.html"} - :profiles {:dev {:dependencies [[org.clojure/clojure "1.6.0"] - [riemann "0.2.6"] - [cloverage "1.0.6"]] + :profiles {:dev {:dependencies [[org.clojure/clojure "1.9.0"] + [riemann "0.3.0"] + [cloverage "1.0.10"]] :resource-paths ["test/resources"]}} :plugins [[lein-cloverage "1.0.6"]] - :dependencies [[org.clojure/tools.logging "0.2.6"] - [org.clojure/tools.macro "0.1.2"] - [com.stuartsierra/dependency "0.1.1"] - [medley "0.5.1"]]) + :dependencies [[org.clojure/tools.logging "0.4.0"] + [org.clojure/tools.macro "0.1.5"] + [com.stuartsierra/dependency "0.2.0"] + [medley "1.0.0"]]) diff --git a/src/tensor/core.clj b/src/tensor/core.clj index a2953c1..e961a4e 100644 --- a/src/tensor/core.clj +++ b/src/tensor/core.clj @@ -17,7 +17,12 @@ (defn- dir-loader [pkg] (debug "Loading package " pkg) - (load (pkg-to-path pkg))) + (let [pkg-path (pkg-to-path pkg)] + (try (load pkg-path) + (catch java.io.FileNotFoundException e + (debug (str "Unable to locate class for package " pkg " on the filesystem")) + (trace e (str "Exception thrown while searching for module " + pkg ". Expected package here: " pkg-path)))))) (defn coerce-list [arg] (if-not (sequential? arg) @@ -44,6 +49,12 @@ (not (:wildcard-exclude (meta s)))))) vals))) +(defn- extract-namespace + "Get the namespace of the desired stream. Also support bare namespaces for wildcarding." + [streamname] + {:pre [(keyword? streamname)]} + (or (namespace streamname) + (name streamname))) (defn get-stream [streamname] (let [streamname (keyword streamname)] @@ -52,8 +63,7 @@ stream (do (debug "Stream " streamname " yet not in registry") - (dir-loader (or (namespace streamname) - (name streamname))) + (dir-loader (extract-namespace streamname)) (if-let [stream (get-stream' streamname)] stream (throw (ex-info (str "Stream " streamname " not found") diff --git a/test/tensor/core_test.clj b/test/tensor/core_test.clj index 78430fa..6261f34 100644 --- a/test/tensor/core_test.clj +++ b/test/tensor/core_test.clj @@ -23,6 +23,16 @@ {:env-only :a :env-include {:d :d}} {:a :a :d :d} {:env-include {:d :d} :env-exclude :b} {:a :a :c :c :d :d}))) +(deftest extract-namespace + (testing "extract the namespace from a keyword for a single stream" + (is (= "blarg" + (#'tensor.core/extract-namespace :blarg/a)))) + (testing "support 'wildcarding' and stringify the namespace from a keyword that doesn't contain a specific stream" + (is (= "honk" + (#'tensor.core/extract-namespace :honk)))) + (testing "fail in a predictable manner if we aren't given the type of input we expect" + (is (thrown? AssertionError + (#'tensor.core/extract-namespace 'honk))))) (deftest resolve-and-load-streamspec (binding [*streams* (atom (into @@ -35,6 +45,7 @@ :args args})}) [:a/stream :b/stream + :b/stream2 :c/stream :d/stream])))] @@ -64,6 +75,16 @@ :args nil} (load-stream-fn 'a/stream {:blarg :honk}))) + ;; (b/stream b/stream2) + (testing "Support loading all streams within a package" + (is (= '({:name :b/stream + :env {:blarg :honk} + :args nil} + {:name :b/stream2 + :env {:blarg :honk} + :args nil}) + (load-stream-fn 'b {:blarg :honk})))) + ;; (a/stream locally-bound-symbol) (is (= {:name :a/stream :env {:blarg :honk @@ -79,7 +100,15 @@ :args [{:name :c/stream :env {:blarg :honk} :args nil}]} - (load-stream-fn 'a/stream {:blarg :honk} '(c/stream)))))) + (load-stream-fn 'a/stream {:blarg :honk} '(c/stream)))) + + (testing "Ensure exception is thrown when no stream is found" + (is (thrown-with-msg? clojure.lang.ExceptionInfo #"Stream :blarg/stream not found" + (get-stream 'blarg/stream))) + (is (= {:type :no-stream-found} + (try (get-stream 'blarg/stream) + (catch clojure.lang.ExceptionInfo e + (ex-data e)))))))) (deftest load-streams-fn-tests (testing "Ensure regression hasn't occurred and load-streams-fn isn't returning a lazy-seq"