Browse Source

Merge remote-tracking branch 'upstream/master' into dropwizard-plaintext

zloster 10 years ago
parent
commit
7365e70783
97 changed files with 1751 additions and 153 deletions
  1. 1 0
      .travis.yml
  2. 0 1
      benchmark.cfg.example
  3. 2 2
      frameworks/C++/treefrog/setup-thread.py
  4. 2 2
      frameworks/C++/treefrog/setup.py
  5. 1 1
      frameworks/C++/wt/install.sh
  6. 1 1
      frameworks/C/lwan/install.sh
  7. 1 1
      frameworks/Erlang/cowboy/install.sh
  8. BIN
      frameworks/Erlang/cowboy/rebar
  9. 1 1
      frameworks/Erlang/cowboy/rebar.config
  10. 3 2
      frameworks/Erlang/cowboy/setup_erlang.py
  11. 1 1
      frameworks/Erlang/elli/install.sh
  12. BIN
      frameworks/Erlang/elli/rebar
  13. 1 1
      frameworks/Erlang/elli/rebar.config
  14. 3 2
      frameworks/Erlang/elli/setup_erlang.py
  15. 30 8
      frameworks/Java/dropwizard-mongodb/src/main/java/com/example/helloworld/resources/WorldResource.java
  16. 31 4
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/WorldResource.java
  17. 27 2
      frameworks/Java/play2-java/benchmark_config
  18. 12 10
      frameworks/Java/play2-java/generate_config.py
  19. 29 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/.gitignore
  20. 40 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md
  21. 151 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java
  22. 34 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java
  23. 38 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java
  24. 21 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java
  25. 8 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java
  26. 26 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java
  27. 23 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java
  28. 16 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/fortunes.scala.html
  29. 12 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/main.scala.html
  30. 17 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt
  31. 14 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml
  32. 97 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf
  33. 1 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/play.plugins
  34. 13 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes
  35. 1 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties
  36. 4 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt
  37. 11 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code
  38. 18 6
      frameworks/Java/play2-java/play2-java-jpa/README.md
  39. 51 10
      frameworks/Java/play2-java/play2-java-jpa/app/controllers/Application.java
  40. 34 0
      frameworks/Java/play2-java/play2-java-jpa/app/models/Fortune.java
  41. 21 6
      frameworks/Java/play2-java/play2-java-jpa/app/models/World.java
  42. 21 0
      frameworks/Java/play2-java/play2-java-jpa/app/utils/Headers.java
  43. 16 0
      frameworks/Java/play2-java/play2-java-jpa/app/views/fortunes.scala.html
  44. 12 0
      frameworks/Java/play2-java/play2-java-jpa/app/views/main.scala.html
  45. 1 1
      frameworks/Java/play2-java/play2-java-jpa/build.sbt
  46. 3 1
      frameworks/Java/play2-java/play2-java-jpa/conf/routes
  47. 1 1
      frameworks/Java/play2-java/play2-java-jpa/project/plugins.sbt
  48. 2 0
      frameworks/Java/play2-java/play2-java-jpa/source_code
  49. 6 0
      frameworks/Java/play2-java/setup_java_jpa_hikaricp.py
  50. 1 1
      frameworks/Lua/lapis/benchmark_config
  51. 16 3
      frameworks/Lua/lapis/web.lua
  52. 6 2
      frameworks/Lua/lapis/web.moon
  53. 1 1
      frameworks/Nimrod/nawak/setup.py
  54. 1 1
      frameworks/Nimrod/nawak/setup_redis.py
  55. 4 1
      frameworks/PHP/php-zend-framework/module/FrameworkBenchmarks/src/FrameworkBenchmarks/Controller/DbController.php
  56. 41 0
      frameworks/PHP/php-zend-framework1/.gitignore
  57. 0 0
      frameworks/PHP/php-zend-framework1/__init__.py
  58. 6 0
      frameworks/PHP/php-zend-framework1/application/Bootstrap.php
  59. 19 0
      frameworks/PHP/php-zend-framework1/application/configs/application.ini
  60. 12 0
      frameworks/PHP/php-zend-framework1/application/controllers/DbController.php
  61. 20 0
      frameworks/PHP/php-zend-framework1/application/controllers/DbMultiController.php
  62. 54 0
      frameworks/PHP/php-zend-framework1/application/controllers/ErrorController.php
  63. 9 0
      frameworks/PHP/php-zend-framework1/application/controllers/JsonController.php
  64. 29 0
      frameworks/PHP/php-zend-framework1/application/views/scripts/error/error.phtml
  65. 9 0
      frameworks/PHP/php-zend-framework1/bash_profile.sh
  66. 25 0
      frameworks/PHP/php-zend-framework1/benchmark_config
  67. 6 0
      frameworks/PHP/php-zend-framework1/composer.json
  68. 133 0
      frameworks/PHP/php-zend-framework1/deploy/nginx.conf
  69. 9 0
      frameworks/PHP/php-zend-framework1/deploy/php-zend-framework
  70. 3 0
      frameworks/PHP/php-zend-framework1/install.sh
  71. 36 0
      frameworks/PHP/php-zend-framework1/lint.xml
  72. 34 0
      frameworks/PHP/php-zend-framework1/phpunit.xml.dist
  73. 16 0
      frameworks/PHP/php-zend-framework1/public/.htaccess
  74. 21 0
      frameworks/PHP/php-zend-framework1/public/index.php
  75. 26 0
      frameworks/PHP/php-zend-framework1/script/setup_dev_and_test_db.php
  76. 24 0
      frameworks/PHP/php-zend-framework1/setup.py
  77. 43 0
      frameworks/PHP/php-zend-framework1/test/application/controllers/DbControllerTest.php
  78. 76 0
      frameworks/PHP/php-zend-framework1/test/application/controllers/DbMultiControllerTest.php
  79. 30 0
      frameworks/PHP/php-zend-framework1/test/application/controllers/JsonControllerTest.php
  80. 22 0
      frameworks/PHP/php-zend-framework1/test/bootstrap.php
  81. 1 1
      frameworks/Scala/play-activate-mysql/setup.py
  82. 67 30
      toolset/benchmark/benchmarker.py
  83. 16 13
      toolset/benchmark/framework_test.py
  84. 5 1
      toolset/benchmark/test_types/db_type.py
  85. 4 3
      toolset/benchmark/test_types/framework_test_type.py
  86. 2 2
      toolset/benchmark/test_types/plaintext_type.py
  87. 15 8
      toolset/benchmark/test_types/query_type.py
  88. 1 1
      toolset/benchmark/utils.py
  89. 1 1
      toolset/run-ci.py
  90. 16 9
      toolset/run-tests.py
  91. 4 3
      toolset/setup/linux/frameworks/wt.sh
  92. 3 3
      toolset/setup/linux/languages/python2.sh
  93. 3 3
      toolset/setup/linux/languages/python3.sh
  94. 3 1
      toolset/setup/linux/languages/rvm.sh
  95. 1 1
      toolset/setup/linux/setup_util.py
  96. 12 0
      toolset/setup/linux/systools/rebar.sh
  97. 6 0
      toolset/setup/linux/webservers/apache.sh

+ 1 - 0
.travis.yml

@@ -123,6 +123,7 @@ env:
     - "TESTDIR=PHP/php-yaf"
     - "TESTDIR=PHP/php-yii2"
     - "TESTDIR=PHP/php-zend-framework"
+    - "TESTDIR=PHP/php-zend-framework1"
     - "TESTDIR=PHP/phreeze"
     - "TESTDIR=Python/bottle"
     - "TESTDIR=Python/django"

+ 0 - 1
benchmark.cfg.example

@@ -21,7 +21,6 @@ threads=8
 mode=benchmark
 name=ec2
 os=linux
-parse=None
 password_prompt=False
 server_host=localhost
 sleep=60

+ 2 - 2
frameworks/C++/treefrog/setup-thread.py

