<commit_before>self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('playbulb-candle').then(cache => {
      return cache.match(event.request).then(response => {

        // If a request doesn't match anything in the cache, get it from the
        // network, send it to the page & add it to the cache at the same time.
        return response || fetch(event.request).then(response => {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

/* Clean up old caches */
self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.filter(cacheName => (cacheName !== 'playbulb-candle'))
                  .map(cacheName => caches.delete(cacheName))
      );
    })
  );
});
<commit_msg>Improve SW readibility (#56)<commit_after>const addToCache = (request, networkResponse) => {
  return caches.open('playbulb-candle')
    .then((cache) => cache.put(request, networkResponse.clone()));
};

const getCacheResponse = (request) => {
  return caches.open('playbulb-candle').then((cache) => {
    return cache.match(request);
  });
};

const getNetworkOrCacheResponse = (request) => {
  return new Promise((resolve) => {
    fetch(request).then((networkResponse) => {
      addToCache(request, networkResponse);
      resolve(networkResponse);
    }).catch(() => {
      getCacheResponse(request).then((cacheResponse) => {
        resolve(cacheResponse || Response.error());
      });
    });
  });
};

self.addEventListener('fetch', (event) => {
  event.respondWith(getNetworkOrCacheResponse(event.request));
});

const cleanOldCache = () => {
  return caches.keys().then(cacheNames => {
    return Promise.all(
      cacheNames.filter(cacheName => (cacheName !== 'playbulb-candle'))
                .map(cacheName => caches.delete(cacheName))
    );
  })
}

self.addEventListener('activate', (event) => {
  event.waitUntil(cleanOldCache());
});
<|endoftext|>


<commit_before>const Operations = require('./operations');
const owningDataSource = new WeakMap();
const { flatten } = require('lodash');
const Client = require('@cardstack/elasticsearch/client');
const log = require('@cardstack/logger')('cardstack/indexers');
const DocumentContext = require('./document-context');

const FINALIZED = {};

class BranchUpdate {
  constructor(branch, seedSchema, client, emitEvent) {
    this.branch = branch;
    this.seedSchema = seedSchema;
    this.client = client;
    this.updaters = Object.create(null);
    this.emitEvent = emitEvent;
    this.schemaModels = [];
    this._schema = null;
    this.bulkOps = null;
    this._touched = Object.create(null);
    this.read = this.read.bind(this);
  }

  async addDataSource(dataSource) {
    if (this._schema) {
      throw new Error("Bug in hub indexing. Something tried to add an indexer after we had already established the schema");
    }
    let indexer = dataSource.indexer;
    if (!indexer) {
      return [];
    }
    let updater = await indexer.beginUpdate(this.branch);
    owningDataSource.set(updater, dataSource);
    let newModels = await updater.schema();
    this.schemaModels.push(newModels);
    this.updaters[dataSource.id] = updater;
    return newModels;
  }

  addStaticModels(schemaModels, allModels) {
    this.schemaModels = this.schemaModels.concat(schemaModels);
    this.updaters['static-models'].staticModels = allModels;
  }

  async schema() {
    if (this._schema === FINALIZED) {
      throw new Error("Bug: the schema has already been taken away from this branch update");
    }
    if (!this._schema) {
      this._schema = await this.seedSchema.applyChanges(flatten(this.schemaModels).map(model => ({ type: model.type, id: model.id, document: model })));
    }
    return this._schema;
  }

  async takeSchema() {
    let schema = await this.schema();
    // We are giving away ownership, so we don't retain our reference
    // and we don't tear it down when we are destroyed
    this._schema = FINALIZED;
    return schema;
  }

  async destroy() {
    if (this._schema && this._schema !== FINALIZED) {
      await this._schema.teardown();
    }
    for (let updater of Object.values(this.updaters)) {
      if (typeof updater.destroy === 'function') {
        await updater.destroy();
      }
    }
  }

  async update(forceRefresh, hints) {
    this.bulkOps = this.client.bulkOps({ forceRefresh });
    await this.client.accomodateSchema(this.branch, await this.schema());
    await this._updateContent(hints);
  }

  async _updateContent(hints) {
    let schema = await this.schema();
    let types = hints && Array.isArray(hints) ? hints.map(hint => hint.type).filter(type => Boolean(type)) : [];
    let updaters = Object.entries(this.updaters);

    let dataSourceIds = types.map(type => {
      let contentType = schema.types.get(type);
      if (!contentType) { return; }
      let dataSource = contentType.dataSource;
      if (!dataSource) { return; }
      return dataSource.id;
    }).filter(item => Boolean(item));

    if (dataSourceIds.length) {
      updaters = updaters.filter(([ sourceId ]) => dataSourceIds.includes(sourceId));
    }

    for (let [sourceId, updater] of updaters) {
      let meta = await this._loadMeta(updater);
      let publicOps = Operations.create(this, sourceId);
      let newMeta = await updater.updateContent(meta, hints, publicOps, this.read);
      await this._saveMeta(updater, newMeta);
    }
    await this._invalidations();
    await this.bulkOps.finalize();
  }

  async _loadMeta(updater) {
    let doc = await this.client.es.getSource({
      index: Client.branchToIndexName(this.branch),
      type: 'meta',
      id: owningDataSource.get(updater).id,
      ignore: [404]
    });
    if (doc) {
      return doc.params;
    }
  }

  async _saveMeta(updater, newMeta) {
    // the plugin-specific metadata is wrapped inside a "params"
    // property so that we can tell elasticsearch not to index any of
    // it. We don't want inconsistent types across plugins to cause
    // mapping errors.
    await this.bulkOps.add({
      index: {
        _index: Client.branchToIndexName(this.branch),
        _type: 'meta',
        _id: owningDataSource.get(updater).id,
      }
    }, { params: newMeta });
  }

  async _findTouchedReferences() {
    let size = 100;
    let esBody = {
      query: {
        bool: {
          must: [
            { terms: { cardstack_references : Object.keys(this._touched) } }
          ],
        }
      },
      size
    };

    let result = await this.client.es.search({
      index: Client.branchToIndexName(this.branch),
      body: esBody
    });

    let docs = result.hits.hits;
    if (docs.length === size) {
      throw new Error("Bug in hub:indexers: need to process larger invalidation sets");
    }
    return docs.map(doc => doc._source.cardstack_pristine.data);
  }

  // This method does not need to recursively invalidate, because each
  // document stores a complete, rolled-up picture of which other
  // documents it references.
  async _invalidations() {
    let schema = await this.schema();
    let pendingOps = [];
    let references = await this._findTouchedReferences();
    for (let { type, id } of references) {
      let key = `${type}/${id}`;
      if (!this._touched[key]) {
        this._touched[key] = true;
        pendingOps.push((async ()=> {
          let resource = await this.read(type, id);
          if (resource) {
            let sourceId = schema.types.get(type).dataSource.id;
            let nonce = 0;
            await this.add(type, id, resource, sourceId, nonce);
          }
        })());
      }
    }
    await Promise.all(pendingOps);
  }

  async read(type, id) {
    let schema = await this.schema();
    let contentType = schema.types.get(type);
    if (!contentType) { return; }
    let source = contentType.dataSource;
    if (!source) { return; }
    let updater = this.updaters[source.id];
    if (!updater) { return; }
    let isSchemaType = schema.isSchemaType(type);
    let model = await updater.read(type, id, isSchemaType, this.read);
    if (!model) {
      // TODO: this is a complexity that can go away after we refactor
      // so that a content type can live in multiple data
      // sources. Right now it's needed because our bootstrap schema
      // and hard-coded data sources can provide models of types that
      // are otherwise also stored elsewhere.
      let staticUpdater = this.updaters['static-models'];
      if (staticUpdater) {
        model = await staticUpdater.read(type, id, isSchemaType, this.read);
      }
    }
    return model;
  }

  async add(type, id, doc, sourceId, nonce) {
    this._touched[`${type}/${id}`] = true;
    let searchDoc = await this._prepareSearchDoc(type, id, doc);
    searchDoc.cardstack_source = sourceId;
    searchDoc.cardstack_pristine.data.meta.source = sourceId;
    if (nonce) {
      searchDoc.cardstack_generation = nonce;
    }
    await this.bulkOps.add({
      index: {
        _index: Client.branchToIndexName(this.branch),
        _type: type,
        _id: `${this.branch}/${id}`,
      }
    }, searchDoc);
    this.emitEvent('add', { type, id, doc });
    log.debug("save %s %s", type, id);
  }

  async delete(type, id) {
    this._touched[`${type}/${id}`] = true;
    await this.bulkOps.add({
      delete: {
        _index: Client.branchToIndexName(this.branch),
        _type: type,
        _id: `${this.branch}/${id}`
      }
    });
    this.emitEvent('delete', { type, id });
    log.debug("delete %s %s", type, id);
  }

  async deleteAllWithoutNonce(sourceId, nonce) {
    await this.bulkOps.add('deleteByQuery', {
      index: Client.branchToIndexName(this.branch),
      conflicts: 'proceed',
      body: {
        query: {
          bool: {
            must: [
              { term: { cardstack_source: sourceId } },
            ],
            must_not: [
              { term: { cardstack_generation: nonce } }
            ]
          }
        }
      }
    });
    this.emitEvent('delete_all_without_nonce', { sourceId, nonce });
    log.debug("bulk delete older content for data source %s", sourceId);
  }

  async _prepareSearchDoc(type, id, doc) {
    let schema = await this.schema();
    let context = new DocumentContext(this, schema, type, id, doc);
    return context.searchDoc();
  }

}

exports.BranchUpdate = BranchUpdate;
<commit_msg>clean up correctly if there's a failure during updater.schema()<commit_after>const Operations = require('./operations');
const owningDataSource = new WeakMap();
const { flatten } = require('lodash');
const Client = require('@cardstack/elasticsearch/client');
const log = require('@cardstack/logger')('cardstack/indexers');
const DocumentContext = require('./document-context');

const FINALIZED = {};

class BranchUpdate {
  constructor(branch, seedSchema, client, emitEvent) {
    this.branch = branch;
    this.seedSchema = seedSchema;
    this.client = client;
    this.updaters = Object.create(null);
    this.emitEvent = emitEvent;
    this.schemaModels = [];
    this._schema = null;
    this.bulkOps = null;
    this._touched = Object.create(null);
    this.read = this.read.bind(this);
  }

  async addDataSource(dataSource) {
    if (this._schema) {
      throw new Error("Bug in hub indexing. Something tried to add an indexer after we had already established the schema");
    }
    let indexer = dataSource.indexer;
    if (!indexer) {
      return [];
    }
    let updater = this.updaters[dataSource.id] = await indexer.beginUpdate(this.branch);
    owningDataSource.set(updater, dataSource);
    let newModels = await updater.schema();
    this.schemaModels.push(newModels);
    return newModels;
  }

  addStaticModels(schemaModels, allModels) {
    this.schemaModels = this.schemaModels.concat(schemaModels);
    this.updaters['static-models'].staticModels = allModels;
  }

  async schema() {
    if (this._schema === FINALIZED) {
      throw new Error("Bug: the schema has already been taken away from this branch update");
    }
    if (!this._schema) {
      this._schema = await this.seedSchema.applyChanges(flatten(this.schemaModels).map(model => ({ type: model.type, id: model.id, document: model })));
    }
    return this._schema;
  }

