Merge pull request #385 from CartoDB/remove-state-dependant-test

Fix acceptance test
This commit is contained in:
Raul Ochoa 2016-11-25 10:52:52 +01:00 committed by GitHub
commit 28dec57dd2
23 changed files with 1393 additions and 3136 deletions

View File

@ -631,7 +631,7 @@ it('SELECT INTO with paging ', function(done){
}), }),
headers: {host: 'vizzuality.cartodb.com'}, headers: {host: 'vizzuality.cartodb.com'},
method: 'GET' method: 'GET'
},{}, function(err, res) { next(null, res); }); }, {}, function(err, res) { next(null, res); });
}, },
function check_drop(err, res) { function check_drop(err, res) {
assert.ifError(err); assert.ifError(err);

View File

@ -124,7 +124,7 @@ describe('batch multiquery', function() {
] ]
]; ];
var jobsQueue = queue(2); var jobsQueue = queue(1);
jobs.forEach(function(job) { jobs.forEach(function(job) {
jobsQueue.defer(function(payload, done) { jobsQueue.defer(function(payload, done) {
@ -165,7 +165,7 @@ describe('batch multiquery', function() {
]; ];
var expectedStatus = [JobStatus.FAILED, JobStatus.DONE]; var expectedStatus = [JobStatus.FAILED, JobStatus.DONE];
var jobsQueue = queue(2); var jobsQueue = queue(1);
jobs.forEach(function(job) { jobs.forEach(function(job) {
jobsQueue.defer(function(payload, done) { jobsQueue.defer(function(payload, done) {
@ -207,7 +207,7 @@ describe('batch multiquery', function() {
]; ];
var expectedStatus = [JobStatus.DONE, JobStatus.FAILED]; var expectedStatus = [JobStatus.DONE, JobStatus.FAILED];
var jobsQueue = queue(2); var jobsQueue = queue(1);
jobs.forEach(function(job) { jobs.forEach(function(job) {
jobsQueue.defer(function(payload, done) { jobsQueue.defer(function(payload, done) {

View File

@ -76,16 +76,9 @@ describe('batch happy cases', function() {
'select * from private_table', 'select * from private_table',
'select * from private_table', 'select * from private_table',
'select * from private_table', 'select * from private_table',
'select * from private_table',
'select * from private_table',
'select * from private_table',
'select * from private_table',
'select * from private_table',
'select * from private_table',
'select * from private_table'
]; ];
var jobsQueue = queue(4); var jobsQueue = queue(1);
jobs.forEach(function(job) { jobs.forEach(function(job) {
jobsQueue.defer(function(payload, done) { jobsQueue.defer(function(payload, done) {
@ -115,19 +108,12 @@ describe('batch happy cases', function() {
var self = this; var self = this;
var jobs = [ var jobs = [
'select * from unexistent_table',
'select * from unexistent_table',
'select * from unexistent_table',
'select * from unexistent_table',
'select * from unexistent_table',
'select * from unexistent_table',
'select * from unexistent_table',
'select * from unexistent_table', 'select * from unexistent_table',
'select * from unexistent_table', 'select * from unexistent_table',
'select * from unexistent_table' 'select * from unexistent_table'
]; ];
var jobsQueue = queue(4); var jobsQueue = queue(1);
jobs.forEach(function(job) { jobs.forEach(function(job) {
jobsQueue.defer(function(payload, done) { jobsQueue.defer(function(payload, done) {

View File

@ -2,6 +2,7 @@ require('../../helper');
var assert = require('../../support/assert'); var assert = require('../../support/assert');
var BatchTestClient = require('../../support/batch-test-client'); var BatchTestClient = require('../../support/batch-test-client');
var JobStatus = require('../../../batch/job_status');
describe('batch work in progress endpoint happy cases', function() { describe('batch work in progress endpoint happy cases', function() {
@ -22,7 +23,7 @@ describe('batch work in progress endpoint happy cases', function() {
it('should get a list of work in progress jobs group by user', function (done) { it('should get a list of work in progress jobs group by user', function (done) {
var self = this; var self = this;
var user = 'vizzuality'; var user = 'vizzuality';
var queries = ['select pg_sleep(0.5)']; var queries = ['select pg_sleep(3)'];
var payload = jobPayload(queries); var payload = jobPayload(queries);
self.batchTestClient.createJob(payload, function(err, jobResult) { self.batchTestClient.createJob(payload, function(err, jobResult) {
@ -30,48 +31,67 @@ describe('batch work in progress endpoint happy cases', function() {
return done(err); return done(err);
} }
setTimeout(function () { jobResult.getStatus(JobStatus.RUNNING, function (err) {
if (err) {
return done(err);
}
self.batchTestClient.getWorkInProgressJobs(function (err, workInProgressJobs) { self.batchTestClient.getWorkInProgressJobs(function (err, workInProgressJobs) {
if (err) { if (err) {
return done(err); return done(err);
} }
if (!workInProgressJobs[user]) {
return done(new Error('User should be in work-in-progress list'));
}
assert.ok(Array.isArray(workInProgressJobs[user])); assert.ok(Array.isArray(workInProgressJobs[user]));
assert.ok(workInProgressJobs[user].length >= 1); assert.ok(workInProgressJobs[user].length >= 1);
for (var i = 0; i < workInProgressJobs[user].length; i++) { for (var i = 0; i < workInProgressJobs[user].length; i++) {
if (workInProgressJobs[user][i] === jobResult.job.job_id) { if (workInProgressJobs[user][i] === jobResult.job.job_id) {
return done(); return jobResult.cancel(done);
} }
} }
return done(new Error('Job should not be in work-in-progress list'));
}); });
}, 100); });
}); });
}); });
it('should get a list of work in progress jobs w/o the finished ones', function (done) { it('should get a list of work in progress jobs w/o the finished ones', function (done) {
var self = this; var self = this;
var user = 'vizzuality'; var user = 'vizzuality';
var queries = ['select pg_sleep(0.1)']; var queries = ['select pg_sleep(0)'];
var payload = jobPayload(queries); var payload = jobPayload(queries);
self.batchTestClient.createJob(payload, function(err, jobResult) { self.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) { if (err) {
return done(err); return done(err);
} }
setTimeout(function () {
jobResult.getStatus(function (err) {
if (err) {
return done(err);
}
self.batchTestClient.getWorkInProgressJobs(function (err, workInProgressJobs) { self.batchTestClient.getWorkInProgressJobs(function (err, workInProgressJobs) {
if (err) { if (err) {
return done(err); return done(err);
} }
assert.ok(Array.isArray(workInProgressJobs[user]));
assert.ok(workInProgressJobs[user].length >= 1); if (workInProgressJobs[user]) {
for (var i = 0; i < workInProgressJobs[user].length; i++) { assert.ok(Array.isArray(workInProgressJobs[user]));
if (workInProgressJobs[user][i] === jobResult.job.job_id) { assert.ok(workInProgressJobs[user].length >= 1);
return done(new Error('Job should not be in work-in-progress list')); for (var i = 0; i < workInProgressJobs[user].length; i++) {
if (workInProgressJobs[user][i] === jobResult.job.job_id) {
return done(new Error('Job should not be in work-in-progress list'));
}
} }
} }
return done(); done();
}); });
}, 200); });
}); });
}); });
}); });

View File

@ -1,219 +1,124 @@
require('../../helper'); require('../../helper');
var assert = require('../../support/assert'); var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils'); var TestClient = require('../../support/test-client');
var server = require('../../../app/server')(); var JobStatus = require('../../../batch/job_status');
var querystring = require('qs'); var BatchTestClient = require('../../support/batch-test-client');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch/index');
var jobStatus = require('../../../batch/job_status');
describe('Batch API callback templates', function () { describe('Batch API callback templates', function () {
before(function () {
function createJob(jobDefinition, callback) { this.batchTestClient = new BatchTestClient();
assert.response(server, { this.testClient = new TestClient();
url: '/api/v2/sql/job?api_key=1234',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
host: 'vizzuality.cartodb.com'
},
method: 'POST',
data: querystring.stringify(jobDefinition)
}, {
status: 201
}, function (err, res) {
if (err) {
return callback(err);
}
return callback(null, JSON.parse(res.body));
});
}
function getJobStatus(jobId, callback) {
assert.response(server, {
url: '/api/v2/sql/job/' + jobId + '?api_key=1234&',
headers: {
host: 'vizzuality.cartodb.com'
},
method: 'GET'
}, {
status: 200
}, function (err, res) {
if (err) {
return callback(err);
}
return callback(null, JSON.parse(res.body));
});
}
function getQueryResult(query, callback) {
assert.response(server, {
url: '/api/v2/sql?' + querystring.stringify({q: query, api_key: 1234}),
headers: {
host: 'vizzuality.cartodb.com'
},
method: 'GET'
}, {
status: 200
}, function (err, res) {
if (err) {
return callback(err);
}
return callback(null, JSON.parse(res.body));
});
}
function validateExpectedResponse(actual, expected) {
actual.query.forEach(function(actualQuery, index) {
var expectedQuery = expected.query[index];
assert.ok(expectedQuery);
Object.keys(expectedQuery).forEach(function(expectedKey) {
assert.equal(
actualQuery[expectedKey],
expectedQuery[expectedKey],
'Expected value for key "' + expectedKey + '" does not match: ' + actualQuery[expectedKey] + ' ==' +
expectedQuery[expectedKey] + ' at query index=' + index + '. Full response: ' +
JSON.stringify(actual, null, 4)
);
});
var propsToCheckDate = ['started_at', 'ended_at'];
propsToCheckDate.forEach(function(propToCheckDate) {
if (actualQuery.hasOwnProperty(propToCheckDate)) {
assert.ok(new Date(actualQuery[propToCheckDate]));
}
});
});
assert.equal(actual.onsuccess, expected.onsuccess);
assert.equal(actual.onerror, expected.onerror);
}
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
}); });
after(function (done) { after(function (done) {
batch.stop(); this.batchTestClient.drain(done);
redisUtils.clean('batch:*', done);
}); });
describe.skip('should use templates for error_message and job_id onerror callback', function () { it('should use templates for error_message and job_id onerror callback' +
var jobResponse; ' and keep the original templated query but use the error message', function (done) {
before(function(done) { var self = this;
getQueryResult('create table test_batch_errors (job_id text, error_message text)', function(err) { var payload = {
"query": {
"query": [
{
"query": "SELECT * FROM invalid_table",
"onerror": "INSERT INTO test_batch_errors " +
"values ('<%= job_id %>', '<%= error_message %>')"
}
]
}
};
var expectedQuery = {
query: [
{
"query": "SELECT * FROM invalid_table",
"onerror": "INSERT INTO test_batch_errors values ('<%= job_id %>', '<%= error_message %>')",
status: 'failed',
fallback_status: 'done'
}
]
};
self.testClient.getResult(
'create table test_batch_errors (job_id text, error_message text)', function (err) {
if (err) {
return done(err);
}
self.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) { if (err) {
return done(err); return done(err);
} }
createJob({
"query": { jobResult.getStatus(JobStatus.FAILED, function (err, job) {
"query": [ if (err) {
{ return done(err);
"query": "SELECT * FROM invalid_table",
"onerror": "INSERT INTO test_batch_errors " +
"values ('<%= job_id %>', '<%= error_message %>')"
}
]
} }
}, function(err, job) { jobResult.validateExpectedResponse(expectedQuery);
jobResponse = job; self.testClient.getResult('select * from test_batch_errors', function(err, rows) {
return done(err); if (err) {
return done(err);
}
assert.equal(rows[0].job_id, job.job_id);
assert.equal(rows[0].error_message, 'relation "invalid_table" does not exist');
self.testClient.getResult('drop table test_batch_errors', done);
});
}); });
}); });
}); });
it('should keep the original templated query but use the error message', function (done) {
var expectedQuery = {
query: [
{
"query": "SELECT * FROM invalid_table",
"onerror": "INSERT INTO test_batch_errors values ('<%= job_id %>', '<%= error_message %>')",
status: 'failed',
fallback_status: 'done'
}
]
};
var interval = setInterval(function () {
getJobStatus(jobResponse.job_id, function(err, job) {
if (job.status === jobStatus.FAILED) {
clearInterval(interval);
validateExpectedResponse(job.query, expectedQuery);
getQueryResult('select * from test_batch_errors', function(err, result) {
if (err) {
return done(err);
}
assert.equal(result.rows[0].job_id, jobResponse.job_id);
assert.equal(result.rows[0].error_message, 'relation "invalid_table" does not exist');
getQueryResult('drop table test_batch_errors', done);
});
} else if (job.status === jobStatus.DONE || job.status === jobStatus.CANCELLED) {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be "failed"'));
}
});
}, 50);
});
}); });
describe('should use template for job_id onsuccess callback', function () { it('should use template for job_id onsuccess callback ' +
var jobResponse; 'and keep the original templated query but use the job_id', function (done) {
before(function(done) { var self = this;
createJob({ var payload = {
"query": { "query": {
"query": [ "query": [
{
query: "create table batch_jobs (job_id text)"
},
{
"query": "SELECT 1",
"onsuccess": "INSERT INTO batch_jobs values ('<%= job_id %>')"
}
]
}
}, function(err, job) {
jobResponse = job;
return done(err);
});
});
it('should keep the original templated query but use the job_id', function (done) {
var expectedQuery = {
query: [
{ {
query: "create table batch_jobs (job_id text)", query: "create table batch_jobs (job_id text)"
status: 'done'
}, },
{ {
query: "SELECT 1", "query": "SELECT 1",
onsuccess: "INSERT INTO batch_jobs values ('<%= job_id %>')", "onsuccess": "INSERT INTO batch_jobs values ('<%= job_id %>')"
status: 'done',
fallback_status: 'done'
} }
] ]
}; }
};
var expectedQuery = {
query: [
{
query: "create table batch_jobs (job_id text)",
status: 'done'
},
{
query: "SELECT 1",
onsuccess: "INSERT INTO batch_jobs values ('<%= job_id %>')",
status: 'done',
fallback_status: 'done'
}
]
};
var interval = setInterval(function () { self.batchTestClient.createJob(payload, function(err, jobResult) {
getJobStatus(jobResponse.job_id, function(err, job) { if (err) {
if (job.status === jobStatus.DONE) { return done(err);
clearInterval(interval); }
validateExpectedResponse(job.query, expectedQuery); jobResult.getStatus(function (err, job) {
getQueryResult('select * from batch_jobs', function(err, result) { if (err) {
if (err) { return done(err);
return done(err); }
}
assert.equal(result.rows[0].job_id, jobResponse.job_id); jobResult.validateExpectedResponse(expectedQuery);
getQueryResult('drop table batch_jobs', done); self.testClient.getResult('select * from batch_jobs', function(err, rows) {
}); if (err) {
} else if (job.status === jobStatus.FAILED || job.status === jobStatus.CANCELLED) { return done(err);
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be "done"'));
} }
assert.equal(rows[0].job_id, job.job_id);
self.testClient.getResult('drop table batch_jobs', done);
}); });
}, 50); });
}); });
}); });
}); });

File diff suppressed because it is too large Load Diff

View File

@ -157,7 +157,6 @@ describe('job module', function() {
status: 400 status: 400
}, function(err, res) { }, function(err, res) {
var error = JSON.parse(res.body); var error = JSON.parse(res.body);
console.log(error);
assert.deepEqual(error , { assert.deepEqual(error , {
error: ['Job with id irrelevantJob not found'] error: ['Job with id irrelevantJob not found']
}); });

View File

@ -1,195 +1,113 @@
require('../../helper'); require('../../helper');
var assert = require('../../support/assert'); var BatchTestClient = require('../../support/batch-test-client');
var redisUtils = require('../../support/redis_utils'); var JobStatus = require('../../../batch/job_status');
var server = require('../../../app/server')();
var querystring = require('qs');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch');
var jobStatus = require('../../../batch/job_status');
describe('Batch API query timing', function () { describe('Batch API query timing', function () {
before(function() {
function createJob(jobDefinition, callback) { this.batchTestClient = new BatchTestClient();
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
host: 'vizzuality.cartodb.com'
},
method: 'POST',
data: querystring.stringify(jobDefinition)
}, {
status: 201
}, function (err, res) {
if (err) {
return callback(err);
}
return callback(null, JSON.parse(res.body));
});
}
function getJobStatus(jobId, callback) {
assert.response(server, {
url: '/api/v2/sql/job/' + jobId + '?api_key=1234&',
headers: {
host: 'vizzuality.cartodb.com'
},
method: 'GET'
}, {
status: 200
}, function (err, res) {
if (err) {
return callback(err);
}
return callback(null, JSON.parse(res.body));
});
}
function validateExpectedResponse(actual, expected) {
actual.query.forEach(function(actualQuery, index) {
var expectedQuery = expected.query[index];
assert.ok(expectedQuery);
Object.keys(expectedQuery).forEach(function(expectedKey) {
assert.equal(actualQuery[expectedKey], expectedQuery[expectedKey]);
});
var propsToCheckDate = ['started_at', 'ended_at'];
propsToCheckDate.forEach(function(propToCheckDate) {
if (actualQuery.hasOwnProperty(propToCheckDate)) {
assert.ok(new Date(actualQuery[propToCheckDate]));
}
});
});
assert.equal(actual.onsuccess, expected.onsuccess);
assert.equal(actual.onerror, expected.onerror);
}
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
}); });
after(function (done) { after(function(done) {
batch.stop(); this.batchTestClient.drain(done);
redisUtils.clean('batch:*', done);
}); });
describe('should report start and end time for each query with fallback queries', function () { it('should report start and end time for each query with fallback queries' +
var jobResponse; 'and expose started_at and ended_at for all queries with fallback mechanism', function (done) {
before(function(done) { var expectedQuery = {
createJob({ query: [{
"query": { query: 'SELECT * FROM untitle_table_4 limit 1',
"query": [ onerror: 'SELECT * FROM untitle_table_4 limit 2',
{ status: 'done',
"query": "SELECT * FROM untitle_table_4 limit 1", fallback_status: 'skipped'
"onerror": "SELECT * FROM untitle_table_4 limit 2" }, {
}, query: 'SELECT * FROM untitle_table_4 limit 3',
{ onerror: 'SELECT * FROM untitle_table_4 limit 4',
"query": "SELECT * FROM untitle_table_4 limit 3", status: 'done',
"onerror": "SELECT * FROM untitle_table_4 limit 4" fallback_status: 'skipped'
} }],
], onerror: 'SELECT * FROM untitle_table_4 limit 5'
"onerror": "SELECT * FROM untitle_table_4 limit 5" };
}
}, function(err, job) {
jobResponse = job;
return done(err);
});
});
it('should expose started_at and ended_at for all queries with fallback mechanism', function (done) { var payload = {
var expectedQuery = { "query": {
query: [{ "query": [
query: 'SELECT * FROM untitle_table_4 limit 1', {
onerror: 'SELECT * FROM untitle_table_4 limit 2', "query": "SELECT * FROM untitle_table_4 limit 1",
status: 'done', "onerror": "SELECT * FROM untitle_table_4 limit 2"
fallback_status: 'skipped' },
}, { {
query: 'SELECT * FROM untitle_table_4 limit 3', "query": "SELECT * FROM untitle_table_4 limit 3",
onerror: 'SELECT * FROM untitle_table_4 limit 4', "onerror": "SELECT * FROM untitle_table_4 limit 4"
status: 'done',
fallback_status: 'skipped'
}],
onerror: 'SELECT * FROM untitle_table_4 limit 5'
};
var interval = setInterval(function () {
getJobStatus(jobResponse.job_id, function(err, job) {
if (job.status === jobStatus.DONE) {
clearInterval(interval);
validateExpectedResponse(job.query, expectedQuery);
job.query.query.forEach(function(actualQuery) {
assert.ok(actualQuery.started_at);
assert.ok(actualQuery.ended_at);
});
done();
} else if (job.status === jobStatus.FAILED || job.status === jobStatus.CANCELLED) {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be "done"'));
} }
}); ],
}, 50); "onerror": "SELECT * FROM untitle_table_4 limit 5"
}
};
this.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) {
return done(err);
}
jobResult.getStatus(function (err) {
if (err) {
return done(err);
}
jobResult.validateExpectedResponse(expectedQuery);
done();
});
}); });
}); });
describe('should report start and end time for each query also for failing queries', function () {
var jobResponse;
before(function(done) {
createJob({
"query": {
"query": [
{
"query": "SELECT * FROM untitle_table_4 limit 1",
"onerror": "SELECT * FROM untitle_table_4 limit 2"
},
{
"query": "SELECT * FROM untitle_table_4 limit 3 failed",
"onerror": "SELECT * FROM untitle_table_4 limit 4"
}
],
"onerror": "SELECT * FROM untitle_table_4 limit 5"
}
}, function(err, job) {
jobResponse = job;
return done(err);
});
});
it('should expose started_at and ended_at for all queries with fallback mechanism (failed)', function (done) { it('should report start and end time for each query also for failing queries' +
var expectedQuery = { 'and expose started_at and ended_at for all queries with fallback mechanism (failed)', function (done) {
query: [{ var expectedQuery = {
query: 'SELECT * FROM untitle_table_4 limit 1', query: [{
onerror: 'SELECT * FROM untitle_table_4 limit 2', query: 'SELECT * FROM untitle_table_4 limit 1',
status: 'done', onerror: 'SELECT * FROM untitle_table_4 limit 2',
fallback_status: 'skipped' status: 'done',
}, { fallback_status: 'skipped'
query: 'SELECT * FROM untitle_table_4 limit 3 failed', }, {
onerror: 'SELECT * FROM untitle_table_4 limit 4', query: 'SELECT * FROM untitle_table_4 limit 3 failed',
status: 'failed', onerror: 'SELECT * FROM untitle_table_4 limit 4',
fallback_status: 'done' status: 'failed',
}], fallback_status: 'done'
onerror: 'SELECT * FROM untitle_table_4 limit 5' }],
}; onerror: 'SELECT * FROM untitle_table_4 limit 5'
};
var interval = setInterval(function () { var payload = {
getJobStatus(jobResponse.job_id, function(err, job) { "query": {
if (job.status === jobStatus.FAILED) { "query": [
clearInterval(interval); {
validateExpectedResponse(job.query, expectedQuery); "query": "SELECT * FROM untitle_table_4 limit 1",
job.query.query.forEach(function(actualQuery) { "onerror": "SELECT * FROM untitle_table_4 limit 2"
assert.ok(actualQuery.started_at); },
assert.ok(actualQuery.ended_at); {
}); "query": "SELECT * FROM untitle_table_4 limit 3 failed",
done(); "onerror": "SELECT * FROM untitle_table_4 limit 4"
} else if (job.status === jobStatus.DONE || job.status === jobStatus.CANCELLED) {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be "failed"'));
} }
}); ],
}, 50); "onerror": "SELECT * FROM untitle_table_4 limit 5"
}
};
this.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) {
return done(err);
}
jobResult.getStatus(JobStatus.FAILED, function (err) {
if (err) {
return done(err);
}
jobResult.validateExpectedResponse(expectedQuery);
done();
});
}); });
}); });
}); });

View File

@ -1,91 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch/index');
describe('Use case 1: cancel and modify a done job', function () {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var doneJob = {};
it('Step 1, should create a job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4"
})
}, {
status: 201
}, function (err, res) {
doneJob = JSON.parse(res.body);
done();
});
});
it('Step 2, job should be done', function (done) {
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + doneJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function (err, res) {
var job = JSON.parse(res.body);
if (job.status === "done") {
clearInterval(interval);
done();
} else if (job.status === "failed" || job.status === "cancelled") {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be done'));
} else {
console.log('Job ' + job.job_id + ' is ' + job.status + ', expecting to be done');
}
});
}, 50);
});
it('Step 3, cancel a done job should give an error', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + doneJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 400
}, function(err, res) {
var errors = JSON.parse(res.body);
assert.equal(errors.error[0], "Cannot set status from done to cancelled");
done();
});
});
});

View File

@ -1,95 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch/index');
describe('Use case 10: cancel and modify a done multiquery job', function () {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var doneJob = {};
it('Step 1, should create a multiquery job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: [
"SELECT * FROM untitle_table_4",
"SELECT * FROM untitle_table_4",
"SELECT * FROM untitle_table_4"
]
})
}, {
status: 201
}, function (err, res) {
doneJob = JSON.parse(res.body);
done();
});
});
it('Step 2, multiquery job should be done', function (done) {
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + doneJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function (err, res) {
var job = JSON.parse(res.body);
if (job.status === "done") {
clearInterval(interval);
done();
} else if (job.status === "failed" || job.status === "cancelled") {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be done'));
} else {
console.log('Job ' + job.job_id + ' is ' + job.status + ', expecting to be done');
}
});
}, 50);
});
it('Step 3, cancel a done multiquery job should give an error', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + doneJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 400
}, function(err, res) {
var errors = JSON.parse(res.body);
assert.equal(errors.error[0], "Cannot set status from done to cancelled");
done();
});
});
});

View File

@ -1,121 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch/index');
describe('Use case 2: cancel a running job', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var runningJob = {};
var cancelledJob = {};
it('Step 1, should create a new job', function (done){
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4; select pg_sleep(3)"
})
}, {
status: 201
}, function(err, res) {
runningJob = JSON.parse(res.body);
done();
});
});
it('Step 2, job should be running', function (done){
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "running") {
clearInterval(interval);
done();
} else if (job.status === "done" || job.status === "failed" || job.status === "cancelled") {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be running'));
}
});
}, 50);
});
it('Step 3, cancel a job', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
cancelledJob = JSON.parse(res.body);
assert.equal(cancelledJob.status, "cancelled");
done();
});
});
it('Step 4, job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "cancelled") {
done();
} else {
done(new Error('Job status is not cancelled, ' + job.status));
}
});
});
it('Step 5, cancel a cancelled should give an error', function (done) {
assert.response(server, {
url: '/api/v2/sql/job/' + cancelledJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 400
}, function(err, res) {
var errors = JSON.parse(res.body);
assert.equal(errors.error[0], "Cannot set status from cancelled to cancelled");
done();
});
});
});