@@ -22,7 +22,7 @@ def start(args, logfile, errfile):
     subprocess.check_call("make clean", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("make -j8", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("rm -f log/*.log", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
-    subprocess.check_call("treefrog -d " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("treefrog -d $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
@@ -32,7 +32,7 @@ def start(args, logfile, errfile):
 ##############
 def stop(logfile, errfile):
   try:
-    subprocess.call("treefrog -k abort " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("treefrog -k abort $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 2 - 2
frameworks/C++/treefrog/setup.py

@@ -22,7 +22,7 @@ def start(args, logfile, errfile):
     subprocess.check_call("make clean", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("make -j8", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("rm -f log/*.log", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
-    subprocess.check_call("treefrog -d " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("treefrog -d $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
@@ -32,7 +32,7 @@ def start(args, logfile, errfile):
 ##############
 def stop(logfile, errfile):
   try:
-    subprocess.call("treefrog -k abort " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("treefrog -k abort $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 1 - 1
frameworks/C++/wt/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends wt
+fw_depends apache wt

+ 1 - 1
frameworks/C/lwan/install.sh

@@ -10,7 +10,7 @@ RETCODE=$(fw_exists ${INSTALLED_FILE})
 
 # Lwan is only built during installation as a dependency sanity check.
 sudo apt-get update && \
-	sudo apt-get install libjemalloc-dev libmysqlclient-dev libsqlite3-dev && \
+	sudo apt-get install -qqy libjemalloc-dev libmysqlclient-dev libsqlite3-dev && \
 	git clone git://github.com/lpereira/lwan.git && \
         cd lwan && \
         git checkout ${REV} && \

+ 1 - 1
frameworks/Erlang/cowboy/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends erlang
+fw_depends erlang rebar

BIN
frameworks/Erlang/cowboy/rebar


+ 1 - 1
frameworks/Erlang/cowboy/rebar.config

@@ -1,6 +1,6 @@
 {deps,
  [
-  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.3"}}},
+  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.5"}}},
   {mimetypes, ".*", {git, "http://github.com/spawngrid/mimetypes.git", {branch, master}}},
   {emysql, ".*", {git, "https://github.com/Eonblast/Emysql.git"}},
   {cowboy, ".*", {git, "https://github.com/extend/cowboy.git", {tag, "0.8.3"}}}

+ 3 - 2
frameworks/Erlang/cowboy/setup_erlang.py

@@ -6,8 +6,9 @@ def start(args, logfile, errfile):
   setup_util.replace_text("cowboy/src/hello_world_app.erl", "\"benchmarkdbpass\", \".*\", 3306", "\"benchmarkdbpass\", \"" + args.database_host + "\", 3306")
 
   try:
-    subprocess.check_call("./rebar get-deps", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
-    subprocess.check_call("./rebar compile", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
+    subprocess.check_call("rm -rf deps/*", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar get-deps", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar compile", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
     subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:

+ 1 - 1
frameworks/Erlang/elli/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends erlang
+fw_depends erlang rebar

BIN
frameworks/Erlang/elli/rebar


+ 1 - 1
frameworks/Erlang/elli/rebar.config

@@ -1,6 +1,6 @@
 {deps,
  [
-  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.3"}}},
+  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.5"}}},
   {emysql, ".*", {git, "https://github.com/Eonblast/Emysql.git"}},
   {elli, "", {git, "git://github.com/knutin/elli.git"}}
  ]}.

+ 3 - 2
frameworks/Erlang/elli/setup_erlang.py

@@ -6,8 +6,9 @@ def start(args, logfile, errfile):
   setup_util.replace_text("elli/src/elli_bench_sup.erl", "\"benchmarkdbpass\", \".*\", 3306", "\"benchmarkdbpass\", \"" + args.database_host + "\", 3306")
   
   try:
-    subprocess.check_call("./rebar get-deps", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
-    subprocess.check_call("./rebar compile", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
+    subprocess.check_call("rm -rf deps/*", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar get-deps", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar compile", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
     # adding +K true seemed to actually slow performance
     subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
     return 0

+ 30 - 8
frameworks/Java/dropwizard-mongodb/src/main/java/com/example/helloworld/resources/WorldResource.java

@@ -13,6 +13,7 @@ import org.mongojack.JacksonDBCollection;
 
 import com.example.helloworld.core.World;
 import com.google.common.base.Optional;
+import com.google.common.primitives.Ints;
 import com.mongodb.BasicDBObject;
 import com.mongodb.DBObject;
 
@@ -29,18 +30,39 @@ public class WorldResource
   }
 
   @GET
-  public World[] dbTest(@QueryParam("queries") Optional<Integer> queries)
+  public Object dbTest(@QueryParam("queries") Optional<String> queries)
   {
-    final int totalQueries = queries.or(1);
-    final World[] worlds = new World[queries.or(1)];
     final Random random = new Random(System.currentTimeMillis());
-
+    if (!queries.isPresent()) 
+    {
+      DBObject query = new BasicDBObject();
+      query.put("_id", (random.nextInt(10000) + 1));
+      DBCursor<World> dbCursor = collection.find(query);
+      return (dbCursor.hasNext()) ? dbCursor.next() : null;
+    }
+    Integer totalQueries = Ints.tryParse(queries.orNull());
+    if (totalQueries != null) 
+    {
+      if (totalQueries > 500) 
+      {
+        totalQueries = 500;
+      }
+      else if (totalQueries < 1) 
+      {
+        totalQueries = 1;
+      }
+    } 
+    else 
+    {
+      totalQueries = 1;
+    }
+    final World[] worlds = new World[totalQueries];
     for (int i = 0; i < totalQueries; i++)
     {
-    	DBObject query = new BasicDBObject();
-    	query.put("_id", (random.nextInt(10000) + 1));
-    	DBCursor<World> dbCursor = collection.find(query);
-        worlds[i] = (dbCursor.hasNext()) ? dbCursor.next() : null;
+      DBObject query = new BasicDBObject();
+      query.put("_id", (random.nextInt(10000) + 1));
+      DBCursor<World> dbCursor = collection.find(query);
+      worlds[i] = (dbCursor.hasNext()) ? dbCursor.next() : null;
     }
     return worlds;
   }

+ 31 - 4
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/WorldResource.java

@@ -3,6 +3,7 @@ package com.example.helloworld.resources;
 import com.example.helloworld.db.WorldDAO;
 import com.example.helloworld.db.model.World;
 import com.google.common.base.Optional;
+import com.google.common.primitives.Ints;
 import io.dropwizard.hibernate.UnitOfWork;
 
 import javax.ws.rs.GET;
@@ -26,8 +27,24 @@ public class WorldResource {
 
     @GET
     @UnitOfWork
-    public World[] dbTest(@QueryParam("queries") Optional<Integer> queries) {
-        final int totalQueries = queries.or(1); // TODO: Should be bound [1,500]
+    public Object dbTest(@QueryParam("queries") Optional<String> queries) {
+        if (!queries.isPresent()) {
+            final long worldId = RANDOM.nextInt(10_000) + 1;
+            return worldDAO.findById(worldId).orNull();
+        }
+
+        Integer totalQueries = Ints.tryParse(queries.orNull());
+        if (totalQueries != null) {
+            if (totalQueries > 500) {
+                totalQueries = 500;
+            } else if (totalQueries < 1) {
+                totalQueries = 1;
+            }
+        } else {
+            totalQueries = 1;
+        }
+
+        
         final World[] worlds = new World[totalQueries];
 
         // TODO: Is parallelising this cheating?
@@ -42,8 +59,18 @@ public class WorldResource {
     @GET
     @Path("/update")
     @UnitOfWork
-    public World[] updateTest(@QueryParam("queries") Optional<Integer> queries) {
-        final int totalQueries = queries.or(1); // TODO: Should be bound [1,500]
+    public World[] updateTest(@QueryParam("queries") Optional<String> queries) {
+        Integer totalQueries = Ints.tryParse(queries.orNull());
+        if (totalQueries != null) {
+            if (totalQueries > 500) {
+                totalQueries = 500;
+            } else if (totalQueries < 1) {
+                totalQueries = 1;
+            }
+        } else {
+            totalQueries = 1;
+        }
+
         final World[] worlds = new World[totalQueries];
 
         // TODO: Is parallelising this cheating?

+ 27 - 2
frameworks/Java/play2-java/benchmark_config

@@ -56,8 +56,33 @@
         "versus": "netty", 
         "port": "9000", 
         "db_url": "/db", 
-        "query_url": "/queries?queries="
+        "query_url": "/queries?queries=", 
+        "fortune_url": "/fortunes", 
+        "update_url": "/update?queries=", 
+        "plaintext_url": "/plaintext"
+      }, 
+      "java-jpa-hikaricp": {
+        "display_name": "play2-java-jpa-hikaricp", 
+        "setup_file": "setup_java_jpa_hikaricp", 
+        "framework": "play2", 
+        "language": "Java", 
+        "orm": "Full", 
+        "os": "Linux", 
+        "database": "MySQL", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "db_url": "/db", 
+        "query_url": "/queries?queries=", 
+        "fortune_url": "/fortunes", 
+        "update_url": "/update?queries=", 
+        "plaintext_url": "/plaintext"
       }
     }
   ]
-}
+}

+ 12 - 10
frameworks/Java/play2-java/generate_config.py

@@ -9,12 +9,13 @@ import collections, json, os, textwrap
 # Format is: (language, orm, (opsys, ...), (test, ...))
 # See the dir_name logic below to see the directory name for each test application.
 configurations = [
-  ('Java',  None,    ['Linux'],            ['json']),
-  ('Java',  'Ebean', ['Linux'],            ['db', 'query']),
-  ('Java',  'JPA',   ['Linux'],            ['db', 'query']),
-  ('Scala', None,    ['Linux'],            ['json']),
-  ('Scala', 'Anorm', ['Linux', 'Windows'], ['db', 'query', 'fortune', 'update']),
-  ('Scala', 'Slick', ['Linux'],            ['db', 'query', 'fortune', 'update']),
+  ('Java',  None,    			['Linux'],            ['json']),
+  ('Java',  'Ebean', 			['Linux'],            ['db', 'query']),
+  ('Java',  'JPA',   			['Linux'],            ['db', 'query', 'fortune', 'update', 'plaintext']),
+  ('Java',  'JPA HikariCP',   	['Linux'],            ['db', 'query', 'fortune', 'update', 'plaintext']),
+  ('Scala', None,    			['Linux'],            ['json']),
+  ('Scala', 'Anorm', 			['Linux', 'Windows'], ['db', 'query', 'fortune', 'update']),
+  ('Scala', 'Slick', 			['Linux'],            ['db', 'query', 'fortune', 'update']),
 ]
 
 # All play2 test applications must use the same URLs.
@@ -24,6 +25,7 @@ test_urls = {
   'query': '/queries?queries=',
   'fortune': '/fortunes',
   'update': '/update?queries=',
+  'plaintext': '/plaintext',
 }
 
 langs = {
@@ -41,8 +43,8 @@ for lang, _ in langs.iteritems():
   lang_test_configs[lang] = collections.OrderedDict()
 
 for lang, orm, opsyses, tests in configurations:
-  dir_name = 'play2-' + lang.lower() + (('-'+orm.lower()) if orm else '')
-  setup_name = 'setup_' + lang.lower() + (('_'+orm.lower()) if orm else '')
+  dir_name = 'play2-' + lang.lower() + (('-'+orm.replace(' ', '-').lower()) if orm else '')
+  setup_name = 'setup_' + lang.lower() + (('_'+orm.replace(' ', '_').lower()) if orm else '')
 
   setup_path = os.path.join(pathForLang(lang), setup_name+'.py')
   print 'Generating', setup_path
@@ -57,9 +59,9 @@ for lang, orm, opsyses, tests in configurations:
 
   for opsys in opsyses:
     if len(opsyses) == 1:
-      test_name = lang.lower() + (('-'+orm.lower()) if orm else '')
+      test_name = lang.lower() + (('-'+orm.replace(' ', '-').lower()) if orm else '')
     else:
-      test_name = lang.lower() + (('-'+orm.lower()) if orm else '') + '-'+opsys.lower()
+      test_name = lang.lower() + (('-'+orm.replace(' ', '-').lower()) if orm else '') + '-'+opsys.lower()
     test_config_json = collections.OrderedDict([
       ('display_name', 'play2-'+test_name),
       ('setup_file', setup_name),

+ 29 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/.gitignore

@@ -0,0 +1,29 @@
+logs
+project/project
+project/target
+target
+tmp
+.history
+dist
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml

+ 40 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md

@@ -0,0 +1,40 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test controller](app/controllers/Application.java)
+
+### Data-Store/Database Mapping Test
+
+* [Database test controller](app/controllers/Application.java)
+* [Database World test model](app/models/World.java)
+* [Database Fortune test model](app/models/Fortune.java)
+
+### Plain Text Test
+
+* [Plain text test controller](app/controllers/Application.java)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7](http://openjdk.java.net/)
+* [Play 2.3.6](http://http://www.playframework.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+* http://localhost/json
+
+### Data-Store/Database Mapping Test
+
+* http://localhost/db
+* http://localhost/queries?queries=10
+* http://localhost/fortunes
+* http://localhost/update?queries=10
+
+### Plain Text Test
+
+* http://localhost/plaintext
+

+ 151 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java

@@ -0,0 +1,151 @@
+package controllers;
+
+import akka.dispatch.ExecutionContexts;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import models.Fortune;
+import models.World;
+import play.*;
+import play.core.NamedThreadFactory;
+import play.libs.F;
+import play.libs.Json;
+import play.mvc.*;
+
+import scala.concurrent.ExecutionContext;
+import utils.Predicate;
+import utils.Predicated;
+import views.html.*;
+
+import java.util.*;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class Application extends Controller {
+
+    private static final int MAX_QUERIES_PER_REQUEST = 20;
+    private static final int TEST_DATABASE_ROWS = 10000;
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+    private static final int partitionCount = Play.application().configuration().getInt("db.default.partitionCount");
+    private static final int maxConnections =
+            partitionCount * Play.application().configuration().getInt("db.default.maxConnectionsPerPartition");
+    private static final int minConnections =
+            partitionCount * Play.application().configuration().getInt("db.default.minConnectionsPerPartition");
+
+    private static final ThreadPoolExecutor tpe = new ThreadPoolExecutor(minConnections, maxConnections,
+            0L, TimeUnit.MILLISECONDS,
+            new LinkedBlockingQueue<Runnable>(),
+            new NamedThreadFactory("dbEc"));
+    private static final ExecutionContext dbEc = ExecutionContexts.fromExecutorService(tpe);
+
+    public static Result json() {
+        final ObjectNode result = OBJECT_MAPPER.createObjectNode();
+        result.put("message", "Hello World!");
+        return ok(result);
+    }
+
+    // If the thread-pool used by the database grows too large then our server
+    // is probably struggling, and we should start dropping requests. Set
+    // the max size of our queue something above the number of concurrent
+    // connections that we need to handle.
+    public static class IsDbAvailable implements Predicate {
+        @Override
+        public boolean condition() {
+            return tpe.getQueue().size() <= 1024;
+        }
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> db() {
+        return getRandomWorlds(1).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) {
+                return ok(Json.toJson(worlds.get(0)));
+            }
+        });
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> queries(final String queryCountString) {
+        return getRandomWorlds(queryCount(queryCountString)).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) {
+                return ok(Json.toJson(worlds));
+            }
+        });
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> fortunes() {
+        return F.Promise.promise(new F.Function0<Result>() {
+
+            @Override
+            public Result apply() throws Throwable {
+                List<Fortune> fortunes = Fortune.findAll();
+                fortunes.add(new Fortune("Additional fortune added at request time."));
+                Collections.sort(fortunes, new Comparator<Fortune>() {
+                    @Override
+                    public int compare(Fortune f1, Fortune f2) {
+                        return f1.message.compareTo(f2.message);
+                    }
+                });
+                return ok(views.html.fortunes.render(fortunes));
+            }
+        }, dbEc);
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> update(final String queryCountString) {
+        return getRandomWorlds(queryCount(queryCountString)).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) throws Throwable {
+                Random random = ThreadLocalRandom.current();
+                for (World world : worlds) {
+                    world.randomNumber = (long) (random.nextInt(10000) + 1);
+                }
+
+                worlds = World.save(worlds);
+                return ok(Json.toJson(worlds));
+            }
+        });
+    }
+
+    public static Result plainText() {
+        return ok("Hello, World!");
+    }
+
+    private static int queryCount(String queryCountString) {
+        int queryCount;
+        try {
+            queryCount = Integer.parseInt(queryCountString, 10);
+        } catch (NumberFormatException e) {
+            queryCount = 1;
+        }
+        if (queryCount < 1) {
+            queryCount = 1;
+        } else if (queryCount > 500) {
+            queryCount = 500;
+        }
+
+        return queryCount;
+    }
+
+    private static F.Promise<List<World>> getRandomWorlds(final int n) {
+        return F.Promise.promise(new F.Function0<List<World>>() {
+            @Override
+            public List<World> apply() throws Throwable {
+                Random random = ThreadLocalRandom.current();
+                List<World> worlds = new ArrayList<World>(n);
+                for (int i = 0; i < n; ++i) {
+                    long randomId = random.nextInt(TEST_DATABASE_ROWS) + 1;
+                    World world = World.findById(randomId);
+                    worlds.add(world);
+                }
+                return worlds;
+            }
+        }, dbEc);
+    }
+
+}

+ 34 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java

@@ -0,0 +1,34 @@
+package models;
+
+import play.db.jpa.JPA;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.criteria.CriteriaQuery;
+import java.util.List;
+
+@Entity
+public class Fortune {
+
+    @Id
+    public Long id = 0L;
+
+    public String message;
+
+    public Fortune() {
+    }
+
+    public Fortune(String message) {
+        this.message = message;
+    }
+
+    public static List<Fortune> findAll() throws Throwable {
+        return JPA.withTransaction("default", true, new play.libs.F.Function0<List<Fortune>>() {
+            public List<Fortune> apply() {
+                CriteriaQuery<Fortune> criteria = JPA.em().getCriteriaBuilder().createQuery(Fortune.class);
+                criteria.select(criteria.from(Fortune.class));
+                return JPA.em().createQuery(criteria).getResultList();
+            }
+        });
+    }
+}

+ 38 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java

@@ -0,0 +1,38 @@
+package models;
+
+import play.db.jpa.JPA;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.List;
+
+@Entity
+public class World {
+
+    @Id
+    public Long id;
+
+    @Column(name = "randomNumber")
+    public Long randomNumber;
+
+    public static World findById(final Long id) throws Throwable {
+        return JPA.withTransaction("default", true, new play.libs.F.Function0<World>() {
+            public World apply() {
+                return JPA.em().find(World.class, id);
+            }
+        });
+    }
+
+    public static List<World> save(final List<World> worlds) throws Throwable {
+        for (final World world : worlds) {
+            JPA.withTransaction("default", false, new play.libs.F.Function0<World>() {
+                public World apply() {
+                    return JPA.em().merge(world);
+                }
+            });
+        }
+
+        return worlds;
+    }
+}

+ 21 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java

@@ -0,0 +1,21 @@
+package utils;
+
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+import play.libs.F;
+import play.mvc.Action;
+import play.mvc.Http;
+import play.mvc.Result;
+
+public class Headers extends Action.Simple {
+
+    private static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC();
+
+    @Override
+    public F.Promise<Result> call(Http.Context context) throws Throwable {
+        context.response().setHeader("Server", "play2-java-jpa");
+        context.response().setHeader("Date", RFC_1123_DATE_TIME.print(new DateTime()));
+        return delegate.call(context);
+    }
+}

+ 8 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java

@@ -0,0 +1,8 @@
+package utils;
+
+/**
+ * Predicates for PredicatedActions.
+ */
+public interface Predicate {
+    boolean condition();
+}

+ 26 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java

@@ -0,0 +1,26 @@
+package utils;
+
+import play.mvc.With;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Declares a composing action that will check for a condition before deciding on whether to proceed with the request.
+ */
+@With(PredicatedAction.class)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Predicated {
+    /**
+     * The condition.
+     */
+    Class<? extends Predicate> predicate();
+
+    /**
+     * The http status code to return if the condition fails.
+     */
+    int failed();
+}

+ 23 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java

@@ -0,0 +1,23 @@
+package utils;
+
+/**
+ * A predicated action is one where a condition must be satisfied in order to proceed with the request. If the
+ * condition is not satisfied then a supplied status result is yielded.
+ */
+
+import play.libs.F;
+import play.mvc.Action;
+import play.mvc.Http;
+import play.mvc.Result;
+
+public class PredicatedAction extends Action<Predicated> {
+    @Override
+    public F.Promise<Result> call(final Http.Context ctx) throws Throwable {
+        final Predicate p = configuration.predicate().newInstance();
+        if (p.condition()) {
+            return delegate.call(ctx);
+        } else {
+            return F.Promise.<Result>pure(status(configuration.failed()));
+        }
+    }
+}

+ 16 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/fortunes.scala.html

@@ -0,0 +1,16 @@
+@(fortunes: List[Fortune])
+
+@main() {
+    <table>
+        <tr>
+            <th>id</th>
+            <th>message</th>
+        </tr>
+        @for(fortune <- fortunes) {
+        <tr>
+            <td>@fortune.id</td>
+            <td>@fortune.message</td>
+        </tr>
+        }
+    </table>
+}

+ 12 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/main.scala.html

@@ -0,0 +1,12 @@
+@()(content: Html)
+
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>Fortunes</title>
+    </head>
+    <body>
+    @content
+    </body>
+</html>

+ 17 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt

@@ -0,0 +1,17 @@
+name := """play2-java-jpa-hikaricp"""
+
+version := "1.0-SNAPSHOT"
+
+lazy val root = (project in file(".")).enablePlugins(PlayJava)
+
+scalaVersion := "2.11.2"
+
+libraryDependencies ++= Seq(
+  javaJdbc,
+  javaJpa,
+  "mysql" % "mysql-connector-java" % "5.1.33",
+  "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final",
+  "com.edulify" %% "play-hikaricp" % "1.5.0"
+)
+
+resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)

+ 14 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml

@@ -0,0 +1,14 @@
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+             version="2.0">
+             
+    <persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL">
+        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
+        <non-jta-data-source>DefaultDS</non-jta-data-source>
+        <properties>
+            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+        </properties>
+    </persistence-unit>
+    
+</persistence>

+ 97 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf

@@ -0,0 +1,97 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# Secret key
+# ~~~~~
+# The secret key is used to secure cryptographics functions.
+#
+# This must be changed for production, but we recommend not changing it in this file.
+#
+# See http://www.playframework.com/documentation/latest/ApplicationSecret for more details.
+application.secret="`o0VB@vXStsF:ffwM5ZZ_r:GYkm96QM[nRUJLpEbI8hwLUdV;N<:UyUWI;lf/XP`"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# application.global=Global
+
+# Router
+# ~~~~~
+# Define the Router object to use for this application.
+# This router will be looked up first when the application is starting up,
+# so make sure this is the entry point.
+# Furthermore, it's assumed your route file is named properly.
+# So for an application router like `conf/my.application.Router`,
+# you may need to define a router file `my.application.routes`.
+# Default to Routes in the root package (and `conf/routes`)
+# application.router=my.application.Routes
+
+# Database configuration
+# ~~~~~
+# You can declare as many datasources as you want.
+# By convention, the default datasource is named `default`
+#
+# db.default.driver=org.h2.Driver
+# db.default.url="jdbc:h2:mem:play"
+# db.default.user=sa
+# db.default.password=""
+#
+# You can expose this datasource via JNDI if needed (Useful for JPA)
+# db.default.jndiName=DefaultDS
+
+db.default.driver= com.mysql.jdbc.Driver
+db.default.url="jdbc:mysql://127.0.0.1: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"
+db.default.user=benchmarkdbuser
+db.default.password=benchmarkdbpass
+db.default.jndiName=DefaultDS
+jpa.default=defaultPersistenceUnit
+
+db.default.partitionCount=4
+
+# The number of connections to create per partition. Setting this to
+# 5 with 3 partitions means you will have 15 unique connections to the
+# database. Note that BoneCP will not create all these connections in
+# one go but rather start off with minConnectionsPerPartition and
+# gradually increase connections as required.
+#
+# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
+db.default.maxConnectionsPerPartition=64
+
+# The number of initial connections, per partition.
+#
+# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
+db.default.minConnectionsPerPartition=64
+
+dbplugin=disabled
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+evolutionplugin=disabled
+
+# Ebean configuration
+# ~~~~~
+# You can declare as many Ebean servers as you want.
+# By convention, the default server is named `default`
+#
+# ebean.default="models.*"
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/),
+# by providing an application-logger.xml file in the conf directory.
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=INFO
+
+# Logger provided to your application:
+logger.application=DEBUG
+

+ 1 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/play.plugins

@@ -0,0 +1 @@
+200:com.edulify.play.hikaricp.HikariCPPlugin

+ 13 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes

@@ -0,0 +1,13 @@
+# Routes
+# This file defines all application routes (Higher priority routes first)
+# ~~~~
+
+GET        /json                controllers.Application.json
+GET        /db                  controllers.Application.db()
+GET        /queries             controllers.Application.queries(queries ?= "1")
+GET        /fortunes            controllers.Application.fortunes
+GET        /update              controllers.Application.update(queries ?= "1")
+GET        /plaintext           controllers.Application.plainText
+
+# Map static resources from the /public folder to the /assets URL path
+GET        /assets/*file        controllers.Assets.at(path="/public", file)

+ 1 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.13.5

+ 4 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt

@@ -0,0 +1,4 @@
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// The Play plugin
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.6")

+ 11 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code

@@ -0,0 +1,11 @@
+./play-java-jpa/app/
+./play-java-jpa/app/controllers
+./play-java-jpa/app/controllers/Application.java
+./play-java-jpa/app/utils
+./play-java-jpa/app/utils/Headers.java
+./play-java-jpa/app/utils/Predicate.java
+./play-java-jpa/app/utils/PredicatedAction.java
+./play-java-jpa/app/utils/Predicated.java
+./play-java-jpa/app/models
+./play-java-jpa/app/models/World.java
+./play-java-jpa/app/models/Fortune.java

+ 18 - 6
frameworks/Java/play2-java/play2-java-jpa/README.md

@@ -4,25 +4,37 @@ This is the Play portion of a [benchmarking test suite](../) comparing a variety
 
 ### JSON Encoding Test
 
-* [JSON test source](app/controllers/Application.java)
+* [JSON test controller](app/controllers/Application.java)
 
 ### Data-Store/Database Mapping Test
 
 * [Database test controller](app/controllers/Application.java)
-* [Database test model](app/models/World.java)
+* [Database World test model](app/models/World.java)
+* [Database Fortune test model](app/models/Fortune.java)
+
+### Plain Text Test
+
+* [Plain text test controller](app/controllers/Application.java)
 
 ## Infrastructure Software Versions
 The tests were run with:
 
 * [Java OpenJDK 1.7](http://openjdk.java.net/)
-* [Play 2.3.3](http://http://www.playframework.com/)
+* [Play 2.3.6](http://http://www.playframework.com/)
 
 ## Test URLs
 ### JSON Encoding Test
 
-http://localhost/json
+* http://localhost/json
 
 ### Data-Store/Database Mapping Test
 
-http://localhost/db
-http://localhost/queries?queries=10
+* http://localhost/db
+* http://localhost/queries?queries=10
+* http://localhost/fortunes
+* http://localhost/update?queries=10
+
+### Plain Text Test
+
+* http://localhost/plaintext
+

+ 51 - 10
frameworks/Java/play2-java/play2-java-jpa/app/controllers/Application.java

@@ -3,6 +3,7 @@ package controllers;
 import akka.dispatch.ExecutionContexts;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import models.Fortune;
 import models.World;
 import play.Play;
 import play.core.NamedThreadFactory;
@@ -14,9 +15,7 @@ import scala.concurrent.ExecutionContext;
 import utils.Predicate;
 import utils.Predicated;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
+import java.util.*;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -24,7 +23,6 @@ import java.util.concurrent.TimeUnit;
 
 public class Application extends Controller {
 
-    private static final int MAX_QUERIES_PER_REQUEST = 20;
     private static final int TEST_DATABASE_ROWS = 10000;
     private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
@@ -69,6 +67,54 @@ public class Application extends Controller {
 
     @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
     public static F.Promise<Result> queries(final String queryCountString) {
+        return getRandomWorlds(queryCount(queryCountString)).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) {
+                return ok(Json.toJson(worlds));
+            }
+        });
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> fortunes() {
+        return F.Promise.promise(new F.Function0<Result>() {
+
+            @Override
+            public Result apply() throws Throwable {
+                List<Fortune> fortunes = Fortune.findAll();
+                fortunes.add(new Fortune("Additional fortune added at request time."));
+                Collections.sort(fortunes, new Comparator<Fortune>() {
+                    @Override
+                    public int compare(Fortune f1, Fortune f2) {
+                        return f1.message.compareTo(f2.message);
+                    }
+                });
+                return ok(views.html.fortunes.render(fortunes));
+            }
+        }, dbEc);
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> update(final String queryCountString) {
+        return getRandomWorlds(queryCount(queryCountString)).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) throws Throwable {
+                Random random = ThreadLocalRandom.current();
+                for (World world : worlds) {
+                    world.randomNumber = (long) (random.nextInt(10000) + 1);
+                }
+
+                worlds = World.save(worlds);
+                return ok(Json.toJson(worlds));
+            }
+        });
+    }
+
+    public static Result plainText() {
+        return ok("Hello, World!");
+    }
+
+    private static int queryCount(String queryCountString) {
         int queryCount;
         try {
             queryCount = Integer.parseInt(queryCountString, 10);
@@ -81,12 +127,7 @@ public class Application extends Controller {
             queryCount = 500;
         }
 
-        return getRandomWorlds(queryCount).map(new F.Function<List<World>, Result>() {
-            @Override
-            public Result apply(List<World> worlds) {
-                return ok(Json.toJson(worlds));
-            }
-        });
+        return queryCount;
     }
 
     private static F.Promise<List<World>> getRandomWorlds(final int n) {

+ 34 - 0
frameworks/Java/play2-java/play2-java-jpa/app/models/Fortune.java

@@ -0,0 +1,34 @@
+package models;
+
+import play.db.jpa.JPA;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.criteria.CriteriaQuery;
+import java.util.List;
+
+@Entity
+public class Fortune {
+
+    @Id
+    public Long id = 0L;
+
+    public String message;
+
+    public Fortune() {
+    }
+
+    public Fortune(String message) {
+        this.message = message;
+    }
+
+    public static List<Fortune> findAll() throws Throwable {
+        return JPA.withTransaction("default", true, new play.libs.F.Function0<List<Fortune>>() {
+            public List<Fortune> apply() {
+                CriteriaQuery<Fortune> criteria = JPA.em().getCriteriaBuilder().createQuery(Fortune.class);
+                criteria.select(criteria.from(Fortune.class));
+                return JPA.em().createQuery(criteria).getResultList();
+            }
+        });
+    }
+}

+ 21 - 6
frameworks/Java/play2-java/play2-java-jpa/app/models/World.java

@@ -1,9 +1,12 @@
 package models;
 
-import javax.persistence.*;
-
 import play.db.jpa.JPA;
 
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.List;
+
 @Entity
 public class World {
 
@@ -14,10 +17,22 @@ public class World {
     public Long randomNumber;
 
     public static World findById(final Long id) throws Throwable {
-      return JPA.withTransaction("default", true, new play.libs.F.Function0<World>() {
-        public World apply() {
-            return JPA.em().find(World.class, id);
+        return JPA.withTransaction("default", true, new play.libs.F.Function0<World>() {
+            public World apply() {
+                return JPA.em().find(World.class, id);
+            }
+        });
+    }
+
+    public static List<World> save(final List<World> worlds) throws Throwable {
+        for (final World world : worlds) {
+            JPA.withTransaction("default", false, new play.libs.F.Function0<World>() {
+                public World apply() {
+                    return JPA.em().merge(world);
+                }
+            });
         }
-      });
+
+        return worlds;
     }
 }

+ 21 - 0
frameworks/Java/play2-java/play2-java-jpa/app/utils/Headers.java

@@ -0,0 +1,21 @@
+package utils;
+
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+import play.libs.F;
+import play.mvc.Action;
+import play.mvc.Http;
+import play.mvc.Result;
+
+public class Headers extends Action.Simple {
+
+    private static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC();
+
+    @Override
+    public F.Promise<Result> call(Http.Context context) throws Throwable {
+        context.response().setHeader("Server", "play2-java-jpa");
+        context.response().setHeader("Date", RFC_1123_DATE_TIME.print(new DateTime()));
+        return delegate.call(context);
+    }
+}

+ 16 - 0
frameworks/Java/play2-java/play2-java-jpa/app/views/fortunes.scala.html

@@ -0,0 +1,16 @@
+@(fortunes: List[Fortune])
+
+@main() {
+    <table>
+        <tr>
+            <th>id</th>
+            <th>message</th>
+        </tr>
+        @for(fortune <- fortunes) {
+        <tr>
+            <td>@fortune.id</td>
+            <td>@fortune.message</td>
+        </tr>
+        }
+    </table>
+}

+ 12 - 0
frameworks/Java/play2-java/play2-java-jpa/app/views/main.scala.html

@@ -0,0 +1,12 @@
+@()(content: Html)
+
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>Fortunes</title>
+    </head>
+    <body>
+    @content
+    </body>
+</html>

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa/build.sbt

@@ -9,7 +9,7 @@ lazy val root = (project in file(".")).enablePlugins(PlayJava)
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.32",
+  "mysql" % "mysql-connector-java" % "5.1.33",
   "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final"
   )
 

+ 3 - 1
frameworks/Java/play2-java/play2-java-jpa/conf/routes

@@ -2,10 +2,12 @@
 # This file defines all application routes (Higher priority routes first)
 # ~~~~
 
-# Home page
 GET        /json                controllers.Application.json
 GET        /db                  controllers.Application.db()
 GET        /queries             controllers.Application.queries(queries ?= "1")
+GET        /fortunes            controllers.Application.fortunes
+GET        /update              controllers.Application.update(queries ?= "1")
+GET        /plaintext           controllers.Application.plainText
 
 # Map static resources from the /public folder to the /assets URL path
 GET        /assets/*file        controllers.Assets.at(path="/public", file)

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.4")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.6")

+ 2 - 0
frameworks/Java/play2-java/play2-java-jpa/source_code

@@ -2,8 +2,10 @@
 ./play-java-jpa/app/controllers
 ./play-java-jpa/app/controllers/Application.java
 ./play-java-jpa/app/utils
+./play-java-jpa/app/utils/Headers.java
 ./play-java-jpa/app/utils/Predicate.java
 ./play-java-jpa/app/utils/PredicatedAction.java
 ./play-java-jpa/app/utils/Predicated.java
 ./play-java-jpa/app/models
 ./play-java-jpa/app/models/World.java
+./play-java-jpa/app/models/Fortune.java

+ 6 - 0
frameworks/Java/play2-java/setup_java_jpa_hikaricp.py

@@ -0,0 +1,6 @@
+
+# This file was generated by frameworks/Java/play2-java/generate_config.py.
+# Do not edit this file directly, use the script to regenerate.
+from .setup_common import make_setup_for_dir
+
+make_setup_for_dir(globals(), 'play2-java-jpa-hikaricp')

+ 1 - 1
frameworks/Lua/lapis/benchmark_config

@@ -5,7 +5,7 @@
       "setup_file": "setup",
       "json_url": "/",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/queries?queries=",
       "fortune_url": "/fortunes",
       "update_url": "/update?queries=",
       "plaintext_url": "/plaintext",

+ 16 - 3
frameworks/Lua/lapis/web.lua

@@ -105,13 +105,24 @@ do
       }
     end,
     ["/db"] = function(self)
+      local w = World:find(random(1, 10000))
+      return {
+        json = {
+          id = w.id,
+          randomNumber = w.randomnumber
+        }
+      }
+    end,
+    ["/queries"] = function(self)
       local num_queries = tonumber(self.params.queries) or 1
       if num_queries < 2 then
         local w = World:find(random(1, 10000))
         return {
           json = {
-            id = w.id,
-            randomNumber = w.randomnumber
+            {
+              id = w.id,
+              randomNumber = w.randomnumber
+            }
           }
         }
       end
@@ -191,7 +202,9 @@ do
       end
       if num_queries < 2 then
         return {
-          json = worlds[1]
+          json = {
+            worlds[1]
+          }
         }
       end
       return {

+ 6 - 2
frameworks/Lua/lapis/web.moon

@@ -15,10 +15,14 @@ class Benchmark extends lapis.Application
     json: {message: "Hello, World!"}
 
   "/db": =>
+      w = World\find random(1, 10000)
+      return json: {id:w.id,randomNumber:w.randomnumber}
+
+  "/queries": =>
     num_queries = tonumber(@params.queries) or 1
     if num_queries < 2 
       w = World\find random(1, 10000)
-      return json: {id:w.id,randomNumber:w.randomnumber}
+      return json: {{id:w.id,randomNumber:w.randomnumber}}
 
     worlds = {}
     num_queries = min(500, num_queries)
@@ -64,7 +68,7 @@ class Benchmark extends lapis.Application
       world\update "randomnumber"
       insert worlds, {id:world.id,randomNumber:world.randomnumber} 
     if num_queries < 2
-      return json: worlds[1]
+      return json: {worlds[1]}
     json: worlds
 
   "/plaintext": =>

+ 1 - 1
frameworks/Nimrod/nawak/setup.py

@@ -27,7 +27,7 @@ def stop(logfile, errfile):
 
   try:
     subprocess.check_call("sudo m2sh stop -every", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
-  except:
+  except Exception:
     ret = 1
 
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)

+ 1 - 1
frameworks/Nimrod/nawak/setup_redis.py

@@ -28,7 +28,7 @@ def stop(logfile, errfile):
 
   try:
     subprocess.check_call("sudo m2sh stop -every", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
-  except:
+  except Exception:
     ret = 1
 
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)

+ 4 - 1
frameworks/PHP/php-zend-framework/module/FrameworkBenchmarks/src/FrameworkBenchmarks/Controller/DbController.php

@@ -49,7 +49,10 @@ class DbController extends AbstractActionController
     {
         /* @var $request \Zend\Http\Request */
         $request = $this->getRequest();
-        $queries = $request->getQuery('queries', 1);
+        $queries = (int) $request->getQuery('queries', 1);
+        $queries = max(1, $queries);
+        $queries = min(500, $queries);
+
         $worlds  = array();
 
         for ($i = 0; $i < $queries; $i += 1) {

+ 41 - 0
frameworks/PHP/php-zend-framework1/.gitignore

@@ -0,0 +1,41 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor or
+# operating system, you probably want to add a global ignore instead:
+#   git config --global core.excludesfile ~/.gitignore_global
+
+/vendor
+/build
+/dist
+.DS_Store
+/tags
+.idea
+composer.lock
+cache.properties
+phpunit.xml
+tmp
+
+# VIM
+[._]*.s[a-w][a-z]
+[._]s[a-w][a-z]
+*.un~
+Session.vim
+.netrwhist
+*~
+
+# Sublime Text
+*.sublime-workspace
+
+# Netbeans IDE
+nbproject
+
+# Eclipse IDE
+.buildpath
+.project
+.settings/
+
+# Notepad++
+nppBackup
+
+# ctags
+tags

+ 0 - 0
frameworks/PHP/php-zend-framework1/__init__.py


+ 6 - 0
frameworks/PHP/php-zend-framework1/application/Bootstrap.php

@@ -0,0 +1,6 @@
+<?php
+
+class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
+{
+
+}

+ 19 - 0
frameworks/PHP/php-zend-framework1/application/configs/application.ini

@@ -0,0 +1,19 @@
+[production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
+bootstrap.class = "Bootstrap"
+resources.frontcontroller.controllerDirectory = APPLICATION_PATH "/controllers"
+resources.frontcontroller.params.displayExceptions = 1
+
+resources.db.adapter = "pdo_mysql"
+resources.db.params.host = "localhost"
+resources.db.params.charset = "utf8"
+resources.db.params.dbname = "hello_world"
+resources.db.params.username = "benchmarkdbuser"
+resources.db.params.password = "benchmarkdbpass"
+
+[development : production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+resources.frontController.params.displayExceptions = 1

+ 12 - 0
frameworks/PHP/php-zend-framework1/application/controllers/DbController.php

@@ -0,0 +1,12 @@
+<?php
+
+class DbController extends Zend_Controller_Action
+{
+    public function indexAction()
+    {
+        $table = new Zend_Db_Table('World');
+        $result = $table->fetchRow(array('id = ?' => mt_rand(1, 10000)));
+
+        $this->_helper->json->sendJson($result->toArray());
+    }
+}

+ 20 - 0
frameworks/PHP/php-zend-framework1/application/controllers/DbMultiController.php

@@ -0,0 +1,20 @@
+<?php
+
+class DbMultiController extends Zend_Controller_Action
+{
+    public function indexAction()
+    {
+        $queries = (int) $this->getParam('queries', 1);
+        $queries = max(1, $queries);
+        $queries = min(500, $queries);
+
+        $table = new Zend_Db_Table('World');
+
+        $worlds = array();
+        for ($i = 0; $i < $queries; $i += 1) {
+            $worlds[] = $table->fetchRow(array('id = ?' => mt_rand(1,10000)))->toArray();
+        }
+
+        $this->_helper->json->sendJson($worlds);
+    }
+}

+ 54 - 0
frameworks/PHP/php-zend-framework1/application/controllers/ErrorController.php

@@ -0,0 +1,54 @@
+<?php
+
+class ErrorController extends Zend_Controller_Action
+{
+    public function errorAction()
+    {
+        $errors = $this->_getParam('error_handler');
+
+        if (!$errors || !$errors instanceof ArrayObject) {
+            $this->view->message = 'You have reached the error page';
+            return;
+        }
+
+        switch ($errors->type) {
+            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
+            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
+            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
+                // 404 error -- controller or action not found
+                $this->getResponse()->setHttpResponseCode(404);
+                $priority = Zend_Log::NOTICE;
+                $this->view->message = 'Page not found';
+                break;
+            default:
+                // application error
+                $this->getResponse()->setHttpResponseCode(500);
+                $priority = Zend_Log::CRIT;
+                $this->view->message = 'Application error';
+                break;
+        }
+
+        // Log exception, if logger available
+        if ($log = $this->getLog()) {
+            $log->log($this->view->message, $priority, $errors->exception);
+            $log->log('Request Parameters', $priority, $errors->request->getParams());
+        }
+
+        // conditionally display exceptions
+        if ($this->getInvokeArg('displayExceptions') == true) {
+            $this->view->exception = $errors->exception;
+        }
+
+        $this->view->request   = $errors->request;
+    }
+
+    public function getLog()
+    {
+        $bootstrap = $this->getInvokeArg('bootstrap');
+        if (!$bootstrap->hasResource('Log')) {
+            return false;
+        }
+        $log = $bootstrap->getResource('Log');
+        return $log;
+    }
+}

+ 9 - 0
frameworks/PHP/php-zend-framework1/application/controllers/JsonController.php

@@ -0,0 +1,9 @@
+<?php
+
+class JsonController extends Zend_Controller_Action
+{
+    public function indexAction()
+    {
+        $this->_helper->json->sendJson(array('message' => 'Hello, World!'));
+    }
+}

+ 29 - 0
frameworks/PHP/php-zend-framework1/application/views/scripts/error/error.phtml

@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Zend Framework Default Application</title>
+</head>
+<body>
+  <h1>An error occurred</h1>
+  <h2><?php echo $this->message ?></h2>
+
+  <?php if (isset($this->exception)): ?>
+
+  <h3>Exception information:</h3>
+  <p>
+      <b>Message:</b> <?php echo $this->exception->getMessage() ?>
+  </p>
+
+  <h3>Stack trace:</h3>
+  <pre><?php echo $this->exception->getTraceAsString() ?>
+  </pre>
+
+  <h3>Request Parameters:</h3>
+  <pre><?php echo $this->escape(var_export($this->request->getParams(), true)) ?>
+  </pre>
+
+  <?php endif ?>
+
+</body>
+</html>

+ 9 - 0
frameworks/PHP/php-zend-framework1/bash_profile.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+export PHP_HOME=${IROOT}/php-5.5.17
+
+export PHP_FPM=$PHP_HOME/sbin/php-fpm
+
+export COMPOSER_HOME=${IROOT}/php-composer
+
+export PATH="$COMPOSER_HOME:$PHP_HOME/bin:$PHP_HOME/sbin:$PATH"

+ 25 - 0
frameworks/PHP/php-zend-framework1/benchmark_config

@@ -0,0 +1,25 @@
+{
+  "framework": "ZendFramework1",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db-multi?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "ZendFramework1",
+      "language": "PHP",
+      "orm": "Full",
+      "platform": "PHP-FPM",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ZendFramework1",
+      "notes": "",
+      "versus": "php"
+    }
+  }]
+}

+ 6 - 0
frameworks/PHP/php-zend-framework1/composer.json

@@ -0,0 +1,6 @@
+{
+    "require": {
+        "php": ">=5.2.11",
+        "zendframework/zendframework1": "~1.12"
+    }
+}

+ 133 - 0
frameworks/PHP/php-zend-framework1/deploy/nginx.conf

@@ -0,0 +1,133 @@
+#user  nobody;
+worker_processes  8;
+
+#error_log  logs/error.log;
+#error_log  logs/error.log  notice;
+#error_log  logs/error.log  info;
+error_log stderr error;
+
+#pid        logs/nginx.pid;
+
+
+events {
+    worker_connections  1024;
+}
+
+
+http {
+    include       /usr/local/nginx/conf/mime.types;
+    default_type  application/octet-stream;
+
+    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+    #                  '$status $body_bytes_sent "$http_referer" '
+    #                  '"$http_user_agent" "$http_x_forwarded_for"';
+
+    #access_log  logs/access.log  main;
+    access_log off;
+
+    sendfile        on;
+    #tcp_nopush     on;
+
+    #keepalive_timeout  0;
+    keepalive_timeout  65;
+
+    #gzip  on;
+
+    upstream fastcgi_backend {
+        server 127.0.0.1:9001;
+        keepalive 32;
+    }
+
+    server {
+        listen       8080;
+        server_name  localhost;
+
+        #charset koi8-r;
+
+        #access_log  logs/host.access.log  main;
+
+        #location / {
+        #    root   html;
+        #    index  index.html index.htm;
+        #}
+
+        #error_page  404              /404.html;
+
+        # redirect server error pages to the static page /50x.html
+        #
+        #error_page   500 502 503 504  /50x.html;
+        #location = /50x.html {
+        #    root   html;
+        #}
+
+        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
+        #
+        #location ~ \.php$ {
+        #    proxy_pass   http://127.0.0.1;
+        #}
+
+        root /home/tfb/FrameworkBenchmarks/php-zend-framework1/public/;
+        index  index.php;
+
+        location / {
+            try_files $uri $uri/ /index.php?$uri&$args;
+        }
+
+        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
+        #
+        location ~ \.php$ {
+            try_files $uri =404;
+            fastcgi_pass   fastcgi_backend;
+            fastcgi_keep_conn on;
+            fastcgi_index  index.php;
+#            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
+            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
+            include        /usr/local/nginx/conf/fastcgi_params;
+        }
+
+        # deny access to .htaccess files, if Apache's document root
+        # concurs with nginx's one
+        #
+        #location ~ /\.ht {
+        #    deny  all;
+        #}
+    }
+
+
+    # another virtual host using mix of IP-, name-, and port-based configuration
+    #
+    #server {
+    #    listen       8000;
+    #    listen       somename:8080;
+    #    server_name  somename  alias  another.alias;
+
+    #    location / {
+    #        root   html;
+    #        index  index.html index.htm;
+    #    }
+    #}
+
+
+    # HTTPS server
+    #
+    #server {
+    #    listen       443;
+    #    server_name  localhost;
+
+    #    ssl                  on;
+    #    ssl_certificate      cert.pem;
+    #    ssl_certificate_key  cert.key;
+
+    #    ssl_session_timeout  5m;
+
+    #    ssl_protocols  SSLv2 SSLv3 TLSv1;
+    #    ssl_ciphers  HIGH:!aNULL:!MD5;
+    #    ssl_prefer_server_ciphers   on;
+
+    #    location / {
+    #        root   html;
+    #        index  index.html index.htm;
+    #    }
+    #}
+
+}

+ 9 - 0
frameworks/PHP/php-zend-framework1/deploy/php-zend-framework

@@ -0,0 +1,9 @@
+<VirtualHost *:8080>
+  Alias /php-zend-framework1/ "/home/ubuntu/FrameworkBenchmarks/php-zend-framework1/public/"
+  <Directory /home/ubuntu/FrameworkBenchmarks/php-zend-framework1/public/>
+          Options Indexes FollowSymLinks MultiViews
+          #AllowOverride None
+          Order allow,deny
+          allow from all
+  </Directory>
+</VirtualHost>

+ 3 - 0
frameworks/PHP/php-zend-framework1/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends php composer nginx

+ 36 - 0
frameworks/PHP/php-zend-framework1/lint.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir="." default="lint">
+
+    <property name="src.dir" location="" />
+
+    <target name="lint" description="Run php syntax check (lint)">
+        <apply executable="php" failonerror="true">
+            <arg value="-l" />
+            <fileset dir="${src.dir}">
+
+                <include name="**/*.php" />
+                <include name="**/*.phtml" />
+
+                <!--
+
+                Zend Framework shouldn't have any syntax errors, but let's just
+                be double sure.
+
+                Excluding tests and other non-runtime stuff
+
+                -->
+                <exclude name="**/vendor/zendframework/zendframework1/bin/**" />
+                <exclude name="**/vendor/zendframework/zendframework1/demos/**" />
+                <exclude name="**/vendor/zendframework/zendframework1/documentation/**" />
+                <exclude name="**/vendor/zendframework/zendframework1/puppet/**" />
+                <exclude name="**/vendor/zendframework/zendframework1/resources/**" />
+                <exclude name="**/vendor/zendframework/zendframework1/tests/**" />
+
+                <!-- cache -->
+                <modified />
+
+            </fileset>
+        </apply>
+    </target>
+
+</project>

+ 34 - 0
frameworks/PHP/php-zend-framework1/phpunit.xml.dist

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         beStrictAboutOutputDuringTests="false"
+         beStrictAboutTestsThatDoNotTestAnything="true"
+         beStrictAboutTestSize="true"
+         beStrictAboutTodoAnnotatedTests="true"
+         bootstrap="test/bootstrap.php"
+         checkForUnintentionallyCoveredCode="true"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         strict="false"
+         verbose="true"
+         >
+
+    <testsuites>
+        <testsuite name="unit">
+            <directory suffix="Test.php">test</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist processUncoveredFilesFromWhitelist="true">
+            <directory suffix=".php">application</directory>
+        </whitelist>
+    </filter>
+
+    <!-- <logging>
+        <log type="coverage-html" target="build/coverage" />
+    </logging> -->
+
+</phpunit>

+ 16 - 0
frameworks/PHP/php-zend-framework1/public/.htaccess

@@ -0,0 +1,16 @@
+RewriteEngine On
+# The following rule tells Apache that if the requested filename
+# exists, simply serve it.
+RewriteCond %{REQUEST_FILENAME} -s [OR]
+RewriteCond %{REQUEST_FILENAME} -l [OR]
+RewriteCond %{REQUEST_FILENAME} -d
+RewriteRule ^.*$ - [NC,L]
+# The following rewrites all other queries to index.php. The
+# condition ensures that if you are using Apache aliases to do
+# mass virtual hosting, the base path will be prepended to
+# allow proper resolution of the index.php file; it will work
+# in non-aliased environments as well, providing a safe, one-size
+# fits all solution.
+RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
+RewriteRule ^(.*)$ - [E=BASE:%1]
+RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]

+ 21 - 0
frameworks/PHP/php-zend-framework1/public/index.php

@@ -0,0 +1,21 @@
+<?php
+
+// Define path to application directory
+defined('APPLICATION_PATH')
+    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
+
+// Define application environment
+defined('APPLICATION_ENV')
+    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
+
+set_include_path(realpath(dirname(__FILE__) . '/../vendor/zendframework/zendframework1/library'));
+
+require_once 'Zend/Application.php';
+
+// Create application, bootstrap, and run
+$application = new Zend_Application(
+    APPLICATION_ENV,
+    APPLICATION_PATH . '/configs/application.ini'
+);
+$application->bootstrap()
+            ->run();

+ 26 - 0
frameworks/PHP/php-zend-framework1/script/setup_dev_and_test_db.php

@@ -0,0 +1,26 @@
+<?php
+
+set_include_path(realpath(dirname(__FILE__) . '/../vendor/zendframework/zendframework1/library'));
+
+require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
+$db = new Zend_Db_Adapter_Pdo_Mysql(array(
+    'host' => 'localhost',
+    'charset' => 'utf8',
+    'dbname'   => 'hello_world',
+    'username' => 'benchmarkdbuser',
+    'password' => 'benchmarkdbpass'
+));
+
+$db->exec('DROP TABLE IF EXISTS `World`;');
+$db->exec('CREATE TABLE `World` (
+  `id` int(11) NOT NULL,
+  `randomNumber` int(11) NOT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;');
+
+for ($i=1; $i <= 10000; $i++) {
+    $db->insert('World', array(
+        'id' => $i,
+        'randomNumber' => $i
+    ));
+}

+ 24 - 0
frameworks/PHP/php-zend-framework1/setup.py

@@ -0,0 +1,24 @@
+import subprocess
+import sys
+import setup_util
+
+def start(args, logfile, errfile):
+  setup_util.replace_text("php-zend-framework1/application/configs/application.ini", "host = \"localhost\"", "host = \"" + args.database_host + "\"")
+  setup_util.replace_text("php-zend-framework1/deploy/nginx.conf", "root .*\/FrameworkBenchmarks/php-zend-framework1", "root " + args.troot)
+
+  try:
+    subprocess.check_call("composer.phar install", shell=True, cwd="php-zend-framework1", stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo chown -R www-data:www-data php-zend-framework1", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo $PHP_FPM --fpm-config $FWROOT/config/php-fpm.conf -g $TROOT/deploy/php-fpm.pid", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c $TROOT/deploy/nginx.conf", shell=True, stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop(logfile, errfile):
+  try:
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("sudo kill -QUIT $( cat $TROOT/deploy/php-fpm.pid )", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo chown -R $USER:$USER php-zend-framework1", shell=True, stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 43 - 0
frameworks/PHP/php-zend-framework1/test/application/controllers/DbControllerTest.php

@@ -0,0 +1,43 @@
+<?php
+
+class DbControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
+{
+    protected function setUp()
+    {
+        $this->bootstrap = new Zend_Application(
+            APPLICATION_ENV,
+            APPLICATION_PATH . '/configs/application.ini'
+        );
+
+        parent::setUp();
+    }
+
+    public function testType2SingleDatabaseQuery()
+    {
+        $this->dispatch('/db');
+
+        $this->assertModule('default');
+        $this->assertController('db');
+        $this->assertAction('index');
+        $this->assertResponseCode(200);
+        $this->assertHeaderRegex('Content-Type', '#^application/json$#');
+
+        $content = $this->getResponse()->getBody();
+
+        $this->assertRegExp('#^{"id"\:"\d+","randomNumber":"\d+"}$#', $content);
+
+        $decodedContent = json_decode($content, true);
+
+        $this->assertTrue(json_last_error() === JSON_ERROR_NONE, 'Json decode failure');
+
+        $this->assertArrayHasKey('id', $decodedContent);
+        $this->assertGreaterThan(0, $decodedContent['id']);
+        $this->assertLessThan(10000, $decodedContent['id']);
+
+        $this->assertArrayHasKey('randomNumber', $decodedContent);
+        $this->assertGreaterThan(0, $decodedContent['randomNumber']);
+        $this->assertLessThan(10000, $decodedContent['randomNumber']);
+
+        $this->assertCount(2, $decodedContent);
+    }
+}

+ 76 - 0
frameworks/PHP/php-zend-framework1/test/application/controllers/DbMultiControllerTest.php

@@ -0,0 +1,76 @@
+<?php
+
+class DbMultiControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
+{
+    protected function setUp()
+    {
+        $this->bootstrap = new Zend_Application(
+            APPLICATION_ENV,
+            APPLICATION_PATH . '/configs/application.ini'
+        );
+
+        parent::setUp();
+    }
+
+    public function testType3MultipleDatabaseQueries()
+    {
+        $this->dispatch('/db-multi?queries=2');
+        $this->assertResponseResultsEquals(2, $this->getResponse()->getBody());
+    }
+
+    public function testType3MultipleDatabaseQueryLessThan1DefaultsTo1()
+    {
+        $this->dispatch('/db-multi?queries=-1');
+        $this->assertResponseResultsEquals(1, $this->getResponse()->getBody());
+    }
+
+    public function testType3MultipleDatabaseQueryMoreThan500DefaultsTo500()
+    {
+        $this->dispatch('/db-multi?queries=501');
+        $this->assertResponseResultsEquals(500, $this->getResponse()->getBody());
+    }
+
+    public function testType3MultipleDatabaseQueryNotAnIntDefaultsTo1()
+    {
+        $this->dispatch('/db-multi?queries=foobar');
+        $this->assertResponseResultsEquals(1, $this->getResponse()->getBody());
+    }
+
+    public function testType3MultipleDatabaseQueryNoQueriesParamDefaultsTo1()
+    {
+        $this->dispatch('/db-multi');
+        $this->assertResponseResultsEquals(1, $this->getResponse()->getBody());
+    }
+    /**
+     * Helper assertion
+     *
+     * @param  int $expectedCount
+     * @param  string $content
+     */
+    protected function assertResponseResultsEquals($expectedCount, $content)
+    {
+        $this->assertModule('default');
+        $this->assertController('db-multi');
+        $this->assertAction('index');
+        $this->assertResponseCode(200);
+        $this->assertHeaderRegex('Content-Type', '#^application/json$#');
+
+        $results = json_decode($content, true);
+
+        $this->assertTrue(json_last_error() === JSON_ERROR_NONE, 'Json decode failure');
+
+        $this->assertCount($expectedCount, $results);
+
+        $count = count($results);
+        for ($i = 0; $i < $count; $i++) {
+
+            $this->assertArrayHasKey('id', $results[$i]);
+            $this->assertGreaterThan(0, $results[$i]['id']);
+            $this->assertLessThan(10000, $results[$i]['id']);
+
+            $this->assertArrayHasKey('randomNumber', $results[$i]);
+            $this->assertGreaterThan(0, $results[$i]['randomNumber']);
+            $this->assertLessThan(10000, $results[$i]['randomNumber']);
+        }
+    }
+}

+ 30 - 0
frameworks/PHP/php-zend-framework1/test/application/controllers/JsonControllerTest.php

@@ -0,0 +1,30 @@
+<?php
+
+class JsonControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
+{
+    protected function setUp()
+    {
+        $this->bootstrap = new Zend_Application(
+            APPLICATION_ENV,
+            APPLICATION_PATH . '/configs/application.ini'
+        );
+
+        parent::setUp();
+    }
+
+    public function testType1JsonSerialization()
+    {
+        $this->dispatch('/json');
+
+        $this->assertModule('default');
+        $this->assertController('json');
+        $this->assertAction('index');
+        $this->assertResponseCode(200);
+        $this->assertHeaderRegex('Content-Type', '#^application/json$#');
+
+        $content = $this->getResponse()->getBody();
+
+        $this->assertSame('{"message":"Hello, World!"}', $content);
+        $this->assertEquals(27, iconv_strlen($content, 'UTF-8'));
+    }
+}

+ 22 - 0
frameworks/PHP/php-zend-framework1/test/bootstrap.php

@@ -0,0 +1,22 @@
+<?php
+
+ini_set('error_reporting', -1);
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+ini_set('log_errors', 0);
+ini_set('date.timezone', 'UTC');
+ini_set('max_execution_time', 0);
+
+// Define path to application directory
+defined('APPLICATION_PATH')
+    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
+
+// Define application environment
+defined('APPLICATION_ENV')
+    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));
+
+// Ensure library/ is on include_path
+set_include_path(realpath(dirname(__FILE__) . '/../vendor/zendframework/zendframework1/library'));
+
+require_once 'Zend/Loader/Autoloader.php';
+Zend_Loader_Autoloader::getInstance();

+ 1 - 1
frameworks/Scala/play-activate-mysql/setup.py

@@ -26,7 +26,7 @@ def stop(logfile, errfile):
     with open("./play-activate-mysql/target/universal/play-activate-mysql-1.0-SNAPSHOT/RUNNING_PID") as f:
       pid = int(f.read())
       os.kill(pid,15)
-  except:
+  except Exception:
     return 1
 
   try:

+ 67 - 30
toolset/benchmark/benchmarker.py

@@ -18,6 +18,7 @@ import sys
 import logging
 import socket
 import threading
+import textwrap
 from pprint import pprint
 
 from multiprocessing import Process
@@ -493,7 +494,7 @@ class Benchmarker:
 
     try:
       os.makedirs(os.path.join(self.latest_results_directory, 'logs', "{name}".format(name=test.name)))
-    except:
+    except Exception:
       pass
     with open(os.path.join(self.latest_results_directory, 'logs', "{name}".format(name=test.name), 'out.txt'), 'w') as out, \
          open(os.path.join(self.latest_results_directory, 'logs', "{name}".format(name=test.name), 'err.txt'), 'w') as err:
@@ -536,10 +537,16 @@ class Benchmarker:
           time.sleep(10)
 
         if self.__is_port_bound(test.port):
-          self.__write_intermediate_results(test.name, "port " + str(test.port) + " is not available before start")
-          err.write(header("Error: Port %s is not available, cannot start %s" % (test.port, test.name)))
+          err.write(header("Error: Port %s is not available, attempting to recover" % test.port))
           err.flush()
-          return exit_with_code(1)
+          print "Error: Port %s is not available, attempting to recover" % test.port
+          self.__forciblyEndPortBoundProcesses(test.port, out, err)
+          if self.__is_port_bound(test.port):
+            self.__write_intermediate_results(test.name, "port " + str(test.port) + " is not available before start")
+            err.write(header("Error: Port %s is not available, cannot start %s" % (test.port, test.name)))
+            err.flush()
+            print "Error: Unable to recover port, cannot start test"
+            return exit_with_code(1)
 
         result = test.start(out, err)
         if result != 0: 
@@ -655,7 +662,7 @@ class Benchmarker:
       s.bind(("", port))
       # If we get here, we were able to bind successfully,
       # which means the port is free.
-    except:
+    except Exception:
       # If we get an exception, it might be because the port is still bound
       # which would be bad, or maybe it is a privileged port (<1024) and we
       # are not running as root, or maybe the server is gone, but sockets are
@@ -666,7 +673,7 @@ class Benchmarker:
         # If we get here, we were able to connect to something, which means
         # that the port is still bound.
         return True
-      except:
+      except Exception:
         # An exception means that we couldn't connect, so a server probably
         # isn't still running on the port.
         pass
@@ -681,41 +688,67 @@ class Benchmarker:
 
   def __forciblyEndPortBoundProcesses(self, test_port, out, err):
     p = subprocess.Popen(['sudo', 'netstat', '-lnp'], stdout=subprocess.PIPE)
-    out, err = p.communicate()
-    for line in out.splitlines():
-      if 'tcp' in line:
+    (ns_out, ns_err) = p.communicate()
+    for line in ns_out.splitlines():
+      # Handles tcp, tcp6, udp, udp6
+      if line.startswith('tcp') or line.startswith('udp'):
         splitline = line.split()
-        port = splitline[3].split(':')
-        port = int(port[len(port) - 1].strip())
+        port = int(splitline[3].split(':')[-1])
+        pid  = splitline[-1].split('/')[0]
+
+        # Sometimes the last column is just a dash
+        if pid == '-':
+          continue
+
         if port > 6000:
+          ps = subprocess.Popen(['ps','p',pid], stdout=subprocess.PIPE)
+          (out_6000, err_6000) = ps.communicate()
           err.write(textwrap.dedent(
-        """
-        A port that shouldn't be open is open. See the following line for netstat output.
-        {splitline}
-        """.format(splitline=splitline)))
+          """
+          Port {port} should not be open. See the following lines for information
+          {netstat}
+          {ps}
+          """.format(port=port, netstat=line, ps=out_6000)))
           err.flush()
+
         if port == test_port:
+          err.write( header("Error: Test port %s should not be open" % port, bottom='') )
           try:
-            pid = splitline[6].split('/')[0].strip()
             ps = subprocess.Popen(['ps','p',pid], stdout=subprocess.PIPE)
             # Store some info about this process
-            proc = ps.communicate()
-            os.kill(int(pid), 15)
+            (out_15, err_15) = ps.communicate()
+            children = subprocess.Popen(['ps','--ppid',pid,'-o','ppid'], stdout=subprocess.PIPE)
+            (out_children, err_children) = children.communicate()
+
+            err.write("  Sending SIGTERM to this process:\n  %s\n" % out_15)
+            err.write("  Also expecting these child processes to die:\n  %s\n" % out_children)
+
+            subprocess.check_output(['sudo','kill',pid])
             # Sleep for 10 sec; kill can be finicky
             time.sleep(10)
+
             # Check that PID again
             ps = subprocess.Popen(['ps','p',pid], stdout=subprocess.PIPE)
-            dead = ps.communicate()
-            if dead in proc:
-              os.kill(int(pid), 9)
-          except OSError:
-            out.write( textwrap.dedent("""
-              -----------------------------------------------------
-                Error: Could not kill pid {pid}
-              -----------------------------------------------------
-              """.format(pid=str(pid))) )
-            # This is okay; likely we killed a parent that ended
-            # up automatically killing this before we could.
+            (out_9, err_9) = ps.communicate()
+            if len(out_9.splitlines()) != 1:  # One line for the header row
+              err.write("  Process is still alive!\n")
+              err.write("  Sending SIGKILL to this process:\n   %s\n" % out_9)
+              subprocess.check_output(['sudo','kill','-9', pid])
+            else:
+              err.write("  Process has been terminated\n")
+
+            # Ensure all children are dead
+            c_pids = [c_pid.strip() for c_pid in out_children.splitlines()[1:]]
+            for c_pid in c_pids:
+              ps = subprocess.Popen(['ps','p',c_pid], stdout=subprocess.PIPE)
+              (out_9, err_9) = ps.communicate()
+              if len(out_9.splitlines()) != 1:  # One line for the header row
+                err.write("  Child Process %s is still alive, sending SIGKILL\n" % c_pid)
+                subprocess.check_output(['sudo','kill','-9', pid])
+          except Exception as e: 
+            err.write( "  Error: Unknown exception %s\n" % e )
+          err.write( header("Done attempting to recover port %s" % port, top='') )
+
 
   ############################################################
   # __parse_results
@@ -904,6 +937,10 @@ class Benchmarker:
     else:
         args['types'] = { args['type'] : types[args['type']] }
     del args['type']
+    
+
+    args['max_threads'] = args['threads']
+    args['max_concurrency'] = max(args['concurrency_levels'])
 
     self.__dict__.update(args)
     # pprint(self.__dict__)
@@ -926,7 +963,7 @@ class Benchmarker:
     self.result_directory = os.path.join("results", self.name)
     self.latest_results_directory = self.latest_results_directory()
   
-    if self.parse != None:
+    if hasattr(self, 'parse') and self.parse != None:
       self.timestamp = self.parse
     else:
       self.timestamp = time.strftime("%Y%m%d%H%M%S", time.localtime())

+ 16 - 13
toolset/benchmark/framework_test.py

@@ -297,7 +297,9 @@ class FrameworkTest:
           pass
 
       if test.passed:
-        if test.requires_db:
+        if test_type == 'plaintext': # One special case
+          remote_script = self.__generate_concurrency_script(test.get_url(), self.port, test.accept_header, levels=[256,1024,4096,16384], pipeline="16")
+        elif test.requires_db:
           remote_script = self.__generate_query_script(test.get_url(), self.port, test.accept_header)
         else:
           remote_script = self.__generate_concurrency_script(test.get_url(), self.port, test.accept_header)
@@ -306,9 +308,10 @@ class FrameworkTest:
         self.__begin_logging(test_type)
         
         # Run the benchmark 
-        p = subprocess.Popen(self.benchmarker.client_ssh_string.split(" "), stdin=subprocess.PIPE, stdout=output_file, stderr=err)
-        p.communicate(remote_script)
-        err.flush()
+        with open(output_file, 'w') as raw_file:
+          p = subprocess.Popen(self.benchmarker.client_ssh_string.split(" "), stdin=subprocess.PIPE, stdout=raw_file, stderr=err)
+          p.communicate(remote_script)
+          err.flush()
 
         # End resource usage metrics collection
         self.__end_logging()
@@ -454,13 +457,13 @@ class FrameworkTest:
   # specifically works for the variable concurrency tests (JSON
   # and DB)
   ############################################################
-  def __generate_concurrency_script(self, url, port, accept_header, wrk_command="wrk", intervals=[], pipeline=""):
-    if len(intervals) == 0:
-      intervals = self.benchmarker.concurrency_levels
+  def __generate_concurrency_script(self, url, port, accept_header, wrk_command="wrk", levels=[], pipeline=""):
+    if len(levels) == 0:
+      levels = self.benchmarker.concurrency_levels
     headers = self.headers_template.format(accept=accept_header)
-    return self.concurrency_template.format(max_concurrency=self.benchmarker.max_concurrency, 
-      max_threads=self.benchmarker.max_threads, name=self.name, duration=self.benchmarker.duration, 
-      interval=" ".join("{}".format(item) for item in intervals), 
+    return self.concurrency_template.format(max_concurrency=max(self.benchmarker.concurrency_levels), 
+      max_threads=self.benchmarker.threads, name=self.name, duration=self.benchmarker.duration, 
+      levels=" ".join("{}".format(item) for item in levels), 
       server_host=self.benchmarker.server_host, port=port, url=url, headers=headers, wrk=wrk_command,
       pipeline=pipeline)
 
@@ -472,9 +475,9 @@ class FrameworkTest:
   ############################################################
   def __generate_query_script(self, url, port, accept_header):
     headers = self.headers_template.format(accept=accept_header)
-    return self.query_template.format(max_concurrency=self.benchmarker.max_concurrency, 
-      max_threads=self.benchmarker.max_threads, name=self.name, duration=self.benchmarker.duration, 
-      interval=" ".join("{}".format(item) for item in self.benchmarker.query_intervals), 
+    return self.query_template.format(max_concurrency=max(self.benchmarker.concurrency_levels), 
+      max_threads=self.benchmarker.threads, name=self.name, duration=self.benchmarker.duration, 
+      levels=" ".join("{}".format(item) for item in self.benchmarker.query_levels), 
       server_host=self.benchmarker.server_host, port=port, url=url, headers=headers)
 
   ############################################################

+ 5 - 1
toolset/benchmark/test_types/db_type.py

@@ -73,7 +73,11 @@ class DBTestType(FrameworkTestType):
     if "id" not in db_object:
       problems.append( ('fail', "Response has no 'id' key", url) ) 
     if "randomnumber" not in db_object:
-      problems.append( ('fail', "Response has no 'randomNumber' key", url) ) 
+      problems.append( ('fail', "Response has no 'randomNumber' key", url) )
+    
+    # Ensure we can continue on to use these keys
+    if "id" not in db_object or "randomnumber" not in db_object:
+      return problems
 
     try:
       float(db_object["id"])

+ 4 - 3
toolset/benchmark/test_types/framework_test_type.py

@@ -64,17 +64,18 @@ class FrameworkTestType:
     # Don't use -f so that the HTTP response code is ignored.
     # Use -sS to hide progress bar, but show errors.
     print "Accessing URL %s" % url
+    self.err.write("Accessing URL %s \n" % url)
+    self.out.write("Accessing URL %s \n" % url)
     p = subprocess.Popen(["curl", "-m", "15", "-i", "-sS", url], stderr=PIPE, stdout=PIPE)
     (out, err) = p.communicate()
     self.err.write(err+'\n')
-    self.out.write(out+'\n')
+    self.out.write("Response: \n\"" + out+ "\"\n")
     if p.returncode != 0:
       return None
     # Get response body
     p = subprocess.Popen(["curl", "-m", "15", "-s", url], stdout=PIPE, stderr=PIPE)
     (out, err) = p.communicate()
-    self.err.write(err+'\n')
-    self.out.write(out+'\n')
+    print "  Response (trimmed to 40 bytes): \"%s\"" % out[:40]
     return out
   
   def verify(self, base_url):

+ 2 - 2
toolset/benchmark/test_types/plaintext_type.py

@@ -23,8 +23,8 @@ class PlaintextTestType(FrameworkTestType):
       return [('fail', "Could not find 'Hello, World!' in response", url)]
 
     if len("hello, world!") < len(body):
-      return [('warn', '''Server is returning more data than is required.
-        This may negatively affect benchmark performance''', url)]
+      return [('warn', """Server is returning %s more bytes than are required.
+        This may negatively affect benchmark performance""" % (len(body) - len("hello, world!")), url)]
 
     return [('pass', '', url)]
 

+ 15 - 8
toolset/benchmark/test_types/query_type.py

@@ -30,11 +30,18 @@ class QueryTestType(DBTestType):
     body = self._curl(url + '0')
     problems += self._verifyQueryList(1, body, url + '0', 'warn')
 
+    # Note: A number of tests fail here because they only parse for 
+    # a number and crash on 'foo'. For now we only warn about this
     body = self._curl(url + 'foo')
-    problems += self._verifyQueryList(1, body, url + 'foo')
+    if body is None:
+      problems += [('warn','No response (this will be a failure in future rounds, please fix)', url)]
+    elif len(body) == 0:
+      problems += [('warn','Empty response (this will be a failure in future rounds, please fix)', url)]
+    else:
+      problems += self._verifyQueryList(1, body, url + 'foo', 'warn')
 
     body = self._curl(url + '501')
-    problems += self._verifyQueryList(500, body, url + '501')
+    problems += self._verifyQueryList(500, body, url + '501', 'warn')
 
     if len(problems) == 0:
       return [('pass','',url + '2'),
@@ -44,22 +51,22 @@ class QueryTestType(DBTestType):
     else:
       return problems
 
-  def _verifyQueryList(self, expectedLength, body, url, incorrect_length_response='fail'):
+  def _verifyQueryList(self, expectedLength, body, url, max_infraction='fail'):
     '''Validates high-level structure (array length, object 
       types, etc) before calling into DBTestType to 
       validate a few individual JSON objects'''
 
     # Empty response
     if body is None:
-      return [('fail','No response', url)]
+      return [(max_infraction,'No response', url)]
     elif len(body) == 0:
-      return [('fail','Empty Response', url)]
+      return [(max_infraction,'Empty Response', url)]
   
     # Valid JSON? 
     try: 
       response = json.loads(body)
     except ValueError as ve:
-      return [('fail',"Invalid JSON - %s" % ve, url)]
+      return [(max_infraction,"Invalid JSON - %s" % ve, url)]
 
     problems = []
 
@@ -72,11 +79,11 @@ class QueryTestType(DBTestType):
       return problems
 
     if any(type(item) != dict for item in response):
-      problems.append(('fail','All items JSON array must be JSON objects', url))
+      problems.append((max_infraction,'All items JSON array must be JSON objects', url))
 
     # For some edge cases we only warn
     if len(response) != expectedLength:
-      problems.append((incorrect_length_response,
+      problems.append((max_infraction,
         "JSON array length of %s != expected length of %s" % (len(response), expectedLength), 
         url))
 

+ 1 - 1
toolset/benchmark/utils.py

@@ -43,7 +43,7 @@ def gather_tests(include = [], exclude=[], benchmarker=None):
     for k,v in defaults.iteritems():
       try:
         defaults[k] = literal_eval(v)
-      except:
+      except Exception:
         pass
 
     # Ensure we only run the __init__ method of Benchmarker

+ 1 - 1
toolset/run-ci.py

@@ -444,7 +444,7 @@ if __name__ == "__main__":
     log.warning("Environment key missing, are you running inside Travis-CI?")
     print traceback.format_exc()
     retcode = 1
-  except:
+  except Exception:
     log.critical("Unknown error")
     print traceback.format_exc()
     retcode = 1

+ 16 - 9
toolset/run-tests.py

@@ -11,6 +11,7 @@ from pprint import pprint
 from benchmark.benchmarker import Benchmarker
 from setup.linux.unbuffered import Unbuffered
 from setup.linux import setup_util
+from ast import literal_eval
 
 # Enable cross-platform colored output
 from colorama import init
@@ -51,7 +52,7 @@ def main(argv=None):
     # Do argv default this way, as doing it in the functional declaration sets it at compile time
     if argv is None:
         argv = sys.argv
-	
+
     # Enable unbuffered output so messages will appear in the proper order with subprocess output.
     sys.stdout=Unbuffered(sys.stdout)
 
@@ -80,6 +81,12 @@ def main(argv=None):
             config = ConfigParser.SafeConfigParser()
             config.read([os.getcwd() + '/' + args.conf_file])
             defaults = dict(config.items("Defaults"))
+            # Convert strings into proper python types
+            for k,v in defaults.iteritems():
+                try:
+                    defaults[k] = literal_eval(v)
+                except Exception:
+                    pass
     except IOError:
         if args.conf_file != 'benchmark.cfg':
             print 'Configuration file not found!'
@@ -98,7 +105,7 @@ def main(argv=None):
     maxThreads = 8
     try:
         maxThreads = multiprocessing.cpu_count()
-    except:
+    except Exception:
         pass
 
     ##########################################################
@@ -134,7 +141,7 @@ def main(argv=None):
                         help='Runs installation script(s) before continuing on to execute the tests.')
     parser.add_argument('--install-error-action', choices=['abort', 'continue'], default='continue', help='action to take in case of error during installation')
     parser.add_argument('--install-strategy', choices=['unified', 'pertest'], default='unified', 
-        help='''Affects `--install server`: With unified, all server software is installed into a single directory. 
+        help='''Affects : With unified, all server software is installed into a single directory. 
         With pertest each test gets its own installs directory, but installation takes longer''')
     parser.add_argument('--install-only', action='store_true', default=False, help='Do not run benchmark or verification, just install and exit')
 
@@ -180,18 +187,18 @@ def main(argv=None):
         print 'Configuration options: '
         pprint(vars(args))
 
-
-
     benchmarker = Benchmarker(vars(args))
 
     # Run the benchmarker in the specified mode
-    if benchmarker.list_tests:
+    #   Do not use benchmarker variables for these checks, 
+    #   they are either str or bool based on the python version
+    if args.list_tests:
       benchmarker.run_list_tests()
-    elif benchmarker.list_test_metadata:
+    elif args.list_test_metadata:
       benchmarker.run_list_test_metadata()
-    elif benchmarker.parse != None:
+    elif args.parse != None:
       benchmarker.parse_timestamp()
-    elif not benchmarker.install_only:
+    elif not args.install_only:
       return benchmarker.run()
 
 if __name__ == "__main__":

+ 4 - 3
toolset/setup/linux/frameworks/wt.sh

@@ -21,7 +21,7 @@ RETCODE=$(fw_exists wt)
 # Instead of compiling from source, just use apt to install onto 
 # host machine
 source /etc/lsb-release
-if [ "$DISTRIB_RELEASE" -eq "14.04" ]; then
+if [ "$DISTRIB_RELEASE" == "14.04" ]; then
     sudo apt-get -y install libboost1.54-all-dev
 else
     sudo apt-get -y install libboost1.48-all-dev
@@ -35,6 +35,7 @@ mkdir -p build
 cd build
 cmake .. -DWT_CPP_11_MODE=-std=c++0x -DCMAKE_BUILD_TYPE=Release \
   -DCMAKE_INSTALL_PREFIX=${IROOT}/wt -DCONFIGDIR=${IROOT}/wt/etc \
-  -DCMAKE_CXX_COMPILER=$(which g++-4.8)
+  -DCMAKE_CXX_COMPILER=$(which g++-4.8) -DDESTDIR=${IROOT}/wt \
+  -DWEBUSER=$(id -u -n) -DWEBGROUP=$(id -g -n)
 make
-make install
+make install

+ 3 - 3
toolset/setup/linux/languages/python2.sh

@@ -7,9 +7,9 @@ fw_get http://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz
 fw_untar Python-2.7.8.tgz
 pre=$(pwd)
 cd Python-2.7.8
-./configure --prefix=${pre}/py2 --disable-shared
-make -j4
-make install
+./configure --prefix=${pre}/py2 --disable-shared --quiet
+make -j4 --quiet
+make install --quiet
 cd ..
 
 if [ ! -f "get-pip.py" ]; then

+ 3 - 3
toolset/setup/linux/languages/python3.sh

@@ -7,9 +7,9 @@ fw_get http://www.python.org/ftp/python/3.4.1/Python-3.4.1.tar.xz
 fw_untar Python-3.4.1.tar.xz
 pre=$(pwd)
 cd Python-3.4.1
-./configure --prefix=${pre}/py3 --disable-shared
-make -j4
-make install
+./configure --prefix=${pre}/py3 --disable-shared --quiet
+make -j4 --quiet
+make install --quiet
 cd ..
 
 if [ ! -f "get-pip.py" ]; then

+ 3 - 1
toolset/setup/linux/languages/rvm.sh

@@ -16,7 +16,9 @@ RETCODE=$(fw_exists rvm.installed)
 }
 
 # Run single-user installation and source rvm
+export SHELL=/bin/bash
+gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
 \curl -sSL https://get.rvm.io | bash -s stable
 source $HOME/.rvm/scripts/rvm
 
-touch $IROOT/rvm.installed
+touch $IROOT/rvm.installed

+ 1 - 1
toolset/setup/linux/setup_util.py

@@ -62,7 +62,7 @@ def replace_environ(config=None, root=None, print_result=False, command='true'):
                     os.environ[key]=mini_environ[key]
                 else:
                     os.environ[key]=value    
-            except:
+            except Exception:
                 if not line: # Don't warn for empty line
                     continue 
                 print "WARN: Line '%s' from '%s' is not an environment variable" % (line, config)

+ 12 - 0
toolset/setup/linux/systools/rebar.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+
+RETCODE=$(fw_exists $IROOT/rebar.installed)
+[ ! "$RETCODE" == 0 ] || { return 0; }
+
+fw_get https://github.com/rebar/rebar/archive/2.5.1.tar.gz -O rebar-2.5.1.tar.gz
+fw_untar rebar-2.5.1.tar.gz
+mv rebar-2.5.1 rebar
+cd rebar
+./bootstrap
+
+touch $IROOT/rebar.installed

+ 6 - 0
toolset/setup/linux/webservers/apache.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+sudo apt-get install -y apache2
+
+# Stop Apache; it starts after it is installed
+sudo /etc/init.d/apache2 stop