From 3954709bbc18f9be5a7c44212eb1b35738d32292 Mon Sep 17 00:00:00 2001 From: Ryan Graham Date: Tue, 9 Aug 2016 13:29:47 -0700 Subject: [PATCH 1/3] test: accept alternate test db credentials Allow the tests to run on ci.strongloop.com using the credentials that are given there, but translate them to the form that is used on cis-jenkins, which is actually the correct format. --- pretest.js | 12 +++++++++++- test/init.js | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pretest.js b/pretest.js index 294a24b..bb2e765 100644 --- a/pretest.js +++ b/pretest.js @@ -1,3 +1,10 @@ +// TODO: used for testing support for parallel testing on ci.strongloop.com which +// provides MYSQL_* env vars instead of TEST_MYSQL_* env vars. +process.env.TEST_MYSQL_USER = process.env.TEST_MYSQL_USER || process.env.MYSQL_USER; +process.env.TEST_MYSQL_PASSWORD = process.env.TEST_MYSQL_PASSWORD || process.env.MYSQL_PASSWORD; +process.env.TEST_MYSQL_HOST = process.env.TEST_MYSQL_HOST || process.env.MYSQL_HOST; +process.env.TEST_MYSQL_PORT = process.env.TEST_MYSQL_PORT || process.env.MYSQL_PORT; + if (!process.env.TEST_MYSQL_USER) { console.log('not seeding DB with example db'); return; @@ -23,6 +30,9 @@ if (process.env.TEST_MYSQL_PASSWORD) { console.log('seeding DB with example db...'); var mysql = cp.spawn('mysql', args, {stdio: stdio}); sql.pipe(mysql.stdin); -mysql.on('exit', function() { +mysql.on('exit', function(code) { console.log('done seeding DB'); + setTimeout(function() { + process.exit(code); + }, 200); }); diff --git a/test/init.js b/test/init.js index ac1e6e5..8d704f4 100644 --- a/test/init.js +++ b/test/init.js @@ -3,6 +3,13 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT +// TODO: used for testing support for parallel testing on ci.strongloop.com which +// provides MYSQL_* env vars instead of TEST_MYSQL_* env vars. +process.env.TEST_MYSQL_USER = process.env.TEST_MYSQL_USER || process.env.MYSQL_USER; +process.env.TEST_MYSQL_PASSWORD = process.env.TEST_MYSQL_PASSWORD || process.env.MYSQL_PASSWORD; +process.env.TEST_MYSQL_HOST = process.env.TEST_MYSQL_HOST || process.env.MYSQL_HOST; +process.env.TEST_MYSQL_PORT = process.env.TEST_MYSQL_PORT || process.env.MYSQL_PORT; + module.exports = require('should'); var DataSource = require('loopback-datasource-juggler').DataSource; From a798377f983deb3c2db8ca93e97e7b86fd5ed1f7 Mon Sep 17 00:00:00 2001 From: Ryan Graham Date: Tue, 9 Aug 2016 18:33:34 -0700 Subject: [PATCH 2/3] test: skip cardinality, update sub_part Index cardinality is actually a metric that is based on MySQL analyzing the table contents, so its value here has more to do with whether the tests are running against a new table, an old table, or whether it has any data in it. The Sub_part field is similarly unimportant for the purposes of these tests since it refers to indexing internals based on data type and partial indexing. See: https://dev.mysql.com/doc/refman/5.5/en/show-index.html --- test/migration.test.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/test/migration.test.js b/test/migration.test.js index 4a84196..9118b7d 100644 --- a/test/migration.test.js +++ b/test/migration.test.js @@ -89,7 +89,10 @@ describe('migrations', function () { Seq_in_index: 1, Column_name: 'id', Collation: 'A', - Cardinality: 0, + // XXX: this actually has more to do with whether the table existed or not and + // what kind of data is in it that MySQL has analyzed: + // https://dev.mysql.com/doc/refman/5.5/en/show-index.html + // Cardinality: /^5\.[567]/.test(mysqlVersion) ? 0 : null, Sub_part: null, Packed: null, Null: '', @@ -102,8 +105,11 @@ describe('migrations', function () { Seq_in_index: 1, Column_name: 'email', Collation: 'A', - Cardinality: /^5\.7/.test(mysqlVersion) ? 0 : null, - Sub_part: /^5\.7/.test(mysqlVersion) ? null : 333, + // XXX: this actually has more to do with whether the table existed or not and + // what kind of data is in it that MySQL has analyzed: + // https://dev.mysql.com/doc/refman/5.5/en/show-index.html + // Cardinality: /^5\.[567]/.test(mysqlVersion) ? 0 : null, + Sub_part: /^5\.7/.test(mysqlVersion) ? null : /^5\.5/.test(mysqlVersion) ? 255 : 333, Packed: null, Null: '', Index_type: 'BTREE', @@ -115,8 +121,11 @@ describe('migrations', function () { Seq_in_index: 1, Column_name: 'email', Collation: 'A', - Cardinality: /^5\.7/.test(mysqlVersion) ? 0 : null, - Sub_part: /^5\.7/.test(mysqlVersion) ? null : 333, + // XXX: this actually has more to do with whether the table existed or not and + // what kind of data is in it that MySQL has analyzed: + // https://dev.mysql.com/doc/refman/5.5/en/show-index.html + // Cardinality: /^5\.[567]/.test(mysqlVersion) ? 0 : null, + Sub_part: /^5\.7/.test(mysqlVersion) ? null : /^5\.5/.test(mysqlVersion) ? 255 : 333, Packed: null, Null: '', Index_type: 'BTREE', From 2533fe840483683df7c0951ddcf3d95e1de3fc79 Mon Sep 17 00:00:00 2001 From: Ryan Graham Date: Tue, 9 Aug 2016 17:25:57 -0700 Subject: [PATCH 3/3] test: use dump of original test DB as seed --- pretest.js | 2 +- test/mysql.discover.test.js | 42 +++---- test/schema.sql | 222 ++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 22 deletions(-) create mode 100644 test/schema.sql diff --git a/pretest.js b/pretest.js index bb2e765..3c48401 100644 --- a/pretest.js +++ b/pretest.js @@ -13,7 +13,7 @@ if (!process.env.TEST_MYSQL_USER) { var fs = require('fs'); var cp = require('child_process'); -var sql = fs.createReadStream(require.resolve('./example/table.sql')); +var sql = fs.createReadStream(require.resolve('./test/schema.sql')); var stdio = ['pipe', process.stdout, process.stderr]; var args = ['--user=' + process.env.TEST_MYSQL_USER]; diff --git a/test/mysql.discover.test.js b/test/mysql.discover.test.js index 15ea848..ea80743 100644 --- a/test/mysql.discover.test.js +++ b/test/mysql.discover.test.js @@ -13,7 +13,7 @@ var db, config; before(function () { require('./init'); config = getConfig(); - config.database = 'strongloop'; + config.database = 'STRONGLOOP'; db = new DataSource(require('../'), config); }); @@ -116,7 +116,7 @@ describe('Discover models including other users', function () { var others = false; models.forEach(function (m) { // console.dir(m); - if (m.owner !== 'strongloop') { + if (m.owner !== 'STRONGLOOP') { others = true; } }); @@ -163,8 +163,8 @@ describe('Discover model primary keys', function () { }); }); - it('should return an array of primary keys for strongloop.product', function (done) { - db.discoverPrimaryKeys('product', {owner: 'strongloop'}, function (err, models) { + it('should return an array of primary keys for STRONGLOOP.PRODUCT', function (done) { + db.discoverPrimaryKeys('product', {owner: 'STRONGLOOP'}, function (err, models) { if (err) { console.error(err); done(err); @@ -180,29 +180,29 @@ describe('Discover model primary keys', function () { }); describe('Discover model foreign keys', function () { - it('should return an array of foreign keys for inventory', function (done) { - db.discoverForeignKeys('inventory', function (err, models) { + it('should return an array of foreign keys for INVENTORY', function (done) { + db.discoverForeignKeys('INVENTORY', function (err, models) { if (err) { console.error(err); done(err); } else { models.forEach(function (m) { // console.dir(m); - assert(m.fkTableName === 'inventory'); + assert(m.fkTableName === 'INVENTORY'); }); done(null, models); } }); }); - it('should return an array of foreign keys for strongloop.inventory', function (done) { - db.discoverForeignKeys('inventory', {owner: 'strongloop'}, function (err, models) { + it('should return an array of foreign keys for STRONGLOOP.INVENTORY', function (done) { + db.discoverForeignKeys('INVENTORY', {owner: 'STRONGLOOP'}, function (err, models) { if (err) { console.error(err); done(err); } else { models.forEach(function (m) { // console.dir(m); - assert(m.fkTableName === 'inventory'); + assert(m.fkTableName === 'INVENTORY'); }); done(null, models); } @@ -213,26 +213,26 @@ describe('Discover model foreign keys', function () { describe('Discover LDL schema from a table', function () { var schema; before(function (done) { - db.discoverSchema('inventory', {owner: 'strongloop'}, function (err, schema_) { + db.discoverSchema('INVENTORY', {owner: 'STRONGLOOP'}, function (err, schema_) { schema = schema_; done(err); }); }); - it('should return an LDL schema for inventory', function () { + it('should return an LDL schema for INVENTORY', function () { var productId = 'productId' in schema.properties ? 'productId' : 'productid'; var locationId = 'locationId' in schema.properties ? 'locationId' : 'locationid'; console.error('schema:', schema); assert.strictEqual(schema.name, 'Inventory'); - assert.ok(/strongloop/i.test(schema.options.mysql.schema)); - assert.strictEqual(schema.options.mysql.table, 'inventory'); + assert.ok(/STRONGLOOP/i.test(schema.options.mysql.schema)); + assert.strictEqual(schema.options.mysql.table, 'INVENTORY'); assert(schema.properties[productId]); // TODO: schema shows this field is default NULL, which means it isn't required // assert(schema.properties[productId].required); assert.strictEqual(schema.properties[productId].type, 'String'); - assert.strictEqual(schema.properties[productId].mysql.columnName, 'productId'); + assert.strictEqual(schema.properties[productId].mysql.columnName, 'PRODUCT_ID'); assert(schema.properties[locationId]); assert.strictEqual(schema.properties[locationId].type, 'String'); - assert.strictEqual(schema.properties[locationId].mysql.columnName, 'locationId'); + assert.strictEqual(schema.properties[locationId].mysql.columnName, 'LOCATION_ID'); assert(schema.properties.available); assert.strictEqual(schema.properties.available.required, false); assert.strictEqual(schema.properties.available.type, 'Number'); @@ -244,7 +244,7 @@ describe('Discover LDL schema from a table', function () { describe('Discover and build models', function () { var models; before(function (done) { - db.discoverAndBuildModels('inventory', {owner: 'strongloop', visited: {}, associations: true}, function (err, models_) { + db.discoverAndBuildModels('INVENTORY', {owner: 'STRONGLOOP', visited: {}, associations: true}, function (err, models_) { models = models_; done(err); }); @@ -254,14 +254,14 @@ describe('Discover and build models', function () { var schema = models.Inventory.definition; var productId = 'productId' in schema.properties ? 'productId' : 'productid'; var locationId = 'locationId' in schema.properties ? 'locationId' : 'locationid'; - assert(/strongloop/i.test(schema.settings.mysql.schema)); - assert.strictEqual(schema.settings.mysql.table, 'inventory'); + assert(/STRONGLOOP/i.test(schema.settings.mysql.schema)); + assert.strictEqual(schema.settings.mysql.table, 'INVENTORY'); assert(schema.properties[productId]); assert.strictEqual(schema.properties[productId].type, String); - assert.strictEqual(schema.properties[productId].mysql.columnName, 'productId'); + assert.strictEqual(schema.properties[productId].mysql.columnName, 'PRODUCT_ID'); assert(schema.properties[locationId]); assert.strictEqual(schema.properties[locationId].type, String); - assert.strictEqual(schema.properties[locationId].mysql.columnName, 'locationId'); + assert.strictEqual(schema.properties[locationId].mysql.columnName, 'LOCATION_ID'); assert(schema.properties.available); assert.strictEqual(schema.properties.available.type, Number); assert(schema.properties.total); diff --git a/test/schema.sql b/test/schema.sql new file mode 100644 index 0000000..5c69b58 --- /dev/null +++ b/test/schema.sql @@ -0,0 +1,222 @@ +-- MySQL dump 10.13 Distrib 5.7.14, for osx10.10 (x86_64) +-- +-- Host: 166.78.158.45 Database: STRONGLOOP +-- ------------------------------------------------------ +-- Server version 5.1.69 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `STRONGLOOP` +-- + +/*!40000 DROP DATABASE IF EXISTS `STRONGLOOP`*/; + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `STRONGLOOP` /*!40100 DEFAULT CHARACTER SET utf8 */; + +USE `STRONGLOOP`; + +-- +-- Table structure for table `CUSTOMER` +-- + +DROP TABLE IF EXISTS `CUSTOMER`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `CUSTOMER` ( + `ID` varchar(20) NOT NULL, + `NAME` varchar(40) DEFAULT NULL, + `MILITARY_AGENCY` varchar(20) DEFAULT NULL, + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `CUSTOMER` +-- + +LOCK TABLES `CUSTOMER` WRITE; +/*!40000 ALTER TABLE `CUSTOMER` DISABLE KEYS */; +/*!40000 ALTER TABLE `CUSTOMER` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `INVENTORY` +-- + +DROP TABLE IF EXISTS `INVENTORY`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `INVENTORY` ( + `PRODUCT_ID` varchar(20) NOT NULL, + `LOCATION_ID` varchar(20) NOT NULL, + `AVAILABLE` int(11) DEFAULT NULL, + `TOTAL` int(11) DEFAULT NULL, + PRIMARY KEY (`PRODUCT_ID`,`LOCATION_ID`), + KEY `LOCATION_FK` (`LOCATION_ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `INVENTORY` +-- + +LOCK TABLES `INVENTORY` WRITE; +/*!40000 ALTER TABLE `INVENTORY` DISABLE KEYS */; +/*!40000 ALTER TABLE `INVENTORY` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Temporary view structure for view `INVENTORY_VIEW` +-- + +DROP TABLE IF EXISTS `INVENTORY_VIEW`; +/*!50001 DROP VIEW IF EXISTS `INVENTORY_VIEW`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +/*!50001 CREATE VIEW `INVENTORY_VIEW` AS SELECT + 1 AS `ID`, + 1 AS `PRODUCT_ID`, + 1 AS `PRODUCT_NAME`, + 1 AS `AUDIBLE_RANGE`, + 1 AS `EFFECTIVE_RANGE`, + 1 AS `ROUNDS`, + 1 AS `EXTRAS`, + 1 AS `FIRE_MODES`, + 1 AS `LOCATION_ID`, + 1 AS `LOCATION`, + 1 AS `CITY`, + 1 AS `ZIPCODE`, + 1 AS `AVAILABLE`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `LOCATION` +-- + +DROP TABLE IF EXISTS `LOCATION`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `LOCATION` ( + `ID` varchar(20) NOT NULL, + `STREET` varchar(20) DEFAULT NULL, + `CITY` varchar(20) DEFAULT NULL, + `ZIPCODE` varchar(20) DEFAULT NULL, + `NAME` varchar(20) DEFAULT NULL, + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `LOCATION` +-- + +LOCK TABLES `LOCATION` WRITE; +/*!40000 ALTER TABLE `LOCATION` DISABLE KEYS */; +/*!40000 ALTER TABLE `LOCATION` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `PRODUCT` +-- + +DROP TABLE IF EXISTS `PRODUCT`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `PRODUCT` ( + `ID` varchar(20) NOT NULL, + `NAME` varchar(64) DEFAULT NULL, + `AUDIBLE_RANGE` decimal(12,2) DEFAULT NULL, + `EFFECTIVE_RANGE` decimal(12,2) DEFAULT NULL, + `ROUNDS` decimal(10,0) DEFAULT NULL, + `EXTRAS` varchar(64) DEFAULT NULL, + `FIRE_MODES` varchar(64) DEFAULT NULL, + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `PRODUCT` +-- + +LOCK TABLES `PRODUCT` WRITE; +/*!40000 ALTER TABLE `PRODUCT` DISABLE KEYS */; +/*!40000 ALTER TABLE `PRODUCT` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `RESERVATION` +-- + +DROP TABLE IF EXISTS `RESERVATION`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `RESERVATION` ( + `ID` varchar(20) NOT NULL, + `PRODUCT_ID` varchar(20) NOT NULL, + `LOCATION_ID` varchar(20) NOT NULL, + `CUSTOMER_ID` varchar(20) NOT NULL, + `QTY` int(11) DEFAULT NULL, + `STATUS` varchar(20) DEFAULT NULL, + `RESERVE_DATE` date DEFAULT NULL, + `PICKUP_DATE` date DEFAULT NULL, + `RETURN_DATE` date DEFAULT NULL, + PRIMARY KEY (`ID`), + KEY `RESERVATION_PRODUCT_FK` (`PRODUCT_ID`), + KEY `RESERVATION_LOCATION_FK` (`LOCATION_ID`), + KEY `RESERVATION_CUSTOMER_FK` (`CUSTOMER_ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `RESERVATION` +-- + +LOCK TABLES `RESERVATION` WRITE; +/*!40000 ALTER TABLE `RESERVATION` DISABLE KEYS */; +/*!40000 ALTER TABLE `RESERVATION` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Current Database: `STRONGLOOP` +-- + +USE `STRONGLOOP`; + +-- +-- Final view structure for view `INVENTORY_VIEW` +-- + +/*!50001 DROP VIEW IF EXISTS `INVENTORY_VIEW`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`strongloop`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `INVENTORY_VIEW` AS select concat(concat(`P`.`ID`,':'),`L`.`ID`) AS `ID`,`P`.`ID` AS `PRODUCT_ID`,`P`.`NAME` AS `PRODUCT_NAME`,`P`.`AUDIBLE_RANGE` AS `AUDIBLE_RANGE`,`P`.`EFFECTIVE_RANGE` AS `EFFECTIVE_RANGE`,`P`.`ROUNDS` AS `ROUNDS`,`P`.`EXTRAS` AS `EXTRAS`,`P`.`FIRE_MODES` AS `FIRE_MODES`,`L`.`ID` AS `LOCATION_ID`,`L`.`NAME` AS `LOCATION`,`L`.`CITY` AS `CITY`,`L`.`ZIPCODE` AS `ZIPCODE`,`I`.`AVAILABLE` AS `AVAILABLE` from ((`INVENTORY` `I` join `PRODUCT` `P`) join `LOCATION` `L`) where ((`P`.`ID` = `I`.`PRODUCT_ID`) and (`L`.`ID` = `I`.`LOCATION_ID`)) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2016-08-09 19:14:01