View File

@ -1,121 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch/index');
describe('Use case 3: cancel a pending job', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var runningJob = {};
var pendingJob = {};
it('Step 1, should create a job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4; select pg_sleep(3)"
})
}, {
status: 201
}, function (err, res) {
runningJob = JSON.parse(res.body);
done();
});
});
it('Step 2, should create a another job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4"
})
}, {
status: 201
}, function(err, res) {
pendingJob = JSON.parse(res.body);
done();
});
});
it('Step 3, job should be pending', function (done){
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + pendingJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "pending") {
clearInterval(interval);
done();
} else {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be pending'));
}
});
}, 50);
});
it('Step 4, cancel a pending job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + pendingJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
var jobGot = JSON.parse(res.body);
assert.equal(jobGot.job_id, pendingJob.job_id);
assert.equal(jobGot.status, "cancelled");
done();
});
});
it('Step 5, running job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
var cancelledJob = JSON.parse(res.body);
assert.equal(cancelledJob.status, "cancelled");
done();
});
});
});

View File

@ -1,106 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch');
describe('Use case 4: modify a pending job', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var runningJob = {};
var pendingJob = {};
it('Step 1, should create a job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4; select pg_sleep(3)"
})
}, {
status: 201
}, function(err, res) {
runningJob = JSON.parse(res.body);
done();
});
});
it('Step 2, should create another job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4"
})
}, {
status: 201
}, function(err, res) {
pendingJob = JSON.parse(res.body);
done();
});
});
it('Step 3, job should be pending', function (done){
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + pendingJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "pending") {
clearInterval(interval);
done();
} else {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be pending'));
}
});
}, 50);
});
it('Step 5, running job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
var cancelledJob = JSON.parse(res.body);
assert.equal(cancelledJob.status, "cancelled");
done();
});
});
});

