 (deftest test-multi-arity-protocol-fn
   (testing "should support protocols with multi-arity fns"
     (let [ma-service  (service MultiArityService
-                               []
-                               (foo [this x] x)
-                               (foo [this x y] (+ x y)))
+                        []
+                        (foo [this x] x)
+                        (foo [this x y] (+ x y)))
           service1    (service Service1
-                               [[:MultiArityService foo]]
-                               (service1-fn [this]
-                                            [(foo 5) (foo 3 6)]))
+                        [[:MultiArityService foo]]
+                        (service1-fn [this]
+                                     [(foo 5) (foo 3 6)]))
           app         (bootstrap-services-with-empty-config [ma-service service1])
           mas         (app/get-service app :MultiArityService)
           s1          (app/get-service app :Service1)]

(deftest context-test
  (testing "should error if lifecycle function doesn't return context"
    (is (thrown-with-msg?
          IllegalStateException
          (re-pattern (str "Lifecycle function 'init' for service "
                           "'puppetlabs.trapperkeeper.services-test/service1'"
                           " must return a context map \\(got: \"hi\"\\)"))
          (bootstrap-services-with-empty-config [service1]))
        "Unexpected shutdown reason for bootstrap")
    (is (thrown-with-msg?
          IllegalStateException
          (re-pattern (str "Lifecycle function 'start' for service "
                           "'puppetlabs.trapperkeeper.services-test/service1-alt'"
                           " must return a context map "
                           "\\(got: \"hi\"\\)"))
          (bootstrap-services-with-empty-config [service1-alt]))
        "Unexpected shutdown reason for bootstrap"))

  (testing "lifecycle error works if service has no service symbol"
    (let [service1 (service Service1
                            []
                            (init [this context] "hi")
                            (service1-fn [this] "hi"))]
      (is (thrown-with-msg?
            IllegalStateException
            (re-pattern (str "Lifecycle function 'init' for service ':Service1'"
                             " must return a context map \\(got: \"hi\"\\)"))
            (bootstrap-services-with-empty-config [service1]))
          "Unexpected shutdown reason for bootstrap"))
    (let [service1 (service Service1
                            []
                            (start [this context] "hi")
                            (service1-fn [this] "hi"))]

      (is (thrown-with-msg?
            IllegalStateException
            (re-pattern (str "Lifecycle function 'start' for service "
                             "':Service1' must return a context map "
                             "\\(got: \"hi\"\\)"))
            (bootstrap-services-with-empty-config [service1]))
          "Unexpected shutdown reason for bootstrap")))

  (testing "context should be available in subsequent lifecycle functions"
    (let [start-context (atom nil)
          service1 (service Service1
                            []
                            (init [this context] (assoc context :foo :bar))
                            (start [this context] (reset! start-context context))
                            (service1-fn [this] "hi"))]
      (bootstrap-services-with-empty-config [service1])
      (is (= {:foo :bar} @start-context))))

  (testing "context should be accessible in service functions"
    (let [sfn-context (atom nil)
          service1 (service Service1
                            []
                            (init [this context] (assoc context :foo :bar))
                            (service1-fn [this] (reset! sfn-context (svcs/service-context this))))
          app (bootstrap-services-with-empty-config [service1])
          s1  (app/get-service app :Service1)]
      (service1-fn s1)

(deftest dependencies-test
  (testing "services should be able to call functions in dependency list"
    (let [service1 (service Service1
                     []
                     (service1-fn [this] "FOO!"))
          service2 (service Service2
                     [[:Service1 service1-fn]]
                     (service2-fn [this] (str "HELLO " (service1-fn))))
          app (bootstrap-services-with-empty-config [service1 service2])
          s2  (app/get-service app :Service2)]
      (is (= "HELLO FOO!" (service2-fn s2)))))

  (testing "services should be able to retrieve instances of services that they depend on"
    (let [service1 (service Service1
                     []
                     (service1-fn [this] "FOO!"))
          service2 (service Service2
                     [[:Service1 service1-fn]]
                     (init [this context]
                           (let [s1 (svcs/get-service this :Service1)]
                             (assoc context :s1 s1)))
                     (service2-fn [this] ((svcs/service-context this) :s1)))
          app               (bootstrap-services-with-empty-config [service1 service2])
          s2                (app/get-service app :Service2)
          s1                (service2-fn s2)]
