<commit_before>'use strict'

/* global describe */
/* global it */

var assert = require('chai').assert
var createIndex = require('../src/mindex')

var testdb = [
  { age: 46,
  id: 'Lamar Goodwin',
  phone: '817-529-2557',
  title: 'Global Usability Coordinator' },
  { age: 13,
  id: 'Elmo Hansen',
  phone: '1-632-301-4062 x8351',
  title: 'Customer Paradigm Assistant' },
  { age: 43,
  id: 'Ashton Oberbrunner',
  phone: '1-292-015-9298 x19171',
  title: 'Legacy Security Planner' },
  { age: 32,
  id: 'Ms. Kiera Hodkiewicz',
  phone: '1-742-905-8677',
  title: 'Legacy Security Planner' },
  { age: 10,
  id: 'Hilda O\'Kon',
  phone: '118.357.9132 x76245',
  title: 'Dynamic Communications Agent' },
  { age: 38,
  id: 'Leland Bahringer',
  phone: '114.754.5482 x7853',
  title: 'Internal Program Officer' },
  { age: 21,
  id: 'Axel Block',
  phone: '816-557-8326 x083',
  title: 'Forward Interactions Liason' },
  { age: 14,
  id: 'Wendy Dare',
  phone: '966.968.5997 x42838',
  title: 'Infrastructure Associate' },
  { age: 23,
  id: 'Miss Fermin Bartell',
  phone: '(003) 694-6712',
  title: 'Product Applications Designer' },
  { age: 68,
  id: 'Marquise Weimann',
  phone: '400.157.6206',
  title: 'Corporate Response Orchestrator' },
  { age: 24,
  id: 'Kaley Jones',
  phone: '1-426-266-8041',
  title: 'District Brand Producer' },
  { age: 51,
  id: 'Dr. Jess Stokes',
  phone: '1-754-630-5989 x8753',
  title: 'Chief Tactics Supervisor' },
  { age: 24,
  id: 'Durward Runolfsson',
  phone: '726.255.5565',
  title: 'Regional Configuration Planner' },
  { age: 64,
  id: 'Clemens Howell Dr.',
  phone: '1-926-168-6208',
  title: 'Global Communications Orchestrator' },
  { age: 22,
  id: 'Catherine Predovic',
  phone: '206-479-6915 x835',
  title: 'Dynamic Accountability Architect' },
  { age: 36,
  id: 'Odie Reichel',
  phone: '(695) 562-6049 x68079',
  title: 'Forward Configuration Representative' },
  { age: 32,
  id: 'Wilfredo Strosin',
  phone: '071.478.7926',
  title: 'Dynamic Web Consultant' },
  { age: 8,
  id: 'Makayla McLaughlin',
  phone: '1-667-221-6294 x87922',
  title: 'Implementation Facilitator' },
  { age: 41,
  id: 'Ardella O\'Conner',
  phone: '1-927-933-8004',
  title: 'Product Operations Supervisor' },
  { age: 8,
  id: 'Magdalen Zulauf Mr.',
  phone: '992-726-6046 x72367',
  title: 'Central Accountability Manager' },
  { age: 62,
  id: 'Santino Kuvalis',
  phone: '(297) 534-9135',
  title: 'Direct Accounts Analyst' },
  { age: 48,
  id: 'Elva Graham',
  phone: '229.798.4078 x4705',
  title: 'International Mobility Facilitator' },
  { age: 16,
  id: 'Lesley Howe',
  phone: '(829) 112-7415 x2891',
  title: 'Internal Response Agent' },
  { age: 49,
  id: 'Antonio Monahan Mr.',
  phone: '(682) 162-2301',
  title: 'Integration Technician' },
  { age: 3,
  id: 'Shana Lubowitz',
  phone: '849-809-2691 x787',
  title: 'Senior Detector Agent' },
  { age: 1,
  id: 'Serena Bruen',
  phone: '1-070-021-2968',
  title: 'Senior Detector Agent' },
  { age: undefined,
  id: 'Clemmie Powlowski',
  phone: '1-796-310-8197 x253',
  title: 'Senior Detector Agent' },
  { age: 2,
  id: 'Albertha Simonis Ms.',
  phone: '1-421-993-2782 x073',
  title: 'Senior Fax Administrator' },
  { age: 4,
  id: 'Kavon Hammes',
  phone: '(913) 113-1961 x68847',
  title: 'Senior Identity Engineer' },
  { age: 5,
  id: 'Kyle MacGyver',
  phone: '333-464-6778 x7218',
  title: 'Senior Klingon Consultant' }
]

