Browse Source

Missing tests implementation

jamming 10 years ago
parent
commit
54b88b6dec

+ 123 - 123
.travis.yml

@@ -15,135 +15,135 @@ env:
     #   find . -type d -depth 2 | sed 's|./|    - "TESTDIR=|' | sed 's/$/"/g'
     #
     #  
-    - "TESTDIR=C/lwan"
-    - "TESTDIR=C/duda"
-    - "TESTDIR=C/haywire"
-    - "TESTDIR=C/onion"
-    - "TESTDIR=CSharp/aspnet"
+    #- "TESTDIR=C/lwan"
+    #- "TESTDIR=C/duda"
+    #- "TESTDIR=C/haywire"
+    #- "TESTDIR=C/onion"
+    #- "TESTDIR=CSharp/aspnet"
     # - "TESTDIR=CSharp/aspnet-stripped"
-    - "TESTDIR=CSharp/evhttp-sharp"
+    #- "TESTDIR=CSharp/evhttp-sharp"
     # - "TESTDIR=CSharp/HttpListener"
-    - "TESTDIR=CSharp/nancy"
-    - "TESTDIR=CSharp/servicestack"
-    - "TESTDIR=C++/cpoll_cppsp"
-    - "TESTDIR=C++/treefrog"
-    - "TESTDIR=C++/ULib"
-    - "TESTDIR=C++/wt"
-    - "TESTDIR=Clojure/compojure"
-    - "TESTDIR=Clojure/http-kit"
-    - "TESTDIR=Clojure/luminus"
-    - "TESTDIR=Dart/dart"
-    - "TESTDIR=Dart/dart-redstone"
-    - "TESTDIR=Dart/dart-start"
-    - "TESTDIR=Dart/dart-stream"
-    - "TESTDIR=Elixir/WeberFramework"
-    - "TESTDIR=Erlang/cowboy"
-    - "TESTDIR=Erlang/elli"
-    - "TESTDIR=Go/beego"
-    - "TESTDIR=Go/falcore"
-    - "TESTDIR=Go/gin"
-    - "TESTDIR=Go/go"
-    - "TESTDIR=Go/gorail"
-    - "TESTDIR=Go/revel"
-    - "TESTDIR=Go/revel-jet"
-    - "TESTDIR=Go/revel-qbs"
-    - "TESTDIR=Go/webgo"
-    - "TESTDIR=Groovy/grails"
-    - "TESTDIR=Haskell/snap"
-    - "TESTDIR=Haskell/wai"
-    - "TESTDIR=Haskell/yesod"
-    - "TESTDIR=Java/activeweb"
-    - "TESTDIR=Java/curacao"
-    - "TESTDIR=Java/dropwizard"
-    - "TESTDIR=Java/dropwizard-mongodb"
-    - "TESTDIR=Java/gemini"
-    - "TESTDIR=Java/grizzly-bm"
-    - "TESTDIR=Java/grizzly-jersey"
-    - "TESTDIR=Java/jetty-servlet"
-    - "TESTDIR=Java/netty"
-    - "TESTDIR=Java/ninja-standalone"
-    - "TESTDIR=Java/play1"
-    - "TESTDIR=Java/play1siena"
-    - "TESTDIR=Java/play2-java"
-    - "TESTDIR=Java/restexpress"
+    #- "TESTDIR=CSharp/nancy"
+    #- "TESTDIR=CSharp/servicestack"
+    #- "TESTDIR=C++/cpoll_cppsp"
+    #- "TESTDIR=C++/treefrog"
+    #- "TESTDIR=C++/ULib"
+    #- "TESTDIR=C++/wt"
+    #- "TESTDIR=Clojure/compojure"
+    #- "TESTDIR=Clojure/http-kit"
+    #- "TESTDIR=Clojure/luminus"
+    #- "TESTDIR=Dart/dart"
+    #- "TESTDIR=Dart/dart-redstone"
+    #- "TESTDIR=Dart/dart-start"
+    #- "TESTDIR=Dart/dart-stream"
+    #- "TESTDIR=Elixir/WeberFramework"
+    #- "TESTDIR=Erlang/cowboy"
+    #- "TESTDIR=Erlang/elli"
+    #- "TESTDIR=Go/beego"
+    #- "TESTDIR=Go/falcore"
+    #- "TESTDIR=Go/gin"
+    #- "TESTDIR=Go/go"
+    #- "TESTDIR=Go/gorail"
+    #- "TESTDIR=Go/revel"
+    #- "TESTDIR=Go/revel-jet"
+    #- "TESTDIR=Go/revel-qbs"
+    #- "TESTDIR=Go/webgo"
+    #- "TESTDIR=Groovy/grails"
+    #- "TESTDIR=Haskell/snap"
+    #- "TESTDIR=Haskell/wai"
+    #- "TESTDIR=Haskell/yesod"
+    #- "TESTDIR=Java/activeweb"
+    #- "TESTDIR=Java/curacao"
+    #- "TESTDIR=Java/dropwizard"
+    #- "TESTDIR=Java/dropwizard-mongodb"
+    #- "TESTDIR=Java/gemini"
+    #- "TESTDIR=Java/grizzly-bm"
+    #- "TESTDIR=Java/grizzly-jersey"
+    #- "TESTDIR=Java/jetty-servlet"
+    #- "TESTDIR=Java/netty"
+    #- "TESTDIR=Java/ninja-standalone"
+    #- "TESTDIR=Java/play1"
+    #- "TESTDIR=Java/play1siena"
+    #- "TESTDIR=Java/play2-java"
+    #- "TESTDIR=Java/restexpress"
     - "TESTDIR=Java/servlet"
     - "TESTDIR=Java/servlet3-cass"
     - "TESTDIR=Java/spark"
     - "TESTDIR=Java/sabina"