View File

@ -1,89 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch');
describe('Use case 5: modify a running job', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var runningJob = {};
it('Step 1, should create job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4; select pg_sleep(3)"
})
}, {
status: 201
}, function (err, res) {
runningJob = JSON.parse(res.body);
done();
});
});
it('Step 2, job should be running', function (done){
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "running") {
clearInterval(interval);
done();
} else if (job.status === "done" || job.status === "failed" || job.status === "cancelled") {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be running'));
}
});
}, 50);
});
it('Step 4, running job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
var cancelledJob = JSON.parse(res.body);
assert.equal(cancelledJob.status, "cancelled");
done();
});
});
});

View File

@ -1,75 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch');
describe('Use case 6: modify a done job', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var doneJob = {};
it('Step 1, should create job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT * FROM untitle_table_4"
})
}, {
status: 201
}, function (err, res) {
doneJob = JSON.parse(res.body);
done();
});
});
it('Step 2, job should be done', function (done) {
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + doneJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "done") {
clearInterval(interval);
done();
} else if (job.status === "failed" || job.status === "cancelled") {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be done'));
}
});
}, 50);
});
});

View File

@ -1,89 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch');
describe('Use case 7: cancel a job with quotes', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var runningJob = {};
it('Step 1, should create job with quotes', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: "SELECT name FROM untitle_table_4 WHERE name = 'Hawai'; select pg_sleep(3)"
})
}, {
status: 201
}, function (err, res) {
runningJob = JSON.parse(res.body);
done();
});
});
it('Step 2, job should be running', function (done){
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "running") {
clearInterval(interval);
done();
} else if (job.status === "done" || job.status === "failed" || job.status === "cancelled") {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be running'));
}
});
}, 50);
});
it('Step 3, running job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
var cancelledJob = JSON.parse(res.body);
assert.equal(cancelledJob.status, "cancelled");
done();
});
});
});

