Skip to content

Commit

Permalink
SNOW-502598: Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-ext-simba-lf committed Oct 20, 2023
1 parent f0abbf9 commit 903a8d8
Show file tree
Hide file tree
Showing 3 changed files with 619 additions and 0 deletions.
245 changes: 245 additions & 0 deletions test/integration/testExecuteAsync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/*
* Copyright (c) 2015-2019 Snowflake Computing Inc. All rights reserved.
*/

const assert = require('assert');
const async = require('async');
const testUtil = require('./testUtil');
const ErrorCodes = require('../../lib/errors').codes;
const QueryStatus = require('../../lib/constants/query_status').code;

describe('ExecuteAsync test', function () {
let connection;

before(function (done) {
connection = testUtil.createConnection();
testUtil.connect(connection, done);
});

after(function (done) {
testUtil.destroyConnection(connection, done);
});

it('testAsyncQueryWithPromise', function (done) {
const expectedSeconds = 3;
const sqlText = `CALL SYSTEM$WAIT(${expectedSeconds}, 'SECONDS')`;
let queryId;

async.series(
[
// Execute query in async mode
function (callback) {
connection.execute({
sqlText: sqlText,
asyncExec: true,
complete: async function (err, stmt) {
assert.ok(!err);
queryId = stmt.getQueryId();
const status = await connection.getQueryStatus(queryId);
assert.ok(connection.isStillRunning(status));
callback();
}
});
},
// Get results using query id
async function () {
const statement = await connection.getResultsFromQueryId({ queryId: queryId });

await new Promise((resolve, reject) => {
statement.streamRows()
.on('error', (err) => reject(err))
.on('data', (row) => assert.strictEqual(row['SYSTEM$WAIT'], `waited ${expectedSeconds} seconds`))
.on('end', async () => {
const status = await connection.getQueryStatus(queryId);
assert.strictEqual(QueryStatus[status], QueryStatus.SUCCESS);
resolve();
});
});
}
],
done
);
});

it('testAsyncQueryWithCallback', function (done) {
const expectedSeconds = 3;
const sqlText = `CALL SYSTEM$WAIT(${expectedSeconds}, 'SECONDS')`;
let queryId;

async.series(
[
// Execute query in async mode
function (callback) {
connection.execute({
sqlText: sqlText,
asyncExec: true,
complete: async function (err, stmt) {
assert.ok(!err);
queryId = stmt.getQueryId();
const status = await connection.getQueryStatus(queryId);
assert.ok(connection.isStillRunning(status));
callback();
}
});
},
// Get results using query id
function (callback) {
connection.getResultsFromQueryId({
queryId: queryId,
complete: async function (err, _stmt, rows) {
assert.ok(!err);
const status = await connection.getQueryStatus(queryId);
assert.strictEqual(QueryStatus[status], QueryStatus.SUCCESS);
assert.strictEqual(rows[0]['SYSTEM$WAIT'], `waited ${expectedSeconds} seconds`);
callback();
}
});
}
],
done
);
});

it('testFailedQueryThrowsError', function (done) {
const sqlText = 'select * from fakeTable';
const timeoutInMs = 1000; // 1 second
let queryId;

async.series(
[
// Execute query in async mode
function (callback) {
connection.execute({
sqlText: sqlText,
asyncExec: true,
complete: async function (err, stmt) {
assert.ok(!err);
queryId = stmt.getQueryId();
callback();
}
});
},
async function () {
// Wait for query to finish executing
while (connection.isStillRunning(await connection.getQueryStatus(queryId))) {
await new Promise((resolve) => {
setTimeout(() => resolve(), timeoutInMs);
});
}

// Check query status failed
const status = await connection.getQueryStatus(queryId);
assert.strictEqual(QueryStatus[status], QueryStatus.FAILED_WITH_ERROR);
assert.ok(connection.isAnError(status));

// Check getting the query status throws an error
try {
await connection.getQueryStatusThrowIfError(queryId);
assert.fail();
} catch (err) {
assert.ok(err);
}

// Check getting the results throws an error
try {
await connection.getResultsFromQueryId({ queryId: queryId });
assert.fail();
} catch (err) {
assert.ok(err);
}
}
],
done
);
});

it('testMixedSyncAndAsyncQueries', function (done) {
const expectedSeconds = '3';
const sqlTextForAsync = `CALL SYSTEM$WAIT(${expectedSeconds}, 'SECONDS')`;
const sqlTextForSync = 'select 1';
let queryId;

async.series(
[
// Execute query in async mode
function (callback) {
connection.execute({
sqlText: sqlTextForAsync,
asyncExec: true,
complete: async function (err, stmt) {
assert.ok(!err);
queryId = stmt.getQueryId();
const status = await connection.getQueryStatus(queryId);
assert.ok(connection.isStillRunning(status));
callback();
}
});
},
// Execute a different query in non-async mode
function (callback) {
testUtil.executeCmd(connection, sqlTextForSync, callback);
},
// Get results using query id
function (callback) {
connection.getResultsFromQueryId({
queryId: queryId,
complete: async function (err, stmt, rows) {
const status = await connection.getQueryStatus(queryId);
assert.strictEqual(QueryStatus[status], QueryStatus.SUCCESS);
assert.strictEqual(rows[0]['SYSTEM$WAIT'], `waited ${expectedSeconds} seconds`);
callback();
}
});
}
],
done
);
});

it('testGetStatusOfInvalidQueryId', async function () {
const fakeQueryId = 'fakeQueryId';

// Get the query status using an invalid query id
try {
// Should fail from invalid uuid
await connection.getQueryStatus(fakeQueryId);
assert.fail();
} catch (err) {
assert.strictEqual(err.code, ErrorCodes.ERR_GET_RESPONSE_QUERY_INVALID_UUID);
}
});

it('testGetResultsOfInvalidQueryId', async function () {
const fakeQueryId = 'fakeQueryId';

// Get the queryresults using an invalid query id
try {
// Should fail from invalid uuid
await connection.getResultsFromQueryId({ queryId: fakeQueryId });
assert.fail();
} catch (err) {
assert.strictEqual(err.code, ErrorCodes.ERR_GET_RESPONSE_QUERY_INVALID_UUID);
}
});

it('testGetStatusOfUnknownQueryId', async function () {
const unknownQueryId = '12345678-1234-4123-A123-123456789012';

// Get the query status using an unknown query id
const status = await connection.getQueryStatus(unknownQueryId);
assert.strictEqual(QueryStatus[status], QueryStatus.NO_DATA);
});

it('testGetResultsOfUnknownQueryId', async function () {
const unknownQueryId = '12345678-1234-4123-A123-123456789012';

// Get the query results using an unknown query id
try {
// Should fail from exceeding NO_DATA retry count
await connection.getResultsFromQueryId({ queryId: unknownQueryId });
assert.fail();
} catch (err) {
assert.strictEqual(err.code, ErrorCodes.ERR_GET_RESULTS_QUERY_ID_NO_DATA);
}
});
});
63 changes: 63 additions & 0 deletions test/unit/mock/mock_http_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,36 @@ MockHttpClient.prototype.request = function (request)
}, delay);
};