-    - "TESTDIR=Java/spring"
-    - "TESTDIR=Java/tapestry"
-    - "TESTDIR=Java/undertow"
-    - "TESTDIR=Java/undertow-edge"
-    - "TESTDIR=Java/vertx"
-    - "TESTDIR=Java/wicket"
-    - "TESTDIR=Java/wildfly-ee7"
-    - "TESTDIR=JavaScript/express"
-    - "TESTDIR=JavaScript/hapi"
-    - "TESTDIR=JavaScript/nodejs"
-    - "TESTDIR=JavaScript/ringojs"
-    - "TESTDIR=JavaScript/ringojs-convenient"
-    - "TESTDIR=Lua/lapis"
-    - "TESTDIR=Lua/openresty"
-    - "TESTDIR=Nim/jester"
-    - "TESTDIR=Nim/nawak"
-    - "TESTDIR=Perl/dancer"
-    - "TESTDIR=Perl/kelp"
-    - "TESTDIR=Perl/mojolicious"
-    - "TESTDIR=Perl/plack"
-    - "TESTDIR=Perl/web-simple"
-    - "TESTDIR=PHP/cakephp"
-    - "TESTDIR=PHP/hhvm"
-    - "TESTDIR=PHP/php"
-    - "TESTDIR=PHP/codeigniter"
-    - "TESTDIR=PHP/php-fatfree"
-    - "TESTDIR=PHP/fuel"
-    - "TESTDIR=PHP/kohana"
-    - "TESTDIR=PHP/php-laravel"
-    - "TESTDIR=PHP/lithium"
-    - "TESTDIR=PHP/php-micromvc"
-    - "TESTDIR=PHP/php-phalcon"
-    - "TESTDIR=PHP/php-phalcon-micro"
-    - "TESTDIR=PHP/php-phpixie"
-    - "TESTDIR=PHP/php-pimf"
-    - "TESTDIR=PHP/php-silex"
-    - "TESTDIR=PHP/php-silex-orm"
-    - "TESTDIR=PHP/php-silica"
-    - "TESTDIR=PHP/php-slim"
-    - "TESTDIR=PHP/symfony2"
-    - "TESTDIR=PHP/symfony2-stripped"
-    - "TESTDIR=PHP/php-yaf"
-    - "TESTDIR=PHP/Yii2"
-    - "TESTDIR=PHP/php-zend-framework"
-    - "TESTDIR=PHP/php-zend-framework1"
-    - "TESTDIR=PHP/phreeze"
-    - "TESTDIR=Python/API-Hour"
-    - "TESTDIR=Python/bottle"
-    - "TESTDIR=Python/django"
-    - "TESTDIR=Python/falcon"
-    - "TESTDIR=Python/flask"
-    - "TESTDIR=Python/pyramid"
-    - "TESTDIR=Python/tornado"
-    - "TESTDIR=Python/uwsgi"
-    - "TESTDIR=Python/wsgi"
-    - "TESTDIR=Racket/racket-ws"
-    - "TESTDIR=Ruby/grape"
-    - "TESTDIR=Ruby/ngx_mruby"
-    - "TESTDIR=Ruby/padrino"
-    - "TESTDIR=Ruby/rack"
-    - "TESTDIR=Ruby/rails"
-    - "TESTDIR=Ruby/rails-stripped"
-    - "TESTDIR=Ruby/sinatra"
-    - "TESTDIR=Scala/finagle"
-    - "TESTDIR=Scala/lift-stateless"
-    - "TESTDIR=Scala/plain"
-    - "TESTDIR=Scala/play-activate-mysql"
-    - "TESTDIR=Scala/play-scala-mongodb"
-    - "TESTDIR=Scala/play2-scala"
-    - "TESTDIR=Scala/scalatra"
-    - "TESTDIR=Scala/scruffy"
-    - "TESTDIR=Scala/spray"
-    - "TESTDIR=Scala/unfiltered"
-    - "TESTDIR=Ur/urweb"
+    #- "TESTDIR=Java/spring"
+    #- "TESTDIR=Java/tapestry"
+    #- "TESTDIR=Java/undertow"
+    #- "TESTDIR=Java/undertow-edge"
+    #- "TESTDIR=Java/vertx"
+    #- "TESTDIR=Java/wicket"
+    #- "TESTDIR=Java/wildfly-ee7"
+    #- "TESTDIR=JavaScript/express"
+    #- "TESTDIR=JavaScript/hapi"
+    #- "TESTDIR=JavaScript/nodejs"
+    #- "TESTDIR=JavaScript/ringojs"
+    #- "TESTDIR=JavaScript/ringojs-convenient"
+    #- "TESTDIR=Lua/lapis"
+    #- "TESTDIR=Lua/openresty"
+    #- "TESTDIR=Nim/jester"
+    #- "TESTDIR=Nim/nawak"
+    #- "TESTDIR=Perl/dancer"
+    #- "TESTDIR=Perl/kelp"
+    #- "TESTDIR=Perl/mojolicious"
+    #- "TESTDIR=Perl/plack"
+    #- "TESTDIR=Perl/web-simple"
+    #- "TESTDIR=PHP/cakephp"
+    #- "TESTDIR=PHP/hhvm"
+    #- "TESTDIR=PHP/php"
+    #- "TESTDIR=PHP/codeigniter"
+    #- "TESTDIR=PHP/php-fatfree"
+    #- "TESTDIR=PHP/fuel"
+    #- "TESTDIR=PHP/kohana"
+    #- "TESTDIR=PHP/php-laravel"
+    #- "TESTDIR=PHP/lithium"
+    #- "TESTDIR=PHP/php-micromvc"
+    #- "TESTDIR=PHP/php-phalcon"
+    #- "TESTDIR=PHP/php-phalcon-micro"
+    #- "TESTDIR=PHP/php-phpixie"
+    #- "TESTDIR=PHP/php-pimf"
+    #- "TESTDIR=PHP/php-silex"
+    #- "TESTDIR=PHP/php-silex-orm"
+    #- "TESTDIR=PHP/php-silica"
+    #- "TESTDIR=PHP/php-slim"
+    #- "TESTDIR=PHP/symfony2"
+    #- "TESTDIR=PHP/symfony2-stripped"
+    #- "TESTDIR=PHP/php-yaf"
+    #- "TESTDIR=PHP/Yii2"
+    #- "TESTDIR=PHP/php-zend-framework"
+    #- "TESTDIR=PHP/php-zend-framework1"
+    #- "TESTDIR=PHP/phreeze"
+    #- "TESTDIR=Python/API-Hour"
+    #- "TESTDIR=Python/bottle"
+    #- "TESTDIR=Python/django"
+    #- "TESTDIR=Python/falcon"
+    #- "TESTDIR=Python/flask"
+    #- "TESTDIR=Python/pyramid"
+    #- "TESTDIR=Python/tornado"
+    #- "TESTDIR=Python/uwsgi"
+    #- "TESTDIR=Python/wsgi"
+    #- "TESTDIR=Racket/racket-ws"
+    #- "TESTDIR=Ruby/grape"
+    #- "TESTDIR=Ruby/ngx_mruby"
+    #- "TESTDIR=Ruby/padrino"
+    #- "TESTDIR=Ruby/rack"
+    #- "TESTDIR=Ruby/rails"
+    #- "TESTDIR=Ruby/rails-stripped"
+    #- "TESTDIR=Ruby/sinatra"
+    #- "TESTDIR=Scala/finagle"
+    #- "TESTDIR=Scala/lift-stateless"
+    #- "TESTDIR=Scala/plain"
+    #- "TESTDIR=Scala/play-activate-mysql"
+    #- "TESTDIR=Scala/play-scala-mongodb"
+    #- "TESTDIR=Scala/play2-scala"
+    #- "TESTDIR=Scala/scalatra"
+    #- "TESTDIR=Scala/scruffy"
+    #- "TESTDIR=Scala/spray"
+    #- "TESTDIR=Scala/unfiltered"
+    #- "TESTDIR=Ur/urweb"
 
 before_install:
   # Need to install python modules before using 

