Skip to content

Commit

Permalink
Update tests
Browse files Browse the repository at this point in the history
Signed-off-by: Levko Kravets <[email protected]>
  • Loading branch information
kravets-levko committed Jul 27, 2023
1 parent 39eb9c9 commit 45df1e2
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 43 deletions.
157 changes: 120 additions & 37 deletions tests/unit/DBSQLClient.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,17 @@ const PlainHttpAuthentication = require('../../dist/connection/auth/PlainHttpAut
const DatabricksOAuth = require('../../dist/connection/auth/DatabricksOAuth').default;
const { AWSOAuthManager, AzureOAuthManager } = require('../../dist/connection/auth/DatabricksOAuth/OAuthManager');

const ConnectionProviderMock = (connection) => ({
connect(options, auth) {
this.options = options;
this.auth = auth;

return Promise.resolve({
getConnection() {
return (
connection || {
on: () => {},
}
);
},
});
},
});
const HttpConnectionModule = require('../../dist/connection/connections/HttpConnection');

class AuthProviderMock {
constructor() {
this.authResult = {};
}

authenticate() {
return Promise.resolve(this.authResult);
}
}

describe('DBSQLClient.connect', () => {
const options = {
Expand All @@ -49,30 +44,18 @@ describe('DBSQLClient.connect', () => {
expect(connectionOptions.options.path).to.equal(path);
});

// client.connect() now does not actually attempt any network operations. for http it never did it
// even before, but this test was not quite correct even then. it needs to be updated
it.skip('should handle network errors', (cb) => {
it('should initialize connection state', async () => {
const client = new DBSQLClient();
client.thrift = {
createClient() {},
};
const connectionProvider = ConnectionProviderMock({
on(name, handler) {
handler(new Error('network error'));
},
});

sinon.stub(client, 'createConnection').returns(Promise.resolve(connectionProvider));
expect(client.client).to.be.null;
expect(client.authProvider).to.be.null;
expect(client.connectionOptions).to.be.null;

client.on('error', (error) => {
expect(error.message).to.be.eq('network error');
cb();
});
await client.connect(options);

client.connectionProvider = connectionProvider;
client.connect(options).catch((error) => {
cb(error);
});
expect(client.client).to.be.null; // it should not be initialized at this point
expect(client.authProvider).to.be.instanceOf(PlainHttpAuthentication);
expect(client.connectionOptions).to.be.deep.equal(options);
});
});

Expand Down Expand Up @@ -155,7 +138,13 @@ describe('DBSQLClient.openSession', () => {
});

describe('DBSQLClient.getClient', () => {
it('should throw an error if the client is not set', async () => {
const options = {
host: '127.0.0.1',
path: '',
token: 'dapi********************************',
};

it('should throw an error if not connected', async () => {
const client = new DBSQLClient();
try {
await client.getClient();
Expand All @@ -167,15 +156,108 @@ describe('DBSQLClient.getClient', () => {
expect(error.message).to.contain('DBSQLClient: not connected');
}
});

it("should create client if wasn't not initialized yet", async () => {
const client = new DBSQLClient();

const thriftClient = {};

client.authProvider = new AuthProviderMock();
client.connectionOptions = { ...options };
client.thrift = {
createClient: sinon.stub().returns(thriftClient),
};
sinon.stub(client, 'createConnection').returns({
getConnection: () => null,
});

const result = await client.getClient();
expect(client.thrift.createClient.called).to.be.true;
expect(client.createConnection.called).to.be.true;
expect(result).to.be.equal(thriftClient);
});

it('should re-create client if auth credentials change', async () => {
const client = new DBSQLClient();

const thriftClient = {};

client.authProvider = new AuthProviderMock();
client.connectionOptions = { ...options };
client.thrift = {
createClient: sinon.stub().returns(thriftClient),
};
sinon.stub(client, 'createConnection').returns({
getConnection: () => null,
});

// initialize client
firstCall: {
const result = await client.getClient();
expect(client.thrift.createClient.callCount).to.be.equal(1);
expect(client.createConnection.callCount).to.be.equal(1);
expect(result).to.be.equal(thriftClient);
}

// credentials stay the same, client should not be re-created
secondCall: {
const result = await client.getClient();
expect(client.thrift.createClient.callCount).to.be.equal(1);
expect(client.createConnection.callCount).to.be.equal(1);
expect(result).to.be.equal(thriftClient);
}

// change credentials mock - client should be re-created
thirdCall: {
client.authProvider.authResult = { b: 2 };

const result = await client.getClient();
expect(client.thrift.createClient.callCount).to.be.equal(2);
expect(client.createConnection.callCount).to.be.equal(2);
expect(result).to.be.equal(thriftClient);
}
});
});

describe('DBSQLClient.createConnection', () => {
afterEach(() => {
HttpConnectionModule.default.restore?.();
});

it('should create connection', async () => {
const thriftConnection = {
on: sinon.stub(),
};

const connectionMock = {
getConnection: sinon.stub().returns(thriftConnection),
};

const connectionProviderMock = {
connect: sinon.stub().returns(Promise.resolve(connectionMock)),
};

sinon.stub(HttpConnectionModule, 'default').returns(connectionProviderMock);

const client = new DBSQLClient();

const result = await client.createConnection({});
expect(result).to.be.equal(connectionMock);
expect(connectionProviderMock.connect.called).to.be.true;
expect(connectionMock.getConnection.called).to.be.true;
expect(thriftConnection.on.called).to.be.true;
});
});

describe('DBSQLClient.close', () => {
it('should close the connection if it was initiated', async () => {
const client = new DBSQLClient();
client.client = {};
client.authProvider = {};
client.connectionOptions = {};

await client.close();
expect(client.client).to.be.null;
expect(client.authProvider).to.be.null;
expect(client.connectionOptions).to.be.null;
// No additional asserts needed - it should just reach this point
Expand All @@ -185,6 +267,7 @@ describe('DBSQLClient.close', () => {
const client = new DBSQLClient();

await client.close();
expect(client.client).to.be.null;
expect(client.authProvider).to.be.null;
expect(client.connectionOptions).to.be.null;
// No additional asserts needed - it should just reach this point
Expand Down
14 changes: 9 additions & 5 deletions tests/unit/hive/HiveDriver.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
const { expect } = require('chai');
const sinon = require('sinon');
const { TCLIService_types } = require('../../../').thrift;
const HiveDriver = require('../../../dist/hive/HiveDriver').default;

const toTitleCase = (str) => str[0].toUpperCase() + str.slice(1);

const testCommand = (command, request) => {
const testCommand = async (command, request) => {
const client = {};
const driver = new HiveDriver(() => Promise.resolve(client));
const clientFactory = sinon.stub().returns(Promise.resolve(client));
const driver = new HiveDriver(clientFactory);

const response = { response: 'value' };
client[toTitleCase(command)] = function (req, cb) {
expect(req).to.be.deep.eq(new TCLIService_types[`T${toTitleCase(command)}Req`](request));
cb(null, response);
};
return driver[command](request).then((resp) => {
expect(resp).to.be.deep.eq(response);
});

const resp = await driver[command](request);
expect(resp).to.be.deep.eq(response);
expect(clientFactory.called).to.be.true;
};

describe('HiveDriver', () => {
Expand Down
105 changes: 104 additions & 1 deletion tests/unit/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
const { expect } = require('chai');

const { buildUserAgentString, definedOrError, formatProgress, ProgressUpdateTransformer } = require('../../dist/utils');
const {
areHeadersEqual,
buildUserAgentString,
definedOrError,
formatProgress,
ProgressUpdateTransformer,
} = require('../../dist/utils');

describe('buildUserAgentString', () => {
// It should follow https://www.rfc-editor.org/rfc/rfc7231#section-5.5.3 and
Expand Down Expand Up @@ -91,3 +97,100 @@ describe('definedOrError', () => {
}).to.throw();
});
});

describe('areHeadersEqual', () => {
it('should return true for same objects', () => {
const a = {};
expect(areHeadersEqual(a, a)).to.be.true;
});

it('should return false for objects with different keys', () => {
const a = { a: 1, x: 2 };
const b = { b: 3, x: 4 };
const c = { c: 5 };

expect(areHeadersEqual(a, b)).to.be.false;
expect(areHeadersEqual(b, a)).to.be.false;
expect(areHeadersEqual(a, c)).to.be.false;
expect(areHeadersEqual(c, a)).to.be.false;
});

it('should compare different types of properties', () => {
case1: {
expect(
areHeadersEqual(
{
a: 1,
b: 'b',
c: ['x', 'y', 'z'],
},
{
a: 1,
b: 'b',
c: ['x', 'y', 'z'],
},
),
).to.be.true;
}

case2: {
const arr = ['a', 'b'];

expect(
areHeadersEqual(
{
a: 1,
b: 'b',
c: arr,
},
{
a: 1,
b: 'b',
c: arr,
},
),
).to.be.true;
}

case3: {
expect(
areHeadersEqual(
{
arr: ['a'],
},
{
arr: ['b'],
},
),
).to.be.false;
}

case4: {
expect(
areHeadersEqual(
{
arr: ['a'],
},
{
arr: ['a', 'b'],
},
),
).to.be.false;
}

case5: {
expect(
areHeadersEqual(
{
arr: ['a'],
prop: 'x',
},
{
arr: ['a'],
prop: 1,
},
),
).to.be.false;
}
});
});

0 comments on commit 45df1e2

Please sign in to comment.