Stat implementation, updated tests.

This commit is contained in:
Alan Kligman 2013-07-12 11:11:05 -04:00
parent 19b21e10de
commit c3c9751ff4
5 changed files with 960 additions and 435 deletions

1096
dist/idbfs.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -18,15 +18,25 @@ require.config({
require(["src/file-system"], function(IDBFS) {
var flags = 'FORMAT';
//var flags = undefined;
//var flags;
var fs = new IDBFS.FileSystem('local', flags);
fs.promise.otherwise(
function(error) {
console.error(error);
}
);
fs.stat('/', function(error, result) {
console.log('stat /', error, result);
});
fs.stat('/tmp', function(error, result) {
console.log('stat /tmp', error, result);
});
/*
fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.stat('/tmp', function(error, result) {
console.log('stat /tmp', error, result);
});
});
*/
/*
function make_tmp_directory() {
return fs.mkdir('/tmp');
};
@ -69,7 +79,7 @@ fs.promise.then(make_tmp_directory)
.then(write_data)
.then(function() { console.log('done'); })
.otherwise(function(error) { console.error(error, error.message, error.stack); });
*/
});
</script>
</html>

View File

@ -91,6 +91,13 @@ define(function(require) {
EIO.prototype.name = "EIO";
EIO.prototype.constructor = EIO;
function EFileSystemError(message){
this.message = message || '';
};
EFileSystemError.prototype = new Error();
EFileSystemError.prototype.name = "EFileSystemError";
EFileSystemError.prototype.constructor = EFileSystemError;
return {
EExists: EExists,
EIsDirectory: EIsDirectory,

View File

@ -24,6 +24,7 @@ define(function(require) {
var ENotMounted = require('src/error').ENotMounted;
var EInvalid = require('src/error').EInvalid;
var EIO = require('src/error').EIO;
var EFileSystemError = require('src/error').EFileSystemError;
var FS_FORMAT = require('src/constants').FS_FORMAT;
var MODE_FILE = require('src/constants').MODE_FILE;
@ -34,7 +35,7 @@ define(function(require) {
var IDB_RO = require('src/constants').IDB_RO;
var FILE_STORE_NAME = require('src/constants').FILE_STORE_NAME;
var METADATA_STORE_NAME = require('src/constants').METADATA_STORE_NAME;
var FS_READY = require('src/constants').READY;
var FS_READY = require('src/constants').FS_READY;
var FS_PENDING = require('src/constants').FS_PENDING;
var FS_ERROR = require('src/constants').FS_ERROR;
var O_READ = require('src/constants').O_READ;
@ -81,7 +82,9 @@ define(function(require) {
this.xattrs = xattrs || {}; // extended attributes
this.nlinks = nlinks || 0; // links count
this.version = version || 0; // node version
this.data = hash(guid()) // id for data object
this.blksize = undefined; // block size
this.nblocks = 1; // blocks count
this.data = hash(guid()); // id for data object
};
/*
@ -96,6 +99,7 @@ define(function(require) {
return callback(new ENoEntry('path is an empty string'));
}
var name = basename(path);
var parentPath = dirname(path);
if(ROOT_DIRECTORY_NAME == name) {
function check_root_directory_node(error, rootDirectoryNode) {
@ -137,7 +141,6 @@ define(function(require) {
}
};
var parentPath = dirname(path);
find_node(objectStore, parentPath, read_parent_directory_data);
}
};
@ -538,6 +541,22 @@ define(function(require) {
};
};
function stat_file(objectStore, path, callback) {
path = normalize(path);
var name = basename(path);
var parentPath = dirname(path);
find_node(objectStore, path, check_file);
function check_file(error, result) {
if(error) {
callback(error);
} else {
callback(undefined, result);
}
};
};
/*
* FileSystem
*/
@ -606,6 +625,7 @@ define(function(require) {
this.db = null;
this.nextDescriptor = nextDescriptor;
this.openFiles = openFiles;
this.name = name;
};
FileSystem.prototype._allocate_descriptor = function _allocate_descriptor(openFileDescription) {
var fd = this.nextDescriptor ++;
@ -615,7 +635,7 @@ define(function(require) {
FileSystem.prototype._release_descriptor = function _release_descriptor(fd) {
delete this.openFiles[fd];
};
FileSystem.prototype.open = function open(path, flags) {
FileSystem.prototype.open = function open(path, flags, callback) {
var that = this;
var deferred = when.defer();
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
@ -644,11 +664,11 @@ define(function(require) {
flags = O_FLAGS[flags];
}
open_file(this, files, path, flags, check_result);
return deferred.promise;
open_file(this, files, path, flags, check_result);
deferred.then(callback);
};
FileSystem.prototype.close = function close(fd) {
FileSystem.prototype.close = function close(fd, callback) {
var deferred = when.defer();
if(!_(this.openFiles).has(fd)) {
@ -658,26 +678,41 @@ define(function(require) {
deferred.resolve();
}
return deferred.promise;
deferred.then(callback);
};
FileSystem.prototype.mkdir = function mkdir(path) {
var deferred = when.defer();
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
var files = transaction.objectStore(FILE_STORE_NAME);
FileSystem.prototype.mkdir = function mkdir(path, callback) {
var that = this;
this.promise.then(
function() {
var deferred = when.defer();
var transaction = that.db.transaction([FILE_STORE_NAME], IDB_RW);
var files = transaction.objectStore(FILE_STORE_NAME);
function check_result(error) {
if(error) {
// if(transaction.error) transaction.abort();
deferred.reject(error);
} else {
deferred.resolve();
function check_result(error) {
if(error) {
// if(transaction.error) transaction.abort();
deferred.reject(error);
} else {
deferred.resolve();
}
};
make_directory(files, path, check_result);
deferred.promise.then(
function() {
callback();
},
function(error) {
callback(error);
}
);
},
function() {
callback(new EFileSystemError('unknown error'));
}
};
make_directory(files, path, check_result);
return deferred.promise;
);
};
FileSystem.prototype.rmdir = function rmdir(path) {
FileSystem.prototype.rmdir = function rmdir(path, callback) {
var deferred = when.defer();
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
var files = transaction.objectStore(FILE_STORE_NAME);
@ -692,27 +727,66 @@ define(function(require) {
};
remove_directory(files, path, check_result);
return deferred.promise;
deferred.then(callback);
};
FileSystem.prototype.stat = function stat(path) {
FileSystem.prototype.readdir = function readdir(path, callback) {
};
FileSystem.prototype.fstat = function fstat(fd) {
FileSystem.prototype.stat = function stat(path, callback) {
var that = this;
this.promise.then(
function() {
var deferred = when.defer();
var transaction = that.db.transaction([FILE_STORE_NAME], IDB_RW);
var files = transaction.objectStore(FILE_STORE_NAME);
function check_result(error, result) {
if(error) {
// if(transaction.error) transaction.abort();
deferred.reject(error);
} else {
var stats = {
dev: that.name,
nlinks: result.nlinks,
atime: result.atime,
mtime: result.mtime,
ctime: result.ctime
};
deferred.resolve(stats);
}
};
stat_file(files, path, check_result);
deferred.promise.then(
function(result) {
callback(undefined, result);
},
function(error) {
callback(error);
}
);
},
function() {
callback(new EFileSystemError('unknown error'));
}
);
};
FileSystem.prototype.fstat = function fstat(fd, callback) {
};
FileSystem.prototype.link = function link(oldpath, newpath) {
FileSystem.prototype.link = function link(oldpath, newpath, callback) {
};
FileSystem.prototype.unlink = function unlink(path) {
FileSystem.prototype.unlink = function unlink(path, callback) {
};
FileSystem.prototype.getxattr = function getxattr(path, name) {
FileSystem.prototype.getxattr = function getxattr(path, name, callback) {
};
FileSystem.prototype.setxattr = function setxattr(path, name, value) {
FileSystem.prototype.setxattr = function setxattr(path, name, value, callback) {
};
FileSystem.prototype.read = function read(fd, buffer, offset, length, position) {
FileSystem.prototype.read = function read(fd, buffer, offset, length, position, callback) {
var deferred = when.defer();
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
var files = transaction.objectStore(FILE_STORE_NAME);
@ -722,6 +796,7 @@ define(function(require) {
function check_result(error, nbytes) {
if(error) {
// if(transaction.error) transaction.abort();
deferred.reject(error);
} else {
deferred.resolve(nbytes);
@ -742,7 +817,7 @@ define(function(require) {
return deferred.promise;
};
FileSystem.prototype.write = function write(fd, buffer, offset, length, position) {
FileSystem.prototype.write = function write(fd, buffer, offset, length, position, callback) {
var deferred = when.defer();
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
var files = transaction.objectStore(FILE_STORE_NAME);

View File

@ -1,15 +1,130 @@
var TEST_DATABASE_NAME = 'test';
var DEFAULT_TIMEOUT = 5000;
describe("file system", function() {
beforeEach(function() {
this.fs = new IDBFS.FileSystem(TEST_DATABASE_NAME, 'FORMAT');
var next_id = 1;
function mk_db_name() {
return TEST_DATABASE_NAME + next_id++;
};
describe("IDBFS", function() {
it("is defined", function() {
expect(typeof IDBFS).not.toEqual(undefined);
});
it("has FileSystem constructor", function() {
expect(typeof IDBFS.FileSystem).toEqual('function');
});
});
describe("new fs", function() {
beforeEach(function() {
this.db_name = mk_db_name();
this.fs = new IDBFS.FileSystem(this.db_name, 'FORMAT');
});
afterEach(function() {
indexedDB.deleteDatabase(this.db_name);
delete this.fs;
});
it("is an object", function() {
expect(typeof this.fs).toEqual('object');
});
var api_methods = [
"mkdir",
"rmdir",
"readdir",
"link",
"unlink",
"open",
"close",
"read",
"write",
"setxattr",
"getxattr",
"stat",
"fstat",
];
api_methods.forEach(function(method) {
it("has method " + method, function() {
expect(typeof this.fs[method]).toEqual('function');
});
});
it('should have a root directory', function() {
var complete = false;
var _error, _result;
this.fs.stat('/', function(error, result) {
_error = error;
_result = result;
complete = true;
});
afterEach(function() {
indexedDB.deleteDatabase(TEST_DATABASE_NAME);
waitsFor(function() {
return complete;
}, 'stat to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_result).toBeDefined();
});
});
});
describe('stat', function() {
beforeEach(function() {
this.db_name = mk_db_name();
this.fs = new IDBFS.FileSystem(this.db_name, 'FORMAT');
});
afterEach(function() {
indexedDB.deleteDatabase(this.db_name);
delete this.fs;
});
describe('on path that does not exist', function() {
it('should return an error', function() {
var complete = false;
var _error, _result;
this.fs.stat('/tmp', function(error, result) {
_error = error;
_result = result;
complete = true;
});
waitsFor(function() {
return complete;
}, 'stat to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_error).toBeDefined();
});
});
it("is created", function() {
expect(typeof this.fs).toEqual('object');
it('should not return a result', function() {
var complete = false;
var _error, _result;
this.fs.stat('/tmp', function(error, result) {
jasmine.log(error, result);
_error = error;
_result = result;
complete = true;
});
waitsFor(function() {
return complete;
}, 'stat to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_result).not.toBeDefined();
});
});
});
});