Browse Source

Merge pull request #1538 from zane-techempower/upgrade-clojure-frameworks

[fixes #1515] Upgrade clojure frameworks
Brittany Mazza 10 years ago
parent
commit
1bfa7c2891

+ 1 - 0
frameworks/Clojure/compojure/benchmark_config.json

@@ -6,6 +6,7 @@
       "json_url": "/compojure/json",
       "db_url": "/compojure/db",
       "query_url": "/compojure/db/",
+      "update_url": "/compojure/updates/",
       "fortune_url": "/compojure/fortune-hiccup",
       "plaintext_url": "/compojure/plaintext",
       "port": 8080,

+ 1 - 2
frameworks/Clojure/compojure/hello/project.clj

@@ -9,8 +9,7 @@
                  [mysql/mysql-connector-java "5.1.6"]
                  [org.clojure/java.jdbc "0.3.0-alpha1"]
                  [c3p0/c3p0 "0.9.1.2"]
-                 [hiccup "1.0.4"]
-                 ]
+                 [hiccup "1.0.4"]]
   :plugins [[lein-ring "0.8.10"]]
   :ring {:handler hello.handler/app}
   :profiles

+ 137 - 49
frameworks/Clojure/compojure/hello/src/hello/handler.clj

@@ -13,6 +13,7 @@
             [clojure.java.jdbc :as jdbc]
             [clojure.java.jdbc.sql :as sql]))
 
+
 ; Database connection
 (defdb db (mysql {:subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
                   :user "benchmarkdbuser"
@@ -22,6 +23,7 @@
                   :maximum-pool-size 256
                   }))
 
+
 ; Set up entity World and the database representation
 (defentity world
   (pk :id)
@@ -29,19 +31,23 @@
   (entity-fields :id :randomNumber)
   (database db))
 
-; Query a random World record from the database
-(defn get-world []
+
+(defn get-world
+  "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (select world
             (fields :id :randomNumber)
             (where {:id id }))))
 
-; Run the specified number of queries, return the results
-(defn run-queries [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world))))
+
+(defn run-queries
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries ; Number of queries to run
+          (repeatedly get-world))))
+
 
 ; Database connection for java.jdbc "raw"
 ; https://github.com/clojure/java.jdbc/blob/master/doc/clojure/java/jdbc/ConnectionPooling.md
@@ -52,6 +58,7 @@
    :user "benchmarkdbuser"
    :password "benchmarkdbpass"})
 
+
 (defn pool
   [spec]
   (let [cpds (doto (ComboPooledDataSource.)
@@ -65,35 +72,42 @@
                (.setMaxIdleTime (* 3 60 60)))]
     {:datasource cpds}))
 
+
 (def pooled-db (delay (pool db-spec-mysql-raw)))
 
+
 (defn db-raw [] @pooled-db)
 
-; Query a random World record from the database
-(defn get-world-raw []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
+
+(defn get-world-raw
+  "Query a random World record from the database"
+  []
+  (let [id (inc (rand-int 9999))]
     (jdbc/with-connection (db-raw)
       ; Set a naming strategy to preserve column name case
       (jdbc/with-naming-strategy {:keyword identity}
         (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
           (doall rs))))))
 
-; Run the specified number of queries, return the results
-(defn run-queries-raw [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world-raw))))
 
