Skip to content

Commit

Permalink
Added full unit-testing of the chunked-upload-routes library and fixe…
Browse files Browse the repository at this point in the history
…d some bugs that came out of that venture
  • Loading branch information
supernomad committed Jun 20, 2015
1 parent 2175455 commit 2bfc617
Show file tree
Hide file tree
Showing 5 changed files with 392 additions and 22 deletions.
7 changes: 4 additions & 3 deletions libs/models/errorModels.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
function GenericError(code, error, message) {
var self = this;
self.Code = code;
self.Error = error;
self.Message = message;
}

function missingCacheItem() {
this = new GenericError(404, "Missing Upload Error", "The upload specified could not be found, please check the supplied id and try again.");
return new GenericError(404, "Missing Upload Error", "The upload specified could not be found, please check the supplied id and try again.");
}

function serverError() {
this = new GenericError(500, "Internal Server Error", "There has been an internal server error, so things are basically blowing up in our datacenter. We will get back to you in a minute but go ahead and try again.");
return new GenericError(500, "Internal Server Error", "There has been an internal server error, so things are basically blowing up in our datacenter. We will get back to you in a minute but go ahead and try again.");
}

function validationError(msg) {
this = new GenericError(400, "Validation Error", msg);
return new GenericError(400, "Validation Error", msg);
}

