All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cognitect.aws.client.test_double.clj Maven / Gradle / Ivy

The newest version!
;; Copyright (c) Cognitect, Inc.
;; All rights reserved.

(ns cognitect.aws.client.test-double
  "Provides a test implementation of the aws client, which can be passed
  to the functions in the cognitect.aws.client.api ns."
  (:require [clojure.core.async :as a]
            [cognitect.aws.client.protocol :as client.protocol]
            [cognitect.aws.client.validation :as validation]
            [cognitect.aws.service :as service])
  (:import (clojure.lang ILookup)))

(set! *warn-on-reflection* true)

(defn ^:private no-handler-provided-anomaly [op]
  {:cognitect.anomalies/category :cognitect.anomalies/incorrect
   :cognitect.anomalies/message  "No handler or response provided for op"
   :op op})

(defprotocol TestDoubleClient
  (-instrument [c ops]))

(deftype Client [info handlers]
  ILookup
  (valAt [this k]
    (.valAt this k nil))

  (valAt [_this k default]
    (case k
      :api
      (-> info :service :metadata :cognitect.aws/service-name)
      :service
      (:service info)
      default))

  client.protocol/Client
  (-get-info [_] info)

  (-invoke [this {:keys [op request] :as op-map}]
    (let [spec    (validation/request-spec (:service info) op)
          handler (get @handlers op)]
      (cond
        (not (get-in info [:service :operations op]))
        (validation/unsupported-op-anomaly (:service info) op)

        (and (validation/validate-requests? this)
             spec
             (not (validation/valid? spec request)))
        (validation/invalid-request-anomaly spec request)

        (not handler)
        (no-handler-provided-anomaly op)

        :else
        (handler op-map))))

  (-invoke-async [this {:keys [ch] :as op-map}]
    (let [response-chan (or ch (a/promise-chan))]
      (a/go
        (let [resp (.-invoke this op-map)]
          (a/>! response-chan resp)))
      response-chan))

  (-stop [_aws-client])
  
  TestDoubleClient
  (-instrument [client ops]
               (swap! (.handlers client)
                      (fn [handlers]
                        (reduce-kv
                         (fn [m op handler]
                           (when-not (some-> client :service  :operations op)
                             (throw (ex-info "Operation not supported"
                                             (validation/unsupported-op-anomaly (-> client :service) op))))
                           (assoc m op (if (fn? handler) handler (constantly handler))))
                         handlers
                         ops)))))

;; ->Client is intended for internal use
(alter-meta! #'->Client assoc :skip-wiki true)
(alter-meta! #'TestDoubleClient assoc :skip-wiki true)

(defn instrument
  "Given a test double client and a `:ops` map of operations to handlers,
   instruments the client with handlers. See `client` for more info about
   `:ops`."
  [client ops]
  (-instrument client ops))

(defn client
  "Given a map with :api and :ops (optional), returns a test double client that
  you can pass to `cognitect.aws.client.api/invoke` and `cognitect.aws.client.api/stop`
  in implementation code.
   
  You can provide :ops on creation or use `instrument` to add them later.

  :ops should be a map of operation (keyword) to one of
  - a function of op-map that returns a response map
  - a literal response map

  Notes:
  - you must instrument every op that will be invoked during a test
  - every op must be supported
    - See (keys (cognitect.aws.client.api/ops ))
  - will validate request payloads passed to `invoke` by default
    - you can disable request validation with (cognitect.aws.client.api/validate-requests client false)
  - will not validate response payloads"
  [{:keys [api ops]}]
  (let [service (service/service-description (name api))]
    (doto (->Client {:service service :validate-requests? (atom true)} (atom {}))
      (instrument ops))))




© 2015 - 2025 Weber Informatics LLC | Privacy Policy