describe('mindex', () => {
  describe('simple keys', () => {
    let index = createIndex()

    it('set does not error', (done) => {
      testdb.forEach(function (record) {
        index.set(record.age, record.id)
      })
      done()
    })

    it('get returns correct result', (done) => {
      let result = index.get(1)
      assert.deepEqual(result, ['Serena Bruen'])
      done()
    })

    it('between returns correct result', (done) => {
      let result = index.between([1], [4])
      assert.deepEqual(result, ['Serena Bruen', 'Albertha Simonis Ms.', 'Shana Lubowitz'])
      done()
    })
  })

  describe('compound keys', () => {
    let index = createIndex(['title', 'age'])

    it('set does not error', (done) => {
      testdb.forEach(function (record) {
        index.insertRecord(record)
      })
      done()
    })

    it('get returns correct result one level deep', (done) => {
      let result = index.get('Senior Detector Agent')
      assert.deepEqual(result, ['Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })

    it('get returns correct result two levels deep', (done) => {
      let result = index.get(['Senior Detector Agent', 1])
      assert.deepEqual(result, ['Serena Bruen'])
      done()
    })

    it('between returns correct result for one level deep', (done) => {
      let result = index.between(['Internal Response Agent'], ['Senior Detector Agent'], {rightInclusive: true})
      assert.deepEqual(result, ['Lesley Howe', 'Elva Graham', 'Ms. Kiera Hodkiewicz', 'Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })

    it('between returns correct result for two levels deep', (done) => {
      let result = index.between(['Internal Response Agent', 20], ['Senior Detector Agent', 3], {rightInclusive: true, offset: 1})
      assert.deepEqual(result, ['Ms. Kiera Hodkiewicz', 'Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })

    it("Query {'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', 3], offset: 2, limit: 5}", (done) => {
      let result = index.query({'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', 3], offset: 2, limit: 5})
      assert.deepEqual(result, ['Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski'])
      done()
    })

    it("Query {'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', 3], offset: 1}", (done) => {
      let result = index.query({'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', undefined], offset: 1})
      assert.deepEqual(result, ['Ms. Kiera Hodkiewicz', 'Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })
  })
})
<commit_msg>add test for clear()<commit_after>'use strict'

/* global describe */
/* global it */

var assert = require('chai').assert
var createIndex = require('../src/mindex')

var testdb = [
  { age: 46,
  id: 'Lamar Goodwin',
  phone: '817-529-2557',
  title: 'Global Usability Coordinator' },
  { age: 13,
  id: 'Elmo Hansen',
  phone: '1-632-301-4062 x8351',
  title: 'Customer Paradigm Assistant' },
  { age: 43,
  id: 'Ashton Oberbrunner',
  phone: '1-292-015-9298 x19171',
  title: 'Legacy Security Planner' },
  { age: 32,
  id: 'Ms. Kiera Hodkiewicz',
  phone: '1-742-905-8677',
  title: 'Legacy Security Planner' },
  { age: 10,
  id: 'Hilda O\'Kon',
  phone: '118.357.9132 x76245',
  title: 'Dynamic Communications Agent' },
  { age: 38,
  id: 'Leland Bahringer',
  phone: '114.754.5482 x7853',
  title: 'Internal Program Officer' },
  { age: 21,
  id: 'Axel Block',
  phone: '816-557-8326 x083',
  title: 'Forward Interactions Liason' },
  { age: 14,
  id: 'Wendy Dare',
  phone: '966.968.5997 x42838',
  title: 'Infrastructure Associate' },
  { age: 23,
  id: 'Miss Fermin Bartell',
  phone: '(003) 694-6712',
  title: 'Product Applications Designer' },
  { age: 68,
  id: 'Marquise Weimann',
  phone: '400.157.6206',
  title: 'Corporate Response Orchestrator' },
  { age: 24,
  id: 'Kaley Jones',
  phone: '1-426-266-8041',
  title: 'District Brand Producer' },
  { age: 51,
  id: 'Dr. Jess Stokes',
  phone: '1-754-630-5989 x8753',
  title: 'Chief Tactics Supervisor' },
  { age: 24,
  id: 'Durward Runolfsson',
  phone: '726.255.5565',
  title: 'Regional Configuration Planner' },
  { age: 64,
  id: 'Clemens Howell Dr.',
  phone: '1-926-168-6208',
  title: 'Global Communications Orchestrator' },
  { age: 22,
  id: 'Catherine Predovic',
  phone: '206-479-6915 x835',
  title: 'Dynamic Accountability Architect' },
  { age: 36,
  id: 'Odie Reichel',
  phone: '(695) 562-6049 x68079',
  title: 'Forward Configuration Representative' },
  { age: 32,
  id: 'Wilfredo Strosin',
  phone: '071.478.7926',
  title: 'Dynamic Web Consultant' },
  { age: 8,
  id: 'Makayla McLaughlin',
  phone: '1-667-221-6294 x87922',
  title: 'Implementation Facilitator' },
  { age: 41,
  id: 'Ardella O\'Conner',
  phone: '1-927-933-8004',
  title: 'Product Operations Supervisor' },
  { age: 8,
  id: 'Magdalen Zulauf Mr.',
  phone: '992-726-6046 x72367',
  title: 'Central Accountability Manager' },
  { age: 62,
  id: 'Santino Kuvalis',
  phone: '(297) 534-9135',
  title: 'Direct Accounts Analyst' },
  { age: 48,
  id: 'Elva Graham',
  phone: '229.798.4078 x4705',
  title: 'International Mobility Facilitator' },
  { age: 16,
  id: 'Lesley Howe',
  phone: '(829) 112-7415 x2891',
  title: 'Internal Response Agent' },
  { age: 49,
  id: 'Antonio Monahan Mr.',
  phone: '(682) 162-2301',
  title: 'Integration Technician' },
  { age: 3,
  id: 'Shana Lubowitz',
  phone: '849-809-2691 x787',
  title: 'Senior Detector Agent' },
  { age: 1,
  id: 'Serena Bruen',
  phone: '1-070-021-2968',
  title: 'Senior Detector Agent' },
  { age: undefined,
  id: 'Clemmie Powlowski',
  phone: '1-796-310-8197 x253',
  title: 'Senior Detector Agent' },
  { age: 2,
  id: 'Albertha Simonis Ms.',
  phone: '1-421-993-2782 x073',
  title: 'Senior Fax Administrator' },
  { age: 4,
  id: 'Kavon Hammes',
  phone: '(913) 113-1961 x68847',
  title: 'Senior Identity Engineer' },
  { age: 5,
  id: 'Kyle MacGyver',
  phone: '333-464-6778 x7218',
  title: 'Senior Klingon Consultant' }
]

describe('mindex', function () {
  describe('simple keys', function () {
    let index

    before(function () {
      index = createIndex(['age'])
      testdb.forEach(function (record) {
        index.insertRecord(record)
      })
    })

    it('insertRecord does not error', function (done) {
      testdb.forEach(function (record) {
        index.insertRecord(record)
      })
      done()
    })

    it('get returns correct result', function (done) {
      let result = index.get(1)
      assert.deepEqual(result, ['Serena Bruen'])
      done()
    })

    it('between returns correct result', function (done) {
      let result = index.between([1], [4])
      assert.deepEqual(result, ['Serena Bruen', 'Albertha Simonis Ms.', 'Shana Lubowitz'])
      done()
    })

    it('clear removes all data', function (done) {
      index.clear()
      let result = index.getAll()
      assert.deepEqual(result, [])
      done()
    })
  })

  describe('compound keys', function () {
    let index = createIndex(['title', 'age'])

    it('insertRecord does not error', (done) => {
      testdb.forEach(function (record) {
        index.insertRecord(record)
      })
      done()
    })

    it('get returns correct result one level deep', (done) => {
      let result = index.get('Senior Detector Agent')
      assert.deepEqual(result, ['Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })

    it('get returns correct result two levels deep', (done) => {
      let result = index.get(['Senior Detector Agent', 1])
      assert.deepEqual(result, ['Serena Bruen'])
      done()
    })

    it('between returns correct result for one level deep', (done) => {
      let result = index.between(['Internal Response Agent'], ['Senior Detector Agent'], {rightInclusive: true})
      assert.deepEqual(result, ['Lesley Howe', 'Elva Graham', 'Ms. Kiera Hodkiewicz', 'Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })

    it('between returns correct result for two levels deep', (done) => {
      let result = index.between(['Internal Response Agent', 20], ['Senior Detector Agent', 3], {rightInclusive: true, offset: 1})
      assert.deepEqual(result, ['Ms. Kiera Hodkiewicz', 'Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })

    it("Query {'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', 3], offset: 2, limit: 5}", (done) => {
      let result = index.query({'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', 3], offset: 2, limit: 5})
      assert.deepEqual(result, ['Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski'])
      done()
    })

    it("Query {'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', 3], offset: 1}", (done) => {
      let result = index.query({'>': ['Internal Response Agent', 20], '<=': ['Senior Detector Agent', undefined], offset: 1})
      assert.deepEqual(result, ['Ms. Kiera Hodkiewicz', 'Ashton Oberbrunner', 'Miss Fermin Bartell', 'Ardella O\'Conner', 'Durward Runolfsson', 'Clemmie Powlowski', 'Serena Bruen', 'Shana Lubowitz'])
      done()
    })
  })
})
<|endoftext|>


<commit_before>var assert = require('assert')
var fs = require('fs')
var path = require('path')
var testutil = require('testutil')
var fse = require('../')

var TEST_DIR = ''

describe('fs-extra', function() {
  beforeEach(function() {
    TEST_DIR = testutil.createTestDir('fs-extra')
  })

  afterEach(function(done) {
    fse.remove(TEST_DIR, done)
  })

  describe('+ mkdirs()', function() {
    it('should make the directory', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())

      assert(!fs.existsSync(dir))

      fse.mkdirs(dir, function(err) {
        assert.ifError(err)
        assert(fs.existsSync(dir))
        done()
      })
    })

    it('should make the entire directory path', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())
      var newDir = path.join(TEST_DIR, 'dfdf', 'ffff', 'aaa')

      assert(!fs.existsSync(dir))

      fse.mkdirs(newDir, function(err) {
        assert.ifError(err)
        assert(fs.existsSync(newDir))
        done()
      })
    })
  })

  describe('+ mkdirsSync()', function() {
    it('should make the directory', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())

      assert(!fs.existsSync(dir))
      fse.mkdirsSync(dir)
      assert(fs.existsSync(dir))

      done()
    })

    it('should make the entire directory path', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())
      var newDir = path.join(dir, 'dfdf', 'ffff', 'aaa')

      assert(!fs.existsSync(dir))
      fse.mkdirsSync(dir)
      assert(fs.existsSync(dir))

      done()
    })
  })
})

<commit_msg>test/mkdir: adhere to standard style<commit_after>var assert = require('assert')
var fs = require('fs')
var path = require('path')
var testutil = require('testutil')
var fse = require('../')

/* global afterEach, beforeEach, describe, it */

var TEST_DIR = ''

describe('fs-extra', function() {
  beforeEach(function() {
    TEST_DIR = testutil.createTestDir('fs-extra')
  })

  afterEach(function(done) {
    fse.remove(TEST_DIR, done)
  })

  describe('+ mkdirs()', function() {
    it('should make the directory', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())

      assert(!fs.existsSync(dir))

      fse.mkdirs(dir, function(err) {
        assert.ifError(err)
        assert(fs.existsSync(dir))
        done()
      })
    })

    it('should make the entire directory path', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())
      var newDir = path.join(TEST_DIR, 'dfdf', 'ffff', 'aaa')

      assert(!fs.existsSync(dir))

      fse.mkdirs(newDir, function(err) {
        assert.ifError(err)
        assert(fs.existsSync(newDir))
        done()
      })
    })
  })

  describe('+ mkdirsSync()', function() {
    it('should make the directory', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())

      assert(!fs.existsSync(dir))
      fse.mkdirsSync(dir)
      assert(fs.existsSync(dir))

      done()
    })

    it('should make the entire directory path', function(done) {
      var dir = path.join(TEST_DIR, 'tmp-' + Date.now() + Math.random())
      var newDir = path.join(dir, 'dfdf', 'ffff', 'aaa')

      assert(!fs.existsSync(newDir))
      fse.mkdirsSync(newDir)
      assert(fs.existsSync(newDir))

      done()
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

// Tests suite
const chai = require('chai');
chai.should();
const expect = chai.expect;

// The star of the show
JSON.truncate = require('../');

// Helper
const createDeep = function(levels) {

    const createALevel = function(obj, level) {
        obj.bool = true;
        obj.num = 10;
        obj.str = `You are on level ${level}`;
        obj.arr = [true, 1, 'hi'];
        obj.sub = {};
        return obj;
    };

    let rootobj = {};
    let levelsCopy = levels;

    let refobj = rootobj;
    while (levelsCopy > 0) {
        levelsCopy--;
        createALevel(refobj, levels - levelsCopy);
        if (levelsCopy > 0) {
            refobj = refobj.sub;
        } else {
            refobj.sub = undefined;
            refobj.arr = undefined;
        }
    }

    //refobj.sub = undefined;
    return rootobj;
};

describe('JSONtruncate', () => {

    describe('defaults', () => {

        it('should truncate to 1', () => {
            JSON.truncate(createDeep(3), 1).should.deep.equal(createDeep(1));
        });

        it('should truncate to default (10)', () => {
            JSON.truncate(createDeep(15)).should.deep.equal(createDeep(10));
        });

        it('should truncate arrays and nested objects', () => {
            JSON.truncate([createDeep(3)], 2).should.deep.equal([createDeep(1)]);
        });

        it('should return flat objects', () => {
            [5, true, false, "hello"].map(val => {
              JSON.truncate(val, 5).should.equal(val);
            });
        });

        it('should return an empty with anything not jsonable', () => {
          JSON.truncate(function(){}, 5).should.deep.equal({});
        });

        it('should return an empty object with a bad maxDepth value', () => {
          expect(JSON.truncate({test: true}, {bad:true})).to.be.undefied;
        });

        it('should resolve recursive objects', () => {
            // setting up a recursive object
            const recursive = {
              test: true
            };
            Object.defineProperty(recursive, 'sub', {
              value: recursive,
              enumerable: true
            });

            JSON.truncate(recursive, 2).should.deep.equal({test: true, sub: {test: true, sub: undefined}});
        });

    });

});
<commit_msg>fix: Resolving additional arrow functions.<commit_after>'use strict';

// Tests suite
const chai = require('chai');
chai.should();
const expect = chai.expect;

// The star of the show
JSON.truncate = require('../');

// Helper
const createDeep = function(levels) {

    const createALevel = function(obj, level) {
        obj.bool = true;
        obj.num = 10;
        obj.str = `You are on level ${level}`;
        obj.arr = [true, 1, 'hi'];
        obj.sub = {};
        return obj;
    };

    let rootobj = {};
    let levelsCopy = levels;

    let refobj = rootobj;
    while (levelsCopy > 0) {
        levelsCopy--;
        createALevel(refobj, levels - levelsCopy);
        if (levelsCopy > 0) {
            refobj = refobj.sub;
        } else {
            refobj.sub = undefined;
            refobj.arr = undefined;
        }
    }

    //refobj.sub = undefined;
    return rootobj;
};

describe('JSONtruncate', function() {

    describe('defaults', function() {

        it('should truncate to 1', function() {
            JSON.truncate(createDeep(3), 1).should.deep.equal(createDeep(1));
        });

        it('should truncate to default (10)', function() {
            JSON.truncate(createDeep(15)).should.deep.equal(createDeep(10));
        });

        it('should truncate arrays and nested objects', () => {
            JSON.truncate([createDeep(3)], 2).should.deep.equal([createDeep(1)]);
        });

        it('should return flat objects', function() {
            [5, true, false, "hello"].map(function(val) {
              JSON.truncate(val, 5).should.equal(val);
            });
        });

        it('should return an empty with anything not jsonable', function() {
          JSON.truncate(function(){}, 5).should.deep.equal({});
        });

        it('should return an empty object with a bad maxDepth value', function() {
          expect(JSON.truncate({test: true}, {bad:true})).to.be.undefied;
        });

        it('should resolve recursive objects', function() {
            // setting up a recursive object
            const recursive = {
              test: true
            };
            Object.defineProperty(recursive, 'sub', {
              value: recursive,
              enumerable: true
            });

            JSON.truncate(recursive, 2).should.deep.equal({test: true, sub: {test: true, sub: undefined}});
        });

    });

});
<|endoftext|>


<commit_before>/* eslint-disable import/newline-after-import */

'use strict'

const assert = require('assert')
const _ = require('lodash')
const cli = require('eslint-find-rules/src/lib/cli-util')

function loadRules(file) {
  return require(file).rules
}

function loadRuleNames(file) {
  return Object.keys(loadRules(file))
}

function getVueRule(ruleName) {
  const unprefixedRuleName = ruleName.replace(/^vue\//, '')
  const vueRule = allVueRules[unprefixedRuleName]

  if (!vueRule) {
    throw new Error(`Unknown rule: ${ruleName}`)
  }

  return vueRule
}

function pickRuleNamesForVueVersion(expectedCategories) {
  return allVueRuleNames.filter(ruleName => {
    const vueRule = getVueRule(ruleName)
    const { deprecated } = vueRule.meta
    const { categories } = vueRule.meta.docs

    if (deprecated) {
      return false
    }

    if (categories == null) {
      return true
    }

    assert(Array.isArray(categories))
    assert(categories.every(category => allCategories.includes(category)))

    if (expectedCategories.some(category => categories.includes(category))) {
      return true
    }

    return false
  })
}

function findDeprecatedRuleNames(ruleNames) {
  return ruleNames.filter(ruleName => {
    const vueRule = getVueRule(ruleName)
    const { deprecated } = vueRule.meta

    return deprecated
  })
}

function findUnusedRuleNames(allRuleNames, usedRuleNames) {
  const unusedRuleNames = _.difference(allRuleNames, usedRuleNames)

  return unusedRuleNames
}

function processResult(sectionTitle, ruleNames) {
  if (ruleNames.length) {
    hasIssues = true

    if (++sectionCount > 1) {
      cli.push('\n')
    }

    cli.push(sectionTitle + '\n')
    cli.push(ruleNames)
  }
}

const allVueRules = loadRules('eslint-plugin-vue')
const allVueRuleNames = loadRuleNames('eslint-plugin-vue').map(ruleName => 'vue/' + ruleName)

const vue3Categories = [ 'base', 'vue3-essential', 'vue3-strongly-recommended', 'vue3-recommended' ]
const vue2Categories = [ 'base', 'essential', 'strongly-recommended', 'recommended' ]
const allCategories = _.union(vue3Categories, vue2Categories)

const allVue3RuleNames = pickRuleNamesForVueVersion(vue3Categories)
const allVue2RuleNames = pickRuleNamesForVueVersion(vue2Categories)

const usedVue3RuleNames = loadRuleNames('../plugin-vue/v3')
const usedVue2RuleNames = loadRuleNames('../plugin-vue/v2')
const usedDeprecatedRuleNames = _.union(
  findDeprecatedRuleNames(usedVue3RuleNames),
  findDeprecatedRuleNames(usedVue2RuleNames),
)

const unusedVue3RuleNames = findUnusedRuleNames(allVue3RuleNames, usedVue3RuleNames)
const unusedVue2RuleNames = findUnusedRuleNames(allVue2RuleNames, usedVue2RuleNames)

let hasIssues = false
let sectionCount = 0

processResult('Unused Vue 3 rules', unusedVue3RuleNames)
processResult('Unused Vue 2 rules', unusedVue2RuleNames)
processResult('Deprecated Vue rules', usedDeprecatedRuleNames)

if (hasIssues) {
  cli.write()
  process.exit(1)
}
<commit_msg>minor update<commit_after>/* eslint-disable import/newline-after-import */

'use strict'

const assert = require('assert')
const _ = require('lodash')
const cli = require('eslint-find-rules/src/lib/cli-util')

function loadRules(file) {
  return require(file).rules
}

function loadRuleNames(file) {
  return Object.keys(loadRules(file))
}

function getVueRule(ruleName) {
  const unprefixedRuleName = ruleName.replace(/^vue\//, '')
  const vueRule = allVueRules[unprefixedRuleName]

  if (!vueRule) {
    throw new Error(`Unknown rule: ${ruleName}`)
  }

  return vueRule
}

function pickRuleNamesForVueVersion(expectedCategories) {
  return allVueRuleNames.filter(ruleName => {
    const vueRule = getVueRule(ruleName)
    const { deprecated } = vueRule.meta
    const { categories } = vueRule.meta.docs

    if (deprecated) {
      return false
    }

    if (categories == null) {
      return true
    }

    assert(Array.isArray(categories))
    assert(categories.every(category => allCategories.includes(category)))

    if (expectedCategories.some(category => categories.includes(category))) {
      return true
    }

    return false
  })
}

function findDeprecatedRuleNames(ruleNames) {
  return ruleNames.filter(ruleName => {
    const vueRule = getVueRule(ruleName)
    const { deprecated } = vueRule.meta

    return deprecated
  })
}

function findUnusedRuleNames(allRuleNames, usedRuleNames) {
  const unusedRuleNames = _.difference(allRuleNames, usedRuleNames)

  return unusedRuleNames
}

function processResult(sectionTitle, ruleNames) {
  if (ruleNames.length) {
    hasIssues = true

    if (++sectionCount > 1) {
      cli.push('\n')
    }

    cli.push(sectionTitle + '\n')
    cli.push(ruleNames)
  }
}

const allVueRules = loadRules('eslint-plugin-vue')
const allVueRuleNames = loadRuleNames('eslint-plugin-vue').map(ruleName => 'vue/' + ruleName)

const vue3Categories = [ 'base', 'vue3-essential', 'vue3-strongly-recommended', 'vue3-recommended' ]
const vue2Categories = [ 'base', 'essential', 'strongly-recommended', 'recommended' ]
const allCategories = _.union(vue3Categories, vue2Categories)

const allVue3RuleNames = pickRuleNamesForVueVersion(vue3Categories)
const allVue2RuleNames = pickRuleNamesForVueVersion(vue2Categories)

const usedVue3RuleNames = loadRuleNames('../plugin-vue/v3')
const usedVue2RuleNames = loadRuleNames('../plugin-vue/v2')
const usedDeprecatedRuleNames = _.union(
  findDeprecatedRuleNames(usedVue3RuleNames),
  findDeprecatedRuleNames(usedVue2RuleNames),
)

const unusedVue3RuleNames = findUnusedRuleNames(allVue3RuleNames, usedVue3RuleNames)
const unusedVue2RuleNames = findUnusedRuleNames(allVue2RuleNames, usedVue2RuleNames)

let hasIssues = false
let sectionCount = 0

processResult('Unused Vue 3 rules', unusedVue3RuleNames)
processResult('Unused Vue 2 rules', unusedVue2RuleNames)
processResult('Deprecated Vue rules', usedDeprecatedRuleNames)

if (hasIssues) {
  cli.write()
  process.exitCode = 1
}
<|endoftext|>


<commit_before>
/**
 * Test dependencies.
 */

var parser = require('../../lib/');
var expect = require('expect.js');

/**
 * Shortcuts
 */
var encode = parser.encodePacket;
var decode = parser.decodePacket;
var encPayload = parser.encodePayload;
var decPayload = parser.decodePayload;
var encPayloadB = parser.encodePayloadAsBinary;
var decPayloadB = parser.decodePayloadAsBinary;

/**
 * Tests.
 */

describe('parser', function() {
  it('should encode a binary message', function(done) {
    var data = new Buffer(5);
    for (var i = 0; i < data.length; i++) { data[i] = i; }
    encode({ type: 'message', data: data }, function(encoded) {
      expect(decode(encoded)).to.eql({ type: 'message', data: data });
      done();
    });
  });

  it('should encode/decode mixed binary and string contents as b64', function(done) {
    var data = new Buffer(5);
    for (var i = 0; i < data.length; i++) data[i] = i;
    encPayload([{ type: 'message', data: data }, { type: 'message', data: 'hello' }], function(encoded) {
      decPayload(encoded,
        function(packet, index, total) {
          var isLast = index + 1 == total;
          expect(packet.type).to.eql('message');
          if (!isLast) {
            expect(packet.data).to.eql(data);
          } else {
            expect(packet.data).to.eql('hello');
            done();
          }
        });
    });
  });

  it('should encode binary contents as binary', function(done) {
    var firstBuffer = new Buffer(5);
      for (var i = 0; i < firstBuffer.length; i++) firstBuffer[i] = i;
      var secondBuffer = new Buffer(4);
      for (var i = 0; i < secondBuffer.length; i++) secondBuffer[i] = firstBuffer.length + i;

      encPayloadB([{ type: 'message', data: firstBuffer }, { type: 'message', data: secondBuffer }], function(data) {
        decPayloadB(data,
          function(packet, index, total) {
            var isLast = index + 1 == total;
            expect(packet.type).to.eql('message');
            if (!isLast) {
              expect(packet.data).to.eql(firstBuffer);
            } else {
              expect(packet.data).to.eql(secondBuffer);
              done();
            }
          });
      });
  });

  it('should encode mixed binary and string contents as binary', function(done) {
    var firstBuffer = new Buffer(123);
    for (var i = 0; i < firstBuffer.length; i++) firstBuffer[i] = i;

    encPayloadB([{ type: 'message', data: firstBuffer }, { type: 'message', data: 'hello' }, { type: 'close' } ], function(data) {
      decPayloadB(data,
        function(packet, index, total) {
          if (index == 0) {
            expect(packet.type).to.eql('message');
            expect(packet.data).to.eql(firstBuffer);
          } else if (index == 1) {
            expect(packet.type).to.eql('message');
            expect(packet.data).to.eql('hello');
          } else {
            expect(packet.type).to.eql('close');
            done();
          }
        });
    });
  });

  it('should encode/decode an ArrayBuffer as b64', function(done) {
    var buffer = new ArrayBuffer(4);
    var dataview = new DataView(buffer);
    for (var i = 0; i < buffer.byteLength ; i++) dataview.setInt8(i, i);

    encode({ type: 'message', data: buffer }, function(encoded) {
      var decoded = decode(encoded, 'arraybuffer');
      expect(decoded).to.eql({ type: 'message', data: buffer });
      expect(new Uint8Array(decoded.data)).to.eql(new Uint8Array(buffer));
      done();
    });
  });

  it('should encode/decode an ArrayBuffer as binary', function(done) {
    var buffer = new ArrayBuffer(4);
    var dataview = new DataView(buffer);
    for (var i = 0; i < buffer.byteLength ; i++) dataview.setInt8(i, i);

    encode({ type: 'message', data: buffer }, true, function(encoded) {
      var decoded = decode(encoded, 'arraybuffer');
      expect(decoded).to.eql({ type: 'message', data: buffer });
      expect(new Uint8Array(decoded.data)).to.eql(new Uint8Array(buffer));
      done();
    });
  });

  it('should decode an ArrayBuffer/Buffer with undeclared type as binary', function(done) {
    var buffer1 = new ArrayBuffer(4);
    var dataview = new DataView(buffer1);
    var buffer2 = new Buffer(4);
    for (var i = 0; i < buffer1.byteLength ; i++) {
      dataview.setInt8(i, 4-i);
      buffer2[i] = 4-i;
    }

    var decoded1 = decode(buffer1, null);
    var decoded2 = decode(buffer2, null);
    expect(decoded1).to.eql({ type: 'message', data: new Buffer([3,2,1])});
    expect(new Uint8Array(decoded1.data)).to.eql(new Uint8Array(buffer1.slice(1)));
    expect(decoded2).to.eql({ type: 'message', data: new Buffer(buffer2.slice(1))});
    expect(new Uint8Array(decoded2.data)).to.eql(new Uint8Array(buffer2.slice(1)));
    done();
  });

  it('should decode an ArrayBuffer/Buffer as binary of type ArrayBuffer', function(done) {
    var buffer1 = new ArrayBuffer(4);
    var dataview = new DataView(buffer1);
    var buffer2 = new Buffer(4);
    for (var i = 0; i < buffer1.byteLength ; i++) {
      dataview.setInt8(i, 4-i);
      buffer2[i] = 4-i;
    }

    var decoded1 = decode(buffer1, 'arraybuffer');
    var decoded2 = decode(buffer2, 'arraybuffer');
    expect(decoded1).to.eql({ type: 'message', data: buffer1.slice(1)});
    expect(new Uint8Array(decoded1.data)).to.eql(new Uint8Array(buffer1.slice(1)));
    expect(decoded2).to.eql({ type: 'message', data:  new ArrayBuffer(buffer2.slice(1))});
    expect(new Uint8Array(decoded2.data)).to.eql(new Uint8Array(buffer2.slice(1)));
    done();
  });

  it('should encode/decode a typed array as binary', function(done) {
    var buffer = new ArrayBuffer(32);
    var typedArray = new Int32Array(buffer, 4, 2);
    typedArray[0] = 1;
    typedArray[1] = 2;

    encode({ type: 'message', data: typedArray }, true, function(encoded) {
      var decoded = decode(encoded, 'arraybuffer');
      expect(decoded.type).to.eql('message');
      expect(areArraysEqual(new Int32Array(decoded.data), typedArray)).to.eql(true);
      done();
    });
  });

});

function areArraysEqual(x, y) {
  if (x.length != y.length) return false;
  for (var i = 0, l = x.length; i < l; i++) {
    if (x[i] !== y[i]) return false;
  }
  return true;
}
<commit_msg>fixed ArrayBuffer/Buffer casting in test<commit_after>
/**
 * Test dependencies.
 */

var parser = require('../../lib/');
var expect = require('expect.js');

/**
 * Shortcuts
 */
var encode = parser.encodePacket;
var decode = parser.decodePacket;
var encPayload = parser.encodePayload;
var decPayload = parser.decodePayload;
var encPayloadB = parser.encodePayloadAsBinary;
var decPayloadB = parser.decodePayloadAsBinary;

/**
 * Tests.
 */

describe('parser', function() {
  it('should encode a binary message', function(done) {
    var data = new Buffer(5);
    for (var i = 0; i < data.length; i++) { data[i] = i; }
    encode({ type: 'message', data: data }, function(encoded) {
      expect(decode(encoded)).to.eql({ type: 'message', data: data });
      done();
    });
  });

  it('should encode/decode mixed binary and string contents as b64', function(done) {
    var data = new Buffer(5);
    for (var i = 0; i < data.length; i++) data[i] = i;
    encPayload([{ type: 'message', data: data }, { type: 'message', data: 'hello' }], function(encoded) {
      decPayload(encoded,
        function(packet, index, total) {
          var isLast = index + 1 == total;
          expect(packet.type).to.eql('message');
          if (!isLast) {
            expect(packet.data).to.eql(data);
          } else {
            expect(packet.data).to.eql('hello');
            done();
          }
        });
    });
  });

  it('should encode binary contents as binary', function(done) {
    var firstBuffer = new Buffer(5);
      for (var i = 0; i < firstBuffer.length; i++) firstBuffer[i] = i;
      var secondBuffer = new Buffer(4);
      for (var i = 0; i < secondBuffer.length; i++) secondBuffer[i] = firstBuffer.length + i;

      encPayloadB([{ type: 'message', data: firstBuffer }, { type: 'message', data: secondBuffer }], function(data) {
        decPayloadB(data,
          function(packet, index, total) {
            var isLast = index + 1 == total;
            expect(packet.type).to.eql('message');
            if (!isLast) {
              expect(packet.data).to.eql(firstBuffer);
            } else {
              expect(packet.data).to.eql(secondBuffer);
              done();
            }
          });
      });
  });

  it('should encode mixed binary and string contents as binary', function(done) {
    var firstBuffer = new Buffer(123);
    for (var i = 0; i < firstBuffer.length; i++) firstBuffer[i] = i;

    encPayloadB([{ type: 'message', data: firstBuffer }, { type: 'message', data: 'hello' }, { type: 'close' } ], function(data) {
      decPayloadB(data,
        function(packet, index, total) {
          if (index == 0) {
            expect(packet.type).to.eql('message');
            expect(packet.data).to.eql(firstBuffer);
          } else if (index == 1) {
            expect(packet.type).to.eql('message');
            expect(packet.data).to.eql('hello');
          } else {
            expect(packet.type).to.eql('close');
            done();
          }
        });
    });
  });

  it('should encode/decode an ArrayBuffer as b64', function(done) {
    var buffer = new ArrayBuffer(4);
    var dataview = new DataView(buffer);
    for (var i = 0; i < buffer.byteLength ; i++) dataview.setInt8(i, i);

    encode({ type: 'message', data: buffer }, function(encoded) {
      var decoded = decode(encoded, 'arraybuffer');
      expect(decoded).to.eql({ type: 'message', data: buffer });
      expect(new Uint8Array(decoded.data)).to.eql(new Uint8Array(buffer));
      done();
    });
  });

  it('should encode/decode an ArrayBuffer as binary', function(done) {
    var buffer = new ArrayBuffer(4);
    var dataview = new DataView(buffer);
    for (var i = 0; i < buffer.byteLength ; i++) dataview.setInt8(i, i);

    encode({ type: 'message', data: buffer }, true, function(encoded) {
      var decoded = decode(encoded, 'arraybuffer');
      expect(decoded).to.eql({ type: 'message', data: buffer });
      expect(new Uint8Array(decoded.data)).to.eql(new Uint8Array(buffer));
      done();
    });
  });

  it('should decode an ArrayBuffer/Buffer with undeclared type as binary', function(done) {
    var buffer1 = new ArrayBuffer(4);
    var dataview = new DataView(buffer1);
    var buffer2 = new Buffer(4);
    for (var i = 0; i < buffer1.byteLength ; i++) {
      dataview.setInt8(i, 4-i);
      buffer2[i] = 4-i;
    }

    var decoded1 = decode(buffer1, null);
    var decoded2 = decode(buffer2, null);
    expect(decoded1).to.eql({ type: 'message', data: new Buffer([3,2,1])});
    expect(new Uint8Array(decoded1.data)).to.eql(new Uint8Array(buffer1.slice(1)));
    expect(decoded2).to.eql({ type: 'message', data: new Buffer(buffer2.slice(1))});
    expect(new Uint8Array(decoded2.data)).to.eql(new Uint8Array(buffer2.slice(1)));
    done();
  });

  it('should decode an ArrayBuffer/Buffer as binary of type ArrayBuffer', function(done) {
    var buffer1 = new ArrayBuffer(4);
    var dataview = new DataView(buffer1);
    var buffer2 = new Buffer(4);
    for (var i = 0; i < buffer1.byteLength ; i++) {
      dataview.setInt8(i, 4-i);
      buffer2[i] = 4-i;
    }

    var decoded1 = decode(buffer1, 'arraybuffer');
    var decoded2 = decode(buffer2, 'arraybuffer');
    expect(decoded1).to.eql({ type: 'message', data: buffer1.slice(1)});
    expect(new Uint8Array(decoded1.data)).to.eql(new Uint8Array(buffer1.slice(1)));

    var testBuffer = new ArrayBuffer(decoded2.data.byteLength);
    var decoded2view = new DataView(decoded2.data);
    var testBufferview = new DataView(testBuffer);
    for (var i = 0; i < decoded2view.byteLength ; i++) {
        testBufferview.setInt8(i, decoded2view.getInt8(i));
    }
    expect(decoded2).to.eql({ type: 'message', data:  testBuffer});
    expect(new Uint8Array(decoded2.data)).to.eql(new Uint8Array(buffer2.slice(1)));
    done();
  });

  it('should encode/decode a typed array as binary', function(done) {
    var buffer = new ArrayBuffer(32);
    var typedArray = new Int32Array(buffer, 4, 2);
    typedArray[0] = 1;
    typedArray[1] = 2;

    encode({ type: 'message', data: typedArray }, true, function(encoded) {
      var decoded = decode(encoded, 'arraybuffer');
      expect(decoded.type).to.eql('message');
      expect(areArraysEqual(new Int32Array(decoded.data), typedArray)).to.eql(true);
      done();
    });
  });

});

function areArraysEqual(x, y) {
  if (x.length != y.length) return false;
  for (var i = 0, l = x.length; i < l; i++) {
    if (x[i] !== y[i]) return false;
  }
  return true;
}
<|endoftext|>


<commit_before>import Random from 'random-seed'
import Patch from '../src/patch'
import {INFINITY_POINT, traverse, traversalDistance, format as formatPoint, isZero as isZeroPoint} from '../src/point-helpers'
import TestDocument from './helpers/test-document'
import './helpers/add-to-html-methods'

describe('Patch', function () {
  it('correctly serializes and deserializes changes', function () {
    let patch = new Patch
    patch.spliceWithText({row: 0, column: 3}, 'abcd', 'hello')
    patch.spliceWithText({row: 1, column: 1}, '', 'hey')
    patch.splice({row: 0, column: 15}, {row: 0, column: 10}, {row: 0, column: 0})
    patch.splice({row: 0, column: 0}, {row: 0, column: 0}, {row: 3, column: 0})
    patch.spliceWithText({row: 4, column: 2}, 'hi', 'ho')

    assert.deepEqual(patch.getChanges(), Patch.deserialize(patch.serialize()).getChanges())
  })

  it('correctly composes changes from multiple patches', function () {
    let patches = [new Patch(), new Patch(), new Patch()]
    patches[0].spliceWithText({row: 0, column: 3}, 'ciao', 'hello')
    patches[0].spliceWithText({row: 1, column: 1}, '', 'hey')
    patches[1].splice({row: 0, column: 15}, {row: 0, column: 10}, {row: 0, column: 0})
    patches[1].splice({row: 0, column: 0}, {row: 0, column: 0}, {row: 3, column: 0})
    patches[2].spliceWithText({row: 4, column: 2}, 'so', 'ho')

    assert.deepEqual(Patch.compose(patches), [
      {oldStart: {row: 0, column: 0}, newStart: {row: 0, column: 0}, oldExtent: {row: 0, column: 0}, newExtent: {row: 3, column: 0}},
      {oldStart: {row: 0, column: 3}, newStart: {row: 3, column: 3}, oldExtent: {row: 0, column: 4}, newExtent: {row: 0, column: 5}, newText: 'hello', oldText: 'ciao'},
      {oldStart: {row: 0, column: 14}, newStart: {row: 3, column: 15}, oldExtent: {row: 0, column: 10}, newExtent: {row: 0, column: 0}},
      {oldStart: {row: 1, column: 1}, newStart: {row: 4, column: 1}, oldExtent: {row: 0, column: 0}, newExtent: {row: 0, column: 3}, newText: 'hho', oldText: ''}
    ])
  })

  it('correctly records basic non-overlapping splices', function () {
    let patch = new Patch()
    patch.spliceWithText({row: 0, column: 3}, 'ciao', 'hello')
    patch.spliceWithText({row: 0, column: 10}, 'quick', 'world')
    assert.deepEqual(patch.getChanges(), [
      {oldStart: {row: 0, column: 3}, newStart: {row: 0, column: 3}, oldExtent: {row: 0, column: 4}, newExtent: {row: 0, column: 5}, newText: 'hello', oldText: 'ciao'},
      {oldStart: {row: 0, column: 9}, newStart: {row: 0, column: 10}, oldExtent: {row: 0, column: 5}, newExtent: {row: 0, column: 5}, newText: 'world', oldText: 'quick'}
    ])
  })

  it('correctly records basic overlapping splices', function () {
    let patch = new Patch()
    patch.spliceWithText({row: 0, column: 3}, 'hola', 'hello world')
    patch.spliceWithText({row: 0, column: 9}, 'zapping', 'sun')
    assert.deepEqual(patch.getChanges(), [
      {oldStart: {row: 0, column: 3}, newStart: {row: 0, column: 3}, oldExtent: {row: 0, column: 6}, newExtent: {row: 0, column: 9}, newText: 'hello sun', oldText: 'holang'}
    ])
  })

  it('correctly records random splices', function () {
    this.timeout(Infinity)

    for (let i = 0; i < 100; i++) {
      let seed = Date.now()
      let seedMessage = `Random seed: ${seed}`
      let random = new Random(seed)
      let input = new TestDocument(seed)
      let output = input.clone()
      let patch = new Patch()

      for (let j = 0; j < 10; j++) {
        let {start, oldText, oldExtent, newExtent, newText} = output.performRandomSplice()
        patch.spliceWithText(start, oldText, newText)
        // document.write(`<div>after splice(${formatPoint(start)}, ${formatPoint(oldExtent)}, ${formatPoint(newExtent)}, ${JSON.stringify(newText)}, ${JSON.stringify(oldText)})</div>`)
        // document.write(patch.toHTML())
        // document.write('
')

        let shouldRebalance = Boolean(random(2))
        if (shouldRebalance) patch.rebalance()

        verifyOutputChanges(patch, input, output, seedMessage)
        verifyInputChanges(patch, input, output, seedMessage)
      }
    }

    function verifyOutputChanges (patch, input, output, seedMessage) {
      let synthesizedOutput = ''
      let synthesizedInput = ''
      patch.iterator.moveToBeginning()
      do {
        if (patch.iterator.inChange()) {
          assert(!(isZeroPoint(patch.iterator.getInputExtent()) && isZeroPoint(patch.iterator.getOutputExtent())), "Empty region found. " + seedMessage);
          synthesizedOutput += patch.iterator.getNewText()
          synthesizedInput += patch.iterator.getOldText()
        } else {
          synthesizedOutput += input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd())
          synthesizedInput += input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd())
        }
      } while (patch.iterator.moveToSuccessor())

      assert.equal(synthesizedInput, input.getText(), seedMessage)
      assert.equal(synthesizedOutput, output.getText(), seedMessage)

      synthesizedInput = output.clone()
      synthesizedOutput = input.clone()
      for (let {oldStart, newStart, oldExtent, newExtent, oldText, newText} of patch.getChanges()) {
        synthesizedInput.splice(oldStart, newExtent, oldText)
        synthesizedOutput.splice(newStart, oldExtent, newText)
      }

      assert.equal(synthesizedInput.getText(), input.getText(), seedMessage)
      assert.equal(synthesizedOutput.getText(), output.getText(), seedMessage)
    }

    function verifyInputChanges (patch, input, output, seedMessage) {
      patch.iterator.moveToEnd()
      let synthesizedInput = input.getTextInRange(patch.iterator.getInputEnd(), INFINITY_POINT)
      let synthesizedOutput = input.getTextInRange(patch.iterator.getInputEnd(), INFINITY_POINT)
      do {
        if (patch.iterator.inChange()) {
          assert(!(isZeroPoint(patch.iterator.getInputExtent()) && isZeroPoint(patch.iterator.getOutputExtent())), "Empty region found. " + seedMessage);
          synthesizedOutput = patch.iterator.getNewText() + synthesizedOutput
          synthesizedInput = patch.iterator.getOldText() + synthesizedInput
        } else {
          synthesizedOutput = input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd()) + synthesizedOutput
          synthesizedInput = input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd()) + synthesizedInput
        }
      } while (patch.iterator.moveToPredecessor())

      assert.equal(synthesizedInput, input.getText(), seedMessage)
      assert.equal(synthesizedOutput, output.getText(), seedMessage)

      synthesizedOutput = input.clone()
      synthesizedInput = output.clone()
      for (let {oldStart, newStart, oldExtent, newExtent, oldText, newText} of patch.getChanges().slice().reverse()) {
        synthesizedOutput.splice(oldStart, oldExtent, newText)
        synthesizedInput.splice(newStart, newExtent, oldText)
      }

      assert.equal(synthesizedOutput.getText(), output.getText(), seedMessage)
      assert.equal(synthesizedInput.getText(), input.getText(), seedMessage)
    }
  })
})
<commit_msg>Assert that deserialized patches are read-only<commit_after>import Random from 'random-seed'
import Patch from '../src/patch'
import {INFINITY_POINT, traverse, traversalDistance, format as formatPoint, isZero as isZeroPoint} from '../src/point-helpers'
import TestDocument from './helpers/test-document'
import './helpers/add-to-html-methods'

describe('Patch', function () {
  it('correctly serializes and deserializes changes', function () {
    let patch = new Patch
    patch.spliceWithText({row: 0, column: 3}, 'abcd', 'hello')
    patch.spliceWithText({row: 1, column: 1}, '', 'hey')
    patch.splice({row: 0, column: 15}, {row: 0, column: 10}, {row: 0, column: 0})
    patch.splice({row: 0, column: 0}, {row: 0, column: 0}, {row: 3, column: 0})
    patch.spliceWithText({row: 4, column: 2}, 'hi', 'ho')

    let deserializedPatch = Patch.deserialize(patch.serialize())
    assert.deepEqual(patch.getChanges(), deserializedPatch.getChanges())
    assert.throws(() => deserializedPatch.splice({row: 0, column: 0}, {row: 1, column: 0}, {row: 0, column: 3}))
  })

  it('correctly composes changes from multiple patches', function () {
    let patches = [new Patch(), new Patch(), new Patch()]
    patches[0].spliceWithText({row: 0, column: 3}, 'ciao', 'hello')
    patches[0].spliceWithText({row: 1, column: 1}, '', 'hey')
    patches[1].splice({row: 0, column: 15}, {row: 0, column: 10}, {row: 0, column: 0})
    patches[1].splice({row: 0, column: 0}, {row: 0, column: 0}, {row: 3, column: 0})
    patches[2].spliceWithText({row: 4, column: 2}, 'so', 'ho')

    assert.deepEqual(Patch.compose(patches), [
      {oldStart: {row: 0, column: 0}, newStart: {row: 0, column: 0}, oldExtent: {row: 0, column: 0}, newExtent: {row: 3, column: 0}},
      {oldStart: {row: 0, column: 3}, newStart: {row: 3, column: 3}, oldExtent: {row: 0, column: 4}, newExtent: {row: 0, column: 5}, newText: 'hello', oldText: 'ciao'},
      {oldStart: {row: 0, column: 14}, newStart: {row: 3, column: 15}, oldExtent: {row: 0, column: 10}, newExtent: {row: 0, column: 0}},
      {oldStart: {row: 1, column: 1}, newStart: {row: 4, column: 1}, oldExtent: {row: 0, column: 0}, newExtent: {row: 0, column: 3}, newText: 'hho', oldText: ''}
    ])
  })

  it('correctly records basic non-overlapping splices', function () {
    let patch = new Patch()
    patch.spliceWithText({row: 0, column: 3}, 'ciao', 'hello')
    patch.spliceWithText({row: 0, column: 10}, 'quick', 'world')
    assert.deepEqual(patch.getChanges(), [
      {oldStart: {row: 0, column: 3}, newStart: {row: 0, column: 3}, oldExtent: {row: 0, column: 4}, newExtent: {row: 0, column: 5}, newText: 'hello', oldText: 'ciao'},
      {oldStart: {row: 0, column: 9}, newStart: {row: 0, column: 10}, oldExtent: {row: 0, column: 5}, newExtent: {row: 0, column: 5}, newText: 'world', oldText: 'quick'}
    ])
  })

  it('correctly records basic overlapping splices', function () {
    let patch = new Patch()
    patch.spliceWithText({row: 0, column: 3}, 'hola', 'hello world')
    patch.spliceWithText({row: 0, column: 9}, 'zapping', 'sun')
    assert.deepEqual(patch.getChanges(), [
      {oldStart: {row: 0, column: 3}, newStart: {row: 0, column: 3}, oldExtent: {row: 0, column: 6}, newExtent: {row: 0, column: 9}, newText: 'hello sun', oldText: 'holang'}
    ])
  })

  it('correctly records random splices', function () {
    this.timeout(Infinity)

    for (let i = 0; i < 100; i++) {
      let seed = Date.now()
      let seedMessage = `Random seed: ${seed}`
      let random = new Random(seed)
      let input = new TestDocument(seed)
      let output = input.clone()
      let patch = new Patch()

      for (let j = 0; j < 10; j++) {
        let {start, oldText, oldExtent, newExtent, newText} = output.performRandomSplice()
        patch.spliceWithText(start, oldText, newText)
        // document.write(`<div>after splice(${formatPoint(start)}, ${formatPoint(oldExtent)}, ${formatPoint(newExtent)}, ${JSON.stringify(newText)}, ${JSON.stringify(oldText)})</div>`)
        // document.write(patch.toHTML())
        // document.write('
')

        let shouldRebalance = Boolean(random(2))
        if (shouldRebalance) patch.rebalance()

        verifyOutputChanges(patch, input, output, seedMessage)
        verifyInputChanges(patch, input, output, seedMessage)
      }
    }

    function verifyOutputChanges (patch, input, output, seedMessage) {
      let synthesizedOutput = ''
      let synthesizedInput = ''
      patch.iterator.moveToBeginning()
      do {
        if (patch.iterator.inChange()) {
          assert(!(isZeroPoint(patch.iterator.getInputExtent()) && isZeroPoint(patch.iterator.getOutputExtent())), "Empty region found. " + seedMessage);
          synthesizedOutput += patch.iterator.getNewText()
          synthesizedInput += patch.iterator.getOldText()
        } else {
          synthesizedOutput += input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd())
          synthesizedInput += input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd())
        }
      } while (patch.iterator.moveToSuccessor())

      assert.equal(synthesizedInput, input.getText(), seedMessage)
      assert.equal(synthesizedOutput, output.getText(), seedMessage)

      synthesizedInput = output.clone()
      synthesizedOutput = input.clone()
      for (let {oldStart, newStart, oldExtent, newExtent, oldText, newText} of patch.getChanges()) {
        synthesizedInput.splice(oldStart, newExtent, oldText)
        synthesizedOutput.splice(newStart, oldExtent, newText)
      }

      assert.equal(synthesizedInput.getText(), input.getText(), seedMessage)
      assert.equal(synthesizedOutput.getText(), output.getText(), seedMessage)
    }

    function verifyInputChanges (patch, input, output, seedMessage) {
      patch.iterator.moveToEnd()
      let synthesizedInput = input.getTextInRange(patch.iterator.getInputEnd(), INFINITY_POINT)
      let synthesizedOutput = input.getTextInRange(patch.iterator.getInputEnd(), INFINITY_POINT)
      do {
        if (patch.iterator.inChange()) {
          assert(!(isZeroPoint(patch.iterator.getInputExtent()) && isZeroPoint(patch.iterator.getOutputExtent())), "Empty region found. " + seedMessage);
          synthesizedOutput = patch.iterator.getNewText() + synthesizedOutput
          synthesizedInput = patch.iterator.getOldText() + synthesizedInput
        } else {
          synthesizedOutput = input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd()) + synthesizedOutput
          synthesizedInput = input.getTextInRange(patch.iterator.getInputStart(), patch.iterator.getInputEnd()) + synthesizedInput
        }
      } while (patch.iterator.moveToPredecessor())

      assert.equal(synthesizedInput, input.getText(), seedMessage)
      assert.equal(synthesizedOutput, output.getText(), seedMessage)

      synthesizedOutput = input.clone()
      synthesizedInput = output.clone()
      for (let {oldStart, newStart, oldExtent, newExtent, oldText, newText} of patch.getChanges().slice().reverse()) {
        synthesizedOutput.splice(oldStart, oldExtent, newText)
        synthesizedInput.splice(newStart, newExtent, oldText)
      }

      assert.equal(synthesizedOutput.getText(), output.getText(), seedMessage)
      assert.equal(synthesizedInput.getText(), input.getText(), seedMessage)
    }
  })
})
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var collectParallel = require('collect-parallel/array');
var CountedReadySignal = require('ready-signal/counted');
var net = require('net');
var timers = require('timers');
var util = require('util');

var allocCluster = require('./lib/test-cluster.js');
var CollapsedAssert = require('./lib/collapsed-assert.js');

/* eslint-disable no-multi-spaces */
var PERIOD           = 100;
var REQUEST_TIMEOUT  = 200;
var REQUEST_FACTOR   = 1;
var COOL_OFF_PERIODS = 10;
var CLUSTER_SIZE     = 10;
var CHURN_FACTOR     = 0.5;
var K_VALUE          = 5;
var SERVICE_SIZE     = 10;

function fuzzedPeriods(N) {
    return 1.05 * N * PERIOD;
}

allocCluster.test('peer churn', {
    size: CLUSTER_SIZE,
    noBob: true,
    noSteve: true,
    noTCollector: true,

    remoteConfig: {
        'kValue.services': {
            'lucy': K_VALUE
        },
        'peerConnecter.period': PERIOD,
        'peerPruner.period': PERIOD,
        'peerReaper.period': PERIOD
    },

    whitelist: [

        // XXX do we care about the rare:
        // AUTOBAHN INFO: ignoring outresponse.send on a closed connection ~ { responseId: 5,

        ['info', 'reaping dead peers'],
        ['info', 'reaping dead peer'],
        ['info', 'draining peer'],

        ['error', 'Failed to register to hyperbahn for remote'],

        ['info', 'Peer drained and closed due to unadvertisement'],
        ['info', 'canceling peer drain'],
        ['info', 'draining pruned peer'],
        ['info', 'pruning peers'],
        ['info', 'stopping peer drain'],

        // XXX flappy logs but no harm
        ['warn', 'error while forwarding'],
        ['info', 'resetting connection']

    ]

}, function t(cluster, assert) {
    var serverOpts = {
        serviceName: 'lucy',
        registerEvery: 50
    };

    var clientOpts = {
        serviceName: 'kathy',
        registerEvery: 50
    };

    var client = cluster.createRemote(clientOpts, clientReady);
    var first = null;
    var second = null;
    var turnips = null;

    function clientReady() {
        assert.comment('- clientReady');
        checkAllLogs(cluster, assert, checkConnectingLog);
        first = createRemotes(cluster, SERVICE_SIZE, serverOpts, gotFirstRound);
    }

    function gotFirstRound() {
        assert.comment('- gotFirstRound');
        checkAllLogs(cluster, assert, checkConnectingLog);
        checkExitsTo(cluster, 'lucy', first, 'the first peers', assert);
        checkRequestsTo('lucy', first, 'the first peers', client.clientChannel, assert, setupSecondRound);
    }

    function setupSecondRound() {
        assert.comment('- setupSecondRound');
        checkNoLogs('first phase sends', cluster, assert);
        second = createRemotes(cluster, Math.round(CHURN_FACTOR * first.length), serverOpts, gotSecondRound);
    }

    function gotSecondRound() {
        assert.comment('- gotSecondRound');
        checkAllLogs(cluster, assert, checkConnectingLog);
        checkExitsTo(cluster, 'lucy', second, 'the second peers', assert);
        checkRequestsTo('lucy', first.concat(second), 'either generation', client.clientChannel, assert, thenShutdownFirstRound);
    }

    function thenShutdownFirstRound() {
        assert.comment('- thenShutdownFirstRound');
        collectParallel(first, function each(remote, i, done) {
            // half of them do an unad then destroy, the other half just go away
            if (i % 2 === 0) {
                remote.doUnregister(function unreged(err) {
                    assert.ifError(err, 'expected no unregister error');
                    remote.destroy(done);
                });
            } else {
                remote.destroy(done);
            }
        }, thenWaitForReaper);
    }

    function thenWaitForReaper() {
        assert.comment('- thenWaitForReaper');

        checkAllLogs(cluster, assert, function checkEachLog(record) {
            assert.ok([
                // happens for destructive shutdown
                'Failed to register to hyperbahn for remote',
                'expected registration failure during destruction',
                'resetting connection',

                // these happen due to the unads
                'Peer drained and closed due to unadvertisement',
                'canceling peer drain',
                'draining peer',
                'implementing affinity change',
                'stopping peer drain',
                'pruning peers'
            ].indexOf(record.msg) >= 0, 'expected reaping logs');
        });

        timers.setTimeout(thenTurnip, fuzzedPeriods(COOL_OFF_PERIODS));
    }

    function thenTurnip() {
        assert.comment('- thenTurnip');

        // checkNoLogs('reap', cluster, assert);

        checkAllLogs(cluster, assert, function checkEachLog(record) {
            assert.ok([
                // these happen more for the peers that didn't unad above
                'connecting peers',
                'resetting connection',
                'reaping dead peers',
                'reaping dead peer',
                'draining peer',
                'pruning peers'
            ].indexOf(record.msg) >= 0, 'expected peer churn logs');
        });

        turnips = createTurnips(first, thenWaitAndSee);
    }

    function thenWaitAndSee() {
        assert.comment('- thenWaitAndSee');

        checkNoLogs('turnip', cluster, assert);

        timers.setTimeout(function tendTurnips() {
            checkNoLogs('turnip tending', cluster, assert);
            checkTurnips();
            sendAfterChurn();
        }, fuzzedPeriods(COOL_OFF_PERIODS));
    }

    function checkTurnips() {
        var logs = turnips.takeConnLogs();
        for (var i = 0; i < logs.length; ++i) {
            var log = logs[i];
            assert.equal(log.length, 0, util.format(
                'expected no connections to turnip[%s] (%s)',
                i, turnips[i].remote.channel.hostPort
            ));
        }
    }

    function sendAfterChurn() {
        assert.comment('- sendAfterChurn');
        checkRequestsTo('lucy', second, 'the second peers', client.clientChannel, assert, thenDestroySecondRound);
    }

    function thenDestroySecondRound() {
        assert.comment('- thenDestroySecondRound');

        // XXX: these don't always happen, but when they do the client retries around them
        checkAllLogs(cluster, assert, function checkEachLog(record) {
            if (record.msg === 'error while forwarding') {
                var fields = record._logData.fields;
                assert.equal(fields.error.type, 'tchannel.connection.reset',
                    'expected connection reset while forwarding error');
            } else {
                assert.equal(record.msg, 'resetting connection',
                    'expected resetting connection log');
            }
        });

        checkTurnips();

        destroyAll(second.concat(turnips).concat([client]), finish);
    }

    function finish() {
        assert.comment('- finish');
        assert.end();
    }
});

function checkConnectingLog(record, assert) {
    assert.ok([
        'connecting peers',
        'implementing affinity change'
    ].indexOf(record.msg) >= 0, 'expected connection logs due to peer advertise');
}

function destroyAll(destroyables, cb) {
    collectParallel(destroyables, destroyEach, cb);
}

function destroyEach(destroyable, i, done) {
    destroyable.destroy(done);
}

function createRemotes(cluster, N, opts, cb) {
    var done = CountedReadySignal(N);
    var res = [];
    for (var i = 0; i < N; ++i) {
        res[i] = cluster.createRemote(opts, done.signal);
        res[i].serverChannel.register('who', who);
    }
    done(cb);
    return res;
}

function who(req, res) {
    res.headers.as = 'raw';
    res.sendOk('', req.channel.hostPort);
}

function checkExitsTo(cluster, serviceName, cohort, desc, assert) {
    var cassert = CollapsedAssert();
    for (var i = 0; i < cohort.length; ++i) {
        var peer = cohort[i];
        cluster.checkExitPeers(cassert, {
            serviceName: serviceName,
            hostPort: peer.hostPort
        });
    }
    cassert.report(assert, 'expected exit peers for ' + desc);
}

/* eslint max-params: [2,8] */
function checkRequestsTo(serviceName, cohort, desc, chan, assert, cb) {
    var cassert = CollapsedAssert();
    sendMany(chan, REQUEST_FACTOR * cohort.length, {
        serviceName: serviceName,
        timeout: REQUEST_TIMEOUT
    }, 'who', '', '', function sent(err, res, arg2, arg3) {
        cassert.ifError(err, 'no unexpected error');
        var serverHostPort = String(arg3);
        cassert.ok(cohort.some(function isit(remote) {
            return remote.hostPort === serverHostPort;
        }), 'expected request to be served by one of ' + desc);
    }, function finish() {
        cassert.report(assert, 'expected requests to be served by ' + desc);
        cb();
    });
}

function sendMany(chan, N, opts, arg1, arg2, arg3, check, cb) {
    var sendsDone = CountedReadySignal(N);
    sendsDone(cb);
    for (var i = 0; i < sendsDone.counter; ++i) {
        timers.setImmediate(doRequest);
    }

    function doRequest() {
        chan.request(opts).send(arg1, arg2, arg3, done);
    }

    function done(err, res, resArg2, resArg3) {
        check(err, res, resArg2, resArg3);
        sendsDone.signal();
    }
}

function takeLogs(dbgLogtron) {
    var records = dbgLogtron._backend.records;
    dbgLogtron._backend.records = [];
    return records;
}

function checkAllLogs(cluster, assert, check) {
    var failed = false;
    assert.on('result', onResult);

    var records = takeLogs(cluster.logger);
    for (var i = 0; i < records.length; ++i) {
        var record = records[i];
        failed = false;
        check(record, assert);
        if (failed) {
            assert.comment(util.format(
                'UNEXPECTED LOG: %s %s: %j',
                record.levelName, record.msg, record._logData.fields
            ));
        }
    }
    assert.removeListener('result', onResult);

    function onResult(result) {
        if (!failed && typeof result === 'object') {
            failed = !result.ok;
        }
    }
}

function checkNoLogs(desc, cluster, assert) {
    var records = takeLogs(cluster.logger);
    assert.equal(records.length, 0, 'expected no logs from ' + desc);
    if (records.length) {
        for (var i = 0; i < records.length; ++i) {
            var record = records[i];
            assert.comment(util.format('UNEXPECTED LOG: %s %s: %j',
                record.levelName, record.msg, record._logData.fields
            ));
        }
    }
}

// creates dirst-stupid fixture tcp servers in place of each destroyed remote
function createTurnips(remotes, cb) {
    var turnips = [];
    turnips.takeConnLogs = takeConnLogs;
    collectParallel(remotes, createEachTurnip, cb);
    return turnips;

    function takeConnLogs() {
        var logs = [];
        for (var i = 0; i < turnips.length; ++i) {
            logs[i] = turnips[i].takeConnLog();
        }
        return logs;
    }

    function createEachTurnip(remote, i, done) {
        turnips[i] = createTurnip(remote, done);
    }
}

function createTurnip(remote, cb) {
    var turnip = {
        remote: remote,
        server: net.createServer(onConnection),
        connLog: [],
        destroy: destroy,
        takeConnLog: takeConnLog
    };

    var parts = remote.channel.hostPort.split(':');
    var host = parts[0];
    var port = parseInt(parts[1], 10);
    turnip.server.listen(port, host, cb);

    return turnip;

    function takeConnLog() {
        var log = turnip.connLog;
        turnip.connLog = [];
        return log;
    }

    function destroy(destroyCb) {
        turnip.server.close(destroyCb);
    }

    function onConnection(socket) {
        turnip.connLog.push({
            remoteAddress: socket.remoteAddress,
            remotePort: socket.remotePort
        });
        socket.end();
    }
}
<commit_msg>Okay, just ignore that log too<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var collectParallel = require('collect-parallel/array');
var CountedReadySignal = require('ready-signal/counted');
var net = require('net');
var timers = require('timers');
var util = require('util');

var allocCluster = require('./lib/test-cluster.js');
var CollapsedAssert = require('./lib/collapsed-assert.js');

/* eslint-disable no-multi-spaces */
var PERIOD           = 100;
var REQUEST_TIMEOUT  = 200;
var REQUEST_FACTOR   = 1;
var COOL_OFF_PERIODS = 10;
var CLUSTER_SIZE     = 10;
var CHURN_FACTOR     = 0.5;
var K_VALUE          = 5;
var SERVICE_SIZE     = 10;

function fuzzedPeriods(N) {
    return 1.05 * N * PERIOD;
}

allocCluster.test('peer churn', {
    size: CLUSTER_SIZE,
    noBob: true,
    noSteve: true,
    noTCollector: true,

    remoteConfig: {
        'kValue.services': {
            'lucy': K_VALUE
        },
        'peerConnecter.period': PERIOD,
        'peerPruner.period': PERIOD,
        'peerReaper.period': PERIOD
    },

    whitelist: [

        // XXX do we care about the rare:
        // AUTOBAHN INFO: ignoring outresponse.send on a closed connection ~ { responseId: 5,

        ['info', 'reaping dead peers'],
        ['info', 'reaping dead peer'],
        ['info', 'draining peer'],

        ['error', 'Failed to register to hyperbahn for remote'],

        ['info', 'Peer drained and closed due to unadvertisement'],
        ['info', 'canceling peer drain'],
        ['info', 'draining pruned peer'],
        ['info', 'pruning peers'],
        ['info', 'stopping peer drain'],

        // XXX flappy logs but no harm
        ['warn', 'error while forwarding'],
        ['info', 'resetting connection']

    ]

}, function t(cluster, assert) {
    var serverOpts = {
        serviceName: 'lucy',
        registerEvery: 50
    };

    var clientOpts = {
        serviceName: 'kathy',
        registerEvery: 50
    };

    var client = cluster.createRemote(clientOpts, clientReady);
    var first = null;
    var second = null;
    var turnips = null;

    function clientReady() {
        assert.comment('- clientReady');
        checkAllLogs(cluster, assert, checkConnectingLog);
        first = createRemotes(cluster, SERVICE_SIZE, serverOpts, gotFirstRound);
    }

    function gotFirstRound() {
        assert.comment('- gotFirstRound');
        checkAllLogs(cluster, assert, checkConnectingLog);
        checkExitsTo(cluster, 'lucy', first, 'the first peers', assert);
        checkRequestsTo('lucy', first, 'the first peers', client.clientChannel, assert, setupSecondRound);
    }

    function setupSecondRound() {
        assert.comment('- setupSecondRound');
        checkNoLogs('first phase sends', cluster, assert);
        second = createRemotes(cluster, Math.round(CHURN_FACTOR * first.length), serverOpts, gotSecondRound);
    }

    function gotSecondRound() {
        assert.comment('- gotSecondRound');
        checkAllLogs(cluster, assert, checkConnectingLog);
        checkExitsTo(cluster, 'lucy', second, 'the second peers', assert);
        checkRequestsTo('lucy', first.concat(second), 'either generation', client.clientChannel, assert, thenShutdownFirstRound);
    }

    function thenShutdownFirstRound() {
        assert.comment('- thenShutdownFirstRound');
        collectParallel(first, function each(remote, i, done) {
            // half of them do an unad then destroy, the other half just go away
            if (i % 2 === 0) {
                remote.doUnregister(function unreged(err) {
                    assert.ifError(err, 'expected no unregister error');
                    remote.destroy(done);
                });
            } else {
                remote.destroy(done);
            }
        }, thenWaitForReaper);
    }

    function thenWaitForReaper() {
        assert.comment('- thenWaitForReaper');

        checkAllLogs(cluster, assert, function checkEachLog(record) {
            assert.ok([
                // happens for destructive shutdown
                'Failed to register to hyperbahn for remote',
                'expected registration failure during destruction',
                'resetting connection',

                // these happen due to the unads
                'Peer drained and closed due to unadvertisement',
                'canceling peer drain',
                'draining peer',
                'implementing affinity change',
                'stopping peer drain',
                'pruning peers'
            ].indexOf(record.msg) >= 0, 'expected reaping logs');
        });

        timers.setTimeout(thenTurnip, fuzzedPeriods(COOL_OFF_PERIODS));
    }

    function thenTurnip() {
        assert.comment('- thenTurnip');

        // checkNoLogs('reap', cluster, assert);

        checkAllLogs(cluster, assert, function checkEachLog(record) {
            assert.ok([
                // these happen more for the peers that didn't unad above
                'connecting peers',
                'resetting connection',
                'reaping dead peers',
                'reaping dead peer',
                'draining peer',
                'pruning peers'
            ].indexOf(record.msg) >= 0, 'expected peer churn logs');
        });

        turnips = createTurnips(first, thenWaitAndSee);
    }

    function thenWaitAndSee() {
        assert.comment('- thenWaitAndSee');

        checkNoLogs('turnip', cluster, assert);

        timers.setTimeout(function tendTurnips() {
            checkNoLogs('turnip tending', cluster, assert);
            checkTurnips();
            sendAfterChurn();
        }, fuzzedPeriods(COOL_OFF_PERIODS));
    }

    function checkTurnips() {
        var logs = turnips.takeConnLogs();
        for (var i = 0; i < logs.length; ++i) {
            var log = logs[i];
            assert.equal(log.length, 0, util.format(
                'expected no connections to turnip[%s] (%s)',
                i, turnips[i].remote.channel.hostPort
            ));
        }
    }

    function sendAfterChurn() {
        assert.comment('- sendAfterChurn');
        checkRequestsTo('lucy', second, 'the second peers', client.clientChannel, assert, thenDestroySecondRound);
    }

    function thenDestroySecondRound() {
        assert.comment('- thenDestroySecondRound');

        // XXX: these don't always happen, but when they do the client retries around them
        checkAllLogs(cluster, assert, function checkEachLog(record) {
            if (record.msg === 'error while forwarding') {
                var fields = record._logData.fields;
                assert.equal(fields.error.type, 'tchannel.connection.reset',
                    'expected connection reset while forwarding error');
            } else {
                assert.equal(record.msg, 'resetting connection',
                    'expected resetting connection log');
            }
        });

        checkTurnips();

        destroyAll(second.concat(turnips).concat([client]), finish);
    }

    function finish() {
        assert.comment('- finish');
        assert.end();
    }
});

function checkConnectingLog(record, assert) {
    assert.ok([
        // XXX this is a sign of this test running too slowly for the given
        // parameters... but finding a balance where travis produces none of
        // them, while still running at useful parameters here is...
        // challenging
        'reaping dead peers',

        'connecting peers',
        'implementing affinity change'
    ].indexOf(record.msg) >= 0, 'expected connection logs due to peer advertise');
}

function destroyAll(destroyables, cb) {
    collectParallel(destroyables, destroyEach, cb);
}

function destroyEach(destroyable, i, done) {
    destroyable.destroy(done);
}

function createRemotes(cluster, N, opts, cb) {
    var done = CountedReadySignal(N);
    var res = [];
    for (var i = 0; i < N; ++i) {
        res[i] = cluster.createRemote(opts, done.signal);
        res[i].serverChannel.register('who', who);
    }
    done(cb);
    return res;
}

function who(req, res) {
    res.headers.as = 'raw';
    res.sendOk('', req.channel.hostPort);
}

function checkExitsTo(cluster, serviceName, cohort, desc, assert) {
    var cassert = CollapsedAssert();
    for (var i = 0; i < cohort.length; ++i) {
        var peer = cohort[i];
        cluster.checkExitPeers(cassert, {
            serviceName: serviceName,
            hostPort: peer.hostPort
        });
    }
    cassert.report(assert, 'expected exit peers for ' + desc);
}

/* eslint max-params: [2,8] */
function checkRequestsTo(serviceName, cohort, desc, chan, assert, cb) {
    var cassert = CollapsedAssert();
    sendMany(chan, REQUEST_FACTOR * cohort.length, {
        serviceName: serviceName,
        timeout: REQUEST_TIMEOUT
    }, 'who', '', '', function sent(err, res, arg2, arg3) {
        cassert.ifError(err, 'no unexpected error');
        var serverHostPort = String(arg3);
        cassert.ok(cohort.some(function isit(remote) {
            return remote.hostPort === serverHostPort;
        }), 'expected request to be served by one of ' + desc);
    }, function finish() {
        cassert.report(assert, 'expected requests to be served by ' + desc);
        cb();
    });
}

function sendMany(chan, N, opts, arg1, arg2, arg3, check, cb) {
    var sendsDone = CountedReadySignal(N);
    sendsDone(cb);
    for (var i = 0; i < sendsDone.counter; ++i) {
        timers.setImmediate(doRequest);
    }

    function doRequest() {
        chan.request(opts).send(arg1, arg2, arg3, done);
    }

    function done(err, res, resArg2, resArg3) {
        check(err, res, resArg2, resArg3);
        sendsDone.signal();
    }
}

function takeLogs(dbgLogtron) {
    var records = dbgLogtron._backend.records;
    dbgLogtron._backend.records = [];
    return records;
}

function checkAllLogs(cluster, assert, check) {
    var failed = false;
    assert.on('result', onResult);

    var records = takeLogs(cluster.logger);
    for (var i = 0; i < records.length; ++i) {
        var record = records[i];
        failed = false;
        check(record, assert);
        if (failed) {
            assert.comment(util.format(
                'UNEXPECTED LOG: %s %s: %j',
                record.levelName, record.msg, record._logData.fields
            ));
        }
    }
    assert.removeListener('result', onResult);

    function onResult(result) {
        if (!failed && typeof result === 'object') {
            failed = !result.ok;
        }
    }
}

function checkNoLogs(desc, cluster, assert) {
    var records = takeLogs(cluster.logger);
    assert.equal(records.length, 0, 'expected no logs from ' + desc);
    if (records.length) {
        for (var i = 0; i < records.length; ++i) {
            var record = records[i];
            assert.comment(util.format('UNEXPECTED LOG: %s %s: %j',
                record.levelName, record.msg, record._logData.fields
            ));
        }
    }
}

// creates dirst-stupid fixture tcp servers in place of each destroyed remote
function createTurnips(remotes, cb) {
    var turnips = [];
    turnips.takeConnLogs = takeConnLogs;
    collectParallel(remotes, createEachTurnip, cb);
    return turnips;

    function takeConnLogs() {
        var logs = [];
        for (var i = 0; i < turnips.length; ++i) {
            logs[i] = turnips[i].takeConnLog();
        }
        return logs;
    }

    function createEachTurnip(remote, i, done) {
        turnips[i] = createTurnip(remote, done);
    }
}

function createTurnip(remote, cb) {
    var turnip = {
        remote: remote,
        server: net.createServer(onConnection),
        connLog: [],
        destroy: destroy,
        takeConnLog: takeConnLog
    };

    var parts = remote.channel.hostPort.split(':');
    var host = parts[0];
    var port = parseInt(parts[1], 10);
    turnip.server.listen(port, host, cb);

    return turnip;

    function takeConnLog() {
        var log = turnip.connLog;
        turnip.connLog = [];
        return log;
    }

    function destroy(destroyCb) {
        turnip.server.close(destroyCb);
    }

    function onConnection(socket) {
        turnip.connLog.push({
            remoteAddress: socket.remoteAddress,
            remotePort: socket.remotePort
        });
        socket.end();
    }
}
<|endoftext|>


<commit_before>import GLTexture from './GLTexture.js';
import GLFrameBuffer from './GLFrameBuffer.js';
import GLProgram from './GLProgram.js';
import GLPlaneObject from './objects/GLPlaneObject.js';

export default class GLShaderTexture extends GLTexture {
  constructor({
    gl,
    width,
    height,
    target = gl.TEXTURE_2D,
    internalFormat = gl.RGBA8 || gl.RGBA,
    format = gl.RGBA,
    type = gl.UNSIGNED_BYTE,
    minFilter = gl.LINEAR,
    magFilter = gl.LINEAR,
    wrapS = gl.REPEAT,
    wrapT = gl.REPEAT,
    generateMipmap = false,
    uniforms = {},
    fragmentShaderChunks = [],
  }) {
    super({
      gl,
      width,
      height,
      target,
      internalFormat,
      format,
      type,
      minFilter,
      magFilter,
      wrapS,
      wrapT,
      generateMipmap,
    });

    this._frameBuffer = new GLFrameBuffer({
      gl: this.gl,
      colorTextures: [this],
    });

    this._quad = new GLPlaneObject({
      gl: this.gl,
      width: 2,
      height: 2,
      uvs: true,
      program: new GLProgram({
        gl: this.gl,
        shader: {
          uniforms,
          vertexShaderChunks: [
            ['start', `
              in vec3 position;
              in vec2 uv;

              out vec2 vUV;
            `],
            ['end', `
              gl_Position = vec4(position, 1.);
              vUV = uv;
            `],
          ],
          fragmentShaderChunks,
        },
      }),
    });
  }

  update({ uniforms = {}, debug = false }) {
    const previousViewport = this.gl.getParameter(this.gl.VIEWPORT);
    this.gl.viewport(0, 0, this.width, this.height);
    this._frameBuffer.bind();
    this._quad.draw({
      uniforms,
    });
    this._frameBuffer.unbind();
    if (debug) {
      this._quad.draw({
        uniforms,
      });
    }
    this.gl.viewport(...previousViewport);
  }
}
<commit_msg>GLShaderTexture update on init<commit_after>import GLTexture from './GLTexture.js';
import GLFrameBuffer from './GLFrameBuffer.js';
import GLProgram from './GLProgram.js';
import GLPlaneObject from './objects/GLPlaneObject.js';

export default class GLShaderTexture extends GLTexture {
  constructor({
    gl,
    width,
    height,
    target = gl.TEXTURE_2D,
    internalFormat = gl.RGBA8 || gl.RGBA,
    format = gl.RGBA,
    type = gl.UNSIGNED_BYTE,
    minFilter = gl.LINEAR,
    magFilter = gl.LINEAR,
    wrapS = gl.REPEAT,
    wrapT = gl.REPEAT,
    generateMipmap = false,
    uniforms = {},
    fragmentShaderChunks = [],
    debug = false,
  }) {
    super({
      gl,
      width,
      height,
      target,
      internalFormat,
      format,
      type,
      minFilter,
      magFilter,
      wrapS,
      wrapT,
      generateMipmap,
    });

    this._frameBuffer = new GLFrameBuffer({
      gl: this.gl,
      colorTextures: [this],
    });

    this._quad = new GLPlaneObject({
      gl: this.gl,
      width: 2,
      height: 2,
      uvs: true,
      program: new GLProgram({
        gl: this.gl,
        shader: {
          uniforms,
          vertexShaderChunks: [
            ['start', `
              in vec3 position;
              in vec2 uv;

              out vec2 vUV;
            `],
            ['end', `
              gl_Position = vec4(position, 1.);
              vUV = uv;
            `],
          ],
          fragmentShaderChunks,
        },
      }),
    });

    this.update({ uniforms, debug });
  }

  update({ uniforms = {}, debug = false } = {}) {
    const previousViewport = this.gl.getParameter(this.gl.VIEWPORT);
    this.gl.viewport(0, 0, this.width, this.height);
    this._frameBuffer.bind();
    this._quad.draw({
      uniforms,
    });
    this._frameBuffer.unbind();
    if (debug) {
      this._quad.draw({
        uniforms,
      });
    }
    this.gl.viewport(...previousViewport);
  }
}
<|endoftext|>


<commit_before>var subject = require('..');
var assert = require('assert');

describe('replacement', function() {
  it('supports replacement for %d', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}d'), 'A/b/c/d');
  });
  it('supports replacement and partials for %d', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}2d'), 'A/b');
  });
  it('supports replacement for %p', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}p'), 'A/b/c/d/file.txt');
  });
  it('supports replacement for %f', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{txt,js}f'), 'file.js');
  });
  it('supports replacement for %n', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{ile,ood}n'), 'food');
  });
  it('supports replacement for %x', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{xt,ext}x'), '.text');
  });
  it('supports replacement for %X', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}X'), 'A/b/c/d/file');
  });
});
<commit_msg>Add tests for replacement callbacks<commit_after>var subject = require('..');
var assert = require('assert');

describe('replacement', function() {
  it('supports replacement for %d', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}d'), 'A/b/c/d');
  });
  it('supports replacement and partials for %d', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}2d'), 'A/b');
  });
  it('supports replacement for %p', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}p'), 'A/b/c/d/file.txt');
  });
  it('supports replacement for %f', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{txt,js}f'), 'file.js');
  });
  it('supports replacement for %n', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{ile,ood}n'), 'food');
  });
  it('supports replacement for %x', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{xt,ext}x'), '.text');
  });
  it('supports replacement for %X', function() {
    assert.equal(subject('a/b/c/d/file.txt', '%{a,A}X'), 'A/b/c/d/file');
  });
  describe('callbacks', function() {
    it('supports replacement callbacks for %d', function() {
      assert.equal(subject('a/b/c/d/file.txt', '%{a,*}d', function() {
        return 'A';
      }), 'A/b/c/d');
    });
    it('supports replacement callbacks and partials for %d', function() {
      assert.equal(subject('a/b/c/d/file.txt', '%{a,*}2d', function() {
        return 'A';
      }), 'A/b');
    });
    it('supports replacement callbacks for %p', function() {
      assert.equal(subject('a/b/c/d/file.txt', '%{a,*}p', function() {
        return 'A';
      }), 'A/b/c/d/file.txt');
    });
    it('supports replacement callbacks for %f', function() {
      assert.equal(subject('a/b/c/d/file.txt', '%{txt,*}f', function() {
        return 'js';
      }), 'file.js');
    });
    it('supports replacement callbacks for %n', function() {
      assert.equal(subject('a/b/c/d/file.txt', '%{ile,*}n', function() {
        return 'ood';
      }), 'food');
    });
    it('supports replacement callbacks for %x', function() {
      assert.equal(subject('a/b/c/d/file.txt', '%{xt,*}x', function() {
        return 'ext';
      }), '.text');
    });
    it('supports replacement callbacks for %X', function() {
      assert.equal(subject('a/b/c/d/file.txt', '%{a,*}X', function() {
        return 'A';
      }), 'A/b/c/d/file');
    });
  });
});
<|endoftext|>


