loopback-connector-mysql/test/connection.test.js

214 lines
6.2 KiB
JavaScript

// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-connector-mysql
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
require('./init.js');
const assert = require('assert');
const should = require('should');
const DataSource = require('loopback-datasource-juggler').DataSource;
const mysqlConnector = require('../');
const url = require('url');
let db, DummyModel, odb, config;
describe('connections', function() {
before(function() {
require('./init.js');
config = global.getConfig();
odb = global.getDataSource({collation: 'utf8_general_ci',
createDatabase: true});
db = odb;
});
it('should pass with valid settings', function(done) {
const db = new DataSource(mysqlConnector, config);
db.ping(done);
});
it('ignores all other settings when url is present', function(done) {
const formatedUrl = generateURL(config);
const dbConfig = {
url: formatedUrl,
host: 'invalid-hostname',
port: 80,
database: 'invalid-database',
username: 'invalid-username',
password: 'invalid-password',
};
const db = new DataSource(mysqlConnector, dbConfig);
db.ping(done);
});
it('should use utf8 charset', function(done) {
const test_set = /utf8mb4/;
const test_collo = /utf8mb4_0900_ai_ci/;
const test_set_str = 'utf8mb4';
const test_set_collo = 'utf8mb4_0900_ai_ci';
charsetTest(test_set, test_collo, test_set_str, test_set_collo, done);
});
it('should disconnect first db', function(done) {
db.disconnect(function() {
odb = global.getDataSource();
done();
});
});
it('should disconnect then connect and ORM should work', function() {
const ds = new DataSource(mysqlConnector, config);
const Student = ds.define('Student', {
name: {type: String, length: 255},
age: {type: Number},
}, {
forceId: false,
});
return ds.connect()
.then(function(err) {
should.not.exist(err);
return ds.automigrate(['Student']);
})
.then(function(err) {
should.not.exist(err);
should(ds.connected).be.True();
return ds.disconnect();
})
.then(function(err) {
should.not.exist(err);
should(ds.connected).be.False();
return ds.connect();
})
.then(function(err) {
should.not.exist(err);
should(ds.connected).be.True();
return Student.count();
})
.then(function(count) {
should(count).be.a.Number();
return ds.disconnect();
});
});
it('should use latin1 charset', function(done) {
const test_set = /latin1/;
const test_collo = /latin1_general_ci/;
const test_set_str = 'latin1';
const test_set_collo = 'latin1_general_ci';
charsetTest(test_set, test_collo, test_set_str, test_set_collo, done);
});
it('should drop db and disconnect all', function(done) {
db.connector.execute('DROP DATABASE IF EXISTS ' + db.settings.database, function(err) {
db.disconnect(function() {
done();
});
});
});
describe('lazyConnect', function() {
it('should skip connect phase (lazyConnect = true)', function(done) {
const dbConfig = {
host: '127.0.0.1',
port: 4,
lazyConnect: true,
};
const ds = new DataSource(mysqlConnector, dbConfig);
const errTimeout = setTimeout(function() {
done();
}, 2000);
ds.on('error', function(err) {
clearTimeout(errTimeout);
done(err);
});
});
it('should report connection error (lazyConnect = false)', function(done) {
const dbConfig = {
host: '127.0.0.1',
port: 4,
lazyConnect: false,
};
const ds = new DataSource(mysqlConnector, dbConfig);
ds.on('error', function(err) {
err.message.should.containEql('ECONNREFUSED');
done();
});
});
});
});
function charsetTest(test_set, test_collo, test_set_str, test_set_collo, done) {
query('DROP DATABASE IF EXISTS ' + odb.settings.database, function(err) {
assert.ok(!err);
odb.disconnect(function() {
db = global.getDataSource({collation: test_set_collo,
createDatabase: true});
DummyModel = db.define('DummyModel', {string: String});
db.automigrate(function() {
const q = 'SELECT DEFAULT_COLLATION_NAME' +
' FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ' +
db.driver.escape(db.settings.database) + ' LIMIT 1';
db.connector.execute(q, function(err, r) {
assert.ok(!err);
should(r[0].DEFAULT_COLLATION_NAME).match(test_collo);
db.connector.execute('SHOW VARIABLES LIKE "character_set%"', function(err, r) {
assert.ok(!err);
let hit_all = 0;
for (const result in r) {
hit_all += matchResult(r[result], 'character_set_connection', test_set);
hit_all += matchResult(r[result], 'character_set_database', test_set);
hit_all += matchResult(r[result], 'character_set_results', test_set);
hit_all += matchResult(r[result], 'character_set_client', test_set);
}
assert.equal(hit_all, 4);
});
db.connector.execute('SHOW VARIABLES LIKE "collation%"', function(err, r) {
assert.ok(!err);
let hit_all = 0;
for (const result in r) {
hit_all += matchResult(r[result], 'collation_connection', test_set);
hit_all += matchResult(r[result], 'collation_database', test_set);
}
assert.equal(hit_all, 2);
done();
});
});
});
});
});
}
function matchResult(result, variable_name, match) {
if (result.Variable_name === variable_name) {
assert.ok(result.Value.match(match));
return 1;
}
return 0;
}
function query(sql, cb) {
odb.connector.execute(sql, cb);
}
function generateURL(config) {
const urlObj = {
protocol: 'mysql',
auth: config.username || '',
hostname: config.host,
pathname: config.database,
slashes: true,
};
if (config.password) {
urlObj.auth += ':' + config.password;
}
const formatedUrl = url.format(urlObj);
return formatedUrl;
}