  async takeSchema() {
    let schema = await this.schema();
    // We are giving away ownership, so we don't retain our reference
    // and we don't tear it down when we are destroyed
    this._schema = FINALIZED;
    return schema;
  }

  async destroy() {
    if (this._schema && this._schema !== FINALIZED) {
      await this._schema.teardown();
    }
    for (let updater of Object.values(this.updaters)) {
      if (typeof updater.destroy === 'function') {
        await updater.destroy();
      }
    }
  }

  async update(forceRefresh, hints) {
    this.bulkOps = this.client.bulkOps({ forceRefresh });
    await this.client.accomodateSchema(this.branch, await this.schema());
    await this._updateContent(hints);
  }

  async _updateContent(hints) {
    let schema = await this.schema();
    let types = hints && Array.isArray(hints) ? hints.map(hint => hint.type).filter(type => Boolean(type)) : [];
    let updaters = Object.entries(this.updaters);

    let dataSourceIds = types.map(type => {
      let contentType = schema.types.get(type);
      if (!contentType) { return; }
      let dataSource = contentType.dataSource;
      if (!dataSource) { return; }
      return dataSource.id;
    }).filter(item => Boolean(item));

    if (dataSourceIds.length) {
      updaters = updaters.filter(([ sourceId ]) => dataSourceIds.includes(sourceId));
    }

    for (let [sourceId, updater] of updaters) {
      let meta = await this._loadMeta(updater);
      let publicOps = Operations.create(this, sourceId);
      let newMeta = await updater.updateContent(meta, hints, publicOps, this.read);
      await this._saveMeta(updater, newMeta);
    }
    await this._invalidations();
    await this.bulkOps.finalize();
  }

  async _loadMeta(updater) {
    let doc = await this.client.es.getSource({
      index: Client.branchToIndexName(this.branch),
      type: 'meta',
      id: owningDataSource.get(updater).id,
      ignore: [404]
    });
    if (doc) {
      return doc.params;
    }
  }

  async _saveMeta(updater, newMeta) {
    // the plugin-specific metadata is wrapped inside a "params"
    // property so that we can tell elasticsearch not to index any of
    // it. We don't want inconsistent types across plugins to cause
    // mapping errors.
    await this.bulkOps.add({
      index: {
        _index: Client.branchToIndexName(this.branch),
        _type: 'meta',
        _id: owningDataSource.get(updater).id,
      }
    }, { params: newMeta });
  }

  async _findTouchedReferences() {
    let size = 100;
    let esBody = {
      query: {
        bool: {
          must: [
            { terms: { cardstack_references : Object.keys(this._touched) } }
          ],
        }
      },
      size
    };

    let result = await this.client.es.search({
      index: Client.branchToIndexName(this.branch),
      body: esBody
    });

    let docs = result.hits.hits;
    if (docs.length === size) {
      throw new Error("Bug in hub:indexers: need to process larger invalidation sets");
    }
    return docs.map(doc => doc._source.cardstack_pristine.data);
  }

  // This method does not need to recursively invalidate, because each
  // document stores a complete, rolled-up picture of which other
  // documents it references.
  async _invalidations() {
    let schema = await this.schema();
    let pendingOps = [];
    let references = await this._findTouchedReferences();
    for (let { type, id } of references) {
      let key = `${type}/${id}`;
      if (!this._touched[key]) {
        this._touched[key] = true;
        pendingOps.push((async ()=> {
          let resource = await this.read(type, id);
          if (resource) {
            let sourceId = schema.types.get(type).dataSource.id;
            let nonce = 0;
            await this.add(type, id, resource, sourceId, nonce);
          }
        })());
      }
    }
    await Promise.all(pendingOps);
  }

  async read(type, id) {
    let schema = await this.schema();
    let contentType = schema.types.get(type);
    if (!contentType) { return; }
    let source = contentType.dataSource;
    if (!source) { return; }
    let updater = this.updaters[source.id];
    if (!updater) { return; }
    let isSchemaType = schema.isSchemaType(type);
    let model = await updater.read(type, id, isSchemaType, this.read);
    if (!model) {
      // TODO: this is a complexity that can go away after we refactor
      // so that a content type can live in multiple data
      // sources. Right now it's needed because our bootstrap schema
      // and hard-coded data sources can provide models of types that
      // are otherwise also stored elsewhere.
      let staticUpdater = this.updaters['static-models'];
      if (staticUpdater) {
        model = await staticUpdater.read(type, id, isSchemaType, this.read);
      }
    }
    return model;
  }

  async add(type, id, doc, sourceId, nonce) {
    this._touched[`${type}/${id}`] = true;
    let searchDoc = await this._prepareSearchDoc(type, id, doc);
    searchDoc.cardstack_source = sourceId;
    searchDoc.cardstack_pristine.data.meta.source = sourceId;
    if (nonce) {
      searchDoc.cardstack_generation = nonce;
    }
    await this.bulkOps.add({
      index: {
        _index: Client.branchToIndexName(this.branch),
        _type: type,
        _id: `${this.branch}/${id}`,
      }
    }, searchDoc);
    this.emitEvent('add', { type, id, doc });
    log.debug("save %s %s", type, id);
  }

  async delete(type, id) {
    this._touched[`${type}/${id}`] = true;
    await this.bulkOps.add({
      delete: {
        _index: Client.branchToIndexName(this.branch),
        _type: type,
        _id: `${this.branch}/${id}`
      }
    });
    this.emitEvent('delete', { type, id });
    log.debug("delete %s %s", type, id);
  }

  async deleteAllWithoutNonce(sourceId, nonce) {
    await this.bulkOps.add('deleteByQuery', {
      index: Client.branchToIndexName(this.branch),
      conflicts: 'proceed',
      body: {
        query: {
          bool: {
            must: [
              { term: { cardstack_source: sourceId } },
            ],
            must_not: [
              { term: { cardstack_generation: nonce } }
            ]
          }
        }
      }
    });
    this.emitEvent('delete_all_without_nonce', { sourceId, nonce });
    log.debug("bulk delete older content for data source %s", sourceId);
  }

  async _prepareSearchDoc(type, id, doc) {
    let schema = await this.schema();
    let context = new DocumentContext(this, schema, type, id, doc);
    return context.searchDoc();
  }

}

exports.BranchUpdate = BranchUpdate;
<|endoftext|>


<commit_before>Template.IMonScatterWidget.onCreated(function() {
  var template = this;
  template.autorun(function() {
    var indicators = [
      Template.currentData().x.indicator,
      Template.currentData().y.indicator
    ];
    template.subscribe('imon_data', 'all', indicators);
    template.subscribe('imon_countries');
  });
});

Template.IMonScatterWidget.onRendered(function() {
  var template = this;
  var node = template.find('.scatter-chart');
  var widgetNode = template.firstNode.parentNode.parentNode;
  var $widgetBody = $(widgetNode).find('.widget-body');

  var chart = d3.select(node).chart('Compose', function(options) {
    var xs = _.pluck(options.data, 'x'), ys = _.pluck(options.data, 'y');

    var scales = {
      x: { domain: [_.min(xs), _.max(xs)] },
      y: { domain: [_.min(ys), _.max(ys)] },
    };

    var charts = [{
      type: 'Dots',
      id: 'dots',
      data: options.data,
      xScale: scales.x,
      yScale: scales.y,
      xJitter: options.xJitter,
      yJitter: options.yJitter,
      labels: {
        offset: 3
      }
    }];

    var title = d3c.title('Custom Chart');
    var xAxis = d3c.axis('xAxis', {scale: scales.x, ticks: 3});
    var yAxis = d3c.axis('yAxis', {scale: scales.y, ticks: 3});
    var xAxisTitle = d3c.axisTitle(options.xAxisTitle);
    var yAxisTitle = d3c.axisTitle(options.yAxisTitle);

    return [
      [yAxisTitle, yAxis, d3c.layered(charts)],
      xAxis,
      xAxisTitle
    ];
  });

  var setChartDims = function() {
    var width = $widgetBody.outerWidth() - Settings.chart.padding.right;
    var height = $widgetBody.outerHeight() - Settings.chart.padding.bottom;
    console.log(width + ' ' + height);
    chart.width(width);
    chart.height(height);
  };

  $(widgetNode).on('gridster:resizestop', function() {
    setChartDims();
    chart.redraw();
  });

  var redrawn = false;
  template.autorun(function() {
    if (!template.subscriptionsReady()) { return; }
    var xIndicator = Template.currentData().x.indicator;
    var yIndicator = Template.currentData().y.indicator;
    var xTitle = xIndicator, yTitle = yIndicator;
    if (Template.currentData().x.log) {
      xTitle = 'Log ' + xTitle;
    }
    if (Template.currentData().y.log) {
      yTitle = 'Log ' + yTitle;
    }

    var data = [];
    IMonCountries.find().forEach(function(country) {
      var x = IMonData.findOne({ countryCode: country.code, name: xIndicator });
      var y = IMonData.findOne({ countryCode: country.code, name: yIndicator });
      if (_.isUndefined(x) || _.isUndefined(y)) { return; }

      var xValue = x.value, yValue = y.value;
      if (Template.currentData().x.log && xValue > 0) {
        xValue = Math.log(xValue);
      }
      if (Template.currentData().y.log && yValue > 0) {
        yValue = Math.log(yValue);
      }

      data.push({
        x: xValue,
        y: yValue,
        code: country.code,
        key: country.code,
        label: country.name
      });
    });

    chart.margins(Settings.chart.margins);
    chart.responsive(false);

    chart.draw({
      data: data,
      xAxisTitle: xTitle,
      yAxisTitle: yTitle,
      xJitter: Template.currentData().x.jitter,
      yJitter: Template.currentData().y.jitter
    });

    // This is a hacky way to get the chart to fit the widget on first draw
    // because it wouldn't throw the draw event correctly.
    if (!redrawn) {
      setChartDims();
      chart.redraw();
      redrawn = true;
    }
  });
});
<commit_msg>remove debugging statement<commit_after>Template.IMonScatterWidget.onCreated(function() {
  var template = this;
  template.autorun(function() {
    var indicators = [
      Template.currentData().x.indicator,
      Template.currentData().y.indicator
    ];
    template.subscribe('imon_data', 'all', indicators);
    template.subscribe('imon_countries');
  });
});

