             [clojure.test :refer :all]
             [clojure.tools.logging :as log]
             [clojure.walk :as walk]
+            [plumbing.core :as pc]
             [waiter.correlation-id :as cid]
             [waiter.util.client-tools :refer :all])
   (:import (com.twosigma.waiter.courier

  (make-request waiter-url "/waiter-ping" :headers request-headers))

(defn start-courier-instance
  [waiter-url]
  (let [[host _] (str/split waiter-url #":")
        h2c-port (Integer/parseInt (retrieve-grpc-cleartext-port waiter-url))
        request-headers (basic-grpc-service-parameters)
        {:keys [cookies headers] :as response} (ping-courier-service waiter-url request-headers)
        cookie-header (str/join "; " (map #(str (:name %) "=" (:value %)) cookies))
        service-id (get headers "x-waiter-service-id")
        request-headers (assoc request-headers
                          "cookie" cookie-header
                          "x-waiter-timeout" "60000")]
    (assert-response-status response 200)
    (log/info "ping cid:" (get headers "x-cid"))
    (log/info "service-id:" service-id)
    (is service-id)
    (when-not service-id
      ;; abort test eagerly when service id is unavailable
      (throw (ex-info "missing service-id in response" {:response response})))
    (let [{:keys [ping-response service-state]} (some-> response :body try-parse-json walk/keywordize-keys)]
      (is (= "received-response" (:result ping-response)) (str ping-response))
      (is (= "OK" (some-> ping-response :body)) (str ping-response))
      (is (str/starts-with? (str (some-> ping-response :headers :server)) "courier-health-check") (str ping-response))
      (assert-response-status ping-response 200)
      (is (true? (:exists? service-state)) (str service-state))
      (is (= service-id (:service-id service-state)) (str service-state))
      (is (contains? #{"Running" "Starting"} (:status service-state)) (str service-state)))
    (assert-service-on-all-routers waiter-url service-id cookies)

    {:h2c-port h2c-port
     :host host
     :request-headers request-headers
     :service-id service-id}))

(defmacro assert-grpc-ok-status
  "Asserts that the status represents a grpc OK status."

    (GrpcClient. host port log-function)))

(defn- basic-grpc-service-parameters
  [& {:keys [prefix] :or {prefix "x-waiter-"}}]
  (let [courier-command (courier-server-command "${PORT0} ${PORT1}")]
    (pc/map-keys
      #(str prefix %)
      {"backend-proto" "h2c"
       "cmd" courier-command
       "cmd-type" "shell"
       "concurrency-level" 32
       "cpus" 0.2
       "debug" true
       "grace-period-secs" 120
       "health-check-port-index" 1
       "health-check-proto" "http"
       "idle-timeout-mins" 10
       "max-instances" 1
       "min-instances" 1
       "mem" 512
       "name" (rand-name)
       "ports" 2
       "version" "version-does-not-matter"})))

(defn- rand-str
  "Generates a random string with the specified length."