<commit_before>var assert = require('assert');
var fs = require('fs');

var grib = require('../grib');

var tpcprblty_grib2 = null;

// Load some sample data into a buffer
beforeEach(function(done) {
  fs.readFile('samples/tpcprblty.grib2', function(err, data) {
    tpcprblty_grib2 = data;
    done(err);
  });
});

describe('grib.readBuffer()', function() {
  it('should return null when no buffer given', function() {
    assert.strictEqual(null, grib.readBuffer());
  });

  it('should return an array of messages with a valid buffer', function() {
    var msgs = grib.readBuffer(tpcprblty_grib2);
    assert.ok(msgs.length >= 1);
    assert.ok(msgs[0]);
  });

  it('should throw an error with an invalid buffer', function() {
    assert.throws(function() { grib.readBuffer("one, two, three"); });
  });
});
<commit_msg>readBuffer: make sure test actually passes a buffer<commit_after>var assert = require('assert');
var fs = require('fs');

var grib = require('../grib');

var tpcprblty_grib2 = null;

// Load some sample data into a buffer
beforeEach(function(done) {
  fs.readFile('samples/tpcprblty.grib2', function(err, data) {
    tpcprblty_grib2 = data;
    done(err);
  });
});

describe('grib.readBuffer()', function() {
  it('should return null when no buffer given', function() {
    assert.strictEqual(null, grib.readBuffer());
  });

  it('should return an array of messages with a valid buffer', function() {
    var msgs = grib.readBuffer(tpcprblty_grib2);
    assert.ok(msgs.length >= 1);
    assert.ok(msgs[0]);
  });

  it('should throw an error with an invalid buffer', function() {
    assert.throws(function() { grib.readBuffer(new Buffer("one, two, three")); });
  });
});
<|endoftext|>