Template.IMonScatterWidget.onRendered(function() {
  var template = this;
  var node = template.find('.scatter-chart');
  var widgetNode = template.firstNode.parentNode.parentNode;
  var $widgetBody = $(widgetNode).find('.widget-body');

  var chart = d3.select(node).chart('Compose', function(options) {
    var xs = _.pluck(options.data, 'x'), ys = _.pluck(options.data, 'y');

    var scales = {
      x: { domain: [_.min(xs), _.max(xs)] },
      y: { domain: [_.min(ys), _.max(ys)] },
    };

    var charts = [{
      type: 'Dots',
      id: 'dots',
      data: options.data,
      xScale: scales.x,
      yScale: scales.y,
      xJitter: options.xJitter,
      yJitter: options.yJitter,
      labels: {
        offset: 3
      }
    }];

    var title = d3c.title('Custom Chart');
    var xAxis = d3c.axis('xAxis', {scale: scales.x, ticks: 3});
    var yAxis = d3c.axis('yAxis', {scale: scales.y, ticks: 3});
    var xAxisTitle = d3c.axisTitle(options.xAxisTitle);
    var yAxisTitle = d3c.axisTitle(options.yAxisTitle);

    return [
      [yAxisTitle, yAxis, d3c.layered(charts)],
      xAxis,
      xAxisTitle
    ];
  });

  var setChartDims = function() {
    var width = $widgetBody.outerWidth() - Settings.chart.padding.right;
    var height = $widgetBody.outerHeight() - Settings.chart.padding.bottom;
    chart.width(width);
    chart.height(height);
  };

  $(widgetNode).on('gridster:resizestop', function() {
    setChartDims();
    chart.redraw();
  });

  var redrawn = false;
  template.autorun(function() {
    if (!template.subscriptionsReady()) { return; }
    var xIndicator = Template.currentData().x.indicator;
    var yIndicator = Template.currentData().y.indicator;
    var xTitle = xIndicator, yTitle = yIndicator;
    if (Template.currentData().x.log) {
      xTitle = 'Log ' + xTitle;
    }
    if (Template.currentData().y.log) {
      yTitle = 'Log ' + yTitle;
    }

    var data = [];
    IMonCountries.find().forEach(function(country) {
      var x = IMonData.findOne({ countryCode: country.code, name: xIndicator });
      var y = IMonData.findOne({ countryCode: country.code, name: yIndicator });
      if (_.isUndefined(x) || _.isUndefined(y)) { return; }

      var xValue = x.value, yValue = y.value;
      if (Template.currentData().x.log && xValue > 0) {
        xValue = Math.log(xValue);
      }
      if (Template.currentData().y.log && yValue > 0) {
        yValue = Math.log(yValue);
      }

      data.push({
        x: xValue,
        y: yValue,
        code: country.code,
        key: country.code,
        label: country.name
      });
    });

    chart.margins(Settings.chart.margins);
    chart.responsive(false);

    chart.draw({
      data: data,
      xAxisTitle: xTitle,
      yAxisTitle: yTitle,
      xJitter: Template.currentData().x.jitter,
      yJitter: Template.currentData().y.jitter
    });

    // This is a hacky way to get the chart to fit the widget on first draw
    // because it wouldn't throw the draw event correctly.
    if (!redrawn) {
      setChartDims();
      chart.redraw();
      redrawn = true;
    }
  });
});
<|endoftext|>


<commit_before>var parser = require('swagger-parser'),
    Endpoint = require('../entities/endpoint'),
    Schema = require('../entities/schema'),
    Importer = require('./importer'),
    Project = require('../entities/project'),
    jsonHelper = require('../utils/json'),
    swaggerHelper = require('../helpers/swagger'),
    YAML = require('yamljs'),
    _ = require('lodash');

function Swagger() {
  this.metadata = null;
  this.dereferencedAPI = null;
  this.filePath = null;
}

function needDeReferenced(ref) {
  if (!ref['$ref']) {
    return false;
  }
  var regex = /\/(parameters|responses)\//i;
  if (ref['$ref'].match(regex)) {
    return true;
  }
  return false;
}

Swagger.prototype = new Importer();

Swagger.prototype._mapSecurityDefinitions = function(securityDefinitions) {
  var result = {};
  for(var name in securityDefinitions) {
    var type = securityDefinitions[name].type;
    if (!result.hasOwnProperty(type)) {
      result[type] = {};
    }
    var sd = securityDefinitions[name];
    switch(type) {
      case 'apiKey':
        var keyPlaceHolder = (sd.in === 'header')?'headers':'queryString';
        if (!result[type].hasOwnProperty(keyPlaceHolder)){
          result[type][keyPlaceHolder] = [];
        }
        result[type][keyPlaceHolder].push({
          name: sd.name,
          value: ''
        });
        break;
      case 'oauth2':
        result[type] = {
          name: name,
          authorizationUrl: sd.authorizationUrl || '',
          scopes: slScopes,
          tokenUrl: sd.tokenUrl || ''
        };

        var slScopes = [], swaggerScopes = sd.scopes;

        if (swaggerScopes) {
          for(var key in swaggerScopes) {
            var scope = {};
            scope['name'] = key;
            scope['value'] = swaggerScopes[key];
            slScopes.push(scope);
          }
        }

        if (sd.flow) {
          result[type]['flow'] = sd.flow;
        }

        if (slScopes.length > 0) {
          result[type]['scopes'] = slScopes;
        }

        break;
      case 'basic':
        result[type] = {
          name: name,
          value: '',
          description: sd.description || ''
        };
        break;
    }
  }
  return result;
};

Swagger.prototype._mapSchema = function(schemaDefinitions) {
  var result = [];
  for (var schemaName in schemaDefinitions) {
    var sd = new Schema(schemaName);
    sd.Name = schemaName;
    //create a close to remove extension properties
    var schemaDataClone = _.clone(schemaDefinitions[schemaName]);
    var re = /^x-/; //properties to avoid
    for(var prop in schemaDataClone) {
      if (prop.match(re)) {
        delete schemaDataClone[prop];
      }
    }
    sd.Definition = jsonHelper.stringify(schemaDataClone, 4);
    result.push(sd);
  }
  return result;
};

Swagger.prototype._mapQueryString = function(params, resolvedParameters) {
  var queryString = {type:'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      //repsonses/parameters schemas
      param = resolvedParameters[i];
    }

    if (param.in && param.in !== 'query') {
      //skip other type of params
      continue;
    }
    queryString.properties[param.name] = swaggerHelper.setParameterFields(param, {});
    if (param.required) {
      queryString.required.push(param.name);
    }
  }
  return queryString;
};

Swagger.prototype._mapURIParams = function(params, resolvedParameters) {
  var pathParams = {type:'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      param = resolvedParameters[i];
    }

    if (param.in && param.in !== 'path') {
      //skip other type of params
      continue;
    }
    pathParams.properties[param.name] = swaggerHelper.setParameterFields(param, {});
    pathParams.required.push(param.name);
  }

  return pathParams;
};

Swagger.prototype._mapRequestBody = function(params, reqType, resolvedParams) {
  var data = {mimeType: reqType || null, body: {properties: {}, required: []}, example: ''};

  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      param = resolvedParams[i];
    }

    if (param.in && param.in !== 'body' && param.in !== 'formData') {
      continue;
    }
    switch(param.in) {
      case 'body':
        data.body = param.schema;
        break;
      case 'formData':
      default:
        var prop = {};
        prop = swaggerHelper.setParameterFields(param, prop);
        if (param.required) {
          data.body.required.push(param.name);
        }
        data.body.properties[param.name] = prop;
    }
  }
  //remove required field if doesn't have anything inside it
  if (data.body.required && data.body.required.length == 0) {
    delete data.body.required;
  }
  return data;
};

Swagger.prototype._mapResponseBody = function(responseBody, resType, resolvedResponses) {
  var data = [];
  for (var code in responseBody) {
    var res = {mimeType: resType, body: {}, example: '', codes: []}, description = '';

    if (needDeReferenced(responseBody[code])) {
        schema = resolvedResponses[code].schema;
        description = resolvedResponses[code].description || '';
        res.body = schema;
    } else if (responseBody[code].schema) {
      var schema = responseBody[code].schema;
      // TODO: Once we support headers, then support headers from swagger spec in responses.
      if (needDeReferenced(responseBody[code].schema)) {
        description = resolvedResponses[code].description || '';
        schema = resolvedResponses[code].schema;
      }
      res.body = schema;
    }

    if (responseBody[code].hasOwnProperty('examples')) {
      for(var t in responseBody[code].examples) {
        if (t === resType) {
          res.example = jsonHelper.stringify(responseBody[code].examples[t], 4);
        }
      }
    }

    res.description = description || responseBody[code].description || '';
    res.body = jsonHelper.stringify(res.body, 4);

    res.codes.push(code);
    data.push(res);
  }

  return data;
};

Swagger.prototype._mapRequestHeaders = function(params, resolvedParameters) {
  var data = {type: 'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      param = resolvedParameters[i];
    } else if (param.in !== 'header') {
      //skip other type of params
      continue;
    }
    data.properties[param.name] = swaggerHelper.setParameterFields(param, {});;
    if (param.required) {
      data.required.push(param.name);
    }
  }
  return data;
};

Swagger.prototype.loadFile = function (path, cb) {
  var me = this;
  this.filePath = path;

  parser.parse(path)
  .then(function(api, metadata) {
    me.data = api;
    me.metadata = metadata;
    parser.dereference(path)
      .then(function(dereferencedAPI) {
        try {
          me.dereferencedAPI = dereferencedAPI;
          cb();
        } catch(err) {
          //ignore reference error
          cb(err);
        }
      })
      .catch(cb);
  })
  .catch(cb);
};

Swagger.prototype.loadData = function(data, cb) {
  var me = this, parsedData;

  try {
    parsedData = JSON.parse(data);
  } catch(err) {
    //Possibly YAML Data
    try {
      parsedData = YAML.parse(data);
    } catch(err) {
      return cb(err);
    }
  }

  parser.parse(parsedData, function(err, api){
    if (err) {
      cb(err);
    } else {
      me.data = api;
      cb();
    }
  });
};

//for now, if 'application/json' exist in supported type, use that
Swagger.prototype.findDefaultMimeType = function(mimeTypes) {
  if (!mimeTypes || mimeTypes.length <= 0) {
    return 'application/json';
  }
  for(var i in mimeTypes) {
    if (mimeTypes[i] === 'application/json') {
      return mimeTypes[i];
    }
  }
  return mimeTypes[0];
};

Swagger.prototype._mapEndpoints = function(defaultReqContentType, defaultResContentType) {
  for (var path in this.data.paths) {
    var methods = this.data.paths[path];
    var pathParams = {};
    if (methods.parameters) {
      var resolvedPathParames = this.dereferencedAPI?this.dereferencedAPI.paths[path].parameters: methods.parameters;
      pathParams = this._mapURIParams(methods.parameters, resolvedPathParames);
    }

    for (var method in methods) {
      var currentMethod = methods[method];
      var currentMethodResolved = this.dereferencedAPI?this.dereferencedAPI.paths[path][method]: currentMethod;

      if (method === 'parameters') {
        continue;
      }
      var endpoint = new Endpoint(currentMethod.operationId || ''),
        reqType = defaultReqContentType,
        resType = defaultResContentType;

      endpoint.Path = path;
      endpoint.Method = method;

      endpoint.Description = currentMethod.description || currentMethod.summary;
      endpoint.Summary = currentMethod.summary || '';

      //map request body
      if (methods[method].consumes) {
        //taking only one
        reqType = this.findDefaultMimeType(currentMethod.consumes);
      }
      if (endpoint.Method.toLowerCase() !== 'get' &&
          endpoint.Method.toLowerCase() !== 'head') {
        endpoint.Body = this._mapRequestBody(currentMethod.parameters, reqType, currentMethodResolved.parameters);
      }

      //map response body
      if (methods[method].produces) {
        //taking only one
        resType = this.findDefaultMimeType(currentMethod.produces);
      }
      endpoint.Responses = this._mapResponseBody(currentMethod.responses, resType, currentMethodResolved.responses);

      //map query string
      endpoint.QueryString = this._mapQueryString(currentMethod.parameters, currentMethodResolved.parameters);

      //if path params are defined in this level
      pathParams = _.merge(pathParams, this._mapURIParams(currentMethod.parameters, currentMethodResolved.parameters));

      //map path params
      endpoint.PathParams = pathParams;

      //map headers
      endpoint.Headers = this._mapRequestHeaders(currentMethod.parameters, currentMethodResolved.parameters);

      //map security
      if (currentMethod.security) {
        var securities = currentMethod.security;
        for (var securityIndex in securities) {
          var keys = Object.keys(securities[securityIndex]);
          var securityName = keys[0];
          var scheme = this.data.securityDefinitions[securityName];
          if (!scheme) {
            //definition error
            continue;
          }
          switch(scheme.type) {
            case 'apiKey':
            case 'basic':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = true;
              break;
            case 'oauth2':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = securities[securityIndex][securityName];
              break;
          }
        }
      }

      this.project.addEndpoint(endpoint);
    }
  }
};

