Merge pull request #198 from humphd/browserify

Fixes #56
This commit is contained in:
Alan K 2014-05-27 14:35:56 -04:00
commit c9a968b009
104 changed files with 8132 additions and 21388 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ node_modules
bower_components bower_components
.env .env
*~ *~
dist/filer-test.js

View File

@ -1,6 +1,6 @@
language: node_js language: node_js
node_js: node_js:
- "0.11" - "0.10"
before_install: npm install -g grunt-cli before_install: npm install -g grunt-cli
notifications: notifications:
email: false email: false

View File

@ -21,7 +21,8 @@ You can now run the following grunt tasks:
* `grunt check` will run [JSHint](http://www.jshint.com/) on your code (do this before submitting a pull request) to catch errors * `grunt check` will run [JSHint](http://www.jshint.com/) on your code (do this before submitting a pull request) to catch errors
* `grunt develop` will create a single file version of the library for testing in `dist/idbfs.js` * `grunt develop` will create a single file version of the library for testing in `dist/idbfs.js`
* `grunt release` like `develop` but will also create a minified version of the library in `dist/idbfs.min.js` * `grunt release` like `develop` but will also create a minified version of the library in `dist/idbfs.min.js`
* `grunt test` will run [JSHint](http://www.jshint.com/) on your code and the test suite in [PhantomJS](http://phantomjs.org/) * `grunt test` or `grunt test-node` will run [JSHint](http://www.jshint.com/) on your code and the test suite in the context of `nodejs`
* `grunt test-browser` will run [JSHint](http://www.jshint.com/) and start a localhost server on port `1234`. Navigating to `localhost:1234/tests/index.html` will run the test suite in the context of the browser. **NOTE:** When finished, you will have to manually shut off the server by pressing `cmd/ctrl`+`c` in the same terminal session you ran `grunt test-browser`.
Once you've done some hacking and you'd like to have your work merged, you'll need to Once you've done some hacking and you'd like to have your work merged, you'll need to
make a pull request. If you're patch includes code, make sure to check that all the make a pull request. If you're patch includes code, make sure to check that all the
@ -31,13 +32,11 @@ to the `AUTHORS` file.
======= =======
### Releasing a new version ### Releasing a new version
======= =======
### Releasing a new version
**NOTE:** This step should only ever be attempted by the owner of the repo (@modeswitch).
`grunt publish` will: `grunt publish` will:
* Run the `grunt release` task * Run the `grunt release` task
* Bump `bower.json` & `package.json` version numbers according to a [Semver](http://semver.org/) compatible scheme (see "How to Publish" below) * Bump `bower.json` & `package.json` version numbers according to a [Semver](http://semver.org/) compatible scheme (see ["How to Publish"](#how-to-publish) below)
* Create a git tag at the new version number * Create a git tag at the new version number
* Create a release commit including `dist/filer.js`, `dist/filer.min.js`, `bower.json` and `package.json` * Create a release commit including `dist/filer.js`, `dist/filer.min.js`, `bower.json` and `package.json`
* Push tag & commit to `origin/develop` * Push tag & commit to `origin/develop`
@ -63,14 +62,14 @@ The user *must* be on their local `develop` branch before running any form of `g
## Tests ## Tests
Tests are writting using [Mocha](http://visionmedia.github.io/mocha/) and [Chai](http://chaijs.com/api/bdd/). Tests are writting using [Mocha](http://visionmedia.github.io/mocha/) and [Chai](http://chaijs.com/api/bdd/).
You can run the tests in your browser by opening the `tests` directory. You can also run them You can run the tests in your browser by running `grunt test-browser` and opening the `tests` directory @ `http://localhost:1234/tests`, or in a nodejs context by running `grunt test`.
[here](http://js-platform.github.io/filer/tests/).
There are a number of configurable options for the test suite, which are set via query string params. There are a number of configurable options for the test suite, which are set via query string params.
First, you can choose which filer source to use (i.e., src/, dist/filer.js or dist/filer.min.js). First, you can choose which filer source to use (i.e., src/, dist/filer-test.js, dist/filer.js or dist/filer.min.js).
The default is to use what is in /src, and you can switch to built versions like so: The default is to use what is in /dist/filer-test.js, and you can switch to other versions like so:
* tests/index.html?filer-dist/filer.js * tests/index.html?filer-dist/filer.js
* tests/index.html?filer-dist/filer.min.js * tests/index.html?filer-dist/filer.min.js
* tests/index.html?filer-src/filer.js (from src)
Second, you can specify which provider to use for all non-provider specific tests (i.e., most of the tests). Second, you can specify which provider to use for all non-provider specific tests (i.e., most of the tests).
The default provider is `Memory`, and you can switch it like so: The default provider is `Memory`, and you can switch it like so:

View File

@ -161,33 +161,6 @@ if( Filer.FileSystem.providers.WebSQL.isSupported() ) {
You can also write your own provider if you need a different backend. See the code in `src/providers` for details. You can also write your own provider if you need a different backend. See the code in `src/providers` for details.
####Filer.FileSystem.adapters - Adapters for Storage Providers
Filer based file systems can acquire new functionality by using adapters. These wrapper objects extend the abilities
of storage providers without altering them in anway. An adapter can be used with any provider, and multiple
adapters can be used together in order to compose complex functionality on top of a provider.
There are currently 2 adapters available:
* `FileSystem.adapters.Compression(provider)` - a compression adapter that uses [Zlib](https://github.com/imaya/zlib.js)
* `FileSystem.adapters.Encryption(passphrase, provider)` - an encryption adapter that uses [AES encryption](http://code.google.com/p/crypto-js/#AES)
```javascript
var FileSystem = Filer.FileSystem;
var providers = FileSystem.providers;
var adapters = FileSystem.adapters;
// Create a WebSQL-based, Encrypted, Compressed File System by
// composing a provider and adatpers.
var webSQLProvider = new providers.WebSQL();
var encryptionAdatper = new adapters.Encryption('super-secret-passphrase', webSQLProvider);
var compressionAdatper = new adatpers.Compression(encryptionAdapter);
var fs = new FileSystem({ provider: compressionAdapter });
```
You can also write your own adapter if you need to add new capabilities to the providers. Adapters share the same
interface as providers. See the code in `src/providers` and `src/adapters` for many examples.
####Filer.Path<a name="FilerPath"></a> ####Filer.Path<a name="FilerPath"></a>
The node.js [path module](http://nodejs.org/api/path.html) is available via the `Filer.Path` object. It is The node.js [path module](http://nodejs.org/api/path.html) is available via the `Filer.Path` object. It is

View File

@ -1,405 +0,0 @@
/**
* almond 0.2.5 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/almond for details
*/
//Going sloppy to avoid 'use strict' string cost, but strict practices should
//be followed.
/*jslint sloppy: true */
/*global setTimeout: false */
var requirejs, require, define;
(function (undef) {
var main, req, makeMap, handlers,
defined = {},
waiting = {},
config = {},
defining = {},
hasOwn = Object.prototype.hasOwnProperty,
aps = [].slice;
function hasProp(obj, prop) {
return hasOwn.call(obj, prop);
}
/**
* Given a relative module name, like ./something, normalize it to
* a real name that can be mapped to a path.
* @param {String} name the relative name
* @param {String} baseName a real name that the name arg is relative
* to.
* @returns {String} normalized name
*/
function normalize(name, baseName) {
var nameParts, nameSegment, mapValue, foundMap,
foundI, foundStarMap, starI, i, j, part,
baseParts = baseName && baseName.split("/"),
map = config.map,
starMap = (map && map['*']) || {};
//Adjust any relative paths.
if (name && name.charAt(0) === ".") {
//If have a base name, try to normalize against it,
//otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end.
if (baseName) {
//Convert baseName to array, and lop off the last part,
//so that . matches that "directory" and not name of the baseName's
//module. For instance, baseName of "one/two/three", maps to
//"one/two/three.js", but we want the directory, "one/two" for
//this normalization.
baseParts = baseParts.slice(0, baseParts.length - 1);
name = baseParts.concat(name.split("/"));
//start trimDots
for (i = 0; i < name.length; i += 1) {
part = name[i];
if (part === ".") {
name.splice(i, 1);
i -= 1;
} else if (part === "..") {
if (i === 1 && (name[2] === '..' || name[0] === '..')) {
//End of the line. Keep at least one non-dot
//path segment at the front so it can be mapped
//correctly to disk. Otherwise, there is likely
//no path mapping for a path starting with '..'.
//This can still fail, but catches the most reasonable
//uses of ..
break;
} else if (i > 0) {
name.splice(i - 1, 2);
i -= 2;
}
}
}
//end trimDots
name = name.join("/");
} else if (name.indexOf('./') === 0) {
// No baseName, so this is ID is resolved relative
// to baseUrl, pull off the leading dot.
name = name.substring(2);
}
}
//Apply map config if available.
if ((baseParts || starMap) && map) {
nameParts = name.split('/');
for (i = nameParts.length; i > 0; i -= 1) {
nameSegment = nameParts.slice(0, i).join("/");
if (baseParts) {
//Find the longest baseName segment match in the config.
//So, do joins on the biggest to smallest lengths of baseParts.
for (j = baseParts.length; j > 0; j -= 1) {
mapValue = map[baseParts.slice(0, j).join('/')];
//baseName segment has config, find if it has one for
//this name.
if (mapValue) {
mapValue = mapValue[nameSegment];
if (mapValue) {
//Match, update name to the new value.
foundMap = mapValue;
foundI = i;
break;
}
}
}
}
if (foundMap) {
break;
}
//Check for a star map match, but just hold on to it,
//if there is a shorter segment match later in a matching
//config, then favor over this star map.
if (!foundStarMap && starMap && starMap[nameSegment]) {
foundStarMap = starMap[nameSegment];
starI = i;
}
}
if (!foundMap && foundStarMap) {
foundMap = foundStarMap;
foundI = starI;
}
if (foundMap) {
nameParts.splice(0, foundI, foundMap);
name = nameParts.join('/');
}
}
return name;
}
function makeRequire(relName, forceSync) {
return function () {
//A version of a require function that passes a moduleName
//value for items that may need to
//look up paths relative to the moduleName
return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));
};
}
function makeNormalize(relName) {
return function (name) {
return normalize(name, relName);
};
}
function makeLoad(depName) {
return function (value) {
defined[depName] = value;
};
}
function callDep(name) {
if (hasProp(waiting, name)) {
var args = waiting[name];
delete waiting[name];
defining[name] = true;
main.apply(undef, args);
}
if (!hasProp(defined, name) && !hasProp(defining, name)) {
throw new Error('No ' + name);
}
return defined[name];
}
//Turns a plugin!resource to [plugin, resource]
//with the plugin being undefined if the name
//did not have a plugin prefix.
function splitPrefix(name) {
var prefix,
index = name ? name.indexOf('!') : -1;
if (index > -1) {
prefix = name.substring(0, index);
name = name.substring(index + 1, name.length);
}
return [prefix, name];
}
/**
* Makes a name map, normalizing the name, and using a plugin
* for normalization if necessary. Grabs a ref to plugin
* too, as an optimization.
*/
makeMap = function (name, relName) {
var plugin,
parts = splitPrefix(name),
prefix = parts[0];
name = parts[1];
if (prefix) {
prefix = normalize(prefix, relName);
plugin = callDep(prefix);
}
//Normalize according
if (prefix) {
if (plugin && plugin.normalize) {
name = plugin.normalize(name, makeNormalize(relName));
} else {
name = normalize(name, relName);
}
} else {
name = normalize(name, relName);
parts = splitPrefix(name);
prefix = parts[0];
name = parts[1];
if (prefix) {
plugin = callDep(prefix);
}
}
//Using ridiculous property names for space reasons
return {
f: prefix ? prefix + '!' + name : name, //fullName
n: name,
pr: prefix,
p: plugin
};
};
function makeConfig(name) {
return function () {
return (config && config.config && config.config[name]) || {};
};
}
handlers = {
require: function (name) {
return makeRequire(name);
},
exports: function (name) {
var e = defined[name];
if (typeof e !== 'undefined') {
return e;
} else {
return (defined[name] = {});
}
},
module: function (name) {
return {
id: name,
uri: '',
exports: defined[name],
config: makeConfig(name)
};
}
};
main = function (name, deps, callback, relName) {
var cjsModule, depName, ret, map, i,
args = [],
usingExports;
//Use name if no relName
relName = relName || name;
//Call the callback to define the module, if necessary.
if (typeof callback === 'function') {
//Pull out the defined dependencies and pass the ordered
//values to the callback.
//Default to [require, exports, module] if no deps
deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
for (i = 0; i < deps.length; i += 1) {
map = makeMap(deps[i], relName);
depName = map.f;
//Fast path CommonJS standard dependencies.
if (depName === "require") {
args[i] = handlers.require(name);
} else if (depName === "exports") {
//CommonJS module spec 1.1
args[i] = handlers.exports(name);
usingExports = true;
} else if (depName === "module") {
//CommonJS module spec 1.1
cjsModule = args[i] = handlers.module(name);
} else if (hasProp(defined, depName) ||
hasProp(waiting, depName) ||
hasProp(defining, depName)) {
args[i] = callDep(depName);
} else if (map.p) {
map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
args[i] = defined[depName];
} else {
throw new Error(name + ' missing ' + depName);
}
}
ret = callback.apply(defined[name], args);
if (name) {
//If setting exports via "module" is in play,
//favor that over return value and exports. After that,
//favor a non-undefined return value over exports use.
if (cjsModule && cjsModule.exports !== undef &&
cjsModule.exports !== defined[name]) {
defined[name] = cjsModule.exports;
} else if (ret !== undef || !usingExports) {
//Use the return value from the function.
defined[name] = ret;
}
}
} else if (name) {
//May just be an object definition for the module. Only
//worry about defining if have a module name.
defined[name] = callback;
}
};
requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
if (typeof deps === "string") {
if (handlers[deps]) {
//callback in this case is really relName
return handlers[deps](callback);
}
//Just return the module wanted. In this scenario, the
//deps arg is the module name, and second arg (if passed)
//is just the relName.
//Normalize module name, if it contains . or ..
return callDep(makeMap(deps, callback).f);
} else if (!deps.splice) {
//deps is a config object, not an array.
config = deps;
if (callback.splice) {
//callback is an array, which means it is a dependency list.
//Adjust args if there are dependencies
deps = callback;
callback = relName;
relName = null;
} else {
deps = undef;
}
}
//Support require(['a'])
callback = callback || function () {};
//If relName is a function, it is an errback handler,
//so remove it.
if (typeof relName === 'function') {
relName = forceSync;
forceSync = alt;
}
//Simulate async callback;
if (forceSync) {
main(undef, deps, callback, relName);
} else {
//Using a non-zero value because of concern for what old browsers
//do, and latest browsers "upgrade" to 4 if lower value is used:
//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
//If want a value immediately, use require('id') instead -- something
//that works in almond on the global level, but not guaranteed and
//unlikely to work in other AMD implementations.
setTimeout(function () {
main(undef, deps, callback, relName);
}, 4);
}
return req;
};
/**
* Just drops the config on the floor, but returns req in case
* the config return value is used.
*/
req.config = function (cfg) {
config = cfg;
if (config.deps) {
req(config.deps, config.callback);
}
return req;
};
define = function (name, deps, callback) {
//This module may not have dependencies
if (!deps.splice) {
//deps is not an array, so probably means
//an object literal or factory function for
//the value. Adjust args.
callback = deps;
deps = [];
}
if (!hasProp(defined, name) && !hasProp(waiting, name)) {
waiting[name] = [name, deps, callback];
}
};
define.amd = {
jQuery: true
};
}());

View File

@ -1,7 +0,0 @@
var Filer = require( "src/index" );
return Filer;
}));

View File

@ -1,27 +0,0 @@
/*
Copyright (c) 2013, Alan Kligman
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the Mozilla Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function( root, factory ) {
if ( typeof exports === "object" ) {
// Node
module.exports = factory();
} else if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define( factory );
} else if( !root.Filer ) {
// Browser globals
root.Filer = factory();
}
}( this, function() {

8560
dist/filer.js vendored

File diff suppressed because it is too large Load Diff

6
dist/filer.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ module.exports = function(grunt) {
grunt.initConfig({ grunt.initConfig({
pkg: grunt.file.readJSON('package.json'), pkg: grunt.file.readJSON('package.json'),
clean: ['dist/'], clean: ['dist/filer-test.js', 'dist/filer_node-test.js'],
uglify: { uglify: {
options: { options: {
@ -51,49 +51,31 @@ module.exports = function(grunt) {
] ]
}, },
connect: { browserify: {
server: { filerDist: {
src: "./src/index.js",
dest: "./dist/filer.js",
options: { options: {
port: 9001, standalone: 'Filer',
hostname: '127.0.0.1', browserifyOptions: {
base: '.' builtins: false,
commondir: false
},
exclude: ["./node_modules/request/index.js"]
}
},
filerTest: {
src: "./tests/index.js",
dest: "./dist/filer-test.js",
options: {
standalone: 'FilerTest'
} }
} }
}, },
mocha: { shell: {
test: { mocha: {
options: { command: './node_modules/.bin/mocha --reporter list tests/index.js'
log: true,
urls: [ 'http://127.0.0.1:9001/tests/index.html' ]
}
}
},
requirejs: {
develop: {
options: {
paths: {
"src": "../src",
"build": "../build"
},
baseUrl: "lib",
name: "build/almond",
include: ["src/index"],
out: "dist/filer.js",
optimize: "none",
wrap: {
startFile: 'build/wrap.start',
endFile: 'build/wrap.end'
},
shim: {
// TextEncoder and TextDecoder shims. encoding-indexes must get loaded first,
// and we use a fake one for reduced size, since we only care about utf8.
"encoding": {
deps: ["encoding-indexes-shim"]
}
}
}
} }
}, },
@ -164,6 +146,21 @@ module.exports = function(grunt) {
remote: GIT_REMOTE, remote: GIT_REMOTE,
branch: 'gh-pages', branch: 'gh-pages',
force: true force: true
},
}
},
connect: {
serverForNode: {
options: {
port: 1234,
base: '.'
}
},
serverForBrowser: {
options: {
port: 1234,
base: '.',
keepalive: true
} }
} }
} }
@ -171,19 +168,19 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mocha');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-bump'); grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-npm'); grunt.loadNpmTasks('grunt-npm');
grunt.loadNpmTasks('grunt-git'); grunt.loadNpmTasks('grunt-git');
grunt.loadNpmTasks('grunt-prompt'); grunt.loadNpmTasks('grunt-prompt');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-browserify');
grunt.registerTask('develop', ['clean', 'requirejs']); grunt.registerTask('develop', ['clean', 'browserify:filerDist']);
grunt.registerTask('build-tests', ['clean', 'browserify:filerTest']);
grunt.registerTask('release', ['develop', 'uglify']); grunt.registerTask('release', ['develop', 'uglify']);
grunt.registerTask('check', ['jshint']);
grunt.registerTask('test', ['check', 'connect', 'mocha']);
grunt.registerTask('publish', 'Publish filer as a new version to NPM, bower and github.', function(patchLevel) { grunt.registerTask('publish', 'Publish filer as a new version to NPM, bower and github.', function(patchLevel) {
var allLevels = ['patch', 'minor', 'major']; var allLevels = ['patch', 'minor', 'major'];
@ -202,10 +199,10 @@ module.exports = function(grunt) {
' to ' + semver.inc(currentVersion, patchLevel).yellow + '?'; ' to ' + semver.inc(currentVersion, patchLevel).yellow + '?';
grunt.config('prompt.confirm.options', promptOpts); grunt.config('prompt.confirm.options', promptOpts);
// TODO: ADD NPM RELEASE
grunt.task.run([ grunt.task.run([
'prompt:confirm', 'prompt:confirm',
'checkBranch', 'checkBranch',
'test-node',
'release', 'release',
'bump:' + patchLevel, 'bump:' + patchLevel,
'gitcheckout:publish', 'gitcheckout:publish',
@ -214,6 +211,9 @@ module.exports = function(grunt) {
'npm-publish' 'npm-publish'
]); ]);
}); });
grunt.registerTask('test-node', ['jshint', 'clean', 'connect:serverForNode', 'shell:mocha']);
grunt.registerTask('test-browser', ['jshint', 'build-tests', 'connect:serverForBrowser']);
grunt.registerTask('test', ['test-node']);
grunt.registerTask('default', ['develop']); grunt.registerTask('default', ['test']);
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +1,71 @@
define(function(require) { // Based on https://github.com/diy/intercom.js/blob/master/lib/events.js
// Copyright 2012 DIY Co Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
// Based on https://github.com/diy/intercom.js/blob/master/lib/events.js function removeItem(item, array) {
// Copyright 2012 DIY Co Apache License, Version 2.0 for (var i = array.length - 1; i >= 0; i--) {
// http://www.apache.org/licenses/LICENSE-2.0 if (array[i] === item) {
array.splice(i, 1);
}
}
return array;
}
function removeItem(item, array) { var EventEmitter = function() {};
for (var i = array.length - 1; i >= 0; i--) {
if (array[i] === item) { EventEmitter.createInterface = function(space) {
array.splice(i, 1); var methods = {};
methods.on = function(name, fn) {
if (typeof this[space] === 'undefined') {
this[space] = {};
}
if (!this[space].hasOwnProperty(name)) {
this[space][name] = [];
}
this[space][name].push(fn);
};
methods.off = function(name, fn) {
if (typeof this[space] === 'undefined') return;
if (this[space].hasOwnProperty(name)) {
removeItem(fn, this[space][name]);
}
};
methods.trigger = function(name) {
if (typeof this[space] !== 'undefined' && this[space].hasOwnProperty(name)) {
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < this[space][name].length; i++) {
this[space][name][i].apply(this[space][name][i], args);
} }
} }
return array;
}
var EventEmitter = function() {};
EventEmitter.createInterface = function(space) {
var methods = {};
methods.on = function(name, fn) {
if (typeof this[space] === 'undefined') {
this[space] = {};
}
if (!this[space].hasOwnProperty(name)) {
this[space][name] = [];
}
this[space][name].push(fn);
};
methods.off = function(name, fn) {
if (typeof this[space] === 'undefined') return;
if (this[space].hasOwnProperty(name)) {
removeItem(fn, this[space][name]);
}
};
methods.trigger = function(name) {
if (typeof this[space] !== 'undefined' && this[space].hasOwnProperty(name)) {
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < this[space][name].length; i++) {
this[space][name][i].apply(this[space][name][i], args);
}
}
};
methods.removeAllListeners = function(name) {
if (typeof this[space] === 'undefined') return;
var self = this;
self[space][name].forEach(function(fn) {
self.off(name, fn);
});
};
return methods;
}; };
var pvt = EventEmitter.createInterface('_handlers'); methods.removeAllListeners = function(name) {
EventEmitter.prototype._on = pvt.on; if (typeof this[space] === 'undefined') return;
EventEmitter.prototype._off = pvt.off; var self = this;
EventEmitter.prototype._trigger = pvt.trigger; self[space][name].forEach(function(fn) {
self.off(name, fn);
var pub = EventEmitter.createInterface('handlers'); });
EventEmitter.prototype.on = function() {
pub.on.apply(this, arguments);
Array.prototype.unshift.call(arguments, 'on');
this._trigger.apply(this, arguments);
}; };
EventEmitter.prototype.off = pub.off;
EventEmitter.prototype.trigger = pub.trigger;
EventEmitter.prototype.removeAllListeners = pub.removeAllListeners;
return EventEmitter; return methods;
}); };
var pvt = EventEmitter.createInterface('_handlers');
EventEmitter.prototype._on = pvt.on;
EventEmitter.prototype._off = pvt.off;
EventEmitter.prototype._trigger = pvt.trigger;
var pub = EventEmitter.createInterface('handlers');
EventEmitter.prototype.on = function() {
pub.on.apply(this, arguments);
Array.prototype.unshift.call(arguments, 'on');
this._trigger.apply(this, arguments);
};
EventEmitter.prototype.off = pub.off;
EventEmitter.prototype.trigger = pub.trigger;
EventEmitter.prototype.removeAllListeners = pub.removeAllListeners;
module.exports = EventEmitter;

View File

@ -1,314 +1,318 @@
define(function(require) { // Based on https://github.com/diy/intercom.js/blob/master/lib/intercom.js
// Copyright 2012 DIY Co Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
// Based on https://github.com/diy/intercom.js/blob/master/lib/intercom.js var EventEmitter = require('./eventemitter.js');
// Copyright 2012 DIY Co Apache License, Version 2.0 var guid = require('../src/shared.js').guid;
// http://www.apache.org/licenses/LICENSE-2.0
var EventEmitter = require('eventemitter'); function throttle(delay, fn) {
var guid = require('src/shared').guid; var last = 0;
return function() {
function throttle(delay, fn) {
var last = 0;
return function() {
var now = Date.now();
if (now - last > delay) {
last = now;
fn.apply(this, arguments);
}
};
}
function extend(a, b) {
if (typeof a === 'undefined' || !a) { a = {}; }
if (typeof b === 'object') {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
}
return a;
}
var localStorage = (function(window) {
if (typeof window.localStorage === 'undefined') {
return {
getItem : function() {},
setItem : function() {},
removeItem : function() {}
};
}
return window.localStorage;
}(this));
function Intercom() {
var self = this;
var now = Date.now(); var now = Date.now();
if (now - last > delay) {
last = now;
fn.apply(this, arguments);
}
};
}
this.origin = guid(); function extend(a, b) {
this.lastMessage = now; if (typeof a === 'undefined' || !a) { a = {}; }
this.receivedIDs = {}; if (typeof b === 'object') {
this.previousValues = {}; for (var key in b) {
if (b.hasOwnProperty(key)) {
var storageHandler = function() { a[key] = b[key];
self._onStorageEvent.apply(self, arguments); }
};
if (document.attachEvent) {
document.attachEvent('onstorage', storageHandler);
} else {
window.addEventListener('storage', storageHandler, false);
} }
} }
return a;
}
Intercom.prototype._transaction = function(fn) { var localStorage = (function(window) {
var TIMEOUT = 1000; if (typeof window === 'undefined' ||
var WAIT = 20; typeof window.localStorage === 'undefined') {
var self = this; return {
var executed = false; getItem : function() {},
var listening = false; setItem : function() {},
var waitTimer = null; removeItem : function() {}
function lock() {
if (executed) {
return;
}
var now = Date.now();
var activeLock = localStorage.getItem(INDEX_LOCK)|0;
if (activeLock && now - activeLock < TIMEOUT) {
if (!listening) {
self._on('storage', lock);
listening = true;
}
waitTimer = window.setTimeout(lock, WAIT);
return;
}
executed = true;
localStorage.setItem(INDEX_LOCK, now);
fn();
unlock();
}
function unlock() {
if (listening) {
self._off('storage', lock);
}
if (waitTimer) {
window.clearTimeout(waitTimer);
}
localStorage.removeItem(INDEX_LOCK);
}
lock();
};
Intercom.prototype._cleanup_emit = throttle(100, function() {
var self = this;
self._transaction(function() {
var now = Date.now();
var threshold = now - THRESHOLD_TTL_EMIT;
var changed = 0;
var messages;
try {
messages = JSON.parse(localStorage.getItem(INDEX_EMIT) || '[]');
} catch(e) {
messages = [];
}
for (var i = messages.length - 1; i >= 0; i--) {
if (messages[i].timestamp < threshold) {
messages.splice(i, 1);
changed++;
}
}
if (changed > 0) {
localStorage.setItem(INDEX_EMIT, JSON.stringify(messages));
}
});
});
Intercom.prototype._cleanup_once = throttle(100, function() {
var self = this;
self._transaction(function() {
var timestamp, ttl, key;
var table;
var now = Date.now();
var changed = 0;
try {
table = JSON.parse(localStorage.getItem(INDEX_ONCE) || '{}');
} catch(e) {
table = {};
}
for (key in table) {
if (self._once_expired(key, table)) {
delete table[key];
changed++;
}
}
if (changed > 0) {
localStorage.setItem(INDEX_ONCE, JSON.stringify(table));
}
});
});
Intercom.prototype._once_expired = function(key, table) {
if (!table) {
return true;
}
if (!table.hasOwnProperty(key)) {
return true;
}
if (typeof table[key] !== 'object') {
return true;
}
var ttl = table[key].ttl || THRESHOLD_TTL_ONCE;
var now = Date.now();
var timestamp = table[key].timestamp;
return timestamp < now - ttl;
};
Intercom.prototype._localStorageChanged = function(event, field) {
if (event && event.key) {
return event.key === field;
}
var currentValue = localStorage.getItem(field);
if (currentValue === this.previousValues[field]) {
return false;
}
this.previousValues[field] = currentValue;
return true;
};
Intercom.prototype._onStorageEvent = function(event) {
event = event || window.event;
var self = this;
if (this._localStorageChanged(event, INDEX_EMIT)) {
this._transaction(function() {
var now = Date.now();
var data = localStorage.getItem(INDEX_EMIT);
var messages;
try {
messages = JSON.parse(data || '[]');
} catch(e) {
messages = [];
}
for (var i = 0; i < messages.length; i++) {
if (messages[i].origin === self.origin) continue;
if (messages[i].timestamp < self.lastMessage) continue;
if (messages[i].id) {
if (self.receivedIDs.hasOwnProperty(messages[i].id)) continue;
self.receivedIDs[messages[i].id] = true;
}
self.trigger(messages[i].name, messages[i].payload);
}
self.lastMessage = now;
});
}
this._trigger('storage', event);
};
Intercom.prototype._emit = function(name, message, id) {
id = (typeof id === 'string' || typeof id === 'number') ? String(id) : null;
if (id && id.length) {
if (this.receivedIDs.hasOwnProperty(id)) return;
this.receivedIDs[id] = true;
}
var packet = {
id : id,
name : name,
origin : this.origin,
timestamp : Date.now(),
payload : message
}; };
}
return window.localStorage;
}(this));
var self = this; function Intercom() {
this._transaction(function() { var self = this;
var data = localStorage.getItem(INDEX_EMIT) || '[]'; var now = Date.now();
var delimiter = (data === '[]') ? '' : ',';
data = [data.substring(0, data.length - 1), delimiter, JSON.stringify(packet), ']'].join('');
localStorage.setItem(INDEX_EMIT, data);
self.trigger(name, message);
window.setTimeout(function() { this.origin = guid();
self._cleanup_emit(); this.lastMessage = now;
}, 50); this.receivedIDs = {};
}); this.previousValues = {};
var storageHandler = function() {
self._onStorageEvent.apply(self, arguments);
}; };
Intercom.prototype.emit = function(name, message) { // If we're in node.js, skip event registration
this._emit.apply(this, arguments); if (typeof window === 'undefined' || typeof document === 'undefined') {
this._trigger('emit', name, message); return;
}; }
Intercom.prototype.once = function(key, fn, ttl) { if (document.attachEvent) {
if (!Intercom.supported) { document.attachEvent('onstorage', storageHandler);
} else {
window.addEventListener('storage', storageHandler, false);
}
}
Intercom.prototype._transaction = function(fn) {
var TIMEOUT = 1000;
var WAIT = 20;
var self = this;
var executed = false;
var listening = false;
var waitTimer = null;
function lock() {
if (executed) {
return; return;
} }
var self = this; var now = Date.now();
this._transaction(function() { var activeLock = localStorage.getItem(INDEX_LOCK)|0;
var data; if (activeLock && now - activeLock < TIMEOUT) {
try { if (!listening) {
data = JSON.parse(localStorage.getItem(INDEX_ONCE) || '{}'); self._on('storage', lock);
} catch(e) { listening = true;
data = {};
}
if (!self._once_expired(key, data)) {
return;
} }
waitTimer = setTimeout(lock, WAIT);
return;
}
executed = true;
localStorage.setItem(INDEX_LOCK, now);
data[key] = {}; fn();
data[key].timestamp = Date.now(); unlock();
if (typeof ttl === 'number') { }
data[key].ttl = ttl * 1000;
}
localStorage.setItem(INDEX_ONCE, JSON.stringify(data)); function unlock() {
fn(); if (listening) {
self._off('storage', lock);
window.setTimeout(function() { }
self._cleanup_once(); if (waitTimer) {
}, 50); clearTimeout(waitTimer);
}); }
};
extend(Intercom.prototype, EventEmitter.prototype);
Intercom.supported = (typeof localStorage !== 'undefined');
var INDEX_EMIT = 'intercom';
var INDEX_ONCE = 'intercom_once';
var INDEX_LOCK = 'intercom_lock';
var THRESHOLD_TTL_EMIT = 50000;
var THRESHOLD_TTL_ONCE = 1000 * 3600;
Intercom.destroy = function() {
localStorage.removeItem(INDEX_LOCK); localStorage.removeItem(INDEX_LOCK);
localStorage.removeItem(INDEX_EMIT); }
localStorage.removeItem(INDEX_ONCE);
lock();
};
Intercom.prototype._cleanup_emit = throttle(100, function() {
var self = this;
self._transaction(function() {
var now = Date.now();
var threshold = now - THRESHOLD_TTL_EMIT;
var changed = 0;
var messages;
try {
messages = JSON.parse(localStorage.getItem(INDEX_EMIT) || '[]');
} catch(e) {
messages = [];
}
for (var i = messages.length - 1; i >= 0; i--) {
if (messages[i].timestamp < threshold) {
messages.splice(i, 1);
changed++;
}
}
if (changed > 0) {
localStorage.setItem(INDEX_EMIT, JSON.stringify(messages));
}
});
});
Intercom.prototype._cleanup_once = throttle(100, function() {
var self = this;
self._transaction(function() {
var timestamp, ttl, key;
var table;
var now = Date.now();
var changed = 0;
try {
table = JSON.parse(localStorage.getItem(INDEX_ONCE) || '{}');
} catch(e) {
table = {};
}
for (key in table) {
if (self._once_expired(key, table)) {
delete table[key];
changed++;
}
}
if (changed > 0) {
localStorage.setItem(INDEX_ONCE, JSON.stringify(table));
}
});
});
Intercom.prototype._once_expired = function(key, table) {
if (!table) {
return true;
}
if (!table.hasOwnProperty(key)) {
return true;
}
if (typeof table[key] !== 'object') {
return true;
}
var ttl = table[key].ttl || THRESHOLD_TTL_ONCE;
var now = Date.now();
var timestamp = table[key].timestamp;
return timestamp < now - ttl;
};
Intercom.prototype._localStorageChanged = function(event, field) {
if (event && event.key) {
return event.key === field;
}
var currentValue = localStorage.getItem(field);
if (currentValue === this.previousValues[field]) {
return false;
}
this.previousValues[field] = currentValue;
return true;
};
Intercom.prototype._onStorageEvent = function(event) {
event = event || window.event;
var self = this;
if (this._localStorageChanged(event, INDEX_EMIT)) {
this._transaction(function() {
var now = Date.now();
var data = localStorage.getItem(INDEX_EMIT);
var messages;
try {
messages = JSON.parse(data || '[]');
} catch(e) {
messages = [];
}
for (var i = 0; i < messages.length; i++) {
if (messages[i].origin === self.origin) continue;
if (messages[i].timestamp < self.lastMessage) continue;
if (messages[i].id) {
if (self.receivedIDs.hasOwnProperty(messages[i].id)) continue;
self.receivedIDs[messages[i].id] = true;
}
self.trigger(messages[i].name, messages[i].payload);
}
self.lastMessage = now;
});
}
this._trigger('storage', event);
};
Intercom.prototype._emit = function(name, message, id) {
id = (typeof id === 'string' || typeof id === 'number') ? String(id) : null;
if (id && id.length) {
if (this.receivedIDs.hasOwnProperty(id)) return;
this.receivedIDs[id] = true;
}
var packet = {
id : id,
name : name,
origin : this.origin,
timestamp : Date.now(),
payload : message
}; };
Intercom.getInstance = (function() { var self = this;
var intercom; this._transaction(function() {
return function() { var data = localStorage.getItem(INDEX_EMIT) || '[]';
if (!intercom) { var delimiter = (data === '[]') ? '' : ',';
intercom = new Intercom(); data = [data.substring(0, data.length - 1), delimiter, JSON.stringify(packet), ']'].join('');
} localStorage.setItem(INDEX_EMIT, data);
return intercom; self.trigger(name, message);
};
})();
return Intercom; setTimeout(function() {
}); self._cleanup_emit();
}, 50);
});
};
Intercom.prototype.emit = function(name, message) {
this._emit.apply(this, arguments);
this._trigger('emit', name, message);
};
Intercom.prototype.once = function(key, fn, ttl) {
if (!Intercom.supported) {
return;
}
var self = this;
this._transaction(function() {
var data;
try {
data = JSON.parse(localStorage.getItem(INDEX_ONCE) || '{}');
} catch(e) {
data = {};
}
if (!self._once_expired(key, data)) {
return;
}
data[key] = {};
data[key].timestamp = Date.now();
if (typeof ttl === 'number') {
data[key].ttl = ttl * 1000;
}
localStorage.setItem(INDEX_ONCE, JSON.stringify(data));
fn();
setTimeout(function() {
self._cleanup_once();
}, 50);
});
};
extend(Intercom.prototype, EventEmitter.prototype);
Intercom.supported = (typeof localStorage !== 'undefined');
var INDEX_EMIT = 'intercom';
var INDEX_ONCE = 'intercom_once';
var INDEX_LOCK = 'intercom_lock';
var THRESHOLD_TTL_EMIT = 50000;
var THRESHOLD_TTL_ONCE = 1000 * 3600;
Intercom.destroy = function() {
localStorage.removeItem(INDEX_LOCK);
localStorage.removeItem(INDEX_EMIT);
localStorage.removeItem(INDEX_ONCE);
};
Intercom.getInstance = (function() {
var intercom;
return function() {
if (!intercom) {
intercom = new Intercom();
}
return intercom;
};
})();
module.exports = Intercom;

View File

@ -7,96 +7,91 @@
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license> * Available under MIT license <http://lodash.com/license>
*/ */
var ArrayProto = Array.prototype;
var nativeForEach = ArrayProto.forEach;
var nativeIndexOf = ArrayProto.indexOf;
var nativeSome = ArrayProto.some;
define(function(require) { var ObjProto = Object.prototype;
var hasOwnProperty = ObjProto.hasOwnProperty;
var nativeKeys = Object.keys;
var ArrayProto = Array.prototype; var breaker = {};
var nativeForEach = ArrayProto.forEach;
var nativeIndexOf = ArrayProto.indexOf;
var nativeSome = ArrayProto.some;
var ObjProto = Object.prototype; function has(obj, key) {
var hasOwnProperty = ObjProto.hasOwnProperty; return hasOwnProperty.call(obj, key);
var nativeKeys = Object.keys; }
var breaker = {}; var keys = nativeKeys || function(obj) {
if (obj !== Object(obj)) throw new TypeError('Invalid object');
var keys = [];
for (var key in obj) if (has(obj, key)) keys.push(key);
return keys;
};
function has(obj, key) { function size(obj) {
return hasOwnProperty.call(obj, key); if (obj == null) return 0;
} return (obj.length === +obj.length) ? obj.length : keys(obj).length;
}
var keys = nativeKeys || function(obj) { function identity(value) {
if (obj !== Object(obj)) throw new TypeError('Invalid object'); return value;
var keys = []; }
for (var key in obj) if (has(obj, key)) keys.push(key);
return keys;
};
function size(obj) { function each(obj, iterator, context) {
if (obj == null) return 0; var i, length;
return (obj.length === +obj.length) ? obj.length : keys(obj).length; if (obj == null) return;
} if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
function identity(value) { } else if (obj.length === +obj.length) {
return value; for (i = 0, length = obj.length; i < length; i++) {
} if (iterator.call(context, obj[i], i, obj) === breaker) return;
}
function each(obj, iterator, context) { } else {
var i, length; var keys = keys(obj);
if (obj == null) return; for (i = 0, length = keys.length; i < length; i++) {
if (nativeForEach && obj.forEach === nativeForEach) { if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (i = 0, length = obj.length; i < length; i++) {
if (iterator.call(context, obj[i], i, obj) === breaker) return;
}
} else {
var keys = keys(obj);
for (i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
}
} }
};
function any(obj, iterator, context) {
iterator || (iterator = identity);
var result = false;
if (obj == null) return result;
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
each(obj, function(value, index, list) {
if (result || (result = iterator.call(context, value, index, list))) return breaker;
});
return !!result;
};
function contains(obj, target) {
if (obj == null) return false;
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
return any(obj, function(value) {
return value === target;
});
};
function Wrapped(value) {
this.value = value;
} }
Wrapped.prototype.has = function(key) { };
return has(this.value, key);
};
Wrapped.prototype.contains = function(target) {
return contains(this.value, target);
};
Wrapped.prototype.size = function() {
return size(this.value);
};
function nodash(value) { function any(obj, iterator, context) {
// don't wrap if already wrapped, even if wrapped by a different `lodash` constructor iterator || (iterator = identity);
return (value && typeof value == 'object' && !Array.isArray(value) && hasOwnProperty.call(value, '__wrapped__')) var result = false;
? value if (obj == null) return result;
: new Wrapped(value); if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
} each(obj, function(value, index, list) {
if (result || (result = iterator.call(context, value, index, list))) return breaker;
});
return !!result;
};
return nodash; function contains(obj, target) {
if (obj == null) return false;
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
return any(obj, function(value) {
return value === target;
});
};
}); function Wrapped(value) {
this.value = value;
}
Wrapped.prototype.has = function(key) {
return has(this.value, key);
};
Wrapped.prototype.contains = function(target) {
return contains(this.value, target);
};
Wrapped.prototype.size = function() {
return size(this.value);
};
function nodash(value) {
// don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
return (value && typeof value == 'object' && !Array.isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
? value
: new Wrapped(value);
}
module.exports = nodash;

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +0,0 @@
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function m(a){throw a;}var q=void 0,u,aa=this;function v(a,b){var c=a.split("."),d=aa;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var f;c.length&&(f=c.shift());)!c.length&&b!==q?d[f]=b:d=d[f]?d[f]:d[f]={}};var w="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;new (w?Uint8Array:Array)(256);var x;for(x=0;256>x;++x)for(var y=x,ba=7,y=y>>>1;y;y>>>=1)--ba;var z=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],B=w?new Uint32Array(z):z;function C(a){var b=a.length,c=0,d=Number.POSITIVE_INFINITY,f,h,k,e,g,l,p,s,r,A;for(s=0;s<b;++s)a[s]>c&&(c=a[s]),a[s]<d&&(d=a[s]);f=1<<c;h=new (w?Uint32Array:Array)(f);k=1;e=0;for(g=2;k<=c;){for(s=0;s<b;++s)if(a[s]===k){l=0;p=e;for(r=0;r<k;++r)l=l<<1|p&1,p>>=1;A=k<<16|s;for(r=l;r<f;r+=g)h[r]=A;++e}++k;e<<=1;g<<=1}return[h,c,d]};var D=[],E;for(E=0;288>E;E++)switch(!0){case 143>=E:D.push([E+48,8]);break;case 255>=E:D.push([E-144+400,9]);break;case 279>=E:D.push([E-256+0,7]);break;case 287>=E:D.push([E-280+192,8]);break;default:m("invalid literal: "+E)}
var ca=function(){function a(a){switch(!0){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:m("invalid length: "+a)}}var b=[],c,d;for(c=3;258>=c;c++)d=a(c),b[c]=d[2]<<24|d[1]<<
16|d[0];return b}();w&&new Uint32Array(ca);function F(a,b){this.l=[];this.m=32768;this.d=this.f=this.c=this.t=0;this.input=w?new Uint8Array(a):a;this.u=!1;this.n=G;this.L=!1;if(b||!(b={}))b.index&&(this.c=b.index),b.bufferSize&&(this.m=b.bufferSize),b.bufferType&&(this.n=b.bufferType),b.resize&&(this.L=b.resize);switch(this.n){case H:this.a=32768;this.b=new (w?Uint8Array:Array)(32768+this.m+258);break;case G:this.a=0;this.b=new (w?Uint8Array:Array)(this.m);this.e=this.X;this.B=this.S;this.q=this.W;break;default:m(Error("invalid inflate mode"))}}
var H=0,G=1;
F.prototype.r=function(){for(;!this.u;){var a=I(this,3);a&1&&(this.u=!0);a>>>=1;switch(a){case 0:var b=this.input,c=this.c,d=this.b,f=this.a,h=b.length,k=q,e=q,g=d.length,l=q;this.d=this.f=0;c+1>=h&&m(Error("invalid uncompressed block header: LEN"));k=b[c++]|b[c++]<<8;c+1>=h&&m(Error("invalid uncompressed block header: NLEN"));e=b[c++]|b[c++]<<8;k===~e&&m(Error("invalid uncompressed block header: length verify"));c+k>b.length&&m(Error("input buffer is broken"));switch(this.n){case H:for(;f+k>d.length;){l=
g-f;k-=l;if(w)d.set(b.subarray(c,c+l),f),f+=l,c+=l;else for(;l--;)d[f++]=b[c++];this.a=f;d=this.e();f=this.a}break;case G:for(;f+k>d.length;)d=this.e({H:2});break;default:m(Error("invalid inflate mode"))}if(w)d.set(b.subarray(c,c+k),f),f+=k,c+=k;else for(;k--;)d[f++]=b[c++];this.c=c;this.a=f;this.b=d;break;case 1:this.q(da,ea);break;case 2:fa(this);break;default:m(Error("unknown BTYPE: "+a))}}return this.B()};
var J=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],K=w?new Uint16Array(J):J,L=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],M=w?new Uint16Array(L):L,ga=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],O=w?new Uint8Array(ga):ga,ha=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ia=w?new Uint16Array(ha):ha,ja=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,
12,12,13,13],P=w?new Uint8Array(ja):ja,Q=new (w?Uint8Array:Array)(288),R,la;R=0;for(la=Q.length;R<la;++R)Q[R]=143>=R?8:255>=R?9:279>=R?7:8;var da=C(Q),S=new (w?Uint8Array:Array)(30),T,ma;T=0;for(ma=S.length;T<ma;++T)S[T]=5;var ea=C(S);function I(a,b){for(var c=a.f,d=a.d,f=a.input,h=a.c,k=f.length,e;d<b;)h>=k&&m(Error("input buffer is broken")),c|=f[h++]<<d,d+=8;e=c&(1<<b)-1;a.f=c>>>b;a.d=d-b;a.c=h;return e}
function U(a,b){for(var c=a.f,d=a.d,f=a.input,h=a.c,k=f.length,e=b[0],g=b[1],l,p;d<g&&!(h>=k);)c|=f[h++]<<d,d+=8;l=e[c&(1<<g)-1];p=l>>>16;a.f=c>>p;a.d=d-p;a.c=h;return l&65535}
function fa(a){function b(a,b,c){var d,e=this.K,f,g;for(g=0;g<a;)switch(d=U(this,b),d){case 16:for(f=3+I(this,2);f--;)c[g++]=e;break;case 17:for(f=3+I(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+I(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}this.K=e;return c}var c=I(a,5)+257,d=I(a,5)+1,f=I(a,4)+4,h=new (w?Uint8Array:Array)(K.length),k,e,g,l;for(l=0;l<f;++l)h[K[l]]=I(a,3);if(!w){l=f;for(f=h.length;l<f;++l)h[K[l]]=0}k=C(h);e=new (w?Uint8Array:Array)(c);g=new (w?Uint8Array:Array)(d);a.K=
0;a.q(C(b.call(a,c,k,e)),C(b.call(a,d,k,g)))}u=F.prototype;u.q=function(a,b){var c=this.b,d=this.a;this.C=a;for(var f=c.length-258,h,k,e,g;256!==(h=U(this,a));)if(256>h)d>=f&&(this.a=d,c=this.e(),d=this.a),c[d++]=h;else{k=h-257;g=M[k];0<O[k]&&(g+=I(this,O[k]));h=U(this,b);e=ia[h];0<P[h]&&(e+=I(this,P[h]));d>=f&&(this.a=d,c=this.e(),d=this.a);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d};
u.W=function(a,b){var c=this.b,d=this.a;this.C=a;for(var f=c.length,h,k,e,g;256!==(h=U(this,a));)if(256>h)d>=f&&(c=this.e(),f=c.length),c[d++]=h;else{k=h-257;g=M[k];0<O[k]&&(g+=I(this,O[k]));h=U(this,b);e=ia[h];0<P[h]&&(e+=I(this,P[h]));d+g>f&&(c=this.e(),f=c.length);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d};
u.e=function(){var a=new (w?Uint8Array:Array)(this.a-32768),b=this.a-32768,c,d,f=this.b;if(w)a.set(f.subarray(32768,a.length));else{c=0;for(d=a.length;c<d;++c)a[c]=f[c+32768]}this.l.push(a);this.t+=a.length;if(w)f.set(f.subarray(b,b+32768));else for(c=0;32768>c;++c)f[c]=f[b+c];this.a=32768;return f};
u.X=function(a){var b,c=this.input.length/this.c+1|0,d,f,h,k=this.input,e=this.b;a&&("number"===typeof a.H&&(c=a.H),"number"===typeof a.Q&&(c+=a.Q));2>c?(d=(k.length-this.c)/this.C[2],h=258*(d/2)|0,f=h<e.length?e.length+h:e.length<<1):f=e.length*c;w?(b=new Uint8Array(f),b.set(e)):b=e;return this.b=b};
u.B=function(){var a=0,b=this.b,c=this.l,d,f=new (w?Uint8Array:Array)(this.t+(this.a-32768)),h,k,e,g;if(0===c.length)return w?this.b.subarray(32768,this.a):this.b.slice(32768,this.a);h=0;for(k=c.length;h<k;++h){d=c[h];e=0;for(g=d.length;e<g;++e)f[a++]=d[e]}h=32768;for(k=this.a;h<k;++h)f[a++]=b[h];this.l=[];return this.buffer=f};
u.S=function(){var a,b=this.a;w?this.L?(a=new Uint8Array(b),a.set(this.b.subarray(0,b))):a=this.b.subarray(0,b):(this.b.length>b&&(this.b.length=b),a=this.b);return this.buffer=a};function V(a){a=a||{};this.files=[];this.v=a.comment}V.prototype.M=function(a){this.j=a};V.prototype.s=function(a){var b=a[2]&65535|2;return b*(b^1)>>8&255};V.prototype.k=function(a,b){a[0]=(B[(a[0]^b)&255]^a[0]>>>8)>>>0;a[1]=(6681*(20173*(a[1]+(a[0]&255))>>>0)>>>0)+1>>>0;a[2]=(B[(a[2]^a[1]>>>24)&255]^a[2]>>>8)>>>0};V.prototype.U=function(a){var b=[305419896,591751049,878082192],c,d;w&&(b=new Uint32Array(b));c=0;for(d=a.length;c<d;++c)this.k(b,a[c]&255);return b};function W(a,b){b=b||{};this.input=w&&a instanceof Array?new Uint8Array(a):a;this.c=0;this.ca=b.verify||!1;this.j=b.password}var na={P:0,N:8},X=[80,75,1,2],Y=[80,75,3,4],Z=[80,75,5,6];function oa(a,b){this.input=a;this.offset=b}
oa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==X[0]||a[b++]!==X[1]||a[b++]!==X[2]||a[b++]!==X[3])&&m(Error("invalid file header signature"));this.version=a[b++];this.ja=a[b++];this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<
8;this.g=a[b++]|a[b++]<<8;this.F=a[b++]|a[b++]<<8;this.fa=a[b++]|a[b++]<<8;this.ha=a[b++]|a[b++]<<8;this.ga=a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24;this.aa=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.filename=String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.v=w?a.subarray(b,b+this.F):a.slice(b,b+this.F);this.length=b-this.offset};function pa(a,b){this.input=a;this.offset=b}var qa={O:1,da:8,ea:2048};
pa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==Y[0]||a[b++]!==Y[1]||a[b++]!==Y[2]||a[b++]!==Y[3])&&m(Error("invalid local file header signature"));this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<8;this.g=a[b++]|a[b++]<<8;this.filename=
String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.length=b-this.offset};
function $(a){var b=[],c={},d,f,h,k;if(!a.i){if(a.o===q){var e=a.input,g;if(!a.D)a:{var l=a.input,p;for(p=l.length-12;0<p;--p)if(l[p]===Z[0]&&l[p+1]===Z[1]&&l[p+2]===Z[2]&&l[p+3]===Z[3]){a.D=p;break a}m(Error("End of Central Directory Record not found"))}g=a.D;(e[g++]!==Z[0]||e[g++]!==Z[1]||e[g++]!==Z[2]||e[g++]!==Z[3])&&m(Error("invalid signature"));a.ia=e[g++]|e[g++]<<8;a.ka=e[g++]|e[g++]<<8;a.la=e[g++]|e[g++]<<8;a.ba=e[g++]|e[g++]<<8;a.R=(e[g++]|e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.o=(e[g++]|
e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.w=e[g++]|e[g++]<<8;a.v=w?e.subarray(g,g+a.w):e.slice(g,g+a.w)}d=a.o;h=0;for(k=a.ba;h<k;++h)f=new oa(a.input,d),f.parse(),d+=f.length,b[h]=f,c[f.filename]=h;a.R<d-a.o&&m(Error("invalid file header size"));a.i=b;a.G=c}}u=W.prototype;u.Z=function(){var a=[],b,c,d;this.i||$(this);d=this.i;b=0;for(c=d.length;b<c;++b)a[b]=d[b].filename;return a};
u.r=function(a,b){var c;this.G||$(this);c=this.G[a];c===q&&m(Error(a+" not found"));var d;d=b||{};var f=this.input,h=this.i,k,e,g,l,p,s,r,A;h||$(this);h[c]===q&&m(Error("wrong index"));e=h[c].aa;k=new pa(this.input,e);k.parse();e+=k.length;g=k.z;if(0!==(k.I&qa.O)){!d.password&&!this.j&&m(Error("please set password"));s=this.T(d.password||this.j);r=e;for(A=e+12;r<A;++r)ra(this,s,f[r]);e+=12;g-=12;r=e;for(A=e+g;r<A;++r)f[r]=ra(this,s,f[r])}switch(k.A){case na.P:l=w?this.input.subarray(e,e+g):this.input.slice(e,
e+g);break;case na.N:l=(new F(this.input,{index:e,bufferSize:k.J})).r();break;default:m(Error("unknown compression type"))}if(this.ca){var t=q,n,N="number"===typeof t?t:t=0,ka=l.length;n=-1;for(N=ka&7;N--;++t)n=n>>>8^B[(n^l[t])&255];for(N=ka>>3;N--;t+=8)n=n>>>8^B[(n^l[t])&255],n=n>>>8^B[(n^l[t+1])&255],n=n>>>8^B[(n^l[t+2])&255],n=n>>>8^B[(n^l[t+3])&255],n=n>>>8^B[(n^l[t+4])&255],n=n>>>8^B[(n^l[t+5])&255],n=n>>>8^B[(n^l[t+6])&255],n=n>>>8^B[(n^l[t+7])&255];p=(n^4294967295)>>>0;k.p!==p&&m(Error("wrong crc: file=0x"+
k.p.toString(16)+", data=0x"+p.toString(16)))}return l};u.M=function(a){this.j=a};function ra(a,b,c){c^=a.s(b);a.k(b,c);return c}u.k=V.prototype.k;u.T=V.prototype.U;u.s=V.prototype.s;v("Zlib.Unzip",W);v("Zlib.Unzip.prototype.decompress",W.prototype.r);v("Zlib.Unzip.prototype.getFilenames",W.prototype.Z);v("Zlib.Unzip.prototype.setPassword",W.prototype.M);}).call(this);

View File

@ -1,3 +1,5 @@
var ZlibNamespace = {};
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var n=void 0,y=!0,aa=this;function G(e,b){var a=e.split("."),d=aa;!(a[0]in d)&&d.execScript&&d.execScript("var "+a[0]);for(var c;a.length&&(c=a.shift());)!a.length&&b!==n?d[c]=b:d=d[c]?d[c]:d[c]={}};var H="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function ba(e,b){this.index="number"===typeof b?b:0;this.f=0;this.buffer=e instanceof(H?Uint8Array:Array)?e:new (H?Uint8Array:Array)(32768);if(2*this.buffer.length<=this.index)throw Error("invalid index");this.buffer.length<=this.index&&ca(this)}function ca(e){var b=e.buffer,a,d=b.length,c=new (H?Uint8Array:Array)(d<<1);if(H)c.set(b);else for(a=0;a<d;++a)c[a]=b[a];return e.buffer=c} /** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var n=void 0,y=!0,aa=this;function G(e,b){var a=e.split("."),d=aa;!(a[0]in d)&&d.execScript&&d.execScript("var "+a[0]);for(var c;a.length&&(c=a.shift());)!a.length&&b!==n?d[c]=b:d=d[c]?d[c]:d[c]={}};var H="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function ba(e,b){this.index="number"===typeof b?b:0;this.f=0;this.buffer=e instanceof(H?Uint8Array:Array)?e:new (H?Uint8Array:Array)(32768);if(2*this.buffer.length<=this.index)throw Error("invalid index");this.buffer.length<=this.index&&ca(this)}function ca(e){var b=e.buffer,a,d=b.length,c=new (H?Uint8Array:Array)(d<<1);if(H)c.set(b);else for(a=0;a<d;++a)c[a]=b[a];return e.buffer=c}
ba.prototype.b=function(e,b,a){var d=this.buffer,c=this.index,f=this.f,l=d[c],p;a&&1<b&&(e=8<b?(L[e&255]<<24|L[e>>>8&255]<<16|L[e>>>16&255]<<8|L[e>>>24&255])>>32-b:L[e]>>8-b);if(8>b+f)l=l<<b|e,f+=b;else for(p=0;p<b;++p)l=l<<1|e>>b-p-1&1,8===++f&&(f=0,d[c++]=L[l],l=0,c===d.length&&(d=ca(this)));d[c]=l;this.buffer=d;this.f=f;this.index=c};ba.prototype.finish=function(){var e=this.buffer,b=this.index,a;0<this.f&&(e[b]<<=8-this.f,e[b]=L[e[b]],b++);H?a=e.subarray(0,b):(e.length=b,a=e);return a}; ba.prototype.b=function(e,b,a){var d=this.buffer,c=this.index,f=this.f,l=d[c],p;a&&1<b&&(e=8<b?(L[e&255]<<24|L[e>>>8&255]<<16|L[e>>>16&255]<<8|L[e>>>24&255])>>32-b:L[e]>>8-b);if(8>b+f)l=l<<b|e,f+=b;else for(p=0;p<b;++p)l=l<<1|e>>b-p-1&1,8===++f&&(f=0,d[c++]=L[l],l=0,c===d.length&&(d=ca(this)));d[c]=l;this.buffer=d;this.f=f;this.index=c};ba.prototype.finish=function(){var e=this.buffer,b=this.index,a;0<this.f&&(e[b]<<=8-this.f,e[b]=L[e[b]],b++);H?a=e.subarray(0,b):(e.length=b,a=e);return a};
var da=new (H?Uint8Array:Array)(256),ha;for(ha=0;256>ha;++ha){for(var U=ha,ja=U,ka=7,U=U>>>1;U;U>>>=1)ja<<=1,ja|=U&1,--ka;da[ha]=(ja<<ka&255)>>>0}var L=da;function la(e){var b=n,a,d="number"===typeof b?b:b=0,c=e.length;a=-1;for(d=c&7;d--;++b)a=a>>>8^V[(a^e[b])&255];for(d=c>>3;d--;b+=8)a=a>>>8^V[(a^e[b])&255],a=a>>>8^V[(a^e[b+1])&255],a=a>>>8^V[(a^e[b+2])&255],a=a>>>8^V[(a^e[b+3])&255],a=a>>>8^V[(a^e[b+4])&255],a=a>>>8^V[(a^e[b+5])&255],a=a>>>8^V[(a^e[b+6])&255],a=a>>>8^V[(a^e[b+7])&255];return(a^4294967295)>>>0} var da=new (H?Uint8Array:Array)(256),ha;for(ha=0;256>ha;++ha){for(var U=ha,ja=U,ka=7,U=U>>>1;U;U>>>=1)ja<<=1,ja|=U&1,--ka;da[ha]=(ja<<ka&255)>>>0}var L=da;function la(e){var b=n,a,d="number"===typeof b?b:b=0,c=e.length;a=-1;for(d=c&7;d--;++b)a=a>>>8^V[(a^e[b])&255];for(d=c>>3;d--;b+=8)a=a>>>8^V[(a^e[b])&255],a=a>>>8^V[(a^e[b+1])&255],a=a>>>8^V[(a^e[b+2])&255],a=a>>>8^V[(a^e[b+3])&255],a=a>>>8^V[(a^e[b+4])&255],a=a>>>8^V[(a^e[b+5])&255],a=a>>>8^V[(a^e[b+6])&255],a=a>>>8^V[(a^e[b+7])&255];return(a^4294967295)>>>0}
@ -34,4 +36,38 @@ W=n,X=n;H&&(O=new Uint32Array(O));W=0;for(X=ea.length;W<X;++W)Pa(O,ea[W]&255);N=
1980&127)<<1|u.getMonth()+1>>3;m=b.h;a[d++]=a[c++]=m&255;a[d++]=a[c++]=m>>8&255;a[d++]=a[c++]=m>>16&255;a[d++]=a[c++]=m>>24&255;h=b.buffer.length;a[d++]=a[c++]=h&255;a[d++]=a[c++]=h>>8&255;a[d++]=a[c++]=h>>16&255;a[d++]=a[c++]=h>>24&255;s=b.size;a[d++]=a[c++]=s&255;a[d++]=a[c++]=s>>8&255;a[d++]=a[c++]=s>>16&255;a[d++]=a[c++]=s>>24&255;a[d++]=a[c++]=t&255;a[d++]=a[c++]=t>>8&255;a[d++]=a[c++]=0;a[d++]=a[c++]=0;a[c++]=r&255;a[c++]=r>>8&255;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]= 1980&127)<<1|u.getMonth()+1>>3;m=b.h;a[d++]=a[c++]=m&255;a[d++]=a[c++]=m>>8&255;a[d++]=a[c++]=m>>16&255;a[d++]=a[c++]=m>>24&255;h=b.buffer.length;a[d++]=a[c++]=h&255;a[d++]=a[c++]=h>>8&255;a[d++]=a[c++]=h>>16&255;a[d++]=a[c++]=h>>24&255;s=b.size;a[d++]=a[c++]=s&255;a[d++]=a[c++]=s>>8&255;a[d++]=a[c++]=s>>16&255;a[d++]=a[c++]=s>>24&255;a[d++]=a[c++]=t&255;a[d++]=a[c++]=t>>8&255;a[d++]=a[c++]=0;a[d++]=a[c++]=0;a[c++]=r&255;a[c++]=r>>8&255;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=
0;a[c++]=0;a[c++]=k&255;a[c++]=k>>8&255;a[c++]=k>>16&255;a[c++]=k>>24&255;if(Q=b.a.filename)if(H)a.set(Q,d),a.set(Q,c),d+=t,c+=t;else for(g=0;g<t;++g)a[d++]=a[c++]=Q[g];if(z=b.a.extraField)if(H)a.set(z,d),a.set(z,c),d+=0,c+=0;else for(g=0;g<r;++g)a[d++]=a[c++]=z[g];if(A=b.a.comment)if(H)a.set(A,c),c+=r;else for(g=0;g<r;++g)a[c++]=A[g];if(H)a.set(b.buffer,d),d+=b.buffer.length;else{g=0;for(J=b.buffer.length;g<J;++g)a[d++]=b.buffer[g]}}a[f++]=Oa[0];a[f++]=Oa[1];a[f++]=Oa[2];a[f++]=Oa[3];a[f++]=0;a[f++]= 0;a[c++]=0;a[c++]=k&255;a[c++]=k>>8&255;a[c++]=k>>16&255;a[c++]=k>>24&255;if(Q=b.a.filename)if(H)a.set(Q,d),a.set(Q,c),d+=t,c+=t;else for(g=0;g<t;++g)a[d++]=a[c++]=Q[g];if(z=b.a.extraField)if(H)a.set(z,d),a.set(z,c),d+=0,c+=0;else for(g=0;g<r;++g)a[d++]=a[c++]=z[g];if(A=b.a.comment)if(H)a.set(A,c),c+=r;else for(g=0;g<r;++g)a[c++]=A[g];if(H)a.set(b.buffer,d),d+=b.buffer.length;else{g=0;for(J=b.buffer.length;g<J;++g)a[d++]=b.buffer[g]}}a[f++]=Oa[0];a[f++]=Oa[1];a[f++]=Oa[2];a[f++]=Oa[3];a[f++]=0;a[f++]=
0;a[f++]=0;a[f++]=0;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=p&255;a[f++]=p>>8&255;a[f++]=p>>16&255;a[f++]=p>>24&255;a[f++]=l&255;a[f++]=l>>8&255;a[f++]=l>>16&255;a[f++]=l>>24&255;r=this.d?this.d.length:0;a[f++]=r&255;a[f++]=r>>8&255;if(this.d)if(H)a.set(this.d,f);else{g=0;for(J=r;g<J;++g)a[f++]=this.d[g]}return a};function Qa(e,b){var a,d=e[2]&65535|2;a=d*(d^1)>>8&255;Pa(e,b);return a^b} 0;a[f++]=0;a[f++]=0;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=p&255;a[f++]=p>>8&255;a[f++]=p>>16&255;a[f++]=p>>24&255;a[f++]=l&255;a[f++]=l>>8&255;a[f++]=l>>16&255;a[f++]=l>>24&255;r=this.d?this.d.length:0;a[f++]=r&255;a[f++]=r>>8&255;if(this.d)if(H)a.set(this.d,f);else{g=0;for(J=r;g<J;++g)a[f++]=this.d[g]}return a};function Qa(e,b){var a,d=e[2]&65535|2;a=d*(d^1)>>8&255;Pa(e,b);return a^b}
function Pa(e,b){e[0]=(V[(e[0]^b)&255]^e[0]>>>8)>>>0;e[1]=(6681*(20173*(e[1]+(e[0]&255))>>>0)>>>0)+1>>>0;e[2]=(V[(e[2]^e[1]>>>24)&255]^e[2]>>>8)>>>0};function Ra(e,b){var a,d,c,f;if(Object.keys)a=Object.keys(b);else for(d in a=[],c=0,b)a[c++]=d;c=0;for(f=a.length;c<f;++c)d=a[c],G(e+"."+d,b[d])};G("Zlib.Zip",$);G("Zlib.Zip.prototype.addFile",$.prototype.m);G("Zlib.Zip.prototype.compress",$.prototype.g);G("Zlib.Zip.prototype.setPassword",$.prototype.q);Ra("Zlib.Zip.CompressionMethod",{STORE:0,DEFLATE:8});Ra("Zlib.Zip.OperatingSystem",{MSDOS:0,UNIX:3,MACINTOSH:7});}).call(this); function Pa(e,b){e[0]=(V[(e[0]^b)&255]^e[0]>>>8)>>>0;e[1]=(6681*(20173*(e[1]+(e[0]&255))>>>0)>>>0)+1>>>0;e[2]=(V[(e[2]^e[1]>>>24)&255]^e[2]>>>8)>>>0};function Ra(e,b){var a,d,c,f;if(Object.keys)a=Object.keys(b);else for(d in a=[],c=0,b)a[c++]=d;c=0;for(f=a.length;c<f;++c)d=a[c],G(e+"."+d,b[d])};G("Zlib.Zip",$);G("Zlib.Zip.prototype.addFile",$.prototype.m);G("Zlib.Zip.prototype.compress",$.prototype.g);G("Zlib.Zip.prototype.setPassword",$.prototype.q);Ra("Zlib.Zip.CompressionMethod",{STORE:0,DEFLATE:8});Ra("Zlib.Zip.OperatingSystem",{MSDOS:0,UNIX:3,MACINTOSH:7});}).call(ZlibNamespace);
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function m(a){throw a;}var q=void 0,u,aa=this;function v(a,b){var c=a.split("."),d=aa;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var f;c.length&&(f=c.shift());)!c.length&&b!==q?d[f]=b:d=d[f]?d[f]:d[f]={}};var w="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;new (w?Uint8Array:Array)(256);var x;for(x=0;256>x;++x)for(var y=x,ba=7,y=y>>>1;y;y>>>=1)--ba;var z=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],B=w?new Uint32Array(z):z;function C(a){var b=a.length,c=0,d=Number.POSITIVE_INFINITY,f,h,k,e,g,l,p,s,r,A;for(s=0;s<b;++s)a[s]>c&&(c=a[s]),a[s]<d&&(d=a[s]);f=1<<c;h=new (w?Uint32Array:Array)(f);k=1;e=0;for(g=2;k<=c;){for(s=0;s<b;++s)if(a[s]===k){l=0;p=e;for(r=0;r<k;++r)l=l<<1|p&1,p>>=1;A=k<<16|s;for(r=l;r<f;r+=g)h[r]=A;++e}++k;e<<=1;g<<=1}return[h,c,d]};var D=[],E;for(E=0;288>E;E++)switch(!0){case 143>=E:D.push([E+48,8]);break;case 255>=E:D.push([E-144+400,9]);break;case 279>=E:D.push([E-256+0,7]);break;case 287>=E:D.push([E-280+192,8]);break;default:m("invalid literal: "+E)}
var ca=function(){function a(a){switch(!0){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:m("invalid length: "+a)}}var b=[],c,d;for(c=3;258>=c;c++)d=a(c),b[c]=d[2]<<24|d[1]<<
16|d[0];return b}();w&&new Uint32Array(ca);function F(a,b){this.l=[];this.m=32768;this.d=this.f=this.c=this.t=0;this.input=w?new Uint8Array(a):a;this.u=!1;this.n=G;this.L=!1;if(b||!(b={}))b.index&&(this.c=b.index),b.bufferSize&&(this.m=b.bufferSize),b.bufferType&&(this.n=b.bufferType),b.resize&&(this.L=b.resize);switch(this.n){case H:this.a=32768;this.b=new (w?Uint8Array:Array)(32768+this.m+258);break;case G:this.a=0;this.b=new (w?Uint8Array:Array)(this.m);this.e=this.X;this.B=this.S;this.q=this.W;break;default:m(Error("invalid inflate mode"))}}
var H=0,G=1;
F.prototype.r=function(){for(;!this.u;){var a=I(this,3);a&1&&(this.u=!0);a>>>=1;switch(a){case 0:var b=this.input,c=this.c,d=this.b,f=this.a,h=b.length,k=q,e=q,g=d.length,l=q;this.d=this.f=0;c+1>=h&&m(Error("invalid uncompressed block header: LEN"));k=b[c++]|b[c++]<<8;c+1>=h&&m(Error("invalid uncompressed block header: NLEN"));e=b[c++]|b[c++]<<8;k===~e&&m(Error("invalid uncompressed block header: length verify"));c+k>b.length&&m(Error("input buffer is broken"));switch(this.n){case H:for(;f+k>d.length;){l=
g-f;k-=l;if(w)d.set(b.subarray(c,c+l),f),f+=l,c+=l;else for(;l--;)d[f++]=b[c++];this.a=f;d=this.e();f=this.a}break;case G:for(;f+k>d.length;)d=this.e({H:2});break;default:m(Error("invalid inflate mode"))}if(w)d.set(b.subarray(c,c+k),f),f+=k,c+=k;else for(;k--;)d[f++]=b[c++];this.c=c;this.a=f;this.b=d;break;case 1:this.q(da,ea);break;case 2:fa(this);break;default:m(Error("unknown BTYPE: "+a))}}return this.B()};
var J=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],K=w?new Uint16Array(J):J,L=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],M=w?new Uint16Array(L):L,ga=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],O=w?new Uint8Array(ga):ga,ha=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ia=w?new Uint16Array(ha):ha,ja=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,
12,12,13,13],P=w?new Uint8Array(ja):ja,Q=new (w?Uint8Array:Array)(288),R,la;R=0;for(la=Q.length;R<la;++R)Q[R]=143>=R?8:255>=R?9:279>=R?7:8;var da=C(Q),S=new (w?Uint8Array:Array)(30),T,ma;T=0;for(ma=S.length;T<ma;++T)S[T]=5;var ea=C(S);function I(a,b){for(var c=a.f,d=a.d,f=a.input,h=a.c,k=f.length,e;d<b;)h>=k&&m(Error("input buffer is broken")),c|=f[h++]<<d,d+=8;e=c&(1<<b)-1;a.f=c>>>b;a.d=d-b;a.c=h;return e}
function U(a,b){for(var c=a.f,d=a.d,f=a.input,h=a.c,k=f.length,e=b[0],g=b[1],l,p;d<g&&!(h>=k);)c|=f[h++]<<d,d+=8;l=e[c&(1<<g)-1];p=l>>>16;a.f=c>>p;a.d=d-p;a.c=h;return l&65535}
function fa(a){function b(a,b,c){var d,e=this.K,f,g;for(g=0;g<a;)switch(d=U(this,b),d){case 16:for(f=3+I(this,2);f--;)c[g++]=e;break;case 17:for(f=3+I(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+I(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}this.K=e;return c}var c=I(a,5)+257,d=I(a,5)+1,f=I(a,4)+4,h=new (w?Uint8Array:Array)(K.length),k,e,g,l;for(l=0;l<f;++l)h[K[l]]=I(a,3);if(!w){l=f;for(f=h.length;l<f;++l)h[K[l]]=0}k=C(h);e=new (w?Uint8Array:Array)(c);g=new (w?Uint8Array:Array)(d);a.K=
0;a.q(C(b.call(a,c,k,e)),C(b.call(a,d,k,g)))}u=F.prototype;u.q=function(a,b){var c=this.b,d=this.a;this.C=a;for(var f=c.length-258,h,k,e,g;256!==(h=U(this,a));)if(256>h)d>=f&&(this.a=d,c=this.e(),d=this.a),c[d++]=h;else{k=h-257;g=M[k];0<O[k]&&(g+=I(this,O[k]));h=U(this,b);e=ia[h];0<P[h]&&(e+=I(this,P[h]));d>=f&&(this.a=d,c=this.e(),d=this.a);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d};
u.W=function(a,b){var c=this.b,d=this.a;this.C=a;for(var f=c.length,h,k,e,g;256!==(h=U(this,a));)if(256>h)d>=f&&(c=this.e(),f=c.length),c[d++]=h;else{k=h-257;g=M[k];0<O[k]&&(g+=I(this,O[k]));h=U(this,b);e=ia[h];0<P[h]&&(e+=I(this,P[h]));d+g>f&&(c=this.e(),f=c.length);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d};
u.e=function(){var a=new (w?Uint8Array:Array)(this.a-32768),b=this.a-32768,c,d,f=this.b;if(w)a.set(f.subarray(32768,a.length));else{c=0;for(d=a.length;c<d;++c)a[c]=f[c+32768]}this.l.push(a);this.t+=a.length;if(w)f.set(f.subarray(b,b+32768));else for(c=0;32768>c;++c)f[c]=f[b+c];this.a=32768;return f};
u.X=function(a){var b,c=this.input.length/this.c+1|0,d,f,h,k=this.input,e=this.b;a&&("number"===typeof a.H&&(c=a.H),"number"===typeof a.Q&&(c+=a.Q));2>c?(d=(k.length-this.c)/this.C[2],h=258*(d/2)|0,f=h<e.length?e.length+h:e.length<<1):f=e.length*c;w?(b=new Uint8Array(f),b.set(e)):b=e;return this.b=b};
u.B=function(){var a=0,b=this.b,c=this.l,d,f=new (w?Uint8Array:Array)(this.t+(this.a-32768)),h,k,e,g;if(0===c.length)return w?this.b.subarray(32768,this.a):this.b.slice(32768,this.a);h=0;for(k=c.length;h<k;++h){d=c[h];e=0;for(g=d.length;e<g;++e)f[a++]=d[e]}h=32768;for(k=this.a;h<k;++h)f[a++]=b[h];this.l=[];return this.buffer=f};
u.S=function(){var a,b=this.a;w?this.L?(a=new Uint8Array(b),a.set(this.b.subarray(0,b))):a=this.b.subarray(0,b):(this.b.length>b&&(this.b.length=b),a=this.b);return this.buffer=a};function V(a){a=a||{};this.files=[];this.v=a.comment}V.prototype.M=function(a){this.j=a};V.prototype.s=function(a){var b=a[2]&65535|2;return b*(b^1)>>8&255};V.prototype.k=function(a,b){a[0]=(B[(a[0]^b)&255]^a[0]>>>8)>>>0;a[1]=(6681*(20173*(a[1]+(a[0]&255))>>>0)>>>0)+1>>>0;a[2]=(B[(a[2]^a[1]>>>24)&255]^a[2]>>>8)>>>0};V.prototype.U=function(a){var b=[305419896,591751049,878082192],c,d;w&&(b=new Uint32Array(b));c=0;for(d=a.length;c<d;++c)this.k(b,a[c]&255);return b};function W(a,b){b=b||{};this.input=w&&a instanceof Array?new Uint8Array(a):a;this.c=0;this.ca=b.verify||!1;this.j=b.password}var na={P:0,N:8},X=[80,75,1,2],Y=[80,75,3,4],Z=[80,75,5,6];function oa(a,b){this.input=a;this.offset=b}
oa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==X[0]||a[b++]!==X[1]||a[b++]!==X[2]||a[b++]!==X[3])&&m(Error("invalid file header signature"));this.version=a[b++];this.ja=a[b++];this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<
8;this.g=a[b++]|a[b++]<<8;this.F=a[b++]|a[b++]<<8;this.fa=a[b++]|a[b++]<<8;this.ha=a[b++]|a[b++]<<8;this.ga=a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24;this.aa=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.filename=String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.v=w?a.subarray(b,b+this.F):a.slice(b,b+this.F);this.length=b-this.offset};function pa(a,b){this.input=a;this.offset=b}var qa={O:1,da:8,ea:2048};
pa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==Y[0]||a[b++]!==Y[1]||a[b++]!==Y[2]||a[b++]!==Y[3])&&m(Error("invalid local file header signature"));this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<8;this.g=a[b++]|a[b++]<<8;this.filename=
String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.length=b-this.offset};
function $(a){var b=[],c={},d,f,h,k;if(!a.i){if(a.o===q){var e=a.input,g;if(!a.D)a:{var l=a.input,p;for(p=l.length-12;0<p;--p)if(l[p]===Z[0]&&l[p+1]===Z[1]&&l[p+2]===Z[2]&&l[p+3]===Z[3]){a.D=p;break a}m(Error("End of Central Directory Record not found"))}g=a.D;(e[g++]!==Z[0]||e[g++]!==Z[1]||e[g++]!==Z[2]||e[g++]!==Z[3])&&m(Error("invalid signature"));a.ia=e[g++]|e[g++]<<8;a.ka=e[g++]|e[g++]<<8;a.la=e[g++]|e[g++]<<8;a.ba=e[g++]|e[g++]<<8;a.R=(e[g++]|e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.o=(e[g++]|
e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.w=e[g++]|e[g++]<<8;a.v=w?e.subarray(g,g+a.w):e.slice(g,g+a.w)}d=a.o;h=0;for(k=a.ba;h<k;++h)f=new oa(a.input,d),f.parse(),d+=f.length,b[h]=f,c[f.filename]=h;a.R<d-a.o&&m(Error("invalid file header size"));a.i=b;a.G=c}}u=W.prototype;u.Z=function(){var a=[],b,c,d;this.i||$(this);d=this.i;b=0;for(c=d.length;b<c;++b)a[b]=d[b].filename;return a};
u.r=function(a,b){var c;this.G||$(this);c=this.G[a];c===q&&m(Error(a+" not found"));var d;d=b||{};var f=this.input,h=this.i,k,e,g,l,p,s,r,A;h||$(this);h[c]===q&&m(Error("wrong index"));e=h[c].aa;k=new pa(this.input,e);k.parse();e+=k.length;g=k.z;if(0!==(k.I&qa.O)){!d.password&&!this.j&&m(Error("please set password"));s=this.T(d.password||this.j);r=e;for(A=e+12;r<A;++r)ra(this,s,f[r]);e+=12;g-=12;r=e;for(A=e+g;r<A;++r)f[r]=ra(this,s,f[r])}switch(k.A){case na.P:l=w?this.input.subarray(e,e+g):this.input.slice(e,
e+g);break;case na.N:l=(new F(this.input,{index:e,bufferSize:k.J})).r();break;default:m(Error("unknown compression type"))}if(this.ca){var t=q,n,N="number"===typeof t?t:t=0,ka=l.length;n=-1;for(N=ka&7;N--;++t)n=n>>>8^B[(n^l[t])&255];for(N=ka>>3;N--;t+=8)n=n>>>8^B[(n^l[t])&255],n=n>>>8^B[(n^l[t+1])&255],n=n>>>8^B[(n^l[t+2])&255],n=n>>>8^B[(n^l[t+3])&255],n=n>>>8^B[(n^l[t+4])&255],n=n>>>8^B[(n^l[t+5])&255],n=n>>>8^B[(n^l[t+6])&255],n=n>>>8^B[(n^l[t+7])&255];p=(n^4294967295)>>>0;k.p!==p&&m(Error("wrong crc: file=0x"+
k.p.toString(16)+", data=0x"+p.toString(16)))}return l};u.M=function(a){this.j=a};function ra(a,b,c){c^=a.s(b);a.k(b,c);return c}u.k=V.prototype.k;u.T=V.prototype.U;u.s=V.prototype.s;v("Zlib.Unzip",W);v("Zlib.Unzip.prototype.decompress",W.prototype.r);v("Zlib.Unzip.prototype.getFilenames",W.prototype.Z);v("Zlib.Unzip.prototype.setPassword",W.prototype.M);}).call(ZlibNamespace);
module.exports = ZlibNamespace.Zlib;

View File

@ -25,24 +25,28 @@
"url": "https://github.com/js-platform/filer.git" "url": "https://github.com/js-platform/filer.git"
}, },
"dependencies": { "dependencies": {
"bower": "~1.0.0" "bower": "~1.0.0",
"request": "^2.36.0"
}, },
"devDependencies": { "devDependencies": {
"chai": "~1.9.1",
"grunt": "~0.4.0", "grunt": "~0.4.0",
"grunt-browserify": "^2.1.0",
"grunt-bump": "0.0.13", "grunt-bump": "0.0.13",
"grunt-contrib-clean": "~0.4.0", "grunt-contrib-clean": "~0.4.0",
"grunt-contrib-compress": "~0.4.1", "grunt-contrib-compress": "~0.4.1",
"grunt-contrib-concat": "~0.1.3", "grunt-contrib-concat": "~0.1.3",
"grunt-contrib-connect": "~0.7.1", "grunt-contrib-connect": "^0.7.1",
"grunt-contrib-jshint": "~0.7.1", "grunt-contrib-jshint": "~0.7.1",
"grunt-contrib-requirejs": "~0.4.0",
"grunt-contrib-uglify": "~0.1.2", "grunt-contrib-uglify": "~0.1.2",
"grunt-contrib-watch": "~0.3.1", "grunt-contrib-watch": "~0.3.1",
"grunt-git": "0.2.10", "grunt-git": "0.2.10",
"grunt-mocha": "0.4.10",
"grunt-npm": "git://github.com/sedge/grunt-npm.git#branchcheck", "grunt-npm": "git://github.com/sedge/grunt-npm.git#branchcheck",
"grunt-prompt": "^1.1.0", "grunt-prompt": "^1.1.0",
"grunt-shell": "~0.7.0",
"habitat": "^1.1.0", "habitat": "^1.1.0",
"mocha": "~1.18.2",
"semver": "^2.3.0" "semver": "^2.3.0"
} },
"main": "./src/index.js"
} }

View File

@ -1,8 +0,0 @@
define(function(require) {
return {
Compression: require('src/adapters/zlib'),
Encryption: require('src/adapters/crypto')
};
});

View File

@ -1,124 +0,0 @@
define(function(require) {
// AES encryption, see http://code.google.com/p/crypto-js/#AES
require("crypto-js/rollups/aes");
// Move back and forth from Uint8Arrays and CryptoJS WordArray
// See http://code.google.com/p/crypto-js/#The_Cipher_Input and
// https://groups.google.com/forum/#!topic/crypto-js/TOb92tcJlU0
var WordArray = CryptoJS.lib.WordArray;
function fromWordArray(wordArray) {
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var u8 = new Uint8Array(sigBytes);
var b;
for (var i = 0; i < sigBytes; i++) {
b = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
u8[i] = b;
}
return u8;
}
function toWordArray(u8arr) {
var len = u8arr.length;
var words = [];
for (var i = 0; i < len; i++) {
words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8);
}
return WordArray.create(words, len);
}
// UTF8 Text De/Encoders
require('encoding');
function encode(str) {
return (new TextEncoder('utf-8')).encode(str);
}
function decode(u8arr) {
return (new TextDecoder('utf-8')).decode(u8arr);
}
function CryptoContext(context, encrypt, decrypt) {
this.context = context;
this.encrypt = encrypt;
this.decrypt = decrypt;
}
CryptoContext.prototype.clear = function(callback) {
this.context.clear(callback);
};
CryptoContext.prototype.get = function(key, callback) {
var decrypt = this.decrypt;
this.context.get(key, function(err, value) {
if(err) {
callback(err);
return;
}
if(value) {
value = decrypt(value);
}
callback(null, value);
});
};
CryptoContext.prototype.put = function(key, value, callback) {
var encryptedValue = this.encrypt(value);
this.context.put(key, encryptedValue, callback);
};
CryptoContext.prototype.delete = function(key, callback) {
this.context.delete(key, callback);
};
// It is up to the app using this wrapper how the passphrase is acquired, probably by
// prompting the user to enter it when the file system is being opened.
function CryptoAdapter(passphrase, provider) {
this.provider = provider;
// Cache cipher algorithm we'll use in encrypt/decrypt
var cipher = CryptoJS.AES;
// To encrypt:
// 1) accept a buffer (Uint8Array) containing binary data
// 2) convert the buffer to a CipherJS WordArray
// 3) encrypt the WordArray using the chosen cipher algorithm + passphrase
// 4) convert the resulting ciphertext to a UTF8 encoded Uint8Array and return
this.encrypt = function(buffer) {
var wordArray = toWordArray(buffer);
var encrypted = cipher.encrypt(wordArray, passphrase);
var utf8EncodedBuf = encode(encrypted);
return utf8EncodedBuf;
};
// To decrypt:
// 1) accept a buffer (Uint8Array) containing a UTF8 encoded Uint8Array
// 2) convert the buffer to string (i.e., the ciphertext we got from encrypting)
// 3) decrypt the ciphertext string
// 4) convert the decrypted cipherParam object to a UTF8 string
// 5) encode the UTF8 string to a Uint8Array buffer and return
this.decrypt = function(buffer) {
var encryptedStr = decode(buffer);
var decrypted = cipher.decrypt(encryptedStr, passphrase);
var decryptedUtf8 = decrypted.toString(CryptoJS.enc.Utf8);
var utf8EncodedBuf = encode(decryptedUtf8);
return utf8EncodedBuf;
};
}
CryptoAdapter.isSupported = function() {
return true;
};
CryptoAdapter.prototype.open = function(callback) {
this.provider.open(callback);
};
CryptoAdapter.prototype.getReadOnlyContext = function() {
return new CryptoContext(this.provider.getReadOnlyContext(),
this.encrypt,
this.decrypt);
};
CryptoAdapter.prototype.getReadWriteContext = function() {
return new CryptoContext(this.provider.getReadWriteContext(),
this.encrypt,
this.decrypt);
};
return CryptoAdapter;
});

View File

@ -1,63 +0,0 @@
define(function(require) {
// Zlib compression, see
// https://github.com/imaya/zlib.js/blob/master/bin/zlib.min.js
require("zlib");
var Inflate = Zlib.Inflate;
function inflate(compressed) {
return (new Inflate(compressed)).decompress();
}
var Deflate = Zlib.Deflate;
function deflate(buffer) {
return (new Deflate(buffer)).compress();
}
function ZlibContext(context) {
this.context = context;
}
ZlibContext.prototype.clear = function(callback) {
this.context.clear(callback);
};
ZlibContext.prototype.get = function(key, callback) {
this.context.get(key, function(err, result) {
if(err) {
callback(err);
return;
}
// Deal with result being null
if(result) {
result = inflate(result);
}
callback(null, result);
});
};
ZlibContext.prototype.put = function(key, value, callback) {
value = deflate(value);
this.context.put(key, value, callback);
};
ZlibContext.prototype.delete = function(key, callback) {
this.context.delete(key, callback);
};
function ZlibAdapter(provider, inflate, deflate) {
this.provider = provider;
}
ZlibAdapter.isSupported = function() {
return true;
};
ZlibAdapter.prototype.open = function(callback) {
this.provider.open(callback);
};
ZlibAdapter.prototype.getReadOnlyContext = function() {
return new ZlibContext(this.provider.getReadOnlyContext());
};
ZlibAdapter.prototype.getReadWriteContext = function() {
return new ZlibContext(this.provider.getReadWriteContext());
};
return ZlibAdapter;
});

View File

@ -1,83 +1,79 @@
define(function(require) { var O_READ = 'READ';
var O_WRITE = 'WRITE';
var O_CREATE = 'CREATE';
var O_EXCLUSIVE = 'EXCLUSIVE';
var O_TRUNCATE = 'TRUNCATE';
var O_APPEND = 'APPEND';
var XATTR_CREATE = 'CREATE';
var XATTR_REPLACE = 'REPLACE';
var O_READ = 'READ'; module.exports = {
var O_WRITE = 'WRITE'; FILE_SYSTEM_NAME: 'local',
var O_CREATE = 'CREATE';
var O_EXCLUSIVE = 'EXCLUSIVE';
var O_TRUNCATE = 'TRUNCATE';
var O_APPEND = 'APPEND';
var XATTR_CREATE = 'CREATE';
var XATTR_REPLACE = 'REPLACE';
return { FILE_STORE_NAME: 'files',
FILE_SYSTEM_NAME: 'local',
FILE_STORE_NAME: 'files', IDB_RO: 'readonly',
IDB_RW: 'readwrite',
IDB_RO: 'readonly', WSQL_VERSION: "1",
IDB_RW: 'readwrite', WSQL_SIZE: 5 * 1024 * 1024,
WSQL_DESC: "FileSystem Storage",
WSQL_VERSION: "1", MODE_FILE: 'FILE',
WSQL_SIZE: 5 * 1024 * 1024, MODE_DIRECTORY: 'DIRECTORY',
WSQL_DESC: "FileSystem Storage", MODE_SYMBOLIC_LINK: 'SYMLINK',
MODE_META: 'META',
MODE_FILE: 'FILE', SYMLOOP_MAX: 10,
MODE_DIRECTORY: 'DIRECTORY',
MODE_SYMBOLIC_LINK: 'SYMLINK',
MODE_META: 'META',
SYMLOOP_MAX: 10, BINARY_MIME_TYPE: 'application/octet-stream',
JSON_MIME_TYPE: 'application/json',
BINARY_MIME_TYPE: 'application/octet-stream', ROOT_DIRECTORY_NAME: '/', // basename(normalize(path))
JSON_MIME_TYPE: 'application/json',
ROOT_DIRECTORY_NAME: '/', // basename(normalize(path)) // FS Mount Flags
FS_FORMAT: 'FORMAT',
FS_NOCTIME: 'NOCTIME',
FS_NOMTIME: 'NOMTIME',
// FS Mount Flags // FS File Open Flags
FS_FORMAT: 'FORMAT', O_READ: O_READ,
FS_NOCTIME: 'NOCTIME', O_WRITE: O_WRITE,
FS_NOMTIME: 'NOMTIME', O_CREATE: O_CREATE,
O_EXCLUSIVE: O_EXCLUSIVE,
O_TRUNCATE: O_TRUNCATE,
O_APPEND: O_APPEND,
// FS File Open Flags O_FLAGS: {
O_READ: O_READ, 'r': [O_READ],
O_WRITE: O_WRITE, 'r+': [O_READ, O_WRITE],
O_CREATE: O_CREATE, 'w': [O_WRITE, O_CREATE, O_TRUNCATE],
O_EXCLUSIVE: O_EXCLUSIVE, 'w+': [O_WRITE, O_READ, O_CREATE, O_TRUNCATE],
O_TRUNCATE: O_TRUNCATE, 'wx': [O_WRITE, O_CREATE, O_EXCLUSIVE, O_TRUNCATE],
O_APPEND: O_APPEND, 'wx+': [O_WRITE, O_READ, O_CREATE, O_EXCLUSIVE, O_TRUNCATE],
'a': [O_WRITE, O_CREATE, O_APPEND],
'a+': [O_WRITE, O_READ, O_CREATE, O_APPEND],
'ax': [O_WRITE, O_CREATE, O_EXCLUSIVE, O_APPEND],
'ax+': [O_WRITE, O_READ, O_CREATE, O_EXCLUSIVE, O_APPEND]
},
O_FLAGS: { XATTR_CREATE: XATTR_CREATE,
'r': [O_READ], XATTR_REPLACE: XATTR_REPLACE,
'r+': [O_READ, O_WRITE],
'w': [O_WRITE, O_CREATE, O_TRUNCATE],
'w+': [O_WRITE, O_READ, O_CREATE, O_TRUNCATE],
'wx': [O_WRITE, O_CREATE, O_EXCLUSIVE, O_TRUNCATE],
'wx+': [O_WRITE, O_READ, O_CREATE, O_EXCLUSIVE, O_TRUNCATE],
'a': [O_WRITE, O_CREATE, O_APPEND],
'a+': [O_WRITE, O_READ, O_CREATE, O_APPEND],
'ax': [O_WRITE, O_CREATE, O_EXCLUSIVE, O_APPEND],
'ax+': [O_WRITE, O_READ, O_CREATE, O_EXCLUSIVE, O_APPEND]
},
XATTR_CREATE: XATTR_CREATE, FS_READY: 'READY',
XATTR_REPLACE: XATTR_REPLACE, FS_PENDING: 'PENDING',
FS_ERROR: 'ERROR',
FS_READY: 'READY', SUPER_NODE_ID: '00000000-0000-0000-0000-000000000000',
FS_PENDING: 'PENDING',
FS_ERROR: 'ERROR',
SUPER_NODE_ID: '00000000-0000-0000-0000-000000000000', // Reserved File Descriptors for streams
STDIN: 0,
STDOUT: 1,
STDERR: 2,
FIRST_DESCRIPTOR: 3,
// Reserved File Descriptors for streams ENVIRONMENT: {
STDIN: 0, TMP: '/tmp',
STDOUT: 1, PATH: ''
STDERR: 2, }
FIRST_DESCRIPTOR: 3, };
ENVIRONMENT: {
TMP: '/tmp',
PATH: ''
}
};
});

View File

@ -1,8 +1,6 @@
define(['src/constants'], function(Constants) { var MODE_FILE = require('./constants.js').MODE_FILE;
return function DirectoryEntry(id, type) { module.exports = function DirectoryEntry(id, type) {
this.id = id; this.id = id;
this.type = type || Constants.MODE_FILE; this.type = type || MODE_FILE;
}; };
});

View File

@ -1,94 +1,92 @@
define(function(require) { var errors = {};
var errors = {}; [
[ /**
/** * node.js errors
* node.js errors */
*/ '-1:UNKNOWN:unknown error',
'-1:UNKNOWN:unknown error', '0:OK:success',
'0:OK:success', '1:EOF:end of file',
'1:EOF:end of file', '2:EADDRINFO:getaddrinfo error',
'2:EADDRINFO:getaddrinfo error', '3:EACCES:permission denied',
'3:EACCES:permission denied', '4:EAGAIN:resource temporarily unavailable',
'4:EAGAIN:resource temporarily unavailable', '5:EADDRINUSE:address already in use',
'5:EADDRINUSE:address already in use', '6:EADDRNOTAVAIL:address not available',
'6:EADDRNOTAVAIL:address not available', '7:EAFNOSUPPORT:address family not supported',
'7:EAFNOSUPPORT:address family not supported', '8:EALREADY:connection already in progress',
'8:EALREADY:connection already in progress', '9:EBADF:bad file descriptor',
'9:EBADF:bad file descriptor', '10:EBUSY:resource busy or locked',
'10:EBUSY:resource busy or locked', '11:ECONNABORTED:software caused connection abort',
'11:ECONNABORTED:software caused connection abort', '12:ECONNREFUSED:connection refused',
'12:ECONNREFUSED:connection refused', '13:ECONNRESET:connection reset by peer',
'13:ECONNRESET:connection reset by peer', '14:EDESTADDRREQ:destination address required',
'14:EDESTADDRREQ:destination address required', '15:EFAULT:bad address in system call argument',
'15:EFAULT:bad address in system call argument', '16:EHOSTUNREACH:host is unreachable',
'16:EHOSTUNREACH:host is unreachable', '17:EINTR:interrupted system call',
'17:EINTR:interrupted system call', '18:EINVAL:invalid argument',
'18:EINVAL:invalid argument', '19:EISCONN:socket is already connected',
'19:EISCONN:socket is already connected', '20:EMFILE:too many open files',
'20:EMFILE:too many open files', '21:EMSGSIZE:message too long',
'21:EMSGSIZE:message too long', '22:ENETDOWN:network is down',
'22:ENETDOWN:network is down', '23:ENETUNREACH:network is unreachable',
'23:ENETUNREACH:network is unreachable', '24:ENFILE:file table overflow',
'24:ENFILE:file table overflow', '25:ENOBUFS:no buffer space available',
'25:ENOBUFS:no buffer space available', '26:ENOMEM:not enough memory',
'26:ENOMEM:not enough memory', '27:ENOTDIR:not a directory',
'27:ENOTDIR:not a directory', '28:EISDIR:illegal operation on a directory',
'28:EISDIR:illegal operation on a directory', '29:ENONET:machine is not on the network',
'29:ENONET:machine is not on the network', // errno 30 skipped, as per https://github.com/rvagg/node-errno/blob/master/errno.js
// errno 30 skipped, as per https://github.com/rvagg/node-errno/blob/master/errno.js '31:ENOTCONN:socket is not connected',
'31:ENOTCONN:socket is not connected', '32:ENOTSOCK:socket operation on non-socket',
'32:ENOTSOCK:socket operation on non-socket', '33:ENOTSUP:operation not supported on socket',
'33:ENOTSUP:operation not supported on socket', '34:ENOENT:no such file or directory',
'34:ENOENT:no such file or directory', '35:ENOSYS:function not implemented',
'35:ENOSYS:function not implemented', '36:EPIPE:broken pipe',
'36:EPIPE:broken pipe', '37:EPROTO:protocol error',
'37:EPROTO:protocol error', '38:EPROTONOSUPPORT:protocol not supported',
'38:EPROTONOSUPPORT:protocol not supported', '39:EPROTOTYPE:protocol wrong type for socket',
'39:EPROTOTYPE:protocol wrong type for socket', '40:ETIMEDOUT:connection timed out',
'40:ETIMEDOUT:connection timed out', '41:ECHARSET:invalid Unicode character',
'41:ECHARSET:invalid Unicode character', '42:EAIFAMNOSUPPORT:address family for hostname not supported',
'42:EAIFAMNOSUPPORT:address family for hostname not supported', // errno 43 skipped, as per https://github.com/rvagg/node-errno/blob/master/errno.js
// errno 43 skipped, as per https://github.com/rvagg/node-errno/blob/master/errno.js '44:EAISERVICE:servname not supported for ai_socktype',
'44:EAISERVICE:servname not supported for ai_socktype', '45:EAISOCKTYPE:ai_socktype not supported',
'45:EAISOCKTYPE:ai_socktype not supported', '46:ESHUTDOWN:cannot send after transport endpoint shutdown',
'46:ESHUTDOWN:cannot send after transport endpoint shutdown', '47:EEXIST:file already exists',
'47:EEXIST:file already exists', '48:ESRCH:no such process',
'48:ESRCH:no such process', '49:ENAMETOOLONG:name too long',
'49:ENAMETOOLONG:name too long', '50:EPERM:operation not permitted',
'50:EPERM:operation not permitted', '51:ELOOP:too many symbolic links encountered',
'51:ELOOP:too many symbolic links encountered', '52:EXDEV:cross-device link not permitted',
'52:EXDEV:cross-device link not permitted', '53:ENOTEMPTY:directory not empty',
'53:ENOTEMPTY:directory not empty', '54:ENOSPC:no space left on device',
'54:ENOSPC:no space left on device', '55:EIO:i/o error',
'55:EIO:i/o error', '56:EROFS:read-only file system',
'56:EROFS:read-only file system', '57:ENODEV:no such device',
'57:ENODEV:no such device', '58:ESPIPE:invalid seek',
'58:ESPIPE:invalid seek', '59:ECANCELED:operation canceled',
'59:ECANCELED:operation canceled',
/** /**
* Filer specific errors * Filer specific errors
*/ */
'1000:ENOTMOUNTED:not mounted', '1000:ENOTMOUNTED:not mounted',
'1001:EFILESYSTEMERROR:missing super node, use \'FORMAT\' flag to format filesystem.', '1001:EFILESYSTEMERROR:missing super node, use \'FORMAT\' flag to format filesystem.',
'1002:ENOATTR:attribute does not exist' '1002:ENOATTR:attribute does not exist'
].forEach(function(e) { ].forEach(function(e) {
e = e.split(':'); e = e.split(':');
var errno = e[0], var errno = e[0],
err = e[1], err = e[1],
message = e[2]; message = e[2];
function ctor(m) { function ctor(m) {
this.message = m || message; this.message = m || message;
} }
var proto = ctor.prototype = new Error(); var proto = ctor.prototype = new Error();
proto.errno = errno; proto.errno = errno;
proto.code = err; proto.code = err;
proto.constructor = ctor; proto.constructor = ctor;
// We expose the error as both Errors.EINVAL and Errors[18] // We expose the error as both Errors.EINVAL and Errors[18]
errors[err] = errors[errno] = ctor; errors[err] = errors[errno] = ctor;
});
return errors;
}); });
module.exports = errors;

File diff suppressed because it is too large Load Diff

View File

@ -1,302 +1,295 @@
define(function(require) { var _ = require('../../lib/nodash.js');
var _ = require('nodash'); var isNullPath = require('../path.js').isNull;
var nop = require('../shared.js').nop;
var isNullPath = require('src/path').isNull; var Constants = require('../constants.js');
var nop = require('src/shared').nop; var FILE_SYSTEM_NAME = Constants.FILE_SYSTEM_NAME;
var FS_FORMAT = Constants.FS_FORMAT;
var FS_READY = Constants.FS_READY;
var FS_PENDING = Constants.FS_PENDING;
var FS_ERROR = Constants.FS_ERROR;
var FILE_SYSTEM_NAME = require('src/constants').FILE_SYSTEM_NAME; var providers = require('../providers/index.js');
var FS_FORMAT = require('src/constants').FS_FORMAT;
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 providers = require('src/providers/providers'); var Shell = require('../shell/shell.js');
var adapters = require('src/adapters/adapters'); var Intercom = require('../../lib/intercom.js');
var FSWatcher = require('../fs-watcher.js');
var Errors = require('../errors.js');
var Shell = require('src/shell/shell'); var STDIN = Constants.STDIN;
var Intercom = require('intercom'); var STDOUT = Constants.STDOUT;
var FSWatcher = require('src/fs-watcher'); var STDERR = Constants.STDERR;
var Errors = require('src/errors'); var FIRST_DESCRIPTOR = Constants.FIRST_DESCRIPTOR;
var STDIN = require('src/constants').STDIN;
var STDOUT = require('src/constants').STDOUT;
var STDERR = require('src/constants').STDERR;
var FIRST_DESCRIPTOR = require('src/constants').FIRST_DESCRIPTOR;
// The core fs operations live on impl // The core fs operations live on impl
var impl = require('src/filesystem/implementation'); var impl = require('./implementation.js');
// node.js supports a calling pattern that leaves off a callback. // node.js supports a calling pattern that leaves off a callback.
function maybeCallback(callback) { function maybeCallback(callback) {
if(typeof callback === "function") { if(typeof callback === "function") {
return callback; return callback;
}
return function(err) {
if(err) {
throw err;
}
};
} }
return function(err) {
if(err) {
throw err;
}
};
}
/** /**
* FileSystem * FileSystem
* *
* A FileSystem takes an `options` object, which can specify a number of, * A FileSystem takes an `options` object, which can specify a number of,
* options. All options are optional, and include: * options. All options are optional, and include:
* *
* name: the name of the file system, defaults to "local" * name: the name of the file system, defaults to "local"
* *
* flags: one or more flags to use when creating/opening the file system. * flags: one or more flags to use when creating/opening the file system.
* For example: "FORMAT" will cause the file system to be formatted. * For example: "FORMAT" will cause the file system to be formatted.
* No explicit flags are set by default. * No explicit flags are set by default.
* *
* provider: an explicit storage provider to use for the file * provider: an explicit storage provider to use for the file
* system's database context provider. A number of context * system's database context provider. A number of context
* providers are included (see /src/providers), and users * providers are included (see /src/providers), and users
* can write one of their own and pass it in to be used. * can write one of their own and pass it in to be used.
* By default an IndexedDB provider is used. * By default an IndexedDB provider is used.
* *
* callback: a callback function to be executed when the file system becomes * callback: a callback function to be executed when the file system becomes
* ready for use. Depending on the context provider used, this might * ready for use. Depending on the context provider used, this might
* be right away, or could take some time. The callback should expect * be right away, or could take some time. The callback should expect
* an `error` argument, which will be null if everything worked. Also * an `error` argument, which will be null if everything worked. Also
* users should check the file system's `readyState` and `error` * users should check the file system's `readyState` and `error`
* properties to make sure it is usable. * properties to make sure it is usable.
*/ */
function FileSystem(options, callback) { function FileSystem(options, callback) {
options = options || {}; options = options || {};
callback = callback || nop; callback = callback || nop;
var flags = options.flags; var flags = options.flags;
var provider = options.provider || new providers.Default(options.name || FILE_SYSTEM_NAME); var provider = options.provider || new providers.Default(options.name || FILE_SYSTEM_NAME);
// If we're given a provider, match its name unless we get an explicit name // If we're given a provider, match its name unless we get an explicit name
var name = options.name || provider.name; var name = options.name || provider.name;
var forceFormatting = _(flags).contains(FS_FORMAT); var forceFormatting = _(flags).contains(FS_FORMAT);
var fs = this; var fs = this;
fs.readyState = FS_PENDING; fs.readyState = FS_PENDING;
fs.name = name; fs.name = name;
fs.error = null; fs.error = null;
fs.stdin = STDIN; fs.stdin = STDIN;
fs.stdout = STDOUT; fs.stdout = STDOUT;
fs.stderr = STDERR; fs.stderr = STDERR;
// Safely expose the list of open files and file // Safely expose the list of open files and file
// descriptor management functions // descriptor management functions
var openFiles = {}; var openFiles = {};
var nextDescriptor = FIRST_DESCRIPTOR; var nextDescriptor = FIRST_DESCRIPTOR;
Object.defineProperty(this, "openFiles", { Object.defineProperty(this, "openFiles", {
get: function() { return openFiles; } get: function() { return openFiles; }
}); });
this.allocDescriptor = function(openFileDescription) { this.allocDescriptor = function(openFileDescription) {
var fd = nextDescriptor ++; var fd = nextDescriptor ++;
openFiles[fd] = openFileDescription; openFiles[fd] = openFileDescription;
return fd; return fd;
}; };
this.releaseDescriptor = function(fd) { this.releaseDescriptor = function(fd) {
delete openFiles[fd]; delete openFiles[fd];
}; };
// Safely expose the operation queue // Safely expose the operation queue
var queue = []; var queue = [];
this.queueOrRun = function(operation) { this.queueOrRun = function(operation) {
var error; var error;
if(FS_READY == fs.readyState) { if(FS_READY == fs.readyState) {
operation.call(fs); operation.call(fs);
} else if(FS_ERROR == fs.readyState) { } else if(FS_ERROR == fs.readyState) {
error = new Errors.EFILESYSTEMERROR('unknown error'); error = new Errors.EFILESYSTEMERROR('unknown error');
} else { } else {
queue.push(operation); queue.push(operation);
}
return error;
};
function runQueued() {
queue.forEach(function(operation) {
operation.call(this);
}.bind(fs));
queue = null;
} }
// We support the optional `options` arg from node, but ignore it return error;
this.watch = function(filename, options, listener) { };
if(isNullPath(filename)) { function runQueued() {
throw new Error('Path must be a string without null bytes.'); queue.forEach(function(operation) {
} operation.call(this);
if(typeof options === 'function') { }.bind(fs));
listener = options; queue = null;
options = {}; }
}
options = options || {};
listener = listener || nop;
var watcher = new FSWatcher(); // We support the optional `options` arg from node, but ignore it
watcher.start(filename, false, options.recursive); this.watch = function(filename, options, listener) {
watcher.on('change', listener); if(isNullPath(filename)) {
throw new Error('Path must be a string without null bytes.');
return watcher;
};
// Let other instances (in this or other windows) know about
// any changes to this fs instance.
function broadcastChanges(changes) {
if(!changes.length) {
return;
}
var intercom = Intercom.getInstance();
changes.forEach(function(change) {
intercom.emit(change.event, change.path);
});
} }
if(typeof options === 'function') {
listener = options;
options = {};
}
options = options || {};
listener = listener || nop;
// Open file system storage provider var watcher = new FSWatcher();
provider.open(function(err, needsFormatting) { watcher.start(filename, false, options.recursive);
function complete(error) { watcher.on('change', listener);
function wrappedContext(methodName) { return watcher;
var context = provider[methodName](); };
context.flags = flags;
context.changes = [];
// When the context is finished, let the fs deal with any change events // Let other instances (in this or other windows) know about
context.close = function() { // any changes to this fs instance.
var changes = context.changes; function broadcastChanges(changes) {
broadcastChanges(changes); if(!changes.length) {
changes.length = 0; return;
}; }
var intercom = Intercom.getInstance();
return context; changes.forEach(function(change) {
} intercom.emit(change.event, change.path);
// Wrap the provider so we can extend the context with fs flags and
// an array of changes (e.g., watch event 'change' and 'rename' events
// for paths updated during the lifetime of the context). From this
// point forward we won't call open again, so it's safe to drop it.
fs.provider = {
openReadWriteContext: function() {
return wrappedContext('getReadWriteContext');
},
openReadOnlyContext: function() {
return wrappedContext('getReadOnlyContext');
}
};
if(error) {
fs.readyState = FS_ERROR;
} else {
fs.readyState = FS_READY;
runQueued();
}
callback(error, fs);
}
if(err) {
return complete(err);
}
// If we don't need or want formatting, we're done
if(!(forceFormatting || needsFormatting)) {
return complete(null);
}
// otherwise format the fs first
var context = provider.getReadWriteContext();
context.clear(function(err) {
if(err) {
complete(err);
return;
}
impl.makeRootDirectory(context, complete);
});
}); });
} }
// Expose storage providers on FileSystem constructor // Open file system storage provider
FileSystem.providers = providers; provider.open(function(err, needsFormatting) {
function complete(error) {
// Expose adatpers on FileSystem constructor function wrappedContext(methodName) {
FileSystem.adapters = adapters; var context = provider[methodName]();
context.flags = flags;
context.changes = [];
/** // When the context is finished, let the fs deal with any change events
* Public API for FileSystem context.close = function() {
*/ var changes = context.changes;
[ broadcastChanges(changes);
'open', changes.length = 0;
'close', };
'mknod',
'mkdir',
'rmdir',
'stat',
'fstat',
'link',
'unlink',
'read',
'readFile',
'write',
'writeFile',
'appendFile',
'exists',
'lseek',
'readdir',
'rename',
'readlink',
'symlink',
'lstat',
'truncate',
'ftruncate',
'utimes',
'futimes',
'setxattr',
'getxattr',
'fsetxattr',
'fgetxattr',
'removexattr',
'fremovexattr'
].forEach(function(methodName) {
FileSystem.prototype[methodName] = function() {
var fs = this;
var args = Array.prototype.slice.call(arguments, 0);
var lastArgIndex = args.length - 1;
// We may or may not get a callback, and since node.js supports return context;
// fire-and-forget style fs operations, we have to dance a bit here.
var missingCallback = typeof args[lastArgIndex] !== 'function';
var callback = maybeCallback(args[lastArgIndex]);
var error = fs.queueOrRun(function() {
var context = fs.provider.openReadWriteContext();
// Wrap the callback so we can explicitly close the context
function complete() {
context.close();
callback.apply(fs, arguments);
}
// Either add or replace the callback with our wrapper complete()
if(missingCallback) {
args.push(complete);
} else {
args[lastArgIndex] = complete;
}
// Forward this call to the impl's version, using the following
// call signature, with complete() as the callback/last-arg now:
// fn(fs, context, arg0, arg1, ... , complete);
var fnArgs = [fs, context].concat(args);
impl[methodName].apply(null, fnArgs);
});
if(error) {
callback(error);
} }
};
// Wrap the provider so we can extend the context with fs flags and
// an array of changes (e.g., watch event 'change' and 'rename' events
// for paths updated during the lifetime of the context). From this
// point forward we won't call open again, so it's safe to drop it.
fs.provider = {
openReadWriteContext: function() {
return wrappedContext('getReadWriteContext');
},
openReadOnlyContext: function() {
return wrappedContext('getReadOnlyContext');
}
};
if(error) {
fs.readyState = FS_ERROR;
} else {
fs.readyState = FS_READY;
runQueued();
}
callback(error, fs);
}
if(err) {
return complete(err);
}
// If we don't need or want formatting, we're done
if(!(forceFormatting || needsFormatting)) {
return complete(null);
}
// otherwise format the fs first
var context = provider.getReadWriteContext();
context.clear(function(err) {
if(err) {
complete(err);
return;
}
impl.makeRootDirectory(context, complete);
});
}); });
}
FileSystem.prototype.Shell = function(options) { // Expose storage providers on FileSystem constructor
return new Shell(this, options); FileSystem.providers = providers;
/**
* Public API for FileSystem
*/
[
'open',
'close',
'mknod',
'mkdir',
'rmdir',
'stat',
'fstat',
'link',
'unlink',
'read',
'readFile',
'write',
'writeFile',
'appendFile',
'exists',
'lseek',
'readdir',
'rename',
'readlink',
'symlink',
'lstat',
'truncate',
'ftruncate',
'utimes',
'futimes',
'setxattr',
'getxattr',
'fsetxattr',
'fgetxattr',
'removexattr',
'fremovexattr'
].forEach(function(methodName) {
FileSystem.prototype[methodName] = function() {
var fs = this;
var args = Array.prototype.slice.call(arguments, 0);
var lastArgIndex = args.length - 1;
// We may or may not get a callback, and since node.js supports
// fire-and-forget style fs operations, we have to dance a bit here.
var missingCallback = typeof args[lastArgIndex] !== 'function';
var callback = maybeCallback(args[lastArgIndex]);
var error = fs.queueOrRun(function() {
var context = fs.provider.openReadWriteContext();
// Wrap the callback so we can explicitly close the context
function complete() {
context.close();
callback.apply(fs, arguments);
}
// Either add or replace the callback with our wrapper complete()
if(missingCallback) {
args.push(complete);
} else {
args[lastArgIndex] = complete;
}
// Forward this call to the impl's version, using the following
// call signature, with complete() as the callback/last-arg now:
// fn(fs, context, arg0, arg1, ... , complete);
var fnArgs = [fs, context].concat(args);
impl[methodName].apply(null, fnArgs);
});
if(error) {
callback(error);
}
}; };
return FileSystem;
}); });
FileSystem.prototype.Shell = function(options) {
return new Shell(this, options);
};
module.exports = FileSystem;

View File

@ -1,54 +1,51 @@
define(function(require) { var EventEmitter = require('../lib/eventemitter.js');
var isNullPath = require('./path.js').isNull;
var Intercom = require('../lib/intercom.js');
var EventEmitter = require('eventemitter'); /**
var isNullPath = require('src/path').isNull; * FSWatcher based on node.js' FSWatcher
var Intercom = require('intercom'); * see https://github.com/joyent/node/blob/master/lib/fs.js
*/
function FSWatcher() {
EventEmitter.call(this);
var self = this;
var recursive = false;
var filename;
/** function onchange(path) {
* FSWatcher based on node.js' FSWatcher // Watch for exact filename, or parent path when recursive is true
* see https://github.com/joyent/node/blob/master/lib/fs.js if(filename === path || (recursive && path.indexOf(filename + '/') === 0)) {
*/ self.trigger('change', 'change', path);
function FSWatcher() { }
EventEmitter.call(this); }
var self = this;
var recursive = false;
var filename;
function onchange(path) { // We support, but ignore the second arg, which node.js uses.
// Watch for exact filename, or parent path when recursive is true self.start = function(filename_, persistent_, recursive_) {
if(filename === path || (recursive && path.indexOf(filename + '/') === 0)) { // Bail if we've already started (and therefore have a filename);
self.trigger('change', 'change', path); if(filename) {
} return;
} }
// We support, but ignore the second arg, which node.js uses. if(isNullPath(filename_)) {
self.start = function(filename_, persistent_, recursive_) { throw new Error('Path must be a string without null bytes.');
// Bail if we've already started (and therefore have a filename); }
if(filename) { // TODO: get realpath for symlinks on filename...
return; filename = filename_;
}
if(isNullPath(filename_)) { // Whether to watch beneath this path or not
throw new Error('Path must be a string without null bytes.'); recursive = recursive_ === true;
}
// TODO: get realpath for symlinks on filename...
filename = filename_;
// Whether to watch beneath this path or not var intercom = Intercom.getInstance();
recursive = recursive_ === true; intercom.on('change', onchange);
};
var intercom = Intercom.getInstance(); self.close = function() {
intercom.on('change', onchange); var intercom = Intercom.getInstance();
}; intercom.off('change', onchange);
self.removeAllListeners('change');
};
}
FSWatcher.prototype = new EventEmitter();
FSWatcher.prototype.constructor = FSWatcher;
self.close = function() { module.exports = FSWatcher;
var intercom = Intercom.getInstance();
intercom.off('change', onchange);
self.removeAllListeners('change');
};
}
FSWatcher.prototype = new EventEmitter();
FSWatcher.prototype.constructor = FSWatcher;
return FSWatcher;
});

View File

@ -1,7 +1,5 @@
define(function(require) { module.exports = {
return { FileSystem: require('./filesystem/interface.js'),
FileSystem: require('src/filesystem/interface'), Path: require('./path.js'),
Path: require('src/path'), Errors: require('./errors.js')
Errors: require('src/errors') };
};
});

59
src/network.js Normal file
View File

@ -0,0 +1,59 @@
function browserDownload(uri, callback) {
var query = new XMLHttpRequest();
query.onload = function() {
var err = query.status != 200 ? { message: query.statusText, code: query.status } : null,
data = err ? null : new Uint8Array(query.response);
callback(err, data);
};
query.open("GET", uri);
if("withCredentials" in query) {
query.withCredentials = true;
}
query.responseType = "arraybuffer";
query.send();
}
function nodeDownload(uri, callback) {
require('request')({
url: uri,
method: "GET",
encoding: null
}, function(err, msg, body) {
var data = null,
arrayBuffer,
statusCode,
arrayLength = body && body.length,
error;
msg = msg || null;
statusCode = msg && msg.statusCode;
error = statusCode != 200 ? { message: err || 'Not found!', code: statusCode } : null;
if (error) {
return callback(error, null);
}
arrayBuffer = arrayLength && new ArrayBuffer(arrayLength);
// Convert buffer to Uint8Array
if (arrayBuffer && (statusCode == 200)) {
data = new Uint8Array(arrayBuffer);
for (var i = 0; i < body.length; ++i) {
data[i] = body[i];
}
}
callback(null, data);
});
}
module.exports.download = (function() {
if (typeof XMLHttpRequest === 'undefined') {
return nodeDownload;
} else {
return browserDownload;
}
}());

View File

@ -1,21 +1,20 @@
define(['src/constants', 'src/shared'], function(Constants, Shared) { var MODE_FILE = require('./constants.js').MODE_FILE;
var guid = require('./shared.js').guid;
return function Node(id, mode, size, atime, ctime, mtime, flags, xattrs, nlinks, version) { module.exports = function Node(id, mode, size, atime, ctime, mtime, flags, xattrs, nlinks, version) {
var now = Date.now(); var now = Date.now();
this.id = id || Shared.guid(); this.id = id || guid();
this.mode = mode || Constants.MODE_FILE; // node type (file, directory, etc) this.mode = mode || MODE_FILE; // node type (file, directory, etc)
this.size = size || 0; // size (bytes for files, entries for directories) this.size = size || 0; // size (bytes for files, entries for directories)
this.atime = atime || now; // access time (will mirror ctime after creation) this.atime = atime || now; // access time (will mirror ctime after creation)
this.ctime = ctime || now; // creation/change time this.ctime = ctime || now; // creation/change time
this.mtime = mtime || now; // modified time this.mtime = mtime || now; // modified time
this.flags = flags || []; // file flags this.flags = flags || []; // file flags
this.xattrs = xattrs || {}; // extended attributes this.xattrs = xattrs || {}; // extended attributes
this.nlinks = nlinks || 0; // links count this.nlinks = nlinks || 0; // links count
this.version = version || 0; // node version this.version = version || 0; // node version
this.blksize = undefined; // block size this.blksize = undefined; // block size
this.nblocks = 1; // blocks count this.nblocks = 1; // blocks count
this.data = Shared.guid(); // id for data object this.data = guid(); // id for data object
}; };
});

View File

@ -1,10 +1,6 @@
define(function(require) { module.exports = function OpenFileDescription(path, id, flags, position) {
this.path = path;
return function OpenFileDescription(path, id, flags, position) { this.id = id;
this.path = path; this.flags = flags;
this.id = id; this.position = position;
this.flags = flags; };
this.position = position;
};
});

View File

@ -20,208 +20,205 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE. // USE OR OTHER DEALINGS IN THE SOFTWARE.
// Based on https://github.com/joyent/node/blob/41e53e557992a7d552a8e23de035f9463da25c99/lib/path.js // Based on https://github.com/joyent/node/blob/41e53e557992a7d552a8e23de035f9463da25c99/lib/path.js
define(function() {
// resolves . and .. elements in a path array with directory names there // resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array // must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish // (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths) // relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) { function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0 // if the path tries to go above the root, `up` ends up > 0
var up = 0; var up = 0;
for (var i = parts.length - 1; i >= 0; i--) { for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i]; var last = parts[i];
if (last === '.') { if (last === '.') {
parts.splice(i, 1); parts.splice(i, 1);
} else if (last === '..') { } else if (last === '..') {
parts.splice(i, 1); parts.splice(i, 1);
up++; up++;
} else if (up) { } else if (up) {
parts.splice(i, 1); parts.splice(i, 1);
up--; up--;
}
} }
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
} }
// Split a filename into [root, dir, basename, ext], unix version // if the path is allowed to go above the root, restore leading ..s
// 'root' is just a slash, or nothing. if (allowAboveRoot) {
var splitPathRe = for (; up--; up) {
/^(\/?)([\s\S]+\/(?!$)|\/)?((?:\.{1,2}$|[\s\S]+?)?(\.[^.\/]*)?)$/; parts.unshift('..');
var splitPath = function(filename) {
var result = splitPathRe.exec(filename);
return [result[1] || '', result[2] || '', result[3] || '', result[4] || ''];
};
// path.resolve([from ...], to)
function resolve() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
// XXXidbfs: we don't have process.cwd() so we use '/' as a fallback
var path = (i >= 0) ? arguments[i] : '/';
// Skip empty and invalid entries
if (typeof path !== 'string' || !path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
} }
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
} }
// path.normalize(path) return parts;
function normalize(path) { }
var isAbsolute = path.charAt(0) === '/',
trailingSlash = path.substr(-1) === '/';
// Normalize the path // Split a filename into [root, dir, basename, ext], unix version
path = normalizeArray(path.split('/').filter(function(p) { // 'root' is just a slash, or nothing.
return !!p; var splitPathRe =
}), !isAbsolute).join('/'); /^(\/?)([\s\S]+\/(?!$)|\/)?((?:\.{1,2}$|[\s\S]+?)?(\.[^.\/]*)?)$/;
var splitPath = function(filename) {
var result = splitPathRe.exec(filename);
return [result[1] || '', result[2] || '', result[3] || '', result[4] || ''];
};
if (!path && !isAbsolute) { // path.resolve([from ...], to)
path = '.'; function resolve() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
// XXXidbfs: we don't have process.cwd() so we use '/' as a fallback
var path = (i >= 0) ? arguments[i] : '/';
// Skip empty and invalid entries
if (typeof path !== 'string' || !path) {
continue;
} }
/*
if (path && trailingSlash) {
path += '/';
}
*/
return (isAbsolute ? '/' : '') + path; resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
} }
function join() { // At this point the path should be resolved to a full absolute path, but
var paths = Array.prototype.slice.call(arguments, 0); // handle relative paths to be safe (might happen when process.cwd() fails)
return normalize(paths.filter(function(p, index) {
return p && typeof p === 'string'; // Normalize the path
}).join('/')); resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
}
// path.normalize(path)
function normalize(path) {
var isAbsolute = path.charAt(0) === '/',
trailingSlash = path.substr(-1) === '/';
// Normalize the path
path = normalizeArray(path.split('/').filter(function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
/*
if (path && trailingSlash) {
path += '/';
}
*/
return (isAbsolute ? '/' : '') + path;
}
function join() {
var paths = Array.prototype.slice.call(arguments, 0);
return normalize(paths.filter(function(p, index) {
return p && typeof p === 'string';
}).join('/'));
}
// path.relative(from, to)
function relative(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
} }
// path.relative(from, to) var fromParts = trim(from.split('/'));
function relative(from, to) { var toParts = trim(to.split('/'));
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) { var length = Math.min(fromParts.length, toParts.length);
var start = 0; var samePartsLength = length;
for (; start < arr.length; start++) { for (var i = 0; i < length; i++) {
if (arr[start] !== '') break; if (fromParts[i] !== toParts[i]) {
} samePartsLength = i;
break;
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
} }
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
} }
function dirname(path) { var outputParts = [];
var result = splitPath(path), for (var i = samePartsLength; i < fromParts.length; i++) {
root = result[0], outputParts.push('..');
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
}
if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
} }
function basename(path, ext) { outputParts = outputParts.concat(toParts.slice(samePartsLength));
var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows? return outputParts.join('/');
if (ext && f.substr(-1 * ext.length) === ext) { }
f = f.substr(0, f.length - ext.length);
} function dirname(path) {
// XXXidbfs: node.js just does `return f` var result = splitPath(path),
return f === "" ? "/" : f; root = result[0],
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
} }
function extname(path) { if (dir) {
return splitPath(path)[3]; // It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
} }
function isAbsolute(path) { return root + dir;
if(path.charAt(0) === '/') { }
return true;
} function basename(path, ext) {
return false; var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
} }
// XXXidbfs: node.js just does `return f`
return f === "" ? "/" : f;
}
function isNull(path) { function extname(path) {
if (('' + path).indexOf('\u0000') !== -1) { return splitPath(path)[3];
return true; }
}
return false; function isAbsolute(path) {
if(path.charAt(0) === '/') {
return true;
} }
return false;
}
// XXXidbfs: we don't support path.exists() or path.existsSync(), which function isNull(path) {
// are deprecated, and need a FileSystem instance to work. Use fs.stat(). if (('' + path).indexOf('\u0000') !== -1) {
return true;
}
return false;
}
return { // XXXidbfs: we don't support path.exists() or path.existsSync(), which
normalize: normalize, // are deprecated, and need a FileSystem instance to work. Use fs.stat().
resolve: resolve,
join: join,
relative: relative,
sep: '/',
delimiter: ':',
dirname: dirname,
basename: basename,
extname: extname,
isAbsolute: isAbsolute,
isNull: isNull
};
}); module.exports = {
normalize: normalize,
resolve: resolve,
join: join,
relative: relative,
sep: '/',
delimiter: ':',
dirname: dirname,
basename: basename,
extname: extname,
isAbsolute: isAbsolute,
isNull: isNull
};

35
src/providers/index.js Normal file
View File

@ -0,0 +1,35 @@
var IndexedDB = require('./indexeddb.js');
var WebSQL = require('./websql.js');
var Memory = require('./memory.js');
module.exports = {
IndexedDB: IndexedDB,
WebSQL: WebSQL,
Memory: Memory,
/**
* Convenience Provider references
*/
// The default provider to use when none is specified
Default: IndexedDB,
// The Fallback provider does automatic fallback checks
Fallback: (function() {
if(IndexedDB.isSupported()) {
return IndexedDB;
}
if(WebSQL.isSupported()) {
return WebSQL;
}
function NotSupported() {
throw "[Filer Error] Your browser doesn't support IndexedDB or WebSQL.";
}
NotSupported.isSupported = function() {
return false;
};
return NotSupported;
}())
};

View File

@ -1,15 +1,14 @@
define(function(require) { (function(global) {
var FILE_SYSTEM_NAME = require('src/constants').FILE_SYSTEM_NAME; var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME;
var FILE_STORE_NAME = require('src/constants').FILE_STORE_NAME; var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME;
var IDB_RW = require('../constants.js').IDB_RW;
var IDB_RO = require('../constants.js').IDB_RO;
var Errors = require('../errors.js');
var indexedDB = window.indexedDB || var indexedDB = global.indexedDB ||
window.mozIndexedDB || global.mozIndexedDB ||
window.webkitIndexedDB || global.webkitIndexedDB ||
window.msIndexedDB; global.msIndexedDB;
var IDB_RW = require('src/constants').IDB_RW;
var IDB_RO = require('src/constants').IDB_RO;
var Errors = require('src/errors');
function IndexedDBContext(db, mode) { function IndexedDBContext(db, mode) {
var transaction = db.transaction(FILE_STORE_NAME, mode); var transaction = db.transaction(FILE_STORE_NAME, mode);
@ -126,5 +125,6 @@ define(function(require) {
return new IndexedDBContext(this.db, IDB_RW); return new IndexedDBContext(this.db, IDB_RW);
}; };
return IndexedDB; module.exports = IndexedDB;
});
}(this));

View File

@ -1,89 +1,87 @@
define(function(require) { var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME;
var FILE_SYSTEM_NAME = require('src/constants').FILE_SYSTEM_NAME; var asyncCallback = require('../../lib/async.js').nextTick;
var asyncCallback = require('async').nextTick;
/** /**
* Make shared in-memory DBs possible when using the same name. * Make shared in-memory DBs possible when using the same name.
*/ */
var createDB = (function() { var createDB = (function() {
var pool = {}; var pool = {};
return function getOrCreate(name) { return function getOrCreate(name) {
var firstAccess = !pool.hasOwnProperty(name); var firstAccess = !pool.hasOwnProperty(name);
if(firstAccess) { if(firstAccess) {
pool[name] = {}; pool[name] = {};
} }
return { return {
firstAccess: firstAccess, firstAccess: firstAccess,
db: pool[name] db: pool[name]
};
}; };
}());
function MemoryContext(db, readOnly) {
this.readOnly = readOnly;
this.objectStore = db;
}
MemoryContext.prototype.clear = function(callback) {
if(this.readOnly) {
asyncCallback(function() {
callback("[MemoryContext] Error: write operation on read only context");
});
return;
}
var objectStore = this.objectStore;
Object.keys(objectStore).forEach(function(key){
delete objectStore[key];
});
asyncCallback(callback);
}; };
MemoryContext.prototype.get = function(key, callback) { }());
var that = this;
function MemoryContext(db, readOnly) {
this.readOnly = readOnly;
this.objectStore = db;
}
MemoryContext.prototype.clear = function(callback) {
if(this.readOnly) {
asyncCallback(function() { asyncCallback(function() {
callback(null, that.objectStore[key]); callback("[MemoryContext] Error: write operation on read only context");
}); });
}; return;
MemoryContext.prototype.put = function(key, value, callback) {
if(this.readOnly) {
asyncCallback(function() {
callback("[MemoryContext] Error: write operation on read only context");
});
return;
}
this.objectStore[key] = value;
asyncCallback(callback);
};
MemoryContext.prototype.delete = function(key, callback) {
if(this.readOnly) {
asyncCallback(function() {
callback("[MemoryContext] Error: write operation on read only context");
});
return;
}
delete this.objectStore[key];
asyncCallback(callback);
};
function Memory(name) {
this.name = name || FILE_SYSTEM_NAME;
} }
Memory.isSupported = function() { var objectStore = this.objectStore;
return true; Object.keys(objectStore).forEach(function(key){
}; delete objectStore[key];
});
Memory.prototype.open = function(callback) { asyncCallback(callback);
var result = createDB(this.name); };
this.db = result.db; MemoryContext.prototype.get = function(key, callback) {
var that = this;
asyncCallback(function() {
callback(null, that.objectStore[key]);
});
};
MemoryContext.prototype.put = function(key, value, callback) {
if(this.readOnly) {
asyncCallback(function() { asyncCallback(function() {
callback(null, result.firstAccess); callback("[MemoryContext] Error: write operation on read only context");
}); });
}; return;
Memory.prototype.getReadOnlyContext = function() { }
return new MemoryContext(this.db, true); this.objectStore[key] = value;
}; asyncCallback(callback);
Memory.prototype.getReadWriteContext = function() { };
return new MemoryContext(this.db, false); MemoryContext.prototype.delete = function(key, callback) {
}; if(this.readOnly) {
asyncCallback(function() {
callback("[MemoryContext] Error: write operation on read only context");
});
return;
}
delete this.objectStore[key];
asyncCallback(callback);
};
return Memory;
}); function Memory(name) {
this.name = name || FILE_SYSTEM_NAME;
}
Memory.isSupported = function() {
return true;
};
Memory.prototype.open = function(callback) {
var result = createDB(this.name);
this.db = result.db;
asyncCallback(function() {
callback(null, result.firstAccess);
});
};
Memory.prototype.getReadOnlyContext = function() {
return new MemoryContext(this.db, true);
};
Memory.prototype.getReadWriteContext = function() {
return new MemoryContext(this.db, false);
};
module.exports = Memory;

View File

@ -1,38 +0,0 @@
define(function(require) {
var IndexedDB = require('src/providers/indexeddb');
var WebSQL = require('src/providers/websql');
var Memory = require('src/providers/memory');
return {
IndexedDB: IndexedDB,
WebSQL: WebSQL,
Memory: Memory,
/**
* Convenience Provider references
*/
// The default provider to use when none is specified
Default: IndexedDB,
// The Fallback provider does automatic fallback checks
Fallback: (function() {
if(IndexedDB.isSupported()) {
return IndexedDB;
}
if(WebSQL.isSupported()) {
return WebSQL;
}
function NotSupported() {
throw "[Filer Error] Your browser doesn't support IndexedDB or WebSQL.";
}
NotSupported.isSupported = function() {
return false;
};
return NotSupported;
}())
};
});

View File

@ -1,11 +1,11 @@
define(function(require) { (function(global) {
var FILE_SYSTEM_NAME = require('src/constants').FILE_SYSTEM_NAME; var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME;
var FILE_STORE_NAME = require('src/constants').FILE_STORE_NAME; var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME;
var WSQL_VERSION = require('src/constants').WSQL_VERSION; var WSQL_VERSION = require('../constants.js').WSQL_VERSION;
var WSQL_SIZE = require('src/constants').WSQL_SIZE; var WSQL_SIZE = require('../constants.js').WSQL_SIZE;
var WSQL_DESC = require('src/constants').WSQL_DESC; var WSQL_DESC = require('../constants.js').WSQL_DESC;
var u8toArray = require('src/shared').u8toArray; var u8toArray = require('../shared.js').u8toArray;
var Errors = require('src/errors'); var Errors = require('../errors.js');
function WebSQLContext(db, isReadOnly) { function WebSQLContext(db, isReadOnly) {
var that = this; var that = this;
@ -98,7 +98,7 @@ define(function(require) {
this.db = null; this.db = null;
} }
WebSQL.isSupported = function() { WebSQL.isSupported = function() {
return !!window.openDatabase; return !!global.openDatabase;
}; };
WebSQL.prototype.open = function(callback) { WebSQL.prototype.open = function(callback) {
@ -110,7 +110,7 @@ define(function(require) {
return; return;
} }
var db = window.openDatabase(that.name, WSQL_VERSION, WSQL_DESC, WSQL_SIZE); var db = global.openDatabase(that.name, WSQL_VERSION, WSQL_DESC, WSQL_SIZE);
if(!db) { if(!db) {
callback("[WebSQL] Unable to open database."); callback("[WebSQL] Unable to open database.");
return; return;
@ -156,5 +156,6 @@ define(function(require) {
return new WebSQLContext(this.db, false); return new WebSQLContext(this.db, false);
}; };
return WebSQL; module.exports = WebSQL;
});
}(this));

View File

@ -1,37 +1,26 @@
define(function(require) { function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
}).toUpperCase();
}
require("crypto-js/rollups/sha256"); var Crypto = CryptoJS; function nop() {}
function guid() { /**
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { * Convert a Uint8Array to a regular array
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); */
return v.toString(16); function u8toArray(u8) {
}).toUpperCase(); var array = [];
var len = u8.length;
for(var i = 0; i < len; i++) {
array[i] = u8[i];
} }
return array;
}
function hash(string) { module.exports = {
return Crypto.SHA256(string).toString(Crypto.enc.hex); guid: guid,
} u8toArray: u8toArray,
nop: nop
function nop() {} };
/**
* Convert a Uint8Array to a regular array
*/
function u8toArray(u8) {
var array = [];
var len = u8.length;
for(var i = 0; i < len; i++) {
array[i] = u8[i];
}
return array;
}
return {
guid: guid,
hash: hash,
u8toArray: u8toArray,
nop: nop
};
});

View File

@ -1,20 +1,15 @@
define(function(require) { var defaults = require('../constants.js').ENVIRONMENT;
var defaults = require('src/constants').ENVIRONMENT; module.exports = function Environment(env) {
env = env || {};
env.TMP = env.TMP || defaults.TMP;
env.PATH = env.PATH || defaults.PATH;
function Environment(env) { this.get = function(name) {
env = env || {}; return env[name];
env.TMP = env.TMP || defaults.TMP; };
env.PATH = env.PATH || defaults.PATH;
this.get = function(name) { this.set = function(name, value) {
return env[name]; env[name] = value;
}; };
};
this.set = function(name, value) {
env[name] = value;
};
}
return Environment;
});

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,35 @@
define(['src/constants'], function(Constants) { var Constants = require('./constants.js');
function Stats(fileNode, devName) { function Stats(fileNode, devName) {
this.node = fileNode.id; this.node = fileNode.id;
this.dev = devName; this.dev = devName;
this.size = fileNode.size; this.size = fileNode.size;
this.nlinks = fileNode.nlinks; this.nlinks = fileNode.nlinks;
this.atime = fileNode.atime; this.atime = fileNode.atime;
this.mtime = fileNode.mtime; this.mtime = fileNode.mtime;
this.ctime = fileNode.ctime; this.ctime = fileNode.ctime;
this.type = fileNode.mode; this.type = fileNode.mode;
} }
Stats.prototype.isFile = function() { Stats.prototype.isFile = function() {
return this.type === Constants.MODE_FILE; return this.type === Constants.MODE_FILE;
}; };
Stats.prototype.isDirectory = function() { Stats.prototype.isDirectory = function() {
return this.type === Constants.MODE_DIRECTORY; return this.type === Constants.MODE_DIRECTORY;
}; };
Stats.prototype.isSymbolicLink = function() { Stats.prototype.isSymbolicLink = function() {
return this.type === Constants.MODE_SYMBOLIC_LINK; return this.type === Constants.MODE_SYMBOLIC_LINK;
}; };
// These will always be false in Filer. // These will always be false in Filer.
Stats.prototype.isSocket = Stats.prototype.isSocket =
Stats.prototype.isFIFO = Stats.prototype.isFIFO =
Stats.prototype.isCharacterDevice = Stats.prototype.isCharacterDevice =
Stats.prototype.isBlockDevice = Stats.prototype.isBlockDevice =
function() { function() {
return false; return false;
}; };
return Stats; module.exports = Stats;
});

View File

@ -1,14 +1,13 @@
define(['src/constants', 'src/shared'], function(Constants, Shared) { var Constants = require('./constants.js');
var guid = require('./shared.js').guid;
return function SuperNode(atime, ctime, mtime) { module.exports = function SuperNode(atime, ctime, mtime) {
var now = Date.now(); var now = Date.now();
this.id = Constants.SUPER_NODE_ID; this.id = Constants.SUPER_NODE_ID;
this.mode = Constants.MODE_META; this.mode = Constants.MODE_META;
this.atime = atime || now; this.atime = atime || now;
this.ctime = ctime || now; this.ctime = ctime || now;
this.mtime = mtime || now; this.mtime = mtime || now;
this.rnode = Shared.guid(); // root node id (randomly generated) this.rnode = guid(); // root node id (randomly generated)
}; };
});

View File

@ -1,32 +1,33 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('trailing slashes in path names, issue 105', function() { describe('trailing slashes in path names, issue 105', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should deal with trailing slashes properly, path == path/', function(done) { it('should deal with trailing slashes properly, path == path/', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.mkdir('/tmp', function(err) { fs.mkdir('/tmp', function(err) {
if(err) throw err;
fs.mkdir('/tmp/foo', function(err) {
if(err) throw err; if(err) throw err;
fs.mkdir('/tmp/foo', function(err) { // Without trailing slash
fs.readdir('/tmp', function(err, result1) {
if(err) throw err; if(err) throw err;
expect(result1).to.exist;
expect(result1.length).to.equal(1);
// Without trailing slash // With trailing slash
fs.readdir('/tmp', function(err, result1) { fs.readdir('/tmp/', function(err, result2) {
if(err) throw err; if(err) throw err;
expect(result1).to.exist; expect(result2).to.exist;
expect(result1.length).to.equal(1); expect(result2[0]).to.equal('foo');
expect(result1).to.deep.equal(result2);
// With trailing slash done();
fs.readdir('/tmp/', function(err, result2) {
if(err) throw err;
expect(result2).to.exist;
expect(result2[0]).to.equal('foo');
expect(result1).to.deep.equal(result2);
done();
});
}); });
}); });
}); });

View File

@ -1,28 +1,29 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.writeFile truncation - issue 106', function() { describe('fs.writeFile truncation - issue 106', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should truncate an existing file', function(done) { it('should truncate an existing file', function(done) {
var fs = util.fs(); var fs = util.fs();
var filename = '/test'; var filename = '/test';
fs.writeFile(filename, '1', function(err) { fs.writeFile(filename, '1', function(err) {
if(err) throw err;
fs.stat(filename, function(err, stats) {
if(err) throw err; if(err) throw err;
expect(stats.size).to.equal(1);
fs.stat(filename, function(err, stats) { fs.writeFile(filename, '', function(err) {
if(err) throw err; if(err) throw err;
expect(stats.size).to.equal(1);
fs.writeFile(filename, '', function(err) { fs.stat(filename, function(err, stats) {
if(err) throw err; if(err) throw err;
expect(stats.size).to.equal(0);
fs.stat(filename, function(err, stats) { done();
if(err) throw err;
expect(stats.size).to.equal(0);
done();
});
}); });
}); });
}); });

View File

@ -6,26 +6,14 @@
<script src="../bower_components/chai/chai.js"></script> <script src="../bower_components/chai/chai.js"></script>
<script src="../bower_components/mocha/mocha.js"></script> <script src="../bower_components/mocha/mocha.js"></script>
<script> <script>
// Polyfill for function.bind, which PhantomJS seems to need, see mocha.setup('bdd').timeout(5000).slow(250);;
// https://gist.github.com/Daniel-Hug/5682738/raw/147ec7d72123fbef4d7471dcc88c2bc3d52de8d9/function-bind.js
Function.prototype.bind = (function () {}).bind || function (b) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
function c() {} window.onload = function() {
var a = [].slice, mocha.checkLeaks();
f = a.call(arguments, 1), mocha.run();
e = this,
d = function () {
return e.apply(this instanceof c ? this : b || window, f.concat(a.call(arguments)));
};
c.prototype = this.prototype;
d.prototype = new c();
return d;
}; };
</script> </script>
<script src="../lib/require.js" data-main="require-config"></script> <script src="../dist/filer-test.js"></script>
</head> </head>
<body> <body>
<div id="mocha"></div> <div id="mocha"></div>

69
tests/index.js Normal file
View File

@ -0,0 +1,69 @@
/**
* Add your test spec files to the list in order to
* get them running by default.
*/
// Filer
require("./spec/filer.spec");
// Filer.FileSystem.*
require("./spec/fs.spec");
require("./spec/fs.stat.spec");
require("./spec/fs.lstat.spec");
require("./spec/fs.exists.spec");
require("./spec/fs.mknod.spec");
require("./spec/fs.mkdir.spec");
require("./spec/fs.readdir.spec");
require("./spec/fs.rmdir.spec");
require("./spec/fs.open.spec");
require("./spec/fs.write.spec");
require("./spec/fs.writeFile-readFile.spec");
require("./spec/fs.appendFile.spec");
require("./spec/fs.read.spec");
require("./spec/fs.close.spec");
require("./spec/fs.link.spec");
require("./spec/fs.unlink.spec");
require("./spec/fs.rename.spec");
require("./spec/fs.lseek.spec");
require("./spec/fs.symlink.spec");
require("./spec/fs.readlink.spec");
require("./spec/fs.truncate.spec");
require("./spec/fs.utimes.spec");
require("./spec/fs.xattr.spec");
require("./spec/fs.stats.spec");
require("./spec/path-resolution.spec");
require("./spec/times.spec");
require("./spec/time-flags.spec");
require("./spec/fs.watch.spec");
require("./spec/errors.spec");
// Filer.FileSystem.providers.*
require("./spec/providers/providers.spec");
require("./spec/providers/providers.indexeddb.spec");
require("./spec/providers/providers.websql.spec");
require("./spec/providers/providers.memory.spec");
// Filer.FileSystemShell.*
require("./spec/shell/cd.spec");
require("./spec/shell/touch.spec");
require("./spec/shell/exec.spec");
require("./spec/shell/cat.spec");
require("./spec/shell/ls.spec");
require("./spec/shell/rm.spec");
require("./spec/shell/env.spec");
require("./spec/shell/mkdirp.spec");
require("./spec/shell/wget.spec");
require("./spec/shell/zip-unzip.spec");
// Custom Filer library modules
require("./spec/libs/network.spec");
// Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test)
require("./spec/node-js/simple/test-fs-mkdir");
require("./spec/node-js/simple/test-fs-null-bytes");
require("./spec/node-js/simple/test-fs-watch");
require("./spec/node-js/simple/test-fs-watch-recursive");
// Regressions; Bugs
require("./bugs/issue105");
require("./bugs/issue106");

View File

@ -1,14 +1,17 @@
define(["Filer"], function(Filer) { (function(global) {
var Filer = require("../..");
var indexedDB = window.indexedDB || var indexedDB = global.indexedDB ||
window.mozIndexedDB || global.mozIndexedDB ||
window.webkitIndexedDB || global.webkitIndexedDB ||
window.msIndexedDB; global.msIndexedDB;
var needsCleanup = []; var needsCleanup = [];
window.addEventListener('beforeunload', function() { if(global.addEventListener) {
needsCleanup.forEach(function(f) { f(); }); global.addEventListener('beforeunload', function() {
}); needsCleanup.forEach(function(f) { f(); });
});
}
function IndexedDBTestProvider(name) { function IndexedDBTestProvider(name) {
var _done = false; var _done = false;
@ -48,6 +51,6 @@ define(["Filer"], function(Filer) {
this.cleanup = cleanup; this.cleanup = cleanup;
} }
return IndexedDBTestProvider; module.exports = IndexedDBTestProvider;
}); }(this));

View File

@ -1,24 +1,22 @@
define(["Filer"], function(Filer) { var Filer = require('../..');
function MemoryTestProvider(name) { function MemoryTestProvider(name) {
var that = this; var that = this;
function cleanup(callback) { function cleanup(callback) {
that.provider = null; that.provider = null;
callback(); callback();
}
function init() {
if(that.provider) {
return;
}
that.provider = new Filer.FileSystem.providers.Memory(name);
}
this.init = init;
this.cleanup = cleanup;
} }
return MemoryTestProvider; function init() {
if(that.provider) {
return;
}
that.provider = new Filer.FileSystem.providers.Memory(name);
}
}); this.init = init;
this.cleanup = cleanup;
}
module.exports = MemoryTestProvider;

View File

@ -1,5 +1,9 @@
define(["Filer", "tests/lib/indexeddb", "tests/lib/websql", "tests/lib/memory"], (function(global) {
function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) {
var Filer = require('../..');
var IndexedDBTestProvider = require('./indexeddb.js');
var WebSQLTestProvider = require('./websql.js');
var MemoryTestProvider = require('./memory.js');
var _provider; var _provider;
var _fs; var _fs;
@ -12,13 +16,6 @@ function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) {
} }
function findBestProvider() { function findBestProvider() {
// When running tests, and when no explicit provider is defined,
// prefer providers in this order: IndexedDB, WebSQL, Memory.
// However, if we're running in PhantomJS, use Memory first.
if(navigator.userAgent.indexOf('PhantomJS') > -1) {
return MemoryTestProvider;
}
var providers = Filer.FileSystem.providers; var providers = Filer.FileSystem.providers;
if(providers.IndexedDB.isSupported()) { if(providers.IndexedDB.isSupported()) {
return IndexedDBTestProvider; return IndexedDBTestProvider;
@ -30,12 +27,12 @@ function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) {
} }
function setup(callback) { function setup(callback) {
// We support specifying the provider via the query string // In browser we support specifying the provider via the query string
// (e.g., ?filer-provider=IndexedDB). If not specified, we use // (e.g., ?filer-provider=IndexedDB). If not specified, we use
// the Memory provider by default. See test/require-config.js // the Memory provider by default. See test/require-config.js
// for definition of window.filerArgs. // for definition of window.filerArgs.
var providerType = window.filerArgs && window.filerArgs.provider ? var providerType = global.filerArgs && global.filerArgs.provider ?
window.filerArgs.provider : 'Memory'; global.filerArgs.provider : 'Memory';
var name = uniqueName(); var name = uniqueName();
@ -55,8 +52,8 @@ function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) {
} }
// Allow passing FS flags on query string // Allow passing FS flags on query string
var flags = window.filerArgs && window.filerArgs.flags ? var flags = global.filerArgs && global.filerArgs.flags ?
window.filerArgs.flags : 'FORMAT'; global.filerArgs.flags : 'FORMAT';
// Create a file system and wait for it to get setup // Create a file system and wait for it to get setup
_provider.init(); _provider.init();
@ -119,7 +116,7 @@ function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) {
return true; return true;
} }
return { module.exports = {
uniqueName: uniqueName, uniqueName: uniqueName,
setup: setup, setup: setup,
fs: fs, fs: fs,
@ -134,4 +131,4 @@ function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) {
typedArrayEqual: typedArrayEqual typedArrayEqual: typedArrayEqual
}; };
}); }(this));

View File

@ -1,9 +1,13 @@
define(["Filer"], function(Filer) { (function(global) {
var Filer = require('../..');
var needsCleanup = []; var needsCleanup = [];
window.addEventListener('beforeunload', function() { if(global.addEventListener) {
needsCleanup.forEach(function(f) { f(); }); window.addEventListener('beforeunload', function() {
}); needsCleanup.forEach(function(f) { f(); });
});
}
function WebSQLTestProvider(name) { function WebSQLTestProvider(name) {
var _done = false; var _done = false;
@ -38,6 +42,6 @@ define(["Filer"], function(Filer) {
this.cleanup = cleanup; this.cleanup = cleanup;
} }
return WebSQLTestProvider; module.exports = WebSQLTestProvider;
}); }(this));

View File

@ -1,90 +0,0 @@
/**
* Add spec files to the list in test-manifest.js
*/
// Dynamically figure out which source to use (dist/ or src/) based on
// query string:
//
// ?filer-dist/filer.js --> use dist/filer.js
// ?filer-dist/filer.min.js --> use dist/filer.min.js
// ?<default> --> (default) use src/filer.js with require
var filerArgs = window.filerArgs = {};
var config = (function() {
var query = window.location.search.substring(1);
query.split('&').forEach(function(pair) {
pair = pair.split('=');
var key = decodeURIComponent(pair[0]);
var value = decodeURIComponent(pair[1]);
if(key.indexOf('filer-') === 0) {
filerArgs[ key.replace(/^filer-/, '') ] = value;
}
});
// Support dist/filer.js
if(filerArgs['filer-dist/filer.js']) {
return {
paths: {
"tests": "../tests",
"spec": "../tests/spec",
"bugs": "../tests/bugs",
"util": "../tests/lib/test-utils",
"Filer": "../dist/filer"
},
baseUrl: "../lib",
optimize: "none"
};
}
// Support dist/filer.min.js
if(filerArgs['filer-dist/filer.min.js']) {
return {
paths: {
"tests": "../tests",
"spec": "../tests/spec",
"bugs": "../tests/bugs",
"util": "../tests/lib/test-utils",
"Filer": "../dist/filer.min"
},
baseUrl: "../lib",
optimize: "none"
};
}
// Support src/ filer via require
return {
paths: {
"tests": "../tests",
"src": "../src",
"spec": "../tests/spec",
"bugs": "../tests/bugs",
"util": "../tests/lib/test-utils",
"Filer": "../src/index"
},
baseUrl: "../lib",
optimize: "none",
shim: {
// TextEncoder and TextDecoder shims. encoding-indexes must get loaded first,
// and we use a fake one for reduced size, since we only care about utf8.
"encoding": {
deps: ["encoding-indexes-shim"]
}
}
};
}());
require.config(config);
// Intentional globals
assert = chai.assert;
expect = chai.expect;
// We need to setup describe() support before loading tests.
// Use a test timeout of 5s and a slow-test warning of 250ms
mocha.setup("bdd").timeout(5000).slow(250);
require(["tests/test-manifest"], function() {
window.onload = function() {
mocha.checkLeaks();
mocha.run();
};
});

View File

@ -1,175 +0,0 @@
define(["Filer", "util"], function(Filer, util) {
// We reuse the same set of tests for all adapters.
// buildTestsFor() creates a set of tests bound to an
// adapter, and uses the provider set on the query string
// (defaults to best available/supported provider, see test-utils.js).
function buildTestsFor(adapterName, buildAdapter) {
function encode(str) {
// TextEncoder is either native, or shimmed by Filer
return (new TextEncoder("utf-8")).encode(str);
}
// Make some string + binary buffer versions of things we'll need
var valueStr = "value", valueBuffer = encode(valueStr);
var value1Str = "value1", value1Buffer = encode(value1Str);
var value2Str = "value2", value2Buffer = encode(value2Str);
function createProvider() {
return buildAdapter(util.provider().provider);
}
describe("Filer.FileSystem.adapters." + adapterName, function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it("is supported -- if it isn't, none of these tests can run.", function() {
// Allow for combined adapters (e.g., 'Encryption+Compression') joined by '+'
adapterName.split('+').forEach(function(name) {
expect(Filer.FileSystem.adapters[name].isSupported()).to.be.true;
});
});
it("has open, getReadOnlyContext, and getReadWriteContext instance methods", function() {
var provider = createProvider();
expect(provider.open).to.be.a('function');
expect(provider.getReadOnlyContext).to.be.a('function');
expect(provider.getReadWriteContext).to.be.a('function');
});
});
describe("open a provider with an " + adapterName + " adapter", function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it("should open a new database", function(done) {
var provider = createProvider();
provider.open(function(error, firstAccess) {
expect(error).not.to.exist;
// NOTE: we test firstAccess logic in the individual provider tests
// (see tests/spec/providers/*) but can't easily/actually test it here,
// since the provider-agnostic code in test-utils pre-creates a
// FileSystem object, thus eating the first access info.
// See https://github.com/js-platform/filer/issues/127
done();
});
});
});
describe("Read/Write operations on a provider with an " + adapterName + " adapter", function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it("should allow put() and get()", function(done) {
var provider = createProvider();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key", valueBuffer, function(error, result) {
if(error) throw error;
context.get("key", function(error, result) {
expect(error).not.to.exist;
expect(util.typedArrayEqual(result, valueBuffer)).to.be.true;
done();
});
});
});
});
it("should allow delete()", function(done) {
var provider = createProvider();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key", valueBuffer, function(error, result) {
if(error) throw error;
context.delete("key", function(error, result) {
if(error) throw error;
context.get("key", function(error, result) {
expect(error).not.to.exist;
expect(result).not.to.exist;
done();
});
});
});
});
});
it("should allow clear()", function(done) {
var provider = createProvider();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key1", value1Buffer, function(error, result) {
if(error) throw error;
context.put("key2", value2Buffer, function(error, result) {
if(error) throw error;
context.clear(function(err) {
if(error) throw error;
context.get("key1", function(error, result) {
if(error) throw error;
expect(result).not.to.exist;
context.get("key2", function(error, result) {
expect(error).not.to.exist;
expect(result).not.to.exist;
done();
});
});
});
});
});
});
});
/**
* With issue 123 (see https://github.com/js-platform/filer/issues/128) we had to
* start using readwrite contexts everywhere with IndexedDB. As such, we can't
* easily test this here, without knowing which provider we have. We test this
* in the actual providers, so this isn't really needed. Skipping for now.
*/
it.skip("should fail when trying to write on ReadOnlyContext", function(done) {
var provider = createProvider();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadOnlyContext();
context.put("key1", value1Buffer, function(error, result) {
expect(error).to.exist;
expect(result).not.to.exist;
done();
});
});
});
});
}
// Encryption
buildTestsFor('Encryption', function buildAdapter(provider) {
var passphrase = '' + Date.now();
return new Filer.FileSystem.adapters.Encryption(passphrase, provider);
});
// Compression
buildTestsFor('Compression', function buildAdapter(provider) {
return new Filer.FileSystem.adapters.Compression(provider);
});
// Encryption + Compression together
buildTestsFor('Encryption+Compression', function buildAdapter(provider) {
var passphrase = '' + Date.now();
var compression = new Filer.FileSystem.adapters.Compression(provider);
var encryptionWithCompression = new Filer.FileSystem.adapters.Encryption(passphrase, compression);
return encryptionWithCompression;
});
});

View File

@ -1,15 +0,0 @@
define(["Filer"], function(Filer) {
describe("Filer.FileSystem.adapters", function() {
it("is defined", function() {
expect(Filer.FileSystem.adapters).to.exist;
});
it("has a default Encryption constructor", function() {
expect(Filer.FileSystem.adapters.Encryption).to.be.a('function');
});
it("has a default Compression constructor", function() {
expect(Filer.FileSystem.adapters.Compression).to.be.a('function');
});
});
});

View File

@ -1,136 +1,136 @@
define(["Filer"], function(Filer) { var Filer = require('../..');
var expect = require('chai').expect;
describe("Filer.Errors", function() { describe("Filer.Errors", function() {
it("has expected errors", function() { it("has expected errors", function() {
expect(Filer.Errors).to.exist; expect(Filer.Errors).to.exist;
// By ctor // By ctor
expect(Filer.Errors.UNKNOWN).to.be.a('function'); expect(Filer.Errors.UNKNOWN).to.be.a('function');
expect(Filer.Errors.OK).to.be.a('function'); expect(Filer.Errors.OK).to.be.a('function');
expect(Filer.Errors.EOF).to.be.a('function'); expect(Filer.Errors.EOF).to.be.a('function');
expect(Filer.Errors.EADDRINFO).to.be.a('function'); expect(Filer.Errors.EADDRINFO).to.be.a('function');
expect(Filer.Errors.EACCES).to.be.a('function'); expect(Filer.Errors.EACCES).to.be.a('function');
expect(Filer.Errors.EAGAIN).to.be.a('function'); expect(Filer.Errors.EAGAIN).to.be.a('function');
expect(Filer.Errors.EADDRINUSE).to.be.a('function'); expect(Filer.Errors.EADDRINUSE).to.be.a('function');
expect(Filer.Errors.EADDRNOTAVAIL).to.be.a('function'); expect(Filer.Errors.EADDRNOTAVAIL).to.be.a('function');
expect(Filer.Errors.EAFNOSUPPORT).to.be.a('function'); expect(Filer.Errors.EAFNOSUPPORT).to.be.a('function');
expect(Filer.Errors.EALREADY).to.be.a('function'); expect(Filer.Errors.EALREADY).to.be.a('function');
expect(Filer.Errors.EBADF).to.be.a('function'); expect(Filer.Errors.EBADF).to.be.a('function');
expect(Filer.Errors.EBUSY).to.be.a('function'); expect(Filer.Errors.EBUSY).to.be.a('function');
expect(Filer.Errors.ECONNABORTED).to.be.a('function'); expect(Filer.Errors.ECONNABORTED).to.be.a('function');
expect(Filer.Errors.ECONNREFUSED).to.be.a('function'); expect(Filer.Errors.ECONNREFUSED).to.be.a('function');
expect(Filer.Errors.ECONNRESET).to.be.a('function'); expect(Filer.Errors.ECONNRESET).to.be.a('function');
expect(Filer.Errors.EDESTADDRREQ).to.be.a('function'); expect(Filer.Errors.EDESTADDRREQ).to.be.a('function');
expect(Filer.Errors.EFAULT).to.be.a('function'); expect(Filer.Errors.EFAULT).to.be.a('function');
expect(Filer.Errors.EHOSTUNREACH).to.be.a('function'); expect(Filer.Errors.EHOSTUNREACH).to.be.a('function');
expect(Filer.Errors.EINTR).to.be.a('function'); expect(Filer.Errors.EINTR).to.be.a('function');
expect(Filer.Errors.EINVAL).to.be.a('function'); expect(Filer.Errors.EINVAL).to.be.a('function');
expect(Filer.Errors.EISCONN).to.be.a('function'); expect(Filer.Errors.EISCONN).to.be.a('function');
expect(Filer.Errors.EMFILE).to.be.a('function'); expect(Filer.Errors.EMFILE).to.be.a('function');
expect(Filer.Errors.EMSGSIZE).to.be.a('function'); expect(Filer.Errors.EMSGSIZE).to.be.a('function');
expect(Filer.Errors.ENETDOWN).to.be.a('function'); expect(Filer.Errors.ENETDOWN).to.be.a('function');
expect(Filer.Errors.ENETUNREACH).to.be.a('function'); expect(Filer.Errors.ENETUNREACH).to.be.a('function');
expect(Filer.Errors.ENFILE).to.be.a('function'); expect(Filer.Errors.ENFILE).to.be.a('function');
expect(Filer.Errors.ENOBUFS).to.be.a('function'); expect(Filer.Errors.ENOBUFS).to.be.a('function');
expect(Filer.Errors.ENOMEM).to.be.a('function'); expect(Filer.Errors.ENOMEM).to.be.a('function');
expect(Filer.Errors.ENOTDIR).to.be.a('function'); expect(Filer.Errors.ENOTDIR).to.be.a('function');
expect(Filer.Errors.EISDIR).to.be.a('function'); expect(Filer.Errors.EISDIR).to.be.a('function');
expect(Filer.Errors.ENONET).to.be.a('function'); expect(Filer.Errors.ENONET).to.be.a('function');
expect(Filer.Errors.ENOTCONN).to.be.a('function'); expect(Filer.Errors.ENOTCONN).to.be.a('function');
expect(Filer.Errors.ENOTSOCK).to.be.a('function'); expect(Filer.Errors.ENOTSOCK).to.be.a('function');
expect(Filer.Errors.ENOTSUP).to.be.a('function'); expect(Filer.Errors.ENOTSUP).to.be.a('function');
expect(Filer.Errors.ENOENT).to.be.a('function'); expect(Filer.Errors.ENOENT).to.be.a('function');
expect(Filer.Errors.ENOSYS).to.be.a('function'); expect(Filer.Errors.ENOSYS).to.be.a('function');
expect(Filer.Errors.EPIPE).to.be.a('function'); expect(Filer.Errors.EPIPE).to.be.a('function');
expect(Filer.Errors.EPROTO).to.be.a('function'); expect(Filer.Errors.EPROTO).to.be.a('function');
expect(Filer.Errors.EPROTONOSUPPORT).to.be.a('function'); expect(Filer.Errors.EPROTONOSUPPORT).to.be.a('function');
expect(Filer.Errors.EPROTOTYPE).to.be.a('function'); expect(Filer.Errors.EPROTOTYPE).to.be.a('function');
expect(Filer.Errors.ETIMEDOUT).to.be.a('function'); expect(Filer.Errors.ETIMEDOUT).to.be.a('function');
expect(Filer.Errors.ECHARSET).to.be.a('function'); expect(Filer.Errors.ECHARSET).to.be.a('function');
expect(Filer.Errors.EAIFAMNOSUPPORT).to.be.a('function'); expect(Filer.Errors.EAIFAMNOSUPPORT).to.be.a('function');
expect(Filer.Errors.EAISERVICE).to.be.a('function'); expect(Filer.Errors.EAISERVICE).to.be.a('function');
expect(Filer.Errors.EAISOCKTYPE).to.be.a('function'); expect(Filer.Errors.EAISOCKTYPE).to.be.a('function');
expect(Filer.Errors.ESHUTDOWN).to.be.a('function'); expect(Filer.Errors.ESHUTDOWN).to.be.a('function');
expect(Filer.Errors.EEXIST).to.be.a('function'); expect(Filer.Errors.EEXIST).to.be.a('function');
expect(Filer.Errors.ESRCH).to.be.a('function'); expect(Filer.Errors.ESRCH).to.be.a('function');
expect(Filer.Errors.ENAMETOOLONG).to.be.a('function'); expect(Filer.Errors.ENAMETOOLONG).to.be.a('function');
expect(Filer.Errors.EPERM).to.be.a('function'); expect(Filer.Errors.EPERM).to.be.a('function');
expect(Filer.Errors.ELOOP).to.be.a('function'); expect(Filer.Errors.ELOOP).to.be.a('function');
expect(Filer.Errors.EXDEV).to.be.a('function'); expect(Filer.Errors.EXDEV).to.be.a('function');
expect(Filer.Errors.ENOTEMPTY).to.be.a('function'); expect(Filer.Errors.ENOTEMPTY).to.be.a('function');
expect(Filer.Errors.ENOSPC).to.be.a('function'); expect(Filer.Errors.ENOSPC).to.be.a('function');
expect(Filer.Errors.EIO).to.be.a('function'); expect(Filer.Errors.EIO).to.be.a('function');
expect(Filer.Errors.EROFS).to.be.a('function'); expect(Filer.Errors.EROFS).to.be.a('function');
expect(Filer.Errors.ENODEV).to.be.a('function'); expect(Filer.Errors.ENODEV).to.be.a('function');
expect(Filer.Errors.ESPIPE).to.be.a('function'); expect(Filer.Errors.ESPIPE).to.be.a('function');
expect(Filer.Errors.ECANCELED).to.be.a('function'); expect(Filer.Errors.ECANCELED).to.be.a('function');
expect(Filer.Errors.ENOTMOUNTED).to.be.a('function'); expect(Filer.Errors.ENOTMOUNTED).to.be.a('function');
expect(Filer.Errors.EFILESYSTEMERROR).to.be.a('function'); expect(Filer.Errors.EFILESYSTEMERROR).to.be.a('function');
expect(Filer.Errors.ENOATTR).to.be.a('function'); expect(Filer.Errors.ENOATTR).to.be.a('function');
// By errno // By errno
expect(Filer.Errors[-1]).to.equal(Filer.Errors.UNKNOWN); expect(Filer.Errors[-1]).to.equal(Filer.Errors.UNKNOWN);
expect(Filer.Errors[0]).to.equal(Filer.Errors.OK); expect(Filer.Errors[0]).to.equal(Filer.Errors.OK);
expect(Filer.Errors[1]).to.equal(Filer.Errors.EOF); expect(Filer.Errors[1]).to.equal(Filer.Errors.EOF);
expect(Filer.Errors[2]).to.equal(Filer.Errors.EADDRINFO); expect(Filer.Errors[2]).to.equal(Filer.Errors.EADDRINFO);
expect(Filer.Errors[3]).to.equal(Filer.Errors.EACCES); expect(Filer.Errors[3]).to.equal(Filer.Errors.EACCES);
expect(Filer.Errors[4]).to.equal(Filer.Errors.EAGAIN); expect(Filer.Errors[4]).to.equal(Filer.Errors.EAGAIN);
expect(Filer.Errors[5]).to.equal(Filer.Errors.EADDRINUSE); expect(Filer.Errors[5]).to.equal(Filer.Errors.EADDRINUSE);
expect(Filer.Errors[6]).to.equal(Filer.Errors.EADDRNOTAVAIL); expect(Filer.Errors[6]).to.equal(Filer.Errors.EADDRNOTAVAIL);
expect(Filer.Errors[7]).to.equal(Filer.Errors.EAFNOSUPPORT); expect(Filer.Errors[7]).to.equal(Filer.Errors.EAFNOSUPPORT);
expect(Filer.Errors[8]).to.equal(Filer.Errors.EALREADY); expect(Filer.Errors[8]).to.equal(Filer.Errors.EALREADY);
expect(Filer.Errors[9]).to.equal(Filer.Errors.EBADF); expect(Filer.Errors[9]).to.equal(Filer.Errors.EBADF);
expect(Filer.Errors[10]).to.equal(Filer.Errors.EBUSY); expect(Filer.Errors[10]).to.equal(Filer.Errors.EBUSY);
expect(Filer.Errors[11]).to.equal(Filer.Errors.ECONNABORTED); expect(Filer.Errors[11]).to.equal(Filer.Errors.ECONNABORTED);
expect(Filer.Errors[12]).to.equal(Filer.Errors.ECONNREFUSED); expect(Filer.Errors[12]).to.equal(Filer.Errors.ECONNREFUSED);
expect(Filer.Errors[13]).to.equal(Filer.Errors.ECONNRESET); expect(Filer.Errors[13]).to.equal(Filer.Errors.ECONNRESET);
expect(Filer.Errors[14]).to.equal(Filer.Errors.EDESTADDRREQ); expect(Filer.Errors[14]).to.equal(Filer.Errors.EDESTADDRREQ);
expect(Filer.Errors[15]).to.equal(Filer.Errors.EFAULT); expect(Filer.Errors[15]).to.equal(Filer.Errors.EFAULT);
expect(Filer.Errors[16]).to.equal(Filer.Errors.EHOSTUNREACH); expect(Filer.Errors[16]).to.equal(Filer.Errors.EHOSTUNREACH);
expect(Filer.Errors[17]).to.equal(Filer.Errors.EINTR); expect(Filer.Errors[17]).to.equal(Filer.Errors.EINTR);
expect(Filer.Errors[18]).to.equal(Filer.Errors.EINVAL); expect(Filer.Errors[18]).to.equal(Filer.Errors.EINVAL);
expect(Filer.Errors[19]).to.equal(Filer.Errors.EISCONN); expect(Filer.Errors[19]).to.equal(Filer.Errors.EISCONN);
expect(Filer.Errors[20]).to.equal(Filer.Errors.EMFILE); expect(Filer.Errors[20]).to.equal(Filer.Errors.EMFILE);
expect(Filer.Errors[21]).to.equal(Filer.Errors.EMSGSIZE); expect(Filer.Errors[21]).to.equal(Filer.Errors.EMSGSIZE);
expect(Filer.Errors[22]).to.equal(Filer.Errors.ENETDOWN); expect(Filer.Errors[22]).to.equal(Filer.Errors.ENETDOWN);
expect(Filer.Errors[23]).to.equal(Filer.Errors.ENETUNREACH); expect(Filer.Errors[23]).to.equal(Filer.Errors.ENETUNREACH);
expect(Filer.Errors[24]).to.equal(Filer.Errors.ENFILE); expect(Filer.Errors[24]).to.equal(Filer.Errors.ENFILE);
expect(Filer.Errors[25]).to.equal(Filer.Errors.ENOBUFS); expect(Filer.Errors[25]).to.equal(Filer.Errors.ENOBUFS);
expect(Filer.Errors[26]).to.equal(Filer.Errors.ENOMEM); expect(Filer.Errors[26]).to.equal(Filer.Errors.ENOMEM);
expect(Filer.Errors[27]).to.equal(Filer.Errors.ENOTDIR); expect(Filer.Errors[27]).to.equal(Filer.Errors.ENOTDIR);
expect(Filer.Errors[28]).to.equal(Filer.Errors.EISDIR); expect(Filer.Errors[28]).to.equal(Filer.Errors.EISDIR);
expect(Filer.Errors[29]).to.equal(Filer.Errors.ENONET); expect(Filer.Errors[29]).to.equal(Filer.Errors.ENONET);
expect(Filer.Errors[31]).to.equal(Filer.Errors.ENOTCONN); expect(Filer.Errors[31]).to.equal(Filer.Errors.ENOTCONN);
expect(Filer.Errors[32]).to.equal(Filer.Errors.ENOTSOCK); expect(Filer.Errors[32]).to.equal(Filer.Errors.ENOTSOCK);
expect(Filer.Errors[33]).to.equal(Filer.Errors.ENOTSUP); expect(Filer.Errors[33]).to.equal(Filer.Errors.ENOTSUP);
expect(Filer.Errors[34]).to.equal(Filer.Errors.ENOENT); expect(Filer.Errors[34]).to.equal(Filer.Errors.ENOENT);
expect(Filer.Errors[35]).to.equal(Filer.Errors.ENOSYS); expect(Filer.Errors[35]).to.equal(Filer.Errors.ENOSYS);
expect(Filer.Errors[36]).to.equal(Filer.Errors.EPIPE); expect(Filer.Errors[36]).to.equal(Filer.Errors.EPIPE);
expect(Filer.Errors[37]).to.equal(Filer.Errors.EPROTO); expect(Filer.Errors[37]).to.equal(Filer.Errors.EPROTO);
expect(Filer.Errors[38]).to.equal(Filer.Errors.EPROTONOSUPPORT); expect(Filer.Errors[38]).to.equal(Filer.Errors.EPROTONOSUPPORT);
expect(Filer.Errors[39]).to.equal(Filer.Errors.EPROTOTYPE); expect(Filer.Errors[39]).to.equal(Filer.Errors.EPROTOTYPE);
expect(Filer.Errors[40]).to.equal(Filer.Errors.ETIMEDOUT); expect(Filer.Errors[40]).to.equal(Filer.Errors.ETIMEDOUT);
expect(Filer.Errors[41]).to.equal(Filer.Errors.ECHARSET); expect(Filer.Errors[41]).to.equal(Filer.Errors.ECHARSET);
expect(Filer.Errors[42]).to.equal(Filer.Errors.EAIFAMNOSUPPORT); expect(Filer.Errors[42]).to.equal(Filer.Errors.EAIFAMNOSUPPORT);
expect(Filer.Errors[44]).to.equal(Filer.Errors.EAISERVICE); expect(Filer.Errors[44]).to.equal(Filer.Errors.EAISERVICE);
expect(Filer.Errors[45]).to.equal(Filer.Errors.EAISOCKTYPE); expect(Filer.Errors[45]).to.equal(Filer.Errors.EAISOCKTYPE);
expect(Filer.Errors[46]).to.equal(Filer.Errors.ESHUTDOWN); expect(Filer.Errors[46]).to.equal(Filer.Errors.ESHUTDOWN);
expect(Filer.Errors[47]).to.equal(Filer.Errors.EEXIST); expect(Filer.Errors[47]).to.equal(Filer.Errors.EEXIST);
expect(Filer.Errors[48]).to.equal(Filer.Errors.ESRCH); expect(Filer.Errors[48]).to.equal(Filer.Errors.ESRCH);
expect(Filer.Errors[49]).to.equal(Filer.Errors.ENAMETOOLONG); expect(Filer.Errors[49]).to.equal(Filer.Errors.ENAMETOOLONG);
expect(Filer.Errors[50]).to.equal(Filer.Errors.EPERM); expect(Filer.Errors[50]).to.equal(Filer.Errors.EPERM);
expect(Filer.Errors[51]).to.equal(Filer.Errors.ELOOP); expect(Filer.Errors[51]).to.equal(Filer.Errors.ELOOP);
expect(Filer.Errors[52]).to.equal(Filer.Errors.EXDEV); expect(Filer.Errors[52]).to.equal(Filer.Errors.EXDEV);
expect(Filer.Errors[53]).to.equal(Filer.Errors.ENOTEMPTY); expect(Filer.Errors[53]).to.equal(Filer.Errors.ENOTEMPTY);
expect(Filer.Errors[54]).to.equal(Filer.Errors.ENOSPC); expect(Filer.Errors[54]).to.equal(Filer.Errors.ENOSPC);
expect(Filer.Errors[55]).to.equal(Filer.Errors.EIO); expect(Filer.Errors[55]).to.equal(Filer.Errors.EIO);
expect(Filer.Errors[56]).to.equal(Filer.Errors.EROFS); expect(Filer.Errors[56]).to.equal(Filer.Errors.EROFS);
expect(Filer.Errors[57]).to.equal(Filer.Errors.ENODEV); expect(Filer.Errors[57]).to.equal(Filer.Errors.ENODEV);
expect(Filer.Errors[58]).to.equal(Filer.Errors.ESPIPE); expect(Filer.Errors[58]).to.equal(Filer.Errors.ESPIPE);
expect(Filer.Errors[59]).to.equal(Filer.Errors.ECANCELED); expect(Filer.Errors[59]).to.equal(Filer.Errors.ECANCELED);
expect(Filer.Errors[1000]).to.equal(Filer.Errors.ENOTMOUNTED); expect(Filer.Errors[1000]).to.equal(Filer.Errors.ENOTMOUNTED);
expect(Filer.Errors[1001]).to.equal(Filer.Errors.EFILESYSTEMERROR); expect(Filer.Errors[1001]).to.equal(Filer.Errors.EFILESYSTEMERROR);
expect(Filer.Errors[1002]).to.equal(Filer.Errors.ENOATTR); expect(Filer.Errors[1002]).to.equal(Filer.Errors.ENOATTR);
});
}); });
}); });

View File

@ -1,13 +1,12 @@
define(["Filer"], function(Filer) { var Filer = require('../..');
var expect = require('chai').expect;
describe("Filer", function() { describe("Filer", function() {
it("is defined", function() { it("is defined", function() {
expect(typeof Filer).not.to.equal(undefined); expect(typeof Filer).not.to.equal(undefined);
});
it("has FileSystem constructor", function() {
expect(typeof Filer.FileSystem).to.equal('function');
});
}); });
}); it("has FileSystem constructor", function() {
expect(typeof Filer.FileSystem).to.equal('function');
});
});

View File

@ -1,129 +1,130 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.appendFile', function() { describe('fs.appendFile', function() {
beforeEach(function(done) { beforeEach(function(done) {
util.setup(function() { util.setup(function() {
var fs = util.fs();
fs.writeFile('/myfile', "This is a file.", { encoding: 'utf8' }, function(error) {
if(error) throw error;
done();
});
});
});
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.appendFile).to.be.a('function'); fs.writeFile('/myfile', "This is a file.", { encoding: 'utf8' }, function(error) {
});
it('should append a utf8 file without specifying utf8 in appendFile', function(done) {
var fs = util.fs();
var contents = "This is a file.";
var more = " Appended.";
fs.appendFile('/myfile', more, function(error) {
if(error) throw error; if(error) throw error;
done();
fs.readFile('/myfile', 'utf8', function(error, data) {
expect(error).not.to.exist;
expect(data).to.equal(contents + more);
done();
});
}); });
}); });
});
afterEach(util.cleanup);
it('should append a utf8 file with "utf8" option to appendFile', function(done) { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
var contents = "This is a file."; expect(fs.appendFile).to.be.a('function');
var more = " Appended."; });
fs.appendFile('/myfile', more, 'utf8', function(error) { it('should append a utf8 file without specifying utf8 in appendFile', function(done) {
if(error) throw error; var fs = util.fs();
var contents = "This is a file.";
var more = " Appended.";
fs.readFile('/myfile', 'utf8', function(error, data) { fs.appendFile('/myfile', more, function(error) {
expect(error).not.to.exist; if(error) throw error;
expect(data).to.equal(contents + more);
done();
});
});
});
it('should append a utf8 file with {encoding: "utf8"} option to appendFile', function(done) { fs.readFile('/myfile', 'utf8', function(error, data) {
var fs = util.fs();
var contents = "This is a file.";
var more = " Appended.";
fs.appendFile('/myfile', more, { encoding: 'utf8' }, function(error) {
if(error) throw error;
fs.readFile('/myfile', { encoding: 'utf8' }, function(error, data) {
expect(error).not.to.exist;
expect(data).to.equal(contents + more);
done();
});
});
});
it('should append a binary file', function(done) {
var fs = util.fs();
// String and utf8 binary encoded versions of the same thing:
var contents = "This is a file.";
var binary = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
var more = " Appended.";
var binary2 = new Uint8Array([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
var binary3 = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46,
32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
fs.writeFile('/mybinaryfile', binary, function(error) {
if(error) throw error;
fs.appendFile('/mybinaryfile', binary2, function(error) {
if(error) throw error;
fs.readFile('/mybinaryfile', 'ascii', function(error, data) {
expect(error).not.to.exist;
expect(data).to.deep.equal(binary3);
done();
});
});
});
});
it('should follow symbolic links', function(done) {
var fs = util.fs();
var contents = "This is a file.";
var more = " Appended.";
fs.symlink('/myfile', '/myFileLink', function (error) {
if (error) throw error;
fs.appendFile('/myFileLink', more, 'utf8', function (error) {
if (error) throw error;
fs.readFile('/myFileLink', 'utf8', function(error, data) {
expect(error).not.to.exist;
expect(data).to.equal(contents + more);
done();
});
});
});
});
it('should work when file does not exist, and create the file', function(done) {
var fs = util.fs();
var contents = "This is a file.";
fs.appendFile('/newfile', contents, { encoding: 'utf8' }, function(error) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(data).to.equal(contents + more);
done();
});
});
});
fs.readFile('/newfile', 'utf8', function(err, data) { it('should append a utf8 file with "utf8" option to appendFile', function(done) {
if(err) throw err; var fs = util.fs();
expect(data).to.equal(contents); var contents = "This is a file.";
var more = " Appended.";
fs.appendFile('/myfile', more, 'utf8', function(error) {
if(error) throw error;
fs.readFile('/myfile', 'utf8', function(error, data) {
expect(error).not.to.exist;
expect(data).to.equal(contents + more);
done();
});
});
});
it('should append a utf8 file with {encoding: "utf8"} option to appendFile', function(done) {
var fs = util.fs();
var contents = "This is a file.";
var more = " Appended.";
fs.appendFile('/myfile', more, { encoding: 'utf8' }, function(error) {
if(error) throw error;
fs.readFile('/myfile', { encoding: 'utf8' }, function(error, data) {
expect(error).not.to.exist;
expect(data).to.equal(contents + more);
done();
});
});
});
it('should append a binary file', function(done) {
var fs = util.fs();
// String and utf8 binary encoded versions of the same thing:
var contents = "This is a file.";
var binary = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
var more = " Appended.";
var binary2 = new Uint8Array([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
var binary3 = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46,
32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
fs.writeFile('/mybinaryfile', binary, function(error) {
if(error) throw error;
fs.appendFile('/mybinaryfile', binary2, function(error) {
if(error) throw error;
fs.readFile('/mybinaryfile', 'ascii', function(error, data) {
expect(error).not.to.exist;
expect(data).to.deep.equal(binary3);
done(); done();
}); });
}); });
}); });
}); });
it('should follow symbolic links', function(done) {
var fs = util.fs();
var contents = "This is a file.";
var more = " Appended.";
fs.symlink('/myfile', '/myFileLink', function (error) {
if (error) throw error;
fs.appendFile('/myFileLink', more, 'utf8', function (error) {
if (error) throw error;
fs.readFile('/myFileLink', 'utf8', function(error, data) {
expect(error).not.to.exist;
expect(data).to.equal(contents + more);
done();
});
});
});
});
it('should work when file does not exist, and create the file', function(done) {
var fs = util.fs();
var contents = "This is a file.";
fs.appendFile('/newfile', contents, { encoding: 'utf8' }, function(error) {
expect(error).not.to.exist;
fs.readFile('/newfile', 'utf8', function(err, data) {
if(err) throw err;
expect(data).to.equal(contents);
done();
});
});
});
}); });

View File

@ -1,30 +1,30 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.close', function() { describe('fs.close', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(typeof fs.close).to.equal('function'); expect(typeof fs.close).to.equal('function');
}); });
it('should release the file descriptor', function(done) { it('should release the file descriptor', function(done) {
var buffer = new Uint8Array(0); var buffer = new Uint8Array(0);
var fs = util.fs(); var fs = util.fs();
fs.open('/myfile', 'w+', function(error, result) { fs.open('/myfile', 'w+', function(error, result) {
if(error) throw error; if(error) throw error;
var fd = result; var fd = result;
fs.close(fd, function(error) { fs.close(fd, function(error) {
fs.read(fd, buffer, 0, buffer.length, undefined, function(error, result) { fs.read(fd, buffer, 0, buffer.length, undefined, function(error, result) {
expect(error).to.exist; expect(error).to.exist;
done(); done();
});
}); });
}); });
}); });
}); });
}); });

View File

@ -1,59 +1,60 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.exists', function() { describe('fs.exists', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(typeof fs.exists).to.equal('function'); expect(typeof fs.exists).to.equal('function');
});
it('should return false if path does not exist', function(done) {
var fs = util.fs();
fs.exists('/tmp', function(result) {
expect(result).to.be.false;
done();
}); });
});
it('should return false if path does not exist', function(done) { it('should return true if path exists', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.exists('/tmp', function(result) { fs.open('/myfile', 'w', function(err, fd) {
expect(result).to.be.false; if(err) throw err;
done();
});
});
it('should return true if path exists', function(done) { fs.close(fd, function(err) {
var fs = util.fs();
fs.open('/myfile', 'w', function(err, fd) {
if(err) throw err; if(err) throw err;
fs.close(fd, function(err) { fs.exists('/myfile', function(result) {
if(err) throw err; expect(result).to.be.true;
done();
});
});
});
});
fs.exists('/myfile', function(result) { it('should follow symbolic links and return true for the resulting path', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.exists('/myfilelink', function(result) {
expect(result).to.be.true; expect(result).to.be.true;
done(); done();
}); });
}); });
}); });
}); });
it('should follow symbolic links and return true for the resulting path', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.exists('/myfilelink', function(result) {
expect(result).to.be.true;
done();
});
});
});
});
});
}); });
}); });

View File

@ -1,67 +1,40 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.link', function() { describe('fs.link', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.link).to.be.a('function'); expect(fs.link).to.be.a('function');
}); });
it('should create a link to an existing file', function(done) { it('should create a link to an existing file', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) { fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error; if(error) throw error;
fs.close(fd, function(error) { fs.link('/myfile', '/myotherfile', function(error) {
if(error) throw error; if(error) throw error;
fs.link('/myfile', '/myotherfile', function(error) { fs.stat('/myfile', function(error, result) {
if(error) throw error; if(error) throw error;
fs.stat('/myfile', function(error, result) { var _oldstats = result;
if(error) throw error; fs.stat('/myotherfile', function(error, result) {
expect(error).not.to.exist;
var _oldstats = result; expect(result.nlinks).to.equal(2);
fs.stat('/myotherfile', function(error, result) { expect(result.dev).to.equal(_oldstats.dev);
expect(error).not.to.exist; expect(result.node).to.equal(_oldstats.node);
expect(result.nlinks).to.equal(2); expect(result.size).to.equal(_oldstats.size);
expect(result.dev).to.equal(_oldstats.dev); expect(result.type).to.equal(_oldstats.type);
expect(result.node).to.equal(_oldstats.node); done();
expect(result.size).to.equal(_oldstats.size);
expect(result.type).to.equal(_oldstats.type);
done();
});
});
});
});
});
});
it('should not follow symbolic links', function(done) {
var fs = util.fs();
fs.stat('/', function (error, result) {
if (error) throw error;
var _oldstats = result;
fs.symlink('/', '/myfileLink', function (error) {
if (error) throw error;
fs.link('/myfileLink', '/myotherfile', function (error) {
if (error) throw error;
fs.lstat('/myfileLink', function (error, result) {
if (error) throw error;
var _linkstats = result;
fs.lstat('/myotherfile', function (error, result) {
expect(error).not.to.exist;
expect(result.dev).to.equal(_linkstats.dev);
expect(result.node).to.equal(_linkstats.node);
expect(result.size).to.equal(_linkstats.size);
expect(result.type).to.equal(_linkstats.type);
expect(result.nlinks).to.equal(2);
done();
});
}); });
}); });
}); });
@ -69,4 +42,31 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); it('should not follow symbolic links', function(done) {
var fs = util.fs();
fs.stat('/', function (error, result) {
if (error) throw error;
var _oldstats = result;
fs.symlink('/', '/myfileLink', function (error) {
if (error) throw error;
fs.link('/myfileLink', '/myotherfile', function (error) {
if (error) throw error;
fs.lstat('/myfileLink', function (error, result) {
if (error) throw error;
var _linkstats = result;
fs.lstat('/myotherfile', function (error, result) {
expect(error).not.to.exist;
expect(result.dev).to.equal(_linkstats.dev);
expect(result.node).to.equal(_linkstats.node);
expect(result.size).to.equal(_linkstats.size);
expect(result.type).to.equal(_linkstats.type);
expect(result.nlinks).to.equal(2);
done();
});
});
});
});
});
});
});

View File

@ -1,157 +1,41 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.lseek', function() { describe('fs.lseek', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.lseek).to.be.a('function'); expect(fs.lseek).to.be.a('function');
}); });
it('should not follow symbolic links', function(done) { it('should not follow symbolic links', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.open('/myfile', 'w', function (error, fd) { fs.open('/myfile', 'w', function (error, fd) {
if (error) throw error;
fs.close(fd, function (error) {
if (error) throw error; if (error) throw error;
fs.close(fd, function (error) { fs.symlink('/myfile', '/myFileLink', function (error) {
if (error) throw error; if (error) throw error;
fs.symlink('/myfile', '/myFileLink', function (error) { fs.rename('/myFileLink', '/myOtherFileLink', function (error) {
if (error) throw error; if (error) throw error;
fs.rename('/myFileLink', '/myOtherFileLink', function (error) { fs.stat('/myfile', function (error, result) {
if (error) throw error;
fs.stat('/myfile', function (error, result) {
expect(error).not.to.exist;
fs.lstat('/myFileLink', function (error, result) {
expect(error).to.exist;
fs.stat('/myOtherFileLink', function (error, result) {
if (error) throw error;
expect(result.nlinks).to.equal(1);
done();
});
});
});
});
});
});
});
});
it('should set the current position if whence is SET', function(done) {
var fs = util.fs();
var offset = 3;
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var result_buffer = new Uint8Array(buffer.length + offset);
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.lseek(fd, offset, 'SET', function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal(offset);
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.read(fd, result_buffer, 0, result_buffer.length, 0, function(error, result) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result.size).to.equal(offset + buffer.length);
var expected = new Uint8Array([1, 2, 3, 1, 2, 3, 4, 5, 6, 7, 8]);
expect(result_buffer).to.deep.equal(expected);
done();
});
});
});
});
});
});
});
it('should update the current position if whence is CUR', function(done) {
var fs = util.fs();
var offset = -2;
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var result_buffer = new Uint8Array(2 * buffer.length + offset);
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.lseek(fd, offset, 'CUR', function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal(offset + buffer.length);
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.read(fd, result_buffer, 0, result_buffer.length, 0, function(error, result) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result.size).to.equal(offset + 2 * buffer.length);
var expected = new Uint8Array([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8]);
expect(result_buffer).to.deep.equal(expected);
done();
});
});
});
});
});
});
});
it('should update the current position if whence is END', function(done) {
var fs = util.fs();
var offset = 5;
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var result_buffer;
fs.open('/myfile', 'w+', function(error, result) {
if(error) throw error;
var fd1 = result;
fs.write(fd1, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.open('/myfile', 'w+', function(error, result) {
if(error) throw error;
var fd2 = result;
fs.lseek(fd2, offset, 'END', function(error, result) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(result).to.equal(offset + buffer.length);
fs.write(fd2, buffer, 0, buffer.length, undefined, function(error, result) { fs.lstat('/myFileLink', function (error, result) {
if(error) throw error; expect(error).to.exist;
fs.stat('/myfile', function(error, result) { fs.stat('/myOtherFileLink', function (error, result) {
if(error) throw error; if (error) throw error;
expect(result.nlinks).to.equal(1);
expect(result.size).to.equal(offset + 2 * buffer.length); done();
result_buffer = new Uint8Array(result.size);
fs.read(fd2, result_buffer, 0, result_buffer.length, 0, function(error, result) {
if(error) throw error;
var expected = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
expect(result_buffer).to.deep.equal(expected);
done();
});
}); });
}); });
}); });
@ -161,4 +45,120 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
it('should set the current position if whence is SET', function(done) {
var fs = util.fs();
var offset = 3;
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var result_buffer = new Uint8Array(buffer.length + offset);
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.lseek(fd, offset, 'SET', function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal(offset);
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.read(fd, result_buffer, 0, result_buffer.length, 0, function(error, result) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result.size).to.equal(offset + buffer.length);
var expected = new Uint8Array([1, 2, 3, 1, 2, 3, 4, 5, 6, 7, 8]);
expect(result_buffer).to.deep.equal(expected);
done();
});
});
});
});
});
});
});
it('should update the current position if whence is CUR', function(done) {
var fs = util.fs();
var offset = -2;
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var result_buffer = new Uint8Array(2 * buffer.length + offset);
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.lseek(fd, offset, 'CUR', function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal(offset + buffer.length);
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.read(fd, result_buffer, 0, result_buffer.length, 0, function(error, result) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result.size).to.equal(offset + 2 * buffer.length);
var expected = new Uint8Array([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8]);
expect(result_buffer).to.deep.equal(expected);
done();
});
});
});
});
});
});
});
it('should update the current position if whence is END', function(done) {
var fs = util.fs();
var offset = 5;
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var result_buffer;
fs.open('/myfile', 'w+', function(error, result) {
if(error) throw error;
var fd1 = result;
fs.write(fd1, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.open('/myfile', 'w+', function(error, result) {
if(error) throw error;
var fd2 = result;
fs.lseek(fd2, offset, 'END', function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal(offset + buffer.length);
fs.write(fd2, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result.size).to.equal(offset + 2 * buffer.length);
result_buffer = new Uint8Array(result.size);
fs.read(fd2, result_buffer, 0, result_buffer.length, 0, function(error, result) {
if(error) throw error;
var expected = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
expect(result_buffer).to.deep.equal(expected);
done();
});
});
});
});
});
});
});
});
}); });

View File

@ -1,51 +1,51 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.lstat', function() { describe('fs.lstat', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(typeof fs.lstat).to.equal('function'); expect(typeof fs.lstat).to.equal('function');
}); });
it('should return an error if path does not exist', function(done) { it('should return an error if path does not exist', function(done) {
var fs = util.fs(); var fs = util.fs();
var _error, _result; var _error, _result;
fs.lstat('/tmp', function(error, result) { fs.lstat('/tmp', function(error, result) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("ENOENT"); expect(error.code).to.equal("ENOENT");
expect(result).not.to.exist; expect(result).not.to.exist;
done(); done();
});
});
it('should return a stat object if path is not a symbolic link', function(done) {
var fs = util.fs();
fs.lstat('/', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('DIRECTORY');
done();
});
});
it('should return a stat object if path is a symbolic link', function(done) {
var fs = util.fs();
fs.symlink('/', '/mylink', function(error) {
if(error) throw error;
fs.lstat('/mylink', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('SYMLINK');
done();
});
});
}); });
}); });
}); it('should return a stat object if path is not a symbolic link', function(done) {
var fs = util.fs();
fs.lstat('/', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('DIRECTORY');
done();
});
});
it('should return a stat object if path is a symbolic link', function(done) {
var fs = util.fs();
fs.symlink('/', '/mylink', function(error) {
if(error) throw error;
fs.lstat('/mylink', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('SYMLINK');
done();
});
});
});
});

View File

@ -1,49 +1,49 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.mkdir', function() { describe('fs.mkdir', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.mkdir).to.be.a('function'); expect(fs.mkdir).to.be.a('function');
}); });
it('should return an error if part of the parent path does not exist', function(done) { it('should return an error if part of the parent path does not exist', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.mkdir('/tmp/mydir', function(error) { fs.mkdir('/tmp/mydir', function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("ENOENT"); expect(error.code).to.equal("ENOENT");
done(); done();
});
});
it('should return an error if the path already exists', function(done) {
var fs = util.fs();
fs.mkdir('/', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("EEXIST");
done();
});
});
it('should make a new directory', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
expect(error).not.to.exist;
if(error) throw error;
fs.stat('/tmp', function(error, stats) {
expect(error).not.to.exist;
expect(stats).to.exist;
expect(stats.type).to.equal('DIRECTORY');
done();
});
});
}); });
}); });
}); it('should return an error if the path already exists', function(done) {
var fs = util.fs();
fs.mkdir('/', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("EEXIST");
done();
});
});
it('should make a new directory', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
expect(error).not.to.exist;
if(error) throw error;
fs.stat('/tmp', function(error, stats) {
expect(error).not.to.exist;
expect(stats).to.exist;
expect(stats.type).to.equal('DIRECTORY');
done();
});
});
});
});

View File

@ -1,80 +1,81 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
describe('fs.mknod', function() { var util = require('../lib/test-utils.js');
beforeEach(util.setup); var expect = require('chai').expect;
afterEach(util.cleanup);
describe('fs.mknod', function() {
it('should be a function', function(done) { beforeEach(util.setup);
var fs = util.fs(); afterEach(util.cleanup);
expect(fs.mknod).to.be.a('function');
it('should be a function', function(done) {
var fs = util.fs();
expect(fs.mknod).to.be.a('function');
done();
});
it('should return an error if part of the parent path does not exist', function(done) {
var fs = util.fs();
fs.mknod('/dir/mydir', 'DIRECTORY', function(error) {
expect(error.code).to.equal('ENOENT');
done(); done();
}); });
it('should return an error if part of the parent path does not exist', function(done) {
var fs = util.fs();
fs.mknod('/dir/mydir', 'DIRECTORY', function(error) {
expect(error.code).to.equal('ENOENT');
done();
});
});
it('should return an error if path already exists', function(done) {
var fs = util.fs();
fs.mknod('/', 'DIRECTORY', function(error) {
expect(error.code).to.equal('EEXIST');
done();
});
});
it('should return an error if the parent node is not a directory', function(done) {
var fs = util.fs();
fs.mknod('/file', 'FILE' , function(error, result) {
if(error) throw error;
fs.mknod('/file/myfile', 'FILE', function(error, result) {
expect(error.code).to.equal('ENOTDIR');
done();
});
});
});
it('should return an error if the mode provided is not DIRECTORY or FILE', function(done) {
var fs = util.fs();
fs.mknod('/symlink', 'SYMLINK', function(error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
it('should make a new directory', function(done) {
var fs = util.fs();
fs.mknod('/dir', 'DIRECTORY', function(error) {
if(error) throw error;
fs.stat('/dir', function(error, stats) {
expect(error).not.to.exist;
expect(stats.type).to.equal('DIRECTORY');
done();
});
});
});
it('should make a new file', function(done) {
var fs = util.fs();
fs.mknod('/file', 'FILE' , function(error, result) {
if(error) throw error;
fs.stat('/file', function(error, result) {
expect(error).not.to.exist;
expect(result.type).to.equal('FILE');
done();
});
});
});
}); });
});
it('should return an error if path already exists', function(done) {
var fs = util.fs();
fs.mknod('/', 'DIRECTORY', function(error) {
expect(error.code).to.equal('EEXIST');
done();
});
});
it('should return an error if the parent node is not a directory', function(done) {
var fs = util.fs();
fs.mknod('/file', 'FILE' , function(error, result) {
if(error) throw error;
fs.mknod('/file/myfile', 'FILE', function(error, result) {
expect(error.code).to.equal('ENOTDIR');
done();
});
});
});
it('should return an error if the mode provided is not DIRECTORY or FILE', function(done) {
var fs = util.fs();
fs.mknod('/symlink', 'SYMLINK', function(error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
it('should make a new directory', function(done) {
var fs = util.fs();
fs.mknod('/dir', 'DIRECTORY', function(error) {
if(error) throw error;
fs.stat('/dir', function(error, stats) {
expect(error).not.to.exist;
expect(stats.type).to.equal('DIRECTORY');
done();
});
});
});
it('should make a new file', function(done) {
var fs = util.fs();
fs.mknod('/file', 'FILE' , function(error, result) {
if(error) throw error;
fs.stat('/file', function(error, result) {
expect(error).not.to.exist;
expect(result.type).to.equal('FILE');
done();
});
});
});
});

View File

@ -1,109 +1,109 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
var constants = require('../../src/constants.js');
describe('fs.open', function() { describe('fs.open', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.open).to.be.a('function'); expect(fs.open).to.be.a('function');
});
it('should return an error if the parent path does not exist', function(done) {
var fs = util.fs();
fs.open('/tmp/myfile', 'w+', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(result).not.to.exist;
done();
}); });
});
it('should return an error if the parent path does not exist', function(done) { it('should return an error when flagged for read and the path does not exist', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.open('/tmp/myfile', 'w+', function(error, result) { fs.open('/myfile', 'r+', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(result).not.to.exist;
done();
});
});
it('should return an error when flagged for write and the path is a directory', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.open('/tmp', 'w', function(error, result) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("ENOENT"); expect(error.code).to.equal("EISDIR");
expect(result).not.to.exist; expect(result).not.to.exist;
done(); done();
}); });
}); });
it('should return an error when flagged for read and the path does not exist', function(done) {
var fs = util.fs();
fs.open('/myfile', 'r+', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(result).not.to.exist;
done();
});
});
it('should return an error when flagged for write and the path is a directory', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.open('/tmp', 'w', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("EISDIR");
expect(result).not.to.exist;
done();
});
});
});
it('should return an error when flagged for append and the path is a directory', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.open('/tmp', 'a', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("EISDIR");
expect(result).not.to.exist;
done();
});
});
});
it('should return a unique file descriptor', function(done) {
var fs = util.fs();
var fd1;
fs.open('/file1', 'w+', function(error, fd) {
if(error) throw error;
expect(error).not.to.exist;
expect(fd).to.be.a('number');
fs.open('/file2', 'w+', function(error, fd) {
if(error) throw error;
expect(error).not.to.exist;
expect(fd).to.be.a('number');
expect(fd).not.to.equal(fd1);
done();
});
});
});
it('should return the argument value of the file descriptor index matching the value set by the first useable file descriptor constant', function(done) {
var fs = util.fs();
var firstFD = require('src/constants').FIRST_DESCRIPTOR;
var fd1;
fs.open('/file1', 'w+', function(error, fd) {
if(error) throw error;
expect(fd).to.equal(firstFD);
done();
});
});
it('should create a new file when flagged for write', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('FILE');
done();
});
});
});
}); });
it('should return an error when flagged for append and the path is a directory', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.open('/tmp', 'a', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("EISDIR");
expect(result).not.to.exist;
done();
});
});
});
it('should return a unique file descriptor', function(done) {
var fs = util.fs();
var fd1;
fs.open('/file1', 'w+', function(error, fd) {
if(error) throw error;
expect(error).not.to.exist;
expect(fd).to.be.a('number');
fs.open('/file2', 'w+', function(error, fd) {
if(error) throw error;
expect(error).not.to.exist;
expect(fd).to.be.a('number');
expect(fd).not.to.equal(fd1);
done();
});
});
});
it('should return the argument value of the file descriptor index matching the value set by the first useable file descriptor constant', function(done) {
var fs = util.fs();
var firstFD = constants.FIRST_DESCRIPTOR;
var fd1;
fs.open('/file1', 'w+', function(error, fd) {
if(error) throw error;
expect(fd).to.equal(firstFD);
done();
});
});
it('should create a new file when flagged for write', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('FILE');
done();
});
});
});
}); });

View File

@ -1,62 +1,62 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.read', function() { describe('fs.read', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.read).to.be.a('function'); expect(fs.read).to.be.a('function');
}); });
it('should read data from a file', function(done) { it('should read data from a file', function(done) {
var fs = util.fs(); var fs = util.fs();
var wbuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); var wbuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var rbuffer = new Uint8Array(wbuffer.length); var rbuffer = new Uint8Array(wbuffer.length);
fs.open('/myfile', 'w+', function(error, fd) { fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.write(fd, wbuffer, 0, wbuffer.length, 0, function(error, result) {
if(error) throw error; if(error) throw error;
fs.write(fd, wbuffer, 0, wbuffer.length, 0, function(error, result) {
fs.read(fd, rbuffer, 0, rbuffer.length, 0, function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal(rbuffer.length);
expect(wbuffer).to.deep.equal(rbuffer);
done();
});
});
});
});
it('should update the current file position', function(done) {
var fs = util.fs();
var wbuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var rbuffer = new Uint8Array(wbuffer.length);
var _result = 0;
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.write(fd, wbuffer, 0, wbuffer.length, 0, function(error, result) {
if(error) throw error;
fs.read(fd, rbuffer, 0, rbuffer.length / 2, undefined, function(error, result) {
if(error) throw error; if(error) throw error;
fs.read(fd, rbuffer, 0, rbuffer.length, 0, function(error, result) { _result += result;
fs.read(fd, rbuffer, rbuffer.length / 2, rbuffer.length, undefined, function(error, result) {
if(error) throw error;
_result += result;
expect(error).not.to.exist; expect(error).not.to.exist;
expect(result).to.equal(rbuffer.length); expect(_result).to.equal(rbuffer.length);
expect(wbuffer).to.deep.equal(rbuffer); expect(wbuffer).to.deep.equal(rbuffer);
done(); done();
}); });
}); });
}); });
}); });
it('should update the current file position', function(done) {
var fs = util.fs();
var wbuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var rbuffer = new Uint8Array(wbuffer.length);
var _result = 0;
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.write(fd, wbuffer, 0, wbuffer.length, 0, function(error, result) {
if(error) throw error;
fs.read(fd, rbuffer, 0, rbuffer.length / 2, undefined, function(error, result) {
if(error) throw error;
_result += result;
fs.read(fd, rbuffer, rbuffer.length / 2, rbuffer.length, undefined, function(error, result) {
if(error) throw error;
_result += result;
expect(error).not.to.exist;
expect(_result).to.equal(rbuffer.length);
expect(wbuffer).to.deep.equal(rbuffer);
done();
});
});
});
});
});
}); });
});
});

View File

@ -1,32 +1,51 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.readdir', function() { describe('fs.readdir', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.readdir).to.be.a('function'); expect(fs.readdir).to.be.a('function');
});
it('should return an error if the path does not exist', function(done) {
var fs = util.fs();
fs.readdir('/tmp/mydir', function(error, files) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(files).not.to.exist;
done();
}); });
});
it('should return an error if the path does not exist', function(done) { it('should return a list of files from an existing directory', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.readdir('/tmp/mydir', function(error, files) { fs.mkdir('/tmp', function(error) {
expect(error).to.exist; if(error) throw error;
expect(error.code).to.equal("ENOENT");
expect(files).not.to.exist; fs.readdir('/', function(error, files) {
expect(error).not.to.exist;
expect(files).to.exist;
expect(files.length).to.equal(1);
expect(files[0]).to.equal('tmp');
done(); done();
}); });
}); });
});
it('should return a list of files from an existing directory', function(done) { it('should follow symbolic links', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.mkdir('/tmp', function(error) { fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.symlink('/', '/tmp/dirLink', function(error) {
if(error) throw error; if(error) throw error;
fs.readdir('/tmp/dirLink', function(error, files) {
fs.readdir('/', function(error, files) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(files).to.exist; expect(files).to.exist;
expect(files.length).to.equal(1); expect(files.length).to.equal(1);
@ -35,24 +54,5 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
it('should follow symbolic links', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.symlink('/', '/tmp/dirLink', function(error) {
if(error) throw error;
fs.readdir('/tmp/dirLink', function(error, files) {
expect(error).not.to.exist;
expect(files).to.exist;
expect(files.length).to.equal(1);
expect(files[0]).to.equal('tmp');
done();
});
});
});
});
}); });
});
});

View File

@ -1,47 +1,47 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.readlink', function() { describe('fs.readlink', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.readlink).to.be.a('function'); expect(fs.readlink).to.be.a('function');
}); });
it('should return an error if part of the parent destination path does not exist', function(done) { it('should return an error if part of the parent destination path does not exist', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.readlink('/tmp/mydir', function(error) { fs.readlink('/tmp/mydir', function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("ENOENT"); expect(error.code).to.equal("ENOENT");
done(); done();
});
});
it('should return an error if the path is not a symbolic link', function(done) {
var fs = util.fs();
fs.readlink('/', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
done();
});
});
it('should return the contents of a symbolic link', function(done) {
var fs = util.fs();
fs.symlink('/', '/myfile', function(error) {
if(error) throw error;
fs.readlink('/myfile', function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal('/');
done();
});
});
}); });
}); });
}); it('should return an error if the path is not a symbolic link', function(done) {
var fs = util.fs();
fs.readlink('/', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
done();
});
});
it('should return the contents of a symbolic link', function(done) {
var fs = util.fs();
fs.symlink('/', '/myfile', function(error) {
if(error) throw error;
fs.readlink('/myfile', function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal('/');
done();
});
});
});
});

View File

@ -1,50 +1,50 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.rename', function() { describe('fs.rename', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.rename).to.be.a('function'); expect(fs.rename).to.be.a('function');
}); });
it('should rename an existing file', function(done) { it('should rename an existing file', function(done) {
var complete1 = false; var complete1 = false;
var complete2 = false; var complete2 = false;
var fs = util.fs(); var fs = util.fs();
function maybeDone() { function maybeDone() {
if(complete1 && complete2) { if(complete1 && complete2) {
done(); done();
}
} }
}
fs.open('/myfile', 'w+', function(error, fd) { fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error; if(error) throw error;
fs.close(fd, function(error) { fs.rename('/myfile', '/myotherfile', function(error) {
if(error) throw error; if(error) throw error;
fs.rename('/myfile', '/myotherfile', function(error) { fs.stat('/myfile', function(error, result) {
if(error) throw error; expect(error).to.exist;
complete1 = true;
maybeDone();
});
fs.stat('/myfile', function(error, result) { fs.stat('/myotherfile', function(error, result) {
expect(error).to.exist; expect(error).not.to.exist;
complete1 = true; expect(result.nlinks).to.equal(1);
maybeDone(); complete2 = true;
}); maybeDone();
fs.stat('/myotherfile', function(error, result) {
expect(error).not.to.exist;
expect(result.nlinks).to.equal(1);
complete2 = true;
maybeDone();
});
}); });
}); });
}); });
}); });
}); });
}); });

View File

@ -1,77 +1,62 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.rmdir', function() { describe('fs.rmdir', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.rmdir).to.be.a('function'); expect(fs.rmdir).to.be.a('function');
});
it('should return an error if the path does not exist', function(done) {
var fs = util.fs();
fs.rmdir('/tmp/mydir', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
done();
}); });
});
it('should return an error if the path does not exist', function(done) { it('should return an error if attempting to remove the root directory', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.rmdir('/tmp/mydir', function(error) { fs.rmdir('/', function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("ENOENT"); expect(error.code).to.equal("EBUSY");
done(); done();
});
}); });
});
it('should return an error if attempting to remove the root directory', function(done) { it('should return an error if the directory is not empty', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.rmdir('/', function(error) { fs.mkdir('/tmp', function(error) {
expect(error).to.exist; if(error) throw error;
expect(error.code).to.equal("EBUSY"); fs.mkdir('/tmp/mydir', function(error) {
done();
});
});
it('should return an error if the directory is not empty', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error; if(error) throw error;
fs.mkdir('/tmp/mydir', function(error) { fs.rmdir('/', function(error) {
if(error) throw error; expect(error).to.exist;
fs.rmdir('/', function(error) { expect(error.code).to.equal("EBUSY");
expect(error).to.exist; done();
expect(error.code).to.equal("EBUSY");
done();
});
}); });
}); });
}); });
});
it('should return an error if the path is not a directory', function(done) { it('should return an error if the path is not a directory', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.mkdir('/tmp', function(error) { fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.open('/tmp/myfile', 'w', function(error, fd) {
if(error) throw error; if(error) throw error;
fs.open('/tmp/myfile', 'w', function(error, fd) { fs.close(fd, function(error) {
if(error) throw error; if(error) throw error;
fs.close(fd, function(error) { fs.rmdir('/tmp/myfile', function(error) {
if(error) throw error;
fs.rmdir('/tmp/myfile', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("ENOTDIR");
done();
});
});
});
});
});
it('should return an error if the path is a symbolic link', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function (error) {
if(error) throw error;
fs.symlink('/tmp', '/tmp/myfile', function (error) {
if(error) throw error;
fs.rmdir('/tmp/myfile', function (error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("ENOTDIR"); expect(error.code).to.equal("ENOTDIR");
done(); done();
@ -79,23 +64,38 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
});
it('should remove an existing directory', function(done) { it('should return an error if the path is a symbolic link', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.mkdir('/tmp', function(error) { fs.mkdir('/tmp', function (error) {
if(error) throw error;
fs.symlink('/tmp', '/tmp/myfile', function (error) {
if(error) throw error; if(error) throw error;
fs.rmdir('/tmp', function(error) { fs.rmdir('/tmp/myfile', function (error) {
expect(error).not.to.exist; expect(error).to.exist;
if(error) throw error; expect(error.code).to.equal("ENOTDIR");
fs.stat('/tmp', function(error, stats) { done();
expect(error).to.exist;
expect(stats).not.to.exist;
done();
});
}); });
}); });
}); });
}); });
it('should remove an existing directory', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error;
fs.rmdir('/tmp', function(error) {
expect(error).not.to.exist;
if(error) throw error;
fs.stat('/tmp', function(error, stats) {
expect(error).to.exist;
expect(stats).not.to.exist;
done();
});
});
});
});
}); });

View File

@ -1,24 +1,24 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe("fs", function() { describe("fs", function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it("is an object", function() { it("is an object", function() {
var fs = util.fs(); var fs = util.fs();
expect(typeof fs).to.equal('object'); expect(typeof fs).to.equal('object');
expect(fs).to.be.an.instanceof(Filer.FileSystem); expect(fs).to.be.an.instanceof(Filer.FileSystem);
});
it('should have a root directory', function(done) {
var fs = util.fs();
fs.stat('/', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('DIRECTORY');
done();
});
});
}); });
it('should have a root directory', function(done) {
var fs = util.fs();
fs.stat('/', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('DIRECTORY');
done();
});
});
}); });

View File

@ -1,95 +1,95 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.stat', function() { describe('fs.stat', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(typeof fs.stat).to.equal('function'); expect(typeof fs.stat).to.equal('function');
});
it('should return an error if path does not exist', function(done) {
var fs = util.fs();
fs.stat('/tmp', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(result).not.to.exist;
done();
}); });
});
it('should return an error if path does not exist', function(done) { it('should return a stat object if path exists', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/tmp', function(error, result) { fs.stat('/', function(error, result) {
expect(error).to.exist; expect(error).not.to.exist;
expect(error.code).to.equal("ENOENT"); expect(result).to.exit;
expect(result).not.to.exist;
done(); expect(result['node']).to.be.a('string');
expect(result['dev']).to.equal(fs.name);
expect(result['size']).to.be.a('number');
expect(result['nlinks']).to.be.a('number');
expect(result['atime']).to.be.a('number');
expect(result['mtime']).to.be.a('number');
expect(result['ctime']).to.be.a('number');
expect(result['type']).to.equal('DIRECTORY');
done();
});
});
it('should follow symbolic links and return a stat object for the resulting path', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result['node']).to.exist;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.stat('/myfilelink', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result['node']).to.exist;
done();
});
});
});
}); });
}); });
});
it('should return a stat object if path exists', function(done) { it('should return a stat object for a valid descriptor', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, result) { fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.fstat(fd, function(error, result) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(result).to.exit; expect(result).to.exist;
expect(result['node']).to.be.a('string'); expect(result['node']).to.exist;
expect(result['dev']).to.equal(fs.name); expect(result['dev']).to.equal(fs.name);
expect(result['size']).to.be.a('number'); expect(result['size']).to.be.a('number');
expect(result['nlinks']).to.be.a('number'); expect(result['nlinks']).to.be.a('number');
expect(result['atime']).to.be.a('number'); expect(result['atime']).to.be.a('number');
expect(result['mtime']).to.be.a('number'); expect(result['mtime']).to.be.a('number');
expect(result['ctime']).to.be.a('number'); expect(result['ctime']).to.be.a('number');
expect(result['type']).to.equal('DIRECTORY'); expect(result['type']).to.equal('FILE');
done(); done();
}); });
}); });
it('should follow symbolic links and return a stat object for the resulting path', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result['node']).to.exist;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.stat('/myfilelink', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result['node']).to.exist;
done();
});
});
});
});
});
});
it('should return a stat object for a valid descriptor', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.fstat(fd, function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result['node']).to.exist;
expect(result['dev']).to.equal(fs.name);
expect(result['size']).to.be.a('number');
expect(result['nlinks']).to.be.a('number');
expect(result['atime']).to.be.a('number');
expect(result['mtime']).to.be.a('number');
expect(result['ctime']).to.be.a('number');
expect(result['type']).to.equal('FILE');
done();
});
});
});
}); });
});
});

View File

@ -1,247 +1,248 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.stats', function() { describe('fs.stats', function() {
describe('#isFile()', function() { describe('#isFile()', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isFile).to.be.a('function'); expect(stats.isFile).to.be.a('function');
});
}); });
});
it('should return true if stats are for file', function(done) { it('should return true if stats are for file', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) { fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error; if(error) throw error;
fs.fstat(fd, function(error, stats) { fs.fstat(fd, function(error, stats) {
expect(stats.isFile()).to.be.true; expect(stats.isFile()).to.be.true;
done();
});
});
});
it('should return false if stats are for directory', function(done) {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isFile()).to.be.false;
done(); done();
}); });
}); });
});
it('should return false if stats are for symbolic link', function(done) { it('should return false if stats are for directory', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) { fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isFile()).to.be.false;
done();
});
});
it('should return false if stats are for symbolic link', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error, stats) {
if(error) throw error; if(error) throw error;
fs.close(fd, function(error, stats) { fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error; if(error) throw error;
fs.symlink('/myfile', '/myfilelink', function(error) { fs.lstat('/myfilelink', function(error, stats) {
if(error) throw error; expect(stats.isFile()).to.be.false;
fs.lstat('/myfilelink', function(error, stats) { done();
expect(stats.isFile()).to.be.false;
done();
});
}); });
}); });
}); });
}); });
}); });
describe('#isDirectory()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isDirectory).to.be.a('function');
});
});
it('should return false if stats are for file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.fstat(fd, function(error, stats) {
expect(stats.isDirectory()).to.be.false;
done();
});
});
});
it('should return true if stats are for directory', function(done) {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isDirectory()).to.be.true;
done();
});
});
it('should return false if stats are for symbolic link', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error, stats) {
if(error) throw error;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.lstat('/myfilelink', function(error, stats) {
expect(stats.isDirectory()).to.be.false;
done();
});
});
});
});
});
});
describe('#isBlockDevice()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isBlockDevice).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isBlockDevice()).to.be.false;
});
});
});
describe('#isCharacterDevice()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isCharacterDevice).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isCharacterDevice()).to.be.false;
});
});
});
describe('#isSymbolicLink()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSymbolicLink).to.be.a('function');
});
});
it('should return false if stats are for file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.fstat(fd, function(error, stats) {
expect(stats.isSymbolicLink()).to.be.false;
done();
});
});
});
it('should return false if stats are for directory', function(done) {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSymbolicLink()).to.be.false;
done();
});
});
it('should return true if stats are for symbolic link', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error, stats) {
if(error) throw error;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.lstat('/myfilelink', function(error, stats) {
expect(stats.isSymbolicLink()).to.be.true;
done();
});
});
});
});
});
});
describe('#isFIFO()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isFIFO).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isFIFO()).to.be.false;
});
});
});
describe('#isSocket()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSocket).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSocket()).to.be.false;
});
});
});
}); });
});
describe('#isDirectory()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isDirectory).to.be.a('function');
});
});
it('should return false if stats are for file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.fstat(fd, function(error, stats) {
expect(stats.isDirectory()).to.be.false;
done();
});
});
});
it('should return true if stats are for directory', function(done) {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isDirectory()).to.be.true;
done();
});
});
it('should return false if stats are for symbolic link', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error, stats) {
if(error) throw error;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.lstat('/myfilelink', function(error, stats) {
expect(stats.isDirectory()).to.be.false;
done();
});
});
});
});
});
});
describe('#isBlockDevice()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isBlockDevice).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isBlockDevice()).to.be.false;
});
});
});
describe('#isCharacterDevice()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isCharacterDevice).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isCharacterDevice()).to.be.false;
});
});
});
describe('#isSymbolicLink()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSymbolicLink).to.be.a('function');
});
});
it('should return false if stats are for file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.fstat(fd, function(error, stats) {
expect(stats.isSymbolicLink()).to.be.false;
done();
});
});
});
it('should return false if stats are for directory', function(done) {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSymbolicLink()).to.be.false;
done();
});
});
it('should return true if stats are for symbolic link', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error, stats) {
if(error) throw error;
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error;
fs.lstat('/myfilelink', function(error, stats) {
expect(stats.isSymbolicLink()).to.be.true;
done();
});
});
});
});
});
});
describe('#isFIFO()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isFIFO).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isFIFO()).to.be.false;
});
});
});
describe('#isSocket()', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSocket).to.be.a('function');
});
});
it('should return false', function() {
var fs = util.fs();
fs.stat('/', function(error, stats) {
if(error) throw error;
expect(stats.isSocket()).to.be.false;
});
});
});
});

View File

@ -1,47 +1,47 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.symlink', function() { describe('fs.symlink', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.symlink).to.be.a('function'); expect(fs.symlink).to.be.a('function');
}); });
it('should return an error if part of the parent destination path does not exist', function(done) { it('should return an error if part of the parent destination path does not exist', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.symlink('/', '/tmp/mydir', function(error) { fs.symlink('/', '/tmp/mydir', function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("ENOENT"); expect(error.code).to.equal("ENOENT");
done(); done();
});
});
it('should return an error if the destination path already exists', function(done) {
var fs = util.fs();
fs.symlink('/tmp', '/', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("EEXIST");
done();
});
});
it('should create a symlink', function(done) {
var fs = util.fs();
fs.symlink('/', '/myfile', function(error) {
expect(error).not.to.exist;
fs.stat('/myfile', function(err, stats) {
expect(error).not.to.exist;
expect(stats.type).to.equal('DIRECTORY');
done();
});
});
}); });
}); });
it('should return an error if the destination path already exists', function(done) {
var fs = util.fs();
fs.symlink('/tmp', '/', function(error) {
expect(error).to.exist;
expect(error.code).to.equal("EEXIST");
done();
});
});
it('should create a symlink', function(done) {
var fs = util.fs();
fs.symlink('/', '/myfile', function(error) {
expect(error).not.to.exist;
fs.stat('/myfile', function(err, stats) {
expect(error).not.to.exist;
expect(stats.type).to.equal('DIRECTORY');
done();
});
});
});
}); });

View File

@ -1,143 +1,119 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.truncate', function() { describe('fs.truncate', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.truncate).to.be.a('function'); expect(fs.truncate).to.be.a('function');
}); });
it('should error when length is negative', function(done) { it('should error when length is negative', function(done) {
var fs = util.fs(); var fs = util.fs();
var contents = "This is a file."; var contents = "This is a file.";
fs.writeFile('/myfile', contents, function(error) { fs.writeFile('/myfile', contents, function(error) {
if(error) throw error; if(error) throw error;
fs.truncate('/myfile', -1, function(error) { fs.truncate('/myfile', -1, function(error) {
expect(error).to.exist;
expect(error.code).to.equal("EINVAL");
done();
});
});
});
it('should error when path is not a file', function(done) {
var fs = util.fs();
fs.truncate('/', 0, function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal("EISDIR"); expect(error.code).to.equal("EINVAL");
done(); done();
}); });
}); });
});
it('should truncate a file', function(done) { it('should error when path is not a file', function(done) {
var fs = util.fs(); var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var truncated = new Uint8Array([1]);
fs.open('/myfile', 'w', function(error, result) { fs.truncate('/', 0, function(error) {
if(error) throw error; expect(error).to.exist;
expect(error.code).to.equal("EISDIR");
var fd = result; done();
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
fs.truncate('/myfile', 1, function(error) {
expect(error).not.to.exist;
fs.readFile('/myfile', function(error, result) {
if(error) throw error;
expect(result).to.deep.equal(truncated);
done();
});
});
});
});
});
}); });
});
it('should pad a file with zeros when the length is greater than the file size', function(done) { it('should truncate a file', function(done) {
var fs = util.fs(); var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var truncated = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 0]); var truncated = new Uint8Array([1]);
fs.open('/myfile', 'w', function(error, result) { fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error; if(error) throw error;
var fd = result; fs.close(fd, function(error) {
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error; if(error) throw error;
fs.close(fd, function(error) { fs.truncate('/myfile', 1, function(error) {
if(error) throw error;
fs.truncate('/myfile', 9, function(error) {
expect(error).not.to.exist;
fs.readFile('/myfile', function(error, result) {
if(error) throw error;
expect(result).to.deep.equal(truncated);
done();
});
});
});
});
});
});
it('should update the file size', function(done) {
var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
fs.truncate('/myfile', 0, function(error) {
expect(error).not.to.exist;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result.size).to.equal(0);
done();
});
});
});
});
});
});
it('should truncate a valid descriptor', function(done) {
var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error;
fs.ftruncate(fd, 0, function(error) {
expect(error).not.to.exist; expect(error).not.to.exist;
fs.fstat(fd, function(error, result) { fs.readFile('/myfile', function(error, result) {
if(error) throw error;
expect(result).to.deep.equal(truncated);
done();
});
});
});
});
});
});
it('should pad a file with zeros when the length is greater than the file size', function(done) {
var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var truncated = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 0]);
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
fs.truncate('/myfile', 9, function(error) {
expect(error).not.to.exist;
fs.readFile('/myfile', function(error, result) {
if(error) throw error;
expect(result).to.deep.equal(truncated);
done();
});
});
});
});
});
});
it('should update the file size', function(done) {
var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
fs.truncate('/myfile', 0, function(error) {
expect(error).not.to.exist;
fs.stat('/myfile', function(error, result) {
if(error) throw error; if(error) throw error;
expect(result.size).to.equal(0); expect(result.size).to.equal(0);
@ -147,37 +123,62 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
});
it('should follow symbolic links', function(done) { it('should truncate a valid descriptor', function(done) {
var fs = util.fs(); var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
fs.open('/myfile', 'w', function(error, result) { fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error; if(error) throw error;
var fd = result; fs.ftruncate(fd, 0, function(error) {
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) { expect(error).not.to.exist;
if(error) throw error;
fs.close(fd, function(error) { fs.fstat(fd, function(error, result) {
if(error) throw error; if(error) throw error;
fs.symlink('/myfile', '/mylink', function(error) { expect(result.size).to.equal(0);
if(error) throw error; done();
});
});
});
});
});
fs.truncate('/mylink', 0, function(error) { it('should follow symbolic links', function(done) {
expect(error).not.to.exist; var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
fs.stat('/myfile', function(error, result) { fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
fs.symlink('/myfile', '/mylink', function(error) {
if(error) throw error;
fs.truncate('/mylink', 0, function(error) {
expect(error).not.to.exist;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result.size).to.equal(0);
fs.lstat('/mylink', function(error, result) {
if(error) throw error; if(error) throw error;
expect(result.size).to.equal(0); expect(result.size).not.to.equal(0);
fs.lstat('/mylink', function(error, result) { done();
if(error) throw error;
expect(result.size).not.to.equal(0);
done();
});
}); });
}); });
}); });
@ -186,4 +187,4 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
}); });

View File

@ -1,80 +1,50 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.unlink', function() { describe('fs.unlink', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.unlink).to.be.a('function'); expect(fs.unlink).to.be.a('function');
}); });
it('should remove a link to an existing file', function(done) { it('should remove a link to an existing file', function(done) {
var fs = util.fs(); var fs = util.fs();
var complete1, complete2; var complete1, complete2;
function maybeDone() { function maybeDone() {
if(complete1 && complete2) { if(complete1 && complete2) {
done(); done();
}
} }
}
fs.open('/myfile', 'w+', function(error, fd) { fs.open('/myfile', 'w+', function(error, fd) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error; if(error) throw error;
fs.close(fd, function(error) { fs.link('/myfile', '/myotherfile', function(error) {
if(error) throw error; if(error) throw error;
fs.link('/myfile', '/myotherfile', function(error) { fs.unlink('/myfile', function(error) {
if(error) throw error; if(error) throw error;
fs.unlink('/myfile', function(error) { fs.stat('/myfile', function(error, result) {
expect(error).to.exist;
complete1 = true;
maybeDone();
});
fs.stat('/myotherfile', function(error, result) {
if(error) throw error; if(error) throw error;
fs.stat('/myfile', function(error, result) { expect(result.nlinks).to.equal(1);
expect(error).to.exist; complete2 = true;
complete1 = true; maybeDone();
maybeDone();
});
fs.stat('/myotherfile', function(error, result) {
if(error) throw error;
expect(result.nlinks).to.equal(1);
complete2 = true;
maybeDone();
});
});
});
});
});
});
it('should not follow symbolic links', function(done) {
var fs = util.fs();
fs.symlink('/', '/myFileLink', function (error) {
if (error) throw error;
fs.link('/myFileLink', '/myotherfile', function (error) {
if (error) throw error;
fs.unlink('/myFileLink', function (error) {
if (error) throw error;
fs.lstat('/myFileLink', function (error, result) {
expect(error).to.exist;
fs.lstat('/myotherfile', function (error, result) {
if (error) throw error;
expect(result.nlinks).to.equal(1);
fs.stat('/', function (error, result) {
if (error) throw error;
expect(result.nlinks).to.equal(1);
done();
});
});
}); });
}); });
}); });
@ -82,4 +52,34 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
it('should not follow symbolic links', function(done) {
var fs = util.fs();
fs.symlink('/', '/myFileLink', function (error) {
if (error) throw error;
fs.link('/myFileLink', '/myotherfile', function (error) {
if (error) throw error;
fs.unlink('/myFileLink', function (error) {
if (error) throw error;
fs.lstat('/myFileLink', function (error, result) {
expect(error).to.exist;
fs.lstat('/myotherfile', function (error, result) {
if (error) throw error;
expect(result.nlinks).to.equal(1);
fs.stat('/', function (error, result) {
if (error) throw error;
expect(result.nlinks).to.equal(1);
done();
});
});
});
});
});
});
});
}); });

View File

@ -1,177 +1,178 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.utimes', function() { describe('fs.utimes', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.utimes).to.be.a('function'); expect(fs.utimes).to.be.a('function');
}); });
it('should error when atime is negative', function(done) { it('should error when atime is negative', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function(error) { fs.writeFile('/testfile', '', function(error) {
if (error) throw error; if (error) throw error;
fs.utimes('/testfile', -1, Date.now(), function (error) { fs.utimes('/testfile', -1, Date.now(), function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when mtime is negative', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function(error) {
if (error) throw error;
fs.utimes('/testfile', Date.now(), -1, function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when atime is as invalid number', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.utimes('/testfile', 'invalid datetime', Date.now(), function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when path does not exist', function(done) {
var fs = util.fs();
var atime = Date.parse('1 Oct 2000 15:33:22');
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.utimes('/pathdoesnotexist', atime, mtime, function (error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal('ENOENT'); expect(error.code).to.equal('EINVAL');
done(); done();
}); });
}); });
});
it('should error when mtime is an invalid number', function(done) { it('should error when mtime is negative', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function(error) {
if (error) throw error; if (error) throw error;
fs.utimes('/testfile', Date.now(), 'invalid datetime', function (error) { fs.utimes('/testfile', Date.now(), -1, function (error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal('EINVAL'); expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when atime is as invalid number', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.utimes('/testfile', 'invalid datetime', Date.now(), function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when path does not exist', function(done) {
var fs = util.fs();
var atime = Date.parse('1 Oct 2000 15:33:22');
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.utimes('/pathdoesnotexist', atime, mtime, function (error) {
expect(error).to.exist;
expect(error.code).to.equal('ENOENT');
done();
});
});
it('should error when mtime is an invalid number', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.utimes('/testfile', Date.now(), 'invalid datetime', function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when file descriptor is invalid', function(done) {
var fs = util.fs();
var atime = Date.parse('1 Oct 2000 15:33:22');
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.futimes(1, atime, mtime, function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EBADF');
done();
});
});
it('should change atime and mtime of a file path', function(done) {
var fs = util.fs();
var atime = Date.parse('1 Oct 2000 15:33:22');
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.utimes('/testfile', atime, mtime, function (error) {
expect(error).not.to.exist;
fs.stat('/testfile', function (error, stat) {
expect(error).not.to.exist;
expect(stat.mtime).to.equal(mtime);
done(); done();
}); });
}); });
}); });
});
it('should error when file descriptor is invalid', function(done) { it ('should change atime and mtime for a valid file descriptor', function(done) {
var fs = util.fs(); var fs = util.fs();
var atime = Date.parse('1 Oct 2000 15:33:22'); var ofd;
var mtime = Date.parse('30 Sep 2000 06:43:54'); var atime = Date.parse('1 Oct 2000 15:33:22');
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.futimes(1, atime, mtime, function (error) { fs.open('/testfile', 'w', function (error, result) {
expect(error).to.exist; if (error) throw error;
expect(error.code).to.equal('EBADF');
done();
});
});
it('should change atime and mtime of a file path', function(done) { ofd = result;
var fs = util.fs(); fs.futimes(ofd, atime, mtime, function (error) {
var atime = Date.parse('1 Oct 2000 15:33:22'); expect(error).not.to.exist;
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.writeFile('/testfile', '', function (error) { fs.fstat(ofd, function (error, stat) {
if (error) throw error;
fs.utimes('/testfile', atime, mtime, function (error) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(stat.mtime).to.equal(mtime);
fs.stat('/testfile', function (error, stat) {
expect(error).not.to.exist;
expect(stat.mtime).to.equal(mtime);
done(); done();
});
}); });
}); });
}); });
});
it ('should change atime and mtime for a valid file descriptor', function(done) { it('should update atime and mtime of directory path', function(done) {
var fs = util.fs(); var fs = util.fs();
var ofd; var atime = Date.parse('1 Oct 2000 15:33:22');
var atime = Date.parse('1 Oct 2000 15:33:22'); var mtime = Date.parse('30 Sep 2000 06:43:54');
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.open('/testfile', 'w', function (error, result) { fs.mkdir('/testdir', function (error) {
if (error) throw error; if (error) throw error;
ofd = result; fs.utimes('/testdir', atime, mtime, function (error) {
fs.futimes(ofd, atime, mtime, function (error) { expect(error).not.to.exist;
fs.stat('/testdir', function (error, stat) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(stat.mtime).to.equal(mtime);
fs.fstat(ofd, function (error, stat) { done();
expect(error).not.to.exist;
expect(stat.mtime).to.equal(mtime);
done();
});
}); });
}); });
}); });
});
it('should update atime and mtime of directory path', function(done) { it('should update atime and mtime using current time if arguments are null', function(done) {
var fs = util.fs(); var fs = util.fs();
var atime = Date.parse('1 Oct 2000 15:33:22'); var atimeEst;
var mtime = Date.parse('30 Sep 2000 06:43:54'); var mtimeEst;
fs.mkdir('/testdir', function (error) { fs.writeFile('/myfile', '', function (error) {
if (error) throw error; if (error) throw error;
fs.utimes('/testdir', atime, mtime, function (error) { var then = Date.now();
fs.utimes('/myfile', null, null, function (error) {
expect(error).not.to.exist;
fs.stat('/myfile', function (error, stat) {
expect(error).not.to.exist; expect(error).not.to.exist;
// Note: testing estimation as time may differ by a couple of milliseconds
fs.stat('/testdir', function (error, stat) { // This number should be increased if tests are on slow systems
expect(error).not.to.exist; var delta = Date.now() - then;
expect(stat.mtime).to.equal(mtime); expect(then - stat.atime).to.be.at.most(delta);
done(); expect(then - stat.mtime).to.be.at.most(delta);
}); done();
});
});
});
it('should update atime and mtime using current time if arguments are null', function(done) {
var fs = util.fs();
var atimeEst;
var mtimeEst;
fs.writeFile('/myfile', '', function (error) {
if (error) throw error;
var then = Date.now();
fs.utimes('/myfile', null, null, function (error) {
expect(error).not.to.exist;
fs.stat('/myfile', function (error, stat) {
expect(error).not.to.exist;
// Note: testing estimation as time may differ by a couple of milliseconds
// This number should be increased if tests are on slow systems
var delta = Date.now() - then;
expect(then - stat.atime).to.be.below(delta);
expect(then - stat.mtime).to.be.below(delta);
done();
});
}); });
}); });
}); });

View File

@ -1,43 +1,43 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.watch', function() { describe('fs.watch', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(typeof fs.watch).to.equal('function'); expect(typeof fs.watch).to.equal('function');
});
it('should get a change event when writing a file', function(done) {
var fs = util.fs();
var watcher = fs.watch('/myfile', function(event, filename) {
expect(event).to.equal('change');
expect(filename).to.equal('/myfile');
watcher.close();
done();
}); });
it('should get a change event when writing a file', function(done) { fs.writeFile('/myfile', 'data', function(error) {
var fs = util.fs(); if(error) throw error;
var watcher = fs.watch('/myfile', function(event, filename) {
expect(event).to.equal('change');
expect(filename).to.equal('/myfile');
watcher.close();
done();
});
fs.writeFile('/myfile', 'data', function(error) {
if(error) throw error;
});
});
it('should get a change event when writing a file in a dir with recursive=true', function(done) {
var fs = util.fs();
var watcher = fs.watch('/', { recursive: true }, function(event, filename) {
expect(event).to.equal('change');
expect(filename).to.equal('/');
watcher.close();
done();
});
fs.writeFile('/myfile', 'data', function(error) {
if(error) throw error;
});
}); });
}); });
it('should get a change event when writing a file in a dir with recursive=true', function(done) {
var fs = util.fs();
var watcher = fs.watch('/', { recursive: true }, function(event, filename) {
expect(event).to.equal('change');
expect(filename).to.equal('/');
watcher.close();
done();
});
fs.writeFile('/myfile', 'data', function(error) {
if(error) throw error;
});
});
}); });

View File

@ -1,62 +1,62 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.write', function() { describe('fs.write', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.write).to.be.a('function'); expect(fs.write).to.be.a('function');
}); });
it('should write data to a file', function(done) { it('should write data to a file', function(done) {
var fs = util.fs(); var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
fs.open('/myfile', 'w', function(error, fd) { fs.open('/myfile', 'w', function(error, fd) {
if(error) throw error; if(error) throw error;
fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) { fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal(buffer.length);
fs.stat('/myfile', function(error, result) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(result).to.equal(buffer.length); expect(result.type).to.equal('FILE');
expect(result.size).to.equal(buffer.length);
fs.stat('/myfile', function(error, result) { done();
expect(error).not.to.exist;
expect(result.type).to.equal('FILE');
expect(result.size).to.equal(buffer.length);
done();
});
});
});
});
it('should update the current file position', function(done) {
var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var _result = 0;
fs.open('/myfile', 'w', function(error, fd) {
if(error) throw error;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
_result += result;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
_result += result;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(error).not.to.exist;
expect(_result).to.equal(2 * buffer.length);
expect(result.size).to.equal(_result);
done();
});
});
}); });
}); });
}); });
}); });
it('should update the current file position', function(done) {
var fs = util.fs();
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
var _result = 0;
fs.open('/myfile', 'w', function(error, fd) {
if(error) throw error;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
_result += result;
fs.write(fd, buffer, 0, buffer.length, undefined, function(error, result) {
if(error) throw error;
_result += result;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(error).not.to.exist;
expect(_result).to.equal(2 * buffer.length);
expect(result.size).to.equal(_result);
done();
});
});
});
});
});
}); });

View File

@ -1,104 +1,104 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.writeFile, fs.readFile', function() { describe('fs.writeFile, fs.readFile', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var fs = util.fs(); var fs = util.fs();
expect(fs.writeFile).to.be.a('function'); expect(fs.writeFile).to.be.a('function');
expect(fs.readFile).to.be.a('function'); expect(fs.readFile).to.be.a('function');
});
it('should error when path is wrong to readFile', function(done) {
var fs = util.fs();
var contents = "This is a file.";
fs.readFile('/no-such-file', 'utf8', function(error, data) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(data).not.to.exist;
done();
}); });
});
it('should error when path is wrong to readFile', function(done) { it('should write, read a utf8 file without specifying utf8 in writeFile', function(done) {
var fs = util.fs(); var fs = util.fs();
var contents = "This is a file."; var contents = "This is a file.";
fs.readFile('/no-such-file', 'utf8', function(error, data) { fs.writeFile('/myfile', contents, function(error) {
expect(error).to.exist; if(error) throw error;
expect(error.code).to.equal("ENOENT"); fs.readFile('/myfile', 'utf8', function(error, data) {
expect(data).not.to.exist; expect(error).not.to.exist;
expect(data).to.equal(contents);
done(); done();
}); });
}); });
});
it('should write, read a utf8 file without specifying utf8 in writeFile', function(done) { it('should write, read a utf8 file with "utf8" option to writeFile', function(done) {
var fs = util.fs(); var fs = util.fs();
var contents = "This is a file."; var contents = "This is a file.";
fs.writeFile('/myfile', contents, function(error) { fs.writeFile('/myfile', contents, 'utf8', function(error) {
if(error) throw error; if(error) throw error;
fs.readFile('/myfile', 'utf8', function(error, data) { fs.readFile('/myfile', 'utf8', function(error, data) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(data).to.equal(contents); expect(data).to.equal(contents);
done(); done();
});
}); });
}); });
});
it('should write, read a utf8 file with "utf8" option to writeFile', function(done) { it('should write, read a utf8 file with {encoding: "utf8"} option to writeFile', function(done) {
var fs = util.fs(); var fs = util.fs();
var contents = "This is a file."; var contents = "This is a file.";
fs.writeFile('/myfile', contents, 'utf8', function(error) { fs.writeFile('/myfile', contents, { encoding: 'utf8' }, function(error) {
if(error) throw error; if(error) throw error;
fs.readFile('/myfile', 'utf8', function(error, data) { fs.readFile('/myfile', 'utf8', function(error, data) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(data).to.equal(contents); expect(data).to.equal(contents);
done(); done();
});
}); });
}); });
});
it('should write, read a utf8 file with {encoding: "utf8"} option to writeFile', function(done) { it('should write, read a binary file', function(done) {
var fs = util.fs(); var fs = util.fs();
var contents = "This is a file."; // String and utf8 binary encoded versions of the same thing:
var contents = "This is a file.";
var binary = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
fs.writeFile('/myfile', contents, { encoding: 'utf8' }, function(error) { fs.writeFile('/myfile', binary, function(error) {
if(error) throw error; if(error) throw error;
fs.readFile('/myfile', 'utf8', function(error, data) { fs.readFile('/myfile', function(error, data) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(data).to.equal(contents); expect(data).to.deep.equal(binary);
done(); done();
});
}); });
}); });
});
it('should write, read a binary file', function(done) { it('should follow symbolic links', function(done) {
var fs = util.fs(); var fs = util.fs();
// String and utf8 binary encoded versions of the same thing: var contents = "This is a file.";
var contents = "This is a file.";
var binary = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
fs.writeFile('/myfile', binary, function(error) { fs.writeFile('/myfile', '', { encoding: 'utf8' }, function(error) {
if(error) throw error; if(error) throw error;
fs.readFile('/myfile', function(error, data) { fs.symlink('/myfile', '/myFileLink', function (error) {
expect(error).not.to.exist; if (error) throw error;
expect(data).to.deep.equal(binary); fs.writeFile('/myFileLink', contents, 'utf8', function (error) {
done();
});
});
});
it('should follow symbolic links', function(done) {
var fs = util.fs();
var contents = "This is a file.";
fs.writeFile('/myfile', '', { encoding: 'utf8' }, function(error) {
if(error) throw error;
fs.symlink('/myfile', '/myFileLink', function (error) {
if (error) throw error; if (error) throw error;
fs.writeFile('/myFileLink', contents, 'utf8', function (error) { fs.readFile('/myFileLink', 'utf8', function(error, data) {
if (error) throw error; expect(error).not.to.exist;
fs.readFile('/myFileLink', 'utf8', function(error, data) { expect(data).to.equal(contents);
expect(error).not.to.exist; done();
expect(data).to.equal(contents);
done();
});
}); });
}); });
}); });
}); });
}); });
});
});

View File

@ -1,393 +1,394 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('fs.xattr', function() { describe('fs.xattr', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function () { it('should be a function', function () {
var fs = util.fs(); var fs = util.fs();
expect(fs.setxattr).to.be.a('function'); expect(fs.setxattr).to.be.a('function');
expect(fs.getxattr).to.be.a('function'); expect(fs.getxattr).to.be.a('function');
expect(fs.removexattr).to.be.a('function'); expect(fs.removexattr).to.be.a('function');
expect(fs.fsetxattr).to.be.a('function'); expect(fs.fsetxattr).to.be.a('function');
expect(fs.fgetxattr).to.be.a('function'); expect(fs.fgetxattr).to.be.a('function');
});
it('should error when setting with a name that is not a string', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 89, 'testvalue', function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
}); });
});
it('should error when setting with a name that is not a string', function(done) { it('should error when setting with a name that is null', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', null, 'testvalue', function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when setting with an invalid flag', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', 'value', 'InvalidFlag', function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when when setting an extended attribute which exists with XATTR_CREATE flag', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function(error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', 'value', function(error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 89, 'testvalue', function (error) { fs.setxattr('/testfile', 'test', 'othervalue', 'CREATE', function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal('EINVAL'); expect(error.code).to.equal('EEXIST');
done(); done();
}); });
}); });
}); });
});
it('should error when setting with a name that is null', function(done) { it('should error when setting an extended attribute which does not exist with XATTR_REPLACE flag', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function(error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', null, 'testvalue', function (error) { fs.setxattr('/testfile', 'test', 'value', 'REPLACE', function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal('EINVAL'); expect(error.code).to.equal('ENOATTR');
done(); done();
});
}); });
}); });
});
it('should error when setting with an invalid flag', function(done) { it('should error when getting an attribute with a name that is empty', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function(error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', 'value', 'InvalidFlag', function (error) { fs.getxattr('/testfile', '', function(error, value) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal('EINVAL'); expect(error.code).to.equal('EINVAL');
done(); done();
});
}); });
}); });
});
it('should error when when setting an extended attribute which exists with XATTR_CREATE flag', function(done) { it('should error when getting an attribute where the name is not a string', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function(error) { fs.writeFile('/testfile', '', function(error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', 'value', function(error) { fs.getxattr('/testfile', 89, function(error, value) {
if (error) throw error; expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
fs.setxattr('/testfile', 'test', 'othervalue', 'CREATE', function(error) { done();
expect(error).to.exist;
expect(error.code).to.equal('EEXIST');
done();
});
});
}); });
}); });
});
it('should error when setting an extended attribute which does not exist with XATTR_REPLACE flag', function(done) { it('should error when getting an attribute that does not exist', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function(error) { fs.writeFile('/testfile', '', function(error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', 'value', 'REPLACE', function(error) { fs.getxattr('/testfile', 'test', function(error, value) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal('ENOATTR'); expect(error.code).to.equal('ENOATTR');
done(); done();
});
}); });
}); });
});
it('should error when getting an attribute with a name that is empty', function(done) { it('should error when file descriptor is invalid', function(done) {
var fs = util.fs(); var fs = util.fs();
var completeSet, completeGet, completeRemove;
var _value;
fs.writeFile('/testfile', '', function(error) { completeSet = completeGet = completeRemove = false;
if (error) throw error;
fs.getxattr('/testfile', '', function(error, value) { function maybeDone() {
expect(error).to.exist; if(completeSet && completeGet && completeRemove) {
expect(error.code).to.equal('EINVAL'); done();
done();
});
});
});
it('should error when getting an attribute where the name is not a string', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function(error) {
if (error) throw error;
fs.getxattr('/testfile', 89, function(error, value) {
expect(error).to.exist;
expect(error.code).to.equal('EINVAL');
done();
});
});
});
it('should error when getting an attribute that does not exist', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function(error) {
if (error) throw error;
fs.getxattr('/testfile', 'test', function(error, value) {
expect(error).to.exist;
expect(error.code).to.equal('ENOATTR');
done();
});
});
});
it('should error when file descriptor is invalid', function(done) {
var fs = util.fs();
var completeSet, completeGet, completeRemove;
var _value;
completeSet = completeGet = completeRemove = false;
function maybeDone() {
if(completeSet && completeGet && completeRemove) {
done();
}
} }
}
fs.fsetxattr(1, 'test', 'value', function(error) { fs.fsetxattr(1, 'test', 'value', function(error) {
expect(error).to.exist; expect(error).to.exist;
expect(error.code).to.equal('EBADF'); expect(error.code).to.equal('EBADF');
completeSet = true; completeSet = true;
maybeDone(); maybeDone();
});
fs.fgetxattr(1, 'test', function(error, value) {
expect(error).to.exist;
expect(error.code).to.equal('EBADF');
expect(value).not.to.exist;
completeGet = true;
maybeDone();
});
fs.fremovexattr(1, 'test', function(error, value) {
expect(error).to.exist;
expect(error.code).to.equal('EBADF');
completeRemove = true;
maybeDone();
});
}); });
it('should set and get an extended attribute of a path', function(done) { fs.fgetxattr(1, 'test', function(error, value) {
var fs = util.fs(); expect(error).to.exist;
var name = 'test'; expect(error.code).to.equal('EBADF');
expect(value).not.to.exist;
completeGet = true;
maybeDone();
});
fs.writeFile('/testfile', '', function (error) { fs.fremovexattr(1, 'test', function(error, value) {
if (error) throw error; expect(error).to.exist;
expect(error.code).to.equal('EBADF');
completeRemove = true;
maybeDone();
});
});
fs.setxattr('/testfile', name, 'somevalue', function(error) { it('should set and get an extended attribute of a path', function(done) {
var fs = util.fs();
var name = 'test';
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', name, 'somevalue', function(error) {
expect(error).not.to.exist;
fs.getxattr('/testfile', name, function(error, value) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(value).to.equal('somevalue');
fs.getxattr('/testfile', name, function(error, value) { done();
expect(error).not.to.exist;
expect(value).to.equal('somevalue');
done();
});
}); });
}); });
}); });
});
it('should error when attempting to remove a non-existing attribute', function(done) { it('should error when attempting to remove a non-existing attribute', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', '', function (error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', '', function (error) { fs.removexattr('/testfile', 'testenoattr', function (error) {
if (error) throw error; expect(error).to.exist;
expect(error.code).to.equal('ENOATTR');
fs.removexattr('/testfile', 'testenoattr', function (error) { done();
expect(error).to.exist;
expect(error.code).to.equal('ENOATTR');
done();
});
}); });
}); });
}); });
});
it('should set and get an empty string as a value', function(done) { it('should set and get an empty string as a value', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function (error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', '', function (error) { fs.setxattr('/testfile', 'test', '', function (error) {
if(error) throw error; if(error) throw error;
fs.getxattr('/testfile', 'test', function (error, value) { fs.getxattr('/testfile', 'test', function (error, value) {
expect(error).not.to.exist;
expect(value).to.equal('');
done();
});
});
});
});
it('should set and get an extended attribute for a valid file descriptor', function(done) {
var fs = util.fs();
fs.open('/testfile', 'w', function (error, ofd) {
if (error) throw error;
fs.fsetxattr(ofd, 'test', 'value', function (error) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(value).to.equal('');
fs.fgetxattr(ofd, 'test', function (error, value) { done();
expect(error).not.to.exist;
expect(value).to.equal('value');
done();
});
}); });
}); });
}); });
});
it('should set and get an object to an extended attribute', function(done) { it('should set and get an extended attribute for a valid file descriptor', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.open('/testfile', 'w', function (error, ofd) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', { key1: 'test', key2: 'value', key3: 87 }, function (error) { fs.fsetxattr(ofd, 'test', 'value', function (error) {
if(error) throw error; expect(error).not.to.exist;
fs.getxattr('/testfile', 'test', function (error, value) { fs.fgetxattr(ofd, 'test', function (error, value) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(value).to.deep.equal({ key1: 'test', key2: 'value', key3: 87 }); expect(value).to.equal('value');
done(); done();
});
}); });
}); });
}); });
});
it('should update/overwrite an existing extended attribute', function(done) { it('should set and get an object to an extended attribute', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', { key1: 'test', key2: 'value', key3: 87 }, function (error) {
if(error) throw error;
fs.getxattr('/testfile', 'test', function (error, value) {
expect(error).not.to.exist;
expect(value).to.deep.equal({ key1: 'test', key2: 'value', key3: 87 });
done();
});
});
});
});
it('should update/overwrite an existing extended attribute', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', 'value', function (error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', 'value', function (error) { fs.getxattr('/testfile', 'test', function (error, value) {
if (error) throw error; if (error) throw error;
expect(value).to.equal('value');
fs.getxattr('/testfile', 'test', function (error, value) { fs.setxattr('/testfile', 'test', { o: 'object', t: 'test' }, function (error) {
if (error) throw error; if (error) throw error;
expect(value).to.equal('value');
fs.setxattr('/testfile', 'test', { o: 'object', t: 'test' }, function (error) { fs.getxattr('/testfile', 'test', function (error, value) {
if (error) throw error; if (error) throw error;
expect(value).to.deep.equal({ o: 'object', t: 'test' });
fs.getxattr('/testfile', 'test', function (error, value) { fs.setxattr('/testfile', 'test', 100, 'REPLACE', function (error) {
if (error) throw error; if (error) throw error;
expect(value).to.deep.equal({ o: 'object', t: 'test' });
fs.setxattr('/testfile', 'test', 100, 'REPLACE', function (error) { fs.getxattr('/testfile', 'test', function (error, value) {
if (error) throw error; expect(value).to.equal(100);
done();
fs.getxattr('/testfile', 'test', function (error, value) {
expect(value).to.equal(100);
done();
});
}); });
}); });
}); });
}); });
}) });
}); })
}); });
});
it('should set multiple extended attributes for a path', function(done) { it('should set multiple extended attributes for a path', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.writeFile('/testfile', '', function (error) { fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', 89, function (error) {
if (error) throw error; if (error) throw error;
fs.setxattr('/testfile', 'test', 89, function (error) { fs.setxattr('/testfile', 'other', 'attribute', function (error) {
if (error) throw error; if(error) throw error;
fs.setxattr('/testfile', 'other', 'attribute', function (error) { fs.getxattr('/testfile', 'test', function (error, value) {
if(error) throw error; if(error) throw error;
expect(value).to.equal(89);
fs.getxattr('/testfile', 'test', function (error, value) { fs.getxattr('/testfile', 'other', function (error, value) {
if(error) throw error; expect(error).not.to.exist;
expect(value).to.equal(89); expect(value).to.equal('attribute');
done();
fs.getxattr('/testfile', 'other', function (error, value) {
expect(error).not.to.exist;
expect(value).to.equal('attribute');
done();
});
}); });
}); });
}); });
}); });
}); });
});
it('should remove an extended attribute from a path', function(done) {
var fs = util.fs(); it('should remove an extended attribute from a path', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error; fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', 'somevalue', function (error) {
if (error) throw error; fs.setxattr('/testfile', 'test', 'somevalue', function (error) {
if (error) throw error;
fs.getxattr('/testfile', 'test', function (error, value) {
if (error) throw error; fs.getxattr('/testfile', 'test', function (error, value) {
expect(value).to.equal('somevalue'); if (error) throw error;
expect(value).to.equal('somevalue');
fs.removexattr('/testfile', 'test', function (error) {
if (error) throw error; fs.removexattr('/testfile', 'test', function (error) {
if (error) throw error;
fs.getxattr('/testfile', 'test', function (error) {
expect(error).to.exist; fs.getxattr('/testfile', 'test', function (error) {
expect(error.code).to.equal('ENOATTR'); expect(error).to.exist;
done(); expect(error.code).to.equal('ENOATTR');
}); done();
}); });
}); });
}); });
}); });
}); });
});
it('should remove an extended attribute from a valid file descriptor', function(done) {
var fs = util.fs(); it('should remove an extended attribute from a valid file descriptor', function(done) {
var fs = util.fs();
fs.open('/testfile', 'w', function (error, ofd) {
if (error) throw error; fs.open('/testfile', 'w', function (error, ofd) {
if (error) throw error;
fs.fsetxattr(ofd, 'test', 'somevalue', function (error) {
if (error) throw error; fs.fsetxattr(ofd, 'test', 'somevalue', function (error) {
if (error) throw error;
fs.fgetxattr(ofd, 'test', function (error, value) {
if (error) throw error; fs.fgetxattr(ofd, 'test', function (error, value) {
expect(value).to.equal('somevalue'); if (error) throw error;
expect(value).to.equal('somevalue');
fs.fremovexattr(ofd, 'test', function (error) {
if (error) throw error; fs.fremovexattr(ofd, 'test', function (error) {
if (error) throw error;
fs.fgetxattr(ofd, 'test', function (error) {
expect(error).to.exist; fs.fgetxattr(ofd, 'test', function (error) {
expect(error.code).to.equal('ENOATTR'); expect(error).to.exist;
done(); expect(error.code).to.equal('ENOATTR');
}); done();
}); });
}); });
}); });
}); });
}); });
});
it('should allow setting with a null value', function(done) {
var fs = util.fs(); it('should allow setting with a null value', function(done) {
var fs = util.fs();
fs.writeFile('/testfile', '', function (error) {
if (error) throw error; fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
fs.setxattr('/testfile', 'test', null, function (error) {
if (error) throw error; fs.setxattr('/testfile', 'test', null, function (error) {
if (error) throw error;
fs.getxattr('/testfile', 'test', function (error, value) {
expect(error).not.to.exist; fs.getxattr('/testfile', 'test', function (error, value) {
expect(value).to.be.null; expect(error).not.to.exist;
done(); expect(value).to.be.null;
}); done();
}); });
}); });
}); });
}); });
}); });

View File

@ -0,0 +1,59 @@
var network = require('../../../src/network.js');
var expect = require('chai').expect;
describe('Network module', function() {
var uri;
if (typeof XMLHttpRequest === 'undefined') {
// Node context
uri = {
valid: 'http://localhost:1234/package.json',
invalid: 'booyah!',
notFound: 'http://localhost:1234/this-isnt-real'
}
} else {
// Browser context
uri = {
valid: '../package.json',
invalid: 'asdf://booyah!',
notFound: 'this-isnt-real'
};
}
it('should get an error when a non-existent path is specified', function(done) {
network.download(uri.notFound, function(error, data) {
expect(error).to.exist;
expect(error.code).to.eql(404);
expect(data).to.be.eql(null);
done();
});
});
if (typeof XMLHttpRequest === 'undefined') {
it('in nodejs, should get an error when an invalid URI is specified', function(done) {
network.download(uri.invalid, function(error, data) {
expect(error).to.exist;
expect(error.code).to.eql(null);
expect(error.message).to.exist;
expect(data).to.be.eql(null);
done();
});
});
} else {
it('in a browser, should throw an error when an invalid URI is specified', function(done) {
expect(function(){
network.download(uri.invalid, function() {});
}).to.throwError;
done();
});
}
it('should download a resource from the server', function(done) {
network.download(uri.valid, function(error, data) {
expect(error).not.to.exist;
expect(data).to.exist;
expect(data).to.have.length.above(0);
done();
});
});
});

View File

@ -0,0 +1,13 @@
define(["Filer", "util"], function(Filer, util) {
describe('Nodejs compatability', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('module should be requireable', function() {
expect(function() {
var Filer = require('../../dist/filer_node.js');
}).to.not.throwError;
});
});
});

View File

@ -1,41 +1,40 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../../..');
var util = require('../../../lib/test-utils.js');
var expect = require('chai').expect;
describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-mkdir.js", function() { describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-mkdir.js", function() {
beforeEach(util.setup);
afterEach(util.cleanup);
beforeEach(util.setup); // Based on test1 from https://github.com/joyent/node/blob/master/test/simple/test-fs-mkdir.js
afterEach(util.cleanup); it('should create a dir without a mode arg', function(done) {
var pathname = '/test1';
var fs = util.fs();
// Based on test1 from https://github.com/joyent/node/blob/master/test/simple/test-fs-mkdir.js fs.mkdir(pathname, function(error) {
it('should create a dir without a mode arg', function(done) { if(error) throw error;
var pathname = '/test1'; fs.stat(pathname, function(error, result) {
var fs = util.fs(); expect(error).not.to.exist;
expect(result).to.exist;
fs.mkdir(pathname, function(error) { expect(result.type).to.equal('DIRECTORY');
if(error) throw error; done();
fs.stat(pathname, function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('DIRECTORY');
done();
});
});
});
// Based on test2 https://github.com/joyent/node/blob/master/test/simple/test-fs-mkdir.js
it('should create a dir with a mode arg', function(done) {
var pathname = '/test2';
var fs = util.fs();
fs.mkdir(pathname, 511 /*=0777*/, function(error) {
if(error) throw error;
fs.stat(pathname, function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('DIRECTORY');
done();
});
}); });
}); });
}); });
// Based on test2 https://github.com/joyent/node/blob/master/test/simple/test-fs-mkdir.js
it('should create a dir with a mode arg', function(done) {
var pathname = '/test2';
var fs = util.fs();
fs.mkdir(pathname, 511 /*=0777*/, function(error) {
if(error) throw error;
fs.stat(pathname, function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result.type).to.equal('DIRECTORY');
done();
});
});
});
}); });

View File

@ -1,62 +1,62 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../../..');
var util = require('../../../lib/test-utils.js');
var expect = require('chai').expect;
describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-null-bytes.js", function() { describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-null-bytes.js", function() {
beforeEach(util.setup);
afterEach(util.cleanup);
beforeEach(util.setup); it('should reject paths with null bytes in them', function(done) {
afterEach(util.cleanup); var checks = [];
var fnCount = 0;
var fnTotal = 16;
var expected = "Path must be a string without null bytes.";
var fs = util.fs();
it('should reject paths with null bytes in them', function(done) { // Make sure function fails with null path error in callback.
var checks = []; function check(fn) {
var fnCount = 0; var args = Array.prototype.slice.call(arguments, 1);
var fnTotal = 16; args = args.concat(function(err) {
var expected = "Path must be a string without null bytes."; checks.push(function(){
var fs = util.fs(); expect(err).to.exist;
expect(err.message).to.equal(expected);
// Make sure function fails with null path error in callback.
function check(fn) {
var args = Array.prototype.slice.call(arguments, 1);
args = args.concat(function(err) {
checks.push(function(){
expect(err).to.exist;
expect(err.message).to.equal(expected);
});
fnCount++;
if(fnCount === fnTotal) {
done();
}
}); });
fnCount++;
fn.apply(fs, args); if(fnCount === fnTotal) {
} done();
}
check(fs.link, '/foo\u0000bar', 'foobar');
check(fs.link, '/foobar', 'foo\u0000bar');
check(fs.lstat, '/foo\u0000bar');
check(fs.mkdir, '/foo\u0000bar', '0755');
check(fs.open, '/foo\u0000bar', 'r');
check(fs.readFile, '/foo\u0000bar');
check(fs.readdir, '/foo\u0000bar');
check(fs.readlink, '/foo\u0000bar');
check(fs.rename, '/foo\u0000bar', 'foobar');
check(fs.rename, '/foobar', 'foo\u0000bar');
check(fs.rmdir, '/foo\u0000bar');
check(fs.stat, '/foo\u0000bar');
check(fs.symlink, '/foo\u0000bar', 'foobar');
check(fs.symlink, '/foobar', 'foo\u0000bar');
check(fs.unlink, '/foo\u0000bar');
check(fs.writeFile, '/foo\u0000bar');
check(fs.appendFile, '/foo\u0000bar');
check(fs.truncate, '/foo\u0000bar');
check(fs.utimes, '/foo\u0000bar', 0, 0);
// TODO - need to be implemented still...
// check(fs.realpath, '/foo\u0000bar');
// check(fs.chmod, '/foo\u0000bar', '0644');
// check(fs.chown, '/foo\u0000bar', 12, 34);
// check(fs.realpath, '/foo\u0000bar');
checks.forEach(function(fn){
fn();
}); });
fn.apply(fs, args);
}
check(fs.link, '/foo\u0000bar', 'foobar');
check(fs.link, '/foobar', 'foo\u0000bar');
check(fs.lstat, '/foo\u0000bar');
check(fs.mkdir, '/foo\u0000bar', '0755');
check(fs.open, '/foo\u0000bar', 'r');
check(fs.readFile, '/foo\u0000bar');
check(fs.readdir, '/foo\u0000bar');
check(fs.readlink, '/foo\u0000bar');
check(fs.rename, '/foo\u0000bar', 'foobar');
check(fs.rename, '/foobar', 'foo\u0000bar');
check(fs.rmdir, '/foo\u0000bar');
check(fs.stat, '/foo\u0000bar');
check(fs.symlink, '/foo\u0000bar', 'foobar');
check(fs.symlink, '/foobar', 'foo\u0000bar');
check(fs.unlink, '/foo\u0000bar');
check(fs.writeFile, '/foo\u0000bar');
check(fs.appendFile, '/foo\u0000bar');
check(fs.truncate, '/foo\u0000bar');
check(fs.utimes, '/foo\u0000bar', 0, 0);
// TODO - need to be implemented still...
// check(fs.realpath, '/foo\u0000bar');
// check(fs.chmod, '/foo\u0000bar', '0644');
// check(fs.chown, '/foo\u0000bar', 12, 34);
// check(fs.realpath, '/foo\u0000bar');
checks.forEach(function(fn){
fn();
}); });
}); });
}); });

View File

@ -1,38 +1,36 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../../..');
var util = require('../../../lib/test-utils.js');
var expect = require('chai').expect;
/** /**
* NOTE: unlike node.js, which either doesn't give filenames (e.g., in case of * NOTE: unlike node.js, which either doesn't give filenames (e.g., in case of
* fd vs. path) for events, or gives only a portion thereof (e.g., basname), * fd vs. path) for events, or gives only a portion thereof (e.g., basname),
* we give full, abs paths always. * we give full, abs paths always.
*/ */
describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-watch-recursive.js", function() {
beforeEach(util.setup);
afterEach(util.cleanup);
describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-watch-recursive.js", function() { it('should get change event for writeFile() under a recursive watched dir', function(done) {
var fs = util.fs();
beforeEach(util.setup); fs.mkdir('/test', function(error) {
afterEach(util.cleanup); if(error) throw error;
it('should get change event for writeFile() under a recursive watched dir', function(done) { fs.mkdir('/test/subdir', function(error) {
var fs = util.fs();
fs.mkdir('/test', function(error) {
if(error) throw error; if(error) throw error;
fs.mkdir('/test/subdir', function(error) { var watcher = fs.watch('/test', {recursive: true});
if(error) throw error; watcher.on('change', function(event, filename) {
expect(event).to.equal('change');
var watcher = fs.watch('/test', {recursive: true}); // Expect to see that a new file was created in /test/subdir
watcher.on('change', function(event, filename) { expect(filename).to.equal('/test/subdir');
expect(event).to.equal('change'); watcher.close();
// Expect to see that a new file was created in /test/subdir done();
expect(filename).to.equal('/test/subdir');
watcher.close();
done();
});
fs.writeFile('/test/subdir/watch.txt', 'world');
}); });
fs.writeFile('/test/subdir/watch.txt', 'world');
}); });
}); });
}); });
}); });

View File

@ -1,73 +1,72 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../../..');
var util = require('../../../lib/test-utils.js');
var expect = require('chai').expect;
/** /**
* NOTE: unlike node.js, which either doesn't give filenames (e.g., in case of * NOTE: unlike node.js, which either doesn't give filenames (e.g., in case of
* fd vs. path) for events, or gives only a portion thereof (e.g., basname), * fd vs. path) for events, or gives only a portion thereof (e.g., basname),
* we give full, abs paths always. * we give full, abs paths always.
*/ */
var filenameOne = '/watch.txt';
var filenameTwo = '/hasOwnProperty';
var filenameOne = '/watch.txt'; describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-watch.js", function() {
var filenameTwo = '/hasOwnProperty'; beforeEach(util.setup);
afterEach(util.cleanup);
describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/test-fs-watch.js", function() { it('should get change event for writeFile() using FSWatcher object', function(done) {
var fs = util.fs();
var changes = 0;
beforeEach(util.setup); var watcher = fs.watch(filenameOne);
afterEach(util.cleanup); watcher.on('change', function(event, filename) {
expect(event).to.equal('change');
expect(filename).to.equal(filenameOne);
it('should get change event for writeFile() using FSWatcher object', function(done) { // Make sure only one change event comes in (i.e., close() works)
var fs = util.fs(); changes++;
var changes = 0; watcher.close();
var watcher = fs.watch(filenameOne); fs.writeFile(filenameOne, 'hello again', function(error) {
watcher.on('change', function(event, filename) { expect(changes).to.equal(1);
expect(event).to.equal('change'); done();
expect(filename).to.equal(filenameOne);
// Make sure only one change event comes in (i.e., close() works)
changes++;
watcher.close();
fs.writeFile(filenameOne, 'hello again', function(error) {
expect(changes).to.equal(1);
done();
});
}); });
fs.writeFile(filenameOne, 'hello');
}); });
it('should get change event for writeFile() using fs.watch() only', function(done) { fs.writeFile(filenameOne, 'hello');
var fs = util.fs(); });
var changes = 0;
var watcher = fs.watch(filenameTwo, function(event, filename) { it('should get change event for writeFile() using fs.watch() only', function(done) {
var fs = util.fs();
var changes = 0;
var watcher = fs.watch(filenameTwo, function(event, filename) {
expect(event).to.equal('change');
expect(filename).to.equal(filenameTwo);
watcher.close();
done();
});
fs.writeFile(filenameTwo, 'pardner');
});
it('should allow watches on dirs', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error;
var watcher = fs.watch('/tmp', function(event, filename) {
// TODO: node thinks this should be 'rename', need to add rename along with change.
expect(event).to.equal('change'); expect(event).to.equal('change');
expect(filename).to.equal(filenameTwo); expect(filename).to.equal('/tmp');
watcher.close(); watcher.close();
done(); done();
}); });
fs.writeFile(filenameTwo, 'pardner'); fs.open('/tmp/newfile.txt', 'w', function(error, fd) {
});
it('should allow watches on dirs', function(done) {
var fs = util.fs();
fs.mkdir('/tmp', function(error) {
if(error) throw error; if(error) throw error;
fs.close(fd);
var watcher = fs.watch('/tmp', function(event, filename) {
// TODO: node thinks this should be 'rename', need to add rename along with change.
expect(event).to.equal('change');
expect(filename).to.equal('/tmp');
watcher.close();
done();
});
fs.open('/tmp/newfile.txt', 'w', function(error, fd) {
if(error) throw error;
fs.close(fd);
});
}); });
}); });
}); });

View File

@ -1,21 +1,45 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../..');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('path resolution', function() { describe('path resolution', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should follow a symbolic link to the root directory', function(done) { it('should follow a symbolic link to the root directory', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.symlink('/', '/mydirectorylink', function(error) { fs.symlink('/', '/mydirectorylink', function(error) {
if(error) throw error;
fs.stat('/', function(error, result) {
if(error) throw error; if(error) throw error;
fs.stat('/', function(error, result) { expect(result['node']).to.exist;
var _node = result['node'];
fs.stat('/mydirectorylink', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result['node']).to.equal(_node);
done();
});
});
});
});
it('should follow a symbolic link to a directory', function(done) {
var fs = util.fs();
fs.mkdir('/mydir', function(error) {
fs.symlink('/mydir', '/mydirectorylink', function(error) {
if(error) throw error;
fs.stat('/mydir', function(error, result) {
if(error) throw error; if(error) throw error;
expect(result['node']).to.exist; expect(result['node']).to.exist;
var _node = result['node']; var _node = result['node'];
fs.stat('/mydirectorylink', function(error, result) { fs.stat('/mydirectorylink', function(error, result) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(result).to.exist; expect(result).to.exist;
@ -25,20 +49,25 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
});
it('should follow a symbolic link to a directory', function(done) { it('should follow a symbolic link to a file', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.mkdir('/mydir', function(error) { fs.open('/myfile', 'w', function(error, result) {
fs.symlink('/mydir', '/mydirectorylink', function(error) { if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error; if(error) throw error;
fs.stat('/mydir', function(error, result) { expect(result['node']).to.exist;
var _node = result['node'];
fs.symlink('/myfile', '/myfilelink', function(error) {
if(error) throw error; if(error) throw error;
expect(result['node']).to.exist; fs.stat('/myfilelink', function(error, result) {
var _node = result['node'];
fs.stat('/mydirectorylink', function(error, result) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(result).to.exist; expect(result).to.exist;
expect(result['node']).to.equal(_node); expect(result['node']).to.equal(_node);
@ -48,24 +77,27 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
});
it('should follow a symbolic link to a file', function(done) { it('should follow multiple symbolic links to a file', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) { fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error; if(error) throw error;
var fd = result; fs.stat('/myfile', function(error, result) {
fs.close(fd, function(error) {
if(error) throw error; if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result['node']).to.exist; expect(result['node']).to.exist;
var _node = result['node']; var _node = result['node'];
fs.symlink('/myfile', '/myfilelink', function(error) { fs.symlink('/myfile', '/myfilelink1', function(error) {
if(error) throw error;
fs.symlink('/myfilelink1', '/myfilelink2', function(error) {
if(error) throw error; if(error) throw error;
fs.stat('/myfilelink', function(error, result) { fs.stat('/myfilelink2', function(error, result) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(result).to.exist; expect(result).to.exist;
expect(result['node']).to.equal(_node); expect(result['node']).to.equal(_node);
@ -76,151 +108,119 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
it('should follow multiple symbolic links to a file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
expect(result['node']).to.exist;
var _node = result['node'];
fs.symlink('/myfile', '/myfilelink1', function(error) {
if(error) throw error;
fs.symlink('/myfilelink1', '/myfilelink2', function(error) {
if(error) throw error;
fs.stat('/myfilelink2', function(error, result) {
expect(error).not.to.exist;
expect(result).to.exist;
expect(result['node']).to.equal(_node);
done();
});
});
});
});
});
});
});
it('should error if symbolic link leads to itself', function(done) {
var fs = util.fs();
fs.symlink('/mylink1', '/mylink2', function(error) {
if(error) throw error;
fs.symlink('/mylink2', '/mylink1', function(error) {
if(error) throw error;
fs.stat('/myfilelink1', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(result).not.to.exist;
done();
});
});
});
});
it('should error if it follows more than 10 symbolic links', function(done) {
var fs = util.fs();
var nlinks = 11;
function createSymlinkChain(n, callback) {
if(n > nlinks) {
return callback();
}
fs.symlink('/myfile' + (n-1), '/myfile' + n, createSymlinkChain.bind(this, n+1, callback));
}
fs.open('/myfile0', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile0', function(error, result) {
if(error) throw error;
createSymlinkChain(1, function() {
fs.stat('/myfile11', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal('ELOOP');
expect(result).not.to.exist;
done();
});
});
});
});
});
});
it('should follow a symbolic link in the path to a file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
var _node = result['node'];
fs.symlink('/', '/mydirlink', function(error) {
if(error) throw error;
fs.stat('/mydirlink/myfile', function(error, result) {
expect(result).to.exist;
expect(error).not.to.exist;
expect(_node).to.exist;
expect(result['node']).to.equal(_node);
done();
});
});
});
});
});
});
it('should error if a symbolic link in the path to a file is itself a file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
fs.open('/myfile2', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.symlink('/myfile2', '/mynotdirlink', function(error) {
if(error) throw error;
fs.stat('/mynotdirlink/myfile', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOTDIR");
expect(result).not.to.exist;
done();
});
});
});
});
});
});
});
});
}); });
it('should error if symbolic link leads to itself', function(done) {
var fs = util.fs();
fs.symlink('/mylink1', '/mylink2', function(error) {
if(error) throw error;
fs.symlink('/mylink2', '/mylink1', function(error) {
if(error) throw error;
fs.stat('/myfilelink1', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOENT");
expect(result).not.to.exist;
done();
});
});
});
});
it('should error if it follows more than 10 symbolic links', function(done) {
var fs = util.fs();
var nlinks = 11;
function createSymlinkChain(n, callback) {
if(n > nlinks) {
return callback();
}
fs.symlink('/myfile' + (n-1), '/myfile' + n, createSymlinkChain.bind(this, n+1, callback));
}
fs.open('/myfile0', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile0', function(error, result) {
if(error) throw error;
createSymlinkChain(1, function() {
fs.stat('/myfile11', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal('ELOOP');
expect(result).not.to.exist;
done();
});
});
});
});
});
});
it('should follow a symbolic link in the path to a file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
var _node = result['node'];
fs.symlink('/', '/mydirlink', function(error) {
if(error) throw error;
fs.stat('/mydirlink/myfile', function(error, result) {
expect(result).to.exist;
expect(error).not.to.exist;
expect(_node).to.exist;
expect(result['node']).to.equal(_node);
done();
});
});
});
});
});
});
it('should error if a symbolic link in the path to a file is itself a file', function(done) {
var fs = util.fs();
fs.open('/myfile', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.stat('/myfile', function(error, result) {
if(error) throw error;
fs.open('/myfile2', 'w', function(error, result) {
if(error) throw error;
var fd = result;
fs.close(fd, function(error) {
if(error) throw error;
fs.symlink('/myfile2', '/mynotdirlink', function(error) {
if(error) throw error;
fs.stat('/mynotdirlink/myfile', function(error, result) {
expect(error).to.exist;
expect(error.code).to.equal("ENOTDIR");
expect(result).not.to.exist;
done();
});
});
});
});
});
});
});
});
}); });

View File

@ -1,15 +1,10 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
if(!Filer.FileSystem.providers.IndexedDB.isSupported()) { var expect = require('chai').expect;
console.log("Skipping Filer.FileSystem.providers.IndexedDB tests, since IndexedDB isn't supported.");
return;
}
if(navigator.userAgent.indexOf('PhantomJS') > -1) {
console.log("Skipping Filer.FileSystem.providers.IndexedDB tests, since PhantomJS doesn't support it.");
return;
}
if(!Filer.FileSystem.providers.IndexedDB.isSupported()) {
console.log("Skipping Filer.FileSystem.providers.IndexedDB tests, since IndexedDB isn't supported.");
} else {
describe("Filer.FileSystem.providers.IndexedDB", function() { describe("Filer.FileSystem.providers.IndexedDB", function() {
it("is supported -- if it isn't, none of these tests can run.", function() { it("is supported -- if it isn't, none of these tests can run.", function() {
expect(Filer.FileSystem.providers.IndexedDB.isSupported()).to.be.true; expect(Filer.FileSystem.providers.IndexedDB.isSupported()).to.be.true;
@ -150,4 +145,4 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); }

View File

@ -1,142 +1,43 @@
define(["Filer"], function(Filer) { var Filer = require('../../..');
var expect = require('chai').expect;
describe("Filer.FileSystem.providers.Memory", function() { describe("Filer.FileSystem.providers.Memory", function() {
it("is supported -- if it isn't, none of these tests can run.", function() { it("is supported -- if it isn't, none of these tests can run.", function() {
expect(Filer.FileSystem.providers.Memory.isSupported()).to.be.true; expect(Filer.FileSystem.providers.Memory.isSupported()).to.be.true;
}); });
it("has open, getReadOnlyContext, and getReadWriteContext instance methods", function() { it("has open, getReadOnlyContext, and getReadWriteContext instance methods", function() {
var memoryProvider = new Filer.FileSystem.providers.Memory(); var memoryProvider = new Filer.FileSystem.providers.Memory();
expect(memoryProvider.open).to.be.a('function'); expect(memoryProvider.open).to.be.a('function');
expect(memoryProvider.getReadOnlyContext).to.be.a('function'); expect(memoryProvider.getReadOnlyContext).to.be.a('function');
expect(memoryProvider.getReadWriteContext).to.be.a('function'); expect(memoryProvider.getReadWriteContext).to.be.a('function');
}); });
describe("Memory provider DBs are sharable", function() { describe("Memory provider DBs are sharable", function() {
it("should share a single memory db when name is the same", function(done) { it("should share a single memory db when name is the same", function(done) {
var provider1; var provider1;
var provider2; var provider2;
var provider3; var provider3;
var name1 = 'memory-db'; var name1 = 'memory-db';
var name2 = 'memory-db2'; var name2 = 'memory-db2';
provider1 = new Filer.FileSystem.providers.Memory(name1); provider1 = new Filer.FileSystem.providers.Memory(name1);
provider1.open(function(error, firstAccess) { provider1.open(function(error, firstAccess) {
expect(error).not.to.exist;
expect(firstAccess).to.be.true;
provider2 = new Filer.FileSystem.providers.Memory(name1);
provider2.open(function(error, firstAccess) {
expect(error).not.to.exist;
expect(firstAccess).to.be.false;
expect(provider1.db).to.equal(provider2.db);
provider3 = new Filer.FileSystem.providers.Memory(name2);
provider3.open(function(error, firstAccess) {
expect(error).not.to.exist; expect(error).not.to.exist;
expect(firstAccess).to.be.true; expect(firstAccess).to.be.true;
expect(provider3.db).not.to.equal(provider2.db);
provider2 = new Filer.FileSystem.providers.Memory(name1);
provider2.open(function(error, firstAccess) {
expect(error).not.to.exist;
expect(firstAccess).to.be.false;
expect(provider1.db).to.equal(provider2.db);
provider3 = new Filer.FileSystem.providers.Memory(name2);
provider3.open(function(error, firstAccess) {
expect(error).not.to.exist;
expect(firstAccess).to.be.true;
expect(provider3.db).not.to.equal(provider2.db);
done();
});
});
});
});
});
});
describe("open an Memory provider", function() {
it("should open a new Memory database", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
expect(error).not.to.exist;
expect(firstAccess).to.be.true;
done();
});
});
});
describe("Read/Write operations on an Memory provider", function() {
it("should allow put() and get()", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key", "value", function(error, result) {
if(error) throw error;
context.get("key", function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal("value");
done();
});
});
});
});
it("should allow delete()", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key", "value", function(error, result) {
if(error) throw error;
context.delete("key", function(error, result) {
if(error) throw error;
context.get("key", function(error, result) {
expect(error).not.to.exist;
expect(result).not.to.exist;
done();
});
});
});
});
});
it("should allow clear()", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key1", "value1", function(error, result) {
if(error) throw error;
context.put("key2", "value2", function(error, result) {
if(error) throw error;
context.clear(function(err) {
if(error) throw error;
context.get("key1", function(error, result) {
if(error) throw error;
expect(result).not.to.exist;
context.get("key2", function(error, result) {
if(error) throw error;
expect(result).not.to.exist;
done();
});
});
});
});
});
});
});
it("should fail when trying to write on ReadOnlyContext", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadOnlyContext();
context.put("key1", "value1", function(error, result) {
expect(error).to.exist;
expect(result).not.to.exist;
done(); done();
}); });
}); });
@ -144,4 +45,101 @@ define(["Filer"], function(Filer) {
}); });
}); });
describe("open an Memory provider", function() {
it("should open a new Memory database", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
expect(error).not.to.exist;
expect(firstAccess).to.be.true;
done();
});
});
});
describe("Read/Write operations on an Memory provider", function() {
it("should allow put() and get()", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key", "value", function(error, result) {
if(error) throw error;
context.get("key", function(error, result) {
expect(error).not.to.exist;
expect(result).to.equal("value");
done();
});
});
});
});
it("should allow delete()", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key", "value", function(error, result) {
if(error) throw error;
context.delete("key", function(error, result) {
if(error) throw error;
context.get("key", function(error, result) {
expect(error).not.to.exist;
expect(result).not.to.exist;
done();
});
});
});
});
});
it("should allow clear()", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadWriteContext();
context.put("key1", "value1", function(error, result) {
if(error) throw error;
context.put("key2", "value2", function(error, result) {
if(error) throw error;
context.clear(function(err) {
if(error) throw error;
context.get("key1", function(error, result) {
if(error) throw error;
expect(result).not.to.exist;
context.get("key2", function(error, result) {
if(error) throw error;
expect(result).not.to.exist;
done();
});
});
});
});
});
});
});
it("should fail when trying to write on ReadOnlyContext", function(done) {
var provider = new Filer.FileSystem.providers.Memory();
provider.open(function(error, firstAccess) {
if(error) throw error;
var context = provider.getReadOnlyContext();
context.put("key1", "value1", function(error, result) {
expect(error).to.exist;
expect(result).not.to.exist;
done();
});
});
});
});
}); });

View File

@ -1,27 +1,28 @@
define(["Filer"], function(Filer) { var Filer = require('../../..');
describe("Filer.FileSystem.providers", function() { var expect = require('chai').expect;
it("is defined", function() {
expect(Filer.FileSystem.providers).to.exist;
});
it("has IndexedDB constructor", function() { describe("Filer.FileSystem.providers", function() {
expect(Filer.FileSystem.providers.IndexedDB).to.be.a('function'); it("is defined", function() {
}); expect(Filer.FileSystem.providers).to.exist;
});
it("has WebSQL constructor", function() { it("has IndexedDB constructor", function() {
expect(Filer.FileSystem.providers.WebSQL).to.be.a('function'); expect(Filer.FileSystem.providers.IndexedDB).to.be.a('function');
}); });
it("has Memory constructor", function() { it("has WebSQL constructor", function() {
expect(Filer.FileSystem.providers.Memory).to.be.a('function'); expect(Filer.FileSystem.providers.WebSQL).to.be.a('function');
}); });
it("has a Default constructor", function() { it("has Memory constructor", function() {
expect(Filer.FileSystem.providers.Default).to.be.a('function'); expect(Filer.FileSystem.providers.Memory).to.be.a('function');
}); });
it("has Fallback constructor", function() { it("has a Default constructor", function() {
expect(Filer.FileSystem.providers.Fallback).to.be.a('function'); expect(Filer.FileSystem.providers.Default).to.be.a('function');
}); });
it("has Fallback constructor", function() {
expect(Filer.FileSystem.providers.Fallback).to.be.a('function');
}); });
}); });

View File

@ -1,15 +1,10 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
if(!Filer.FileSystem.providers.WebSQL.isSupported()) { var expect = require('chai').expect;
console.log("Skipping Filer.FileSystem.providers.WebSQL tests, since WebSQL isn't supported.");
return;
}
if(navigator.userAgent.indexOf('PhantomJS') > -1) {
console.log("Skipping Filer.FileSystem.providers.WebSQL tests, since PhantomJS doesn't support it.");
return;
}
if(!Filer.FileSystem.providers.WebSQL.isSupported()) {
console.log("Skipping Filer.FileSystem.providers.WebSQL tests, since WebSQL isn't supported.");
} else {
describe("Filer.FileSystem.providers.WebSQL", function() { describe("Filer.FileSystem.providers.WebSQL", function() {
it("is supported -- if it isn't, none of these tests can run.", function() { it("is supported -- if it isn't, none of these tests can run.", function() {
expect(Filer.FileSystem.providers.WebSQL.isSupported()).to.be.true; expect(Filer.FileSystem.providers.WebSQL.isSupported()).to.be.true;
@ -145,4 +140,4 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); }

View File

@ -1,84 +1,84 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.cat', function() { describe('FileSystemShell.cat', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.cat).to.be.a('function'); expect(shell.cat).to.be.a('function');
});
it('should fail when files argument is absent', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.cat(null, function(error, data) {
expect(error).to.exist;
expect(error.code).to.equal("EINVAL");
expect(data).not.to.exist;
done();
}); });
});
it('should fail when files argument is absent', function(done) { it('should return the contents of a single file', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var contents = "file contents";
shell.cat(null, function(error, data) { fs.writeFile('/file', contents, function(err) {
expect(error).to.exist; if(err) throw err;
expect(error.code).to.equal("EINVAL");
expect(data).not.to.exist; shell.cat('/file', function(err, data) {
expect(err).not.to.exist;
expect(data).to.equal(contents);
done(); done();
}); });
}); });
});
it('should return the contents of a single file', function(done) { it('should return the contents of multiple files', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var contents = "file contents"; var contents = "file contents";
var contents2 = contents + '\n' + contents;
fs.writeFile('/file', contents, function(err) { fs.writeFile('/file', contents, function(err) {
if(err) throw err;
fs.writeFile('/file2', contents2, function(err) {
if(err) throw err; if(err) throw err;
shell.cat('/file', function(err, data) { shell.cat(['/file', '/file2'], function(err, data) {
expect(err).not.to.exist; expect(err).not.to.exist;
expect(data).to.equal(contents); expect(data).to.equal(contents + '\n' + contents2);
done(); done();
}); });
}); });
}); });
});
it('should return the contents of multiple files', function(done) { it('should fail if any of multiple file paths is invalid', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var contents = "file contents"; var contents = "file contents";
var contents2 = contents + '\n' + contents; var contents2 = contents + '\n' + contents;
fs.writeFile('/file', contents, function(err) { fs.writeFile('/file', contents, function(err) {
if(err) throw err;
fs.writeFile('/file2', contents2, function(err) {
if(err) throw err; if(err) throw err;
fs.writeFile('/file2', contents2, function(err) { shell.cat(['/file', '/nofile'], function(err, data) {
if(err) throw err; expect(err).to.exist;
expect(err.code).to.equal("ENOENT");
shell.cat(['/file', '/file2'], function(err, data) { expect(data).not.to.exist;
expect(err).not.to.exist; done();
expect(data).to.equal(contents + '\n' + contents2);
done();
});
}); });
}); });
}); });
it('should fail if any of multiple file paths is invalid', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var contents = "file contents";
var contents2 = contents + '\n' + contents;
fs.writeFile('/file', contents, function(err) {
if(err) throw err;
fs.writeFile('/file2', contents2, function(err) {
if(err) throw err;
shell.cat(['/file', '/nofile'], function(err, data) {
expect(err).to.exist;
expect(err.code).to.equal("ENOENT");
expect(data).not.to.exist;
done();
});
});
});
});
}); });
}); });

View File

@ -1,123 +1,123 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.cd', function() { describe('FileSystemShell.cd', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.cd).to.be.a('function'); expect(shell.cd).to.be.a('function');
}); });
it('should default to a cwd of /', function() {
var shell = util.shell();
expect(shell.pwd()).to.equal('/');
});
it('should allow changing the path to a valid dir', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
it('should default to a cwd of /', function() {
var shell = util.shell();
expect(shell.pwd()).to.equal('/'); expect(shell.pwd()).to.equal('/');
}); shell.cd('/dir', function(err) {
expect(err).not.to.exist;
it('should allow changing the path to a valid dir', function(done) { expect(shell.pwd()).to.equal('/dir');
var fs = util.fs(); done();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
expect(shell.pwd()).to.equal('/');
shell.cd('/dir', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/dir');
done();
});
}); });
}); });
});
it('should fail when changing the path to an invalid dir', function(done) { it('should fail when changing the path to an invalid dir', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
fs.mkdir('/dir', function(err) { fs.mkdir('/dir', function(err) {
if(err) throw err; if(err) throw err;
expect(shell.pwd()).to.equal('/');
shell.cd('/nodir', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
expect(shell.pwd()).to.equal('/'); expect(shell.pwd()).to.equal('/');
shell.cd('/nodir', function(err) { done();
expect(err).to.exist; });
expect(err.code).to.equal('ENOTDIR'); });
});
it('should fail when changing the path to a file', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.writeFile('/file', 'file', function(err) {
if(err) throw err;
expect(shell.pwd()).to.equal('/');
shell.cd('/file', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
expect(shell.pwd()).to.equal('/');
done();
});
});
});
it('should allow relative paths for a valid dir', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
expect(shell.pwd()).to.equal('/');
shell.cd('./dir', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/dir');
done();
});
});
});
it('should allow .. in paths for a valid dir', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
expect(shell.pwd()).to.equal('/');
shell.cd('./dir', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/dir');
shell.cd('..', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/'); expect(shell.pwd()).to.equal('/');
done(); done();
}); });
}); });
}); });
});
it('should fail when changing the path to a file', function(done) { it('should follow symlinks to dirs', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell();
fs.writeFile('/file', 'file', function(err) { fs.mkdir('/dir', function(error) {
if(err) throw err; if(error) throw error;
expect(shell.pwd()).to.equal('/'); fs.symlink('/dir', '/link', function(error) {
shell.cd('/file', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
expect(shell.pwd()).to.equal('/');
done();
});
});
});
it('should allow relative paths for a valid dir', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
expect(shell.pwd()).to.equal('/');
shell.cd('./dir', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/dir');
done();
});
});
});
it('should allow .. in paths for a valid dir', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
expect(shell.pwd()).to.equal('/');
shell.cd('./dir', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/dir');
shell.cd('..', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/');
done();
});
});
});
});
it('should follow symlinks to dirs', function(done) {
var fs = util.fs();
fs.mkdir('/dir', function(error) {
if(error) throw error; if(error) throw error;
fs.symlink('/dir', '/link', function(error) { var shell = fs.Shell();
if(error) throw error; shell.cd('link', function(error) {
expect(error).not.to.exist;
var shell = fs.Shell(); expect(shell.pwd()).to.equal('/link');
shell.cd('link', function(error) { done();
expect(error).not.to.exist;
expect(shell.pwd()).to.equal('/link');
done();
});
}); });
}); });
}); });
}); });
}); });

View File

@ -1,113 +1,113 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.env', function() { describe('FileSystemShell.env', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should get default env options', function() { it('should get default env options', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.env).to.exist; expect(shell.env).to.exist;
expect(shell.env.get('TMP')).to.equal('/tmp'); expect(shell.env.get('TMP')).to.equal('/tmp');
expect(shell.env.get('PATH')).to.equal(''); expect(shell.env.get('PATH')).to.equal('');
expect(shell.pwd()).to.equal('/'); expect(shell.pwd()).to.equal('/');
});
it('should be able to specify env options', function() {
var options = {
env: {
TMP: '/tempdir',
PATH: '/dir'
}
};
var shell = util.shell(options);
expect(shell.env).to.exist;
expect(shell.env.get('TMP')).to.equal('/tempdir');
expect(shell.env.get('PATH')).to.equal('/dir');
expect(shell.pwd()).to.equal('/');
expect(shell.env.get('FOO')).not.to.exist;
shell.env.set('FOO', 1);
expect(shell.env.get('FOO')).to.equal(1);
});
it('should fail when dirs argument is absent', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.cat(null, function(error, list) {
expect(error).to.exist;
expect(error.code).to.equal("EINVAL");
expect(list).not.to.exist;
done();
}); });
});
it('should give new value for shell.pwd() when cwd changes', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
it('should be able to specify env options', function() {
var options = {
env: {
TMP: '/tempdir',
PATH: '/dir'
}
};
var shell = util.shell(options);
expect(shell.env).to.exist;
expect(shell.env.get('TMP')).to.equal('/tempdir');
expect(shell.env.get('PATH')).to.equal('/dir');
expect(shell.pwd()).to.equal('/'); expect(shell.pwd()).to.equal('/');
shell.cd('/dir', function(err) {
expect(shell.env.get('FOO')).not.to.exist; expect(err).not.to.exist;
shell.env.set('FOO', 1); expect(shell.pwd()).to.equal('/dir');
expect(shell.env.get('FOO')).to.equal(1);
});
it('should fail when dirs argument is absent', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.cat(null, function(error, list) {
expect(error).to.exist;
expect(error.code).to.equal("EINVAL");
expect(list).not.to.exist;
done(); done();
}); });
}); });
});
it('should give new value for shell.pwd() when cwd changes', function(done) { it('should create/return the default tmp dir', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
fs.mkdir('/dir', function(err) { expect(shell.env.get('TMP')).to.equal('/tmp');
if(err) throw err; shell.tempDir(function(err, tmp) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/'); shell.cd(tmp, function(err) {
shell.cd('/dir', function(err) {
expect(err).not.to.exist;
expect(shell.pwd()).to.equal('/dir');
done();
});
});
});
it('should create/return the default tmp dir', function(done) {
var fs = util.fs();
var shell = fs.Shell();
expect(shell.env.get('TMP')).to.equal('/tmp');
shell.tempDir(function(err, tmp) {
expect(err).not.to.exist; expect(err).not.to.exist;
shell.cd(tmp, function(err) { expect(shell.pwd()).to.equal('/tmp');
expect(err).not.to.exist; done();
expect(shell.pwd()).to.equal('/tmp');
done();
});
}); });
}); });
});
it('should create/return the tmp dir specified in env.TMP', function(done) { it('should create/return the tmp dir specified in env.TMP', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell({ var shell = fs.Shell({
env: { env: {
TMP: '/tempdir' TMP: '/tempdir'
} }
}); });
expect(shell.env.get('TMP')).to.equal('/tempdir'); expect(shell.env.get('TMP')).to.equal('/tempdir');
shell.tempDir(function(err, tmp) { shell.tempDir(function(err, tmp) {
expect(err).not.to.exist;
shell.cd(tmp, function(err) {
expect(err).not.to.exist; expect(err).not.to.exist;
shell.cd(tmp, function(err) { expect(shell.pwd()).to.equal('/tempdir');
expect(err).not.to.exist; done();
expect(shell.pwd()).to.equal('/tempdir');
done();
});
}); });
}); });
});
it('should allow repeated calls to tempDir()', function(done) { it('should allow repeated calls to tempDir()', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
expect(shell.env.get('TMP')).to.equal('/tmp');
shell.tempDir(function(err, tmp) {
expect(err).not.to.exist;
expect(tmp).to.equal('/tmp');
expect(shell.env.get('TMP')).to.equal('/tmp');
shell.tempDir(function(err, tmp) { shell.tempDir(function(err, tmp) {
expect(err).not.to.exist; expect(err).not.to.exist;
expect(tmp).to.equal('/tmp'); expect(tmp).to.equal('/tmp');
done();
shell.tempDir(function(err, tmp) {
expect(err).not.to.exist;
expect(tmp).to.equal('/tmp');
done();
});
}); });
}); });
}); });
}); });

View File

@ -1,33 +1,33 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.exec', function() { describe('FileSystemShell.exec', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.exec).to.be.a('function'); expect(shell.exec).to.be.a('function');
}); });
it('should be able to execute a command .js file from the filesystem', function(done) { it('should be able to execute a command .js file from the filesystem', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var cmdString = "fs.writeFile(args[0], args[1], callback);"; var cmdString = "fs.writeFile(args[0], args[1], callback);";
fs.writeFile('/cmd.js', cmdString, function(error) { fs.writeFile('/cmd.js', cmdString, function(error) {
if(error) throw error;
shell.exec('/cmd.js', ['/test', 'hello world'], function(error, result) {
if(error) throw error; if(error) throw error;
shell.exec('/cmd.js', ['/test', 'hello world'], function(error, result) { fs.readFile('/test', 'utf8', function(error, data) {
if(error) throw error; if(error) throw error;
expect(data).to.equal('hello world');
fs.readFile('/test', 'utf8', function(error, data) { done();
if(error) throw error;
expect(data).to.equal('hello world');
done();
});
}); });
}); });
}); });
}); });
}); });

View File

@ -1,73 +1,134 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.ls', function() { describe('FileSystemShell.ls', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.ls).to.be.a('function'); expect(shell.ls).to.be.a('function');
});
it('should fail when dirs argument is absent', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.cat(null, function(error, list) {
expect(error).to.exist;
expect(error.code).to.equal("EINVAL");
expect(list).not.to.exist;
done();
}); });
});
it('should fail when dirs argument is absent', function(done) { it('should return the contents of a simple dir', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var contents = "a";
var contents2 = "bb";
shell.cat(null, function(error, list) { fs.writeFile('/file', contents, function(err) {
expect(error).to.exist; if(err) throw err;
expect(error.code).to.equal("EINVAL");
expect(list).not.to.exist;
done();
});
});
it('should return the contents of a simple dir', function(done) { fs.writeFile('/file2', contents2, function(err) {
var fs = util.fs();
var shell = fs.Shell();
var contents = "a";
var contents2 = "bb";
fs.writeFile('/file', contents, function(err) {
if(err) throw err; if(err) throw err;
fs.writeFile('/file2', contents2, function(err) { shell.ls('/', function(err, list) {
expect(err).not.to.exist;
expect(list.length).to.equal(2);
var item0 = list[0];
expect(item0.path).to.equal('file');
expect(item0.links).to.equal(1);
expect(item0.size).to.equal(1);
expect(item0.modified).to.be.a('number');
expect(item0.type).to.equal('FILE');
expect(item0.contents).not.to.exist;
var item1 = list[1];
expect(item1.path).to.equal('file2');
expect(item1.links).to.equal(1);
expect(item1.size).to.equal(2);
expect(item1.modified).to.be.a('number');
expect(item1.type).to.equal('FILE');
expect(item0.contents).not.to.exist;
done();
});
});
});
});
it('should return the shallow contents of a dir tree', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var contents = "a";
fs.mkdir('/dir', function(err) {
if(err) throw err;
fs.mkdir('/dir/dir2', function(err) {
if(err) throw err;
fs.writeFile('/dir/file', contents, function(err) {
if(err) throw err; if(err) throw err;
shell.ls('/', function(err, list) { fs.writeFile('/dir/file2', contents, function(err) {
expect(err).not.to.exist; if(err) throw err;
expect(list.length).to.equal(2);
var item0 = list[0]; shell.ls('/dir', function(err, list) {
expect(item0.path).to.equal('file'); expect(err).not.to.exist;
expect(item0.links).to.equal(1); expect(list.length).to.equal(3);
expect(item0.size).to.equal(1);
expect(item0.modified).to.be.a('number');
expect(item0.type).to.equal('FILE');
expect(item0.contents).not.to.exist;
var item1 = list[1]; // We shouldn't rely on the order we'll get the listing
expect(item1.path).to.equal('file2'); list.forEach(function(item, i, arr) {
expect(item1.links).to.equal(1); switch(item.path) {
expect(item1.size).to.equal(2); case 'dir2':
expect(item1.modified).to.be.a('number'); expect(item.links).to.equal(1);
expect(item1.type).to.equal('FILE'); expect(item.size).to.be.a('number');
expect(item0.contents).not.to.exist; expect(item.modified).to.be.a('number');
expect(item.type).to.equal('DIRECTORY');
expect(item.contents).not.to.exist;
break;
case 'file':
case 'file2':
expect(item.links).to.equal(1);
expect(item.size).to.equal(1);
expect(item.modified).to.be.a('number');
expect(item.type).to.equal('FILE');
expect(item.contents).not.to.exist;
break;
default:
// shouldn't happen
expect(true).to.be.false;
break;
}
done(); if(i === arr.length -1) {
done();
}
});
});
}); });
}); });
}); });
}); });
});
it('should return the shallow contents of a dir tree', function(done) { it('should return the deep contents of a dir tree', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var contents = "a"; var contents = "a";
fs.mkdir('/dir', function(err) { fs.mkdir('/dir', function(err) {
if(err) throw err;
fs.mkdir('/dir/dir2', function(err) {
if(err) throw err; if(err) throw err;
fs.mkdir('/dir/dir2', function(err) { fs.writeFile('/dir/dir2/file', contents, function(err) {
if(err) throw err; if(err) throw err;
fs.writeFile('/dir/file', contents, function(err) { fs.writeFile('/dir/file', contents, function(err) {
@ -76,7 +137,7 @@ define(["Filer", "util"], function(Filer, util) {
fs.writeFile('/dir/file2', contents, function(err) { fs.writeFile('/dir/file2', contents, function(err) {
if(err) throw err; if(err) throw err;
shell.ls('/dir', function(err, list) { shell.ls('/dir', { recursive: true }, function(err, list) {
expect(err).not.to.exist; expect(err).not.to.exist;
expect(list.length).to.equal(3); expect(list.length).to.equal(3);
@ -88,7 +149,15 @@ define(["Filer", "util"], function(Filer, util) {
expect(item.size).to.be.a('number'); expect(item.size).to.be.a('number');
expect(item.modified).to.be.a('number'); expect(item.modified).to.be.a('number');
expect(item.type).to.equal('DIRECTORY'); expect(item.type).to.equal('DIRECTORY');
expect(item.contents).not.to.exist; expect(item.contents).to.exist;
expect(item.contents.length).to.equal(1);
var contents0 = item.contents[0];
expect(contents0.path).to.equal('file');
expect(contents0.links).to.equal(1);
expect(contents0.size).to.equal(1);
expect(contents0.modified).to.be.a('number');
expect(contents0.type).to.equal('FILE');
expect(contents0.contents).not.to.exist;
break; break;
case 'file': case 'file':
case 'file2': case 'file2':
@ -114,74 +183,5 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
it('should return the deep contents of a dir tree', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var contents = "a";
fs.mkdir('/dir', function(err) {
if(err) throw err;
fs.mkdir('/dir/dir2', function(err) {
if(err) throw err;
fs.writeFile('/dir/dir2/file', contents, function(err) {
if(err) throw err;
fs.writeFile('/dir/file', contents, function(err) {
if(err) throw err;
fs.writeFile('/dir/file2', contents, function(err) {
if(err) throw err;
shell.ls('/dir', { recursive: true }, function(err, list) {
expect(err).not.to.exist;
expect(list.length).to.equal(3);
// We shouldn't rely on the order we'll get the listing
list.forEach(function(item, i, arr) {
switch(item.path) {
case 'dir2':
expect(item.links).to.equal(1);
expect(item.size).to.be.a('number');
expect(item.modified).to.be.a('number');
expect(item.type).to.equal('DIRECTORY');
expect(item.contents).to.exist;
expect(item.contents.length).to.equal(1);
var contents0 = item.contents[0];
expect(contents0.path).to.equal('file');
expect(contents0.links).to.equal(1);
expect(contents0.size).to.equal(1);
expect(contents0.modified).to.be.a('number');
expect(contents0.type).to.equal('FILE');
expect(contents0.contents).not.to.exist;
break;
case 'file':
case 'file2':
expect(item.links).to.equal(1);
expect(item.size).to.equal(1);
expect(item.modified).to.be.a('number');
expect(item.type).to.equal('FILE');
expect(item.contents).not.to.exist;
break;
default:
// shouldn't happen
expect(true).to.be.false;
break;
}
if(i === arr.length -1) {
done();
}
});
});
});
});
});
});
});
});
}); });
}); });

View File

@ -1,97 +1,98 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.mkdirp', function() { describe('FileSystemShell.mkdirp', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.mkdirp).to.be.a('function'); expect(shell.mkdirp).to.be.a('function');
});
it('should fail without a path provided', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.mkdirp(null, function(err) {
expect(err).to.exist;
expect(err.code).to.equal('EINVAL');
done();
}); });
});
it('should fail without a path provided', function(done) { it('should succeed if provided path is root', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
shell.mkdirp('/', function(err) {
expect(err).to.not.exist;
done();
});
});
shell.mkdirp(null, function(err) { it('should succeed if the directory exists', function(done) {
expect(err).to.exist; var fs = util.fs();
expect(err.code).to.equal('EINVAL'); var shell = fs.Shell();
done(); fs.mkdir('/test', function(err){
expect(err).to.not.exist;
shell.mkdirp('/test',function(err) {
expect(err).to.not.exist;
done();
}); });
}); });
});
it('should succeed if provided path is root', function(done) { it('fail if a file name is provided', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
shell.mkdirp('/', function(err) { fs.writeFile('/test.txt', 'test', function(err){
expect(err).to.not.exist; expect(err).to.not.exist;
done(); shell.mkdirp('/test.txt', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
done();
}); });
}); });
});
it('should succeed if the directory exists', function(done) { it('should succeed on a folder on root (\'/test\')', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
fs.mkdir('/test', function(err){ shell.mkdirp('/test', function(err) {
expect(err).to.not.exist; expect(err).to.not.exist;
shell.mkdirp('/test',function(err) { fs.exists('/test', function(dir){
expect(err).to.not.exist; expect(dir).to.be.true;
done(); done();
});
});
});
it('fail if a file name is provided', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.writeFile('/test.txt', 'test', function(err){
expect(err).to.not.exist;
shell.mkdirp('/test.txt', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
done();
});
}); });
}); });
});
it('should succeed on a folder on root (\'/test\')', function(done) { it('should succeed on a folder with a nonexistant parent (\'/test/test\')', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
shell.mkdirp('/test', function(err) { shell.mkdirp('/test/test', function(err) {
expect(err).to.not.exist; expect(err).to.not.exist;
fs.exists('/test', function(dir){ fs.exists('/test', function(dir1){
expect(dir).to.be.true; expect(dir1).to.be.true;
done(); fs.exists('/test/test', function(dir2){
}); expect(dir2).to.be.true;
});
});
it('should succeed on a folder with a nonexistant parent (\'/test/test\')', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.mkdirp('/test/test', function(err) {
expect(err).to.not.exist;
fs.exists('/test', function(dir1){
expect(dir1).to.be.true;
fs.exists('/test/test', function(dir2){
expect(dir2).to.be.true;
done();
});
});
});
});
it('should fail on a folder with a file for its parent (\'/test.txt/test\')', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.writeFile('/test.txt', 'test', function(err){
expect(err).to.not.exist;
shell.mkdirp('/test.txt/test', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
done(); done();
}); });
}); });
}); });
}); });
it('should fail on a folder with a file for its parent (\'/test.txt/test\')', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.writeFile('/test.txt', 'test', function(err){
expect(err).to.not.exist;
shell.mkdirp('/test.txt/test', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
done();
});
});
});
}); });

View File

@ -1,54 +1,97 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.rm', function() { describe('FileSystemShell.rm', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.rm).to.be.a('function'); expect(shell.rm).to.be.a('function');
});
it('should fail when path argument is absent', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.rm(null, function(error, list) {
expect(error).to.exist;
expect(error.code).to.equal("EINVAL");
expect(list).not.to.exist;
done();
}); });
});
it('should fail when path argument is absent', function(done) { it('should remove a single file', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var contents = "a";
shell.rm(null, function(error, list) { fs.writeFile('/file', contents, function(err) {
expect(error).to.exist; if(err) throw err;
expect(error.code).to.equal("EINVAL");
expect(list).not.to.exist;
done();
});
});
it('should remove a single file', function(done) { shell.rm('/file', function(err) {
var fs = util.fs(); expect(err).not.to.exist;
var shell = fs.Shell();
var contents = "a";
fs.writeFile('/file', contents, function(err) { fs.stat('/file', function(err, stats) {
if(err) throw err; expect(err).to.exist;
expect(stats).not.to.exist;
shell.rm('/file', function(err) { done();
expect(err).not.to.exist;
fs.stat('/file', function(err, stats) {
expect(err).to.exist;
expect(stats).not.to.exist;
done();
});
}); });
}); });
}); });
});
it('should remove an empty dir', function(done) { it('should remove an empty dir', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
fs.mkdir('/dir', function(err) { fs.mkdir('/dir', function(err) {
if(err) throw err;
shell.rm('/dir', function(err) {
expect(err).not.to.exist;
fs.stat('/dir', function(err, stats) {
expect(err).to.exist;
expect(stats).not.to.exist;
done();
});
});
});
});
it('should fail to remove a non-empty dir', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
shell.touch('/dir/file', function(err) {
if(err) throw err; if(err) throw err;
shell.rm('/dir', function(err) { shell.rm('/dir', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTEMPTY');
done();
});
});
});
});
it('should remove a non-empty dir with option.recursive set', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
shell.touch('/dir/file', function(err) {
if(err) throw err;
shell.rm('/dir', { recursive: true }, function(err) {
expect(err).not.to.exist; expect(err).not.to.exist;
fs.stat('/dir', function(err, stats) { fs.stat('/dir', function(err, stats) {
@ -59,80 +102,37 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
}); });
});
it('should fail to remove a non-empty dir', function(done) { it('should work on a complex dir structure', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var contents = "a";
fs.mkdir('/dir', function(err) { fs.mkdir('/dir', function(err) {
if(err) throw err;
fs.mkdir('/dir/dir2', function(err) {
if(err) throw err; if(err) throw err;
shell.touch('/dir/file', function(err) { fs.writeFile('/dir/file', contents, function(err) {
if(err) throw err; if(err) throw err;
shell.rm('/dir', function(err) { fs.writeFile('/dir/file2', contents, function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTEMPTY');
done();
});
});
});
});
it('should remove a non-empty dir with option.recursive set', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/dir', function(err) {
if(err) throw err;
shell.touch('/dir/file', function(err) {
if(err) throw err;
shell.rm('/dir', { recursive: true }, function(err) {
expect(err).not.to.exist;
fs.stat('/dir', function(err, stats) {
expect(err).to.exist;
expect(stats).not.to.exist;
done();
});
});
});
});
});
it('should work on a complex dir structure', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var contents = "a";
fs.mkdir('/dir', function(err) {
if(err) throw err;
fs.mkdir('/dir/dir2', function(err) {
if(err) throw err;
fs.writeFile('/dir/file', contents, function(err) {
if(err) throw err; if(err) throw err;
fs.writeFile('/dir/file2', contents, function(err) { shell.rm('/dir', { recursive: true }, function(err) {
if(err) throw err; expect(err).not.to.exist;
shell.rm('/dir', { recursive: true }, function(err) { fs.stat('/dir', function(err, stats) {
expect(err).not.to.exist; expect(err).to.exist;
expect(stats).not.to.exist;
fs.stat('/dir', function(err, stats) { done();
expect(err).to.exist;
expect(stats).not.to.exist;
done();
});
}); });
}); });
}); });
}); });
}); });
}); });
}); });
}); });

View File

@ -1,98 +1,76 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
function getTimes(fs, path, callback) { function getTimes(fs, path, callback) {
fs.stat(path, function(error, stats) { fs.stat(path, function(error, stats) {
if(error) throw error;
callback({mtime: stats.mtime, atime: stats.atime});
});
}
describe('FileSystemShell.touch', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var shell = util.shell();
expect(shell.touch).to.be.a('function');
});
it('should create a new file if path does not exist', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.touch('/newfile', function(error) {
if(error) throw error; if(error) throw error;
callback({mtime: stats.mtime, atime: stats.atime});
fs.stat('/newfile', function(error, stats) {
expect(error).not.to.exist;
expect(stats.type).to.equal('FILE');
done();
});
}); });
} });
describe('FileSystemShell.touch', function() { it('should skip creating a new file if options.updateOnly is true', function(done) {
beforeEach(util.setup); var fs = util.fs();
afterEach(util.cleanup); var shell = fs.Shell();
it('should be a function', function() { shell.touch('/newfile', { updateOnly: true }, function(error) {
var shell = util.shell(); if(error) throw error;
expect(shell.touch).to.be.a('function');
fs.stat('/newfile', function(error, stats) {
expect(error).to.exist;
done();
});
}); });
});
it('should create a new file if path does not exist', function(done) { it('should update times if path does exist', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var atime = Date.parse('1 Oct 2000 15:33:22');
var mtime = Date.parse('30 Sep 2000 06:43:54');
shell.touch('/newfile', function(error) { fs.open('/newfile', 'w', function (error, fd) {
if (error) throw error;
fs.futimes(fd, atime, mtime, function (error) {
if(error) throw error; if(error) throw error;
fs.stat('/newfile', function(error, stats) {
expect(error).not.to.exist;
expect(stats.type).to.equal('FILE');
done();
});
});
});
it('should skip creating a new file if options.updateOnly is true', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.touch('/newfile', { updateOnly: true }, function(error) {
if(error) throw error;
fs.stat('/newfile', function(error, stats) {
expect(error).to.exist;
done();
});
});
});
it('should update times if path does exist', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var atime = Date.parse('1 Oct 2000 15:33:22');
var mtime = Date.parse('30 Sep 2000 06:43:54');
fs.open('/newfile', 'w', function (error, fd) {
if (error) throw error;
fs.futimes(fd, atime, mtime, function (error) {
if(error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
getTimes(fs, '/newfile', function(times1) {
shell.touch('/newfile', function(error) {
expect(error).not.to.exist;
getTimes(fs, '/newfile', function(times2) {
expect(times2.mtime).to.be.above(times1.mtime);
expect(times2.atime).to.be.above(times1.atime);
done();
});
});
});
});
});
});
});
it('should update times to specified date if path does exist', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var date = Date.parse('1 Oct 2001 15:33:22');
fs.open('/newfile', 'w', function (error, fd) {
if (error) throw error;
fs.close(fd, function(error) { fs.close(fd, function(error) {
if(error) throw error; if(error) throw error;
shell.touch('/newfile', { date: date }, function(error) { getTimes(fs, '/newfile', function(times1) {
expect(error).not.to.exist; shell.touch('/newfile', function(error) {
expect(error).not.to.exist;
getTimes(fs, '/newfile', function(times) { getTimes(fs, '/newfile', function(times2) {
expect(times.mtime).to.equal(date); expect(times2.mtime).to.be.above(times1.mtime);
done(); expect(times2.atime).to.be.above(times1.atime);
done();
});
}); });
}); });
}); });
@ -100,4 +78,26 @@ define(["Filer", "util"], function(Filer, util) {
}); });
}); });
it('should update times to specified date if path does exist', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var date = Date.parse('1 Oct 2001 15:33:22');
fs.open('/newfile', 'w', function (error, fd) {
if (error) throw error;
fs.close(fd, function(error) {
if(error) throw error;
shell.touch('/newfile', { date: date }, function(error) {
expect(error).not.to.exist;
getTimes(fs, '/newfile', function(times) {
expect(times.mtime).to.equal(date);
done();
});
});
});
});
});
}); });

View File

@ -1,116 +1,95 @@
define(["Filer", "util"], function(Filer, util) { var Filer = require('../../..');
var util = require('../../lib/test-utils.js');
var expect = require('chai').expect;
describe('FileSystemShell.wget', function() { describe('FileSystemShell.wget', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function() {
var shell = util.shell(); var shell = util.shell();
expect(shell.wget).to.be.a('function'); expect(shell.wget).to.be.a('function');
});
it('should fail when url argument is absent', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.wget(null, function(err, data) {
expect(err).to.exist;
expect(data).not.to.exist;
done();
}); });
});
it('should fail when url argument is absent', function(done) { it('should fail when the url does not exist (404)', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
shell.wget(null, function(err, data) { shell.wget("no-such-url", function(err, data) {
expect(err).to.exist; expect(err).to.exist;
expect(data).not.to.exist; expect(data).not.to.exist;
done();
});
});
it('should download the contents of a file from a url to default filename', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var url = typeof XMLHttpRequest === "undefined" ? "http://localhost:1234/tests/test-file.txt" : "/tests/test-file.txt";
var contents = "This is a test file used in some of the tests.\n";
shell.wget(url, function(err, path) {
if(err) throw err;
expect(path).to.equal('/test-file.txt');
fs.readFile(path, 'utf8', function(err, data) {
if(err) throw err;
expect(data).to.equal(contents);
done(); done();
}); });
}); });
});
it('should fail when the url does not exist (404)', function(done) { it('should download the contents of a file from a url to specified filename', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var url = typeof XMLHttpRequest === "undefined" ? "http://localhost:1234/tests/test-file.txt" : "/tests/test-file.txt";
var contents = "This is a test file used in some of the tests.\n";
shell.wget("no-such-url", function(err, data) { shell.wget(url, { filename: 'test-file.txt' }, function(err, path) {
expect(err).to.exist; if(err) throw err;
expect(data).not.to.exist;
expect(path).to.equal('/test-file.txt');
fs.readFile(path, 'utf8', function(err, data) {
if(err) throw err;
expect(data).to.equal(contents);
done(); done();
}); });
}); });
});
it('should download the contents of a file from a url to default filename', function(done) { it('should download the contents of a file from a url with query string', function(done) {
var fs = util.fs(); var fs = util.fs();
var shell = fs.Shell(); var shell = fs.Shell();
var url = "test-file.txt"; var url = typeof XMLHttpRequest === "undefined" ? "http://localhost:1234/tests/test-file.txt?foo" : "/tests/test-file.txt?foo";
var contents = "This is a test file used in some of the tests.\n"; var contents = "This is a test file used in some of the tests.\n";
shell.wget(url, function(err, path) { shell.wget(url, function(err, path) {
if(err) throw err;
expect(path).to.equal('/test-file.txt?foo');
fs.readFile(path, 'utf8', function(err, data) {
if(err) throw err; if(err) throw err;
expect(path).to.equal('/test-file.txt'); expect(data).to.equal(contents);
done();
fs.readFile(path, 'utf8', function(err, data) {
if(err) throw err;
expect(data).to.equal(contents);
done();
});
}); });
}); });
it('should download the contents of a file from a url to specified filename', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var url = "test-file.txt";
var contents = "This is a test file used in some of the tests.\n";
shell.wget(url, { filename: 'test-file.txt' }, function(err, path) {
if(err) throw err;
expect(path).to.equal('/test-file.txt');
fs.readFile(path, 'utf8', function(err, data) {
if(err) throw err;
expect(data).to.equal(contents);
done();
});
});
});
it('should download the contents of a file from a url with query string', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var url = "test-file.txt?foo";
var contents = "This is a test file used in some of the tests.\n";
shell.wget(url, function(err, path) {
if(err) throw err;
expect(path).to.equal('/test-file.txt?foo');
fs.readFile(path, 'utf8', function(err, data) {
if(err) throw err;
expect(data).to.equal(contents);
done();
});
});
});
it('should download the contents of a file from a url to specified filename, stripping : and /', function(done) {
var fs = util.fs();
var shell = fs.Shell();
var url = "test-file.txt?foo=:/";
var contents = "This is a test file used in some of the tests.\n";
shell.wget(url, function(err, path) {
if(err) throw err;
expect(path).to.equal('/test-file.txt?foo=');
fs.readFile(path, 'utf8', function(err, data) {
if(err) throw err;
expect(data).to.equal(contents);
done();
});
});
});
}); });
}); });

Some files were not shown because too many files have changed in this diff Show More