-(defn get-query-count [queries]
+(defn run-queries-raw
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries
+          (repeatedly get-world-raw))))
+
+
+(defn get-query-count
   "Parse provided string value of query count, clamping values to between 1 and 500."
-  (let [q (try (Integer/parseInt queries)
+  [queries]
+  (let [n (try (Integer/parseInt queries)
                (catch Exception e 1))] ; default to 1 on parse failure
-    (if (> q 500)
-      500 ; clamp to 500 max
-      (if (< q 1)
-        1 ; clamp to 1 min
-        q)))) ; otherwise use provided value
+    (cond
+      (< n 1) 1
+      (> n 500) 500
+      :else n)))
+
 
 ; Set up entity World and the database representation
 (defentity fortune
@@ -102,19 +116,27 @@
   (entity-fields :id :message)
   (database db))
 
-(defn get-all-fortunes []
+
+(defn get-all-fortunes
   "Query all Fortune records from the database."
-    (select fortune
-            (fields :id :message)))
+  []
+  (select fortune
+          (fields :id :message)))
+
 
-(defn get-fortunes []
+(defn get-fortunes
   "Fetch the full list of Fortunes from the database, sort them by the fortune
-message text, and then return the results."
-  (let [fortunes (conj (get-all-fortunes) {:id 0 :message "Additional fortune added at request time."} )]
+  message text, and then return the results."
+  []
+  (let [fortunes (conj (get-all-fortunes)
+                       {:id 0
+                        :message "Additional fortune added at request time."})]
     (sort-by #(:message %) fortunes)))
 
-(defn fortunes-hiccup [fortunes]
+
+(defn fortunes-hiccup
   "Render the given fortunes to simple HTML using Hiccup."
+  [fortunes]
   (html5
    [:head
     [:title "Fortunes"]]
@@ -129,27 +151,93 @@ message text, and then return the results."
         [:td (escape-html (:message x))]])
      ]]))
 
-(defn fortunes-enlive [fortunes]
-  "Render the given fortunes to simple HTML using Enlive."
-  "todo")
 
-; Define route handlers
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (let [results (run-queries queries)]
+    (for [w results]
+      (update-in w [:randomNumber (inc (rand-int 9999))]
+        (update world
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))
+
+
+(def json-serialization
+  "Test 1: JSON serialization"
+  (response {:message "Hello, World!"}))
+
+
+(def single-query-test
+  "Test 2: Single database query"
+  (-> 1
+      (run-queries)
+      (first)
+      (response)))
+
+
+(defn multiple-query-test
+  "Test 3: Multiple database queries"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries)
+      (response)))
+
+
+(def single-query-test-raw
+  "Test 2: Single database query (raw)"
+  (-> 1
+      (run-queries-raw)
+      (first)
+      (response)))
+
+
+(defn multiple-query-test-raw
+  "Test 3: Multiple database queries (raw)"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries-raw)
+      (response)))
+
+
+(def fortune-test
+  "Test 4: Fortunes"
+  (response (fortunes-hiccup (get-fortunes))))
+
+
+(defn db-updates
+  "Test 5: Database updates"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (update-and-persist)
+      (response)))
+
+(def plaintext
+  "Test 6: Plaintext"
+  {:status 200
+   :headers {"Content-Type" "text/plain; charset=utf-8"}
+   :body "Hello, World!"})
+
+
 (defroutes app-routes
-  (GET "/" [] "Hello, World!")
-  (GET "/plaintext" []
-       {:status 200
-        :headers {"Content-Type" "text/plain; charset=utf-8"}
-        :body "Hello, World!"})
-  (GET "/json" [] (response {:message "Hello, World!"}))
-  (GET "/db" [] (response (first (run-queries 1))))
-  (GET "/db/:queries" [queries] (response (run-queries (get-query-count queries))))
-  (GET "/dbraw" [] (response (first (run-queries-raw 1))))
-  (GET "/dbraw/:queries" [queries] (response (run-queries-raw (get-query-count queries))))
-  (GET "/fortune" [] (response (get-fortunes)))
-  (GET "/fortune-hiccup" [] (fortunes-hiccup (get-fortunes)))
-  (GET "/fortune-enlive" [] (fortunes-enlive (get-fortunes)))
+  (GET "/"                 [] "Hello, World!")
+  (GET "/json"             [] json-serialization)
+  (GET "/db"               [] single-query-test)
+  (GET "/db/:queries"      [queries] (multiple-query-test queries))
+  (GET "/dbraw"            [] single-query-test-raw)
+  (GET "/dbraw/:queries"   [queries] (multiple-query-test-raw queries))
+  (GET "/fortunes"         [] (response (get-fortunes))) ; Raw json of fortunes
+  (GET "/fortune-hiccup"   [] fortune-test)
+  (GET "/updates/:queries" [queries] (db-updates queries))
+  (GET "/plaintext"        [] plaintext)
   (route/not-found "Not Found"))
 
-; Format responses as JSON
+
 (def app
+  "Format responses as JSON"
   (wrap-json-response app-routes))

+ 12 - 7
frameworks/Clojure/compojure/setup.sh

@@ -2,17 +2,22 @@
 
 source $IROOT/java7.installed
 
-export RESIN_HOME=${IROOT}/resin-4.0.41
-export LEIN_HOME=$IROOT/lein
+source $IROOT/lein.installed
 