Swagger.prototype._import = function() {

  var defaultReqContentType = this.findDefaultMimeType(this.data.consumes),
      defaultResContentType = this.findDefaultMimeType(this.data.produces);

  this.project = new Project(this.data.info.title);
  this.project.Description = this.data.info.description || '';

  var protocol = 'http';
  if (this.data.schemes && this.data.schemes.length > 0) {
    this.project.Environment.Protocols = this.data.schemes;
    protocol = this.data.schemes[0];
  }

  this._mapEndpoints(defaultReqContentType, defaultResContentType);

  this.project.Environment.BasePath = this.data.basePath || '';
  this.project.Environment.Host = this.data.host?(protocol + '://' + this.data.host) : null;
  this.project.Environment.Version = this.data.info.version;

  if (this.data.produces) {
    //taking the first as default one
    this.project.Environment.DefaultResponseType = defaultResContentType;
  }

  if (this.data.consumes) {
    //taking the first as default one
    this.project.Environment.DefaultRequestType = defaultReqContentType;
  }
  if (this.data.securityDefinitions) {
    this.project.Environment.SecuritySchemes = this._mapSecurityDefinitions(this.data.securityDefinitions);
  }

  var schemas = this._mapSchema(this.data.definitions);
  for(var i in schemas) {
    this.project.addSchema(schemas[i]);
  }
};

module.exports = Swagger;
<commit_msg>- dereference api upon string data loading as well.<commit_after>var parser = require('swagger-parser'),
    Endpoint = require('../entities/endpoint'),
    Schema = require('../entities/schema'),
    Importer = require('./importer'),
    Project = require('../entities/project'),
    jsonHelper = require('../utils/json'),
    swaggerHelper = require('../helpers/swagger'),
    YAML = require('yamljs'),
    _ = require('lodash');

function Swagger() {
  this.dereferencedAPI = null;
}

function needDeReferenced(ref) {
  if (!ref['$ref']) {
    return false;
  }
  var regex = /\/(parameters|responses)\//i;
  if (ref['$ref'].match(regex)) {
    return true;
  }
  return false;
}

Swagger.prototype = new Importer();

Swagger.prototype._mapSecurityDefinitions = function(securityDefinitions) {
  var result = {};
  for(var name in securityDefinitions) {
    var type = securityDefinitions[name].type;
    if (!result.hasOwnProperty(type)) {
      result[type] = {};
    }
    var sd = securityDefinitions[name];
    switch(type) {
      case 'apiKey':
        var keyPlaceHolder = (sd.in === 'header')?'headers':'queryString';
        if (!result[type].hasOwnProperty(keyPlaceHolder)){
          result[type][keyPlaceHolder] = [];
        }
        result[type][keyPlaceHolder].push({
          name: sd.name,
          value: ''
        });
        break;
      case 'oauth2':
        result[type] = {
          name: name,
          authorizationUrl: sd.authorizationUrl || '',
          scopes: slScopes,
          tokenUrl: sd.tokenUrl || ''
        };

        var slScopes = [], swaggerScopes = sd.scopes;

        if (swaggerScopes) {
          for(var key in swaggerScopes) {
            var scope = {};
            scope['name'] = key;
            scope['value'] = swaggerScopes[key];
            slScopes.push(scope);
          }
        }

        if (sd.flow) {
          result[type]['flow'] = sd.flow;
        }

        if (slScopes.length > 0) {
          result[type]['scopes'] = slScopes;
        }

        break;
      case 'basic':
        result[type] = {
          name: name,
          value: '',
          description: sd.description || ''
        };
        break;
    }
  }
  return result;
};

Swagger.prototype._mapSchema = function(schemaDefinitions) {
  var result = [];
  for (var schemaName in schemaDefinitions) {
    var sd = new Schema(schemaName);
    sd.Name = schemaName;
    //create a close to remove extension properties
    var schemaDataClone = _.clone(schemaDefinitions[schemaName]);
    var re = /^x-/; //properties to avoid
    for(var prop in schemaDataClone) {
      if (prop.match(re)) {
        delete schemaDataClone[prop];
      }
    }
    sd.Definition = jsonHelper.stringify(schemaDataClone, 4);
    result.push(sd);
  }
  return result;
};

Swagger.prototype._mapQueryString = function(params, resolvedParameters) {
  var queryString = {type:'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      //repsonses/parameters schemas
      param = resolvedParameters[i];
    }

    if (param.in && param.in !== 'query') {
      //skip other type of params
      continue;
    }
    queryString.properties[param.name] = swaggerHelper.setParameterFields(param, {});
    if (param.required) {
      queryString.required.push(param.name);
    }
  }
  return queryString;
};

Swagger.prototype._mapURIParams = function(params, resolvedParameters) {
  var pathParams = {type:'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      param = resolvedParameters[i];
    }

    if (param.in && param.in !== 'path') {
      //skip other type of params
      continue;
    }
    pathParams.properties[param.name] = swaggerHelper.setParameterFields(param, {});
    pathParams.required.push(param.name);
  }

  return pathParams;
};

Swagger.prototype._mapRequestBody = function(params, reqType, resolvedParams) {
  var data = {mimeType: reqType || null, body: {properties: {}, required: []}, example: ''};

  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      param = resolvedParams[i];
    }

    if (param.in && param.in !== 'body' && param.in !== 'formData') {
      continue;
    }
    switch(param.in) {
      case 'body':
        data.body = param.schema;
        break;
      case 'formData':
      default:
        var prop = {};
        prop = swaggerHelper.setParameterFields(param, prop);
        if (param.required) {
          data.body.required.push(param.name);
        }
        data.body.properties[param.name] = prop;
    }
  }
  //remove required field if doesn't have anything inside it
  if (data.body.required && data.body.required.length == 0) {
    delete data.body.required;
  }
  return data;
};

Swagger.prototype._mapResponseBody = function(responseBody, resType, resolvedResponses) {
  var data = [];
  for (var code in responseBody) {
    var res = {mimeType: resType, body: {}, example: '', codes: []}, description = '';
    // TODO: Once we support headers, then support headers from swagger spec in responses.
    if (needDeReferenced(responseBody[code])) {
        schema = resolvedResponses[code].schema;
        description = resolvedResponses[code].description || '';
        res.body = schema;
    } else if (responseBody[code].schema) {
      var schema = responseBody[code].schema;
      if (needDeReferenced(responseBody[code].schema)) {
        description = resolvedResponses[code].description || '';
        schema = resolvedResponses[code].schema;
      }
      res.body = schema;
    }

    if (responseBody[code].hasOwnProperty('examples')) {
      for(var t in responseBody[code].examples) {
        if (t === resType) {
          res.example = jsonHelper.stringify(responseBody[code].examples[t], 4);
        }
      }
    }

    res.description = description || responseBody[code].description || '';
    res.body = jsonHelper.stringify(res.body, 4);

    res.codes.push(code);
    data.push(res);
  }

  return data;
};

Swagger.prototype._mapRequestHeaders = function(params, resolvedParameters) {
  var data = {type: 'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (needDeReferenced(param)) {
      param = resolvedParameters[i];
    } else if (param.in !== 'header') {
      //skip other type of params
      continue;
    }
    data.properties[param.name] = swaggerHelper.setParameterFields(param, {});;
    if (param.required) {
      data.required.push(param.name);
    }
  }
  return data;
};

Swagger.prototype._parseData = function(dataOrPath, cb) {
  var me = this;
  parser.parse(dataOrPath, function(err, api){
    if (err) {
      cb(err);
    } else {
      me.data = api;

      parser.dereference(JSON.parse(JSON.stringify(api)))
      .then(function(dereferencedAPI) {
        try {
          me.dereferencedAPI = dereferencedAPI;
          cb();
        } catch(err) {
          //ignore reference error
          cb(err);
        }
      })
      .catch(cb);
    }
  });
};

// Load a swagger spec by local or remote file path
Swagger.prototype.loadFile = function (path, cb) {
  return this._parseData(path, cb);
};

// Load a swagger spec by string data
Swagger.prototype.loadData = function(data, cb) {
  var me = this, parsedData;

  try {
    parsedData = JSON.parse(data);
  } catch(err) {
    //Possibly YAML Data
    try {
      parsedData = YAML.parse(data);
    } catch(err) {
      return cb(err);
    }
  }
  return this._parseData(parsedData, cb);
};

//for now, if 'application/json' exist in supported type, use that
Swagger.prototype.findDefaultMimeType = function(mimeTypes) {
  if (!mimeTypes || mimeTypes.length <= 0) {
    return 'application/json';
  }
  for(var i in mimeTypes) {
    if (mimeTypes[i] === 'application/json') {
      return mimeTypes[i];
    }
  }
  return mimeTypes[0];
};

