Added unit tests for the blobstore rewrites

100% test coverage.
This commit is contained in:
Michael Krotscheck 2016-04-08 10:30:55 -07:00
parent 9ec3da6e82
commit b900ee45ff
No known key found for this signature in database
GPG Key ID: 20E618D878DE38AB
5 changed files with 336 additions and 9 deletions

3
.gitignore vendored
View File

@ -24,6 +24,9 @@ www
node_modules
bower_components
# Dev test output
output
# Optional npm cache directory
.npm

View File

@ -4,14 +4,39 @@
var options = require('./lib/args');
var blobstore = require('fs-blob-store')(options.dir);
function afsify (opts) {
function clone (instance) {
return JSON.parse(JSON.stringify(instance));
}
function ensort (opts) {
// First clone the instance.
opts = clone(opts);
if (typeof opts === 'string') {
// Packages that start with alphanumerics are rewritten:
// foo -> f/foo, bar -> b/bar
opts = opts.replace(/^\/?([a-zA-Z0-9])/, function(match, submatch) {
return submatch + '/' + submatch;
return opts.replace(/^\/?([a-zA-Z0-9])/, function(match, submatch) {
return match + '/' + submatch;
});
return opts;
} else if (opts.hasOwnProperty('key')) {
opts.key = ensort(opts.key); // Yes this is recursion, what of it?
}
return opts;
}
function desort (opts) {
// First clone the instance.
opts = clone(opts);
if (typeof opts === 'string') {
// Packages that start with alphanumerics are rewritten:
// foo -> f/foo, bar -> b/bar
return opts.replace(/^(\/?([a-zA-Z0-9]))\/\2/, function(match, s1) {
return s1;
});
} else if (opts.hasOwnProperty('key')) {
opts.key = desort(opts.key);
}
return opts;
@ -19,16 +44,20 @@
module.exports = {
createWriteStream: function(opts, cb) {
return blobstore.createWriteStream(afsify(opts), cb);
return blobstore.createWriteStream(ensort(opts), function(results) {
if (cb) {
return cb(desort(results));
}
});
},
createReadStream: function(key, opts) {
return blobstore.createReadStream(afsify(key), opts);
return blobstore.createReadStream(ensort(key), opts);
},
exists: function(opts, cb) {
return blobstore.exists(afsify(opts), cb);
return blobstore.exists(ensort(opts), cb);
},
remove: function(opts, cb) {
return blobstore.remove(afsify(opts), cb);
return blobstore.remove(ensort(opts), cb);
}
};
})();

View File

@ -9,11 +9,11 @@
"yargs": "^4.4.0"
},
"devDependencies": {
"abstract-blob-store": "^3.2.0",
"eslint": "^1.5.0",
"eslint-config-openstack": "^1.2.4",
"istanbul": "^0.4.2",
"jasmine": "^2.4.1",
"mockery": "^1.4.1",
"nsp": "^2.3.0"
},
"scripts": {

231
spec/index.js Normal file
View File

@ -0,0 +1,231 @@
/*
* Copyright (c) 2016 Hewlett Packard Enterprise Development Company, LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
var mockery = require('mockery');
var testData = {
'-/index.json': '-/index.json',
'-/404.json': '-/404.json',
'black/index.json': 'b/black/index.json',
'black/latest/index.json': 'b/black/latest/index.json',
'black/0.3.0/index.json': 'b/black/0.3.0/index.json',
'black/-/black-0.3.0.tgz': 'b/black/-/black-0.3.0.tgz',
'/-/index.json': '/-/index.json',
'/-/404.json': '/-/404.json',
'/black/index.json': '/b/black/index.json',
'/black/latest/index.json': '/b/black/latest/index.json',
'/black/0.3.0/index.json': '/b/black/0.3.0/index.json',
'/black/-/black-0.3.0.tgz': '/b/black/-/black-0.3.0.tgz'
};
var mockBlobStore = {
createWriteStream: function(opts, cb) {
if (cb) {
return cb(opts);
}
},
createReadStream: function() {
},
exists: function(opts, cb) {
if (cb) {
return cb(opts);
}
},
remove: function(opts, cb) {
if (cb) {
return cb(opts);
}
}
};
describe('sorting-blob-store', function() {
beforeEach(function(done) {
mockery.registerMock('fs-blob-store', function() {
return mockBlobStore;
});
mockery.enable({
useCleanCache: true,
warnOnReplace: false,
warnOnUnregistered: false
});
mockery.resetCache();
done();
});
afterEach(function(done) {
mockery.disable();
mockery.deregisterAll();
done();
});
it('should rewrite the path on createWriteStream', function() {
var spy = spyOn(mockBlobStore, 'createWriteStream').and.callThrough();
var blobstore = require('../index');
for (var key in testData) {
if (!testData.hasOwnProperty(key)) {
continue;
}
blobstore.createWriteStream(key);
expect(spy.calls.mostRecent().args[0]).toEqual(testData[key]);
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
blobstore.createWriteStream({key: key});
expect(spy.calls.mostRecent().args[0]).toEqual({key: testData[key]});
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
}
});
it('should decode the path on createWriteStream\'s callback', function() {
var cbSpy = spyOn(mockBlobStore, 'createWriteStream').and.callFake(function(opts, cb) {
if (typeof opts === 'string') {
return cb({key: opts});
} else {
return cb(opts);
}
});
var spy = jasmine.createSpy('spy');
var blobstore = require('../index');
for (var key in testData) {
if (!testData.hasOwnProperty(key)) {
continue;
}
blobstore.createWriteStream(key, spy);
expect(cbSpy.calls.mostRecent().args[0]).toEqual(testData[key]);
expect(spy.calls.mostRecent().args[0]).toEqual({key: key});
expect(cbSpy.calls.count()).toEqual(1);
expect(spy.calls.count()).toEqual(1);
cbSpy.calls.reset();
spy.calls.reset();
blobstore.createWriteStream({key: key}, spy);
expect(cbSpy.calls.mostRecent().args[0]).toEqual({key: testData[key]});
expect(spy.calls.mostRecent().args[0]).toEqual({key: key});
expect(cbSpy.calls.count()).toEqual(1);
expect(spy.calls.count()).toEqual(1);
cbSpy.calls.reset();
spy.calls.reset();
}
});
it('should decode a newly created path on createWriteStream\'s callback', function() {
var supernewPath = '/supernewpath/supernewpath.tgz';
var cbSpy = spyOn(mockBlobStore, 'createWriteStream').and.callFake(function(opts, cb) {
return cb({
key: '/s' + supernewPath
});
});
var spy = jasmine.createSpy('spy');
var blobstore = require('../index');
blobstore.createWriteStream({}, spy);
expect(cbSpy.calls.mostRecent().args[0]).toEqual({});
expect(spy.calls.mostRecent().args[0]).toEqual({key: supernewPath});
expect(cbSpy.calls.count()).toEqual(1);
expect(spy.calls.count()).toEqual(1);
cbSpy.calls.reset();
spy.calls.reset();
});
it('should not decode anything if createWriteStream does not create a new path', function() {
var cbSpy = spyOn(mockBlobStore, 'createWriteStream').and.callFake(function(opts, cb) {
return cb({});
});
var spy = jasmine.createSpy('spy');
var blobstore = require('../index');
blobstore.createWriteStream({}, spy);
expect(cbSpy.calls.mostRecent().args[0]).toEqual({});
expect(spy.calls.mostRecent().args[0]).toEqual({});
expect(cbSpy.calls.count()).toEqual(1);
expect(spy.calls.count()).toEqual(1);
cbSpy.calls.reset();
spy.calls.reset();
});
it('should rewrite the path on createReadStream', function() {
var spy = spyOn(mockBlobStore, 'createReadStream').and.callThrough();
var blobstore = require('../index');
for (var key in testData) {
if (!testData.hasOwnProperty(key)) {
continue;
}
blobstore.createReadStream(key);
expect(spy.calls.mostRecent().args[0]).toEqual(testData[key]);
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
blobstore.createReadStream({key: key});
expect(spy.calls.mostRecent().args[0]).toEqual({key: testData[key]});
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
}
});
it('should rewrite the path on exists', function() {
var spy = spyOn(mockBlobStore, 'exists').and.callThrough();
var blobstore = require('../index');
for (var key in testData) {
if (!testData.hasOwnProperty(key)) {
continue;
}
blobstore.exists(key);
expect(spy.calls.mostRecent().args[0]).toEqual(testData[key]);
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
blobstore.exists({key: key});
expect(spy.calls.mostRecent().args[0]).toEqual({key: testData[key]});
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
}
});
it('should rewrite the path on remove', function() {
var spy = spyOn(mockBlobStore, 'remove').and.callThrough();
var blobstore = require('../index');
for (var key in testData) {
if (!testData.hasOwnProperty(key)) {
continue;
}
blobstore.remove(key);
expect(spy.calls.mostRecent().args[0]).toEqual(testData[key]);
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
blobstore.remove({key: key});
expect(spy.calls.mostRecent().args[0]).toEqual({key: testData[key]});
expect(spy.calls.count()).toEqual(1);
spy.calls.reset();
}
});
});
})();

64
spec/lib/args.js Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2016 Hewlett Packard Enterprise Development Company, LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
var argsLibPath = '../../lib/args';
describe('args', function() {
var actualArgs;
beforeEach(function(done) {
// Store argv so we can modify it in our tests.
actualArgs = process.argv;
done();
});
afterEach(function(done) {
// Reset the old argv.
process.argv = actualArgs;
// Delete the cached entry so we reparse with new args.
delete require.cache[require.resolve(argsLibPath)];
done();
});
it('should accept the --dir flag', function(done) {
process.argv = [
'node',
'asdfasda',
'--dir',
'./foo'
];
var args = require(argsLibPath);
expect(args.dir).toBe('./foo');
done();
});
it('should accept the --o flag', function(done) {
process.argv = [
'node',
'asdfasda',
'-o',
'./bar'
];
var args = require(argsLibPath);
expect(args.o).toBe('./bar');
expect(args.dir).toBe('./bar');
done();
});
});
})();