<commit_before>const hub = require('../')
const test = require('tape')

test('references', t => {
  const scraper = hub({
    _uid_: 'scraper',
    port: 6060,
    a: {
      b: {
        c: 'c!'
      }
    },
    bla: [ '@', 'parent', 'a', 'b', 'c' ]
  })

  const client = hub({
    _uid_: 'client',
    url: 'ws://localhost:6060'
  })

  client.subscribe({ bla: true })

  client.get([ 'a', 'b', 'c' ], {}).once('c!').then(() => {
    t.pass('received reference')
    client.set(null)
    scraper.set(null)
    t.end()
  })
})

test('circular references', t => {
  const scraper = hub({
    _uid_: 'scraper',
    port: 6060,
    a: {
      items: {
        b: ['@', 'root', 'b'],
        c: ['@', 'root', 'c']
      }
    },
    b: {
      val: 'valB',
      siblings: ['@', 'root', 'a', 'items']
    },
    c: {
      val: 'valC',
      siblings: ['@', 'root', 'a', 'items']
    }
  })

  const client = hub({
    _uid_: 'client',
    url: 'ws://localhost:6060'
  })

  client.subscribe(true)

  // this get does not work since it does not know the refs yet -- now gets its own path
  // client.get([ 'a', 'items', 'c', 'siblings', 'b' ], {}).once('valB').then(() => {

  // })

  setTimeout(() => {
    client.get([ 'a', 'items', 'c', 'siblings', 'b' ], {}).once('valB').then(() => {
      t.pass('received circular reference')
      client.set(null)
      scraper.set(null)
      t.end()
    })
  }, 100)
})
<commit_msg>with context<commit_after>const hub = require('../')
const test = require('tape')

