<commit_before>/**
 * Module dependencies.
 */
var fs = require('fs')
  , ltx = require('ltx')
  , element = require('./element');

/**
 * Render a Less-Than XML builder file at the given `path` and callback
 * `fn(err, str)`.
 *
 * @param {String} path
 * @param {Object|Function} options or callback
 * @param {Function} fn
 * @api public
 */
function renderFile(path, options, fn) {
  if ('function' == typeof options) {
    fn = options, options = {};
  }

  try {
    options.filename = path;
    var str = options.cache
      ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
      : fs.readFileSync(path, 'utf8');
    exports.render(str, options, fn);
  } catch (err) {
    fn(err);
  }
}

/**
 * Export `renderFile` as module function.
 *
 * @api public
 */
exports = module.exports = renderFile;

/**
 * Template function cache.
 */
exports.cache = {};

/**
 * Factory function to create new `Element`.
 *
 * @return {ltx.Element}
 * @api private
 */
function factory() {
  var el = new ltx.Element();
  el.n = element.n;
  return el
}

/**
 * Parse the given `str` of Less-Than XML builder and return a function body.
 *
 * @param {String} str
 * @param {Object} options
 * @return {String}
 * @api private
 */
function parse(str, options) {
  var doc = options.document || 'xml'
    , js = str;

  return ''
    + 'var ' + doc + ' = factory();\n'
    + (options.self
      ? 'var self = locals || {};\n' + js
      : 'with (locals || {}) {\n' + js + '\n}\n')
    + 'return ' + doc + '.toString()';
}

/**
 * Re-throw the given `err` in context to the `str` of Less-Than XML builder,
 * `filename`, and `lineno`.
 *
 * @param {Error} err
 * @param {String} str
 * @param {String} filename
 * @param {String} lineno
 * @api private
 */
function rethrow(err, str, filename, lineno) {
  var context = 3
    , lines = str.split('\n')
    , start = Math.max(lineno - context, 0)
    , end = Math.min(lines.length, lineno + context);

  // NOTE: Due to the fact that this "template" is not being parsed line by
  //       line, `lineno` here is always 1.  If there is an elegant apprach to
  //       determining the offending line, it is TBD; despite this, the error is
  //       made more useful by including the context and filename.

  // Error context
  var context = lines.slice(start, end).map(function(line, i){
    var curr = i + start + 1;
    return (curr == lineno ? ' >> ' : '    ')
      + curr
      + '| '
      + line;
  }).join('\n');

  // Alter exception message
  err.path = filename;
  err.message = (filename || 'ltxb') + ':' + lineno
    + '\n' + context + '\n\n' + err.message;
  throw err;
}

/**
 * Compile a `Function` representation of the given Less-Than XML builder `str`.
 *
 * Options:
 *
 *   - `compileDebug` when `false` debugging code is stripped from the compiled template
 *
 * @param {String} str
 * @param {Options} options
 * @return {Function}
 * @api public
 */
exports.compile = function(str, options) {
  options = options || {};

  var input = JSON.stringify(str)
    , filename = options.filename
      ? JSON.stringify(options.filename)
      : 'undefined'
    , fn;

  if (options.compileDebug !== false) {
    fn = [
        'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };'
      , 'try {'
      , parse(str, options)
      , '} catch (err) {'
      , '  rethrow(err, __stack.input, __stack.filename, __stack.lineno);'
      , '}'
    ].join('\n');
  } else {
    fn = parse(str, options);
  }

  fn = new Function('locals, rethrow, factory', fn);
  return function(locals) {
    return fn(locals, rethrow, factory);
  };
}

/**
 * Render the given `str` of Less-Than XML builder and invoke the callback
 * `fn(err, str)`.
 *
 * Options:
 *
 *   - `cache`    enable template caching
 *   - `filename` filename required for caching
 *
 * @param {String} str
 * @param {Object|Function} options or fn
 * @param {Function} fn
 * @api public
 */
exports.render = function(str, options, fn) {
  if ('function' == typeof options) {
    fn = options, options = {};
  }

  // cache requires .filename
  if (options.cache && !options.filename) {
    return fn(new Error('the "filename" option is required for caching'));
  }

  try {
    var path = options.filename;
    var tmpl = options.cache
      ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
      : exports.compile(str, options);
    fn(null, tmpl(options));
  } catch (err) {
    fn(err);
  }
}

/**
 * Express support.
 */
exports.__express = renderFile;
<commit_msg>Add missing cache key.<commit_after>/**
 * Module dependencies.
 */
var fs = require('fs')
  , ltx = require('ltx')
  , element = require('./element');

/**
 * Render a Less-Than XML builder file at the given `path` and callback
 * `fn(err, str)`.
 *
 * @param {String} path
 * @param {Object|Function} options or callback
 * @param {Function} fn
 * @api public
 */
function renderFile(path, options, fn) {
  var key = path + ':string';

  if ('function' == typeof options) {
    fn = options, options = {};
  }

  try {
    options.filename = path;
    var str = options.cache
      ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
      : fs.readFileSync(path, 'utf8');
    exports.render(str, options, fn);
  } catch (err) {
    fn(err);
  }
}

/**
 * Export `renderFile` as module function.
 *
 * @api public
 */
exports = module.exports = renderFile;

/**
 * Template function cache.
 */
exports.cache = {};

/**
 * Factory function to create new `Element`.
 *
 * @return {ltx.Element}
 * @api private
 */
function factory() {
  var el = new ltx.Element();
  el.n = element.n;
  return el
}

/**
 * Parse the given `str` of Less-Than XML builder and return a function body.
 *
 * @param {String} str
 * @param {Object} options
 * @return {String}
 * @api private
 */
function parse(str, options) {
  var doc = options.document || 'xml'
    , js = str;

  return ''
    + 'var ' + doc + ' = factory();\n'
    + (options.self
      ? 'var self = locals || {};\n' + js
      : 'with (locals || {}) {\n' + js + '\n}\n')
    + 'return ' + doc + '.toString()';
}

/**
 * Re-throw the given `err` in context to the `str` of Less-Than XML builder,
 * `filename`, and `lineno`.
 *
 * @param {Error} err
 * @param {String} str
 * @param {String} filename
 * @param {String} lineno
 * @api private
 */
function rethrow(err, str, filename, lineno) {
  var context = 3
    , lines = str.split('\n')
    , start = Math.max(lineno - context, 0)
    , end = Math.min(lines.length, lineno + context);

  // NOTE: Due to the fact that this "template" is not being parsed line by
  //       line, `lineno` here is always 1.  If there is an elegant apprach to
  //       determining the offending line, it is TBD; despite this, the error is
  //       made more useful by including the context and filename.

  // Error context
  var context = lines.slice(start, end).map(function(line, i){
    var curr = i + start + 1;
    return (curr == lineno ? ' >> ' : '    ')
      + curr
      + '| '
      + line;
  }).join('\n');

  // Alter exception message
  err.path = filename;
  err.message = (filename || 'ltxb') + ':' + lineno
    + '\n' + context + '\n\n' + err.message;
  throw err;
}

/**
 * Compile a `Function` representation of the given Less-Than XML builder `str`.
 *
 * Options:
 *
 *   - `compileDebug` when `false` debugging code is stripped from the compiled template
 *
 * @param {String} str
 * @param {Options} options
 * @return {Function}
 * @api public
 */
exports.compile = function(str, options) {
  options = options || {};

  var input = JSON.stringify(str)
    , filename = options.filename
      ? JSON.stringify(options.filename)
      : 'undefined'
    , fn;

  if (options.compileDebug !== false) {
    fn = [
        'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };'
      , 'try {'
      , parse(str, options)
      , '} catch (err) {'
      , '  rethrow(err, __stack.input, __stack.filename, __stack.lineno);'
      , '}'
    ].join('\n');
  } else {
    fn = parse(str, options);
  }

  fn = new Function('locals, rethrow, factory', fn);
  return function(locals) {
    return fn(locals, rethrow, factory);
  };
}

/**
 * Render the given `str` of Less-Than XML builder and invoke the callback
 * `fn(err, str)`.
 *
 * Options:
 *
 *   - `cache`    enable template caching
 *   - `filename` filename required for caching
 *
 * @param {String} str
 * @param {Object|Function} options or fn
 * @param {Function} fn
 * @api public
 */
exports.render = function(str, options, fn) {
  if ('function' == typeof options) {
    fn = options, options = {};
  }

  // cache requires .filename
  if (options.cache && !options.filename) {
    return fn(new Error('the "filename" option is required for caching'));
  }

  try {
    var path = options.filename;
    var tmpl = options.cache
      ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
      : exports.compile(str, options);
    fn(null, tmpl(options));
  } catch (err) {
    fn(err);
  }
}

/**
 * Express support.
 */
exports.__express = renderFile;
<|endoftext|>


<commit_before>'use strict';
/**
 * This object contains all the handlers to use for this providers
 */
var googleapis = require('googleapis');
var rarity = require('rarity');
var async = require('async');
var OAuth2Client = googleapis.OAuth2Client;

var config = require('../config/configuration.js');
var retrieveFiles = require('./helpers/retrieve.js');
var uploadFile = require('./helpers/upload.js');
var deleteFile = require('./helpers/delete.js');
var selectBestDownload = require('./helpers/select-best-download.js');

var redirectToService = function(callbackUrl, cb) {
  googleapis.execute(function(err) {
    if(err) {
      return cb(err);
    }

    var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, callbackUrl);

    // generate consent page url for Google Drive access, even when user is not connected (offline)
    var redirectUrl = oauth2Client.generateAuthUrl({
      access_type: 'offline',
      scope: 'https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.email',
      approval_prompt: 'force', // Force resending a refresh_token
    });

    cb(null, redirectUrl, {callbackUrl: callbackUrl});
  });
};

var retrieveTokens = function(reqParams, storedParams, cb) {
  async.waterfall([
    function getClient(cb) {
      googleapis.discover('oauth2', 'v2').execute(cb);
    },
    function getToken(client, cb) {
      var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, storedParams.callbackUrl);
      oauth2Client.getToken(reqParams.code, rarity.carryAndSlice([oauth2Client, client], 4, cb));
    },
    function getUserInfo(oauth2Client, client, tokens, cb) {
      oauth2Client.credentials = tokens;
      client.oauth2.userinfo.get().withAuthClient(oauth2Client).execute(rarity.carryAndSlice([tokens], 3, cb));
    },
    function callFinalCb(tokens, data, cb) {
      cb(null, data.email, {tokens: tokens, callbackUrl: storedParams.callbackUrl});
    }
  ], cb);
};