View File

@ -1,125 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch');
describe('Use case 8: cancel a running multiquery job', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var runningJob = {};
var cancelledJob = {};
it('Step 1, should create a new multiquery job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: [
"select pg_sleep(1)",
"select pg_sleep(1)",
"select pg_sleep(1)"
]
})
}, {
status: 201
}, function(err, res) {
runningJob = JSON.parse(res.body);
done();
});
});
it('Step 2, multiquery job should be running', function (done){
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "running") {
clearInterval(interval);
done();
} else if (job.status === "done" || job.status === "failed" || job.status === "cancelled") {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be running'));
}
});
}, 50);
});
it('Step 3, cancel a multiquery job', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
cancelledJob = JSON.parse(res.body);
assert.equal(cancelledJob.status, "cancelled");
done();
});
});
it('Step 4, multiquery job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "cancelled") {
done();
} else {
done(new Error('Job status is not cancelled, ' + job.status));
}
});
});
it('Step 5, cancel a cancelled multiquery job should give an error', function (done) {
assert.response(server, {
url: '/api/v2/sql/job/' + cancelledJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 400
}, function(err, res) {
var errors = JSON.parse(res.body);
assert.equal(errors.error[0], "Cannot set status from cancelled to cancelled");
done();
});
});
});

View File