Swagger.prototype._mapEndpoints = function(defaultReqContentType, defaultResContentType) {
  for (var path in this.data.paths) {
    var methods = this.data.paths[path];
    var pathParams = {};
    if (methods.parameters) {
      var resolvedPathParames = this.dereferencedAPI?this.dereferencedAPI.paths[path].parameters: methods.parameters;
      pathParams = this._mapURIParams(methods.parameters, resolvedPathParames);
    }

    for (var method in methods) {
      var currentMethod = methods[method];
      var currentMethodResolved = this.dereferencedAPI?this.dereferencedAPI.paths[path][method]: currentMethod;

      if (method === 'parameters') {
        continue;
      }
      var endpoint = new Endpoint(currentMethod.operationId || ''),
        reqType = defaultReqContentType,
        resType = defaultResContentType;

      endpoint.Path = path;
      endpoint.Method = method;

      endpoint.Description = currentMethod.description || currentMethod.summary;
      endpoint.Summary = currentMethod.summary || '';

      //map request body
      if (methods[method].consumes) {
        //taking only one
        reqType = this.findDefaultMimeType(currentMethod.consumes);
      }
      if (endpoint.Method.toLowerCase() !== 'get' &&
          endpoint.Method.toLowerCase() !== 'head') {
        endpoint.Body = this._mapRequestBody(currentMethod.parameters, reqType, currentMethodResolved.parameters);
      }

      //map response body
      if (methods[method].produces) {
        //taking only one
        resType = this.findDefaultMimeType(currentMethod.produces);
      }
      endpoint.Responses = this._mapResponseBody(currentMethod.responses, resType, currentMethodResolved.responses);

      //map query string
      endpoint.QueryString = this._mapQueryString(currentMethod.parameters, currentMethodResolved.parameters);

      //if path params are defined in this level
      pathParams = _.merge(pathParams, this._mapURIParams(currentMethod.parameters, currentMethodResolved.parameters));

      //map path params
      endpoint.PathParams = pathParams;

      //map headers
      endpoint.Headers = this._mapRequestHeaders(currentMethod.parameters, currentMethodResolved.parameters);

      //map security
      if (currentMethod.security) {
        var securities = currentMethod.security;
        for (var securityIndex in securities) {
          var keys = Object.keys(securities[securityIndex]);
          var securityName = keys[0];
          var scheme = this.data.securityDefinitions[securityName];
          if (!scheme) {
            //definition error
            continue;
          }
          switch(scheme.type) {
            case 'apiKey':
            case 'basic':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = true;
              break;
            case 'oauth2':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = securities[securityIndex][securityName];
              break;
          }
        }
      }

      this.project.addEndpoint(endpoint);
    }
  }
};

Swagger.prototype._import = function() {

  var defaultReqContentType = this.findDefaultMimeType(this.data.consumes),
      defaultResContentType = this.findDefaultMimeType(this.data.produces);

  this.project = new Project(this.data.info.title);
  this.project.Description = this.data.info.description || '';

  var protocol = 'http';
  if (this.data.schemes && this.data.schemes.length > 0) {
    this.project.Environment.Protocols = this.data.schemes;
    protocol = this.data.schemes[0];
  }

  this._mapEndpoints(defaultReqContentType, defaultResContentType);

  this.project.Environment.BasePath = this.data.basePath || '';
  this.project.Environment.Host = this.data.host?(protocol + '://' + this.data.host) : null;
  this.project.Environment.Version = this.data.info.version;

  if (this.data.produces) {
    //taking the first as default one
    this.project.Environment.DefaultResponseType = defaultResContentType;
  }

  if (this.data.consumes) {
    //taking the first as default one
    this.project.Environment.DefaultRequestType = defaultReqContentType;
  }
  if (this.data.securityDefinitions) {
    this.project.Environment.SecuritySchemes = this._mapSecurityDefinitions(this.data.securityDefinitions);
  }

  var schemas = this._mapSchema(this.data.definitions);
  for(var i in schemas) {
    this.project.addSchema(schemas[i]);
  }
};

module.exports = Swagger;
<|endoftext|>


