<commit_before>// FLUSHALL Redis before starting
require('../support/test_helper');

var assert = require('../support/assert');
var querystring = require('querystring');
var fs = require('fs');
var redis = require('redis');
var step = require('step');
var mapnik = require('mapnik');
var Windshaft = require('../../lib/windshaft');
var ServerOptions = require('../support/server_options');
var semver = require('semver');
var http = require('http');
var testClient = require('../support/test_client');

function rmdir_recursive_sync(dirname) {
  var files = fs.readdirSync(dirname);
  for (var i=0; i<files.length; ++i) {
    var f = dirname + "/" + files[i];
    var s = fs.lstatSync(f);
    if ( s.isFile() ) {
      fs.unlinkSync(f);
    }
    else {
        rmdir_recursive_sync(f);
    }
  }
}

suite('server_gettile', function() {

    ////////////////////////////////////////////////////////////////////
    //
    // SETUP
    //
    ////////////////////////////////////////////////////////////////////

    var server = new Windshaft.Server(ServerOptions);
    server.setMaxListeners(0);
    var redis_client = redis.createClient(ServerOptions.redis.port);
    var res_serv; // resources server
    var res_serv_status = { numrequests:0 }; // status of resources server
    var res_serv_port = 8033; // FIXME: make configurable ?

    var IMAGE_EQUALS_TOLERANCE_PER_MIL = 25;

    suiteSetup(function(done) {

      // Check that we start with an empty redis db
      redis_client.keys("*", function(err, matches) {

        if ( err ) { done(err); return; }

        assert.equal(matches.length, 0,
          "redis keys present at setup time on port " +
          ServerOptions.redis.port + ":\n" + matches.join("\n"));

        // Start a server to test external resources
        res_serv = http.createServer( function(request, response) {
            ++res_serv_status.numrequests;
            var filename = __dirname + '/../fixtures/markers' + request.url;
            fs.readFile(filename, "binary", function(err, file) {
              if ( err ) {
                response.writeHead(404, {'Content-Type': 'text/plain'});
                response.write("404 Not Found\n");
              } else {
                response.writeHead(200);
                response.write(file, "binary");
              }
              response.end();
            });
        });
        res_serv.listen(res_serv_port, done);

      });

    });

    function imageCompareFn(fixture, done) {
        return function(err, res) {
            if (err) {
                return done(err);
            }
            assert.imageEqualsFile(res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
        };
    }


    ////////////////////////////////////////////////////////////////////
    //
    // GET TILE
    // --{
    ////////////////////////////////////////////////////////////////////

    test("get'ing a tile with default style should return an expected tile", function(done){
      testClient.getTile(testClient.defaultTableMapConfig('test_table'), 13, 4011, 3088,
          imageCompareFn('test_table_13_4011_3088.png', done)
      );
    });

    test.skip("response of get tile can be served by renderer cache",  function(done){
      var cb = Date.now();
      step(
        function get1 () {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check1(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function get2() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check2(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get3() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png',
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check3(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get4() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster='+(cb+1),
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check4(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function finish(err) {
          done(err);
        }
      );
    });

    test("should not choke when queries end with a semicolon",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2;'), 0, 0, 0, done);
    });

    test("should not choke when sql ends with a semicolon and some blanks",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2; \t\n'), 0, 0, 0, done);
    });

    test("should not strip quoted semicolons within an sql query",  function(done){
        testClient.getTile(
            testClient.singleLayerMapConfig("SELECT * FROM test_table where name != ';\n'"), 0, 0, 0, done
        );
    });

    test("getting two tiles with same configuration uses renderer cache",  function(done) {

        var imageFixture = './test/fixtures/test_table_13_4011_3088_styled.png';
        var tileUrl = '/13/4011/3088.png';
        var mapConfig = testClient.defaultTableMapConfig(
            'test_table',
            '#test_table{marker-fill: blue;marker-line-color: black;}'
        );

        function validateLayergroup(res) {
            assert.ok(!res.headers.hasOwnProperty('x-windshaft-cache'), "Did hit renderer cache on first time");
        }

        testClient.withLayergroup(mapConfig, validateLayergroup, function(err, requestTile, finish) {

            requestTile(tileUrl, function(err, res) {
                assert.ok(res.headers.hasOwnProperty('x-windshaft-cache'), "Did not hit renderer cache on second time");
                assert.ok(res.headers['x-windshaft-cache'] >= 0);

                assert.imageEqualsFile(res.body, imageFixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {

                    finish(function(finishErr) {
                        done(err || finishErr);
                    });
                });
            });
        });
    });

    var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:5}";
    var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:10}";

    test("get'ing a tile with url specified 2.0.0 style should return an expected tile",  function(done){
        testClient.getTile(testClient.defaultTableMapConfig('test_table', test_style_black_200, '2.0.0'),
            13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));<commit_msg>Note about the change in the test<commit_after>// FLUSHALL Redis before starting
require('../support/test_helper');

var assert = require('../support/assert');
var querystring = require('querystring');
var fs = require('fs');
var redis = require('redis');
var step = require('step');
var mapnik = require('mapnik');
var Windshaft = require('../../lib/windshaft');
var ServerOptions = require('../support/server_options');
var semver = require('semver');
var http = require('http');
var testClient = require('../support/test_client');

function rmdir_recursive_sync(dirname) {
  var files = fs.readdirSync(dirname);
  for (var i=0; i<files.length; ++i) {
    var f = dirname + "/" + files[i];
    var s = fs.lstatSync(f);
    if ( s.isFile() ) {
      fs.unlinkSync(f);
    }
    else {
        rmdir_recursive_sync(f);
    }
  }
}

suite('server_gettile', function() {

    ////////////////////////////////////////////////////////////////////
    //
    // SETUP
    //
    ////////////////////////////////////////////////////////////////////

    var server = new Windshaft.Server(ServerOptions);
    server.setMaxListeners(0);
    var redis_client = redis.createClient(ServerOptions.redis.port);
    var res_serv; // resources server
    var res_serv_status = { numrequests:0 }; // status of resources server
    var res_serv_port = 8033; // FIXME: make configurable ?

    var IMAGE_EQUALS_TOLERANCE_PER_MIL = 25;

    suiteSetup(function(done) {

      // Check that we start with an empty redis db
      redis_client.keys("*", function(err, matches) {

        if ( err ) { done(err); return; }

        assert.equal(matches.length, 0,
          "redis keys present at setup time on port " +
          ServerOptions.redis.port + ":\n" + matches.join("\n"));

        // Start a server to test external resources
        res_serv = http.createServer( function(request, response) {
            ++res_serv_status.numrequests;
            var filename = __dirname + '/../fixtures/markers' + request.url;
            fs.readFile(filename, "binary", function(err, file) {
              if ( err ) {
                response.writeHead(404, {'Content-Type': 'text/plain'});
                response.write("404 Not Found\n");
              } else {
                response.writeHead(200);
                response.write(file, "binary");
              }
              response.end();
            });
        });
        res_serv.listen(res_serv_port, done);

      });

    });

    function imageCompareFn(fixture, done) {
        return function(err, res) {
            if (err) {
                return done(err);
            }
            assert.imageEqualsFile(res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
        };
    }


    ////////////////////////////////////////////////////////////////////
    //
    // GET TILE
    // --{
    ////////////////////////////////////////////////////////////////////

    test("get'ing a tile with default style should return an expected tile", function(done){
      testClient.getTile(testClient.defaultTableMapConfig('test_table'), 13, 4011, 3088,
          imageCompareFn('test_table_13_4011_3088.png', done)
      );
    });

    test.skip("response of get tile can be served by renderer cache",  function(done){
      var cb = Date.now();
      step(
        function get1 () {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check1(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function get2() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check2(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get3() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png',
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check3(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get4() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster='+(cb+1),
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check4(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function finish(err) {
          done(err);
        }
      );
    });

    test("should not choke when queries end with a semicolon",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2;'), 0, 0, 0, done);
    });

    test("should not choke when sql ends with a semicolon and some blanks",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2; \t\n'), 0, 0, 0, done);
    });

    test("should not strip quoted semicolons within an sql query",  function(done){
        testClient.getTile(
            testClient.singleLayerMapConfig("SELECT * FROM test_table where name != ';\n'"), 0, 0, 0, done
        );
    });

    test("getting two tiles with same configuration uses renderer cache",  function(done) {

        var imageFixture = './test/fixtures/test_table_13_4011_3088_styled.png';
        var tileUrl = '/13/4011/3088.png';
        var mapConfig = testClient.defaultTableMapConfig(
            'test_table',
            '#test_table{marker-fill: blue;marker-line-color: black;}'
        );

        function validateLayergroup(res) {
            // cache is hit because we create a renderer to validate the map config
            assert.ok(!res.headers.hasOwnProperty('x-windshaft-cache'), "Did hit renderer cache on first time");
        }

        testClient.withLayergroup(mapConfig, validateLayergroup, function(err, requestTile, finish) {

            requestTile(tileUrl, function(err, res) {
                assert.ok(res.headers.hasOwnProperty('x-windshaft-cache'), "Did not hit renderer cache on second time");
                assert.ok(res.headers['x-windshaft-cache'] >= 0);

                assert.imageEqualsFile(res.body, imageFixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {

                    finish(function(finishErr) {
                        done(err || finishErr);
                    });
                });
            });
        });
    });

    var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:5}";
    var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:10}";

    test("get'ing a tile with url specified 2.0.0 style should return an expected tile",  function(done){
        testClient.getTile(testClient.defaultTableMapConfig('test_table', test_style_black_200, '2.0.0'),
            13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));
{'fraction_non_alphanumeric': 0.16356968215158924, 'fraction_numerical': 0.021026894865525673, 'mean_word_length': 1.8789371810663382, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2627568', 'n_tokens_mistral': 4980, 'n_tokens_neox': 4697, 'n_words': 1004}