-# Path vars must be set here
-export PATH="$JAVA_HOME/bin:$PATH"
+export RESIN_HOME=${IROOT}/resin-4.0.41
 
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/handler.clj
 
 cd hello
-$LEIN_HOME/bin/lein clean
-$LEIN_HOME/bin/lein ring uberwar
+lein clean
+lein ring uberwar
 rm -rf $RESIN_HOME/webapps/*
 cp target/hello-compojure-standalone.war $RESIN_HOME/webapps/compojure.war
-$RESIN_HOME/bin/resinctl start
+
+$RESIN_HOME/bin/resinctl start
+
+# preform an initial request to warm up the server
+# initial requests were taking >15 seconds, causing fails in the tests
+echo "Sleeping, then executing an initial request to ensure server is in a responsive state"
+sleep 30
+curl -m 60 http://localhost:8080/compojure/ > /dev/null 2>&1

+ 6 - 3
frameworks/Clojure/http-kit/benchmark_config.json

@@ -3,9 +3,12 @@
   "tests": [{
     "default": {
       "setup_file": "setup",
-      "json_url": "/http-kit/json",
-      "db_url": "/http-kit/db",
-      "query_url": "/http-kit/db/",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries/",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates/",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 10 - 2
frameworks/Clojure/http-kit/hello/project.clj

@@ -6,9 +6,17 @@
                  [ring/ring-json "0.2.0"]
                  [org.clojure/tools.cli "0.2.1"]
                  [http-kit/dbcp "0.1.0"]
-                 [http-kit "2.0.1"]
+                 [http-kit "2.1.18"]
                  [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
-                 [mysql/mysql-connector-java "5.1.6"]]
+                 ; [ch.qos.logback/logback-classic "1.1.2" :exclusions [org.slf4j/slf4j-api]]
+                 ; [org.slf4j/jul-to-slf4j "1.7.7"]
+                 ; [org.slf4j/jcl-over-slf4j "1.7.7"]
+                 ; [org.slf4j/log4j-over-slf4j "1.7.7"]
+                 [org.clojure/data.json "0.2.5"]
+                 [org.clojure/java.jdbc "0.3.6"]
+                 [korma "0.4.0"]
+                 [mysql/mysql-connector-java "5.1.6"]
+                 [hiccup "1.0.4"]]
   :main hello.handler
   :aot [hello.handler]
   :uberjar-name "http-kit-standalone.jar"

+ 182 - 47
frameworks/Clojure/http-kit/hello/src/hello/handler.clj

@@ -1,72 +1,207 @@
 (ns hello.handler
   (:gen-class)
+  (:import com.mchange.v2.c3p0.ComboPooledDataSource)
   (:use compojure.core
         ring.middleware.json
         org.httpkit.server
         [clojure.tools.cli :only [cli]]
-        ring.util.response)
+        korma.db
+        korma.core
+        hiccup.core
+        hiccup.util
+        hiccup.page)
   (:require [compojure.handler :as handler]
-            [org.httpkit.dbcp :as db]
-            [compojure.route :as route]))
-
-;;; convert to int
-(defn to-int [s] (cond
-                  (string? s) (Integer/parseInt s)
-                  (instance? Integer s) s
-                  (instance? Long s) (.intValue ^Long s)
-                  :else 0))
-
-;; Query a random World record from the database
-(defn get-world []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
-    ; Set a naming strategy to preserve column name case
-    (clojure.java.jdbc/with-naming-strategy {:keyword identity}
-      (db/query "select * from world where id = ?" id))))
-
-;; Run the specified number of queries, return the results
-(defn run-queries [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world))))
-
-(defn get-query-count [queries]
-  "Parse provided string value of query count, clamping values to between 1 and 500."
-  (let [q (try (Integer/parseInt queries)
+            [compojure.route :as route]
+            [ring.util.response :as ring-resp]
+            [clojure.data.json :as json]
+            [clojure.java.jdbc :as jdbc]))
+
+
+(defn parse-port [s] 
+  "Convert stringy port number int. Defaults to 8080."
+  (cond
+    (string? s) (Integer/parseInt s)
+    (instance? Integer s) s
+    (instance? Long s) (.intValue ^Long s)
+    :else 8080))
+
+
+;; MySQL connection
+(defdb mysql-db
+  (mysql {
+    :classname "com.mysql.jdbc.Driver"
+    :subprotocol "mysql"
+    :subname "//127.0.0.1:3306/hello_world"
+    :user "benchmarkdbuser"
+    :password "benchmarkdbpass"
+    ;;OPTIONAL KEYS
+    :delimiters "" ;; remove delimiters
+    :maximum-pool-size 256}))
+
+
+;; Set up entity World and the database representation
+(defentity world
+  (pk :id)
+  (table :world)
+  (entity-fields :id :randomNumber) ;; Default fields for select
+  (database mysql-db))
+
+
+(defn sanitize-queries-param
+  "Sanitizes the `queries` parameter. Caps the value between 1 and 500.
+  Invalid (stringy) values become 1"
+  [queries]
+  (let [n (try (Integer/parseInt queries)
                (catch Exception e 1))] ; default to 1 on parse failure
-    (if (> q 500)
-      500 ; clamp to 500 max
-      (if (< q 1)
-        1 ; clamp to 1 min
-        q)))) ; otherwise use provided value
+    (cond
+      (< n 1) 1
+      (> n 500) 500
+      :else n)))
+
+
+(defn random-world
+  "Query a random World record from the database"
+  []
+  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
+    (select world
+            (where {:id id }))))
+
+
+(defn run-queries
+  "Run query repeatedly -- Always returns an array"
+  [queries]
+  (flatten (take queries (repeatedly random-world))))
+
+; Set up entity Fortune and the database representation
+(defentity fortune
+  (pk :id)
+  (table :fortune)
+  (entity-fields :id :message)
+  (database mysql-db))
+
+
+(defn get-all-fortunes
+  "Query all Fortune records from the database."
+  []
+  (select fortune
+          (fields :id :message)))
+
+
+(defn get-fortunes
+  "Fetch the full list of Fortunes from the database, sort them by the fortune
+  message text, and then return the results."
+  []
+  (sort-by #(:message %)
+    (conj
+      (get-all-fortunes)
+      { :id 0 :message "Additional fortune added at request time." })))
+
+
+(defn fortunes-hiccup
+  "Render the given fortunes to simple HTML using Hiccup."
+  [fortunes]
+  (html5
+   [:head
+    [:title "Fortunes"]]
+   [:body
+    [:table
+     [:tr
+      [:th "id"]
+      [:th "message"]]
+     (for [x fortunes]
+       [:tr
+        [:td (:id x)]
+        [:td (escape-html (:message x))]])
+     ]]))
+
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (let [results (-> queries
+                    (sanitize-queries-param)
+                    (run-queries))]
+    (for [w results]
+      (update-in w [:randomNumber (inc (rand-int 9999))]
+        (update world
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))
+
+
+(def json-serialization
+  "Test 1: JSON serialization"
+  (ring-resp/response {:message "Hello, World!"}))
+
+
+(def single-query-test
+  "Test 2: Single database query"
+  (ring-resp/response (first (run-queries 1))))
+
+
+(defn multiple-queries-test
+  "Test 3: Multiple database queries"
+  [queries]
+  (-> queries
+      (sanitize-queries-param)
+      (run-queries)
+      (ring-resp/response)
+      (ring-resp/content-type "application/json")))
+
+
+(def fortune-test
+  "Test 4: Fortunes"
+  (->
+    (get-fortunes)
+    (fortunes-hiccup)
+    (ring-resp/response)
+    (ring-resp/content-type "text/html")))
+
+
+(defn db-updates
+  "Test 5: Database updates"
+  [queries]
+  (-> queries
+      (update-and-persist)
+      (ring-resp/response)))
+
+
+(def plaintext
+  "Test 6: Plaintext"
+  (->
+    (ring-resp/response "Hello, World!")
+    (ring-resp/content-type "text/plain")))
+
 
 ;; Define route handlers
 (defroutes app-routes
-  (GET "/http-kit/" [] "Hello, World!")
-  (GET "/http-kit/json" [] (response {:message "Hello, World!"}))
-  (GET "/http-kit/db" []
-       (response (first (run-queries 1))))
-  (GET "/http-kit/db/:queries" [queries]
-       (response (run-queries (get-query-count queries))))
+  (GET "/"                 [] "Hello, World!")
+  (GET "/json"             [] json-serialization)
+  (GET "/db"               [] single-query-test)
+  (GET "/queries/:queries" [queries] (multiple-queries-test queries))
+  (GET "/fortunes"         [] fortune-test)
+  (GET "/updates/:queries" [queries] (db-updates queries))
+  (GET "/plaintext"        [] plaintext)
   (route/not-found "Not Found"))
 
 
-(defn start-server [{:keys [port db-host]}]
-  (db/use-database! (str "jdbc:mysql://" db-host "/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true")
-                    "benchmarkdbuser"
-                    "benchmarkdbpass")
+(defn start-server [{:keys [port]}]
   ;; Format responses as JSON
   (let [handler (wrap-json-response app-routes)
         cpu (.availableProcessors (Runtime/getRuntime))]
     ;; double worker threads should increase database access performance
-    (run-server handler {:port port :thread (* 2 cpu)})
+    (run-server handler {:port port
+                         :thread (* 2 cpu)})
     (println (str "http-kit server listens at :" port))))
 
+
 (defn -main [& args]
   (let [[options _ banner]
         (cli args
-             ["-p" "--port" "Port to listen" :default 8080 :parse-fn to-int]
-             ["--db-host" "MySQL database host" :default "localhost"]
+             ["-p" "--port" "Port to listen" :default 8080 :parse-fn parse-port]
              ["--[no-]help" "Print this help"])]
-    (when (:help options) (println banner) (System/exit 0))
+    (when (:help options)
+          (println banner)
+          (System/exit 0))
     (start-server options)))

+ 9 - 5
frameworks/Clojure/http-kit/setup.sh

@@ -1,13 +1,17 @@
 #!/bin/bash
 source $IROOT/java7.installed
-export LEIN_HOME=$IROOT/lein
+source $IROOT/lein.installed
+
+
+# Update db host in the source file
+sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/handler.clj
 
 cd hello
-$LEIN_HOME/bin/lein clean
-$LEIN_HOME/bin/lein deps
+lein clean
+lein deps
 rm -rf target
 # pack all dependencies into a single jar: target/http-kit-standalone.jar
-$LEIN_HOME/bin/lein uberjar
+lein uberjar
 # -server is much faster
 # 'lein run' passes '-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' which make it starts fast, but runs slow
-$JAVA_HOME/bin/java -server -jar target/http-kit-standalone.jar --db-host ${DBHOST} &
+java -server -jar target/http-kit-standalone.jar  &

+ 1 - 0
frameworks/Clojure/luminus/benchmark_config.json

@@ -7,6 +7,7 @@
       "db_url": "/luminus/db",
       "query_url": "/luminus/db/",
       "fortune_url": "/luminus/fortune",
+      "update_url": "/luminus/update/",
       "plaintext_url": "/luminus/plaintext",
       "port": 8080,
       "approach": "Realistic",

+ 4 - 0
frameworks/Clojure/luminus/hello/src/hello/handler.clj

@@ -6,13 +6,16 @@
             [taoensso.timbre :as timbre]
             [taoensso.timbre.appenders.rotor :as rotor]))
 
+
 (defroutes app-routes
   (route/resources "/")
   (route/not-found "Not Found"))
 
+
 (defn destroy []
   (timbre/info "picture-gallery is shutting down"))
 
+
 (defn init
   "init will be called once when
    app is deployed as a servlet on
@@ -33,6 +36,7 @@
 
   (timbre/info "hello started successfully"))
 
+
 (defn destroy
   "destroy will be called when your application
    shuts down, put any clean up code here"

+ 44 - 22
frameworks/Clojure/luminus/hello/src/hello/models/db.clj

@@ -12,15 +12,19 @@
   (entity-fields :id :randomNumber)
   (database db))
 
-; Query a random World record from the database
-(defn get-world []
+
+(defn get-world
+  "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (select world
             (fields :id :randomNumber)
             (where {:id id }))))
 
-; Query a random World record from the database
-(defn get-world-raw []
+
+(defn get-world-raw
+  "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (jdbc/with-connection (db-raw)
       ; Set a naming strategy to preserve column name case
@@ -28,19 +32,21 @@
         (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
           (doall rs))))))
 
-; Run the specified number of queries, return the results
-(defn run-queries [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world))))
 
-; Run the specified number of queries, return the results
+(defn run-queries
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries
+          (repeatedly get-world))))
+
+
 (defn run-queries-raw [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world-raw))))
+  "Run the specified number of queries, return the results"
+  (flatten ; Make it a list of maps
+    (take queries
+          (repeatedly get-world-raw))))
+
 
 (defn get-query-count [queries]
   "Parse provided string value of query count, clamping values to between 1 and 500."
@@ -60,13 +66,29 @@
   (entity-fields :id :message)
   (database db))
 
-(defn get-all-fortunes []
+
+(def get-all-fortunes
   "Query all Fortune records from the database."
-    (select fortune
-            (fields :id :message)))
+  (select fortune
+          (fields :id :message)))
+
 
-(defn get-fortunes []
-  "Fetch the full list of Fortunes from the database, sort them by the fortune
-   message text, and then return the results."
-  (let [fortunes (conj (get-all-fortunes) {:id 0 :message "Additional fortune added at request time."} )]
+(def get-fortunes
+  "Fetch the full list of Fortunes from the database. Insert an additional fortune at runtime.
+  Then sort all by fortune message text. Return the results."
+  (let [fortunes (conj get-all-fortunes
+                       {:id 0 :message "Additional fortune added at request time."})]
     (sort-by :message fortunes)))
+
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (let [results (run-queries queries)]
+    (for [w results]
+      (update-in w [:randomNumber (inc (rand-int 9999))]
+        (update world
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))

+ 68 - 12
frameworks/Clojure/luminus/hello/src/hello/routes/home.clj

@@ -4,16 +4,72 @@
   (:require [hello.views.layout :as layout]
             [noir.response :as response]))
 
-(defroutes home-routes
-  (GET "/" [] "Hello, World!")
-  (GET "/plaintext" []
-       {:status 200
-        :headers {"Content-Type" "text/plain; charset=utf-8"}
-        :body "Hello, World!"})
-  (GET "/json" [] (response/json {:message "Hello, World!"}))
-  (GET "/db" [] (response/json (first (run-queries 1))))
-  (GET "/db/:queries" [queries] (response/json (run-queries (get-query-count queries))))
-  (GET "/dbraw" [] (response/json (first (run-queries-raw 1))))
-  (GET "/dbraw/:queries" [queries] (response/json (run-queries-raw (get-query-count queries))))  
-  (GET "/fortune" [] (layout/render "home.html" {:messages (get-fortunes)})))
 
+(def json-serialization
+  "Test 1: JSON serialization"
+  (response/json {:message "Hello, World!"}))
+
+
+(def single-query-test
+  "Test 2: Single database query"
+  (response/json (first (run-queries 1))))
+
+
+(defn multiple-query-test
+  "Test 3: Multiple database query"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries)
+      (response/json)))
+
+
+(def single-query-test-raw
+  "Test 2: Single database query (raw)"
+  (-> 1
+      (run-queries-raw)
+      (first)
+      (response/json)))
+
+
+(defn multiple-query-test-raw
+  "Test 3: Multiple database query (raw)"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries-raw)
+      (response/json)))
+
+
+(def fortunes
+  "Test 4: Fortunes"
+  (layout/render "home.html"
+                 {:messages get-fortunes}))
+
+
+(defn db-update
+  "Test 5: Database updates"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (update-and-persist)
+      (response/json)))
+
+
+(def plaintext
+  "Test 6: Plaintext"
+  {:status 200
+   :headers {"Content-Type" "text/plain; charset=utf-8"}
+   :body "Hello, World!"})
+
+
+(defroutes home-routes
+  (GET "/"                [] "Hello, World!")
+  (GET "/plaintext"       [] plaintext)
+  (GET "/json"            [] json-serialization)
+  (GET "/db"              [] single-query-test)
+  (GET "/db/:queries"     [queries] (multiple-query-test queries))
+  (GET "/dbraw"           [] single-query-test-raw)
+  (GET "/dbraw/:queries"  [queries] (multiple-query-test-raw queries))
+  (GET "/fortune"         [] fortunes)
+  (GET "/update/:queries" [queries] (db-update queries)))

+ 5 - 2
frameworks/Clojure/luminus/setup.sh

@@ -1,6 +1,9 @@
 #!/bin/bash
 
 source $IROOT/java7.installed
+
+source $IROOT/lein.installed
+
 export RESIN_HOME=${IROOT}/resin-4.0.41
 
 # Path vars must be set here
@@ -9,8 +12,8 @@ export PATH="$JAVA_HOME/bin:$PATH"
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/models/schema.clj
 
 cd hello
-$IROOT/lein/bin/lein clean
-$IROOT/lein/bin/lein ring uberwar
+lein clean
+lein ring uberwar
 rm -rf $RESIN_HOME/webapps/*
 cp target/hello-luminus-standalone.war $RESIN_HOME/webapps/luminus.war
 $RESIN_HOME/bin/resinctl start

+ 36 - 28
frameworks/Clojure/pedestal/src/pedestal/service.clj

@@ -41,11 +41,12 @@
   (database mysql-db))
 
 
-(defn random-world []
+(defn random-world
   "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (select world
-      (where {:id id }))))
+            (where {:id id }))))
 
 
 (defn run-queries
@@ -62,26 +63,27 @@
 
 (defn sanitizeQueriesParam
   "Sanitizes the `queries` parameter. Caps the value between 1 and 500.
-Invalid (stringy) values become 1"
+  Invalid (stringy) values become 1"
   [request]
-  (let [queries (-> request :params :queries)]
-    (let [n
-      (if (= (re-find #"\A-?\d+" queries) nil)
-        1
-        (Integer/parseInt queries))]
-    (cond
-      (< n 1) 1
-      (> n 500) 500
-      :else n))))
+  (let [queries (-> request
+                    :params
+                    :queries)]
+    (if-let [n (if (= (re-find #"\A-?\d+" queries) nil)
+                   1
+                   (Integer/parseInt queries))]
+      (cond
+        (< n 1) 1
+        (> n 500) 500
+        :else n))))
 
 
 (defn multiple-query-test
   "Test 3: Multiple database queries"
   [request]
   (-> request
-    (sanitizeQueriesParam)
-    (run-queries)
-    (bootstrap/json-response)))
+      (sanitizeQueriesParam)
+      (run-queries)
+      (bootstrap/json-response)))
 
 
 ; Set up entity Fortune and the database representation
@@ -92,23 +94,26 @@ Invalid (stringy) values become 1"
   (database mysql-db))
 
 
-(defn get-all-fortunes []
+(defn get-all-fortunes
   "Query all Fortune records from the database."
+  []
   (select fortune
-    (fields :id :message)))
+          (fields :id :message)))
 
 
-(defn get-fortunes []
+(defn get-fortunes
   "Fetch the full list of Fortunes from the database, sort them by the fortune
-message text, and then return the results."
+  message text, and then return the results."
+  []
   (sort-by #(:message %)
     (conj
       (get-all-fortunes)
       { :id 0 :message "Additional fortune added at request time." })))
 
 
-(defn fortunes-hiccup [fortunes]
+(defn fortunes-hiccup
   "Render the given fortunes to simple HTML using Hiccup."
+  [fortunes]
   (html5
    [:head
     [:title "Fortunes"]]
@@ -124,8 +129,9 @@ message text, and then return the results."
      ]]))
 
 
-(defn fortune-test [request]
+(defn fortune-test
   "Test 4: Fortunes"
+  [request]
   (->
     (get-fortunes)
     (fortunes-hiccup)
@@ -136,23 +142,25 @@ message text, and then return the results."
 
 (defn update-and-persist
   "Changes the :randomNumber of a number of world entities.
-Persists the changes to sql then returns the updated entities"
+  Persists the changes to sql then returns the updated entities"
   [request]
-  (let [results (-> request (sanitizeQueriesParam) (run-queries))]
+  (let [results (-> request
+                    (sanitizeQueriesParam)
+                    (run-queries))]
     (for [w results]
       (update-in w [:randomNumber (inc (rand-int 9999))]
         (update world
-          (set-fields {:randomNumber (:randomNumber w)})
-          (where {:id [:id w]}))))
-  results))
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))
 
 
 (defn db-updates
   "Test 5: Database updates"
   [request]
   (-> request
-    (update-and-persist)
-    (bootstrap/json-response)))
+      (update-and-persist)
+      (bootstrap/json-response)))
 
 
 (defn plaintext

+ 1 - 2
toolset/benchmark/test_types/framework_test_type.py

@@ -77,9 +77,8 @@ class FrameworkTestType:
   def _curl_body(self, url):
     '''Downloads a URL and returns the HTTP body'''
     # Use -m 15 to make curl stop trying after 15sec.
-    # Use -i to output response with headers
     # Don't use -f so that the HTTP response code is ignored.
-    # Use -sS to hide progress bar, but show errors.
+    # Use -s to hide progress bar
     # Get response body
     p = subprocess.Popen(["curl", "-m", "15", "-s", url], stdout=PIPE, stderr=PIPE)
     (out, err) = p.communicate()