+ 7 - 4
frameworks/Java/sabina/benchmark_config

@@ -2,16 +2,19 @@
   "framework": "sabina",
   "tests": [{
     "default": {
-      "setup_file": "setup",
       "json_url": "/json",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
       "plaintext_url": "/plaintext",
-      "port": 8080,
+
+      "port": 5050,
+      "setup_file": "setup",
       "approach": "Realistic",
       "classification": "Micro",
       "database": "MySQL",
-      "framework": "sabina",
+      "framework": "Sabina",
       "language": "Java",
       "orm": "Raw",
       "platform": "Servlet",

+ 9 - 3
frameworks/Java/sabina/pom.xml

@@ -7,7 +7,7 @@
 
     <groupId>sabina</groupId>
     <artifactId>sabina</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>1.0.0</version>
 
     <name>Sabina benchmark project</name>
 
@@ -21,9 +21,8 @@
         <maven.compiler.debug>false</maven.compiler.debug>
 
         <db.host>localhost</db.host>
-        <web.port>8080</web.port>
 
-        <sabina-version>1.0.0</sabina-version>
+        <sabina-version>1.1.0</sabina-version>
         <mysql-connector-version>5.1.28</mysql-connector-version>
     </properties>
 
@@ -87,6 +86,13 @@
             <version>4.11</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.8.8</version>
+            <scope>test</scope>
+        </dependency>
+        <!--testCompile 'org.testng:testng:6.8.8'-->
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>fluent-hc</artifactId>

+ 0 - 4
frameworks/Java/sabina/readme.md

@@ -38,7 +38,3 @@ http://localhost:8080/db?queries=5
 
 http://localhost:8080/plaintext
 
-## TODO
-
-* Implement 'update' test
-* Implement 'fortunes' test

+ 7 - 4
frameworks/Java/sabina/source_code

@@ -1,4 +1,7 @@
-./sabina/src/main/java/
-./sabina/src/main/java/Application.java
-./sabina/src/main/java/Message.java
-./sabina/src/main/java/World.java
+./sabina/src/main/java/sabina/benchmark/
+./sabina/src/main/java/sabina/benchmark/Application.java
+./sabina/src/main/java/sabina/benchmark/Message.java
+./sabina/src/main/java/sabina/benchmark/World.java
+./sabina/src/main/java/sabina/benchmark/Fortune.java
+./sabina/src/main/resources/fortunes.mustache
+./sabina/src/main/resources/server.properties

+ 94 - 49
frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java

@@ -3,41 +3,46 @@ package sabina.benchmark;
 import static java.lang.Integer.parseInt;
 import static sabina.Sabina.*;
 import static sabina.content.JsonContent.toJson;
+import static sabina.view.MustacheView.renderMustache;
 
 import com.mchange.v2.c3p0.ComboPooledDataSource;
-import sabina.Exchange;
 import sabina.Request;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.Date;
-import java.util.Properties;
-import java.util.Random;
+import java.util.*;
 import java.util.concurrent.ThreadLocalRandom;
 
 import javax.sql.DataSource;
 
 /**
- * When it is implemented, add this to benchmark_config
- * "fortune_url": "/fortune",
- * "update_url": "/update",
+ * .
  */
 final class Application {
-    private static final Properties CONFIG = loadConfig ();
-    private static final DataSource DS = createSessionFactory ();
-    private static final String QUERY = "select * from world where id = ?";
+    private static final String SETTINGS_RESOURCE = "/server.properties";
+    private static final Properties SETTINGS = loadConfiguration ();
 
+    private static final String JDBC_URL = SETTINGS.getProperty ("mysql.uri")
+        .replace ("${db.host}", "localhost"); // TODO Move this to Gradle build
+    private static final DataSource DATA_SOURCE = createSessionFactory ();
     private static final int DB_ROWS = 10000;
+
+    private static final String SELECT_WORLD = "select * from world where id = ?";
+    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
+    private static final String SELECT_FORTUNES = "select * from fortune";
+
     private static final String MESSAGE = "Hello, World!";
     private static final String CONTENT_TYPE_TEXT = "text/plain";
+    private static final String CONTENT_TYPE_JSON = "application/json";
+    private static final String QUERIES_PARAM = "queries";
 
-    private static Properties loadConfig () {
+    private static Properties loadConfiguration () {
         try {
-            Properties config = new Properties ();
-            config.load (Class.class.getResourceAsStream ("/server.properties"));
-            return config;
+            Properties settings = new Properties ();
+            settings.load (Class.class.getResourceAsStream (SETTINGS_RESOURCE));
+            return settings;
         }
         catch (Exception ex) {
             throw new RuntimeException (ex);
@@ -46,13 +51,13 @@ final class Application {
 
     private static DataSource createSessionFactory () {
         try {
-            ComboPooledDataSource cpds = new ComboPooledDataSource ();
-            cpds.setJdbcUrl (CONFIG.getProperty ("mysql.uri"));
-            cpds.setMinPoolSize (32);
-            cpds.setMaxPoolSize (256);
-            cpds.setCheckoutTimeout (1800);
-            cpds.setMaxStatements (50);
-            return cpds;
+            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
+            dataSource.setMinPoolSize (32);
+            dataSource.setMaxPoolSize (256);
+            dataSource.setCheckoutTimeout (1800);
+            dataSource.setMaxStatements (50);
+            dataSource.setJdbcUrl (JDBC_URL);
+            return dataSource;
         }
         catch (Exception ex) {
             throw new RuntimeException (ex);
@@ -61,11 +66,11 @@ final class Application {
 
     private static int getQueries (final Request request) {
         try {
-            String param = request.queryParams ("queries");
-            if (param == null)
+            String parameter = request.queryParams (QUERIES_PARAM);
+            if (parameter == null)
                 return 1;
 
-            int queries = parseInt (param);
+            int queries = parseInt (parameter);
             if (queries < 1)
                 return 1;
             if (queries > 500)
@@ -78,51 +83,90 @@ final class Application {
         }
     }
 
-    private static Object getJson (Exchange it) {
-        it.response.type ("application/json");
+    private static Object getJson (Request it) {
+        it.response.type (CONTENT_TYPE_JSON);
         return toJson (new Message ());
     }
 
-    private static Object getDb (Exchange it) {
-        final int queries = getQueries (it.request);
+    private static Object getDb (Request it) {
+        final int queries = getQueries (it);
         final World[] worlds = new World[queries];
 
-        try (final Connection con = DS.getConnection ()) {
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
             final Random random = ThreadLocalRandom.current ();
-            PreparedStatement stmt = con.prepareStatement (QUERY);
+            final PreparedStatement stmt = con.prepareStatement (SELECT_WORLD);
 
-            for (int i = 0; i < queries; i++) {
+            for (int ii = 0; ii < queries; ii++) {
                 stmt.setInt (1, random.nextInt (DB_ROWS) + 1);
-                ResultSet rs = stmt.executeQuery ();
-                while (rs.next ()) {
-                    worlds[i] = new World ();
-                    worlds[i].id = rs.getInt (1);
-                    worlds[i].randomNumber = rs.getInt (2);
-                }
+                final ResultSet rs = stmt.executeQuery ();
+                while (rs.next ())
+                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
             }
         }
         catch (SQLException e) {
             e.printStackTrace ();
         }
 
-        it.response.type ("application/json");
-        return toJson (it.request.queryParams ("queries") == null? worlds[0] : worlds);
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
     }
 
-    private static Object getFortune (Exchange aExchange) {
-        throw new UnsupportedOperationException ();
+    private static Object getFortunes (Request it) {
+        final List<Fortune> fortunes = new ArrayList<> ();
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
+            while (rs.next ())
+                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        fortunes.add (new Fortune (42, "Additional fortune added at request time."));
+        fortunes.sort ((a, b) -> a.message.compareTo (b.message));
+
+        it.response.type ("text/html; charset=utf-8");
+        return renderMustache ("/fortunes.mustache", fortunes);
     }
 
-    private static Object getUpdate (Exchange aExchange) {
-        throw new UnsupportedOperationException ();
+    private static Object getUpdates (Request it) {
+        final int queries = getQueries (it);
+        final World[] worlds = new World[queries];
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            con.setAutoCommit (false);
+            final Random random = ThreadLocalRandom.current ();
+            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
+            final PreparedStatement stmtUpdate = con.prepareStatement (UPDATE_WORLD);
+
+            for (int ii = 0; ii < queries; ii++) {
+                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
+                final ResultSet rs = stmtSelect.executeQuery ();
+                while (rs.next ()) {
+                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
+                    stmtUpdate.setInt (1, random.nextInt (DB_ROWS) + 1);
+                    stmtUpdate.setInt (2, worlds[ii].id);
+                    stmtUpdate.addBatch ();
+                }
+            }
+            stmtUpdate.executeBatch ();
+            con.commit ();
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
     }
 
-    private static Object getPlaintext (Exchange it) {
+    private static Object getPlaintext (Request it) {
         it.response.type (CONTENT_TYPE_TEXT);
         return MESSAGE;
     }
 
-    private static void addCommonHeaders (Exchange it) {
+    private static void addCommonHeaders (Request it) {
         it.header ("Server", "Undertow/1.1.2");
         it.response.raw ().addDateHeader ("Date", new Date ().getTime ());
     }
@@ -130,12 +174,13 @@ final class Application {
     public static void main (String[] args) {
         get ("/json", Application::getJson);
         get ("/db", Application::getDb);
-        get ("/fortune", Application::getFortune);
-        get ("/update", Application::getUpdate);
+        get ("/query", Application::getDb);
+        get ("/fortune", Application::getFortunes);
+        get ("/update", Application::getUpdates);
         get ("/plaintext", Application::getPlaintext);
         after (Application::addCommonHeaders);
 
-        setIpAddress (CONFIG.getProperty ("web.host"));
-        start (parseInt (CONFIG.getProperty ("web.port")));
+        host (SETTINGS.getProperty ("web.host"));
+        start (parseInt (SETTINGS.getProperty ("web.port")));
     }
 }

+ 11 - 1
frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java

@@ -5,5 +5,15 @@ package sabina.benchmark;
  *
  * @author jam
  */
-public class Fortune {
+final class Fortune {
+    final int id;
+    final String message;
+
+    Fortune (final int id, final String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId () { return id; }
+    public String getMessage () { return message; }
 }

+ 1 - 1
frameworks/Java/sabina/src/main/java/sabina/benchmark/Message.java

@@ -1,5 +1,5 @@
 package sabina.benchmark;
 
 final class Message {
-    public final String message = "Hello, World!";
+    final String message = "Hello, World!";
 }

+ 6 - 1
frameworks/Java/sabina/src/main/java/sabina/benchmark/World.java

@@ -1,5 +1,10 @@
 package sabina.benchmark;
 
 final class World {
-    public int id, randomNumber;
+    final int id, randomNumber;
+
+    World (final int id, final int randomNumber) {
+        this.id = id;
+        this.randomNumber = randomNumber;
+    }
 }

+ 4 - 4
frameworks/Java/sabina/src/main/resources/sabina/view/fortunes.ftl → frameworks/Java/sabina/src/main/resources/fortunes.mustache

@@ -10,10 +10,10 @@
         <th>message</th>
     </tr>
     {{#.}}
-      <tr>
-          <td>{{id}}</td>
-          <td>{{message}}</td>
-      </tr>
+    <tr>
+        <td>{{id}}</td>
+        <td>{{message}}</td>
+    </tr>
     {{/.}}
 </table>
 </body>

+ 0 - 20
frameworks/Java/sabina/src/main/resources/sabina/view/fortunes.html

@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Fortunes</title>
-</head>
-<body>
-<table>
-    <tr>
-        <th>id</th>
-        <th>message</th>
-    </tr>
-    <#list fortunes as fortune>
-      <tr>
-          <td>${fortune.id}</td>
-          <td>${fortune.message!null}</td>
-      </tr>
-    </#list>
-</table>
-</body>
-</html>

+ 1 - 1
frameworks/Java/sabina/src/main/resources/server.properties

@@ -1,4 +1,4 @@
-web.port = ${web.port}
+web.port = 5050
 web.host = 0.0.0.0
 
 mongodb.uri = ${db.host}:27017

+ 75 - 41
frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java

@@ -1,14 +1,15 @@
 package sabina.benchmark;
 
 import static org.apache.http.client.fluent.Request.Get;
-import static org.junit.Assert.*;
+import static org.testng.AssertJUnit.*;
 import static sabina.benchmark.Application.main;
 import static sabina.Sabina.stop;
-import static sun.misc.IOUtils.readFully;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.List;
 import java.util.Map;
+import java.util.Scanner;
 
 import com.google.gson.Gson;
 import org.apache.http.HttpResponse;
@@ -16,15 +17,18 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
[email protected]
 public final class ApplicationTest {
-    private static final String ENDPOINT = "http://localhost:8080";
+    private static final String ENDPOINT = "http://localhost:5050";
     private static final Gson GSON = new Gson ();
 
-    @BeforeClass public static void setup () {
+    @org.testng.annotations.BeforeClass @BeforeClass
+    public static void setup () {
         main (null);
     }
 
-    @AfterClass public static void close () {
+    @org.testng.annotations.AfterClass @AfterClass
+    public static void close () {
         stop ();
     }
 
@@ -54,74 +58,104 @@ public final class ApplicationTest {
     }
 
     @Test public void empty_query_parameter () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db?queries");
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        checkResultItems (content, 1);
+        checkDbRequest ("/query?queries", 1);
     }
 
     @Test public void text_query_parameter () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db?queries=text");
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        checkResultItems (content, 1);
+        checkDbRequest ("/query?queries=text", 1);
     }
 
     @Test public void zero_queries () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db?queries=0");
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        checkResultItems (content, 1);
+        checkDbRequest ("/query?queries=0", 1);
     }
 
     @Test public void one_thousand_queries () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db?queries=1000");
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        checkResultItems (content, 500);
+        checkDbRequest ("/query?queries=1000", 500);
     }
 
     @Test public void one_query () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db?queries=1");
+        checkDbRequest ("/query?queries=1", 1);
+    }
+
+    @Test public void ten_queries () throws IOException {
+        checkDbRequest ("/query?queries=10", 10);
+    }
+
+    @Test public void five_hundred_queries () throws IOException {
+        checkDbRequest ("/query?queries=500", 500);
+    }
+
+    @Test public void fortunes () throws IOException {
+        HttpResponse response = get (ENDPOINT + "/fortune");
         String content = getContent (response);
+        String contentType = response.getEntity ().getContentType ().getValue ();
 
-        checkResponse (response, content, "application/json");
-        checkResultItems (content, 1);
+        assertTrue (response.getFirstHeader ("Server") != null);
+        assertTrue (response.getFirstHeader ("Date") != null);
+        assertTrue (content.contains ("&lt;script&gt;alert(&quot;This should not be displayed"));
+        assertTrue (content.contains ("フレームワークのベンチマーク"));
+        assertEquals ("text/html; charset=utf-8", contentType);
     }
 
-    @Test public void ten_query () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db?queries=10");
+    @Test public void no_updates_parameter () throws IOException {
+        HttpResponse response = get (ENDPOINT + "/update");
         String content = getContent (response);
 
         checkResponse (response, content, "application/json");
-        checkResultItems (content, 10);
+        Map<?, ?> resultsMap = GSON.fromJson (content, Map.class);
+        assertTrue (resultsMap.containsKey ("id") && resultsMap.containsKey ("randomNumber"));
     }
 
-    @Test public void five_hundred_queries () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db?queries=500");
+    @Test public void empty_updates_parameter () throws IOException {
+        checkDbRequest ("/update?queries", 1);
+    }
+
+    @Test public void text_updates_parameter () throws IOException {
+        checkDbRequest ("/update?queries=text", 1);
+    }
+
+    @Test public void zero_updates () throws IOException {
+        checkDbRequest ("/update?queries=0", 1);
+    }
+
+    @Test public void one_thousand_updates () throws IOException {
+        checkDbRequest ("/update?queries=1000", 500);
+    }
+
+    @Test public void one_update () throws IOException {
+        checkDbRequest ("/update?queries=1", 1);
+    }
+
+    @Test public void ten_updates () throws IOException {
+        checkDbRequest ("/update?queries=10", 10);
+    }
+
+    @Test public void five_hundred_updates () throws IOException {
+        checkDbRequest ("/update?queries=500", 500);
+    }
+
+    private void checkDbRequest (String path, int itemsCount) throws IOException {
+        HttpResponse response = get (ENDPOINT + path);
         String content = getContent (response);
 
         checkResponse (response, content, "application/json");
-        checkResultItems (content, 500);
+        checkResultItems (content, itemsCount);
     }
 
     private HttpResponse get (String uri) throws IOException {
         return Get (uri).execute ().returnResponse ();
     }
 
-    private String getContent (HttpResponse aResponse) throws IOException {
-        return new String (readFully (aResponse.getEntity ().getContent (), -1, true));
+    private String getContent (HttpResponse response) throws IOException {
+        InputStream in = response.getEntity ().getContent ();
+        return new Scanner (in).useDelimiter ("\\A").next ();
     }
 
-    private void checkResponse (HttpResponse aRes, String aContent, String contentType) {
-        assertTrue (aRes.getFirstHeader ("Server") != null);
-        assertTrue (aRes.getFirstHeader ("Date") != null);
-        assertEquals (aContent.length (), aRes.getEntity ().getContentLength ());
-        assertEquals (contentType, aRes.getEntity ().getContentType ().getValue ());
+    private void checkResponse (HttpResponse res, String content, String contentType) {
+        assertTrue (res.getFirstHeader ("Server") != null);
+        assertTrue (res.getFirstHeader ("Date") != null);
+        assertEquals (content.length (), res.getEntity ().getContentLength ());
+        assertEquals (contentType, res.getEntity ().getContentType ().getValue ());
     }
 
     private void checkResultItems (String result, int size) {