/**
* Issues an async request.
*
* @param {Object} request the request options.
*/
MockHttpClient.prototype.requestAsync = function (request) {
// build the request-to-output map if this is the first request
if (!this._mapRequestToOutput) {
this._mapRequestToOutput =
buildRequestToOutputMap(buildRequestOutputMappings(this._clientInfo));
}

// Closing a connection includes a requestID as a query parameter in the url
// Example: http://fake504.snowflakecomputing.com/session?delete=true&requestId=a40454c6-c3bb-4824-b0f3-bae041d9d6a2
if (request.url.includes('session?delete=true')) {
// Remove the requestID query parameter for the mock HTTP client
request.url = request.url.substring(0, request.url.indexOf('&requestId='));
}

// get the output of the specified request from the map
const requestOutput = this._mapRequestToOutput[serializeRequest(request)];

Errors.assertInternal(Util.isObject(requestOutput),
'no response available for: ' + serializeRequest(request));

const response = JSON.parse(JSON.stringify(requestOutput.response));

return response;
};

/**
* Builds a map in which the keys are requests (or rather, serialized versions
* of the requests) and the values are the outputs of the corresponding request
Expand Down Expand Up @@ -993,6 +1023,39 @@ function buildRequestOutputMappings(clientInfo)
}
}
},
{
request:
{
method: 'GET',
url: 'http://fakeaccount.snowflakecomputing.com/monitoring/queries/00000000-0000-0000-0000-000000000000',
headers:
{
'Accept': 'application/json',
'Authorization': 'Snowflake Token="SESSION_TOKEN"',
'Content-Type': 'application/json'
//"CLIENT_APP_VERSION": clientInfo.version,
//"CLIENT_APP_ID": "JavaScript"
}
},
output:
{
err: null,
response:
{
statusCode: 200,
statusMessage: "OK",
body:
{
code: null,
data: {
queries: [{ status: 'RESTARTED' }]
},
message: null,
success: true
}
}
}
},
{
request:
{
Expand Down
Loading

0 comments on commit 903a8d8

Please sign in to comment.