var updateAccount = function(serviceData, cursor, queues, cb) {
  // Retrieve all files since last call
  async.waterfall([
    function refreshTokens(cb) {
      var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.refreshToken_(serviceData.tokens.refresh_token, function(err, tokens) {
        tokens.refresh_token = serviceData.tokens.refresh_token;
        serviceData.tokens = tokens;
        cb(err);
      });
    },
    function getClient(cb) {
      googleapis.discover('drive', 'v2').execute(cb);
    },
    function retrieveChanges(client, cb) {
      var options = {
        maxResults: 1000,
      };

      if(cursor) {
        options.startChangeId = cursor;
      }

      options.includeDeleted = (cursor) ? true : false;

      var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.credentials = serviceData.tokens;

      retrieveFiles(client, oauth2Client, options, [], cb);
    },
    function applyChanges(newCursor, changes, cb) {
      changes.forEach(function(change) {
        var id = "https://docs.google.com/file/d/" + change.fileId;

        if(change.deleted || (cursor && change.file.labels.trashed)) {
          queues.deletion.push({
            title: change.file.title,
            id: id
          });
        }
        else {
          var download = selectBestDownload(change.file);

          if(download.url && !change.file.labels.trashed && (!change.file.fileSize || change.file.fileSize < config.maxSize * 1024 * 1024)) {
            queues.addition.push({
              title: change.file.title + ((change.file.title.indexOf(download.extension) === -1) ? download.extension : ''),
              downloadUrl: download.url,
              type: download.type,
              date: change.file.createdDate,
              starred: change.file.labels.starred,
              id: id,
              exported: download.exported,
              link: change.file.alternateLink
            });
          }
        }
      });

      cb(null, newCursor, serviceData);
    }
  ], cb);
};

var additionQueueWorker = function(job, cb) {
  console.log("Uploading", job.task.title);
  uploadFile(job.task, job.anyfetchClient, job.serviceData.tokens.access_token, cb);
};

var deletionQueueWorker = function(job, cb) {
  console.log("Deleting", job.task.title);
  deleteFile(job.task, job.anyfetchClient, cb);
};

additionQueueWorker.concurrency = config.maxConcurrency;
deletionQueueWorker.concurrency = config.maxConcurrency;

module.exports = {
  connectFunctions: {
    redirectToService: redirectToService,
    retrieveTokens: retrieveTokens
  },
  updateAccount: updateAccount,
  workers: {
    addition: additionQueueWorker,
    deletion: deletionQueueWorker
  },

  config: config
};
<commit_msg>Unable direct stream to upload file<commit_after>'use strict';
/**
 * This object contains all the handlers to use for this providers
 */
var googleapis = require('googleapis');
var rarity = require('rarity');
var async = require('async');
var OAuth2Client = googleapis.OAuth2Client;

var config = require('../config/configuration.js');
var retrieveFiles = require('./helpers/retrieve.js');
var uploadFile = require('./helpers/upload.js');
var deleteFile = require('./helpers/delete.js');
var selectBestDownload = require('./helpers/select-best-download.js');

var redirectToService = function(callbackUrl, cb) {
  googleapis.execute(function(err) {
    if(err) {
      return cb(err);
    }

    var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, callbackUrl);

    // generate consent page url for Google Drive access, even when user is not connected (offline)
    var redirectUrl = oauth2Client.generateAuthUrl({
      access_type: 'offline',
      scope: 'https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.email',
      approval_prompt: 'force', // Force resending a refresh_token
    });

    cb(null, redirectUrl, {callbackUrl: callbackUrl});
  });
};

var retrieveTokens = function(reqParams, storedParams, cb) {
  async.waterfall([
    function getClient(cb) {
      googleapis.discover('oauth2', 'v2').execute(cb);
    },
    function getToken(client, cb) {
      var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, storedParams.callbackUrl);
      oauth2Client.getToken(reqParams.code, rarity.carryAndSlice([oauth2Client, client], 4, cb));
    },
    function getUserInfo(oauth2Client, client, tokens, cb) {
      oauth2Client.credentials = tokens;
      client.oauth2.userinfo.get().withAuthClient(oauth2Client).execute(rarity.carryAndSlice([tokens], 3, cb));
    },
    function callFinalCb(tokens, data, cb) {
      cb(null, data.email, {tokens: tokens, callbackUrl: storedParams.callbackUrl});
    }
  ], cb);
};

var updateAccount = function(serviceData, cursor, queues, cb) {
  // Retrieve all files since last call
  async.waterfall([
    function refreshTokens(cb) {
      var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.refreshToken_(serviceData.tokens.refresh_token, function(err, tokens) {
        tokens.refresh_token = serviceData.tokens.refresh_token;
        serviceData.tokens = tokens;
        cb(err);
      });
    },
    function getClient(cb) {
      googleapis.discover('drive', 'v2').execute(cb);
    },
    function retrieveChanges(client, cb) {
      var options = {
        maxResults: 1000,
      };

      if(cursor) {
        options.startChangeId = cursor;
      }

      options.includeDeleted = (cursor) ? true : false;

      var oauth2Client = new OAuth2Client(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.credentials = serviceData.tokens;

      retrieveFiles(client, oauth2Client, options, [], cb);
    },
    function applyChanges(newCursor, changes, cb) {
      changes.forEach(function(change) {
        var id = "https://docs.google.com/file/d/" + change.fileId;

        if(change.deleted || (cursor && change.file.labels.trashed)) {
          queues.deletion.push({
            title: change.file.title,
            id: id
          });
        }
        else {
          var download = selectBestDownload(change.file);

          if(download.url && !change.file.labels.trashed && (!change.file.fileSize || change.file.fileSize < config.maxSize * 1024 * 1024)) {
            queues.addition.push({
              title: change.file.title + ((change.file.title.indexOf(download.extension) === -1) ? download.extension : ''),
              downloadUrl: download.url,
              type: download.type,
              date: change.file.createdDate,
              starred: change.file.labels.starred,
              id: id,
              exported: true,
              link: change.file.alternateLink
            });
          }
        }
      });

      cb(null, newCursor, serviceData);
    }
  ], cb);
};

var additionQueueWorker = function(job, cb) {
  console.log("Uploading", job.task.title);
  uploadFile(job.task, job.anyfetchClient, job.serviceData.tokens.access_token, cb);
};

var deletionQueueWorker = function(job, cb) {
  console.log("Deleting", job.task.title);
  deleteFile(job.task, job.anyfetchClient, cb);
};

additionQueueWorker.concurrency = config.maxConcurrency;
deletionQueueWorker.concurrency = config.maxConcurrency;

module.exports = {
  connectFunctions: {
    redirectToService: redirectToService,
    retrieveTokens: retrieveTokens
  },
  updateAccount: updateAccount,
  workers: {
    addition: additionQueueWorker,
    deletion: deletionQueueWorker
  },

  config: config
};
<|endoftext|>


<commit_before>var supertest = require('supertest');
var should = require('should');

var mongoose = require('mongoose');
var config = require('../config');

var Url = require('../urlModel');

mongoose.connect('mongodb://' + config.db.host + '/' + config.db.name, {
  useMongoClient: true,
});

var server = supertest.agent('http://localhost:4000');

describe('url shortning project unit tests', function() {

  it('a get request to homepage should respond with: Welcome to Shortly', function(done) {
    server
    .get('/')
    .expect('Content-type', /text/)
    .expect(200) // THis is HTTP response
    .end(function(err, res) {
      res.status.should.equal(200);
      res.text.should.equal('Welcome to Shortly');
      done();
    });
  });

  it('if a long url is added twice it should generate two different short urls ', function(done) {
    var body = { url: 'www.cloudFlare.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short1 = res.body.shortenedURL.slice(22);

      server
      .post('/api/shorten')
      .send(body)
      .end(function(err, res) {
        var short2 = res.body.shortenedURL.slice(22);
        short2.should.not.equal(short1);
        done();

      });

    });
  });

  it('should persist short url to database ', function(done) {
    var body = { url: 'www.facebook.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short = res.body.shortenedURL.slice(22);
      Url.findOne({short}, function (err, doc) {

      })
      .then(function(doc) {
        doc.long.should.equal(body.url);
      });
      done();

    });
  });

  it('should generate a short url and persist it to db and subsequent get should properly redirect to original long url', function(done) {
    var body = { url: 'www.google.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short = res.body.shortenedURL.slice(22);

      server
      .get('/' + short)
      .expect('Location', body.url)
      .expect(302)
      .end(function(err, res) {
        res.status.should.equal(302);
        res.redirect.should.equal(true);
        done();
      });

    });
  });

  it('should redirect a short url to a long url in under 10ms', function(done) {
    var body = { url: 'www.google.com' };
    var start = new Date();
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var end = new Date();
      var responseTime = end - start;
      responseTime.should.be.within(0, 10);
      done();
    });
  });

});

describe('url shortning project unit tests 2 - testing stats', function() {
  const msToDays = 1000 * 60 * 60 * 24;
  var date = new Date();
  var twoDaysLater = new Date();
  twoDaysLater.setDate(twoDaysLater.getDate() + 2);
  var tenDaysLater = new Date();
  tenDaysLater.setDate(tenDaysLater.getDate() + 10);

  before(function() {

    var newUrl = Url({
      long: 'www.uber.com',
      short: 'B1W2p3aJOb',
      allTime: 0,
      lastSeven: []
    });

    newUrl.save(function(err) {
      if (err) {
        console.log(err);
      }
    });

  });

  it('should return 0 for allTime after short url creation', function(done) {
    var body = { url: 'www.google.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short = res.body.shortenedURL.slice(22);
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(0);
        done();
      });

    });
  });

  it('should return 1 for allTime after short url first use for a testDate value within 24 hours', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/' + short)
    .end(function(err, res) {
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(1);
        done();
      });
    });
  });

  it('should return 1 for last24 after short url first use for a testDate value within 24 hours', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/last24')
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('last24');
      body.results.should.equal(1);
      done();
    });

  });

  it('should return 2 for allTime after short url first use for a testDate value 2days later', function(done) {
    var short = 'B1W2p3aJOb';

    server
    .get('/' + short + '?testDate=' + twoDaysLater)
    .end(function(err, res) {
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(2);
        done();
      });
    });
  });

  it('should return 2 for pastWeek after short url use for a testDate value 2 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/pastWeek' + '?testDate=' + twoDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('pastWeek');
      body.results.should.equal(2);
      done();
    });

  });

  it('should return 1 for last24 after short url use for a testDate value 2 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/last24' + '?testDate=' + twoDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('last24');
      body.results.should.equal(1);
      done();
    });

  });

  it('should return 3 for allTime after short url use for a testDate value 10 days later', function(done) {
    var short = 'B1W2p3aJOb';

    server
    .get('/' + short + '?testDate=' + tenDaysLater)
    .end(function(err, res) {
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(3);
        done();
      });
    });
  });

  it('should return 1 for last24 after short url use for a testDate value 10 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/last24' + '?testDate=' + tenDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('last24');
      body.results.should.equal(1);
      done();
    });

  });

  it('should return 1 for pastWeek after short url use for a testDate value 10 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/pastWeek' + '?testDate=' + tenDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('pastWeek');
      body.results.should.equal(1);
      done();
    });

  });

  after(function() {
    // mongoose.connect('mongodb://' + config.db.host + '/' + config.db.name, function() {
    //   mongoose.connection.db.dropDatabase();
    // });
    Url.collection.drop();
  });

});

