Demo for query storing
Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-execArgv-child.js b/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-execArgv-child.js
new file mode 100644
index 0000000..f0d1d1f
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-execArgv-child.js
@@ -0,0 +1,7 @@
+module.exports = function(grunt) {
+
+ grunt.registerTask('default', function(text) {
+ console.log('OUTPUT: ' + process.execArgv.join(' '));
+ });
+
+};
diff --git a/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-execArgv.js b/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-execArgv.js
new file mode 100644
index 0000000..7ad3db0
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-execArgv.js
@@ -0,0 +1,17 @@
+module.exports = function(grunt) {
+
+ var util = require('../../');
+
+ grunt.registerTask('default', function(text) {
+ var done = this.async();
+ util.spawn({
+ grunt: true,
+ args: ['--gruntfile', 'Gruntfile-execArgv-child.js'],
+ }, function(err, result, code) {
+ var matches = result.stdout.match(/^(OUTPUT: .*)/m);
+ console.log(matches ? matches[1] : '');
+ done();
+ });
+ });
+
+};
diff --git a/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-print-text.js b/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-print-text.js
new file mode 100644
index 0000000..910197d
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/fixtures/Gruntfile-print-text.js
@@ -0,0 +1,8 @@
+module.exports = function(grunt) {
+
+ grunt.registerTask('print', 'Print the specified text.', function(text) {
+ console.log('OUTPUT: ' + text);
+ // console.log(process.cwd());
+ });
+
+};
diff --git a/node_modules/grunt-legacy-util/test/fixtures/exec.cmd b/node_modules/grunt-legacy-util/test/fixtures/exec.cmd
new file mode 100644
index 0000000..6e4a52b
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/fixtures/exec.cmd
@@ -0,0 +1 @@
+@echo done
diff --git a/node_modules/grunt-legacy-util/test/fixtures/exec.sh b/node_modules/grunt-legacy-util/test/fixtures/exec.sh
new file mode 100644
index 0000000..8890799
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/fixtures/exec.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+echo "done"
diff --git a/node_modules/grunt-legacy-util/test/fixtures/spawn-multibyte.js b/node_modules/grunt-legacy-util/test/fixtures/spawn-multibyte.js
new file mode 100644
index 0000000..b592341
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/fixtures/spawn-multibyte.js
@@ -0,0 +1,17 @@
+// This is a test fixture for a case where spawn receives incomplete
+// multibyte strings in separate data events.
+
+// A multibyte buffer containing all our output. We will slice it later.
+// In this case we are using a Japanese word for hello / good day, where each
+// character takes three bytes.
+var fullOutput = Buffer.from('こんにちは');
+
+// Output one full character and one third of a character
+process.stdout.write(fullOutput.slice(0, 4));
+
+// Output the rest of the string
+process.stdout.write(fullOutput.slice(4));
+
+// Do the same for stderr
+process.stderr.write(fullOutput.slice(0, 4));
+process.stderr.write(fullOutput.slice(4));
diff --git a/node_modules/grunt-legacy-util/test/fixtures/spawn.js b/node_modules/grunt-legacy-util/test/fixtures/spawn.js
new file mode 100644
index 0000000..14c7029
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/fixtures/spawn.js
@@ -0,0 +1,8 @@
+
+var code = Number(process.argv[2]);
+
+process.stdout.write('stdout\n');
+process.stderr.write('stderr\n');
+
+// Instead of process.exit. See https://github.com/cowboy/node-exit
+require('exit')(code);
diff --git a/node_modules/grunt-legacy-util/test/index.js b/node_modules/grunt-legacy-util/test/index.js
new file mode 100644
index 0000000..55cf79f
--- /dev/null
+++ b/node_modules/grunt-legacy-util/test/index.js
@@ -0,0 +1,554 @@
+'use strict';
+
+var util = require('../');
+
+var fs = require('fs');
+var path = require('path');
+
+var Tempfile = require('temporary/lib/file');
+
+exports['util.callbackify'] = {
+ 'return': function(test) {
+ test.expect(1);
+ // This function returns a value.
+ function add(a, b) {
+ return a + b;
+ }
+ util.callbackify(add)(1, 2, function(result) {
+ test.equal(result, 3, 'should be the correct result.');
+ test.done();
+ });
+ },
+ 'callback (sync)': function(test) {
+ test.expect(1);
+ // This function accepts a callback which it calls synchronously.
+ function add(a, b, done) {
+ done(a + b);
+ }
+ util.callbackify(add)(1, 2, function(result) {
+ test.equal(result, 3, 'should be the correct result.');
+ test.done();
+ });
+ },
+ 'callback (async)': function(test) {
+ test.expect(1);
+ // This function accepts a callback which it calls asynchronously.
+ function add(a, b, done) {
+ setTimeout(done.bind(null, a + b), 0);
+ }
+ util.callbackify(add)(1, 2, function(result) {
+ test.equal(result, 3, 'should be the correct result.');
+ test.done();
+ });
+ }
+};
+
+exports['util'] = {
+ 'error': function(test) {
+ test.expect(9);
+ var origError = new Error('Original error.');
+
+ var err = util.error('Test message.');
+ test.ok(err instanceof Error, 'Should be an Error.');
+ test.equal(err.name, 'Error', 'Should be an Error.');
+ test.equal(err.message, 'Test message.', 'Should have the correct message.');
+
+ err = util.error('Test message.', origError);
+ test.ok(err instanceof Error, 'Should be an Error.');
+ test.equal(err.name, 'Error', 'Should be an Error.');
+ test.equal(err.message, 'Test message.', 'Should have the correct message.');
+ test.equal(err.origError, origError, 'Should reflect the original error.');
+
+ var newError = new Error('Test message.');
+ err = util.error(newError, origError);
+ test.equal(err, newError, 'Should be the passed-in Error.');
+ test.equal(err.origError, origError, 'Should reflect the original error.');
+ test.done();
+ },
+ 'linefeed': function(test) {
+ test.expect(1);
+ if (process.platform === 'win32') {
+ test.equal(util.linefeed, '\r\n', 'linefeed should be operating-system appropriate.');
+ } else {
+ test.equal(util.linefeed, '\n', 'linefeed should be operating-system appropriate.');
+ }
+ test.done();
+ },
+ 'normalizelf': function(test) {
+ test.expect(1);
+ if (process.platform === 'win32') {
+ test.equal(util.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\r\nbar\r\nbaz\r\n\r\nqux\r\n\r\nquux', 'linefeeds should be normalized');
+ } else {
+ test.equal(util.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\nbar\nbaz\n\nqux\n\nquux', 'linefeeds should be normalized');
+ }
+ test.done();
+ }
+};
+
+exports['util.spawn'] = {
+ setUp: function(done) {
+ this.script = path.resolve('test/fixtures/spawn.js');
+ done();
+ },
+ 'exit code 0': function(test) {
+ test.expect(6);
+ util.spawn({
+ cmd: process.execPath,
+ args: [ this.script, 0 ],
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.equals(result.stdout, 'stdout');
+ test.equals(result.stderr, 'stderr');
+ test.equals(result.code, 0);
+ test.equals(String(result), 'stdout');
+ test.done();
+ });
+ },
+ 'exit code 0, fallback': function(test) {
+ test.expect(6);
+ util.spawn({
+ cmd: process.execPath,
+ args: [ this.script, 0 ],
+ fallback: 'ignored if exit code is 0'
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.equals(result.stdout, 'stdout');
+ test.equals(result.stderr, 'stderr');
+ test.equals(result.code, 0);
+ test.equals(String(result), 'stdout');
+ test.done();
+ });
+ },
+ 'non-zero exit code': function(test) {
+ test.expect(7);
+ util.spawn({
+ cmd: process.execPath,
+ args: [ this.script, 123 ],
+ }, function(err, result, code) {
+ test.ok(err instanceof Error);
+ test.equals(err.message, 'stderr');
+ test.equals(code, 123);
+ test.equals(result.stdout, 'stdout');
+ test.equals(result.stderr, 'stderr');
+ test.equals(result.code, 123);
+ test.equals(String(result), 'stderr');
+ test.done();
+ });
+ },
+ 'non-zero exit code, fallback': function(test) {
+ test.expect(6);
+ util.spawn({
+ cmd: process.execPath,
+ args: [ this.script, 123 ],
+ fallback: 'custom fallback'
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 123);
+ test.equals(result.stdout, 'stdout');
+ test.equals(result.stderr, 'stderr');
+ test.equals(result.code, 123);
+ test.equals(String(result), 'custom fallback');
+ test.done();
+ });
+ },
+ 'cmd not found': function(test) {
+ test.expect(3);
+ util.spawn({
+ cmd: 'nodewtfmisspelled',
+ }, function(err, result, code) {
+ test.ok(err instanceof Error);
+ test.equals(code, 127);
+ test.equals(result.code, 127);
+ test.done();
+ });
+ },
+ 'cmd not found, fallback': function(test) {
+ test.expect(4);
+ util.spawn({
+ cmd: 'nodewtfmisspelled',
+ fallback: 'use a fallback or good luck'
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 127);
+ test.equals(result.code, 127);
+ test.equals(String(result), 'use a fallback or good luck');
+ test.done();
+ });
+ },
+ 'cmd not in path': function(test) {
+ test.expect(6);
+ var win32 = process.platform === 'win32';
+ util.spawn({
+ cmd: 'test\\fixtures\\exec' + (win32 ? '.cmd' : '.sh'),
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.equals(result.stdout, 'done');
+ test.equals(result.stderr, '');
+ test.equals(result.code, 0);
+ test.equals(String(result), 'done');
+ test.done();
+ });
+ },
+ 'cmd not in path (with cwd)': function(test) {
+ test.expect(6);
+ var win32 = process.platform === 'win32';
+ util.spawn({
+ cmd: './exec' + (win32 ? '.cmd' : '.sh'),
+ opts: {cwd: 'test/fixtures'},
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.equals(result.stdout, 'done');
+ test.equals(result.stderr, '');
+ test.equals(result.code, 0);
+ test.equals(String(result), 'done');
+ test.done();
+ });
+ },
+ 'grunt': function(test) {
+ test.expect(3);
+ util.spawn({
+ grunt: true,
+ args: [ '--gruntfile', 'test/fixtures/Gruntfile-print-text.js', 'print:foo' ],
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.ok(/^OUTPUT: foo/m.test(result.stdout), 'stdout should contain output indicating the grunt task was run.');
+ test.done();
+ });
+ },
+ 'grunt (with cwd)': function(test) {
+ test.expect(3);
+ util.spawn({
+ grunt: true,
+ args: [ '--gruntfile', 'Gruntfile-print-text.js', 'print:foo' ],
+ opts: {cwd: 'test/fixtures'},
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.ok(/^OUTPUT: foo/m.test(result.stdout), 'stdout should contain output indicating the grunt task was run.');
+ test.done();
+ });
+ },
+ 'grunt passes execArgv': function(test) {
+ test.expect(3);
+ util.spawn({
+ cmd: process.execPath,
+ args: [ '--harmony', process.argv[1], '--gruntfile', 'test/fixtures/Gruntfile-execArgv.js'],
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.ok(/^OUTPUT: --harmony/m.test(result.stdout), 'stdout should contain passed-through process.execArgv.');
+ test.done();
+ });
+ },
+ 'grunt result.toString() with error': function(test) {
+ // grunt.log.error uses standard out, to be fixed in 0.5.
+ test.expect(4);
+ util.spawn({
+ grunt: true,
+ args: [ 'nonexistentTask' ]
+ }, function(err, result, code) {
+ test.ok(err instanceof Error, 'Should be an Error.');
+ test.equal(err.name, 'Error', 'Should be an Error.');
+ test.equals(code, 3);
+ test.ok(/Warning: Task "nonexistentTask" not found./m.test(result.toString()), 'stdout should contain output indicating the grunt task was (attempted to be) run.');
+ test.done();
+ });
+ },
+ 'custom stdio stream(s)': function(test) {
+ test.expect(6);
+ var stdoutFile = new Tempfile();
+ var stderrFile = new Tempfile();
+ var stdout = fs.openSync(stdoutFile.path, 'a');
+ var stderr = fs.openSync(stderrFile.path, 'a');
+ var child = util.spawn({
+ cmd: process.execPath,
+ args: [ this.script, 0 ],
+ opts: {stdio: [null, stdout, stderr]},
+ }, function(err, result, code) {
+ test.equals(code, 0);
+ test.equals(String(fs.readFileSync(stdoutFile.path)), 'stdout\n', 'Child process stdout should have been captured via custom stream.');
+ test.equals(String(fs.readFileSync(stderrFile.path)), 'stderr\n', 'Child process stderr should have been captured via custom stream.');
+ stdoutFile.unlinkSync();
+ stderrFile.unlinkSync();
+ test.equals(result.stdout, '', 'Nothing will be passed to the stdout string when spawn stdio is a custom stream.');
+ test.done();
+ });
+ test.ok(!child.stdout, 'child should not have a stdout property.');
+ test.ok(!child.stderr, 'child should not have a stderr property.');
+ },
+};
+
+exports['util.spawn.multibyte'] = {
+ setUp: function(done) {
+ this.script = path.resolve('test/fixtures/spawn-multibyte.js');
+ done();
+ },
+ 'partial stdout': function(test) {
+ test.expect(4);
+ util.spawn({
+ cmd: process.execPath,
+ args: [ this.script ],
+ }, function(err, result, code) {
+ test.equals(err, null);
+ test.equals(code, 0);
+ test.equals(result.stdout, 'こんにちは');
+ test.equals(result.stderr, 'こんにちは');
+ test.done();
+ });
+ }
+};
+
+exports['util.underscore.string'] = function(test) {
+ test.expect(4);
+ test.equals(util._.trim(' foo '), 'foo', 'Should have trimmed the string.');
+ test.equals(util._.capitalize('foo'), 'Foo', 'Should have capitalized the first letter.');
+ test.equals(util._.words('one two three').length, 3, 'Should have counted three words.');
+ test.ok(util._.isBlank(' '), 'Should be blank.');
+ test.done();
+};
+
+function getType(val) {
+ if (Buffer.isBuffer(val)) { return 'buffer'; }
+ return Object.prototype.toString.call(val).slice(8, -1).toLowerCase();
+}
+
+exports['util.recurse'] = {
+ setUp: function(done) {
+ this.typeValue = function(value) {
+ return {
+ value: value,
+ type: getType(value),
+ };
+ };
+ done();
+ },
+ 'primitives': function(test) {
+ test.expect(1);
+ var actual = util.recurse({
+ bool: true,
+ num: 1,
+ str: 'foo',
+ nul: null,
+ undef: undefined,
+ }, this.typeValue);
+ var expected = {
+ bool: {type: 'boolean', value: true},
+ num: {type: 'number', value: 1},
+ str: {type: 'string', value: 'foo'},
+ nul: {type: 'null', value: null},
+ undef: {type: 'undefined', value: undefined},
+ };
+ test.deepEqual(actual, expected, 'Should process primitive values.');
+ test.done();
+ },
+ 'array': function(test) {
+ test.expect(1);
+ var actual = util.recurse({
+ arr: [
+ true,
+ 1,
+ 'foo',
+ null,
+ undefined,
+ [
+ true,
+ 1,
+ 'foo',
+ null,
+ undefined,
+ ],
+ ],
+ }, this.typeValue);
+ var expected = {
+ arr: [
+ {type: 'boolean', value: true},
+ {type: 'number', value: 1},
+ {type: 'string', value: 'foo'},
+ {type: 'null', value: null},
+ {type: 'undefined', value: undefined},
+ [
+ {type: 'boolean', value: true},
+ {type: 'number', value: 1},
+ {type: 'string', value: 'foo'},
+ {type: 'null', value: null},
+ {type: 'undefined', value: undefined},
+ ],
+ ],
+ };
+ test.deepEqual(actual, expected, 'Should recurse over arrays.');
+ test.done();
+ },
+ 'object': function(test) {
+ test.expect(1);
+ var actual = util.recurse({
+ obj: {
+ bool: true,
+ num: 1,
+ str: 'foo',
+ nul: null,
+ undef: undefined,
+ obj: {
+ bool: true,
+ num: 1,
+ str: 'foo',
+ nul: null,
+ undef: undefined,
+ },
+ },
+ }, this.typeValue);
+ var expected = {
+ obj: {
+ bool: {type: 'boolean', value: true},
+ num: {type: 'number', value: 1},
+ str: {type: 'string', value: 'foo'},
+ nul: {type: 'null', value: null},
+ undef: {type: 'undefined', value: undefined},
+ obj: {
+ bool: {type: 'boolean', value: true},
+ num: {type: 'number', value: 1},
+ str: {type: 'string', value: 'foo'},
+ nul: {type: 'null', value: null},
+ undef: {type: 'undefined', value: undefined},
+ },
+ },
+ };
+ test.deepEqual(actual, expected, 'Should recurse over objects.');
+ test.done();
+ },
+ 'array in object': function(test) {
+ test.expect(1);
+ var actual = util.recurse({
+ obj: {
+ arr: [
+ true,
+ 1,
+ 'foo',
+ null,
+ undefined,
+ ],
+ },
+ }, this.typeValue);
+ var expected = {
+ obj: {
+ arr: [
+ {type: 'boolean', value: true},
+ {type: 'number', value: 1},
+ {type: 'string', value: 'foo'},
+ {type: 'null', value: null},
+ {type: 'undefined', value: undefined},
+ ],
+ },
+ };
+ test.deepEqual(actual, expected, 'Should recurse over arrays in objects.');
+ test.done();
+ },
+ 'object in array': function(test) {
+ test.expect(1);
+ var actual = util.recurse({
+ arr: [
+ true,
+ {
+ num: 1,
+ str: 'foo',
+ },
+ null,
+ undefined,
+ ],
+ }, this.typeValue);
+ var expected = {
+ arr: [
+ {type: 'boolean', value: true},
+ {
+ num: {type: 'number', value: 1},
+ str: {type: 'string', value: 'foo'},
+ },
+ {type: 'null', value: null},
+ {type: 'undefined', value: undefined},
+ ],
+ };
+ test.deepEqual(actual, expected, 'Should recurse over objects in arrays.');
+ test.done();
+ },
+ 'buffer': function(test) {
+ test.expect(1);
+ var actual = util.recurse({
+ buf: Buffer.from('buf'),
+ }, this.typeValue);
+ var expected = {
+ buf: {type: 'buffer', value: Buffer.from('buf')},
+ };
+ test.deepEqual(actual, expected, 'Should not mangle Buffer instances.');
+ test.done();
+ },
+ 'inherited properties': function(test) {
+ test.expect(1);
+ var actual = util.recurse({
+ obj: Object.create({num: 1}, {
+ str: {value: 'foo', enumerable: true},
+ ignored: {value: 'ignored', enumerable: false},
+ }),
+ }, this.typeValue);
+ var expected = {
+ obj: {
+ num: {type: 'number', value: 1},
+ str: {type: 'string', value: 'foo'},
+ }
+ };
+ test.deepEqual(actual, expected, 'Should enumerate inherited object properties.');
+ test.done();
+ },
+ 'circular references': function(test) {
+ test.expect(6);
+ function assertErrorWithPath(expectedPath) {
+ return function(actual) {
+ return actual.path === expectedPath &&
+ actual.message === 'Circular reference detected (' + expectedPath + ')';
+ };
+ }
+ test.doesNotThrow(function() {
+ var obj = {
+ // wat
+ a:[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
+ // does
+ b:[[[[],[[[],[[[[],[[[],[[[],[[[],[[[],[[[[],[[]]]]]]]]]]]]]]]]]]]]],
+ // it
+ c:{d:{e:{f:{g:{h:{i:{j:{k:{l:{m:{n:{o:{p:{q:{r:{s:{}}}}}}}}}}}}}}}}},
+ // mean
+ t:[{u:[{v:[[[[],[[[],[[[{w:[{x:[[[],[[[{y:[[1]]}]]]]]}]}]]]]]]]]}]}],
+ };
+ util.recurse(obj, function(v) { return v; });
+ }, 'Should not throw when no circular reference is detected.');
+ test.throws(function() {
+ var obj = {a: 1, b: 2};
+ obj.obj = obj;
+ util.recurse(obj, function(v) { return v; });
+ }, assertErrorWithPath('.obj'), 'Should throw when a circular reference is detected.');
+ test.throws(function() {
+ var obj = {a:{'b b':{'c-c':{d_d:{e:{f:{g:{h:{i:{j:{k:{l:{}}}}}}}}}}}}};
+ obj.a['b b']['c-c'].d_d.e.f.g.h.i.j.k.l.obj = obj;
+ util.recurse(obj, function(v) { return v; });
+ }, assertErrorWithPath('.a["b b"]["c-c"].d_d.e.f.g.h.i.j.k.l.obj'), 'Should throw when a circular reference is detected.');
+ test.throws(function() {
+ var obj = {a: 1, b: 2};
+ obj.arr = [1, 2, obj, 3, 4];
+ util.recurse(obj, function(v) { return v; });
+ }, assertErrorWithPath('.arr[2]'), 'Should throw when a circular reference is detected.');
+ test.throws(function() {
+ var obj = {a: 1, b: 2};
+ obj.arr = [{a:[1,{b:[2,{c:[3,obj,4]},5]},6]},7];
+ util.recurse(obj, function(v) { return v; });
+ }, assertErrorWithPath('.arr[0].a[1].b[1].c[1]'), 'Should throw when a circular reference is detected.');
+ test.throws(function() {
+ var obj = {a: 1, b: 2};
+ obj.arr = [];
+ obj.arr.push(0,{a:[1,{b:[2,{c:[3,obj.arr,4]},5]},6]},7);
+ util.recurse(obj, function(v) { return v; });
+ }, assertErrorWithPath('.arr[1].a[1].b[1].c[1]'), 'Should throw when a circular reference is detected.');
+ test.done();
+ },
+};