<commit_before>/**
 * Copyright 2017, Google, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const {assert} = require('chai');
const {execSync} = require('child_process');

describe('dataproc samples', () => {
  it('should run the quickstart', async () => {
    const stdout = execSync('node quickstart');
    assert.match(stdout, /Total resources:/);
  });
});
<commit_msg>refactor: wrap execSync with encoding: utf-8 (#188)<commit_after>/**
 * Copyright 2017, Google, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const {assert} = require('chai');
const cp = require('child_process');

const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});

describe('dataproc samples', () => {
  it('should run the quickstart', async () => {
    const stdout = execSync('node quickstart');
    assert.match(stdout, /Total resources:/);
  });
});
<|endoftext|>


<commit_before>var createTorrent = require('../')
var crypto = require('crypto')
var parseTorrent = require('parse-torrent')
var test = require('tape')

function sha1 (buf) {
  return crypto.createHash('sha1').update(buf).digest('hex')
}

test('create single file torrent', function (t) {
  t.plan(12)

  var leavesPath = __dirname + '/content/Leaves of Grass by Walt Whitman.epub'

  var startTime = Date.now()
  createTorrent(leavesPath, function (err, torrent) {
    t.error(err)

    var parsedTorrent = parseTorrent(torrent)

    t.equals(parsedTorrent.name, 'Leaves of Grass by Walt Whitman.epub')

    t.notOk(parsedTorrent.private)

    var createdTime = parsedTorrent.created / 1000
    t.ok(createdTime >= startTime, 'created time is after start time')
    t.ok(createdTime <= Date.now(), 'created time is before now')

    t.deepEquals(parsedTorrent.announceList, [
      ['udp://tracker.publicbt.com:80'],
      ['udp://tracker.openbittorrent.com:80'],
      ['udp://tracker.webtorrent.io:80'],
      ['wss://tracker.webtorrent.io']
    ])

    t.equals(parsedTorrent.files[0].path, 'Leaves of Grass by Walt Whitman.epub')
    t.equals(parsedTorrent.files[0].length, 362017)

    t.equal(parsedTorrent.length, 362017)
    t.equal(parsedTorrent.pieceLength, 16384)

    t.deepEquals(parsedTorrent.pieces, [
      '1f9c3f59beec079715ec53324bde8569e4a0b4eb',
      'ec42307d4ce5557b5d3964c5ef55d354cf4a6ecc',
      '7bf1bcaf79d11fa5e0be06593c8faafc0c2ba2cf',
      '76d71c5b01526b23007f9e9929beafc5151e6511',
      '0931a1b44c21bf1e68b9138f90495e690dbc55f5',
      '72e4c2944cbacf26e6b3ae8a7229d88aafa05f61',
      'eaae6abf3f07cb6db9677cc6aded4dd3985e4586',
      '27567fa7639f065f71b18954304aca6366729e0b',
      '4773d77ae80caa96a524804dfe4b9bd3deaef999',
      'c9dd51027467519d5eb2561ae2cc01467de5f643',
      '0a60bcba24797692efa8770d23df0a830d91cb35',
      'b3407a88baa0590dc8c9aa6a120f274367dcd867',
      'e88e8338c572a06e3c801b29f519df532b3e76f6',
      '70cf6aee53107f3d39378483f69cf80fa568b1ea',
      'c53b506159e988d8bc16922d125d77d803d652c3',
      'ca3070c16eed9172ab506d20e522ea3f1ab674b3',
      'f923d76fe8f44ff32e372c3b376564c6fb5f0dbe',
      '52164f03629fd1322636babb2c014b7dae582da4',
      '1363965261e6ce12b43701f0a8c9ed1520a70eba',
      '004400a267765f6d3dd5c7beb5bd3c75f3df2a54',
      '560a61801147fa4ec7cf568e703acb04e5610a4d',
      '56dcc242d03293e9446cf5e457d8eb3d9588fd90',
      'c698de9b0dad92980906c026d8c1408fa08fe4ec'
    ])

    t.equals(sha1(parsedTorrent.infoBuffer), 'd2474e86c95b19b8bcfdb92bc12c9d44667cfa36')
  })
})

test('create multi file torrent', function (t) {
  t.plan(16)

  var numbersPath = __dirname + '/content/numbers'

  var startTime = Date.now()
  createTorrent(numbersPath, {
    pieceLength: 32768, // force piece length to 32KB so info-hash will
                        // match what transmission generataed, since we use
                        // a different algo for picking piece length

    private: false      // also force `private: false` to match transmission

  }, function (err, torrent) {
    t.error(err)

    var parsedTorrent = parseTorrent(torrent)

    t.equals(parsedTorrent.name, 'numbers')

    t.notOk(parsedTorrent.private)

    var createdTime = parsedTorrent.created / 1000
    t.ok(createdTime >= startTime, 'created time is after start time')
    t.ok(createdTime <= Date.now(), 'created time is before now')

    t.deepEquals(parsedTorrent.announceList, [
      ['udp://tracker.publicbt.com:80'],
      ['udp://tracker.openbittorrent.com:80'],
      ['udp://tracker.webtorrent.io:80'],
      ['wss://tracker.webtorrent.io']
    ])

    t.deepEquals(parsedTorrent.files[0].path, 'numbers/1.txt')
    t.deepEquals(parsedTorrent.files[0].length, 1)

    t.deepEquals(parsedTorrent.files[1].path, 'numbers/2.txt')
    t.deepEquals(parsedTorrent.files[1].length, 2)

    t.deepEquals(parsedTorrent.files[2].path, 'numbers/3.txt')
    t.deepEquals(parsedTorrent.files[2].length, 3)

    t.equal(parsedTorrent.length, 6)
    t.equal(parsedTorrent.pieceLength, 32768)

    t.deepEquals(parsedTorrent.pieces, [
      '1f74648e50a6a6708ec54ab327a163d5536b7ced'
    ])
    t.equals(sha1(parsedTorrent.infoBuffer), '80562f38656b385ea78959010e51a2cc9db41ea0')
  })
})

test('create multi file torrent with nested directories', function (t) {
  t.plan(22)

  var numbersPath = __dirname + '/content/lots-of-numbers'

  var startTime = Date.now()
  createTorrent(numbersPath, {
    pieceLength: 32768, // force piece length to 32KB so info-hash will
                        // match what transmission generataed, since we use
                        // a different algo for picking piece length

    private: false      // also force `private: false` to match transmission

  }, function (err, torrent) {
    t.error(err)

    var parsedTorrent = parseTorrent(torrent)

    t.equals(parsedTorrent.name, 'lots-of-numbers')

    t.notOk(parsedTorrent.private)

    var createdTime = parsedTorrent.created / 1000
    t.ok(createdTime >= startTime, 'created time is after start time')
    t.ok(createdTime <= Date.now(), 'created time is before now')

    t.deepEquals(parsedTorrent.announceList, [
      ['udp://tracker.publicbt.com:80'],
      ['udp://tracker.openbittorrent.com:80'],
      ['udp://tracker.webtorrent.io:80'],
      ['wss://tracker.webtorrent.io']
    ])

    t.deepEquals(parsedTorrent.files[0].path, 'lots-of-numbers/big numbers/10.txt')
    t.deepEquals(parsedTorrent.files[0].length, 2)

    t.deepEquals(parsedTorrent.files[1].path, 'lots-of-numbers/big numbers/11.txt')
    t.deepEquals(parsedTorrent.files[1].length, 2)

    t.deepEquals(parsedTorrent.files[2].path, 'lots-of-numbers/big numbers/12.txt')
    t.deepEquals(parsedTorrent.files[2].length, 2)

    t.deepEquals(parsedTorrent.files[3].path, 'lots-of-numbers/small numbers/1.txt')
    t.deepEquals(parsedTorrent.files[3].length, 1)

    t.deepEquals(parsedTorrent.files[4].path, 'lots-of-numbers/small numbers/2.txt')
    t.deepEquals(parsedTorrent.files[4].length, 2)

    t.deepEquals(parsedTorrent.files[5].path, 'lots-of-numbers/small numbers/3.txt')
    t.deepEquals(parsedTorrent.files[5].length, 3)

    t.equal(parsedTorrent.length, 12)
    t.equal(parsedTorrent.pieceLength, 32768)

    t.deepEquals(parsedTorrent.pieces, [
      '47972f2befaee58b6f3860cd39bd56cb33a488f0'
    ])

    t.equals(sha1(parsedTorrent.infoBuffer), '427887e9c03e123f9c8458b1947090edf1c75baa')
  })
})
<commit_msg>fix path separator comparison in Windows<commit_after>var path = require('path')
var createTorrent = require('../')
var crypto = require('crypto')
var parseTorrent = require('parse-torrent')
var test = require('tape')

function sha1 (buf) {
  return crypto.createHash('sha1').update(buf).digest('hex')
}

test('create single file torrent', function (t) {
  t.plan(12)

  var leavesPath = __dirname + '/content/Leaves of Grass by Walt Whitman.epub'

  var startTime = Date.now()
  createTorrent(leavesPath, function (err, torrent) {
    t.error(err)

    var parsedTorrent = parseTorrent(torrent)

    t.equals(parsedTorrent.name, 'Leaves of Grass by Walt Whitman.epub')

    t.notOk(parsedTorrent.private)

    var createdTime = parsedTorrent.created / 1000
    t.ok(createdTime >= startTime, 'created time is after start time')
    t.ok(createdTime <= Date.now(), 'created time is before now')

    t.deepEquals(parsedTorrent.announceList, [
      ['udp://tracker.publicbt.com:80'],
      ['udp://tracker.openbittorrent.com:80'],
      ['udp://tracker.webtorrent.io:80'],
      ['wss://tracker.webtorrent.io']
    ])

    t.equals(path.normalize(parsedTorrent.files[0].path), path.normalize('Leaves of Grass by Walt Whitman.epub'))
    t.equals(parsedTorrent.files[0].length, 362017)

    t.equal(parsedTorrent.length, 362017)
    t.equal(parsedTorrent.pieceLength, 16384)

    t.deepEquals(parsedTorrent.pieces, [
      '1f9c3f59beec079715ec53324bde8569e4a0b4eb',
      'ec42307d4ce5557b5d3964c5ef55d354cf4a6ecc',
      '7bf1bcaf79d11fa5e0be06593c8faafc0c2ba2cf',
      '76d71c5b01526b23007f9e9929beafc5151e6511',
      '0931a1b44c21bf1e68b9138f90495e690dbc55f5',
      '72e4c2944cbacf26e6b3ae8a7229d88aafa05f61',
      'eaae6abf3f07cb6db9677cc6aded4dd3985e4586',
      '27567fa7639f065f71b18954304aca6366729e0b',
      '4773d77ae80caa96a524804dfe4b9bd3deaef999',
      'c9dd51027467519d5eb2561ae2cc01467de5f643',
      '0a60bcba24797692efa8770d23df0a830d91cb35',
      'b3407a88baa0590dc8c9aa6a120f274367dcd867',
      'e88e8338c572a06e3c801b29f519df532b3e76f6',
      '70cf6aee53107f3d39378483f69cf80fa568b1ea',
      'c53b506159e988d8bc16922d125d77d803d652c3',
      'ca3070c16eed9172ab506d20e522ea3f1ab674b3',
      'f923d76fe8f44ff32e372c3b376564c6fb5f0dbe',
      '52164f03629fd1322636babb2c014b7dae582da4',
      '1363965261e6ce12b43701f0a8c9ed1520a70eba',
      '004400a267765f6d3dd5c7beb5bd3c75f3df2a54',
      '560a61801147fa4ec7cf568e703acb04e5610a4d',
      '56dcc242d03293e9446cf5e457d8eb3d9588fd90',
      'c698de9b0dad92980906c026d8c1408fa08fe4ec'
    ])

    t.equals(sha1(parsedTorrent.infoBuffer), 'd2474e86c95b19b8bcfdb92bc12c9d44667cfa36')
  })
})

test('create multi file torrent', function (t) {
  t.plan(16)

  var numbersPath = __dirname + '/content/numbers'

  var startTime = Date.now()
  createTorrent(numbersPath, {
    pieceLength: 32768, // force piece length to 32KB so info-hash will
                        // match what transmission generataed, since we use
                        // a different algo for picking piece length

    private: false      // also force `private: false` to match transmission

  }, function (err, torrent) {
    t.error(err)

    var parsedTorrent = parseTorrent(torrent)

    t.equals(parsedTorrent.name, 'numbers')

    t.notOk(parsedTorrent.private)

    var createdTime = parsedTorrent.created / 1000
    t.ok(createdTime >= startTime, 'created time is after start time')
    t.ok(createdTime <= Date.now(), 'created time is before now')

    t.deepEquals(parsedTorrent.announceList, [
      ['udp://tracker.publicbt.com:80'],
      ['udp://tracker.openbittorrent.com:80'],
      ['udp://tracker.webtorrent.io:80'],
      ['wss://tracker.webtorrent.io']
    ])

    t.deepEquals(path.normalize(parsedTorrent.files[0].path), path.normalize('numbers/1.txt'))
    t.deepEquals(parsedTorrent.files[0].length, 1)

    t.deepEquals(path.normalize(parsedTorrent.files[1].path), path.normalize('numbers/2.txt'))
    t.deepEquals(parsedTorrent.files[1].length, 2)

    t.deepEquals(path.normalize(parsedTorrent.files[2].path), path.normalize('numbers/3.txt'))
    t.deepEquals(parsedTorrent.files[2].length, 3)

    t.equal(parsedTorrent.length, 6)
    t.equal(parsedTorrent.pieceLength, 32768)

    t.deepEquals(parsedTorrent.pieces, [
      '1f74648e50a6a6708ec54ab327a163d5536b7ced'
    ])
    t.equals(sha1(parsedTorrent.infoBuffer), '80562f38656b385ea78959010e51a2cc9db41ea0')
  })
})

test('create multi file torrent with nested directories', function (t) {
  t.plan(22)

  var numbersPath = __dirname + '/content/lots-of-numbers'

  var startTime = Date.now()
  createTorrent(numbersPath, {
    pieceLength: 32768, // force piece length to 32KB so info-hash will
                        // match what transmission generataed, since we use
                        // a different algo for picking piece length

    private: false      // also force `private: false` to match transmission

  }, function (err, torrent) {
    t.error(err)

    var parsedTorrent = parseTorrent(torrent)

    t.equals(parsedTorrent.name, 'lots-of-numbers')

    t.notOk(parsedTorrent.private)

    var createdTime = parsedTorrent.created / 1000
    t.ok(createdTime >= startTime, 'created time is after start time')
    t.ok(createdTime <= Date.now(), 'created time is before now')

    t.deepEquals(parsedTorrent.announceList, [
      ['udp://tracker.publicbt.com:80'],
      ['udp://tracker.openbittorrent.com:80'],
      ['udp://tracker.webtorrent.io:80'],
      ['wss://tracker.webtorrent.io']
    ])

    t.deepEquals(path.normalize(parsedTorrent.files[0].path), path.normalize('lots-of-numbers/big numbers/10.txt'))
    t.deepEquals(parsedTorrent.files[0].length, 2)

    t.deepEquals(path.normalize(parsedTorrent.files[1].path), path.normalize('lots-of-numbers/big numbers/11.txt'))
    t.deepEquals(parsedTorrent.files[1].length, 2)

    t.deepEquals(path.normalize(parsedTorrent.files[2].path), path.normalize('lots-of-numbers/big numbers/12.txt'))
    t.deepEquals(parsedTorrent.files[2].length, 2)

    t.deepEquals(path.normalize(parsedTorrent.files[3].path), path.normalize('lots-of-numbers/small numbers/1.txt'))
    t.deepEquals(parsedTorrent.files[3].length, 1)

    t.deepEquals(path.normalize(parsedTorrent.files[4].path), path.normalize('lots-of-numbers/small numbers/2.txt'))
    t.deepEquals(parsedTorrent.files[4].length, 2)

    t.deepEquals(path.normalize(parsedTorrent.files[5].path), path.normalize('lots-of-numbers/small numbers/3.txt'))
    t.deepEquals(parsedTorrent.files[5].length, 3)

    t.equal(parsedTorrent.length, 12)
    t.equal(parsedTorrent.pieceLength, 32768)

    t.deepEquals(parsedTorrent.pieces, [
      '47972f2befaee58b6f3860cd39bd56cb33a488f0'
    ])

    t.equals(sha1(parsedTorrent.infoBuffer), '427887e9c03e123f9c8458b1947090edf1c75baa')
  })
})
<|endoftext|>


<commit_before>var npa = require("../npa.js")
var path = require("path")

require("tap").test("basic", function (t) {
  t.setMaxListeners(999)

  var tests = {
    "foo@1.2": {
      name: "foo",
      type: "range",
      spec: ">=1.2.0 <1.3.0",
      raw: "foo@1.2",
      rawSpec: "1.2"
    },

    "@foo/bar": {
      raw: "@foo/bar",
      name: "@foo/bar",
      scope: "@foo",
      rawSpec: "",
      spec: "*",
      type: "range"
    },

    "@foo/bar@": {
      raw: "@foo/bar@",
      name: "@foo/bar",
      scope: "@foo",
      rawSpec: "",
      spec: "*",
      type: "range"
    },

    "@foo/bar@baz": {
      raw: "@foo/bar@baz",
      name: "@foo/bar",
      scope: "@foo",
      rawSpec: "baz",
      spec: "baz",
      type: "tag"
    },

    "@f fo o al/ a d s ;f ": {
      raw: "@f fo o al/ a d s ;f",
      name: null,
      rawSpec: "@f fo o al/ a d s ;f",
      spec: path.resolve("@f fo o al/ a d s ;f"),
      type: "local"
    },

    "foo@1.2.3": {
      name: "foo",
      type: "version",
      spec: "1.2.3",
      raw: "foo@1.2.3"
    },

    "foo@=v1.2.3": {
      name: "foo",
      type: "version",
      spec: "1.2.3",
      raw: "foo@=v1.2.3",
      rawSpec: "=v1.2.3"
    },

    "git+ssh://git@notgithub.com/user/foo#1.2.3": {
      name: null,
      type: "git",
      spec: "ssh://git@notgithub.com/user/foo#1.2.3",
      raw: "git+ssh://git@notgithub.com/user/foo#1.2.3"
    },

    "git+file://path/to/repo#1.2.3": {
      name: null,
      type: "git",
      spec: "file://path/to/repo#1.2.3",
      raw: "git+file://path/to/repo#1.2.3"
    },

    "git://notgithub.com/user/foo": {
      name: null,
      type: "git",
      spec: "git://notgithub.com/user/foo",
      raw: "git://notgithub.com/user/foo"
    },

    "@foo/bar@git+ssh://notgithub.com/user/foo": {
      name: "@foo/bar",
      scope: "@foo",
      spec: "ssh://notgithub.com/user/foo",
      rawSpec: "git+ssh://notgithub.com/user/foo",
      raw: "@foo/bar@git+ssh://notgithub.com/user/foo"
    },

    "/path/to/foo": {
      name: null,
      type: "local",
      spec: "/path/to/foo",
      raw: "/path/to/foo"
    },

    "file:path/to/foo": {
      name: null,
      type: "local",
      spec: "path/to/foo",
      raw: "file:path/to/foo"
    },

    "file:~/path/to/foo": {
      name: null,
      type: "local",
      spec: "~/path/to/foo",
      raw: "file:~/path/to/foo"
    },

    "file:../path/to/foo": {
      name: null,
      type: "local",
      spec: "../path/to/foo",
      raw: "file:../path/to/foo"
    },

    "file:///path/to/foo": {
      name: null,
      type: "local",
      spec: "/path/to/foo",
      raw: "file:///path/to/foo"
    },

    "https://server.com/foo.tgz": {
      name: null,
      type: "remote",
      spec: "https://server.com/foo.tgz",
      raw: "https://server.com/foo.tgz"
    },

    "foo@latest": {
      name: "foo",
      type: "tag",
      spec: "latest",
      raw: "foo@latest"
    },

    "foo": {
      name: "foo",
      type: "range",
      spec: "*",
      raw: "foo"
    }
  }

  Object.keys(tests).forEach(function (arg) {
    var res = npa(arg)
    t.type(res, "Result", arg + " is result")
    t.has(res, tests[arg], arg + " matches expectations")
  })

  // Completely unreasonable invalid garbage throws an error
  t.throws(function() {
    npa("this is not a \0 valid package name or url")
  })

  t.throws(function() {
    npa("gopher://yea right")
  }, "Unsupported URL Type: gopher://yea right")

  t.end()
})
<commit_msg>Fix: /path/to/foo test in windows<commit_after>var npa = require("../npa.js")
var path = require("path")

require("tap").test("basic", function (t) {
  t.setMaxListeners(999)

  var tests = {
    "foo@1.2": {
      name: "foo",
      type: "range",
      spec: ">=1.2.0 <1.3.0",
      raw: "foo@1.2",
      rawSpec: "1.2"
    },

    "@foo/bar": {
      raw: "@foo/bar",
      name: "@foo/bar",
      scope: "@foo",
      rawSpec: "",
      spec: "*",
      type: "range"
    },

    "@foo/bar@": {
      raw: "@foo/bar@",
      name: "@foo/bar",
      scope: "@foo",
      rawSpec: "",
      spec: "*",
      type: "range"
    },

    "@foo/bar@baz": {
      raw: "@foo/bar@baz",
      name: "@foo/bar",
      scope: "@foo",
      rawSpec: "baz",
      spec: "baz",
      type: "tag"
    },

    "@f fo o al/ a d s ;f ": {
      raw: "@f fo o al/ a d s ;f",
      name: null,
      rawSpec: "@f fo o al/ a d s ;f",
      spec: path.resolve("@f fo o al/ a d s ;f"),
      type: "local"
    },

    "foo@1.2.3": {
      name: "foo",
      type: "version",
      spec: "1.2.3",
      raw: "foo@1.2.3"
    },

    "foo@=v1.2.3": {
      name: "foo",
      type: "version",
      spec: "1.2.3",
      raw: "foo@=v1.2.3",
      rawSpec: "=v1.2.3"
    },

    "git+ssh://git@notgithub.com/user/foo#1.2.3": {
      name: null,
      type: "git",
      spec: "ssh://git@notgithub.com/user/foo#1.2.3",
      raw: "git+ssh://git@notgithub.com/user/foo#1.2.3"
    },

    "git+file://path/to/repo#1.2.3": {
      name: null,
      type: "git",
      spec: "file://path/to/repo#1.2.3",
      raw: "git+file://path/to/repo#1.2.3"
    },

    "git://notgithub.com/user/foo": {
      name: null,
      type: "git",
      spec: "git://notgithub.com/user/foo",
      raw: "git://notgithub.com/user/foo"
    },

    "@foo/bar@git+ssh://notgithub.com/user/foo": {
      name: "@foo/bar",
      scope: "@foo",
      spec: "ssh://notgithub.com/user/foo",
      rawSpec: "git+ssh://notgithub.com/user/foo",
      raw: "@foo/bar@git+ssh://notgithub.com/user/foo"
    },

    "/path/to/foo": {
      name: null,
      type: "local",
      spec: path.resolve(__dirname, "/path/to/foo"),
      raw: "/path/to/foo"
    },

    "file:path/to/foo": {
      name: null,
      type: "local",
      spec: "path/to/foo",
      raw: "file:path/to/foo"
    },

    "file:~/path/to/foo": {
      name: null,
      type: "local",
      spec: "~/path/to/foo",
      raw: "file:~/path/to/foo"
    },

    "file:../path/to/foo": {
      name: null,
      type: "local",
      spec: "../path/to/foo",
      raw: "file:../path/to/foo"
    },

    "file:///path/to/foo": {
      name: null,
      type: "local",
      spec: "/path/to/foo",
      raw: "file:///path/to/foo"
    },

    "https://server.com/foo.tgz": {
      name: null,
      type: "remote",
      spec: "https://server.com/foo.tgz",
      raw: "https://server.com/foo.tgz"
    },

    "foo@latest": {
      name: "foo",
      type: "tag",
      spec: "latest",
      raw: "foo@latest"
    },

    "foo": {
      name: "foo",
      type: "range",
      spec: "*",
      raw: "foo"
    }
  }

  Object.keys(tests).forEach(function (arg) {
    var res = npa(arg)
    t.type(res, "Result", arg + " is result")
    t.has(res, tests[arg], arg + " matches expectations")
  })

  // Completely unreasonable invalid garbage throws an error
  t.throws(function() {
    npa("this is not a \0 valid package name or url")
  })

  t.throws(function() {
    npa("gopher://yea right")
  }, "Unsupported URL Type: gopher://yea right")

  t.end()
})
<|endoftext|>


<commit_before>var nodeunit = require('nodeunit'), fs = require('fs');
var GQ = require('../index');

var data_types = new Array();
module.exports = nodeunit.testCase({
  'one-task': function(t) {

    var q = GQ(), pkgj = './task-test1.json';
    var p = {}, task_ids = [];
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push(type), type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      q.destroy(), t.ok(true, 'one-task: going to done.');
      t.done();
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  },
  'two-tasks': function(t) {

    var q = GQ(), pkgjs = ['./task-test1.json', './task-test2.json'];
    var p = {}, task_ids = [];

    var pkgcs = pkgjs.map(function(pkgj) {
      return JSON.parse(fs.readFileSync(pkgj).toString());
    });

    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      var pkgc = (pkgcs[0].taskList.length == 0 ? pkgcs.shift(): pkgcs[0]);
      data_types.push(type), type == 'finish' && (function(name) {
        var pkgc = pkgcs[pkgcs[0].taskList[0] == name ? 0: 1];
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      if(task_ids.length == 0) {
        q.destroy(), t.ok(true, 'two-tasks: going to done.');
        t.done();
      }
    }));

    pkgjs.forEach(function(pkgj, i) {
      _setConcatTaskp(p, i + 1), _setUglifyTaskp(p);
      q.enqueue(pkgj, p, {
        workdir: __dirname
      }).on('end', function(_id, task) {
        t.equal(_id.length, 32), t.equal(task._id, _id);
        task_ids.push(_id);
      });
    });

  },
  'error-task': function(t) {

    var q = GQ(), pkgj = './task-teste.json';
    var p = {}, task_ids = [], e = 1;
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push(type), type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('error', function() {
      e--;
      q.progress(task_ids[0], function(err, data) {
        t.equal(data.state, 'error');
        t.ok(data.progress instanceof Error);
      });
      if(e === 0)
        setTimeout(function() {
          q.progress(task_ids[0], function(err, data) {
            t.equal(e, 0);
            t.equal(data.state, 'error');
            t.ok(data.progress instanceof Error);
            q.destroy(), t.ok(true, 'error-task: going to done.');
            // 2(start, finish) * 7 (complete-task-num) + 1 * 1 (error-task-num)
            t.equals(data_types.length, 2 * 7 + 1), t.done();
          });
        }, 5000);
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname,
      timeout: 10 * 1000
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  }
});

function _setConcatTaskp(p, tidx) {
  p.concat = {};
  p.concat.options = {
    separator: ";"
  };
  p.concat.dist = {
    src: ["src/test" + tidx + "/*.js"],
    dest: "dist/<%= pkg.name %>.js"
  };
}

function _setUglifyTaskp(p) {
  p.uglify = {};
  p.uglify.options = {
    banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
  };
  p.uglify.dist = {
    files: {
      'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
    }
  };
}

function _bindLogging(ee) {
  ee.on('ready', function() {
    //console.log('ready', arguments);
  }).on('error', function() {
    console.error(arguments);
  }).on('busy', function() {
    console.error('onbusy', arguments);
  }).on('empty', function() {
    console.error('onempty', arguments);
  }).on('data', function() {
    //console.log('ondata', arguments);
  }).on('progress', function() {
    //console.log('onprogress', arguments);
  });
}

function chkReady(q, t) {
  // q._ready has been set true.
  t.ok(q._ready);
}

function chkProgress(q, t, task_id, task_ids) {

  // task_id has been returned after enqueue
  t.ok(~task_ids.indexOf(task_id), 'Task #' + task_id + ' end.');

  t.equal(GQ.Task.countAlives(), task_ids.length);
  q.dequeue(task_id);

  // dequeue twice is not allowed
  try {
    q.dequeue(task_id)
  } catch(e) {
    t.equal(/The task is not found./.test(e.message), true);
  }

  task_ids.splice(task_ids.indexOf(task_id), 1);
  t.equal(GQ.Task.countAlives(), task_ids.length);
  t.equal(q._q.length, 1);
  t.equal(Object.keys(q._fq).length, 0);
  t.equal(q._workers.length, require('os').cpus().length);

}
<commit_msg>for debug on travis <commit_after>var nodeunit = require('nodeunit'), fs = require('fs');
var GQ = require('../index');

var data_types = new Array();
module.exports = nodeunit.testCase({
  'one-task': function(t) {

    var q = GQ(), pkgj = './task-test1.json';
    var p = {}, task_ids = [];
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      q.destroy(), t.ok(true, 'one-task: going to done.');
      t.done();
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  },
  'two-tasks': function(t) {

    var q = GQ(), pkgjs = ['./task-test1.json', './task-test2.json'];
    var p = {}, task_ids = [];

    var pkgcs = pkgjs.map(function(pkgj) {
      return JSON.parse(fs.readFileSync(pkgj).toString());
    });

    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      var pkgc = (pkgcs[0].taskList.length == 0 ? pkgcs.shift(): pkgcs[0]);
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        var pkgc = pkgcs[pkgcs[0].taskList[0] == name ? 0: 1];
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      if(task_ids.length == 0) {
        q.destroy(), t.ok(true, 'two-tasks: going to done.');
        t.done();
      }
    }));

    pkgjs.forEach(function(pkgj, i) {
      _setConcatTaskp(p, i + 1), _setUglifyTaskp(p);
      q.enqueue(pkgj, p, {
        workdir: __dirname
      }).on('end', function(_id, task) {
        t.equal(_id.length, 32), t.equal(task._id, _id);
        task_ids.push(_id);
      });
    });

  },
  'error-task': function(t) {

    var q = GQ(), pkgj = './task-teste.json';
    var p = {}, task_ids = [], e = 1;
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('error', function() {
      e--;
      q.progress(task_ids[0], function(err, data) {
        t.equal(data.state, 'error');
        t.ok(data.progress instanceof Error);
      });
      if(e === 0)
        setTimeout(function() {
          q.progress(task_ids[0], function(err, data) {
            t.equal(e, 0);
            t.equal(data.state, 'error');
            t.ok(data.progress instanceof Error);
            q.destroy(), t.ok(true, 'error-task: going to done.');
            // 2(start, finish) * 8 (complete-task-num) + 1 * 1 (error-task-num)
            console.log(data_types); // for debug.
            t.equals(data_types.length, 2 * 7 + 1), t.done();
          });
        }, 5000);
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname,
      timeout: 10 * 1000
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  }
});

function _setConcatTaskp(p, tidx) {
  p.concat = {};
  p.concat.options = {
    separator: ";"
  };
  p.concat.dist = {
    src: ["src/test" + tidx + "/*.js"],
    dest: "dist/<%= pkg.name %>.js"
  };
}

function _setUglifyTaskp(p) {
  p.uglify = {};
  p.uglify.options = {
    banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
  };
  p.uglify.dist = {
    files: {
      'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
    }
  };
}

function _bindLogging(ee) {
  ee.on('ready', function() {
    //console.log('ready', arguments);
  }).on('error', function() {
    console.error(arguments);
  }).on('busy', function() {
    console.error('onbusy', arguments);
  }).on('empty', function() {
    console.error('onempty', arguments);
  }).on('data', function() {
    //console.log('ondata', arguments);
  }).on('progress', function() {
    //console.log('onprogress', arguments);
  });
}

function chkReady(q, t) {
  // q._ready has been set true.
  t.ok(q._ready);
}

function chkProgress(q, t, task_id, task_ids) {

  // task_id has been returned after enqueue
  t.ok(~task_ids.indexOf(task_id), 'Task #' + task_id + ' end.');

  t.equal(GQ.Task.countAlives(), task_ids.length);
  q.dequeue(task_id);

  // dequeue twice is not allowed
  try {
    q.dequeue(task_id)
  } catch(e) {
    t.equal(/The task is not found./.test(e.message), true);
  }

  task_ids.splice(task_ids.indexOf(task_id), 1);
  t.equal(GQ.Task.countAlives(), task_ids.length);
  t.equal(q._q.length, 1);
  t.equal(Object.keys(q._fq).length, 0);
  t.equal(q._workers.length, require('os').cpus().length);

}
<|endoftext|>


<commit_before>var nodeunit = require('nodeunit');
var jsdom = require("jsdom");

var repo_be = 'https://raw.github.com/ystskm/browser-emitter-js/';
var repo_ne = 'https://raw.github.com/ystskm/noleak-emitter-js/';

var scripts = [];
scripts.push(repo_be + "master/Emitter.js");
scripts.push(repo + "master/NoleakEmitter.js");

function setup(callback) {
  jsdom.env("", {
    scripts: scripts
  }, function(errors, window) {
    errors && console.error(errors), callback(window);
  });
}

module.exports = nodeunit.testCase({
  'readme': function(t) {
    setup(function(window) {

      var TestEmitter = window.NoleakEmitter;
      t.equal(typeof TestEmitter, 'function');

      var emitter = new TestEmitter();
      var cnt = 0;

      emitter.on('readme-test', function() {
        t.equal(arguments[0], 0);
        t.equal(arguments[1], 1);
        t.equal(arguments[2], 2);
        cnt++;
      });
      emitter.on('error', function() {
        t.equal(arguments[0], 3);
        t.equal(arguments[1], 4);
        t.equal(arguments[2], 5);
        cnt++;
      });
      emitter.on('end', function() {
        t.equal(arguments[0], 3);
        t.equal(arguments[1], 4);
        t.equal(arguments[2], 5);
        cnt++;
      });

      emitter.emit('readme-test', 0, 1, 2);
      emitter.emit('end', 3, 4, 5);

      setTimeout(function() {
        emitter.emit('readme-test');
        emitter.emit('error');
        emitter.emit('end');
        t.equal(cnt, 2);
        t.done();
      }, 4);
    });
  }
});
<commit_msg>update test<commit_after>var nodeunit = require('nodeunit');
var jsdom = require("jsdom");

var repo_be = 'https://raw.github.com/ystskm/browser-emitter-js/';
var repo_ne = 'https://raw.github.com/ystskm/noleak-emitter-js/';

var scripts = [];
scripts.push(repo_be + "master/Emitter.js");
scripts.push(repo_ne + "master/NoleakEmitter.js");

function setup(callback) {
  jsdom.env("", {
    scripts: scripts
  }, function(errors, window) {
    errors && console.error(errors), callback(window);
  });
}

module.exports = nodeunit.testCase({
  'readme': function(t) {
    setup(function(window) {

      var TestEmitter = window.NoleakEmitter;
      t.equal(typeof TestEmitter, 'function');

      var emitter = new TestEmitter();
      var cnt = 0;

      emitter.on('readme-test', function() {
        t.equal(arguments[0], 0);
        t.equal(arguments[1], 1);
        t.equal(arguments[2], 2);
        cnt++;
      });
      emitter.on('error', function() {
        t.equal(arguments[0], 3);
        t.equal(arguments[1], 4);
        t.equal(arguments[2], 5);
        cnt++;
      });
      emitter.on('end', function() {
        t.equal(arguments[0], 3);
        t.equal(arguments[1], 4);
        t.equal(arguments[2], 5);
        cnt++;
      });

      emitter.emit('readme-test', 0, 1, 2);
      emitter.emit('end', 3, 4, 5);

      setTimeout(function() {
        emitter.emit('readme-test');
        emitter.emit('error');
        emitter.emit('end');
        t.equal(cnt, 2);
        t.done();
      }, 4);
    });
  }
});
<|endoftext|>


<commit_before>var createContext = require('./util/create-context')
var createREGL = require('../regl')
var tape = require('tape')

function find (array, pred) {
  for (var i = 0; i < array.length; ++i) {
    if (pred(array[i])) {
      return array[i]
    }
  }
}

tape('batch', function (t) {
  setTimeout(function () {
    var gl = createContext(5, 5)
    var regl = createREGL(gl)

    var points = [
      [2, 2],
      [0, 2],
      [2, 0],
      [4, 2],
      [2, 4]
    ]

    regl.clear({
      color: [1, 0, 0, 1]
    })

    var drawBatch = regl({
      frag: [
        'void main() {',
        '  gl_FragColor = vec4(0, 0, 1, 1);',
        '}'
      ].join('\n'),

      vert: [
        'attribute vec2 position;',
        'uniform vec2 offset;',
        'void main() {',
        '  gl_Position = vec4(position + offset, 0, 1);',
        '}'
      ].join('\n'),

      attributes: {
        position: regl.buffer([
          [0, 0]
        ])
      },

      uniforms: {
        offset: regl.prop('offset')
      },

      count: 1,

      depth: {enable: false},

      primitive: 'points'
    })

    var drawBatchCount = regl({
      frag: [
        'void main() {',
        '  gl_FragColor = vec4(0, 0, 1, 1);',
        '}'
      ].join('\n'),

      vert: [
        'attribute vec2 position;',
        'uniform vec2 offset;',
        'void main() {',
        '  gl_Position = vec4(position + offset, 0, 1);',
        '}'
      ].join('\n'),

      attributes: {
        position: regl.buffer([
          [0, 0]
        ])
      },

      uniforms: {
        offset: function (context, props, batchId) {
          var p = points[batchId]
          return [(p[0] - 2.0) / 2.1, (p[1] - 2.0) / 2.1]
        }
      },

      count: 1,

      depth: {enable: false},

      primitive: 'points'
    })

    function runTest () {
      var pixels = regl.read()

      for (var i = 0; i < 5; ++i) {
        for (var j = 0; j < 5; ++j) {
          var ptr = 4 * (5 * i + j)
          var hit = !!find(points, function (p) {
            return p[0] === i && p[1] === j
          })
          var actual = [
            pixels[ptr],
            pixels[ptr + 1],
            pixels[ptr + 2],
            pixels[ptr + 3]
          ]
          var expected = hit ? [0, 0, 255, 255] : [255, 0, 0, 255]
          t.same(actual, expected, (hit ? '*' : '_') + ' @ ' + [i, j])
        }
      }
    }

    drawBatch(points.map(function (p) {
      return {
        offset: [(p[0] - 2.0) / 2.1, (p[1] - 2.0) / 2.1]
      }
    }))
    runTest()

    drawBatchCount(points.length)
    runTest()

    regl.destroy()
    createContext.destroy(gl)
    t.end()
  }, 120)
})
<commit_msg>switch viewport size in batch test to 8x8<commit_after>var createContext = require('./util/create-context')
var createREGL = require('../regl')
var tape = require('tape')

function find (array, pred) {
  for (var i = 0; i < array.length; ++i) {
    if (pred(array[i])) {
      return array[i]
    }
  }
}

tape('batch', function (t) {
  setTimeout(function () {
    var gl = createContext(8, 8)
    var regl = createREGL(gl)

    var points = [
      [2, 2],
      [0, 2],
      [2, 0],
      [4, 2],
      [2, 4]
    ]

    regl.clear({
      color: [1, 0, 0, 1]
    })

    var drawBatch = regl({
      frag: [
        'void main() {',
        '  gl_FragColor = vec4(0, 0, 1, 1);',
        '}'
      ].join('\n'),

      vert: [
        'attribute vec2 position;',
        'uniform vec2 offset;',
        'void main() {',
        '  gl_Position = vec4(0.25 * (position + offset - 3.5), 0, 1);',
        '}'
      ].join('\n'),

      attributes: {
        position: regl.buffer([
          [0, 0]
        ])
      },

      uniforms: {
        offset: regl.prop('offset')
      },

      count: 1,

      depth: {enable: false},

      primitive: 'points'
    })

    var drawBatchCount = regl({
      frag: [
        'void main() {',
        '  gl_FragColor = vec4(0, 0, 1, 1);',
        '}'
      ].join('\n'),

      vert: [
        'attribute vec2 position;',
        'uniform vec2 offset;',
        'void main() {',
        '  gl_Position = vec4(0.25 * (position + offset - 3.5), 0, 1);',
        '}'
      ].join('\n'),

      attributes: {
        position: regl.buffer([
          [0, 0]
        ])
      },

      uniforms: {
        offset: function (context, props, batchId) {
          return points[batchId]
        }
      },

      count: 1,

      depth: {enable: false},

      primitive: 'points'
    })

    function runTest () {
      var pixels = regl.read()

      for (var i = 0; i < 8; ++i) {
        for (var j = 0; j < 8; ++j) {
          var ptr = 4 * (8 * i + j)
          var hit = !!find(points, function (p) {
            return p[0] === i && p[1] === j
          })
          var actual = [
            pixels[ptr],
            pixels[ptr + 1],
            pixels[ptr + 2],
            pixels[ptr + 3]
          ]
          var expected = hit ? [0, 0, 255, 255] : [255, 0, 0, 255]
          t.same(actual, expected, (hit ? '*' : '_') + ' @ ' + [i, j])
        }
      }
    }

    drawBatch(points.map(function (p) {
      return {
        offset: p
      }
    }))
    runTest()

    drawBatchCount(points.length)
    runTest()

    regl.destroy()
    createContext.destroy(gl)
    t.end()
  }, 120)
})
<|endoftext|>