<commit_msg>minor typo fix<commit_after>var supertest = require('supertest');
var should = require('should');

var mongoose = require('mongoose');
var config = require('../config');

var Url = require('../urlModel');

mongoose.connect('mongodb://' + config.db.host + '/' + config.db.name, {
  useMongoClient: true,
});

var server = supertest.agent('http://localhost:4000');

describe('url shortning project unit tests', function() {

  it('a get request to homepage should respond with: Welcome to Shortly', function(done) {
    server
    .get('/')
    .expect('Content-type', /text/)
    .expect(200) // THis is HTTP response
    .end(function(err, res) {
      res.status.should.equal(200);
      res.text.should.equal('Welcome to Shortly');
      done();
    });
  });

  it('if a long url is added twice it should generate two different short urls ', function(done) {
    var body = { url: 'www.cloudFlare.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short1 = res.body.shortenedURL.slice(22);

      server
      .post('/api/shorten')
      .send(body)
      .end(function(err, res) {
        var short2 = res.body.shortenedURL.slice(22);
        short2.should.not.equal(short1);
        done();

      });

    });
  });

  it('should persist short url to database ', function(done) {
    var body = { url: 'www.facebook.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short = res.body.shortenedURL.slice(22);
      Url.findOne({short}, function (err, doc) {

      })
      .then(function(doc) {
        doc.long.should.equal(body.url);
      });
      done();

    });
  });

  it('should generate a short url and persist it to db and subsequent get should properly redirect to original long url', function(done) {
    var body = { url: 'www.google.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short = res.body.shortenedURL.slice(22);

      server
      .get('/' + short)
      .expect('Location', body.url)
      .expect(302)
      .end(function(err, res) {
        res.status.should.equal(302);
        res.redirect.should.equal(true);
        done();
      });

    });
  });

  it('should redirect a short url to a long url in under 10ms', function(done) {
    var body = { url: 'www.google.com' };
    var start = new Date();
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var end = new Date();
      var responseTime = end - start;
      responseTime.should.be.within(0, 10);
      done();
    });
  });

});

describe('url shortning project unit tests 2 - testing stats', function() {
  const msToDays = 1000 * 60 * 60 * 24;
  var date = new Date();
  var twoDaysLater = new Date();
  twoDaysLater.setDate(twoDaysLater.getDate() + 2);
  var tenDaysLater = new Date();
  tenDaysLater.setDate(tenDaysLater.getDate() + 10);

  before(function() {

    var newUrl = Url({
      long: 'www.uber.com',
      short: 'B1W2p3aJOb',
      allTime: 0,
      lastSeven: []
    });

    newUrl.save(function(err) {
      if (err) {
        console.log(err);
      }
    });

  });

  it('should return 0 for allTime after short url creation', function(done) {
    var body = { url: 'www.google.com' };
    server
    .post('/api/shorten')
    .send(body)
    .end(function(err, res) {
      var short = res.body.shortenedURL.slice(22);
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(0);
        done();
      });

    });
  });

  it('should return 1 for allTime after short url first use for a testDate value within 24 hours', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/' + short)
    .end(function(err, res) {
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(1);
        done();
      });
    });
  });

  it('should return 1 for last24 after short url first use for a testDate value within 24 hours', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/last24')
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('last24');
      body.results.should.equal(1);
      done();
    });

  });

  it('should return 2 for allTime after short url first use for a testDate value 2days later', function(done) {
    var short = 'B1W2p3aJOb';

    server
    .get('/' + short + '?testDate=' + twoDaysLater)
    .end(function(err, res) {
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(2);
        done();
      });
    });
  });

  it('should return 2 for pastWeek after short url use for a testDate value 2 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/pastWeek' + '?testDate=' + twoDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('pastWeek');
      body.results.should.equal(2);
      done();
    });

  });

  it('should return 1 for last24 after short url use for a testDate value 2 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/last24' + '?testDate=' + twoDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('last24');
      body.results.should.equal(1);
      done();
    });

  });

  it('should return 3 for allTime after short url use for a testDate value 10 days later', function(done) {
    var short = 'B1W2p3aJOb';

    server
    .get('/' + short + '?testDate=' + tenDaysLater)
    .end(function(err, res) {
      server
      .get('/stats/' + short + '/allTime')
      .end(function(err, res) {
        var body = res.body;
        body.should.have.property('results');
        body.should.have.property('statsQuery');
        body.statsQuery.should.equal('allTime');
        body.results.should.equal(3);
        done();
      });
    });
  });

  it('should return 1 for last24 after short url use for a testDate value 10 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/last24' + '?testDate=' + tenDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('last24');
      body.results.should.equal(1);
      done();
    });

  });

  it('should return 1 for pastWeek after short url use for a testDate value 10 days later', function(done) {
    var short = 'B1W2p3aJOb';
    server
    .get('/stats/' + short + '/pastWeek' + '?testDate=' + tenDaysLater)
    .end(function(err, res) {
      var body = res.body;
      body.should.have.property('results');
      body.should.have.property('statsQuery');
      body.statsQuery.should.equal('pastWeek');
      body.results.should.equal(1);
      done();
    });

  });

  after(function() {
    Url.collection.drop();
  });

});

<|endoftext|>


<commit_before>var Module = require('module');
var join = require('path').join;
var debug = require('debug')('injective');

module.exports = exports = Injective;

var injectiveProp = typeof Symbol === 'undefined' ? '@@injective' : Symbol.for('injective');
var typeProp = 'type';
var depsProp = 'deps';
var singletonProp = 'singleton';
var injectProp = 'inject';
var injectDepsProp = 'injectDeps';

function Injective(config, cache) {
    this._config = config || {};
    this._cache = cache || {};
}

Injective.injective = null;

Injective.isInjective = function(module) {
    return injectiveProp in module.exports;
};

Injective.isInjectable = function(module) {
    return Injective.isInjective(module) && injectProp in module.exports[injectiveProp] && typeof module.exports[injectiveProp][injectProp] === 'function';
};

Injective.isInstantiable = function(module) {
    return Injective.isInjective(module) && typeProp in module.exports[injectiveProp];
};

Injective.install = function(config) {
    var extension = '.js';
    Module._extensions[extension] = function(func, module, filename) {
        module.injective = Injective.injective;
        func(module, filename);
        if (Injective.isInjectable(module)) {
            Injective.injective._inject(module, filename);
        }
    }.bind(Module, require.extensions[extension]);
    Injective.injective = new Injective(config);
    return Injective.injective;
};

Injective.prototype.create = function() {
    debug('Creating new context');
    Injective.injective = new Injective(this._config, Object.create(this._cache));
    return Injective.injective;
};

Injective.prototype.define = function(id, obj) {
    debug('Defining instance for ' + id);
    this._cache[id] = obj;
};

/**
 * (Array)
 * (String)
 * (Array, Function)
 * (String, Function)
 */
Injective.prototype.require = function(module, deps, callback) {
    var self = this;
    Injective.injective = this;
    deps = Array.isArray(deps) ? deps : [deps];
    var resolvedDeps = this._resolveDeps(module, deps);

    if (typeof callback === 'function') {
        return callback.apply(null, resolvedDeps);
    }
};

/**
 * Turn require id and its dependencies into instance
 * path path of dep
 * module the module that requiring the dep
 */
Injective.prototype._load = function(module, path) {
    debug('Loading ' + path + ' from module ' + module.id);

    // user-defined object
    if (path in this._cache) {
        debug('Pre-defined instance exists, using cache: ' + path);
        return this._cache[path];
    }

    var filename = Module._resolveFilename(this._resolvePath(path), module);

    debug('Resolved ' + path + ' -> ' + filename);

    // singleton
    if (filename in this._cache) {
        debug('Instance exists, using cache: ' + filename);
        return this._cache[filename];
    }

    // Make sure it is loaded by node and got injected
    var mod = module.require(filename);
    var cachedModule = Module._cache[filename];

    // non-singleton
    if (Injective.isInstantiable(cachedModule)) {
        return this._instantiate(cachedModule, filename);
    }

    debug('Rely on native require() to load: ' + filename);

    return mod;
};

// upgrade path if necessary
Injective.prototype._resolvePath = function(path) {
    if ('bundles' in this._config && path in this._config.bundles) {
        path = this._config.bundles[path];
    }

    if ('paths' in this._config && path in this._config.paths) {
        path = this._config.paths[path];
    }

    if (path[0] === '/') {
        path = join(process.cwd(), path);
    }

    return path;
};

Injective.prototype._resolveDeps = function(module, deps) {
    var self = this;
    return deps.map(function(dep) {
        var resolvedPath = self._resolvePath(dep);

        // Bundles
        if (Array.isArray(resolvedPath)) {
            return resolvedPath.forEach(function(dep) {
                self._load(module, dep);
            });
        }

        return self._load(module, dep);
    });
};

Injective.prototype._inject = function(module, filename) {
    var self = this;
    debug('Injecting dependency into ' + filename);
    var injectiveCfg = module.exports[injectiveProp];
    var resolvedDeps = injectDepsProp in injectiveCfg ? this._resolveDeps(module, injectiveCfg[injectDepsProp]) : [];
    injectiveCfg[injectProp].apply(null, resolvedDeps);
    return module.exports;
};

/**
 * Inject dependency and/or create (singleton) instance
 */
Injective.prototype._instantiate = function(module, filename) {
    debug('Creating new instance for ' + filename);
    var self = this;
    var injectiveCfg = module.exports[injectiveProp];
    var resolvedDeps = depsProp in injectiveCfg ? this._resolveDeps(module, injectiveCfg[depsProp]) : [];
    var instance;
    var type = injectiveCfg[typeProp];

    switch (type) {
        case 'factory':
            instance = module.exports.apply(module.exports, resolvedDeps);
            break;
        case 'constructor':
            instance = new(Function.prototype.bind.apply(module.exports, [null].concat(resolvedDeps)));
            break;
        default:
            throw new Error('Unknown type ' + type + ' defined in ' + filename);
    }

    if (injectiveCfg[singletonProp]) {
        this.define(filename, instance);
    }

    return instance;
};<commit_msg>make return value more meaningful<commit_after>var Module = require('module');
var join = require('path').join;
var debug = require('debug')('injective');

