From 9f2e7f04ad12ff9f87dea9341ffa3ef39f27491d Mon Sep 17 00:00:00 2001 From: David Thomas Hume Date: Thu, 13 Mar 2014 08:26:23 +0000 Subject: [PATCH] Added basic perforate benchmark based on the "things" resource from test_get_put.clj --- benchmarks/things_bench.clj | 56 ++++++++++++++++++++++++++++++++ project.clj | 8 ++++- src/liberator/core.clj | 6 ++-- src/liberator/representation.clj | 2 +- src/liberator/util.clj | 4 +-- 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 benchmarks/things_bench.clj diff --git a/benchmarks/things_bench.clj b/benchmarks/things_bench.clj new file mode 100644 index 0000000..5f26417 --- /dev/null +++ b/benchmarks/things_bench.clj @@ -0,0 +1,56 @@ +(ns things-bench + (:require [liberator.core :refer (defresource request-method-in)] + [liberator.representation :refer (ring-response)] + [perforate.core :refer :all] + [ring.mock.request :refer (request header)]) + (:import [java.security MessageDigest])) + +(defresource thing-resource + [things] + ;; early lookup + :service-available? (fn [ctx] {::r (get @things (get-in ctx [:request :uri]))}) + :method-allowed? (request-method-in :get :put :delete) + ;; lookup media types of the requested resource + :available-media-types #(if-let [m (get-in % [::r :media-type])] [m]) + ;; the resource exists if a value is stored in @things at the uri + ;; store the looked up value at key ::r in the context + :exists? #(get % ::r) + ;; ...it existed if the stored value is nil (and not some random + ;; Objeced we use as a setinel) + :existed? #(nil? (get @things (get-in % [:request :uri]) (Object.))) + ;; use the previously stored value at ::r + :handle-ok #(get-in % [::r :content]) + ;; update the representation + :put! #(dosync + (alter things assoc-in + [(get-in % [:request :uri])] + {:content (get-in % [:request :body]) + :media-type (get-in % [:request :headers "content-type"] + "application/octet-stream") + :last-modified (java.util.Date.)})) + ;; ...store a nil value to marke the resource as gone + :delete! #(dosync (alter things assoc (get-in % [:request :uri]) nil)) + :last-modified #(get-in % [::r :last-modified])) + +(defgoal things-bench "'Things' Resource benchmarks") + +(defcase things-bench "Things" + [] + (let [t-r (thing-resource (ref nil))] + (let [resp (t-r (request :get "/r1"))] + (-> resp :status (= 404) assert)) + (let [resp (t-r (-> (request :put "/r1") + (assoc :body "r1") + (header "content-type" "text/plain")))] + (-> resp :status (= 201) assert)) + (let [resp (t-r (-> (request :get "/r1")))] + (-> resp :status (= 200) assert) + (-> resp :body (= "r1") assert) + (-> resp (get-in [:headers "Content-Type"]) + (= "text/plain;charset=UTF-8") + assert)) + (let [resp (t-r (-> (request :delete "/r1")))] + (-> resp :status (= 204) assert) + (-> resp :body nil? assert)) + (let [resp (t-r (request :get "/r1"))] + (-> resp :status (= 410) assert)))) diff --git a/project.clj b/project.clj index cb91a0c..b58c005 100644 --- a/project.clj +++ b/project.clj @@ -16,7 +16,8 @@ :url "https://github.com/clojure-liberator/liberator"} :plugins [[lein-midje "3.1.3" :exclusions [leiningen-core]] - [lein-ring "0.8.10" :exclusions [org.clojure/clojure]]] + [lein-ring "0.8.10" :exclusions [org.clojure/clojure]] + [perforate "0.3.3"]] :profiles {:dev {:dependencies [[ring/ring-jetty-adapter "1.2.1" :exclusions [joda-time]] [ring-mock "0.1.2"] @@ -33,6 +34,11 @@ :source-paths ["src"] :test-paths ["test"] + :perforate + {:environments [{:name :core + :profiles [:dev :1.5] + :namespaces [things-bench]}]} + :ring {:handler examples.server/handler :adapter {:port 8000}} diff --git a/src/liberator/core.clj b/src/liberator/core.clj index 0700ad2..6a8390c 100644 --- a/src/liberator/core.clj +++ b/src/liberator/core.clj @@ -206,7 +206,7 @@ (defmethod to-location clojure.lang.APersistentMap [this] this) -(defmethod to-location java.net.URL [url] (to-location (.toString url))) +(defmethod to-location java.net.URL [^java.net.URL url] (to-location (.toString url))) (defmethod to-location nil [this] this) @@ -310,7 +310,7 @@ (defdecision modified-since? (fn [context] - (let [last-modified (gen-last-modified context)] + (let [^java.util.Date last-modified (gen-last-modified context)] [(and last-modified (.after last-modified (::if-modified-since-date context))) {::last-modified last-modified}])) method-delete? @@ -346,7 +346,7 @@ (defdecision unmodified-since? (fn [context] - (let [last-modified (gen-last-modified context)] + (let [^java.util.Date last-modified (gen-last-modified context)] [(and last-modified (.after last-modified (::if-unmodified-since-date context))) diff --git a/src/liberator/representation.clj b/src/liberator/representation.clj index 4baed21..030c7fb 100644 --- a/src/liberator/representation.clj +++ b/src/liberator/representation.clj @@ -179,7 +179,7 @@ (render-seq-generic data (assoc-in context [:representation :media-type] "application/json")))) -(defn in-charset [string charset] +(defn in-charset [^String string ^String charset] (if (and charset (not (.equalsIgnoreCase charset "UTF-8"))) (java.io.ByteArrayInputStream. (.getBytes string (java.nio.charset.Charset/forName charset))) diff --git a/src/liberator/util.clj b/src/liberator/util.clj index 4538e78..640bd4e 100644 --- a/src/liberator/util.clj +++ b/src/liberator/util.clj @@ -24,7 +24,7 @@ nil (as-date [this] nil)) -(defn http-date-format [] +(defn ^SimpleDateFormat http-date-format [] (let [df (new SimpleDateFormat "EEE, dd MMM yyyy HH:mm:ss z" Locale/US)] @@ -32,7 +32,7 @@ df))) (defn relative-date [future] - (Date. (+ (System/currentTimeMillis) future))) + (Date. (long (+ (System/currentTimeMillis) future)))) (defn http-date [date] (format "%s" (.format (http-date-format) date)))