module.exports = {
Expand Down
38 changes: 38 additions & 0 deletions mocks/libs/caching/localCache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
var typeHelper = require.main.require('libs/helpers/typeHelper'),
cache = {};
function create(key, val, ttl, callback) {
cache[key] = val;
if(typeHelper.isFunction(callback)) {
callback(null, true);
} else {
return true;
}
}

function restore(key, callback) {
if(typeHelper.isFunction(callback)) {
callback(null, {key: key, value: cache[key]});
} else {
return {key: key, value: cache[key]};
}
}

function update(key, val, ttl, callback) {
return create(key, val, ttl, callback);
}

function del(key, callback) {
delete cache[key];
if(typeHelper.isFunction(callback)) {
callback(null, 1);
} else {
return 1;
}
}

module.exports = {
"create": create,
"restore": restore,
"update": update,
"delete": del
};
41 changes: 41 additions & 0 deletions mocks/libs/io.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* global Buffer */
var fs = require('fs');

function getFileStats(path, callback) {
// TODO get temp stats object
callback(null, {});
}

function createFile(path, buffer, offset, length, callback) {
callback(null);
}

function writeFileChunk(path, buffer, offset, length, position, callback) {
callback(null);
}

function deleteFile(path, callback) {
callback(null);
}

function readFile(path, callback) {
callback(null, new Buffer(0));
}

function readFileChunk(path, buffer, offset, length, position, callback) {
callback(null, 0, new Buffer(0));
}

function renameFile(path, newPath, callback) {
callback(null);
}

module.exports = {
GetFileStats: getFileStats,
CreateFile: createFile,
WriteFileChunk: writeFileChunk,
DeleteFile: deleteFile,
ReadFile: readFile,
ReadFileChunk: readFileChunk,
RenameFile: renameFile
};
37 changes: 20 additions & 17 deletions routes/chunked-upload-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ var debug = false,
var routes = {
"get": new apiModels.RouteHandler(routePrefix + "/:uploadId", function (req, res) {
if (!guidHelper.isGuid(req.params.uploadId)){
throw new errorModels.ValidationError("The supplied uploadId is not a valid v4 GUID");
throw errorModels.ValidationError("The supplied uploadId is not a valid v4 GUID");
}

dataCache.restore(req.params.uploadId, function name(error, upload) {
errorHelper.genericErrorHandler(error, debug);
if(typeHelper.doesExist(upload)){
res.json(new apiModels.ApiResponse(routePrefix, {}, upload.value));
} else {
throw new errorModels.MissingCacheItem();
throw errorModels.MissingCacheItem();
}
});
}),
"post": new apiModels.RouteHandler(routePrefix, function (req, res) {
var valid = validators.validateUploadRequest(req.body);
if(valid !== validators.valid) {
throw new errorModels.ValidationError(valid);
throw errorModels.ValidationError(valid);
}

var upload = new apiModels.Upload(req.body);
Expand All @@ -47,24 +47,25 @@ var routes = {
res.json(new apiModels.ApiResponse(routePrefix, {}, upload.id));
});
} else {
throw new errorModels.ServerError();
throw errorModels.ServerError();
}
});
}),
"put": new apiModels.RouteHandler(routePrefix + "/:uploadId/:index", function (req, res) {
var valid = validators.validateChunkRequest(req);
var index = parseInt(req.params.index);
if(valid !== validators.valid) {
throw new errorModels.ValidationError(valid);
throw errorModels.ValidationError(valid);
} else if (!guidHelper.isGuid(req.params.uploadId)){
throw new errorModels.ValidationError("The supplied uploadId is not a valid v4 GUID");
throw errorModels.ValidationError("The supplied uploadId is not a valid v4 GUID");
} else if (!typeHelper.isNumber(index)) {
throw new errorModels.ValidationError("The supplied index is not a valid number");
throw errorModels.ValidationError("The supplied index is not a valid number");
}

dataCache.restore(req.params.uploadId, function(error, upload) {
dataCache.restore(req.params.uploadId, function(error, keyVal) {
errorHelper.genericErrorHandler(error, debug);
var file = {};
var upload = keyVal.value;
for (var key in req.files) {
if (req.files.hasOwnProperty(key)) {
file = req.files[key];
Expand All @@ -91,48 +92,50 @@ var routes = {

function renameCallback(error) {
errorHelper.genericErrorHandler(error, debug);
dataCache.remove(upload.id, function(error, count) {
dataCache.delete(upload.id, function(error, count) {
errorHelper.genericErrorHandler(error, debug);
});
res.json(new apiModels.ApiResponse(routePrefix, {}, "Chunk Recieved"));

res.json(new apiModels.ApiResponse(routePrefix, {}, "Upload Complete"));
};

if(upload) {
upload.chunks[index] = true;
dataCache.update(upload.Id, upload, function(error, success) {
dataCache.update(upload.Id, upload, defaultTtl, function(error, success) {
errorHelper.genericErrorHandler(error, debug);

if(success) {
io.ReadFile(file.path, readCallback);
} else {
throw new errorModels.ServerError();
throw errorModels.ServerError();
}
});
} else {
throw new errorModels.MissingCacheItem();
throw errorModels.MissingCacheItem();
}
});
}),
"delete": new apiModels.RouteHandler(routePrefix + "/:uploadId", function (req, res) {
if (!guidHelper.isGuid(req.params.uploadId)){
throw new errorModels.ValidationError("The supplied uploadId is not a valid v4 GUID");
throw errorModels.ValidationError("The supplied uploadId is not a valid v4 GUID");
}

dataCache.restore(req.params.uploadId, function name(error, upload) {
errorHelper.genericErrorHandler(error, debug);
if(typeHelper.doesExist(upload)){
dataCache.remove(upload.id, function (error, count) {
dataCache.delete(upload.id, function (error, count) {
errorHelper.genericErrorHandler(error);
if(count === 1) {
io.DeleteFile(upload.tempPath, function(deleteError) {
errorHelper.genericErrorHandler(deleteError);
res.json(new apiModels.ApiResponse(routePrefix, {}, "Upload: " + req.params.uploadId + ", deleted successfuly."));
});
} else {
throw new errorModels.MissingCacheItem();
throw errorModels.MissingCacheItem();
}
});
} else {
throw new errorModels.MissingCacheItem();
throw errorModels.MissingCacheItem();
}
});
}),
Expand Down
Loading

0 comments on commit 2bfc617

Please sign in to comment.