module.exports = exports = Injective;

var injectiveProp = typeof Symbol === 'undefined' ? '@@injective' : Symbol.for('injective');
var typeProp = 'type';
var depsProp = 'deps';
var singletonProp = 'singleton';
var injectProp = 'inject';
var injectDepsProp = 'injectDeps';

function Injective(config, cache) {
    this._config = config || {};
    this._cache = cache || {};
}

Injective.injective = null;

Injective.isInjective = function(module) {
    return injectiveProp in module.exports;
};

Injective.isInjectable = function(module) {
    return Injective.isInjective(module) && injectProp in module.exports[injectiveProp] && typeof module.exports[injectiveProp][injectProp] === 'function';
};

Injective.isInstantiable = function(module) {
    return Injective.isInjective(module) && typeProp in module.exports[injectiveProp];
};

Injective.install = function(config) {
    var extension = '.js';
    Module._extensions[extension] = function(func, module, filename) {
        module.injective = Injective.injective;
        func(module, filename);
        if (Injective.isInjectable(module)) {
            Injective.injective._inject(module, filename);
        }
    }.bind(Module, require.extensions[extension]);
    Injective.injective = new Injective(config);
    return Injective.injective;
};

Injective.prototype.create = function() {
    debug('Creating new context');
    Injective.injective = new Injective(this._config, Object.create(this._cache));
    return Injective.injective;
};

Injective.prototype.define = function(id, obj) {
    debug('Defining instance for ' + id);
    this._cache[id] = obj;
    return this;
};

/**
 * (Module, Array)
 * (Module, String)
 */
Injective.prototype.require = function(module, deps) {
    var self = this;
    Injective.injective = this;
    deps = Array.isArray(deps) ? deps : [deps];
    return this._resolveDeps(module, deps);
};

/**
 * Turn require id and its dependencies into instance
 * path path of dep
 * module the module that requiring the dep
 */
Injective.prototype._load = function(module, path) {
    debug('Loading ' + path + ' from module ' + module.id);

    // user-defined object
    if (path in this._cache) {
        debug('Pre-defined instance exists, using cache: ' + path);
        return this._cache[path];
    }

    var filename = Module._resolveFilename(this._resolvePath(path), module);

    debug('Resolved ' + path + ' -> ' + filename);

    // singleton
    if (filename in this._cache) {
        debug('Instance exists, using cache: ' + filename);
        return this._cache[filename];
    }

    // Make sure it is loaded by node and got injected
    var mod = module.require(filename);
    var cachedModule = Module._cache[filename];

    // non-singleton
    if (Injective.isInstantiable(cachedModule)) {
        return this._instantiate(cachedModule, filename);
    }

    debug('Rely on native require() to load: ' + filename);

    return mod;
};

// upgrade path if necessary
Injective.prototype._resolvePath = function(path) {
    if ('bundles' in this._config && path in this._config.bundles) {
        path = this._config.bundles[path];
    }

    if ('paths' in this._config && path in this._config.paths) {
        path = this._config.paths[path];
    }

    if (path[0] === '/') {
        path = join(process.cwd(), path);
    }

    return path;
};

Injective.prototype._resolveDeps = function(module, deps) {
    var self = this;
    return deps.map(function(dep) {
        var resolvedPath = self._resolvePath(dep);

        // Bundles
        if (Array.isArray(resolvedPath)) {
            return resolvedPath.forEach(function(dep) {
                self._load(module, dep);
            });
        }

        return self._load(module, dep);
    });
};

Injective.prototype._inject = function(module, filename) {
    var self = this;
    debug('Injecting dependency into ' + filename);
    var injectiveCfg = module.exports[injectiveProp];
    var resolvedDeps = injectDepsProp in injectiveCfg ? this._resolveDeps(module, injectiveCfg[injectDepsProp]) : [];
    injectiveCfg[injectProp].apply(null, resolvedDeps);
    return module.exports;
};

/**
 * Inject dependency and/or create (singleton) instance
 */
Injective.prototype._instantiate = function(module, filename) {
    debug('Creating new instance for ' + filename);
    var self = this;
    var injectiveCfg = module.exports[injectiveProp];
    var resolvedDeps = depsProp in injectiveCfg ? this._resolveDeps(module, injectiveCfg[depsProp]) : [];
    var instance;
    var type = injectiveCfg[typeProp];

    switch (type) {
        case 'factory':
            instance = module.exports.apply(module.exports, resolvedDeps);
            break;
        case 'constructor':
            instance = new(Function.prototype.bind.apply(module.exports, [null].concat(resolvedDeps)));
            break;
        default:
            throw new Error('Unknown type ' + type + ' defined in ' + filename);
    }

    if (injectiveCfg[singletonProp]) {
        this.define(filename, instance);
    }

    return instance;
};<|endoftext|>


<commit_before>'use strict';

import fs from 'fs';
import http from 'http';
import path from 'path';
import finalhandler from 'finalhandler';
import serveStatic from 'serve-static';
import {Promise as Bluebird} from 'bluebird';
import getPort from 'get-port';
import test from 'ava';
import resolver from '..';

const readFile = Bluebird.promisify(fs.readFile);

// Start fresh server before tests
test.beforeEach(async t => {
  const base = path.join(__dirname, 'fixtures');
  const serve = serveStatic(base);
  const port = await getPort();
  const server = http.createServer((req, res) =>
    serve(req, res, finalhandler(req, res))
  );

  server.listen(port);

  t.context.port = port;
  t.context.server = server;
});

// Stop server in any case
test.afterEach.cb(t => {
  t.context.server.close(t.end);
});

test('should fail on wrong url', async t => {
  const error = await t.throwsAsync(async () => {
    await resolver.getResource('blank.gif', {
      base: ['//localhost/']
    });
  }, Error);

  t.regex(error.message, /.*blank\.gif.*/);
});

test('should find the file by url', async t => {
  const expected = await readFile(path.join(__dirname, 'fixtures/blank.gif'));
  const res = await resolver.getResource('blank.gif', {
    base: ['//localhost:' + t.context.port + '/', 'fixture']
  });

  t.is(res.contents.toString(), expected.toString());
  t.is(res.path, 'http://localhost:' + t.context.port + '/blank.gif');
  t.is(res.mime, 'image/gif');
});

test('should find the file by file', async t => {
  const expected = await readFile(path.join(__dirname, 'fixtures/check.svg'));
  const res = await resolver.getResource('check.svg', {
    base: ['//localhost:' + t.context.port + '/test/', 'test/fixtures']
  });

  t.is(res.contents.toString(), expected.toString());
  t.is(res.path, path.join('test', 'fixtures', 'check.svg'));
  t.is(res.mime, 'image/svg+xml');
});

test('should find the file by glob', async t => {
  const expected = await readFile(path.join(__dirname, 'fixtures/check.svg'));
  const res = await resolver.getResource('check.svg', {
    base: [path.join(__dirname, '/*/')]
  });

  t.is(res.contents.toString(), expected.toString());
  t.is(res.path, path.join(__dirname, 'fixtures', 'check.svg'));
  t.is(res.mime, 'image/svg+xml');
});

test('should use consider sync filter', async t => {
  const base = ['//localhost:' + t.context.port + '/'];
  const filter = resource => {
    return (
      resource.path !== 'http://localhost:' + t.context.port + '/blank.gif' ||
      resource.mime !== 'image/gif'
    );
  };

  const error = await t.throwsAsync(async () => {
    await resolver.getResource('blank.gif', {base, filter});
  }, Error);

  t.regex(error.message, /blank\.gif.*could not be resolved/);
  t.regex(error.message, /.*rejected by filter/);
});