@ -1,112 +0,0 @@
/**
*
* Requires the database and tables setup in config/environments/test.js to exist
* Ensure the user is present in the pgbouncer auth file too
* TODO: Add OAuth tests.
*
* To run this test, ensure that cartodb_test_user_1_db metadata exists
* in Redis for the vizzuality.cartodb.com domain
*
* SELECT 5
* HSET rails:users:vizzuality id 1
* HSET rails:users:vizzuality database_name cartodb_test_user_1_db
*
*/
require('../../helper');
var server = require('../../../app/server')();
var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils');
var querystring = require('querystring');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var batchFactory = require('../../../batch');
describe('Use case 9: modify a pending multiquery job', function() {
var batch = batchFactory(metadataBackend, redisUtils.getPool());
before(function (done) {
batch.start();
batch.on('ready', done);
});
after(function (done) {
batch.stop();
redisUtils.clean('batch:*', done);
});
var runningJob = {};
var pendingJob = {};
it('Step 1, should create a multiquery job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: [
"select pg_sleep(3)",
"SELECT * FROM untitle_table_4"
]
})
}, {
status: 201
}, function(err, res) {
runningJob = JSON.parse(res.body);
done();
});
});
it('Step 2, should create another multiquery job', function (done) {
assert.response(server, {
url: '/api/v2/sql/job?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
data: querystring.stringify({
query: [
"SELECT pg_sleep(1)",
"SELECT * FROM untitle_table_4"
]
})
}, {
status: 201
}, function(err, res) {
pendingJob = JSON.parse(res.body);
done();
});
});
it('Step 3, multiquery job should be pending', function (done){
var interval = setInterval(function () {
assert.response(server, {
url: '/api/v2/sql/job/' + pendingJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'GET'
}, {
status: 200
}, function(err, res) {
var job = JSON.parse(res.body);
if (job.status === "pending") {
clearInterval(interval);
done();
} else {
clearInterval(interval);
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be pending'));
}
});
}, 50);
});
it('Step 5, running multiquery job should be cancelled', function (done){
assert.response(server, {
url: '/api/v2/sql/job/' + runningJob.job_id + '?api_key=1234',
headers: { 'host': 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'DELETE'
}, {
status: 200
}, function(err, res) {
var cancelledJob = JSON.parse(res.body);
assert.equal(cancelledJob.status, "cancelled");
done();
});
});
});