test('references', t => {
  const scraper = hub({
    _uid_: 'scraper',
    port: 6060,
    a: {
      b: {
        c: 'c!'
      }
    },
    bla: [ '@', 'parent', 'a', 'b', 'c' ]
  })

  const client = hub({
    _uid_: 'client',
    url: 'ws://localhost:6060'
  })

  client.subscribe({ bla: true })

  client.get([ 'a', 'b', 'c' ], {}).once('c!').then(() => {
    t.pass('received reference')
    client.set(null)
    scraper.set(null)
    t.end()
  })
})

test('circular references', t => {
  const scraper = hub({
    _uid_: 'scraper',
    port: 6060,
    a: {
      items: {
        b: ['@', 'root', 'b'],
        c: ['@', 'root', 'c']
      }
    },
    b: {
      val: 'valB',
      siblings: ['@', 'root', 'a', 'items']
    },
    c: {
      val: 'valC',
      siblings: ['@', 'root', 'a', 'items']
    }
  })

  const client = hub({
    _uid_: 'client',
    url: 'ws://localhost:6060',
    context: 'someContextKey'
  })

  client.subscribe(true)

  setTimeout(() => {
    client.get([ 'a', 'items', 'c' ], {}).once('valC').then(() => {
      t.pass('received circular reference')
      client.set(null)
      scraper.set(null)
      t.end()
    })
  }, 100)
})
<|endoftext|>