test('should use consider async filter returning a promise', async t => {
  const base = ['//localhost/', path.join(__dirname, 'fixtures')];
  const filter = () => {
    return new Bluebird((resolve, reject) => {
      setTimeout(() => {
        reject(new Error('FINE'));
      }, 1000);
    });
  };

  const error = await t.throwsAsync(async () => {
    await resolver.getResource('check.svg', {base, filter});
  }, Error);

  t.regex(error.message, /check\.svg.*could not be resolved/);
});
<commit_msg>test.js: use `util.promisify` (#229)<commit_after>'use strict';

import fs from 'fs';
import http from 'http';
import path from 'path';
import {promisify} from 'util';
import finalhandler from 'finalhandler';
import serveStatic from 'serve-static';
import {Promise as Bluebird} from 'bluebird';
import getPort from 'get-port';
import test from 'ava';
import resolver from '..';

const readFile = promisify(fs.readFile);

// Start fresh server before tests
test.beforeEach(async t => {
  const base = path.join(__dirname, 'fixtures');
  const serve = serveStatic(base);
  const port = await getPort();
  const server = http.createServer((req, res) =>
    serve(req, res, finalhandler(req, res))
  );

  server.listen(port);

  t.context.port = port;
  t.context.server = server;
});

// Stop server in any case
test.afterEach.cb(t => {
  t.context.server.close(t.end);
});

test('should fail on wrong url', async t => {
  const error = await t.throwsAsync(async () => {
    await resolver.getResource('blank.gif', {
      base: ['//localhost/']
    });
  }, Error);

  t.regex(error.message, /.*blank\.gif.*/);
});

test('should find the file by url', async t => {
  const expected = await readFile(path.join(__dirname, 'fixtures/blank.gif'));
  const res = await resolver.getResource('blank.gif', {
    base: ['//localhost:' + t.context.port + '/', 'fixture']
  });

  t.is(res.contents.toString(), expected.toString());
  t.is(res.path, 'http://localhost:' + t.context.port + '/blank.gif');
  t.is(res.mime, 'image/gif');
});

test('should find the file by file', async t => {
  const expected = await readFile(path.join(__dirname, 'fixtures/check.svg'));
  const res = await resolver.getResource('check.svg', {
    base: ['//localhost:' + t.context.port + '/test/', 'test/fixtures']
  });

  t.is(res.contents.toString(), expected.toString());
  t.is(res.path, path.join('test', 'fixtures', 'check.svg'));
  t.is(res.mime, 'image/svg+xml');
});

test('should find the file by glob', async t => {
  const expected = await readFile(path.join(__dirname, 'fixtures/check.svg'));
  const res = await resolver.getResource('check.svg', {
    base: [path.join(__dirname, '/*/')]
  });

  t.is(res.contents.toString(), expected.toString());
  t.is(res.path, path.join(__dirname, 'fixtures', 'check.svg'));
  t.is(res.mime, 'image/svg+xml');
});

test('should use consider sync filter', async t => {
  const base = ['//localhost:' + t.context.port + '/'];
  const filter = resource => {
    return (
      resource.path !== 'http://localhost:' + t.context.port + '/blank.gif' ||
      resource.mime !== 'image/gif'
    );
  };

  const error = await t.throwsAsync(async () => {
    await resolver.getResource('blank.gif', {base, filter});
  }, Error);

  t.regex(error.message, /blank\.gif.*could not be resolved/);
  t.regex(error.message, /.*rejected by filter/);
});

test('should use consider async filter returning a promise', async t => {
  const base = ['//localhost/', path.join(__dirname, 'fixtures')];
  const filter = () => {
    return new Bluebird((resolve, reject) => {
      setTimeout(() => {
        reject(new Error('FINE'));
      }, 1000);
    });
  };

  const error = await t.throwsAsync(async () => {
    await resolver.getResource('check.svg', {base, filter});
  }, Error);

  t.regex(error.message, /check\.svg.*could not be resolved/);
});
<|endoftext|>


<commit_before>// gridform

/**
 * Module dependencies
 */

var gridstream = require('gridfs-stream');
var formidable = require('formidable');
var File = require('./file');

/**
 * Expose
 */

module.exports = exports = gridform;
exports.File = File;
exports.gridfsStream = gridstream;

/**
 * gridform
 *
 * @param {Object} options
 * @return {formidable.IncomingForm}
 */

function gridform (options) {
  options || (options = {});

  var db = options.db || (options.db = exports.db);
  if (!db) throw new Error('missing db');
  delete options.db;

  var mongo = options.mongo || (options.mongo = exports.mongo);
  if (!mongo) throw new Error('missing mongodb native driver');
  delete options.mongo;

  var filename = options.filename || (options.filename = exports.filename || ƒ);
  delete options.filename;

  var form = new formidable.IncomingForm;
  form.__gridstream = gridstream(db, mongo);
  form.__filename = filename;
  form.onPart = onPart;
  return form;
}

/**
 * onPart
 *
 * @param {formidable Part} part
 * @api private
 * @ignore
 */

function onPart (part) {
  var form = this;

  if (undefined === part.filename) return form.handlePart(part);

  ++form._flushing;

  var file = new File(part.filename, form.__filename(part.filename), part.mime);

  form.emit('fileBegin', part.name, file);

  var options = { mode: 'w', content_type: file.type };
  if (form.chunk_size) options.chunk_size = form.chunk_size;
  if (form.root) options.root = form.root;
  options.metadata = file.metadata ? file.metadata
                   : form.metadata ? form.metadata
                   : undefined
  var ws = form.__gridstream.createWriteStream(file.path, options);

  ws.on('progress', onprogress);
  ws.on('drain', resume);
  ws.once('error', done);
  part.on('data', onData);
  part.once('end', onEnd);

  function onprogress (size) {
    file.lastModified = new Date;
    file.size = size;
    file.emit('progress', size);
  }

  function resume () {
    form.resume();
  };

  function onData (data) {
    form.pause();
    ws.write(data);
  };

  function onEnd () {
    part.removeListener('data', onData);
    part.removeListener('end', onEnd);
    ws.once('close', done);
    ws.end();
  };

  function done (err) {
    if (done.err) return;
    if (err) return form.emit('error', done.err = err);

    ws.removeListener('progress', onprogress);
    ws.removeListener('drain', resume);
    ws.removeListener('error', done);

    file.id || (file.id = ws._store.fileId);
    file.root = ws._store.root;
    file.size = ws._store.position;
    file.emit('end');

    --form._flushing;

    form.emit('file', part.name, file);
    form._maybeEnd();
  }
}

/**
 * @api private
 */

function ƒ (v) {
  return v;
}

<commit_msg>fixed; writeStream!close arg handling<commit_after>// gridform

/**
 * Module dependencies
 */

var gridstream = require('gridfs-stream');
var formidable = require('formidable');
var File = require('./file');

/**
 * Expose
 */

module.exports = exports = gridform;
exports.File = File;
exports.gridfsStream = gridstream;

/**
 * gridform
 *
 * @param {Object} options
 * @return {formidable.IncomingForm}
 */

function gridform (options) {
  options || (options = {});

  var db = options.db || (options.db = exports.db);
  if (!db) throw new Error('missing db');
  delete options.db;

  var mongo = options.mongo || (options.mongo = exports.mongo);
  if (!mongo) throw new Error('missing mongodb native driver');
  delete options.mongo;

  var filename = options.filename || (options.filename = exports.filename || ƒ);
  delete options.filename;

  var form = new formidable.IncomingForm;
  form.__gridstream = gridstream(db, mongo);
  form.__filename = filename;
  form.onPart = onPart;
  return form;
}

/**
 * onPart
 *
 * @param {formidable Part} part
 * @api private
 * @ignore
 */

function onPart (part) {
  var form = this;

  if (undefined === part.filename) return form.handlePart(part);

  ++form._flushing;

  var file = new File(part.filename, form.__filename(part.filename), part.mime);

  form.emit('fileBegin', part.name, file);

  var options = { mode: 'w', content_type: file.type };
  if (form.chunk_size) options.chunk_size = form.chunk_size;
  if (form.root) options.root = form.root;
  options.metadata = file.metadata ? file.metadata
                   : form.metadata ? form.metadata
                   : undefined
  var ws = form.__gridstream.createWriteStream(file.path, options);

  ws.on('progress', onprogress);
  ws.on('drain', resume);
  ws.once('error', done);
  part.on('data', onData);
  part.once('end', onEnd);

  function onprogress (size) {
    file.lastModified = new Date;
    file.size = size;
    file.emit('progress', size);
  }

  function resume () {
    form.resume();
  };

  function onData (data) {
    form.pause();
    ws.write(data);
  };

  function onEnd () {
    part.removeListener('data', onData);
    part.removeListener('end', onEnd);
    ws.once('close', function (_) {
      done();
    });
    ws.end();
  };

  function done (err) {
    if (done.err) return;
    if (err) return form.emit('error', done.err = err);

    ws.removeListener('progress', onprogress);
    ws.removeListener('drain', resume);
    ws.removeListener('error', done);

    file.id || (file.id = ws._store.fileId);
    file.root = ws._store.root;
    file.size = ws._store.position;
    file.emit('end');

    --form._flushing;

    form.emit('file', part.name, file);
    form._maybeEnd();
  }
}

/**
 * @api private
 */

function ƒ (v) {
  return v;
}

<|endoftext|>


<commit_before>#!/usr/bin/env node

const Ajv = require('ajv');
const strictDeepEquals = require('deep-equal');
const fs = require("fs");
const _ = require("lodash");
const path = require("path");
const shell = require("shelljs");
const deepEquals = require("./deepEquals");
const Main = require("../output/Main");
const Samples = require("../output/Samples");
const assert = require("assert");
const { inParallel } = require("./multicore");
const os = require("os");
const exit = require('exit');

//////////////////////////////////////
// Constants
/////////////////////////////////////

function debug(x) {
    if (!process.env.DEBUG) return;
    console.log(x);
    return x;
}

const IS_CI = process.env.CI === "true";
const BRANCH = process.env.TRAVIS_BRANCH;
const IS_BLESSED = ["master"].indexOf(BRANCH) !== -1;
const IS_PUSH = process.env.TRAVIS_EVENT_TYPE === "push";
const IS_PR = process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== "false";
const DEBUG = typeof process.env.DEBUG !== 'undefined';

const CPUs = IS_CI
    ? 2 /* Travis has only 2 but reports 8 */
    : process.env.CPUs || os.cpus().length;

const QUICKTYPE_CLI = path.resolve("./cli/quicktype.js");

const NODE_BIN = path.resolve("./node_modules/.bin");
process.env.PATH += `:${NODE_BIN}`;

//////////////////////////////////////
// Fixtures
/////////////////////////////////////

const FIXTURES = [
    {
        name: "csharp",
        base: "test/csharp",
        setup: "dotnet restore",
        diffViaSchema: false,
        output: "QuickType.cs",
        test: testCSharp
    },
    {
        name: "golang",
        base: "test/golang",
        diffViaSchema: true,
        output: "quicktype.go",
        test: testGo
    },
    {
        name: "json-schema",
        base: "test/golang",
        diffViaSchema: false,
        output: "schema.json",
        test: testJsonSchema
    },
    {
        name: "elm",
        base: "test/elm",
        setup: IS_CI
                ? "./setup-ci.sh"
                : "rm -rf elm-stuff/build-artifacts && elm-make --yes",
        diffViaSchema: false,
        output: "QuickType.elm",
        test: testElm
    }
].filter(({name}) => !process.env.FIXTURE || name === process.env.FIXTURE);

//////////////////////////////////////
// Go tests
/////////////////////////////////////

const knownUnicodeFails = ["identifiers.json"];
const unicodeWillFail = (sample) => knownUnicodeFails.indexOf(path.basename(sample)) !== -1;

function testGo(sample) {
    if (unicodeWillFail(sample)) {
        console.error(`Skipping golang ${sample} – known to fail`);
        return;
    }

    compareJsonFileToJson({
        expectedFile: sample,
        jsonCommand: `go run main.go quicktype.go < "${sample}"`,
        strict: false
    });
}

//////////////////////////////////////
// C# tests
/////////////////////////////////////

function testCSharp(sample) {
    compareJsonFileToJson({
        expectedFile: sample,
        jsonCommand: `dotnet run "${sample}"`,
        strict: false
    });
}

//////////////////////////////////////
// Elm tests
/////////////////////////////////////

function testElm(sample) {
    if (unicodeWillFail(sample)) {
        console.error(`Skipping elm ${sample} – known to fail`);
        return;
    }

    let limit_cpus = IS_CI ? "$TRAVIS_BUILD_DIR/sysconfcpus/bin/sysconfcpus -n 2" : "";
    exec(`${limit_cpus} elm-make Main.elm QuickType.elm --output elm.js`, {silent: true});

    compareJsonFileToJson({
        expectedFile: sample,
        jsonCommand: `node ./runner.js "${sample}"`,
        strict: false
    });
}

//////////////////////////////////////
// JSON Schema tests
/////////////////////////////////////

function testJsonSchema(sample) {
    let input = JSON.parse(fs.readFileSync(sample));
    let schema = JSON.parse(fs.readFileSync("schema.json"));

    let ajv = new Ajv();
    let valid = ajv.validate(schema, input);
    if (!valid) {
        failWith({
            sample,
            error: "Generated schema does not validate input JSON.",
        });
    }

    // Generate Go from the schema
    exec(`quicktype --srcLang json-schema -o quicktype.go --src schema.json`);

    // Possibly check the output of the Go program against the sample
    if (unicodeWillFail(sample)) {
        console.error("Known to fail - not checking output.");
    } else {
        // Parse the sample with Go generated from its schema, and compare to the sample
        compareJsonFileToJson({
            expectedFile: sample,
            jsonCommand: `go run main.go quicktype.go < "${sample}"`,
            strict: false
        });
    }

    // Generate a schema from the schema, making sure the schemas are the same
    compareJsonFileToJson({
        expectedFile: "schema.json",
        jsonCommand: `quicktype --srcLang json-schema --src schema.json --lang json`,
        strict: true
    });
}

//////////////////////////////////////
// Test driver
/////////////////////////////////////

function failWith(obj) {
    obj.cwd = process.cwd();
    console.error(JSON.stringify(obj, null, "  "));
    throw obj;
}

function exec(s, opts, cb) {
    // Disable silent when DEBUG
    opts = opts || {};
    opts.silent = !DEBUG && opts.silent;

    // We special-case quicktype execution
    s = s.replace(/^quicktype /, `node ${QUICKTYPE_CLI} `);

    debug(s);

    let result = shell.exec(s, opts, cb);
    if (result.code !== 0) {
        console.error(result.stdout);
        console.error(result.stderr);
        failWith({
            command: s,
            code: result.code
        });
    }
    return result;
}

function compareJsonFileToJson({expectedFile, jsonFile, jsonCommand, strict}) {
    debug({expectedFile, jsonFile, jsonCommand, strict});

    let jsonString = jsonFile
        ? fs.readFileSync(jsonFile)
        : exec(jsonCommand, {silent: true}).stdout;

    debug({ jsonString });

    let givenJSON = JSON.parse(jsonString);
    let expectedJSON = JSON.parse(fs.readFileSync(expectedFile));

    let jsonAreEqual = strict
        ? strictDeepEquals(givenJSON, expectedJSON)
        : deepEquals(expectedJSON, givenJSON, []);

    if (!jsonAreEqual) {
        console.error("Error: Output is not equivalent to input.");
        failWith({
            expectedFile,
            jsonCommand,
            jsonFile
        });
    }
}

function inDir(dir, work) {
    let origin = process.cwd();

    debug(`cd ${dir}`)
    process.chdir(dir);

    work();
    process.chdir(origin);
}

function runFixtureWithSample(fixture, sample) {
    let tmp = path.resolve(os.tmpdir(), require("crypto").randomBytes(8).toString('hex'));
    let sampleAbs = path.resolve(sample);

    let stats = fs.statSync(sampleAbs);
    if (stats.size > 32 * 1024 * 1024) {
        console.error(`* Skipping ${sampleAbs} because it's too large`);
        return;
    }

    shell.cp("-R", fixture.base, tmp);

    inDir(tmp, () => {
        // Generate code from the sample
        exec(`quicktype --src ${sampleAbs} --srcLang json -o ${fixture.output}`);

        fixture.test(sampleAbs);

        if (fixture.diffViaSchema) {
            debug("* Diffing with code generated via JSON Schema");
            // Make a schema
            exec(`quicktype --src ${sampleAbs} --srcLang json -o schema.json`);
            // Quicktype from the schema and compare to expected code
            shell.mv(fixture.output, `${fixture.output}.expected`);
            exec(`quicktype --src schema.json --srcLang json-schema -o ${fixture.output}`);

            // Compare fixture.output to fixture.output.expected
            try {
                exec(`diff -Naur ${fixture.output}.expected ${fixture.output}`);
            } catch ({ command }) {
                // FIXME: Set this to fail once we have it working.  See issue #59.
                console.error(`Command failed, but we're allowing it: ${command}`);
            }
        }
    });

    shell.rm("-rf", tmp);
}

function testAll(samples) {
    // Get an array of all { sample, fixtureName } objects we'll run
    let tests =  _
        .chain(FIXTURES)
        .flatMap((fixture) => samples.map((sample) => {
            return { sample, fixtureName: fixture.name };
        }))
        .shuffle()
        .value();

    inParallel({
        queue: tests,
        workers: CPUs,
        setup: () => {
            FIXTURES.forEach(({ name, base, setup }) => {
                if (!setup) return;
                console.error(`* Setting up ${name} fixture`);
                inDir(base, () => exec(setup, { silent: true }));
            });
        },
        work: ({ sample, fixtureName }, i) => {
            console.error(`* [${i+1}/${tests.length}] ${fixtureName} ${sample}`);

            let fixture = _.find(FIXTURES, { name: fixtureName });
            try {
                runFixtureWithSample(fixture, sample);
            } catch (e) {
                console.error(e);
                console.trace();
                exit(1);
            }
        }
    });
}

function testsInDir(dir) {
    return shell.ls(`${dir}/*.json`);
}

function main(sources) {
    if (sources.length == 0) {
        sources = testsInDir("test/inputs/json");
    }

    if (IS_CI && !IS_PR && !IS_BLESSED) {
        // Run just a few random samples on low-priority CI branches
        sources = _.chain(sources).shuffle().take(3).value();
    }

    if (sources.length == 1 && fs.lstatSync(sources[0]).isDirectory()) {
        sources = testsInDir(sources[0]);
    }

    testAll(sources);
}

// skip 2 `node` args
main(process.argv.slice(2));
<commit_msg>Attempt to skip CI tests when only webapp changed<commit_after>#!/usr/bin/env node

const Ajv = require('ajv');
const strictDeepEquals = require('deep-equal');
const fs = require("fs");
const _ = require("lodash");
const path = require("path");
const shell = require("shelljs");
const deepEquals = require("./deepEquals");
const Main = require("../output/Main");
const Samples = require("../output/Samples");
const assert = require("assert");
const { inParallel } = require("./multicore");
const os = require("os");
const exit = require('exit');

//////////////////////////////////////
// Constants
/////////////////////////////////////

function debug(x) {
    if (!process.env.DEBUG) return;
    console.log(x);
    return x;
}

const IS_CI = process.env.CI === "true";
const BRANCH = process.env.TRAVIS_BRANCH;
const IS_BLESSED = ["master"].indexOf(BRANCH) !== -1;
const IS_PUSH = process.env.TRAVIS_EVENT_TYPE === "push";
const IS_PR = process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== "false";
const DEBUG = typeof process.env.DEBUG !== 'undefined';

const CPUs = IS_CI
    ? 2 /* Travis has only 2 but reports 8 */
    : process.env.CPUs || os.cpus().length;

const QUICKTYPE_CLI = path.resolve("./cli/quicktype.js");

const NODE_BIN = path.resolve("./node_modules/.bin");
process.env.PATH += `:${NODE_BIN}`;

//////////////////////////////////////
// Fixtures
/////////////////////////////////////

const FIXTURES = [
    {
        name: "csharp",
        base: "test/csharp",
        setup: "dotnet restore",
        diffViaSchema: false,
        output: "QuickType.cs",
        test: testCSharp
    },
    {
        name: "golang",
        base: "test/golang",
        diffViaSchema: true,
        output: "quicktype.go",
        test: testGo
    },
    {
        name: "json-schema",
        base: "test/golang",
        diffViaSchema: false,
        output: "schema.json",
        test: testJsonSchema
    },
    {
        name: "elm",
        base: "test/elm",
        setup: IS_CI
                ? "./setup-ci.sh"
                : "rm -rf elm-stuff/build-artifacts && elm-make --yes",
        diffViaSchema: false,
        output: "QuickType.elm",
        test: testElm
    }
].filter(({name}) => !process.env.FIXTURE || name === process.env.FIXTURE);

//////////////////////////////////////
// Go tests
/////////////////////////////////////

const knownUnicodeFails = ["identifiers.json"];
const unicodeWillFail = (sample) => knownUnicodeFails.indexOf(path.basename(sample)) !== -1;

function testGo(sample) {
    if (unicodeWillFail(sample)) {
        console.error(`Skipping golang ${sample} – known to fail`);
        return;
    }

    compareJsonFileToJson({
        expectedFile: sample,
        jsonCommand: `go run main.go quicktype.go < "${sample}"`,
        strict: false
    });
}

//////////////////////////////////////
// C# tests
/////////////////////////////////////

function testCSharp(sample) {
    compareJsonFileToJson({
        expectedFile: sample,
        jsonCommand: `dotnet run "${sample}"`,
        strict: false
    });
}

//////////////////////////////////////
// Elm tests
/////////////////////////////////////

function testElm(sample) {
    if (unicodeWillFail(sample)) {
        console.error(`Skipping elm ${sample} – known to fail`);
        return;
    }

    let limit_cpus = IS_CI ? "$TRAVIS_BUILD_DIR/sysconfcpus/bin/sysconfcpus -n 2" : "";
    exec(`${limit_cpus} elm-make Main.elm QuickType.elm --output elm.js`, {silent: true});

    compareJsonFileToJson({
        expectedFile: sample,
        jsonCommand: `node ./runner.js "${sample}"`,
        strict: false
    });
}

//////////////////////////////////////
// JSON Schema tests
/////////////////////////////////////

function testJsonSchema(sample) {
    let input = JSON.parse(fs.readFileSync(sample));
    let schema = JSON.parse(fs.readFileSync("schema.json"));

    let ajv = new Ajv();
    let valid = ajv.validate(schema, input);
    if (!valid) {
        failWith({
            sample,
            error: "Generated schema does not validate input JSON.",
        });
    }

    // Generate Go from the schema
    exec(`quicktype --srcLang json-schema -o quicktype.go --src schema.json`);

    // Possibly check the output of the Go program against the sample
    if (unicodeWillFail(sample)) {
        console.error("Known to fail - not checking output.");
    } else {
        // Parse the sample with Go generated from its schema, and compare to the sample
        compareJsonFileToJson({
            expectedFile: sample,
            jsonCommand: `go run main.go quicktype.go < "${sample}"`,
            strict: false
        });
    }

    // Generate a schema from the schema, making sure the schemas are the same
    compareJsonFileToJson({
        expectedFile: "schema.json",
        jsonCommand: `quicktype --srcLang json-schema --src schema.json --lang json`,
        strict: true
    });
}

//////////////////////////////////////
// Test driver
/////////////////////////////////////

function failWith(obj) {
    obj.cwd = process.cwd();
    console.error(JSON.stringify(obj, null, "  "));
    throw obj;
}

function exec(s, opts, cb) {
    // Disable silent when DEBUG
    opts = opts || {};
    opts.silent = !DEBUG && opts.silent;

    // We special-case quicktype execution
    s = s.replace(/^quicktype /, `node ${QUICKTYPE_CLI} `);

    debug(s);

    let result = shell.exec(s, opts, cb);
    if (result.code !== 0) {
        console.error(result.stdout);
        console.error(result.stderr);
        failWith({
            command: s,
            code: result.code
        });
    }
    return result;
}

function compareJsonFileToJson({expectedFile, jsonFile, jsonCommand, strict}) {
    debug({expectedFile, jsonFile, jsonCommand, strict});

    let jsonString = jsonFile
        ? fs.readFileSync(jsonFile)
        : exec(jsonCommand, {silent: true}).stdout;

    debug({ jsonString });

    let givenJSON = JSON.parse(jsonString);
    let expectedJSON = JSON.parse(fs.readFileSync(expectedFile));

    let jsonAreEqual = strict
        ? strictDeepEquals(givenJSON, expectedJSON)
        : deepEquals(expectedJSON, givenJSON, []);

    if (!jsonAreEqual) {
        console.error("Error: Output is not equivalent to input.");
        failWith({
            expectedFile,
            jsonCommand,
            jsonFile
        });
    }
}

function inDir(dir, work) {
    let origin = process.cwd();

    debug(`cd ${dir}`)
    process.chdir(dir);

    work();
    process.chdir(origin);
}

function runFixtureWithSample(fixture, sample) {
    let tmp = path.resolve(os.tmpdir(), require("crypto").randomBytes(8).toString('hex'));
    let sampleAbs = path.resolve(sample);

    let stats = fs.statSync(sampleAbs);
    if (stats.size > 32 * 1024 * 1024) {
        console.error(`* Skipping ${sampleAbs} because it's too large`);
        return;
    }

    shell.cp("-R", fixture.base, tmp);

    inDir(tmp, () => {
        // Generate code from the sample
        exec(`quicktype --src ${sampleAbs} --srcLang json -o ${fixture.output}`);

        fixture.test(sampleAbs);

        if (fixture.diffViaSchema) {
            debug("* Diffing with code generated via JSON Schema");
            // Make a schema
            exec(`quicktype --src ${sampleAbs} --srcLang json -o schema.json`);
            // Quicktype from the schema and compare to expected code
            shell.mv(fixture.output, `${fixture.output}.expected`);
            exec(`quicktype --src schema.json --srcLang json-schema -o ${fixture.output}`);

            // Compare fixture.output to fixture.output.expected
            try {
                exec(`diff -Naur ${fixture.output}.expected ${fixture.output}`);
            } catch ({ command }) {
                // FIXME: Set this to fail once we have it working.  See issue #59.
                console.error(`Command failed, but we're allowing it: ${command}`);
            }
        }
    });

    shell.rm("-rf", tmp);
}

function testAll(samples) {
    // Get an array of all { sample, fixtureName } objects we'll run
    let tests =  _
        .chain(FIXTURES)
        .flatMap((fixture) => samples.map((sample) => {
            return { sample, fixtureName: fixture.name };
        }))
        .shuffle()
        .value();

    inParallel({
        queue: tests,
        workers: CPUs,
        setup: () => {
            FIXTURES.forEach(({ name, base, setup }) => {
                if (!setup) return;
                console.error(`* Setting up ${name} fixture`);
                inDir(base, () => exec(setup, { silent: true }));
            });
        },
        work: ({ sample, fixtureName }, i) => {
            console.error(`* [${i+1}/${tests.length}] ${fixtureName} ${sample}`);

            let fixture = _.find(FIXTURES, { name: fixtureName });
            try {
                runFixtureWithSample(fixture, sample);
            } catch (e) {
                console.error(e);
                console.trace();
                exit(1);
            }
        }
    });
}

function testsInDir(dir) {
    return shell.ls(`${dir}/*.json`);
}

function main(sources) {
    if (IS_CI && process.env.TRAVIS_COMMIT_RANGE) {
        let changed = exec("git diff --name-only $TRAVIS_COMMIT_RANGE").split("\n");
        let onlyWebAppChanged = _.every(changed, (file) => file.startsWith("app/"));
        if (onlyWebAppChanged) {
            console.error(`Only app/ paths changed; skipping tests.`);
            return;
        } else {
            console.error(`Other paths changed; not skipping tests.`);
            return;
        }
    }

    if (sources.length == 0) {
        sources = testsInDir("test/inputs/json");
    }

    if (IS_CI && !IS_PR && !IS_BLESSED) {
        // Run just a few random samples on low-priority CI branches
        sources = _.chain(sources).shuffle().take(3).value();
    }

    if (sources.length == 1 && fs.lstatSync(sources[0]).isDirectory()) {
        sources = testsInDir(sources[0]);
    }

    testAll(sources);
}

// skip 2 `node` args
main(process.argv.slice(2));
<|endoftext|>


<commit_before>var exec, extractRaw, os, parseApk, parseOutput;

os = require('os');

exec = require('child_process').execFile;

parseApk = function(filename, cb) {
  return exec("" + __dirname + "/../tools/aapt", ['l', '-a', filename], {
    maxBuffer: 1024 * 1024
  }, function(err, out) {
    if (err) {
      return cb(err);
    }
    return parseOutput(out, cb);
  });
};

extractRaw = function(string) {
  var parts, sep, value;
  sep = '" (Raw: "';
  parts = string.split(sep);
  value = parts.slice(0, parts.length / 2).join(sep);
  return value.substring(1);
};

parseOutput = function(text, cb) {
  var depth, element, inManifest, indent, input, line, lines, matches, name, parent, parts, rest, result, stack, type, value, _i, _len;
  if (!text) {
    return cb(new Error('No input!'));
  }
  lines = text.split('\n');
  result = {};
  stack = [result];
  inManifest = false;
  for (_i = 0, _len = lines.length; _i < _len; _i++) {
    line = lines[_i];
    if (line.trim() === 'Android manifest:') {
      inManifest = true;
      continue;
    }
    if (!inManifest) {
      continue;
    }
    if (line.trim() === '') {
      continue;
    }
    if (line.match(/^N:/)) {
      continue;
    }
    matches = line.match(/^( +)(A|E): ([\w:\-]+)(.*)$/);
    if (!matches) {
      return cb(new Error('Parse failure: ' + line));
    }
    input = matches[0], indent = matches[1], type = matches[2], name = matches[3], rest = matches[4];
    depth = indent.length / 2;
    parent = stack[depth - 1];
    if (type === 'E') {
      element = {};
      while (stack.length > depth) {
        stack.pop();
      }
      if (depth === stack.length) {
        stack.push(element);
      }
      if (!parent[name]) {
        parent[name] = [];
      }
      parent[name].push(element);
    } else if (type === 'A') {
      value = null;
      if (rest.substring(0, 2) === '="') {
        value = extractRaw(rest.substring(1));
      } else if (rest.substring(0, 12) === '=(type 0x12)') {
        value = rest[14] === '1';
      } else {
        parts = rest.match(/^\(0x[0-9a-f]+\)\=(.*)$/);
        if (!parts) {
          return cb(new Error('Cannot parse value: ' + rest));
        }
        if (parts[1][0] === '"') {
          value = extractRaw(parts[1]);
        } else {
          if (parts[1].substring(0, 11) === '(type 0x10)') {
            value = parseInt(parts[1].substring(13), 16);
          } else {
            value = parts[1];
          }
        }
      }
      parent['@' + name] = value;
    } else {
      return cb(new Error('Unknown type: ' + type));
    }
  }
  return cb(null, result);
};

parseApk.parseOutput = parseOutput;

module.exports = parseApk;
<commit_msg>add maxBuffer configuration<commit_after>var exec, extractRaw, os, parseApk, parseOutput;

os = require('os');

exec = require('child_process').execFile;

parseApk = function (filename, maxBuffer, cb) {
  'use strict'

  if (typeof (maxBuffer) == 'function') {
    maxBuffer = 1024 * 1024;
    cb = maxBuffer;
  }
  return exec("" + __dirname + "/../tools/aapt", ['l', '-a', filename], {
    maxBuffer: maxBuffer
  }, function (err, out) {
    if (err) {
      return cb(err);
    }
    return parseOutput(out, cb);
  });
};

extractRaw = function (string) {
  var parts, sep, value;
  sep = '" (Raw: "';
  parts = string.split(sep);
  value = parts.slice(0, parts.length / 2).join(sep);
  return value.substring(1);
};

parseOutput = function (text, cb) {
  var depth, element, inManifest, indent, input, line, lines, matches, name, parent, parts, rest, result, stack, type, value, _i, _len;
  if (!text) {
    return cb(new Error('No input!'));
  }
  lines = text.split('\n');
  result = {};
  stack = [result];
  inManifest = false;
  for (_i = 0, _len = lines.length; _i < _len; _i++) {
    line = lines[_i];
    if (line.trim() === 'Android manifest:') {
      inManifest = true;
      continue;
    }
    if (!inManifest) {
      continue;
    }
    if (line.trim() === '') {
      continue;
    }
    if (line.match(/^N:/)) {
      continue;
    }
    matches = line.match(/^( +)(A|E): ([\w:\-]+)(.*)$/);
    if (!matches) {
      return cb(new Error('Parse failure: ' + line));
    }
    input = matches[0], indent = matches[1], type = matches[2], name = matches[3], rest = matches[4];
    depth = indent.length / 2;
    parent = stack[depth - 1];
    if (type === 'E') {
      element = {};
      while (stack.length > depth) {
        stack.pop();
      }
      if (depth === stack.length) {
        stack.push(element);
      }
      if (!parent[name]) {
        parent[name] = [];
      }
      parent[name].push(element);
    } else if (type === 'A') {
      value = null;
      if (rest.substring(0, 2) === '="') {
        value = extractRaw(rest.substring(1));
      } else if (rest.substring(0, 12) === '=(type 0x12)') {
        value = rest[14] === '1';
      } else {
        parts = rest.match(/^\(0x[0-9a-f]+\)\=(.*)$/);
        if (!parts) {
          return cb(new Error('Cannot parse value: ' + rest));
        }
        if (parts[1][0] === '"') {
          value = extractRaw(parts[1]);
        } else {
          if (parts[1].substring(0, 11) === '(type 0x10)') {
            value = parseInt(parts[1].substring(13), 16);
          } else {
            value = parts[1];
          }
        }
      }
      parent['@' + name] = value;
    } else {
      return cb(new Error('Unknown type: ' + type));
    }
  }
  return cb(null, result);
};

parseApk.parseOutput = parseOutput;

module.exports = parseApk;<|endoftext|>


<commit_before>'use babel';

import { getImports, getPackage, getPackageDefinitionEndPoint, getLastImportEndPoint } from './helpers';

export default {

  activate() {
    const ImportOrganizer = require('./import-organizer');
    this.importOrganizer = new ImportOrganizer();
  },

  provideImport() {
    return ::this.addImport;
  },

  consumeJavaClasspathRegistry(registry) {
    this.classpathRegistry = registry;
    atom.commands.add('atom-text-editor', 'java-import-wiz:do-import', ::this.doImport);
  },

  async doImport() {
    const textEditor = atom.workspace.getActiveTextEditor();
    const className = textEditor.getWordUnderCursor();
    const klasses = this.classpathRegistry.find(fullyQualifiedClass =>
      fullyQualifiedClass.substr(fullyQualifiedClass.lastIndexOf('.') + 1) === className);

    if (klasses.length === 0) {
      return;
    }

    let item = klasses[0].name;
    if (klasses.length > 1) {
      const ImportView = require('./import-view');
      try {
        item = await new ImportView(klasses.map(k => k.name)).getSelection();
      } catch (err) {
        return;
      }
    }

    this.addImport(textEditor, item);
  },

  /**
   * Checks if the fullyQualifiedClass exists in the array of imports.
   * Supports wildcard imports (such as `java.util.*;`).
   */
  importsIncludes(imports, fullyQualifiedClass) {
    for (const imp of imports) {
      if (imp === fullyQualifiedClass) {
        return true;
      }
      if (this.getClassFromFullyQualifiedClass(imp) === '*') {
        // This is a wildcard import. Check if package is the same.
        if (this.getPackageFromFullyQualifiedClass(fullyQualifiedClass) === this.getPackageFromFullyQualifiedClass(imp)) {
          return true;
        }
      }
    }
    return false;
  },

  getPackageFromFullyQualifiedClass(fullyQualifiedClass) {
    return fullyQualifiedClass.substr(0, fullyQualifiedClass.lastIndexOf('.'));
  },

  getClassFromFullyQualifiedClass(fullyQualifiedClass) {
    return fullyQualifiedClass.substr(fullyQualifiedClass.lastIndexOf('.') + 1);
  },

  getImportInsertPoint(editor) {
    let point = getLastImportEndPoint(editor);
    if (!point) {
      point = getPackageDefinitionEndPoint(editor);
    }
    if (!point) {
      point = [ 0, 0 ];
    }
    return point;
  },

  addImport(editor, fullyQualifiedClass) {
    let rootClass = fullyQualifiedClass;
    const subClassIndex = fullyQualifiedClass.indexOf('$'); // A nested class, e.g. javax.ws.rs.core.Response$Status
    if (subClassIndex !== -1) {
      rootClass = fullyQualifiedClass.substr(0, subClassIndex);
    }

    if (this.importsIncludes(getImports(editor), rootClass)) {
      return;
    }

    const pkg = getPackage(editor);
    const importPkg = this.getPackageFromFullyQualifiedClass(rootClass);
    if (importPkg === pkg || 'java.lang' === importPkg) {
      return;
    }

    const point = this.getImportInsertPoint(editor);
    editor.getBuffer().insert(point, `import ${rootClass};\n`);
  }

};
<commit_msg>Update to registry api<commit_after>'use babel';

import { getImports, getPackage, getPackageDefinitionEndPoint, getLastImportEndPoint } from './helpers';

export default {

  activate() {
    const ImportOrganizer = require('./import-organizer');
    this.importOrganizer = new ImportOrganizer();
  },

  provideImport() {
    return ::this.addImport;
  },

  consumeJavaClasspathRegistry(registry) {
    this.classpathRegistry = registry;
    atom.commands.add('atom-text-editor', 'java-import-wiz:do-import', ::this.doImport);
  },

  async doImport() {
    const textEditor = atom.workspace.getActiveTextEditor();
    const className = textEditor.getWordUnderCursor();
    const klasses = this.classpathRegistry.filter(fullyQualifiedClass =>
      fullyQualifiedClass.substr(fullyQualifiedClass.lastIndexOf('.') + 1) === className);

    if (klasses.length === 0) {
      return;
    }

    let item = klasses[0].name;
    if (klasses.length > 1) {
      const ImportView = require('./import-view');
      try {
        item = await new ImportView(klasses.map(k => k.name)).getSelection();
      } catch (err) {
        return;
      }
    }

    this.addImport(textEditor, item);
  },

  /**
   * Checks if the fullyQualifiedClass exists in the array of imports.
   * Supports wildcard imports (such as `java.util.*;`).
   */
  importsIncludes(imports, fullyQualifiedClass) {
    for (const imp of imports) {
      if (imp === fullyQualifiedClass) {
        return true;
      }
      if (this.getClassFromFullyQualifiedClass(imp) === '*') {
        // This is a wildcard import. Check if package is the same.
        if (this.getPackageFromFullyQualifiedClass(fullyQualifiedClass) === this.getPackageFromFullyQualifiedClass(imp)) {
          return true;
        }
      }
    }
    return false;
  },

  getPackageFromFullyQualifiedClass(fullyQualifiedClass) {
    return fullyQualifiedClass.substr(0, fullyQualifiedClass.lastIndexOf('.'));
  },

  getClassFromFullyQualifiedClass(fullyQualifiedClass) {
    return fullyQualifiedClass.substr(fullyQualifiedClass.lastIndexOf('.') + 1);
  },

  getImportInsertPoint(editor) {
    let point = getLastImportEndPoint(editor);
    if (!point) {
      point = getPackageDefinitionEndPoint(editor);
    }
    if (!point) {
      point = [ 0, 0 ];
    }
    return point;
  },

  addImport(editor, fullyQualifiedClass) {
    let rootClass = fullyQualifiedClass;
    const subClassIndex = fullyQualifiedClass.indexOf('$'); // A nested class, e.g. javax.ws.rs.core.Response$Status
    if (subClassIndex !== -1) {
      rootClass = fullyQualifiedClass.substr(0, subClassIndex);
    }

    if (this.importsIncludes(getImports(editor), rootClass)) {
      return;
    }

    const pkg = getPackage(editor);
    const importPkg = this.getPackageFromFullyQualifiedClass(rootClass);
    if (importPkg === pkg || 'java.lang' === importPkg) {
      return;
    }

    const point = this.getImportInsertPoint(editor);
    editor.getBuffer().insert(point, `import ${rootClass};\n`);
  }

};
<|endoftext|>


<commit_before>var async = require('async');

function captainHook(schema) {

  // Pre-Save Setup
  schema.pre('save', function (next) {
    var self = this;
    this._wasNew = this.isNew;
    if (this.isNew) {
      this.runPreCreate(self, function(){
        next();
      });
    } else {
      this.runPreUpdate(self, function(){
        next();
      });
    }
  });

  // Post-Save Setup
  schema.post('save', function () {
    var self = this;
    if (this._wasNew) {
      this.runPostCreate(self);
    } else {
      this.runPostUpdate(self);
    }
  });

  // Pre-Create Methods
  schema.preCreateMethods = [];

  schema.preCreate = function(fn){
    schema.preCreateMethods.push(fn);
  };

  schema.methods.runPreCreate = function(self, callback){
    async.eachSeries(schema.preCreateMethods,
      function(fn, cb) {
        fn(self, cb);
      }, function(err){
        if (err){ throw err; }
        callback();
    });
  };

  // Pre-Update Methods
  schema.preUpdateMethods = [];

  schema.preUpdate = function(fn){
    schema.preUpdateMethods.push(fn);
  };

  schema.methods.runPreUpdate = function(self, callback){
    async.eachSeries(schema.preUpdateMethods,
      function(fn, cb) {
        fn(self, cb);
      }, function(err){
        if (err){ throw err; }
        callback();
    });
  };

  // Post-Create Methods
  schema.postCreateMethods = [];

  schema.postCreate = function(fn){
    schema.postCreateMethods.push(fn);
  };

  schema.methods.runPostCreate = function(self){
    async.eachSeries(schema.postCreateMethods,
      function(fn, cb) {
        fn(self, cb);
      }, function(err){
        if (err){ throw err; }
    });
  };

  // Post-Update Methods
  schema.postUpdateMethods = [];

  schema.postUpdate = function(fn){
    schema.postUpdateMethods.push(fn);
  };

  schema.methods.runPostUpdate = function(self){
    async.eachSeries(schema.postUpdateMethods,
      function(fn, cb) {
        fn(self, cb);
      }, function(err){
        if (err){ throw err; }
    });
  };

}

module.exports = captainHook;
<commit_msg>DRY up calls to async.eachSeries()<commit_after>var async = require('async');

function captainHook(schema) {

  // Pre-Save Setup
  schema.pre('save', function (next) {
    var self = this;
    this._wasNew = this.isNew;
    if (this.isNew) {
      runPreMethods(schema.preCreateMethods, self, function(){
        next();
      });
    } else {
      runPreMethods(schema.preUpdateMethods, self, function(){
        next();
      });
    }
  });

  // Post-Save Setup
  schema.post('save', function () {
    var self = this;
    if (this._wasNew) {
      runPostMethods(schema.postCreateMethods, self);
    } else {
      runPostMethods(schema.postUpdateMethods, self);
    }
  });

  /**
   * Pre-Hooks
   * These hooks run before an instance has been created / updated
   *
   */

  runPreMethods = function(methods, self, callback){
    async.eachSeries(methods,
      function(fn, cb) {
        fn(self, cb);
      }, function(err){
        if (err){ throw err; }
        callback();
    });
  };

  // Pre-Create Methods
  schema.preCreateMethods = [];

  schema.preCreate = function(fn){
    schema.preCreateMethods.push(fn);
  };

  // Pre-Update Methods
  schema.preUpdateMethods = [];

  schema.preUpdate = function(fn){
    schema.preUpdateMethods.push(fn);
  };

  /**
   * Post-Hooks
   * These hooks run after an instance has been created / updated
   *
   */

  runPostMethods = function(methods, self){
    async.eachSeries(methods,
      function(fn, cb) {
        fn(self, cb);
      }, function(err){
        if (err){ throw err; }
    });
  };

  // Post-Create Methods
  schema.postCreateMethods = [];

  schema.postCreate = function(fn){
    schema.postCreateMethods.push(fn);
  };

  // Post-Update Methods
  schema.postUpdateMethods = [];

  schema.postUpdate = function(fn){
    schema.postUpdateMethods.push(fn);
  };

}

module.exports = captainHook;
<|endoftext|>