diff --git a/CHANGELOG.md b/CHANGELOG.md index fffbde45..66838a13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ The official release will have a defined and more stable API. If you are already ## 0.11.0 * Improvements: - * Keeps a history of pipeline structure if persistence component supports it (#131, #6) + * Keeps a history of pipeline structure if persistence component supports it (#131, #6); Implemented for default persistence * Bug fixes: * Fix deadlock occurring when steps write a lot of step-results in quick succession and step results are inherited by their parents (as in chaining) (#135) * API changes: diff --git a/src/clj/lambdacd/internal/default_pipeline_state.clj b/src/clj/lambdacd/internal/default_pipeline_state.clj index 61764f7c..5e198bd7 100644 --- a/src/clj/lambdacd/internal/default_pipeline_state.clj +++ b/src/clj/lambdacd/internal/default_pipeline_state.clj @@ -3,8 +3,10 @@ i.e. what's currently running, what are the results of each step, ..." (:require [lambdacd.internal.default-pipeline-state-persistence :as persistence] [clj-time.core :as t] - [lambdacd.internal.pipeline-state :as pipeline-state] - [lambdacd.util :as util])) + [lambdacd.internal.pipeline-state :as old-pipeline-state] + [lambdacd.state.protocols :as protocols] + [lambdacd.util :as util] + [clojure.data :as data])) (def clean-pipeline-state {}) @@ -21,36 +23,46 @@ (defn- update-step-result-in-state [build-number step-id new-step-result current-state] (update-in current-state [build-number step-id] #(update-step-result new-step-result %))) -(defn- truncate-build-history [max-builds state] - (->> state - (sort-by key >) - (take max-builds) - (into {}))) +(defn- truncate-build-history [home-dir max-builds state] + (let [new-state (->> state + (sort-by key >) + (take max-builds) + (into {})) + [only-in-old _ _] (data/diff (set (keys state)) (set (keys new-state)))] + (persistence/clean-up-old-builds home-dir only-in-old) + new-state)) (defn- most-recent-build-number-in-state [pipeline-state] (if-let [current-build-number (last (sort (keys pipeline-state)))] current-build-number 0)) -(defrecord DefaultPipelineState [state-atom home-dir max-builds] - pipeline-state/PipelineStateComponent +(defrecord DefaultPipelineState [state-atom structure-atom home-dir max-builds] + old-pipeline-state/PipelineStateComponent (update [self build-number step-id new-step-result] (if (not (nil? state-atom)) ; convenience for tests: if no state exists we just do nothing (let [new-state (swap! state-atom #(->> % (update-step-result-in-state build-number step-id new-step-result) - (truncate-build-history max-builds)))] - (persistence/write-build-history home-dir build-number new-state) - (persistence/clean-up-old-history home-dir new-state)))) + (truncate-build-history home-dir max-builds)))] + (persistence/write-build-history home-dir build-number new-state)))) (get-all [self] @state-atom) (get-internal-state [self] state-atom) (next-build-number [self] - (inc (most-recent-build-number-in-state @state-atom)))) + (inc (most-recent-build-number-in-state @state-atom))) + protocols/PipelineStructureConsumer + (consume-pipeline-structure [self build-number pipeline-structure-representation] + (swap! structure-atom #(assoc % build-number pipeline-structure-representation)) + (persistence/write-pipeline-structure home-dir build-number pipeline-structure-representation)) + protocols/PipelineStructureSource + (get-pipeline-structure [self build-number] + (get @structure-atom build-number))) (defn new-default-pipeline-state [config & {:keys [initial-state-for-testing]}] - (let [state-atom (atom (or initial-state-for-testing (initial-pipeline-state config))) - home-dir (:home-dir config) + (let [home-dir (:home-dir config) + state-atom (atom (or initial-state-for-testing (initial-pipeline-state config))) + structure-atom (atom (persistence/read-pipeline-structures home-dir)) max-builds (or (:max-builds config) Integer/MAX_VALUE) - instance (->DefaultPipelineState state-atom home-dir max-builds)] + instance (->DefaultPipelineState state-atom structure-atom home-dir max-builds)] instance)) diff --git a/src/clj/lambdacd/internal/default_pipeline_state_persistence.clj b/src/clj/lambdacd/internal/default_pipeline_state_persistence.clj index e089dec1..06b0a964 100644 --- a/src/clj/lambdacd/internal/default_pipeline_state_persistence.clj +++ b/src/clj/lambdacd/internal/default_pipeline_state_persistence.clj @@ -45,14 +45,16 @@ (into {} (map step-result-with-formatted-step-ids->step-result m))) (defn- build-number-from-path [path] - (util/parse-int (second (re-find #"build-(\d+)" path)))) + (util/parse-int (second (re-find #"build-(\d+)" (str path))))) (defn- build-state-path [dir] - (str dir "/" "build-state.edn")) + (io/file dir "build-state.edn")) -(defn- read-build-edn [dir] - (let [path (build-state-path dir) - build-number (build-number-from-path path) +(defn- pipeline-structure-path [dir] + (io/file dir "pipeline-structure.edn")) + +(defn- read-build-edn [path] + (let [build-number (build-number-from-path path) data-str (slurp path) state (formatted-step-ids->pipeline-state (dates->clj-times (edn/read-string data-str)))] {build-number state})) @@ -69,25 +71,42 @@ build-dirs (filter #(.startsWith (.getName %) "build-") directories-in-home)] build-dirs)) +(defn- build-dir [home-dir build-number] + (let [result (str home-dir "/" "build-" build-number)] + (.mkdirs (io/file result)) + result)) + (defn write-build-history [home-dir build-number new-state] (if home-dir - (let [dir (str home-dir "/" "build-" build-number) - edn-path (build-state-path dir) - build (get new-state build-number)] - (.mkdirs (io/file dir)) + (let [dir (build-dir home-dir build-number) + edn-path (build-state-path dir) + build (get new-state build-number)] (write-build-edn edn-path build)))) -(defn read-build-history-from [home-dir] - (let [states (map read-build-edn (build-dirs home-dir))] - (into {} states))) +(defn file-exists? [f] + (.exists f)) -(defn clean-up-old-history [home-dir new-state] - (if home-dir - (let [existing-build-dirs (map str (build-dirs home-dir)) - expected-build-numbers (keys new-state) - expected-build-dirs (map #(str (io/file home-dir (str "build-" %))) expected-build-numbers) - [only-in-existing _ _] (data/diff (set existing-build-dirs) (set expected-build-dirs))] - (doall (for [old-build-dir only-in-existing] - (do - (log/info "Cleaning up old build directory" old-build-dir) - (fs/delete-dir old-build-dir))))))) +(defn read-build-history-from [home-dir] + (->> (build-dirs home-dir) + (map build-state-path) + (filter file-exists?) + (map read-build-edn) + (into {}))) + +(defn write-pipeline-structure [home-dir build-number pipeline-structure] + (let [f (pipeline-structure-path (build-dir home-dir build-number))] + (spit f (pr-str pipeline-structure)))) + +(defn- read-pipeline-structure-edn [f] + {(build-number-from-path f) (edn/read-string (slurp f))}) + +(defn read-pipeline-structures [home-dir] + (->> (build-dirs home-dir) + (map pipeline-structure-path) + (filter file-exists?) + (map read-pipeline-structure-edn) + (into {}))) + +(defn clean-up-old-builds [home-dir old-build-numbers] + (doall (map (fn [old-build-number] + (fs/delete-dir (build-dir home-dir old-build-number))) old-build-numbers))) diff --git a/test/clj/lambdacd/internal/default_pipeline_state_persistence_test.clj b/test/clj/lambdacd/internal/default_pipeline_state_persistence_test.clj index c69a3e34..dcc6a9d3 100644 --- a/test/clj/lambdacd/internal/default_pipeline_state_persistence_test.clj +++ b/test/clj/lambdacd/internal/default_pipeline_state_persistence_test.clj @@ -2,35 +2,45 @@ (:use [lambdacd.testsupport.test-util]) (:require [clojure.test :refer :all] [lambdacd.internal.default-pipeline-state-persistence :refer :all] + [lambdacd.presentation.pipeline-structure-test :as pipeline-structure-test] [clj-time.core :as t] [lambdacd.util :as utils] [clojure.java.io :as io])) (deftest roundtrip-persistence-test - (testing "the standard case" - (let [some-pipeline-state {3 {'(0) {:status :success :most-recent-update-at (t/epoch)} - '(0 1 2) {:status :failure :out "something went wrong"}}} - home-dir (utils/create-temp-dir)] - (write-build-history home-dir 3 some-pipeline-state) - (is (= some-pipeline-state (read-build-history-from home-dir))))) - (testing "that string-keys in a step result are suppored as well (#101)" - (let [some-pipeline-state {3 {'(0) {:status :success :_git-last-seen-revisions {"refs/heads/master" "some-sha"}}}} - home-dir (utils/create-temp-dir)] - (write-build-history home-dir 3 some-pipeline-state) - (is (= some-pipeline-state (read-build-history-from home-dir))))) - (testing "that keyworded values in a step result are suppored as well (#101)" - (let [some-pipeline-state {3 {'(0) {:status :success :v :x}}} - home-dir (utils/create-temp-dir)] - (write-build-history home-dir 3 some-pipeline-state) - (is (= some-pipeline-state (read-build-history-from home-dir))))) + (testing "pipeline-state" + (testing "the standard case" + (let [some-pipeline-state {3 {'(0) {:status :success :most-recent-update-at (t/epoch)} + '(0 1 2) {:status :failure :out "something went wrong"}}} + home-dir (utils/create-temp-dir)] + (write-build-history home-dir 3 some-pipeline-state) + (is (= some-pipeline-state (read-build-history-from home-dir))))) + (testing "that string-keys in a step result are supported as well (#101)" + (let [some-pipeline-state {3 {'(0) {:status :success :_git-last-seen-revisions {"refs/heads/master" "some-sha"}}}} + home-dir (utils/create-temp-dir)] + (write-build-history home-dir 3 some-pipeline-state) + (is (= some-pipeline-state (read-build-history-from home-dir))))) + (testing "that keyworded values in a step result are suppored as well (#101)" + (let [some-pipeline-state {3 {'(0) {:status :success :v :x}}} + home-dir (utils/create-temp-dir)] + (write-build-history home-dir 3 some-pipeline-state) + (is (= some-pipeline-state (read-build-history-from home-dir)))))) + (testing "pipeline-structure" + (testing "the standard case" + (let [home-dir (utils/create-temp-dir) + some-pipeline-structure pipeline-structure-test/foo-pipeline-display-representation] + (write-pipeline-structure home-dir 1 some-pipeline-structure) + (write-pipeline-structure home-dir 2 some-pipeline-structure) + (is (= some-pipeline-structure (get (read-pipeline-structures home-dir) 1))) + (is (= some-pipeline-structure (get (read-pipeline-structures home-dir) 2))))))) + +(deftest clean-up-old-builds-test (testing "cleaning up old history" - (testing "that build-directories will be deleted if they no longer exist in the build-state" - (let [some-pipeline-state {0 {'(0) {:status :success}} - 1 {'(0) {:status :success}} - 2 {'(0) {:status :success}}} - truncated-pipeline-state {1 {'(0) {:status :success}} + (testing "that given build-directories will be deleted" + (let [some-pipeline-state {0 {'(0) {:status :success}} + 1 {'(0) {:status :success}} 2 {'(0) {:status :success}}} - home-dir (utils/create-temp-dir)] + home-dir (utils/create-temp-dir)] (doall (for [build (range 0 3)] (write-build-history home-dir build some-pipeline-state))) (doall (for [build (range 0 3)] @@ -39,19 +49,36 @@ (is (.exists (io/file home-dir "build-0"))) (is (.exists (io/file home-dir "build-1"))) (is (.exists (io/file home-dir "build-2"))) - (clean-up-old-history home-dir truncated-pipeline-state) + (clean-up-old-builds home-dir [0]) (is (not (.exists (io/file home-dir "build-0")))) (is (.exists (io/file home-dir "build-1"))) (is (.exists (io/file home-dir "build-2"))))) (testing "that it does not clean up things other than build directories" - (let [truncated-pipeline-state {} - home-dir (utils/create-temp-dir)] + (let [home-dir (utils/create-temp-dir)] (.mkdirs (io/file home-dir "helloworld")) (is (.exists (io/file home-dir "helloworld"))) - (clean-up-old-history home-dir truncated-pipeline-state) + (clean-up-old-builds home-dir [0]) (is (.exists (io/file home-dir "helloworld"))))))) +(deftest read-build-history-from-test ; covers only edge-cases that aren't coverd by roundtrip + (testing "that it will return an empty history if no state has been written yet" + (let [home-dir (utils/create-temp-dir)] + (is (= {} (read-build-history-from home-dir))))) + (testing "that it ignores build directories with no build state (e.g. because only structure has been written yet" + (let [home-dir (utils/create-temp-dir)] + (.mkdirs (io/file home-dir "build-1")) + (is (= {} (read-build-history-from home-dir)))))) + +(deftest read-pipeline-structures-test ; covers only edge-cases that aren't covered by roundtrip + (testing "that it will return an empty data if no state has been written yet" + (let [home-dir (utils/create-temp-dir)] + (is (= {} (read-pipeline-structures home-dir))))) + (testing "that it ignores build directories with no pipeline structure (e.g. because they were created before this feature was available)" + (let [home-dir (utils/create-temp-dir)] + (.mkdirs (io/file home-dir "build-1")) + (is (= {} (read-pipeline-structures home-dir)))))) + (defn- roundtrip-date-time [data] (dates->clj-times (clj-times->dates data))) diff --git a/test/clj/lambdacd/internal/default_pipeline_state_test.clj b/test/clj/lambdacd/internal/default_pipeline_state_test.clj index 2be5ff04..cb2d614f 100644 --- a/test/clj/lambdacd/internal/default_pipeline_state_test.clj +++ b/test/clj/lambdacd/internal/default_pipeline_state_test.clj @@ -8,27 +8,28 @@ [lambdacd.testsupport.test-util :as tu] [lambdacd.testsupport.data :refer [some-ctx-with some-ctx]] [clojure.java.io :as io] - [clojure.edn :as edn]) + [clojure.edn :as edn] + [lambdacd.state.protocols :as protocols]) (:import (java.util Date))) (def no-home-dir nil) (def keep-all-builds Integer/MAX_VALUE) (defn- after-update [build id newstate] - (let [state (->DefaultPipelineState (atom clean-pipeline-state) no-home-dir keep-all-builds)] + (let [state (->DefaultPipelineState (atom clean-pipeline-state) (atom {}) no-home-dir keep-all-builds)] (pipeline-state-record/update state build id newstate) (pipeline-state-record/get-all state))) (deftest general-pipeline-state-test (testing "that the next buildnumber is the highest build-number currently in the pipeline-state" - (is (= 5 (next-build-number (->DefaultPipelineState (atom { 3 {} 4 {} 1 {}}) no-home-dir keep-all-builds)))) - (is (= 1 (next-build-number (->DefaultPipelineState (atom clean-pipeline-state) no-home-dir keep-all-builds))))) + (is (= 5 (next-build-number (->DefaultPipelineState (atom { 3 {} 4 {} 1 {}}) (atom {}) no-home-dir keep-all-builds)))) + (is (= 1 (next-build-number (->DefaultPipelineState (atom clean-pipeline-state) (atom {}) no-home-dir keep-all-builds))))) (testing "that a new pipeline-state will be set on update" (is (= { 10 { [0] { :foo :bar }}} (tu/without-ts (after-update 10 [0] {:foo :bar}))))) (testing "that update will set a first-updated-at and most-recent-update-at timestamp" (let [first-update-timestamp (t/minus (t/now) (t/minutes 1)) last-updated-timestamp (t/now) - state (->DefaultPipelineState (atom clean-pipeline-state) no-home-dir keep-all-builds)] + state (->DefaultPipelineState (atom clean-pipeline-state) (atom {}) no-home-dir keep-all-builds)] (t/do-at first-update-timestamp (pipeline-state-record/update state 10 [0] {:foo :bar})) (t/do-at last-updated-timestamp (pipeline-state-record/update state 10 [0] {:foo :baz})) (is (= {10 {[0] {:foo :baz :most-recent-update-at last-updated-timestamp :first-updated-at first-update-timestamp}}} @@ -36,7 +37,7 @@ (testing "that updating will save the current state to the file-system" (let [home-dir (utils/create-temp-dir) step-result {:foo :bar} - state (->DefaultPipelineState (atom clean-pipeline-state) home-dir keep-all-builds)] + state (->DefaultPipelineState (atom clean-pipeline-state) (atom {}) home-dir keep-all-builds)] (t/do-at (t/epoch) (pipeline-state-record/update state 10 [0] step-result)) (is (= [{:step-id "0" :step-result {:foo :bar @@ -46,7 +47,7 @@ (testing "truncate" (testing "that updating will remove the oldest build if more than the maximum number of builds are written" (let [max-builds 5 - state (->DefaultPipelineState (atom clean-pipeline-state) no-home-dir max-builds)] + state (->DefaultPipelineState (atom clean-pipeline-state) (atom {}) no-home-dir max-builds)] (doall (for [build (range 5)] (pipeline-state-record/update state build [0] {:foo :baz :build build}))) (is (= {[0] {:foo :baz :build 0}} (tu/without-ts (get (pipeline-state-record/get-all state) 0)))) @@ -60,7 +61,7 @@ (testing "that updating will remove outdated state from file-system" (let [max-builds 5 home-dir (utils/create-temp-dir) - state (->DefaultPipelineState (atom clean-pipeline-state) home-dir max-builds)] + state (->DefaultPipelineState (atom clean-pipeline-state) (atom {}) home-dir max-builds)] (doall (for [build (range 5)] (pipeline-state-record/update state build [0] {:foo :baz :build build}))) (is (.exists (io/file home-dir "build-0/build-state.edn"))) @@ -71,25 +72,34 @@ (is (not (.exists (io/file home-dir "build-0/build-state.edn")))) (is (.exists (io/file home-dir "build-4/build-state.edn"))) - (is (.exists (io/file home-dir "build-5/build-state.edn"))))))) - -(defn- write-pipeline-state [home-dir build-number state] - (let [dir (str home-dir "/" "build-" build-number) - path (str dir "/build-state.edn")] - (.mkdirs (io/file dir)) - (spit (io/file path) (pr-str state)))) + (is (.exists (io/file home-dir "build-5/build-state.edn"))))) + (testing "that it will not accidently remove pipeline-structures for builds that arent truncated but don't have a state yet" + (let [max-builds 10 + home-dir (utils/create-temp-dir) + state (->DefaultPipelineState (atom clean-pipeline-state) (atom {}) home-dir max-builds) + build-dir (io/file home-dir "build-6") + pipeline-structure-file (io/file build-dir "pipeine-structure.edn")] + (doall (for [build (range 5)] + (pipeline-state-record/update state build [0] {:foo :baz :build build}))) + (.mkdirs build-dir) + (spit pipeline-structure-file "test") + (is (.exists pipeline-structure-file)) -(deftest initial-pipeline-state-test - (testing "that with a clean home-directory, the initial pipeline-state is clean as well" - (let [home-dir (utils/create-temp-dir) - config {:home-dir home-dir}] - (is (= clean-pipeline-state (initial-pipeline-state config))))) - (testing "that it reads the state from disk correctly" - (let [home-dir (utils/create-temp-dir) - config {:home-dir home-dir}] - (write-pipeline-state home-dir 1 [{:step-id "0" :step-result {:foo "bar" }}]) - (write-pipeline-state home-dir 2 [{:step-id "1-2" :step-result {:bar "baz" }}]) - (is (= {1 { [0] {:foo "bar"}} - 2 { [1 2] {:bar "baz"}}} (initial-pipeline-state config)))))) + (pipeline-state-record/update state 5 [0] {:foo :baz :build 5}) + (is (.exists pipeline-structure-file)))))) +(deftest pipeline-structure-state-test + (testing "that we can consume and retrieve pipeline-structure" + (let [component (new-default-pipeline-state {:home-dir (utils/create-temp-dir)})] + (protocols/consume-pipeline-structure component 1 {:some-pipeline :structure}) + (is (= {:some-pipeline :structure} (protocols/get-pipeline-structure component 1))))) + (testing "that we return nil if pipeline-structure isn't there" + (let [component (new-default-pipeline-state {:home-dir (utils/create-temp-dir)})] + (is (= nil (protocols/get-pipeline-structure component 43))))) + (testing "that we can retrieve the pipeline-structure from disk" + (let [home (utils/create-temp-dir) + component (new-default-pipeline-state {:home-dir home})] + (protocols/consume-pipeline-structure component 1 {:some-pipeline :structure}) + (let [other-component (new-default-pipeline-state {:home-dir home})] + (is (= {:some-pipeline :structure} (protocols/get-pipeline-structure other-component 1))))))) diff --git a/test/clj/lambdacd/internal/execution_test.clj b/test/clj/lambdacd/internal/execution_test.clj index 94ec77fe..a1e8d07f 100644 --- a/test/clj/lambdacd/internal/execution_test.clj +++ b/test/clj/lambdacd/internal/execution_test.clj @@ -16,7 +16,8 @@ [lambdacd.event-bus :as event-bus] [lambdacd.state.internal.pipeline-state-updater :as pipeline-state-updater] [lambdacd.steps.control-flow :as control-flow] - [lambdacd.state.core :as state]) + [lambdacd.state.core :as state] + [lambdacd.util :as util]) (:import java.lang.IllegalStateException)) (defn some-step-processing-input [arg & _] @@ -460,5 +461,6 @@ (let [started-steps (atom #{:foo}) ctx (some-ctx-with :step-id [3 1] :started-steps started-steps - :config {:ms-to-wait-for-shutdown 200})] + :config {:ms-to-wait-for-shutdown 200 + :home-dir (util/create-temp-dir)})] (is (not= {:status :timeout} (call-with-timeout 1000 (kill-all-pipelines ctx))))))) diff --git a/test/clj/lambdacd/presentation/pipeline_structure_test.clj b/test/clj/lambdacd/presentation/pipeline_structure_test.clj index cf19b063..bba38adb 100644 --- a/test/clj/lambdacd/presentation/pipeline_structure_test.clj +++ b/test/clj/lambdacd/presentation/pipeline_structure_test.clj @@ -61,6 +61,23 @@ (in-cwd "bar" do-other-stuff)))) +(def foo-pipeline-display-representation + [{:name "in-parallel" + :type :parallel + :step-id '(1) + :has-dependencies false + :children + [{:name "in-cwd foo" + :type :container + :step-id '(1 1) + :has-dependencies false + :children [{:name "do-stuff" :type :step :step-id '(1 1 1) :has-dependencies false}]} + {:name "in-cwd bar" + :type :container + :step-id '(2 1) + :has-dependencies false + :children [{:name "do-other-stuff" :type :step :step-id '(1 2 1) :has-dependencies true}]}]}]) + (def pipeline-with-container-without-display-type `((container-without-display-type do-stuff))) @@ -156,21 +173,7 @@ (testing "that aliasing makes the aliased child disappear" (is (= [{:name "do-stuff-alias" :type :step :step-id '(1 1) :has-dependencies false} {:name "do-other-stuff" :type :step :step-id '(2) :has-dependencies true}] (pipeline-display-representation pipeline-with-alias)))) (testing "that foo-pipeline works" - (is (= [{:name "in-parallel" - :type :parallel - :step-id '(1) - :has-dependencies false - :children - [{:name "in-cwd foo" - :type :container - :step-id '(1 1) - :has-dependencies false - :children [{:name "do-stuff" :type :step :step-id '(1 1 1) :has-dependencies false}]} - {:name "in-cwd bar" - :type :container - :step-id '(2 1) - :has-dependencies false - :children [{:name "do-other-stuff" :type :step :step-id '(1 2 1) :has-dependencies true}]}]}] (pipeline-display-representation foo-pipeline)))) + (is (= foo-pipeline-display-representation (pipeline-display-representation foo-pipeline)))) (testing "that nesting parallel in sequential containers works (reproduces #47)" (is (not (nil? (:children (first (pipeline-display-representation `((run (in-parallel do-stuff)))))))))) (testing "that display type defaults to :container for container-steps" diff --git a/test/clj/lambdacd/steps/support_test.clj b/test/clj/lambdacd/steps/support_test.clj index 420394df..3a0e8faa 100644 --- a/test/clj/lambdacd/steps/support_test.clj +++ b/test/clj/lambdacd/steps/support_test.clj @@ -38,12 +38,12 @@ {:status :success :no-arg :passed-in}) (defn some-step-returning-the-context-passed-in [args ctx] - {:status :success :the-ctx-1 ctx}) + {:status :success :the-ctx-1 (:v ctx)}) (defn some-step-receiving-only-ctx [ctx] - {:status :success :the-ctx-1 ctx}) + {:status :success :the-ctx-1 (:v ctx)}) (defn some-other-step-returning-the-context-passed-in [args ctx] - {:status :success :the-ctx-2 ctx}) + {:status :success :the-ctx-2 (:v ctx)}) (defn some-step-saying-hello [args ctx] {:status :success :out "hello"}) @@ -126,10 +126,10 @@ {:status :success :out "hello\nhelloworld\n"}] (slurp-chan result-channel))))) (testing "that the context is passed to all the steps" (let [result (unit-under-test {} (some-ctx-with :v 42) - some-step-returning-the-context-passed-in - some-other-step-returning-the-context-passed-in)] - (is (map-containing {:v 42} (:the-ctx-1 result))) - (is (map-containing {:v 42} (:the-ctx-2 result))))) + some-step-returning-the-context-passed-in + some-other-step-returning-the-context-passed-in)] + (is (= 42 (:the-ctx-1 result))) + (is (= 42 (:the-ctx-2 result))))) (testing "that the steps individual outputs are available in the end result" (is (map-containing {:outputs {[1 42] {:status :success} [2 42] {:status :success :v 42}}} @@ -186,10 +186,10 @@ (some-step injected-args injected-ctx) {:status :success :this-is :test})))) (testing "that a given context is passed on to the step" - (is (map-containing {:v 42} (:the-ctx-1 (chaining {} (some-ctx-with :v 42) + (is (= 42 (:the-ctx-1 (chaining {} (some-ctx-with :v 42) (some-step-returning-the-context-passed-in injected-args injected-ctx)))))) (testing "that we can pass in only the ctx" - (is (map-containing {:v 42} (:the-ctx-1 (chaining {} (some-ctx-with :v 42) + (is (= 42 (:the-ctx-1 (chaining {} (some-ctx-with :v 42) (some-step-receiving-only-ctx injected-ctx)))))) (testing "that we can pass in only the args" (is (map-containing {:status :success :the-arg 42} diff --git a/test/clj/lambdacd/testsupport/data.clj b/test/clj/lambdacd/testsupport/data.clj index 50ec02aa..144b8158 100644 --- a/test/clj/lambdacd/testsupport/data.clj +++ b/test/clj/lambdacd/testsupport/data.clj @@ -23,7 +23,7 @@ (defn- add-pipeline-state-component [template] (if (nil? (:pipeline-state-component template)) (assoc template :pipeline-state-component - (default-pipeline-state/new-default-pipeline-state template :initial-state-for-testing (:initial-pipeline-state template))) + (default-pipeline-state/new-default-pipeline-state (:config template) :initial-state-for-testing (:initial-pipeline-state template))) template)) (defn run-pipeline-state-updater [ctx]