<commit_before>
import { Observable, ObservableObject } from '../observable';
import CacheMapException from './CacheMapException';

class CacheMap extends ObservableObject {

    constructor(cacheMapId, entriesAreObservables) {
        this._cacheMapId = cacheMapId;
        this._entriesAreObservables = entriesAreObservables;
        this._entries = {};
    }

    _remove(entryId) {
        const entry = this.find(entryId);
        if (this._entriesAreObservables) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.removeParentObserver(this.observer);
        }
        delete this._entries[entryId];
        this._markAsChanged();
    }

    get cacheMapId() {
        return this._cacheMapId;
    }

    get entriesAreObservables() {
        return this._entriesAreObservables;
    }

    exists(entryId) {
        return this._entries.hasOwnProperty(entryId);
    }

    find(entryId) {
        return this.exists(entryId)
            ? this._entries[entryId] : undefined;
    }

    set(entryId, entry) {
        if (this.exists(entryId)) {
            this._remove(entryId);
        }
        this._entries[entryId] = entry;
        if (entry instanceof Observable) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.addParentObserver(this.observer);
        }
        this._markAsChanged();
        return this;
    }

    remove(entryId) {
        if (this.exists(entryId)) {
            this._remove(entryId);
        }
        return this;
    }

}

export default CacheMap;
<commit_msg>added Exception if it will be tried to remove none existing entries<commit_after>
import { Observable, ObservableObject } from '../observable';
import CacheMapException from './CacheMapException';

class CacheMap extends ObservableObject {

    constructor(cacheMapId, entriesAreObservables) {
        this._cacheMapId = cacheMapId;
        this._entriesAreObservables = entriesAreObservables;
        this._entries = {};
    }

    _remove(entryId) {
        const entry = this.find(entryId);
        if (this._entriesAreObservables) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.removeParentObserver(this.observer);
        }
        delete this._entries[entryId];
        this._markAsChanged();
    }

    get cacheMapId() {
        return this._cacheMapId;
    }

    get entriesAreObservables() {
        return this._entriesAreObservables;
    }

    exists(entryId) {
        return this._entries.hasOwnProperty(entryId);
    }

    find(entryId) {
        return this.exists(entryId)
            ? this._entries[entryId] : undefined;
    }

    set(entryId, entry) {
        if (this.exists(entryId)) {
            this._remove(entryId);
        }
        this._entries[entryId] = entry;
        if (entry instanceof Observable) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.addParentObserver(this.observer);
        }
        this._markAsChanged();
        return this;
    }

    remove(entryId) {
        if (!this.exists(entryId)) {
            throw new CacheMapException('Try to remove entry which doesn\'t exist!');
        }
        this._remove(entryId);
        return this;
    }

}

export default CacheMap;
<|endoftext|>


<commit_before>module("Course Tests");
asyncTest("getComp4350", 2,
	function()
	{
		var cid = "Comp4350";
		var cname = "Software Engineering 2"

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/courses/_query",
					cid,
					function(data)
					{
						equal(data.courses[0].cid, cid, "Course ID Matches");
						equal(data.courses[0].cname, cname, "Course Name Matches");
						start();
					});
	}
);

asyncTest("getComp3030", 2,
	function()
	{
		var cid = "Comp3030";
		var cname = "Automata Theory and Formal Languages";

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/courses/_query",
					cid,
					function(data)
					{
						equal(data.courses[0].cid, cid, "Course ID Matches");
						equal(data.courses[0].cname, cname, "Course Name Matches");
						start();
					});
	}
);

asyncTest("getAll", 1,
	function()
	{
		var cid = "";
		var num = 7;
		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/courses/_query",
					cid,
					function(data)
					{
						equal(data.courses.length, num, "We have received all courses successfull");
						start();
					});
	}
);

module("Reviews Tests");
asyncTest("getComp4350", 1,
	function()
	{
		var cid = "Comp4350";
		var expected = 0.85;

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/reviews/_query_by_course",
					cid,
					function(data)
					{
						equal(data.reviews[0].rscr, 0.85, "We have successfully received the one review for Comp4350");
						start();
					});
	}
);

asyncTest("getComp3030", 1,
	function()
	{
		var cid = "Comp303";
		var num = 0;

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/reviews/_query_by_course",
					cid,
					function(data)
					{
						equal(data.reviews.length, num, "Have successfully haven't received any course for Comp3030");
						start();
					});
	}
);

<commit_msg>Modified tests.js<commit_after>module("Course Tests");
asyncTest("getComp4350", 2,
	function()
	{
		var cid = "Comp4350";
		var cname = "Software Engineering 2"

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/courses/_query",
					cid,
					function(data)
					{
						equal(data.courses[0].cid, cid, "Course ID Matches");
						equal(data.courses[0].cname, cname, "Course Name Matches");
						start();
					});
	}
);

asyncTest("getComp3030", 2,
	function()
	{
		var cid = "Comp3030";
		var cname = "Automata Theory and Formal Languages";

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/courses/_query",
					cid,
					function(data)
					{
						equal(data.courses[0].cid, cid, "Course ID Matches");
						equal(data.courses[0].cname, cname, "Course Name Matches");
						start();
					});
	}
);

asyncTest("getAll", 1,
	function()
	{
		var cid = "";
		var num = 7;
		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/courses/_query",
					cid,
					function(data)
					{
						equal(data.courses.length, num, "We have received all courses successfull");
						start();
					});
	}
);

module("Reviews Tests");
asyncTest("getComp4350", 1,
	function()
	{
		var cid = "Comp4350";
		var expected = 0.85;

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/reviews/_query_by_course",
					cid,
					function(data)
					{
						equal(data.reviews[0].rscr, 0.85, "We have successfully received the one review for Comp4350");
						start();
					});
	}
);

asyncTest("getComp3030", 1,
	function()
	{
		var cid = "Comp3030";
		var num = 0;

		//I don't know why the url_for doesn't work here
		getObjects(	$SCRIPT_ROOT + "/reviews/_query_by_course",
					cid,
					function(data)
					{
						equal(data.reviews.length, num, "Have successfully haven't received any course for Comp3030");
						start();
					});
	}
);

<|endoftext|>


<commit_before>var vows = require('vows');
var assert = require('assert');
var util = require('util');
var code = require('../../lib/grant/code');

function MockRequest() {
}

function MockResponse() {
  this._headers = {};
  this._data = '';
}

MockResponse.prototype.setHeader = function(name, value) {
  this._headers[name] = value;
}

MockResponse.prototype.redirect = function(location) {
  this._redirect = location;
  this.end();
}

MockResponse.prototype.end = function(data, encoding) {
  this._data += data;
  if (this.done) { this.done(); }
}