View File

@ -2,8 +2,6 @@ require('../../helper');
var assert = require('../../support/assert'); var assert = require('../../support/assert');
var redisUtils = require('../../support/redis_utils'); var redisUtils = require('../../support/redis_utils');
var batchFactory = require('../../../batch/index');
var metadataBackend = require('cartodb-redis')({ pool: redisUtils.getPool() });
var TestClient = require('../../support/test-client'); var TestClient = require('../../support/test-client');
describe('max queued jobs', function() { describe('max queued jobs', function() {
@ -20,23 +18,8 @@ describe('max queued jobs', function() {
}); });
after(function (done) { after(function (done) {
var self = this;
global.settings.batch_max_queued_jobs = this.batch_max_queued_jobs; global.settings.batch_max_queued_jobs = this.batch_max_queued_jobs;
var batch = batchFactory(metadataBackend, redisUtils.getPool()); redisUtils.clean('batch:*', done);
batch.start();
batch.on('ready', function() {
// this is not ideal as the first job might not be committed yet
setTimeout(function() {
batch.stop(function() {
self.testClient.getResult('select count(*) from max_queued_jobs_inserts', function(err, rows) {
assert.ok(!err);
assert.equal(rows[0].count, 1);
redisUtils.clean('batch:*', done);
});
});
}, 100);
});
}); });
function createJob(server, status, callback) { function createJob(server, status, callback) {

View File

@ -0,0 +1,188 @@
require('../../helper');
var assert = require('../../support/assert');
var JobStatus = require('../../../batch/job_status');
var BatchTestClient = require('../../support/batch-test-client');
describe('Use cases', function () {
before(function() {
this.batchTestClient = new BatchTestClient();
});
after(function(done) {
this.batchTestClient.drain(done);
});
it('cancel a done job should return an error', function (done) {
var payload = {
query: "SELECT * FROM untitle_table_4"
};
this.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) {
return done(err);
}
jobResult.getStatus(JobStatus.DONE, function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.DONE);
jobResult.tryCancel(function (err, body) {
assert.equal(body.error[0], "Cannot set status from done to cancelled");
done();
});
});
});
});
it('cancel a running job', function (done) {
var payload = {
query: "SELECT * FROM untitle_table_4; select pg_sleep(3)"
};
this.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) {
return done(err);
}
jobResult.getStatus(JobStatus.RUNNING, function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.RUNNING);
jobResult.cancel(function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.CANCELLED);
jobResult.tryCancel(function (err, body) {
assert.equal(body.error[0], "Cannot set status from cancelled to cancelled");
done();
});
});
});
});
});
it('cancel a pending job', function (done) {
var self = this;
var payload1 = {
query: "SELECT * FROM untitle_table_4; select pg_sleep(3)"
};
this.batchTestClient.createJob(payload1, function(err, jobResult1) {
if (err) {
return done(err);
}
var payload2 = {
query: "SELECT * FROM untitle_table_4"
};
self.batchTestClient.createJob(payload2, function(err, jobResult2) {
if (err) {
return done(err);
}
jobResult2.getStatus(JobStatus.PENDING, function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.PENDING);
jobResult2.cancel(function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.CANCELLED);
jobResult1.cancel(function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.CANCELLED);
done();
});
});
});
});
});
});
it('cancel a job with quotes', function (done) {
var payload = {
query: "SELECT name FROM untitle_table_4 WHERE name = 'Hawai'; select pg_sleep(3)"
};
this.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) {
return done(err);
}
jobResult.getStatus(JobStatus.RUNNING, function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.RUNNING);
jobResult.cancel(function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.CANCELLED);
done();
});
});
});
});
it('cancel a running multiquery job', function (done) {
var payload = {
query: [
"select pg_sleep(1)",
"select pg_sleep(1)",
"select pg_sleep(1)"
]
};
this.batchTestClient.createJob(payload, function(err, jobResult) {
if (err) {
return done(err);
}
jobResult.getStatus(JobStatus.RUNNING, function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.RUNNING);
jobResult.cancel(function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.status, JobStatus.CANCELLED);
jobResult.tryCancel(function (err, body) {
assert.equal(body.error[0], "Cannot set status from cancelled to cancelled");
done();
});
});
});
});
});
});