vows.describe('code').addBatch({

  // OK
  'middleware': {
    topic: function() {
      return code(function() {});
    },

    'should return a module named code' : function(mod) {
      assert.equal(mod.name, 'code');
    },
    'should return a module with request and response functions' : function(mod) {
      assert.isFunction(mod.request);
      assert.isFunction(mod.response);
    },
  },

  // OK
  'request parsing function that receives a request': {
    topic: function() {
      return code(function() {});
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        req.query = { client_id: 'c123',
          redirect_uri: 'http://example.com/auth/callback',
          state: 'f1o1o1'
        };

        process.nextTick(function () {
          try {
            var obj = code.request(req);
            self.callback(null, obj);
          } catch (e) {
            self.callback(e);
          }
        });
      },

      'should not throw' : function(err, obj) {
        assert.isNull(err);
      },
      'should parse request' : function(err, obj) {
        assert.equal(obj.clientID, 'c123');
        assert.equal(obj.redirectURI, 'http://example.com/auth/callback');
        assert.isUndefined(obj.scope);
        assert.equal(obj.state, 'f1o1o1');
      },
    },
  },

  // OK
  'request parsing function that receives a request with scope': {
    topic: function() {
      return code(function() {});
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        req.query = { client_id: 'c123',
          redirect_uri: 'http://example.com/auth/callback',
          state: 'f1o1o1',
          scope: 'read'
        };

        process.nextTick(function () {
          try {
            var obj = code.request(req);
            self.callback(null, obj);
          } catch (e) {
            self.callback(e);
          }
        });
      },

      'should not throw' : function(err, obj) {
        assert.isNull(err);
      },
      'should parse request' : function(err, obj) {
        assert.equal(obj.clientID, 'c123');
        assert.equal(obj.redirectURI, 'http://example.com/auth/callback');
        assert.isArray(obj.scope);
        assert.lengthOf(obj.scope, 1);
        assert.equal(obj.scope[0], 'read');
        assert.equal(obj.state, 'f1o1o1');
      },
    },
  },

  // OK
  'request parsing function that receives a request with list of scopes': {
    topic: function() {
      return code(function() {});
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        req.query = { client_id: 'c123',
          redirect_uri: 'http://example.com/auth/callback',
          state: 'f1o1o1',
          scope: 'read write'
        };

        process.nextTick(function () {
          try {
            var obj = code.request(req);
            self.callback(null, obj);
          } catch (e) {
            self.callback(e);
          }
        });
      },

      'should not throw' : function(err, obj) {
        assert.isNull(err);
      },
      'should parse request' : function(err, obj) {
        assert.equal(obj.clientID, 'c123');
        assert.equal(obj.redirectURI, 'http://example.com/auth/callback');
        assert.isArray(obj.scope);
        assert.lengthOf(obj.scope, 2);
        assert.equal(obj.scope[0], 'read');
        assert.equal(obj.scope[1], 'write');
        assert.equal(obj.state, 'f1o1o1');
      },
    },
  },

  // OK
  'request parsing function using scope separator that receives a request with list of scopes': {
    topic: function() {
      return code({ scopeSeparator: ',' }, function() {});
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        req.query = { client_id: 'c123',
          redirect_uri: 'http://example.com/auth/callback',
          state: 'f1o1o1',
          scope: 'read,write'
        };

        process.nextTick(function () {
          try {
            var obj = code.request(req);
            self.callback(null, obj);
          } catch (e) {
            self.callback(e);
          }
        });
      },

      'should not throw' : function(err, obj) {
        assert.isNull(err);
      },
      'should parse request' : function(err, obj) {
        assert.equal(obj.clientID, 'c123');
        assert.equal(obj.redirectURI, 'http://example.com/auth/callback');
        assert.isArray(obj.scope);
        assert.lengthOf(obj.scope, 2);
        assert.equal(obj.scope[0], 'read');
        assert.equal(obj.scope[1], 'write');
        assert.equal(obj.state, 'f1o1o1');
      },
    },
  },

  // OK
  'request parsing function using multiple scope separators that receives a request with list of scopes': {
    topic: function() {
      return code({ scopeSeparator: [' ', ','] }, function() {});
    },

    'when handling a request with space scope separator': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        req.query = { client_id: 'c123',
          redirect_uri: 'http://example.com/auth/callback',
          state: 'f1o1o1',
          scope: 'read write'
        };

        process.nextTick(function () {
          try {
            var obj = code.request(req);
            self.callback(null, obj);
          } catch (e) {
            self.callback(e);
          }
        });
      },

      'should not throw' : function(err, obj) {
        assert.isNull(err);
      },
      'should parse request' : function(err, obj) {
        assert.equal(obj.clientID, 'c123');
        assert.equal(obj.redirectURI, 'http://example.com/auth/callback');
        assert.isArray(obj.scope);
        assert.lengthOf(obj.scope, 2);
        assert.equal(obj.scope[0], 'read');
        assert.equal(obj.scope[1], 'write');
        assert.equal(obj.state, 'f1o1o1');
      },
    },

    'when handling a request with comma scope separator': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        req.query = { client_id: 'c123',
          redirect_uri: 'http://example.com/auth/callback',
          state: 'f1o1o1',
          scope: 'read,write'
        };

        process.nextTick(function () {
          try {
            var obj = code.request(req);
            self.callback(null, obj);
          } catch (e) {
            self.callback(e);
          }
        });
      },

      'should not throw' : function(err, obj) {
        assert.isNull(err);
      },
      'should parse request' : function(err, obj) {
        assert.equal(obj.clientID, 'c123');
        assert.equal(obj.redirectURI, 'http://example.com/auth/callback');
        assert.isArray(obj.scope);
        assert.lengthOf(obj.scope, 2);
        assert.equal(obj.scope[0], 'read');
        assert.equal(obj.scope[1], 'write');
        assert.equal(obj.state, 'f1o1o1');
      },
    },
  },

  // OK
  'request parsing function that receives a request with missing client_id parameter': {
    topic: function() {
      return code(function() {});
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        req.query = { redirect_uri: 'http://example.com/auth/callback',
          state: 'f1o1o1'
        };

        process.nextTick(function () {
          try {
            var obj = code.request(req);
            self.callback(null, obj);
          } catch (e) {
            self.callback(e);
          }
        });
      },

      'should throw' : function(err, obj) {
        assert.instanceOf(err, Error);
        assert.equal(err.constructor.name, 'AuthorizationError');
        assert.equal(err.code, 'invalid_request');
        //assert.equal(err.message, 'missing client_id parameter');
      },
    },
  },

  // OK
  'response handling function that processes a decision': {
    topic: function() {
      return code(function(client, redirectURI, user, done) {
        if (client.id == 'c123' && redirectURI == 'http://example.com/auth/other/callback' && user.id == 'u123') {
          return done(null, 'xyz');
        } else {
          return done(new Error('something is wrong'));
        }
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(null, req, res);
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.redirectURI = 'http://example.com/auth/callback';
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: true }

        function next(err) {
          self.callback(new Error('should not be called'));
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not throw' : function(err, req, res) {
        assert.isNull(err);
      },
      'should parse request' : function(err, req, res) {
        assert.equal(res._redirect, 'http://example.com/auth/callback?code=xyz');
      },
    },
  },

  // OK
  'response handling function that processes a decision with state': {
    topic: function() {
      return code(function(client, redirectURI, user, done) {
        if (client.id == 'c123' && redirectURI == 'http://example.com/auth/other/callback' && user.id == 'u123') {
          return done(null, 'xyz');
        } else {
          return done(new Error('something is wrong'));
        }
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(null, req, res);
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.redirectURI = 'http://example.com/auth/callback';
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback',
          state: 'f1o1o1'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: true }

        function next(err) {
          self.callback(new Error('should not be called'));
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not throw' : function(err, req, res) {
        assert.isNull(err);
      },
      'should parse request' : function(err, req, res) {
        assert.equal(res._redirect, 'http://example.com/auth/callback?code=xyz&state=f1o1o1');
      },
    },
  },

  // OK
  'response handling function that processes a decision using user response': {
    topic: function() {
      return code(function(client, redirectURI, user, ares, done) {
        if (client.id == 'c123' && redirectURI == 'http://example.com/auth/other/callback' && user.id == 'u123' && ares.scope == 'foo') {
          return done(null, 'xyz');
        } else {
          return done(new Error('something is wrong'));
        }
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(null, req, res);
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.redirectURI = 'http://example.com/auth/callback';
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: true, scope: 'foo' };

        function next(err) {
          self.callback(new Error('should not be called'));
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not throw' : function(err, req, res) {
        assert.isNull(err);
      },
      'should parse request' : function(err, req, res) {
        assert.equal(res._redirect, 'http://example.com/auth/callback?code=xyz');
      },
    },
  },

  // OK
  'response handling function that processes a decision to disallow': {
    topic: function() {
      return code(function(client, redirectURI, user, done) {
        return done(new Error('should not be called'));
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(null, req, res);
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.redirectURI = 'http://example.com/auth/callback';
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: false }

        function next(err) {
          self.callback(new Error('should not be called'));
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not throw' : function(err, req, res) {
        assert.isNull(err);
      },
      'should parse request' : function(err, req, res) {
        assert.equal(res._redirect, 'http://example.com/auth/callback?error=access_denied');
      },
    },
  },

  // OK
  'response handling function that processes a decision to disallow with state': {
    topic: function() {
      return code(function(client, redirectURI, user, done) {
        return done(new Error('should not be called'));
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(null, req, res);
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.redirectURI = 'http://example.com/auth/callback';
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback',
          state: 'f2o2o2'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: false }

        function next(err) {
          self.callback(new Error('should not be called'));
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not throw' : function(err, req, res) {
        assert.isNull(err);
      },
      'should parse request' : function(err, req, res) {
        assert.equal(res._redirect, 'http://example.com/auth/callback?error=access_denied&state=f2o2o2');
      },
    },
  },

  // OK
  'response handling function that does not issue a code': {
    topic: function() {
      return code(function(client, redirectURI, user, done) {
        return done(null, false);
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(new Error('should not be called'));
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.redirectURI = 'http://example.com/auth/callback';
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: true }

        function next(err) {
          self.callback(null, req, res, err);
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not respond' : function(err, req, res, e) {
        assert.isNull(err);
      },
      'should next with error' : function(err, req, res, e) {
        assert.instanceOf(e, Error);
        assert.equal(e.constructor.name, 'AuthorizationError')
        assert.equal(e.code, 'access_denied')
        //assert.equal(e.message, 'authorization server denied request')
      },
      'should not parse request' : function(err, req, res, e) {
        assert.isUndefined(res._redirect);
      },
    },
  },

  // OK
  'response handling function that errors while processing a decision': {
    topic: function() {
      return code(function(client, redirectURI, user, done) {
        return done(new Error('something went wrong'))
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(new Error('should not be called'));
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.redirectURI = 'http://example.com/auth/callback';
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: true }

        function next(err) {
          self.callback(null, req, res, err);
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not respond' : function(err, req, res, e) {
        assert.isNull(err);
      },
      'should next with error' : function(err, req, res, e) {
        assert.instanceOf(e, Error);
      },
      'should not parse request' : function(err, req, res, e) {
        assert.isUndefined(res._redirect);
      },
    },
  },

  'response handling function processes a transaction witout redirect URI': {
    topic: function() {
      return code(function(client, redirectURI, user, done) {
        return done(null, 'xyz');
      });
    },

    'when handling a request': {
      topic: function(code) {
        var self = this;
        var req = new MockRequest();
        var res = new MockResponse();
        res.done = function() {
          self.callback(new Error('should not be called'));
        }

        var txn = {};
        txn.client = { id: 'c123', name: 'Example' };
        txn.req = {
          redirectURI: 'http://example.com/auth/other/callback'
        }
        txn.user = { id: 'u123', name: 'Bob' };
        txn.res = { allow: true }

        function next(err) {
          self.callback(null, req, res, err);
        }
        process.nextTick(function () {
          code.response(txn, res, next)
        });
      },

      'should not respond' : function(err, req, res, e) {
        assert.isNull(err);
      },
      'should next with error' : function(err, req, res, e) {
        assert.instanceOf(e, Error);
        //assert.equal(e.message, 'No redirect URI available to send OAuth 2.0 response.');
      },
      'should not parse request' : function(err, req, res, e) {
        assert.isUndefined(res._redirect);
      },
    },
  },

  // OK
  'middleware constructed without an issue function': {
    'should throw an error': function () {
      assert.throws(function() { code() });
    },
  },

}).export(module);
<commit_msg>Remove vows tests for code grant.<commit_after><|endoftext|>


<commit_before>import { sync as exec } from 'execa';

import { sync as glob } from 'glob';

import {
  readFileSync as readFile,
  existsSync as exists
} from 'fs';

import path from 'path';

import DmnModdle from '../..';

import SchemaValidator from 'xsd-schema-validator';

import { expect } from 'chai';

const DMN_XSD = 'resources/dmn/xsd/DMN13.xsd';

const tckDirectory = 'tmp/tck';

describe('dmn-moddle - TCK roundtrip', function() {

  const moddle = new DmnModdle();

  this.timeout(30000);

  if (exists(path.join(__dirname, tckDirectory, '.git'))) {
    console.log('tck repository already cloned, fetching and checking out origin/master...');

    const cwd = path.join(__dirname, tckDirectory);

    exec('git', [ 'fetch' ], { cwd });
    exec('git', [ 'checkout', 'origin/master' ], { cwd });
  } else {
    console.log(`cloning tck repository to ${ tckDirectory }...`);

    exec(
      'git',
      [ 'clone', '--depth=1', 'git@github.com:dmn-tck/tck.git', tckDirectory ],
      { cwd: __dirname }
    );
  }

  const fileNames = glob(tckDirectory + '/TestCases/**/*.dmn', { cwd: __dirname });

  function shouldRun(fileName) {
    const match = process.env.GREP;

    return !match || fileName.toLowerCase().includes(match);
  }

  describe('should roundtrip', function() {

    for (const fileName of fileNames) {

      (shouldRun(fileName) ? it : it.skip)(fileName, function(done) {
        this.timeout(5000);

        // given
        let fileContents = readFile(`${ __dirname }/${ fileName }`, 'utf8');

        // replace DMN 1.2 namespaces with DMN 1.3 namespaces
        fileContents = replaceNamespaces(fileContents, {
          'http://www.omg.org/spec/DMN/20180521/MODEL/': 'https://www.omg.org/spec/DMN/20191111/MODEL/',
          'http://www.omg.org/spec/DMN/20180521/DMNDI/': 'https://www.omg.org/spec/DMN/20191111/DMNDI/',
        });

        // when
        moddle.fromXML(fileContents, 'dmn:Definitions', function(err, result, context) {

          if (err) {
            return done(err);
          }

          try {
            expect(context.warnings).to.be.empty;
          } catch (err) {
            return done(err);
          }

          return toXML(result, { format: true }, function(err, xml) {

            // then
            validate(err, xml, done);
          });
        });
      });

    }

  });

});

/**
 * Replace namespaces in XML.
 *
 * @param {string} xml
 * @param {Object} namespaces
 *
 * @returns {string}
 */
function replaceNamespaces(xml, namespaces) {
  for (const namespace in namespaces) {
    const namespaceRegExp = new RegExp(namespace, 'g');

    xml = xml.replace(namespaceRegExp, namespaces[ namespace ]);
  }

  return xml;
}

function toXML(element, opts, done) {
  element.$model.toXML(element, opts, done);
}

function validate(err, xml, done) {

  if (err) {
    return done(err);
  }

  if (!xml) {
    return done(new Error('XML is not defined'));
  }

  SchemaValidator.validateXML(xml, DMN_XSD, function(err, result) {

    if (err) {
      return done(err);
    }

    expect(result.valid).to.be.true;
    done();
  });
}<commit_msg>test(tck): filter warning for broken diagram<commit_after>import { sync as exec } from 'execa';

import { sync as glob } from 'glob';

import {
  readFileSync as readFile,
  existsSync as exists
} from 'fs';

import path from 'path';

import DmnModdle from '../..';

import SchemaValidator from 'xsd-schema-validator';

import { expect } from 'chai';

const DMN_XSD = 'resources/dmn/xsd/DMN13.xsd';

const tckDirectory = 'tmp/tck';

describe('dmn-moddle - TCK roundtrip', function() {

  const moddle = new DmnModdle();

  this.timeout(30000);

  if (exists(path.join(__dirname, tckDirectory, '.git'))) {
    console.log('tck repository already cloned, fetching and checking out origin/master...');

    const cwd = path.join(__dirname, tckDirectory);

    exec('git', [ 'fetch' ], { cwd });
    exec('git', [ 'checkout', 'origin/master' ], { cwd });
  } else {
    console.log(`cloning tck repository to ${ tckDirectory }...`);

    exec(
      'git',
      [ 'clone', '--depth=1', 'git@github.com:dmn-tck/tck.git', tckDirectory ],
      { cwd: __dirname }
    );
  }

  const fileNames = glob(tckDirectory + '/TestCases/**/*.dmn', { cwd: __dirname });

  function shouldRun(fileName) {
    const match = process.env.GREP;

    return !match || fileName.toLowerCase().includes(match);
  }

  describe('should roundtrip', function() {

    for (const fileName of fileNames) {

      (shouldRun(fileName) ? it : it.skip)(fileName, function(done) {
        this.timeout(5000);

        // given
        let fileContents = readFile(`${ __dirname }/${ fileName }`, 'utf8');

        // replace DMN 1.2 namespaces with DMN 1.3 namespaces
        fileContents = replaceNamespaces(fileContents, {
          'http://www.omg.org/spec/DMN/20180521/MODEL/': 'https://www.omg.org/spec/DMN/20191111/MODEL/',
          'http://www.omg.org/spec/DMN/20180521/DMNDI/': 'https://www.omg.org/spec/DMN/20191111/DMNDI/',
        });

        // when
        moddle.fromXML(fileContents, 'dmn:Definitions', function(err, result, context) {

          if (err) {
            return done(err);
          }

          try {
            const warnings = filterWhitelisted(context.warnings, fileName);

            expect(warnings).to.be.empty;
          } catch (err) {
            return done(err);
          }

          return toXML(result, { format: true }, function(err, xml) {

            // then
            validate(err, xml, done);
          });
        });
      });

    }

  });

});

/**
 * Replace namespaces in XML.
 *
 * @param {string} xml
 * @param {Object} namespaces
 *
 * @returns {string}
 */
function replaceNamespaces(xml, namespaces) {
  for (const namespace in namespaces) {
    const namespaceRegExp = new RegExp(namespace, 'g');

    xml = xml.replace(namespaceRegExp, namespaces[ namespace ]);
  }

  return xml;
}

function toXML(element, opts, done) {
  element.$model.toXML(element, opts, done);
}

function validate(err, xml, done) {

  if (err) {
    return done(err);
  }

  if (!xml) {
    return done(new Error('XML is not defined'));
  }

  SchemaValidator.validateXML(xml, DMN_XSD, function(err, result) {

    if (err) {
      return done(err);
    }

    expect(result.valid).to.be.true;
    done();
  });
}

function filterWhitelisted(warnings, fileName) {

  if (fileName.endsWith('0086-import.dmn')) {
    return warnings.filter(err => err.message !== 'unresolved reference <include1:_32543811-b499-4608-b784-6c6f294b1c58>');
  }

  return warnings;
}<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');
var Client = require('../lib/owfs').Client;
var spawn = require('child_process').spawn;

function startTestServer(port, devices, callback) {
    if (Array.isArray(devices)) {
        devices = devices.join(',');
    }

    var server = spawn('owserver', [
        '--foreground',
        '--Celsius',
        '--port=127.0.0.1:'+port,
        '--error_print=2',
        '--error_level=2',
        '--tester='+devices
    ]);

    var timeout = setTimeout(function () {
        server.kill('SIGTERM');
        throw new Error('Timeout while starting owserver');
    }, 1000);

    server.stderr.on('data', function(data) {
        var str = data.toString();
        if (str.match(/Setting up tester Bus Master/)) {
            clearTimeout(timeout);
            if (callback) {
                callback();
            }
        }
    });

    server.on('error', function (err) {
        throw new Error('owserver error: '+err);
    });

    return server;
}

describe('Integration Test', function () {
    var server;
    var port = 43041;
    before(function (done) {
        server = startTestServer(port, 'DS18B20', done);
    });

    after(function () {
        server.kill('SIGTERM');
    });

    it('should read a temperature from a DS18B20 device', function (done) {
        var client = new Client('127.0.0.1', port);
        client.read('/28.000028D70000/temperature', function(err, result) {
            assert.equal(err, undefined);
            assert.equal(result, '4');
            done();
        });
    });

});
<commit_msg>Added printing of owserver log lines if there is an error<commit_after>'use strict';

var assert = require('assert');
var Client = require('../lib/owfs').Client;
var spawn = require('child_process').spawn;

function startTestServer(port, devices, callback) {
    if (Array.isArray(devices)) {
        devices = devices.join(',');
    }

    var server = spawn('owserver', [
        '--foreground',
        '--Celsius',
        '--port=127.0.0.1:'+port,
        '--error_print=2',
        '--error_level=2',
        '--tester='+devices
    ]);

    var logLines = '';
    var timeout = setTimeout(function () {
        server.kill('SIGTERM');
        throw new Error('Timeout while starting owserver: '+logLines);
    }, 1000);

    server.stderr.on('data', function(data) {
        var str = data.toString();
        logLines += str;
        if (str.match(/Setting up tester Bus Master/)) {
            clearTimeout(timeout);
            if (callback) {
                callback();
            }
        }
    });

    server.on('error', function (err) {
        console.log(logLines);
        throw new Error('owserver error: '+err);
    });

    return server;
}

describe('Integration Test', function () {
    var server;
    var port = 43041;
    before(function (done) {
        server = startTestServer(port, 'DS18B20', done);
    });

    after(function () {
        server.kill('SIGTERM');
    });

    it('should read a temperature from a DS18B20 device', function (done) {
        var client = new Client('127.0.0.1', port);
        client.read('/28.000028D70000/temperature', function(err, result) {
            assert.equal(err, undefined);
            assert.equal(result, '4');
            done();
        });
    });

});
<|endoftext|>


<commit_before>"use strict";

var http = require('http'),
    assert = require('assert'),
    ipResolver = require('../lib/rate-limiter/ipresolver');

var EXPECTED = "expected";
var ACTUAL = "actual";
var HOST = "localhost";
var PORT = "9876";

var CLIENT_IP = "12.34.56.78";
var LOCAL_HOST = "127.0.0.1";
var SOME_IP = "11.22.33.44";
var IP_LIST = CLIENT_IP + ", " + LOCAL_HOST;
var LONG_IP_LIST = SOME_IP + " ," + IP_LIST;

function createRequest(headers, expected, done) {
    headers[EXPECTED] = expected;
    var options = {
        hostname: HOST,
        path: '/',
        port: PORT,
        headers: headers
    };
    var req = http.request(options, function (response) {
        assert.equal(response.headers[ACTUAL], expected);
        done();
    });
    req.end();
}

describe("Client IP tests", function () {
    var headers;

    before(function () {
        http.createServer(function (req, res) {
            var ip = ipResolver.resolve(req);
            res.setHeader(ACTUAL, ip);
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end();
        }).listen(PORT);
    });

    beforeEach(function () {
        headers = {};
    });

    it("SMARTROUTER: if available, takes precedence", function (done) {
        headers[ipResolver.SMARTROUTER_HEADER] = CLIENT_IP;
        headers[ipResolver.PROXY_HEADER] = LOCAL_HOST;
        headers[ipResolver.REMOTE_ADDR] = LOCAL_HOST;
        createRequest(headers, CLIENT_IP, done);
    });

    it("SMARTROUTER: the last ip in the list is always correct", function (done) {
        headers[ipResolver.SMARTROUTER_HEADER] = IP_LIST;
        createRequest(headers, LOCAL_HOST, done);
    });

    it("PROXY_HEADER: if no SMARTROUTER header, PROXY_HEADER takes precedence", function (done) {
        headers[ipResolver.PROXY_HEADER] = CLIENT_IP;
        headers[ipResolver.REMOTE_ADDR] = LOCAL_HOST;
        createRequest(headers, CLIENT_IP, done);
    });

    it("PROXY_HEADER: the last public ip is the one we need", function (done) {
        headers[ipResolver.PROXY_HEADER] = LONG_IP_LIST;
        createRequest(headers, CLIENT_IP, done);
    });

    it("PROXY_HEADER: if there is no public ip return private", function (done) {
        headers[ipResolver.PROXY_HEADER] = LOCAL_HOST;
        createRequest(headers, LOCAL_HOST, done);
    });

    it("REMOTE_ADDR: no proxies involved, use what we get from server", function (done) {
        headers[ipResolver.REMOTE_ADDR] = LOCAL_HOST;
        createRequest(headers, LOCAL_HOST, done);
    });
});
<commit_msg>ipresolver test should close its test HTTP server<commit_after>"use strict";

var http = require('http'),
    assert = require('assert'),
    ipResolver = require('../lib/rate-limiter/ipresolver');

var EXPECTED = "expected";
var ACTUAL = "actual";
var HOST = "localhost";
var PORT = "9876";

var CLIENT_IP = "12.34.56.78";
var LOCAL_HOST = "127.0.0.1";
var SOME_IP = "11.22.33.44";
var IP_LIST = CLIENT_IP + ", " + LOCAL_HOST;
var LONG_IP_LIST = SOME_IP + " ," + IP_LIST;

function createRequest(headers, expected, done) {
    headers[EXPECTED] = expected;
    var options = {
        hostname: HOST,
        path: '/',
        port: PORT,
        headers: headers
    };
    var req = http.request(options, function (response) {
        assert.equal(response.headers[ACTUAL], expected);
        done();
    });
    req.end();
}

describe("Client IP tests", function () {
    var headers;
    var httpServer;

    before(function () {
        httpServer = http.createServer(function (req, res) {
            var ip = ipResolver.resolve(req);
            res.setHeader(ACTUAL, ip);
            res.setHeader("Connection", "close");
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end();
        }).listen(PORT);
    });

    after(function (done) {
        httpServer.close(function () {
            done();
        });
    });

    beforeEach(function () {
        headers = {};
    });

    it("SMARTROUTER: if available, takes precedence", function (done) {
        headers[ipResolver.SMARTROUTER_HEADER] = CLIENT_IP;
        headers[ipResolver.PROXY_HEADER] = LOCAL_HOST;
        headers[ipResolver.REMOTE_ADDR] = LOCAL_HOST;
        createRequest(headers, CLIENT_IP, done);
    });

    it("SMARTROUTER: the last ip in the list is always correct", function (done) {
        headers[ipResolver.SMARTROUTER_HEADER] = IP_LIST;
        createRequest(headers, LOCAL_HOST, done);
    });

    it("PROXY_HEADER: if no SMARTROUTER header, PROXY_HEADER takes precedence", function (done) {
        headers[ipResolver.PROXY_HEADER] = CLIENT_IP;
        headers[ipResolver.REMOTE_ADDR] = LOCAL_HOST;
        createRequest(headers, CLIENT_IP, done);
    });

    it("PROXY_HEADER: the last public ip is the one we need", function (done) {
        headers[ipResolver.PROXY_HEADER] = LONG_IP_LIST;
        createRequest(headers, CLIENT_IP, done);
    });

    it("PROXY_HEADER: if there is no public ip return private", function (done) {
        headers[ipResolver.PROXY_HEADER] = LOCAL_HOST;
        createRequest(headers, LOCAL_HOST, done);
    });

    it("REMOTE_ADDR: no proxies involved, use what we get from server", function (done) {
        headers[ipResolver.REMOTE_ADDR] = LOCAL_HOST;
        createRequest(headers, LOCAL_HOST, done);
    });
});
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.

/**
 * @fileoverview ChromeOS Chinese Input Method in JavaScript Extension
 * @author hungte@google.com (Hung-Te Lin)
 */

/**
 * The root namespace.
 */

var croscin = {};

/**
 * Chinese IME class.
 * @constructor
 */
croscin.IME = function() {
  var self = this;

  // TODO(hungte) load default debug flag from options
  self.debug = true;

  self.kMenuOptions = "options";
  self.kMenuOptionsLabel = chrome.i18n.getMessage("menuOptions");

  self.imctx = {};
  self.im = null;
  self.im_name = '';
  self.im_label = '';

  self.engineID = null;
  self.context = null;

  // Standard utilities
  self.GetContextArg = function() {
    return {'contextID': this.context.contextID};
  }

  self.GetEngineArg = function() {
    return {'engineID': jscin.ENGINE_ID};
  }

  self.log = function(s) {
    if (self.debug)
      jscin.log(s);
  }

  // Core functions
  self.Commit = function(text) {
    // TODO(hungte) fixme when gen_inp has fixed this.
    if (typeof(text) != typeof('')) {
      text = text[0];
      self.log("croscin.Commit: WARNING: input text is not a simple string.");
    }

    if (text) {
      var arg = self.GetContextArg();
      arg.text = text;
      self.ime_api.commitText(arg);
      self.log("croscin.Commit: value: " + text);
    } else {
      self.log("croscin.Commmit: warning: called with empty string.");
    }
  }

  self.ProcessKeyEvent = function(keyData) {
    self.log("ProcessKeyEvent: " + keyData.key);

    // Currently all of the modules uses key down.
    if (keyData.type != 'keydown') {
      return false;
    }

    var ret = self.im.onKeystroke(self.imctx, keyData);
    self.log(dump_inpinfo(self.imctx));

    switch (ret) {
      case jscin.IMKEY_COMMIT:
        self.log("im.onKeystroke: return IMKEY_COMMIT");
        self.Commit(self.imctx.cch);
        self.UpdateUI();
        return true;

      case jscin.IMKEY_ABSORB:
        self.log("im.onKeystroke: return IMKEY_ABSORB");
        self.UpdateUI();
        return true;

      case jscin.IMKEY_IGNORE:
        self.log("im.onKeystroke: return IMKEY_IGNORE");
        self.UpdateUI();
        return false;
    }

    // default: Unknown return value.
    self.log("croscin.ProcessKeyEvent: Unknown return value: " + ret);
    return false;
  }

  self.SimulateKeyDown = function(key) {
    var keyEvent = {
      'type': 'keydown',
      'key': key,
      'altKey': false,
      'ctrlKey': false,
      'shiftKey': false,
    };
    return self.ProcessKeyEvent(keyEvent);
  }

  self.SetCandidatesWindowProperty = function(name, value) {
    self.log("croscin.SetCandidatesWindowProperty: set " + name + ": " + value);
    var prop = {};
    var arg = self.GetEngineArg();
    arg['properties'] = prop;
    prop[name] = value;
    self.ime_api.setCandidateWindowProperties(arg);
  }

  self.InitializeUI = function() {
    // Vertical candidates window looks better on ChromeOS.
    self.SetCandidatesWindowProperty('vertical', true);
    // CIN tables don't expect cursor in candidates window.
    self.SetCandidatesWindowProperty('cursorVisible', false);
    self.SetCandidatesWindowProperty('visible', false);

    // Setup menu
    self.InitializeMenu();
  }

  self.UpdateComposition = function(text) {
    var arg = self.GetContextArg();
    self.log("croscin.UpdateComposition: " + text);
    if (text) {
      arg.text = text;
      // Select everything in composition.
      arg.selectionStart = 0;
      arg.selectionEnd = text.length;
      arg.cursor = text.length;
      self.ime_api.setComposition(arg);
    } else {
      self.ime_api.clearComposition(arg);
    }
  }

  self.UpdateCandidates = function(candidate_list, labels) {
    self.log("croscin.UpdateCandidates: elements = " + candidate_list.length +
             ", labels = " + labels);
    if (candidate_list.length > 0) {
      var arg = self.GetContextArg();
      var candidates = [];
      for (var i = 0; i < candidate_list.length; i++) {
        // TODO(hungte) fix label, annotation
        candidates.push({
          'candidate': candidate_list[i],
          'id': i,
          'label': labels.charAt(i),
        });
      }
      self.log('candidates:');
      self.log(candidates);
      arg.candidates = candidates;
      self.ime_api.setCandidates(arg);
      self.SetCandidatesWindowProperty('pageSize', candidate_list.length);
      self.SetCandidatesWindowProperty('auxiliaryTextVisible', true);
      self.SetCandidatesWindowProperty('visible', true);
    } else {
      self.SetCandidatesWindowProperty('auxiliaryTextVisible', false);
      self.SetCandidatesWindowProperty('visible', false);
    }
  }

  self.UpdateUI = function() {
    var imctx = self.imctx;
    // process:
    //  - keystroke
    self.UpdateComposition(imctx.keystroke);
    //  - selkey, mcch
    self.UpdateCandidates(imctx.mcch, imctx.selkey);
    //  - (TODO) lcch, cch_publish
  }

  self.ActivateInputMethod = function(name) {

    if (name && name == self.im_name) {
      self.log("croscin.ActivateInputMethod: already activated: " + name);
      return;
    }
    if (!name) {
      name = jscin.readLocalStorage(
          jscin.kDefaultCinTableKey, jscin.default_input_method);
    }

    if (name in jscin.input_methods) {
      self.log("croscin.ActivateInputMethod: Started: " + name);
      self.imctx = {};
      self.im = jscin.create_input_method(name, self.imctx);
      self.im_name = name;
      self.im_label = jscin.get_input_method_label(name);
      self.InitializeUI();
      jscin.writeLocalStorage(jscin.kDefaultCinTableKey, name);
      jscin.default_input_method = name;
      self.SetCandidatesWindowProperty('auxiliaryText', self.im_label);
    } else {
      self.log("croscin.ActivateInputMethod: Invalid item: " + name);
    }
  }

  self.InitializeMenu = function() {
    var menu_items = [];

    for (var i in jscin.input_methods) {
      var label = jscin.get_input_method_label(i);
      if (label)
        label = label + " (" + i + ")";
      else
        label = i;
      menu_items.push({
        "id": "ime:" + i,
        "label": label,
        "style": "radio",
        "checked": i == self.im_name,
      });
    }
    self.log("croscin.InitializeMenu: " + menu_items.length + " items.");
    // Separator is broken on R28, and may not appear after R29.
    // It depends on ChromeOS UI design so let's not use it.
    // menu_items.push({"id": "", "style": "separator"});
    menu_items.push({"id": self.kMenuOptions, "label": self.kMenuOptionsLabel});

    var arg = self.GetEngineArg();
    arg['items'] = menu_items;
    self.ime_api.setMenuItems(arg);

    // TODO(hungte) ime_api.updateMenuItems is broken so we can't really
    // "update" it - just always do setMenuItems.
    // self.UpdateMenu();
  }

  self.LoadExtensionResource = function(url) {
    var rsrc = chrome.extension.getURL(url);
    var xhr = new XMLHttpRequest();
    self.log("croscin.LoadExtensionResource: " + url);
    xhr.open("GET", rsrc, false);
    xhr.send();
    if (xhr.readyState != 4 || xhr.status != 200) {
      self.log("croscin.LoadExtensionResource: failed to fetch: " + url);
      return null;
    }
    return xhr.responseText;
  }

  self.LoadBuiltinTables = function(reload) {
    var list = self.LoadExtensionResource("tables/builtin.json");
    if (!list) {
      self.log("croscin.LoadBuiltinTables: No built-in tables.");
      return;
    }
    var table_metadata = jscin.getTableMetadatas();
    list = JSON.parse(list);
    for (var table_name in list) {
      if (table_name in table_metadata && !reload) {
        self.log("croscin.LoadBuiltinTables: skip loaded table: " + table_name);
        continue;
      }
      var content = self.LoadExtensionResource("tables/" + list[table_name]);
      if (!content) {
        self.log("croscin.LoadBuiltinTables: Failed to load: " + table_name);
        continue;
      }
      var results = parseCin(content);
      if (!results[0]) {
        self.log("croscin.LoadBuiltinTables: Incorrect table: " + table_name);
        continue;
      }
      var table_content = results[1].data;
      var metadata = results[1].metadata;
      self.log("croscin.LoadBuiltinTables: Load table: " + table_name);
      var ename = metadata['ename'];
      metadata['builtin'] = true;
      jscin.addTable(ename, metadata, table_content);
    }
  }

  var version = chrome.runtime.getManifest().version;
  var reload = (version !== jscin.readLocalStorage(jscin.kVersionKey, 0));
  self.LoadBuiltinTables(reload);
  if (reload) {
    jscin.reloadNonBuiltinTables();
    jscin.writeLocalStorage(jscin.kVersionKey, version);
  }
  jscin.reload_configuration();
  self.resolve_ime_api();
  if (navigator.appVersion.match(/Mac OS/)) {
    self.hook_dumb_ime();
    jscin.ime_api = self.ime_api;  // FIXME(kcwu): dirty hack
  }
  self.registerEventHandlers();
  // Start the default input method.
  self.ActivateInputMethod(null);
};

croscin.IME.prototype.resolve_ime_api = function() {
  /* find out proper ime_api: chrome.input.ime or chrome.experimental.input */
  var ime_api = null;
  if ("input" in chrome && "ime" in chrome.input)
    ime_api = chrome.input.ime;
  else
    ime_api = chrome.experimental.input;
  if ("ime" in ime_api)
    ime_api = ime_api.ime;

  this.ime_api = ime_api;
}

croscin.IME.prototype.hook_dumb_ime = function() {
  var self = this;
  var hook_listener = [
      'onActivate', 'onDeactivated', 'onFocus', 'onBlur', 'onKeyEvent',
      'onInputContextUpdate', 'onCandidateClicked', 'onMenuItemActivated',
      ];
  jscin.dumb_ime = { 'listener': {} };
  ime_api = self.ime_api;

  for (var i in hook_listener) {
    var name = hook_listener[i];
    jscin.dumb_ime.listener[name] = [];
    ime_api[name].addListener = (function (name) {
      return function (arg) {
        jscin.dumb_ime.listener[name].push(arg);
      };
    })(name);
  }
}

/**
 * Registers event handlers to the browser.
 */
croscin.IME.prototype.registerEventHandlers = function() {
  var self = this;
  ime_api = self.ime_api;

  ime_api.onActivate.addListener(function(engineID) {
    self.engineID = engineID;
    self.InitializeUI();
  });

  ime_api.onDeactivated.addListener(function(engineID) {
    self.context = null;
  });

  ime_api.onFocus.addListener(function(context) {
    self.context = context;
    // Calling updateUI here to forward unfinished composition (preedit) into
    // the new input element.
    self.UpdateUI();
  });

  ime_api.onBlur.addListener(function(contextID) {
    if (!self.context) {
      self.log("croscin.onBlur: WARNING: no existing context.");
      return;
    }
    if (self.context.contextID != contextID) {
      self.log("croscin.onBlur: WARNING: incompatible context.");
      return;
    }
    // TODO(hungte) Uncomment this if we don't want context to be carried when
    // input focus changes.
    // self.SimulateKeyDown('Esc');
    self.context = null;
  });

  ime_api.onKeyEvent.addListener(function(engine, keyData) {
    return self.ProcessKeyEvent(keyData);
  });

  ime_api.onInputContextUpdate.addListener(function(context) {
  });

  ime_api.onCandidateClicked.addListener(
      function(engineID, candidateID, button) {
        self.log("onCandidateClicked: " + candidateID + ", " + button);
        if (button == "left") {
          self.SimulateKeyDown(self.imctx.selkey.charAt(candidateID));
        }
  });

  ime_api.onMenuItemActivated.addListener(function(engineID, name) {
    self.log("croscin.onMenuItemActivated: name=" + name);

    if (name == self.kMenuOptions) {
      var options_url = chrome.extension.getURL("options/options.html");
      chrome.tabs.create({"url": options_url});
    } else if (name.match(/^ime:/)) {
      self.ActivateInputMethod(name.replace(/^ime:/, ''));
    }
  });

  window.on_debug_mode_change = function(debug) {
    self.debug = debug;
  }

  window.on_config_changed = function() {
    // Some configuration is changed - we need to validate and refresh all.
    self.log("croscin.on_config_changed: notified.");
    jscin.reload_configuration();
    self.InitializeUI();
  }

  window.jscin = jscin;
};

// Browser loader entry
document.addEventListener(
    'readystatechange',
    function() {
      if (document.readyState === 'complete') {
        foobar = new croscin.IME;
      }
    }
)
<commit_msg>Fix missing option dialog when there are no other active Chrome windows.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.

/**
 * @fileoverview ChromeOS Chinese Input Method in JavaScript Extension
 * @author hungte@google.com (Hung-Te Lin)
 */

/**
 * The root namespace.
 */

var croscin = {};

/**
 * Chinese IME class.
 * @constructor
 */
croscin.IME = function() {
  var self = this;

  // TODO(hungte) load default debug flag from options
  self.debug = true;

  self.kMenuOptions = "options";
  self.kMenuOptionsLabel = chrome.i18n.getMessage("menuOptions");

  self.imctx = {};
  self.im = null;
  self.im_name = '';
  self.im_label = '';

  self.engineID = null;
  self.context = null;

  // Standard utilities
  self.GetContextArg = function() {
    return {'contextID': this.context.contextID};
  }

  self.GetEngineArg = function() {
    return {'engineID': jscin.ENGINE_ID};
  }

  self.log = function(s) {
    if (self.debug)
      jscin.log(s);
  }

  // Core functions
  self.Commit = function(text) {
    // TODO(hungte) fixme when gen_inp has fixed this.
    if (typeof(text) != typeof('')) {
      text = text[0];
      self.log("croscin.Commit: WARNING: input text is not a simple string.");
    }

    if (text) {
      var arg = self.GetContextArg();
      arg.text = text;
      self.ime_api.commitText(arg);
      self.log("croscin.Commit: value: " + text);
    } else {
      self.log("croscin.Commmit: warning: called with empty string.");
    }
  }

  self.ProcessKeyEvent = function(keyData) {
    self.log("ProcessKeyEvent: " + keyData.key);

    // Currently all of the modules uses key down.
    if (keyData.type != 'keydown') {
      return false;
    }

    var ret = self.im.onKeystroke(self.imctx, keyData);
    self.log(dump_inpinfo(self.imctx));

    switch (ret) {
      case jscin.IMKEY_COMMIT:
        self.log("im.onKeystroke: return IMKEY_COMMIT");
        self.Commit(self.imctx.cch);
        self.UpdateUI();
        return true;

      case jscin.IMKEY_ABSORB:
        self.log("im.onKeystroke: return IMKEY_ABSORB");
        self.UpdateUI();
        return true;

      case jscin.IMKEY_IGNORE:
        self.log("im.onKeystroke: return IMKEY_IGNORE");
        self.UpdateUI();
        return false;
    }

    // default: Unknown return value.
    self.log("croscin.ProcessKeyEvent: Unknown return value: " + ret);
    return false;
  }

  self.SimulateKeyDown = function(key) {
    var keyEvent = {
      'type': 'keydown',
      'key': key,
      'altKey': false,
      'ctrlKey': false,
      'shiftKey': false,
    };
    return self.ProcessKeyEvent(keyEvent);
  }

  self.SetCandidatesWindowProperty = function(name, value) {
    self.log("croscin.SetCandidatesWindowProperty: set " + name + ": " + value);
    var prop = {};
    var arg = self.GetEngineArg();
    arg['properties'] = prop;
    prop[name] = value;
    self.ime_api.setCandidateWindowProperties(arg);
  }

  self.InitializeUI = function() {
    // Vertical candidates window looks better on ChromeOS.
    self.SetCandidatesWindowProperty('vertical', true);
    // CIN tables don't expect cursor in candidates window.
    self.SetCandidatesWindowProperty('cursorVisible', false);
    self.SetCandidatesWindowProperty('visible', false);

    // Setup menu
    self.InitializeMenu();
  }

  self.UpdateComposition = function(text) {
    var arg = self.GetContextArg();
    self.log("croscin.UpdateComposition: " + text);
    if (text) {
      arg.text = text;
      // Select everything in composition.
      arg.selectionStart = 0;
      arg.selectionEnd = text.length;
      arg.cursor = text.length;
      self.ime_api.setComposition(arg);
    } else {
      self.ime_api.clearComposition(arg);
    }
  }

  self.UpdateCandidates = function(candidate_list, labels) {
    self.log("croscin.UpdateCandidates: elements = " + candidate_list.length +
             ", labels = " + labels);
    if (candidate_list.length > 0) {
      var arg = self.GetContextArg();
      var candidates = [];
      for (var i = 0; i < candidate_list.length; i++) {
        // TODO(hungte) fix label, annotation
        candidates.push({
          'candidate': candidate_list[i],
          'id': i,
          'label': labels.charAt(i),
        });
      }
      self.log('candidates:');
      self.log(candidates);
      arg.candidates = candidates;
      self.ime_api.setCandidates(arg);
      self.SetCandidatesWindowProperty('pageSize', candidate_list.length);
      self.SetCandidatesWindowProperty('auxiliaryTextVisible', true);
      self.SetCandidatesWindowProperty('visible', true);
    } else {
      self.SetCandidatesWindowProperty('auxiliaryTextVisible', false);
      self.SetCandidatesWindowProperty('visible', false);
    }
  }

  self.UpdateUI = function() {
    var imctx = self.imctx;
    // process:
    //  - keystroke
    self.UpdateComposition(imctx.keystroke);
    //  - selkey, mcch
    self.UpdateCandidates(imctx.mcch, imctx.selkey);
    //  - (TODO) lcch, cch_publish
  }

  self.ActivateInputMethod = function(name) {

    if (name && name == self.im_name) {
      self.log("croscin.ActivateInputMethod: already activated: " + name);
      return;
    }
    if (!name) {
      name = jscin.readLocalStorage(
          jscin.kDefaultCinTableKey, jscin.default_input_method);
    }

    if (name in jscin.input_methods) {
      self.log("croscin.ActivateInputMethod: Started: " + name);
      self.imctx = {};
      self.im = jscin.create_input_method(name, self.imctx);
      self.im_name = name;
      self.im_label = jscin.get_input_method_label(name);
      self.InitializeUI();
      jscin.writeLocalStorage(jscin.kDefaultCinTableKey, name);
      jscin.default_input_method = name;
      self.SetCandidatesWindowProperty('auxiliaryText', self.im_label);
    } else {
      self.log("croscin.ActivateInputMethod: Invalid item: " + name);
    }
  }

  self.InitializeMenu = function() {
    var menu_items = [];

    for (var i in jscin.input_methods) {
      var label = jscin.get_input_method_label(i);
      if (label)
        label = label + " (" + i + ")";
      else
        label = i;
      menu_items.push({
        "id": "ime:" + i,
        "label": label,
        "style": "radio",
        "checked": i == self.im_name,
      });
    }
    self.log("croscin.InitializeMenu: " + menu_items.length + " items.");
    // Separator is broken on R28, and may not appear after R29.
    // It depends on ChromeOS UI design so let's not use it.
    // menu_items.push({"id": "", "style": "separator"});
    menu_items.push({"id": self.kMenuOptions, "label": self.kMenuOptionsLabel});

    var arg = self.GetEngineArg();
    arg['items'] = menu_items;
    self.ime_api.setMenuItems(arg);

    // TODO(hungte) ime_api.updateMenuItems is broken so we can't really
    // "update" it - just always do setMenuItems.
    // self.UpdateMenu();
  }

  self.LoadExtensionResource = function(url) {
    var rsrc = chrome.extension.getURL(url);
    var xhr = new XMLHttpRequest();
    self.log("croscin.LoadExtensionResource: " + url);
    xhr.open("GET", rsrc, false);
    xhr.send();
    if (xhr.readyState != 4 || xhr.status != 200) {
      self.log("croscin.LoadExtensionResource: failed to fetch: " + url);
      return null;
    }
    return xhr.responseText;
  }

  self.LoadBuiltinTables = function(reload) {
    var list = self.LoadExtensionResource("tables/builtin.json");
    if (!list) {
      self.log("croscin.LoadBuiltinTables: No built-in tables.");
      return;
    }
    var table_metadata = jscin.getTableMetadatas();
    list = JSON.parse(list);
    for (var table_name in list) {
      if (table_name in table_metadata && !reload) {
        self.log("croscin.LoadBuiltinTables: skip loaded table: " + table_name);
        continue;
      }
      var content = self.LoadExtensionResource("tables/" + list[table_name]);
      if (!content) {
        self.log("croscin.LoadBuiltinTables: Failed to load: " + table_name);
        continue;
      }
      var results = parseCin(content);
      if (!results[0]) {
        self.log("croscin.LoadBuiltinTables: Incorrect table: " + table_name);
        continue;
      }
      var table_content = results[1].data;
      var metadata = results[1].metadata;
      self.log("croscin.LoadBuiltinTables: Load table: " + table_name);
      var ename = metadata['ename'];
      metadata['builtin'] = true;
      jscin.addTable(ename, metadata, table_content);
    }
  }

  var version = chrome.runtime.getManifest().version;
  var reload = (version !== jscin.readLocalStorage(jscin.kVersionKey, 0));
  self.LoadBuiltinTables(reload);
  if (reload) {
    jscin.reloadNonBuiltinTables();
    jscin.writeLocalStorage(jscin.kVersionKey, version);
  }
  jscin.reload_configuration();
  self.resolve_ime_api();
  if (navigator.appVersion.match(/Mac OS/)) {
    self.hook_dumb_ime();
    jscin.ime_api = self.ime_api;  // FIXME(kcwu): dirty hack
  }
  self.registerEventHandlers();
  // Start the default input method.
  self.ActivateInputMethod(null);
};

croscin.IME.prototype.resolve_ime_api = function() {
  /* find out proper ime_api: chrome.input.ime or chrome.experimental.input */
  var ime_api = null;
  if ("input" in chrome && "ime" in chrome.input)
    ime_api = chrome.input.ime;
  else
    ime_api = chrome.experimental.input;
  if ("ime" in ime_api)
    ime_api = ime_api.ime;

  this.ime_api = ime_api;
}

croscin.IME.prototype.hook_dumb_ime = function() {
  var self = this;
  var hook_listener = [
      'onActivate', 'onDeactivated', 'onFocus', 'onBlur', 'onKeyEvent',
      'onInputContextUpdate', 'onCandidateClicked', 'onMenuItemActivated',
      ];
  jscin.dumb_ime = { 'listener': {} };
  ime_api = self.ime_api;

  for (var i in hook_listener) {
    var name = hook_listener[i];
    jscin.dumb_ime.listener[name] = [];
    ime_api[name].addListener = (function (name) {
      return function (arg) {
        jscin.dumb_ime.listener[name].push(arg);
      };
    })(name);
  }
}

/**
 * Registers event handlers to the browser.
 */
croscin.IME.prototype.registerEventHandlers = function() {
  var self = this;
  ime_api = self.ime_api;

  ime_api.onActivate.addListener(function(engineID) {
    self.engineID = engineID;
    self.InitializeUI();
  });

  ime_api.onDeactivated.addListener(function(engineID) {
    self.context = null;
  });

  ime_api.onFocus.addListener(function(context) {
    self.context = context;
    // Calling updateUI here to forward unfinished composition (preedit) into
    // the new input element.
    self.UpdateUI();
  });

  ime_api.onBlur.addListener(function(contextID) {
    if (!self.context) {
      self.log("croscin.onBlur: WARNING: no existing context.");
      return;
    }
    if (self.context.contextID != contextID) {
      self.log("croscin.onBlur: WARNING: incompatible context.");
      return;
    }
    // TODO(hungte) Uncomment this if we don't want context to be carried when
    // input focus changes.
    // self.SimulateKeyDown('Esc');
    self.context = null;
  });

  ime_api.onKeyEvent.addListener(function(engine, keyData) {
    return self.ProcessKeyEvent(keyData);
  });

  ime_api.onInputContextUpdate.addListener(function(context) {
  });

  ime_api.onCandidateClicked.addListener(
      function(engineID, candidateID, button) {
        self.log("onCandidateClicked: " + candidateID + ", " + button);
        if (button == "left") {
          self.SimulateKeyDown(self.imctx.selkey.charAt(candidateID));
        }
  });

  ime_api.onMenuItemActivated.addListener(function(engineID, name) {
    self.log("croscin.onMenuItemActivated: name=" + name);

    if (name == self.kMenuOptions) {
      var options_url = chrome.extension.getURL("options/options.html");
      // Tabs are better, but if there are no active windows (which is common in
      // ChromeOS if you put everything behind) then chrome.tabs.create would
      // fail.
      chrome.windows.create({"url": options_url, type:"popup"});
    } else if (name.match(/^ime:/)) {
      self.ActivateInputMethod(name.replace(/^ime:/, ''));
    }
  });

  window.on_debug_mode_change = function(debug) {
    self.debug = debug;
  }

  window.on_config_changed = function() {
    // Some configuration is changed - we need to validate and refresh all.
    self.log("croscin.on_config_changed: notified.");
    jscin.reload_configuration();
    self.InitializeUI();
  }

  window.jscin = jscin;
};

// Browser loader entry
document.addEventListener(
    'readystatechange',
    function() {
      if (document.readyState === 'complete') {
        foobar = new croscin.IME;
      }
    }
)
<|endoftext|>


<commit_before>/* eslint-env mocha */
'use strict'

const assert = require('assert')
const WS2Manager = require('../../lib/ws2_manager')
const WSv2 = require('../../lib/transports/ws2')

describe('WS2Manager', () => {
  describe('getDataChannelCount', () => {
    it('takes pending subs & unsubs into account', () => {
      const s = {
        ws: new WSv2(),
        pendingSubscriptions: [['book', {}]],
        pendingUnsubscriptions: []
      }

      s.ws._channelMap = {
        0: { channel: 'trades' },
        1: { channel: 'candles', key: 'test' },
        2: { channel: 'auth' }
      }

      const count = WS2Manager.getDataChannelCount(s)

      assert.strictEqual(s.ws.getDataChannelCount(), 2)
      assert.strictEqual(count, 3)
    })
  })

  describe('auth', () => {
    it('does nothing if api key/secret are already provided', () => {
      const m = new WS2Manager({ apiKey: 'x', apiSecret: 'x' })

      m.auth({ apiKey: '42', apiSecret: '43' })
      assert.strictEqual(m._socketArgs.apiKey, 'x')
      assert.strictEqual(m._socketArgs.apiSecret, 'x')
    })

    it('saves auth args', () => {
      const m = new WS2Manager()

      m.auth({ calc: 1, dms: 4 })
      assert.strictEqual(m._authArgs.calc, 1)
      assert.strictEqual(m._authArgs.dms, 4)
    })

    it('calls auth on existing unauthenticated sockets', (done) => {
      let cred = false
      const m = new WS2Manager()

      m._sockets = [{
        ws: {
          isAuthenticated: () => false,
          setAuthCredentials: (key, secret) => { cred = `${key}:${secret}` },
          auth: ({ calc, dms }) => {
            assert.strictEqual(calc, 1)
            assert.strictEqual(dms, 4)
            assert.strictEqual(cred, '41:42')
            done()
          }
        }
      }]

      m.auth({ apiKey: '41', apiSecret: '42', calc: 1, dms: 4 })
    })
  })

  describe('openSocket', () => {
    it('binds listeners to forward events', () => {
      const heardEvents = {}
      const events = [
        'open', 'message', 'auth', 'error', 'close', 'subscribed',
        'unsubscribed'
      ]

      const m = new WS2Manager()
      const s = m.openSocket()
      const { ws } = s

      events.forEach(e => {
        m.on(e, () => { heardEvents[e] = true })
      })

      events.forEach(e => ws.emit(e))
      events.forEach(e => {
        assert(heardEvents[e])
      })
    })

    it('saves socket state', () => {
      const m = new WS2Manager()
      const s = m.openSocket()
      assert.deepStrictEqual(m._sockets[0], s)
    })

    it('binds \'unsubscribed\' listener to remove channel from pending unsubs', () => {
      const m = new WS2Manager()
      const s = m.openSocket()

      s.pendingUnsubscriptions.push(`${42}`)
      s.ws.emit('unsubscribed', { chanId: 42 })

      assert.strictEqual(s.pendingUnsubscriptions.length, 0)
    })

    it('binds \'subscribed\' listener to remove channel from pending subs', () => {
      const m = new WS2Manager()
      const s = m.openSocket()

      s.pendingSubscriptions.push(['book', { symbol: 'tBTCUSD', prec: 'R0' }])
      s.ws.emit('subscribed', {
        channel: 'book',
        symbol: 'tBTCUSD',
        prec: 'R0',
        len: '25'
      })

      assert.strictEqual(s.pendingSubscriptions.length, 0)
    })
  })

  describe('getFreeDataSocket', () => {
    it('returns the first socket below the data channel limit', () => {
      const m = new WS2Manager()

      m._sockets[0] = {
        ws: { getDataChannelCount: () => 200 },
        pendingSubscriptions: new Array(70),
        pendingUnsubscriptions: new Array(10)
      }

      m._sockets[1] = {
        ws: { getDataChannelCount: () => 5 },
        pendingSubscriptions: [],
        pendingUnsubscriptions: []
      }

      const s = m.getFreeDataSocket()
      assert.deepStrictEqual(s, m._sockets[1])
    })
  })

  describe('getSocketWithDataChannel', () => {
    it('returns socket subscribed to specified channel/filter pair', () => {
      const m = new WS2Manager()
      m._sockets[0] = {
        ws: {},
        pendingSubscriptions: [['candles', { key: 'test' }]],
        pendingUnsubscriptions: []
      }

      let s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert.deepStrictEqual(s, m._sockets[0])

      /// /
      m._sockets[0] = {
        ws: { getDataChannelId: () => false },
        pendingSubscriptions: [['auth', {}]],
        pendingUnsubscriptions: []
      }

      s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert(!s)

      /// /
      m._sockets[0] = {
        ws: {
          getDataChannelId: (type, filter) => {
            assert.strictEqual(type, 'candles')
            assert.deepStrictEqual(filter, { key: 'test' })
            return 1
          }
        },
        pendingSubscriptions: [],
        pendingUnsubscriptions: []
      }

      s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert.deepStrictEqual(s, m._sockets[0])

      /// /
      m._sockets[0] = {
        ws: {
          getDataChannelId: (type, filter) => {
            assert.strictEqual(type, 'candles')
            assert.deepStrictEqual(filter, { key: 'test' })
            return 1
          }
        },
        pendingSubscriptions: [],
        pendingUnsubscriptions: [1]
      }

      s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert(!s)
    })
  })

  describe('getSocketWithChannel', () => {
    it('returns correct socket', () => {
      const m = new WS2Manager()
      m._sockets[0] = {
        pendingUnsubscriptions: [],
        ws: {
          hasChannel: (id) => {
            return id === 42
          }
        }
      }

      let s = m.getSocketWithChannel(42)
      assert.deepStrictEqual(s, m._sockets[0])

      /// /
      m._sockets[0] = {
        pendingUnsubscriptions: [42],
        ws: {
          hasChannel: (id) => {
            return id === 42
          }
        }
      }

      s = m.getSocketWithChannel(42)
      assert(!s)
    })
  })

  describe('subscribe', () => {
    it('delays sub for unopened sockets', () => {
      const m = new WS2Manager()
      let onceOpenCalled = false

      m._sockets[0] = {
        pendingSubscriptions: [],
        pendingUnsubscriptions: [],
        ws: {
          getDataChannelCount: () => 0,
          managedSubscribe: () => assert(false),
          isOpen: () => false,
          once: (eName) => {
            assert.strictEqual(eName, 'open')
            onceOpenCalled = true
          }
        }
      }

      m.subscribe('candles', 'test', { key: 'test' })
      assert(onceOpenCalled)
    })

    it('saves pending sub', () => {
      const m = new WS2Manager()
      m._sockets[0] = {
        pendingSubscriptions: [],
        pendingUnsubscriptions: [],
        ws: {
          getDataChannelCount: () => 0,
          managedSubscribe: () => {},
          isOpen: () => true
        }
      }

      m.subscribe('candles', 'test', { key: 'test' })
      assert.deepStrictEqual(m._sockets[0].pendingSubscriptions, [
        ['candles', { key: 'test' }]
      ])
    })

    it('opens a new socket if no sockets are available', () => {
      const m = new WS2Manager()
      let openCalled = false

      m.openSocket = () => {
        openCalled = true

        return {
          pendingSubscriptions: [],
          ws: {
            once: () => {},
            isOpen: () => false // to avoid managed sub
          }
        }
      }

      m.subscribe('candles', 'test', { key: 'test' })
      assert(openCalled)
    })

    it('opens a new socket if no sockets are below data limit', () => {
      const m = new WS2Manager()
      let openCalled = false

      m._sockets[0] = {
        pendingSubscriptions: [],
        pendingUnsubscriptions: [],
        ws: {
          getDataChannelCount: () => 255
        }
      }

      m.openSocket = () => {
        openCalled = true

        const state = {
          pendingSubscriptions: [],
          ws: {
            once: () => {},
            isOpen: () => false // to avoid managed sub
          }
        }

        m._sockets.push(state)
        return state
      }

      m.subscribe('candles', 'test', { key: 'test' })

      assert(openCalled)
      assert.strictEqual(m._sockets.length, 2)
    })
  })

  describe('unsubscribe', () => {
    it('saves pending unsub & calls unsub on socket', () => {
      const m = new WS2Manager()
      let unsubCalled = false

      m._sockets[0] = {
        pendingUnsubscriptions: [],
        ws: {
          unsubscribe: (cid) => {
            assert.strictEqual(cid, 42)
            unsubCalled = true
          },

          hasChannel: (cid) => {
            return cid === 42
          }
        }
      }

      m.unsubscribe(42)
      assert.deepStrictEqual(m._sockets[0].pendingUnsubscriptions, [42])
      assert(unsubCalled)
    })
  })

  describe('withAllSockets', () => {
    it('calls the provided cb with all internal sockets', () => {
      const m = new WS2Manager()
      const socketsSeen = {}

      m._sockets = ['a', 'b', 'c']
      m.withAllSockets((sock) => {
        socketsSeen[sock] = true
      })

      assert(socketsSeen.a)
      assert(socketsSeen.b)
      assert(socketsSeen.c)
    })
  })
})
<commit_msg>(fix) WS2Manager test<commit_after>/* eslint-env mocha */
'use strict'

const assert = require('assert')
const WS2Manager = require('../../lib/ws2_manager')
const WSv2 = require('../../lib/transports/ws2')

describe('WS2Manager', () => {
  describe('getDataChannelCount', () => {
    it('takes pending subs & unsubs into account', () => {
      const s = {
        ws: new WSv2(),
        pendingSubscriptions: [['book', {}]],
        pendingUnsubscriptions: []
      }

      s.ws._channelMap = {
        0: { channel: 'trades' },
        1: { channel: 'candles', key: 'test' },
        2: { channel: 'auth' }
      }

      const count = WS2Manager.getDataChannelCount(s)

      assert.strictEqual(s.ws.getDataChannelCount(), 2)
      assert.strictEqual(count, 3)
    })
  })

  describe('auth', () => {
    it('does nothing if api key/secret are already provided', () => {
      const m = new WS2Manager({ apiKey: 'x', apiSecret: 'x' })

      m.auth({ apiKey: '42', apiSecret: '43' })
      assert.strictEqual(m._socketArgs.apiKey, 'x')
      assert.strictEqual(m._socketArgs.apiSecret, 'x')
    })

    it('saves auth args', () => {
      const m = new WS2Manager()

      m.auth({ calc: 1, dms: 4 })
      assert.strictEqual(m._authArgs.calc, 1)
      assert.strictEqual(m._authArgs.dms, 4)
    })

    it('calls auth on existing unauthenticated sockets', (done) => {
      let cred = false
      const m = new WS2Manager()

      m._sockets = [{
        ws: {
          isAuthenticated: () => false,
          setAPICredentials: (key, secret) => { cred = `${key}:${secret}` },
          updateAuthArgs: () => {},
          auth: () => {
            assert.strictEqual(cred, '41:42')
            done()
          }
        }
      }]

      m.auth({ apiKey: '41', apiSecret: '42' })
    })
  })

  describe('openSocket', () => {
    it('binds listeners to forward events', () => {
      const heardEvents = {}
      const events = [
        'open', 'message', 'auth', 'error', 'close', 'subscribed',
        'unsubscribed'
      ]

      const m = new WS2Manager()
      const s = m.openSocket()
      const { ws } = s

      events.forEach(e => {
        m.on(e, () => { heardEvents[e] = true })
      })

      events.forEach(e => ws.emit(e))
      events.forEach(e => {
        assert(heardEvents[e])
      })
    })

    it('saves socket state', () => {
      const m = new WS2Manager()
      const s = m.openSocket()
      assert.deepStrictEqual(m._sockets[0], s)
    })

    it('binds \'unsubscribed\' listener to remove channel from pending unsubs', () => {
      const m = new WS2Manager()
      const s = m.openSocket()

      s.pendingUnsubscriptions.push(`${42}`)
      s.ws.emit('unsubscribed', { chanId: 42 })

      assert.strictEqual(s.pendingUnsubscriptions.length, 0)
    })

    it('binds \'subscribed\' listener to remove channel from pending subs', () => {
      const m = new WS2Manager()
      const s = m.openSocket()

      s.pendingSubscriptions.push(['book', { symbol: 'tBTCUSD', prec: 'R0' }])
      s.ws.emit('subscribed', {
        channel: 'book',
        symbol: 'tBTCUSD',
        prec: 'R0',
        len: '25'
      })

      assert.strictEqual(s.pendingSubscriptions.length, 0)
    })
  })

  describe('getFreeDataSocket', () => {
    it('returns the first socket below the data channel limit', () => {
      const m = new WS2Manager()

      m._sockets[0] = {
        ws: { getDataChannelCount: () => 200 },
        pendingSubscriptions: new Array(70),
        pendingUnsubscriptions: new Array(10)
      }

      m._sockets[1] = {
        ws: { getDataChannelCount: () => 5 },
        pendingSubscriptions: [],
        pendingUnsubscriptions: []
      }

      const s = m.getFreeDataSocket()
      assert.deepStrictEqual(s, m._sockets[1])
    })
  })

  describe('getSocketWithDataChannel', () => {
    it('returns socket subscribed to specified channel/filter pair', () => {
      const m = new WS2Manager()
      m._sockets[0] = {
        ws: {},
        pendingSubscriptions: [['candles', { key: 'test' }]],
        pendingUnsubscriptions: []
      }

      let s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert.deepStrictEqual(s, m._sockets[0])

      /// /
      m._sockets[0] = {
        ws: { getDataChannelId: () => false },
        pendingSubscriptions: [['auth', {}]],
        pendingUnsubscriptions: []
      }

      s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert(!s)

      /// /
      m._sockets[0] = {
        ws: {
          getDataChannelId: (type, filter) => {
            assert.strictEqual(type, 'candles')
            assert.deepStrictEqual(filter, { key: 'test' })
            return 1
          }
        },
        pendingSubscriptions: [],
        pendingUnsubscriptions: []
      }

      s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert.deepStrictEqual(s, m._sockets[0])

      /// /
      m._sockets[0] = {
        ws: {
          getDataChannelId: (type, filter) => {
            assert.strictEqual(type, 'candles')
            assert.deepStrictEqual(filter, { key: 'test' })
            return 1
          }
        },
        pendingSubscriptions: [],
        pendingUnsubscriptions: [1]
      }

      s = m.getSocketWithDataChannel('candles', { key: 'test' })
      assert(!s)
    })
  })

  describe('getSocketWithChannel', () => {
    it('returns correct socket', () => {
      const m = new WS2Manager()
      m._sockets[0] = {
        pendingUnsubscriptions: [],
        ws: {
          hasChannel: (id) => {
            return id === 42
          }
        }
      }

      let s = m.getSocketWithChannel(42)
      assert.deepStrictEqual(s, m._sockets[0])

      /// /
      m._sockets[0] = {
        pendingUnsubscriptions: [42],
        ws: {
          hasChannel: (id) => {
            return id === 42
          }
        }
      }

      s = m.getSocketWithChannel(42)
      assert(!s)
    })
  })

  describe('subscribe', () => {
    it('delays sub for unopened sockets', () => {
      const m = new WS2Manager()
      let onceOpenCalled = false

      m._sockets[0] = {
        pendingSubscriptions: [],
        pendingUnsubscriptions: [],
        ws: {
          getDataChannelCount: () => 0,
          managedSubscribe: () => assert(false),
          isOpen: () => false,
          once: (eName) => {
            assert.strictEqual(eName, 'open')
            onceOpenCalled = true
          }
        }
      }

      m.subscribe('candles', 'test', { key: 'test' })
      assert(onceOpenCalled)
    })

    it('saves pending sub', () => {
      const m = new WS2Manager()
      m._sockets[0] = {
        pendingSubscriptions: [],
        pendingUnsubscriptions: [],
        ws: {
          getDataChannelCount: () => 0,
          managedSubscribe: () => {},
          isOpen: () => true
        }
      }

      m.subscribe('candles', 'test', { key: 'test' })
      assert.deepStrictEqual(m._sockets[0].pendingSubscriptions, [
        ['candles', { key: 'test' }]
      ])
    })

    it('opens a new socket if no sockets are available', () => {
      const m = new WS2Manager()
      let openCalled = false

      m.openSocket = () => {
        openCalled = true

        return {
          pendingSubscriptions: [],
          ws: {
            once: () => {},
            isOpen: () => false // to avoid managed sub
          }
        }
      }

      m.subscribe('candles', 'test', { key: 'test' })
      assert(openCalled)
    })

    it('opens a new socket if no sockets are below data limit', () => {
      const m = new WS2Manager()
      let openCalled = false

      m._sockets[0] = {
        pendingSubscriptions: [],
        pendingUnsubscriptions: [],
        ws: {
          getDataChannelCount: () => 255
        }
      }

      m.openSocket = () => {
        openCalled = true

        const state = {
          pendingSubscriptions: [],
          ws: {
            once: () => {},
            isOpen: () => false // to avoid managed sub
          }
        }

        m._sockets.push(state)
        return state
      }

      m.subscribe('candles', 'test', { key: 'test' })

      assert(openCalled)
      assert.strictEqual(m._sockets.length, 2)
    })
  })

  describe('unsubscribe', () => {
    it('saves pending unsub & calls unsub on socket', () => {
      const m = new WS2Manager()
      let unsubCalled = false

      m._sockets[0] = {
        pendingUnsubscriptions: [],
        ws: {
          unsubscribe: (cid) => {
            assert.strictEqual(cid, 42)
            unsubCalled = true
          },

          hasChannel: (cid) => {
            return cid === 42
          }
        }
      }

      m.unsubscribe(42)
      assert.deepStrictEqual(m._sockets[0].pendingUnsubscriptions, [42])
      assert(unsubCalled)
    })
  })

  describe('withAllSockets', () => {
    it('calls the provided cb with all internal sockets', () => {
      const m = new WS2Manager()
      const socketsSeen = {}

      m._sockets = ['a', 'b', 'c']
      m.withAllSockets((sock) => {
        socketsSeen[sock] = true
      })

      assert(socketsSeen.a)
      assert(socketsSeen.b)
      assert(socketsSeen.c)
    })
  })
})
<|endoftext|>


<commit_before>var config = require('../lib/config');

exports.testSomething = function(test){
    test.expect(1);
    test.ok(true, "this assertion should pass");
    test.done();
};
<commit_msg>mocha boilerplate<commit_after>'use strict';

var expect = require('chai').expect;

describe('dalek', function() {

  it('should get default config filename', function(){
    var config = require('../lib/config')({}, {config: {}, tests: []});
    expect(config.defaultFilename).to.equal('Dalekfile');
  });

});
<|endoftext|>


<commit_before>'use strict';

var Matrix = require('../../');
var util = require('../util');
var assert = require('assert');

describe('Matrix creation', function () {
    it('should create a new object', function () {
        var array = util.getSquareArray();
        var matrix = new Matrix(array);
        matrix.should.not.equal(array);
    });
    it('should extend Array', function () {
        var array = util.getSquareArray();
        var matrix = new Matrix(array);
        matrix.should.be.instanceof(Matrix);
        matrix.should.be.instanceof(Array);
        Matrix.isMatrix(matrix).should.be.true();
        Array.isArray(matrix).should.be.true();
    });
    it('should clone existing matrix', function () {
        var original = util.getSquareMatrix();
        var matrix = new Matrix(original);
        matrix.should.not.equal(original);
        matrix.should.eql(original);
    });
    it('should create an empty matrix', function () {
        var matrix = new Matrix(3, 9);
        matrix.rows.should.equal(3);
        matrix.columns.should.equal(9);
        assert.strictEqual(matrix[0][0], undefined);
    });
    it('should throw with wrong arguments', function () {
        (function(){ new Matrix(6) }).should.throw(TypeError, /^nColumns must be a positive integer/);
        (function(){ new Matrix(0) }).should.throw(TypeError, /^First argument must be a positive number or an array$/);
        (function(){ new Matrix([[]]) }).should.throw(TypeError, /^Data must be a 2D array with at least one element$/);
        (function(){ new Matrix([0, 1, 2, 3]) }).should.throw(TypeError, /^Data must be a 2D array/);
        (function(){ new Matrix([[0, 1], [0, 1, 2]]) }).should.throw(RangeError, /^Inconsistent array dimensions$/);
        (function(){ new Matrix() }).should.throw(TypeError, /^First argument must be a positive number or an array$/);
    });
    it('should correctly set rows, columns and values', function () {
        var matrix = util.getSquareMatrix();
        matrix.rows.should.exactly(3);
        matrix.columns.should.exactly(3);
        matrix[1][2].should.exactly(7);
    });
    it('should correctly check if argument is a matrix', function () {
        var array = util.getSquareArray();
        var matrix = Matrix.checkMatrix(array);
        Matrix.isMatrix(matrix).should.be.true();
        var check2 = Matrix.checkMatrix(matrix);
        check2.should.exactly(matrix);
        (function() {
            Matrix.checkMatrix();
        }).should.throw(TypeError, /^Argument has to be a matrix$/);
    });
    it('should create a matrix from 1D array', function () {
        var matrix = Matrix.from1DArray(3, 2, [0, 1, 2, 3, 4, 5]);
        matrix.rows.should.exactly(3);
        matrix.columns.should.exactly(2);
        (function () {
            Matrix.from1DArray(3, 2, [0, 1, 2, 3]);
        }).should.throw(RangeError, /^Data length does not match given dimensions$/);
    });
    it('row vector', function () {
        var vector = Matrix.rowVector([0, 1, 2, 3]);
        vector.rows.should.equal(1);
        vector.columns.should.equal(4);
        vector.to2DArray().should.eql([[0, 1, 2, 3]]);
    });
    it('column vector', function () {
        var vector = Matrix.columnVector([0, 1, 2, 3]);
        vector.rows.should.equal(4);
        vector.columns.should.equal(1);
        vector.to2DArray().should.eql([[0], [1], [2], [3]]);
    });
    it('empty', function () {
        Matrix.empty(3, 3).should.eql(new Matrix(3, 3));
    });
    it('zeros', function () {
        Matrix.zeros(2, 3).to2DArray().should.eql([[0, 0, 0], [0, 0, 0]]);
    });
    it('ones', function () {
        Matrix.ones(2, 3).to2DArray().should.eql([[1, 1, 1], [1, 1, 1]]);
    });
    it('random', function () {
        var random = Matrix.rand(2, 3);
        var random2 = Matrix.rand(2, 3);
        random.to2DArray().should.not.eql(random2.to2DArray());
        for (var i = 0; i < 2; i++) {
            for (var j = 0; j < 3; j++) {
                random[i][j].should.be.within(0, 1);
            }
        }
    });
    it('random with custom RNG', function () {
        function fakeRNG() { return 2; }
        Matrix.rand(2, 2, fakeRNG).to2DArray().should.eql([[2, 2], [2, 2]]);
    });
    it('eye/identity', function () {
        var eye1 = Matrix.eye(3);
        eye1.should.eql(Matrix.identity(3));
        eye1.to2DArray().should.eql([[1, 0, 0], [0, 1, 0], [0, 0, 1]]);

        var eye2 = Matrix.eye(3, 2);
        eye2.to2DArray().should.eql([[1, 0], [0, 1], [0, 0]]);
    });
    it('diag/diagonal', function () {
        var arr = [1, 2, 3];
        var diag = Matrix.diag(arr);
        diag.should.eql(Matrix.diagonal(arr));
        diag.to2DArray().should.eql([[1, 0, 0], [0, 2, 0], [0, 0, 3]]);

        Matrix.diag(arr, 2).to2DArray().should.eql([[1, 0], [0, 2]]);
        Matrix.diag(arr, 2, 4).to2DArray().should.eql([[1, 0, 0, 0], [0, 2, 0, 0]]);
        Matrix.diag(arr, 4, 4).to2DArray().should.eql([[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 0]]);
    });
    it('regression test for Symbol.species (V8 5.1)', function () {
        var matrix = Matrix.ones(1, 2);
        matrix.map(x => 1).should.eql([1]);
    });
});
<commit_msg>test: fix creation test and add test for Symbol.species<commit_after>'use strict';

var Matrix = require('../../');
var util = require('../util');
var assert = require('assert');

describe('Matrix creation', function () {
    it('should create a new object', function () {
        var array = util.getSquareArray();
        var matrix = new Matrix(array);
        matrix.should.not.equal(array);
    });

    it('should extend Array', function () {
        var array = util.getSquareArray();
        var matrix = new Matrix(array);
        matrix.should.be.instanceof(Matrix);
        matrix.should.be.instanceof(Array);
        Matrix.isMatrix(matrix).should.be.true();
        Array.isArray(matrix).should.be.true();
    });

    it('should clone existing matrix', function () {
        var original = util.getSquareMatrix();
        var matrix = new Matrix(original);
        matrix.should.not.equal(original);
        matrix.should.eql(original);
    });

    it('should create an empty matrix', function () {
        var matrix = new Matrix(3, 9);
        matrix.rows.should.equal(3);
        matrix.columns.should.equal(9);
        assert.strictEqual(matrix[0][0], undefined);
    });

    it('should throw with wrong arguments', function () {
        (function(){ new Matrix(6, -1) }).should.throw(TypeError, /^nColumns must be a positive integer/);
        (function(){ new Matrix(0, 0) }).should.throw(TypeError, /^First argument must be a positive number or an array$/);
        (function(){ new Matrix([[]]) }).should.throw(TypeError, /^Data must be a 2D array with at least one element$/);
        (function(){ new Matrix([0, 1, 2, 3]) }).should.throw(TypeError, /^Data must be a 2D array/);
        (function(){ new Matrix([[0, 1], [0, 1, 2]]) }).should.throw(RangeError, /^Inconsistent array dimensions$/);
        (function(){ new Matrix() }).should.throw(TypeError, /^First argument must be a positive number or an array$/);
    });

    it('should correctly set rows, columns and values', function () {
        var matrix = util.getSquareMatrix();
        matrix.rows.should.exactly(3);
        matrix.columns.should.exactly(3);
        matrix[1][2].should.exactly(7);
    });

    it('should correctly check if argument is a matrix', function () {
        var array = util.getSquareArray();
        var matrix = Matrix.checkMatrix(array);
        Matrix.isMatrix(matrix).should.be.true();
        var check2 = Matrix.checkMatrix(matrix);
        check2.should.exactly(matrix);
        (function() {
            Matrix.checkMatrix();
        }).should.throw(TypeError, /^Argument has to be a matrix$/);
    });

    it('should create a matrix from 1D array', function () {
        var matrix = Matrix.from1DArray(3, 2, [0, 1, 2, 3, 4, 5]);
        matrix.rows.should.exactly(3);
        matrix.columns.should.exactly(2);
        (function () {
            Matrix.from1DArray(3, 2, [0, 1, 2, 3]);
        }).should.throw(RangeError, /^Data length does not match given dimensions$/);
    });

    it('row vector', function () {
        var vector = Matrix.rowVector([0, 1, 2, 3]);
        vector.rows.should.equal(1);
        vector.columns.should.equal(4);
        vector.to2DArray().should.eql([[0, 1, 2, 3]]);
    });

    it('column vector', function () {
        var vector = Matrix.columnVector([0, 1, 2, 3]);
        vector.rows.should.equal(4);
        vector.columns.should.equal(1);
        vector.to2DArray().should.eql([[0], [1], [2], [3]]);
    });

    it('empty', function () {
        Matrix.empty(3, 3).should.eql(new Matrix(3, 3));
    });

    it('zeros', function () {
        Matrix.zeros(2, 3).to2DArray().should.eql([[0, 0, 0], [0, 0, 0]]);
    });

    it('ones', function () {
        Matrix.ones(2, 3).to2DArray().should.eql([[1, 1, 1], [1, 1, 1]]);
    });

    it('random', function () {
        var random = Matrix.rand(2, 3);
        var random2 = Matrix.rand(2, 3);
        random.to2DArray().should.not.eql(random2.to2DArray());
        for (var i = 0; i < 2; i++) {
            for (var j = 0; j < 3; j++) {
                random[i][j].should.be.within(0, 1);
            }
        }
    });

    it('random with custom RNG', function () {
        function fakeRNG() { return 2; }
        Matrix.rand(2, 2, fakeRNG).to2DArray().should.eql([[2, 2], [2, 2]]);
    });

    it('eye/identity', function () {
        var eye1 = Matrix.eye(3);
        eye1.should.eql(Matrix.identity(3));
        eye1.to2DArray().should.eql([[1, 0, 0], [0, 1, 0], [0, 0, 1]]);

        var eye2 = Matrix.eye(3, 2);
        eye2.to2DArray().should.eql([[1, 0], [0, 1], [0, 0]]);
    });

    it('diag/diagonal', function () {
        var arr = [1, 2, 3];
        var diag = Matrix.diag(arr);
        diag.should.eql(Matrix.diagonal(arr));
        diag.to2DArray().should.eql([[1, 0, 0], [0, 2, 0], [0, 0, 3]]);

        Matrix.diag(arr, 2).to2DArray().should.eql([[1, 0], [0, 2]]);
        Matrix.diag(arr, 2, 4).to2DArray().should.eql([[1, 0, 0, 0], [0, 2, 0, 0]]);
        Matrix.diag(arr, 4, 4).to2DArray().should.eql([[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 0]]);
    });

    it('regression test for Symbol.species (V8 5.1)', function () {
        var matrix = Matrix.ones(1, 2);
        matrix.map(x => 1).should.eql([1]);
    });

    it('Symbol.species should work for views', function () {
        var matrix = new Matrix([[1, 1, 1], [1, 1, 1]]);
        var view = matrix.transposeView();
        matrix.transpose().mmul(matrix).should.eql(view.mmul(matrix));
    });
});
<|endoftext|>