View File

@ -66,6 +66,31 @@ describe('job backend', function() {
}); });
}); });
it('.get() should return a job with the given id', function (done) {
var jobData = createWadusJob();
jobBackend.create(jobData.data, function (err, jobCreated) {
if (err) {
return done(err);
}
assert.ok(jobCreated.job_id);
jobBackend.get(jobCreated.job_id, function (err, job) {
if (err) {
return done(err);
}
assert.equal(job.job_id, jobCreated.job_id);
assert.equal(job.user, jobData.data.user);
assert.equal(job.query, jobData.data.query);
assert.equal(job.host, jobData.data.host);
assert.equal(job.status, jobStatus.PENDING);
done();
});
});
});
it('.update() should update an existent job', function (done) { it('.update() should update an existent job', function (done) {
var job = createWadusJob(); var job = createWadusJob();
@ -100,6 +125,24 @@ describe('job backend', function() {
}); });
}); });
it('.save() should save a job', function (done) {
var job = createWadusJob();
jobBackend.save(job.data, function (err, jobSaved) {
if (err) {
return done(err);
}
assert.ok(jobSaved.job_id);
assert.equal(jobSaved.user, job.data.user);
assert.equal(jobSaved.query, job.data.query);
assert.equal(jobSaved.host, job.data.host);
assert.equal(jobSaved.status, jobStatus.PENDING);
done();
});
});
it('.addWorkInProgressJob() should add current job to user and host lists', function (done) { it('.addWorkInProgressJob() should add current job to user and host lists', function (done) {
var job = createWadusJob(); var job = createWadusJob();
@ -156,4 +199,21 @@ describe('job backend', function() {
}); });
}); });
it('.clearWorkInProgressJob() should remove job from work in progress list', function (done) {
var job = createWadusJob();
jobBackend.addWorkInProgressJob(job.data.user, job.data.job_id, function (err) {
if (err) {
return done(err);
}
jobBackend.clearWorkInProgressJob(job.data.user, job.data.job_id, function (err) {
if (err) {
return done(err);
}
done();
});
});
});
}); });

View File

@ -34,7 +34,7 @@ assert.response = function(server, req, res, callback) {
url: 'http://' + host + ':' + port + req.url, url: 'http://' + host + ':' + port + req.url,
method: req.method || 'GET', method: req.method || 'GET',
headers: req.headers || {}, headers: req.headers || {},
timeout: req.timeout || 0, timeout: req.timeout || 5000,
encoding: req.encoding || 'utf8' encoding: req.encoding || 'utf8'
}; };

View File

@ -18,7 +18,8 @@ function response(code) {
var RESPONSE = { var RESPONSE = {
OK: response(200), OK: response(200),
CREATED: response(201) CREATED: response(201),
BAD_REQUEST: response(400)
}; };
@ -86,7 +87,8 @@ BatchTestClient.prototype.getJobStatus = function(jobId, override, callback) {
headers: { headers: {
host: this.getHost(override) host: this.getHost(override)
}, },
method: 'GET' method: 'GET',
timeout: override.timeout
}, },
RESPONSE.OK, RESPONSE.OK,
function (err, res) { function (err, res) {
@ -127,13 +129,13 @@ BatchTestClient.prototype.cancelJob = function(jobId, override, callback) {
assert.response( assert.response(
this.server, this.server,
{ {
url: this.getUrl(jobId), url: this.getUrl(override, jobId),
headers: { headers: {
host: this.getHost(override) host: this.getHost(override)
}, },
method: 'DELETE' method: 'DELETE'
}, },
RESPONSE.OK, override.statusCode,
function (err, res) { function (err, res) {
if (err) { if (err) {
return callback(err); return callback(err);
@ -174,25 +176,105 @@ function JobResult(job, batchTestClient, override) {
this.override = override; this.override = override;
} }
JobResult.prototype.getStatus = function(callback) { JobResult.prototype.getStatus = function(requiredStatus, callback) {
if (!callback) {
callback = requiredStatus;
requiredStatus = undefined;
}
var self = this; var self = this;
var attempts = 1;
self.override.timeout = 1000;
var interval = setInterval(function () { var interval = setInterval(function () {
self.batchTestClient.getJobStatus(self.job.job_id, self.override, function (err, job) { self.batchTestClient.getJobStatus(self.job.job_id, self.override, function (err, job) {
if (err) { if (err) {
clearInterval(interval); clearInterval(interval);
return callback(err); return callback(err);
} }
attempts += 1;
if (JobStatus.isFinal(job.status)) { if (attempts > 20) {
clearInterval(interval); clearInterval(interval);
return callback(new Error('Reached maximum number of request (20) to check job status'));
}
if (hasRequiredStatus(job, requiredStatus)) {
clearInterval(interval);
self.job = job;
return callback(null, job); return callback(null, job);
} else { } else {
debug('Job %s [status=%s] waiting to be done', self.job.job_id, job.status); debug('Job %s [status=%s] waiting to be done', self.job.job_id, job.status);
} }
}); });
}, 50); }, 100);
}; };
JobResult.prototype.cancel = function(callback) { function hasRequiredStatus(job, requiredStatus) {
this.batchTestClient.cancelJob(this.job.job_id, this.override, callback); if (requiredStatus) {
return job.status === requiredStatus;
}
if (JobStatus.isFinal(job.status)) {
if (job.fallback_status !== undefined) {
if (JobStatus.isFinal(job.fallback_status) || job.fallback_status === JobStatus.SKIPPED) {
return true;
}
} else {
return true;
}
}
return false;
}
JobResult.prototype.cancel = function (callback) {
var self = this;
this.override.statusCode = response(RESPONSE.OK);
this.batchTestClient.cancelJob(this.job.job_id, this.override, function (err, job) {
if (err) {
return callback(err);
}
self.job = job;
callback(null, job);
});
};
JobResult.prototype.tryCancel = function (callback) {
var self = this;
this.override.statusCode = response();
this.batchTestClient.cancelJob(this.job.job_id, this.override, function (err, job) {
if (err) {
return callback(err);
}
self.job = job;
callback(null, job);
});
};
JobResult.prototype.validateExpectedResponse = function (expected) {
var actual = this.job.query;
actual.query.forEach(function(actualQuery, index) {
var expectedQuery = expected.query[index];
assert.ok(expectedQuery);
Object.keys(expectedQuery).forEach(function(expectedKey) {
assert.equal(
actualQuery[expectedKey],
expectedQuery[expectedKey],
'Expected value for key "' + expectedKey + '" does not match: ' + actualQuery[expectedKey] + ' ==' +
expectedQuery[expectedKey] + ' at query index=' + index + '. Full response: ' +
JSON.stringify(actual, null, 4)
);
});
var propsToCheckDate = ['started_at', 'ended_at'];
propsToCheckDate.forEach(function(propToCheckDate) {
if (actualQuery.hasOwnProperty(propToCheckDate)) {
assert.ok(new Date(actualQuery[propToCheckDate]));
}
});
});
assert.equal(actual.onsuccess, expected.onsuccess);
assert.equal(actual.onerror, expected.onerror);
}; };