<commit_before>var engine = require("../../engine").engine,
    _ = require("underscore");

var num_to_s = function(some_number){
    return (new Number(some_number)).toString();
};

var logging_gateway = engine.logging_gateway.create();
var stdout_client = engine.logging_stdout_client.create();
//logging_gateway.add_logger(stdout_client);

var create_tcp_intake = function(listening_port, sending_port){
    return engine.intake.create({
	listening_endpoint: "tcp://*:"+listening_port,
	sending_endpoint: "tcp://*:"+sending_port,
	logging_gateway: logging_gateway
    });
};

var create_tcp_exhaust = function(listening_port, publishing_port){
    return engine.exhaust.create({
	listening_endpoint: "tcp://*:"+listening_port,
	publishing_endpoint: "tcp://*:"+publishing_port,
	logging_gateway: logging_gateway
    });
};

var create_ipc_intake = function(identifier){
    return engine.intake.create({
	listening_endpoint: "ipc://intake-listener-"+identifier+".ipc",
	sending_endpoint: "ipc://cylinder-listener-"+identifier+".ipc",
	logging_gateway: logging_gateway
    });
};

var create_ipc_exhaust = function(identifier){
    return engine.exhaust.create({
	listening_endpoint: "ipc://exhaust-listener-"+identifier+".ipc",
	publishing_endpoint: "ipc://exhaust-publisher-"+identifier+".ipc",
	logging_gateway: logging_gateway
    });
};

var create_tcp_clients = function(num, sending_port, listening_port){
    var clients = {};
    for(var i=1; i<=num; i++){
	clients[num_to_s(i)] = engine.client.create({
	    sending_endpoint: "tcp://127.0.0.1:"+sending_port,
	    listening_endpoint: "tcp://127.0.0.1:"+listening_port
	});
    }
    return clients;
};

var create_ipc_clients = function(num, identifier){
    var clients = {};
    for(var i=1; i<=num; i++){
	clients[num_to_s(i)] = engine.client.create({
	    sending_endpoint: "ipc://intake-listener-"+identifier+".ipc",
	    listening_endpoint: "ipc://exhaust-publisher-"+identifier+".ipc"
	});
    }
    return clients;
};

var create_tcp_cylinders = function(num, listening_port, exhaust_port){
    var cylinders = {};
    for(var i=1; i<=num; i++){
	cylinders[num_to_s(i)] = engine.cylinder.create({
	    listening_endpoint: "tcp://127.0.0.1:"+listening_port,
	    exhaust_endpoint: "tcp://127.0.0.1:"+exhaust_port,
	    piston_script: "./script/piston.js",
	    logging_gateway: logging_gateway
	});
    }
    return cylinders;
};

var create_ipc_cylinders = function(num, identifier){
    var cylinders = {};
    for(var i=1; i<=num; i++){
	cylinders[num_to_s(i)] = engine.cylinder.create({
	    listening_endpoint: "ipc://cylinder-listener-"+identifier+".ipc",
	    exhaust_endpoint: "ipc://exhaust-listener-"+identifier+".ipc",
	    piston_script: "./script/piston.js",
	    logging_gateway: logging_gateway
	});
    }
    return cylinders;
};

var run_parameterized_system_test = function(scheme, num_clients, tasks_per_client, num_cylinders){

    var components = {};
    runs(function(){
	if (scheme == "tcp") {
	    components['intake'] = create_tcp_intake(5555, 5556);
	    components['exhaust'] = create_tcp_exhaust(5557, 5558);
	    components['clients'] = create_tcp_clients(num_clients, 5555, 5558);
	    components['cylinders'] = create_tcp_cylinders(num_cylinders, 5556, 5557);
	} else if (scheme == "ipc") {
	    var identifier = num_to_s(num_clients) + "-" +
	     num_to_s(tasks_per_client) + "-" +
	     num_to_s(num_cylinders);

	    components['intake'] = create_ipc_intake(identifier);
	    components['exhaust'] = create_ipc_exhaust(identifier);
	    components['clients'] = create_ipc_clients(num_clients, identifier);
	    components['cylinders'] = create_ipc_cylinders(num_cylinders, identifier);
	} else {
	    throw "'scheme' must be either 'ipc' or 'tcp'";
	}
    });

    waits(1000);

    var tasks = {}, task, callback, int1, int2;
    runs(function(){
	_.each(components['clients'], function(client){
	    for(var i = 1; i <= tasks_per_client; i++){
		int1 = Math.random(0,100);
		int2 = Math.random(0,200);
		task = client.createTask();
		task.setContext("(function(locals){ return { add: function(a,b){ return a+b; } } })");
		task.setLocals({});
		task.setCode("add("+int1+","+int2+")");
		callback = jasmine.createSpy();
		task.on('eval', callback);
		tasks[task.id] = {};
		tasks[task.id]['task'] = task;
		tasks[task.id]['callback'] = callback;
		tasks[task.id]['expected_result'] = int1+int2;
		task.run();
	    }
	});
    });

    waitsFor(function(){
	return _.all(tasks, function(data, task_id){
	    return data['callback'].callCount > 0;
	});
    },100000);

    runs(function(){
	_.each(tasks, function(data, task_id){
	    expect(data['callback'].mostRecentCall.args[0]).toBe(data['expected_result']);
	    data['task'].done();
	});
    });

    runs(function(){
	components['intake'].close();
	components['exhaust'].close();
	_.each(components['cylinders'], function(cylinder){
	    cylinder.close();
	});
	_.each(components['clients'], function(client){
	    client.close();
	});
    });
};

describe("Parameterized system test", function(){
    it("runs 1 client, 5 tasks, and 1 cylinder", function(){
	run_parameterized_system_test('tcp',1,5,1);
	run_parameterized_system_test('ipc',1,5,1);
    });

    it("runs 5 clients, 5 tasks, and 1 cylinder", function(){
	run_parameterized_system_test('tcp',5,5,5);
	run_parameterized_system_test('ipc',5,5,1);
    });

    it("runs 5 clients, 5 tasks, and 5 cylinders", function(){
	run_parameterized_system_test('tcp',5,5,5);
	run_parameterized_system_test('ipc',5,5,5);
    });

    it("runs 10 clients, 50 tasks, and 10 cylinders", function(){
	run_parameterized_system_test('tcp',10,45,10);
	run_parameterized_system_test('ipc',10,45,10);
    });

    it("runs 50 clients, 5 tasks, and 10 cylinders", function(){
	run_parameterized_system_test('tcp',50,5,10);
	run_parameterized_system_test('ipc',50,5,10);
    });
});<commit_msg>Added 50,50,50 case<commit_after>var engine = require("../../engine").engine,
    _ = require("underscore");

var num_to_s = function(some_number){
    return (new Number(some_number)).toString();
};

var logging_gateway = engine.logging_gateway.create();
var stdout_client = engine.logging_stdout_client.create();
//logging_gateway.add_logger(stdout_client);

var create_tcp_intake = function(listening_port, sending_port){
    return engine.intake.create({
	listening_endpoint: "tcp://*:"+listening_port,
	sending_endpoint: "tcp://*:"+sending_port,
	logging_gateway: logging_gateway
    });
};

var create_tcp_exhaust = function(listening_port, publishing_port){
    return engine.exhaust.create({
	listening_endpoint: "tcp://*:"+listening_port,
	publishing_endpoint: "tcp://*:"+publishing_port,
	logging_gateway: logging_gateway
    });
};

var create_ipc_intake = function(identifier){
    return engine.intake.create({
	listening_endpoint: "ipc://intake-listener-"+identifier+".ipc",
	sending_endpoint: "ipc://cylinder-listener-"+identifier+".ipc",
	logging_gateway: logging_gateway
    });
};

var create_ipc_exhaust = function(identifier){
    return engine.exhaust.create({
	listening_endpoint: "ipc://exhaust-listener-"+identifier+".ipc",
	publishing_endpoint: "ipc://exhaust-publisher-"+identifier+".ipc",
	logging_gateway: logging_gateway
    });
};

var create_tcp_clients = function(num, sending_port, listening_port){
    var clients = {};
    for(var i=1; i<=num; i++){
	clients[num_to_s(i)] = engine.client.create({
	    sending_endpoint: "tcp://127.0.0.1:"+sending_port,
	    listening_endpoint: "tcp://127.0.0.1:"+listening_port
	});
    }
    return clients;
};

var create_ipc_clients = function(num, identifier){
    var clients = {};
    for(var i=1; i<=num; i++){
	clients[num_to_s(i)] = engine.client.create({
	    sending_endpoint: "ipc://intake-listener-"+identifier+".ipc",
	    listening_endpoint: "ipc://exhaust-publisher-"+identifier+".ipc"
	});
    }
    return clients;
};

var create_tcp_cylinders = function(num, listening_port, exhaust_port){
    var cylinders = {};
    for(var i=1; i<=num; i++){
	cylinders[num_to_s(i)] = engine.cylinder.create({
	    listening_endpoint: "tcp://127.0.0.1:"+listening_port,
	    exhaust_endpoint: "tcp://127.0.0.1:"+exhaust_port,
	    piston_script: "./script/piston.js",
	    logging_gateway: logging_gateway
	});
    }
    return cylinders;
};

var create_ipc_cylinders = function(num, identifier){
    var cylinders = {};
    for(var i=1; i<=num; i++){
	cylinders[num_to_s(i)] = engine.cylinder.create({
	    listening_endpoint: "ipc://cylinder-listener-"+identifier+".ipc",
	    exhaust_endpoint: "ipc://exhaust-listener-"+identifier+".ipc",
	    piston_script: "./script/piston.js",
	    logging_gateway: logging_gateway
	});
    }
    return cylinders;
};

var run_parameterized_system_test = function(scheme, num_clients, tasks_per_client, num_cylinders){

    var components = {};
    runs(function(){
	if (scheme == "tcp") {
	    components['intake'] = create_tcp_intake(5555, 5556);
	    components['exhaust'] = create_tcp_exhaust(5557, 5558);
	    components['clients'] = create_tcp_clients(num_clients, 5555, 5558);
	    components['cylinders'] = create_tcp_cylinders(num_cylinders, 5556, 5557);
	} else if (scheme == "ipc") {
	    var identifier = num_to_s(num_clients) + "-" +
	     num_to_s(tasks_per_client) + "-" +
	     num_to_s(num_cylinders);

	    components['intake'] = create_ipc_intake(identifier);
	    components['exhaust'] = create_ipc_exhaust(identifier);
	    components['clients'] = create_ipc_clients(num_clients, identifier);
	    components['cylinders'] = create_ipc_cylinders(num_cylinders, identifier);
	} else {
	    throw "'scheme' must be either 'ipc' or 'tcp'";
	}
    });

    waits(1000);

    var tasks = {}, task, callback, int1, int2;
    runs(function(){
	_.each(components['clients'], function(client){
	    for(var i = 1; i <= tasks_per_client; i++){
		int1 = Math.random(0,100);
		int2 = Math.random(0,200);
		task = client.createTask();
		task.setContext("(function(locals){ return { add: function(a,b){ return a+b; } } })");
		task.setLocals({});
		task.setCode("add("+int1+","+int2+")");
		callback = jasmine.createSpy();
		task.on('eval', callback);
		tasks[task.id] = {};
		tasks[task.id]['task'] = task;
		tasks[task.id]['callback'] = callback;
		tasks[task.id]['expected_result'] = int1+int2;
		task.run();
	    }
	});
    });

    waitsFor(function(){
	return _.all(tasks, function(data, task_id){
	    return data['callback'].callCount > 0;
	});
    },100000);

    runs(function(){
	_.each(tasks, function(data, task_id){
	    expect(data['callback'].mostRecentCall.args[0]).toBe(data['expected_result']);
	    data['task'].done();
	});
    });

    runs(function(){
	components['intake'].close();
	components['exhaust'].close();
	_.each(components['cylinders'], function(cylinder){
	    cylinder.close();
	});
	_.each(components['clients'], function(client){
	    client.close();
	});
    });
};

describe("Parameterized system test", function(){
    it("runs 1 client, 5 tasks, and 1 cylinder", function(){
	run_parameterized_system_test('tcp',1,5,1);
	run_parameterized_system_test('ipc',1,5,1);
    });

    it("runs 5 clients, 5 tasks, and 1 cylinder", function(){
	run_parameterized_system_test('tcp',5,5,5);
	run_parameterized_system_test('ipc',5,5,1);
    });

    it("runs 5 clients, 5 tasks, and 5 cylinders", function(){
	run_parameterized_system_test('tcp',5,5,5);
	run_parameterized_system_test('ipc',5,5,5);
    });

    it("runs 10 clients, 50 tasks, and 10 cylinders", function(){
	run_parameterized_system_test('tcp',10,50,10);
	run_parameterized_system_test('ipc',10,50,10);
    });

    it("runs 50 clients, 5 tasks, and 10 cylinders", function(){
	run_parameterized_system_test('tcp',50,5,10);
	run_parameterized_system_test('ipc',50,5,10);
    });

    it("runs 50 clients, 50 tasks, and 50 cylinders", function(){
	run_parameterized_system_test('tcp',50,50,10);
	run_parameterized_system_test('ipc',50,50,10);
    });
});<|endoftext|>


<commit_before>const LetterState = {};
LetterState.UNKNOWN = 'empty';
LetterState.ABSENT = 'absent';
LetterState.ELSEWHERE = 'elsewhere';
LetterState.CORRECT = 'correct';
const START_HELP_TEXT = 'Enter a word for someone!\nOr choose a random word.';

const GameState = {};
GameState.CHOOSING_WORD = 'choose';
GameState.GUESSING_WORD = 'guess';
GameState.COMPLETE = 'complete';

const CORRECT_COLOR = '#F7A8B8';
const ELSEWHERE_COLOR = '#55CDFC';

const DEFAULT_WORD_SIZE = 4;

const ENTER_KEY = '\u21A9';
const BACKSPACE_KEY = '\u232B';
const KEYS = ['qwertyuiop', 'asdfghjkl', ENTER_KEY + 'zxcvbnm' + BACKSPACE_KEY];

const NUMBERS = ['\u24EA', '\u2460', '\u2461', '\u2462', '\u2463', '\u2464', '\u2465', '\u2466', '\u2467', '\u2468'];

class Game {
  constructor() {
  }

  newGame() {
    document.activeElement.blur();
    this.stateList = [];
    this.guessList = [];
    this.keyStates = {};
    this.pendingTarget = '';
    this.guess = '';
    this.board = document.getElementsByClassName('board')[0];
    while (this.board.firstChild) {
      this.board.removeChild(this.board.firstChild);
    }
    this.board.className = 'board';
    const share = document.getElementById('share');
    share.className = 'share';
    this.gameState = GameState.CHOOSING_WORD;

    const row = document.createElement('div');
    row.className = 'row';
    this.board.appendChild(row);
    const randomButton = document.getElementById('random');
    randomButton.style.display = 'unset';
    row.innerText = START_HELP_TEXT;
    this.updateKeys();
    this.showNotification(null);
  }

  chooseWord(target) {
    if (words.indexOf(target) < 0) {
      if (target.length == 0) {
        this.showNotification(START_HELP_TEXT);
      } else {
        this.showNotification('Unknown word ' + target.toUpperCase() + '');
      }
      return null;
    }
    this.pendingTarget = '';
    this.size = target.length;
    this.target = target;
    window.location.hash = '#' + encode(target);
    this.targetWordList = wordsByLength[this.target.length];
    this.board.removeChild(this.board.firstChild);
    this.startNewRow();
    this.gameState = GameState.GUESSING_WORD;
    const randomButton = document.getElementById('random');
    randomButton.style.display = 'none';
    this.updateGuess();
  }

  chooseRandomWord(size) {
    let target = '';
    if (size == 4) {
      let attemptedTarget = null;
      while (!attemptedTarget) {
        attemptedTarget = freq[Math.floor(Math.random() * freq.length)];
        if (wordsByLength[size].indexOf(attemptedTarget) < 0) {
          attemptedTarget = null;
        }
      }
      target = attemptedTarget;
    } else {
      const max = wordsByLength[size].length;
      target = wordsByLength[size][Math.floor(Math.random() * max)];
    }
    this.chooseWord(target);
  }

  startNewRow() {
    const row = document.createElement('div');
    row.className = 'row';
    this.board.appendChild(row);
    this.updateGuess();
  }

  letterCounts(word) {
    const counts = {};
    for (let i = 0; i < word.length; i++) {
      let count = counts[word[i]] || 0;
      counts[word[i]] = count + 1;
    }
    return counts;
  }

  showNotification(text, timeout = 10000) {
    const notif = document.getElementsByClassName('notification')[0];
    if (!text || text === '') {
      notif.style.display = 'none';
      if (this.timer_) {
        clearTimeout(this.timer_);
      }
    } else {
      notif.innerText = text;
      notif.style.display = 'unset';
      if (this.timer_) {
        clearTimeout(this.timer_);
      }
      this.timer_ = setTimeout(() => notif.style.display = 'none', timeout);
    }
  }
  commitWord() {
    this.chooseWord(this.pendingTarget);
  }

  guessWord() {
    document.activeElement.blur();
    const input = this.guess.toLowerCase();
    if (input.length !== this.size) {
      return;
    }
    const states = this.wordStates(input);
    if (states == null) {
      // Invalid word
      this.showNotification('Unknown word ' + input.toUpperCase());
      return;
    }
    this.showNotification(null);
    this.updateGuess(states);
    this.guessList.push(this.guess);
    this.stateList.push(states);

    this.updateKeys();
    if (this.guess === this.target) {
      this.board.className = 'board won';
      const share = document.getElementById('share');
      share.className = 'share won';
      this.gameState = GameState.COMPLETE;
      window.location.hash = '';
      this.showNotification('Got it in ' + this.stateList.length +'! Press R or Enter to restart.');
    } else {
      this.guess = '';
      this.startNewRow();
      window.scrollTo(0, document.body.scrollHeight);
    }
  }

  updateKeys() {
    for (let key in keyMap) {
      keyMap[key].className = 'key';
    }
    for (let i = 0; i < this.guessList.length; i++) {
      const guess = this.guessList[i];
      for (let j = 0; j < guess.length; j++) {
        const letter = guess.charAt(j);
        keyMap[letter].className = 'key used';
      }
    }
  }

  makeLetter(state, l) {
    const letter = document.createElement('div');
    letter.className = 'letter ' + state;
    if (l) {
      letter.appendChild(document.createTextNode(l.toUpperCase()));
    }
    return letter;
  }

  typeLetter(letter) {
    if (this.gameState == GameState.CHOOSING_WORD) {
      this.pendingTarget += letter;
    } else {
      if (this.guess.length < this.size) {
        this.guess += letter;
      }
    }
    this.updateGuess();

  }

  deleteLetterTarget() {
    if (this.pendingTarget.length >= 1) {
      this.pendingTarget = this.pendingTarget.substring(0, this.pendingTarget.length - 1);
    }
    this.updateGuess();
    if (this.pendingTarget.length === 0) {
      const row = this.board.lastChild;
      row.innerText = START_HELP_TEXT;
    }
  }

  deleteLetterGuess() {
    if (this.guess.length >= 1) {
      this.guess = this.guess.substring(0, this.guess.length - 1);
    }
    this.updateGuess();
  }

  updateGuess(states) {
    const row = this.board.lastChild;
    while (row.firstChild) {
      row.removeChild(row.firstChild);
    }
    if (this.gameState == GameState.CHOOSING_WORD) {
      for (let i = 0; i < this.pendingTarget.length; i++) {
        row.appendChild(this.makeLetter(LetterState.UNKNOWN, this.pendingTarget[i]));
      }
      return;
    }
    // const player = document.createElement('div');
    // player.className = 'counter';
    // player.appendChild(document.createTextNode(this.stateList.length + 1));
    // row.appendChild(player);
    for (let i = 0; i < this.target.length; i++) {
      // row.appendChild(this.makeLetter(states ? states[i] : LetterState.UNKNOWN, this.guess[i]));
      row.appendChild(this.makeLetter(LetterState.UNKNOWN, this.guess[i]));
    }
    let correct = '';
    let elsewhere = '';
    if (states) {
      correct = 0;
      elsewhere = 0;
      for (let i = 0; i < states.length; i++) {
        if (states[i] === LetterState.CORRECT) {
          correct++;
        } else if (states[i] === LetterState.ELSEWHERE) {
          elsewhere++;
        }
      }
    }
    row.appendChild(this.createCountNode(correct, 'right'));
    row.appendChild(this.createCountNode(elsewhere, 'else'));
  }

  createCountNode(count, kind) {
    const player = document.createElement('div');
    player.className = 'state ' + kind;
    player.appendChild(document.createTextNode(count));
    return player;
  }

  wordStates(input) {
    if (input.length !== this.target.length) {
      return null;
    } else if (this.targetWordList.indexOf(input)<0) {
      return null;
    }
    return this.wordMatches(input, this.target);
  }

  wordMatches(input, target) {
    const states = [];
    for (let i = 0; i < input.length; i++) {
      states[i] = LetterState.ABSENT;
    }
    const countsByLetter = this.letterCounts(this.target);
    // First check for exact matches
    for (let i = 0; i < input.length; i++) {
      if (input[i] === this.target[i]) {
        states[i] = LetterState.CORRECT;
        countsByLetter[input[i]]--;
      }
    }
    // Then check for right-letter-wrong-place
    for (let i = 0; i < input.length; i++) {
      if (countsByLetter[input[i]] > 0 && states[i] !== LetterState.CORRECT) {
        states[i] = LetterState.ELSEWHERE;
        countsByLetter[input[i]]--;
      }
    }
    return states;
  }

  showHelp(event) {
    this.showNotification('To start, enter a word for someone else to guess, or choose a random word.\n' +
    'Green (left): correct letter, correct location\n' +
        'Blue (right): correct letter, wrong location');
  }

  showSettings(event) {
    this.showNotification('Sorry no settings yet :)');
  }

  share(event) {
    let text = '';
    if (this.gameState === GameState.GUESSING_WORD) {
      text = 'Here you go! ' + window.location;
    } else if (this.gameState == GameState.COMPLETE) {
      for (let i = 0; i < this.stateList.length; i++) {
        const states = this.stateList[i];
        let correct = 0;
        let elsewhere = 0;
        for (let i = 0; i < states.length; i++) {
          if (states[i] === LetterState.CORRECT) {
            correct++;
          } else if (states[i] === LetterState.ELSEWHERE) {
            elsewhere++;
          }
        }
        text += NUMBERS[correct];
        text += NUMBERS[elsewhere];
        text += '\n';
      }
      text += '\n';
      text += window.location + '#' + encode(this.target);
    }
    if (navigator) {
      if (navigator.share) {
        navigator.share({
          title: 'Friendl',
          text: text
          // url: window.location + '#' + encode(this.target)
        });
      } else if (navigator.clipboard) {
        navigator.clipboard.writeText(text);
      } else {
        g.showNotification(text, 1000000);
      }
    }
  }

  setup() {
    const help = document.getElementById('help');
    help.addEventListener('click', (event) => this.showHelp(), false);
    // const settings = document.getElementById('settings');
    // settings.addEventListener('click', (event) => this.showSettings(), false);
    const share = document.getElementById('share');
    share.addEventListener('click', (event) => this.share(), false);
    const restart = document.getElementById('restart');
    restart.addEventListener('click', (event) => this.newGame(), false);
    const randomButton = document.getElementById('random');
    randomButton.addEventListener('click',
    (event) => this.chooseRandomWord(DEFAULT_WORD_SIZE), false);
  }

  handleKeyPress(letter) {
    if (g.gameState == GameState.COMPLETE) {
      if (letter === 'r' || letter === ENTER_KEY) {
        g.newGame(DEFAULT_WORD_SIZE);
      }
    } else if (g.gameState == GameState.GUESSING_WORD) {
      if (letter === BACKSPACE_KEY) {
        g.deleteLetterGuess();
      } else if (letter === ENTER_KEY) {
        g.guessWord();
      } else {
        g.typeLetter(letter);
      }
    } else {
      if (letter === BACKSPACE_KEY) {
        g.deleteLetterTarget();
      } else if (letter === ENTER_KEY) {
        g.commitWord();
      } else {
        g.typeLetter(letter);
      }
    }
  }
}

function createKey(letter) {
  const singleKey = document.createElement('button');
  singleKey.innerText = letter;
  singleKey.className = 'key';
  if (letter === BACKSPACE_KEY || letter === ENTER_KEY) {
      singleKey.style.width = '70px';
  }
  singleKey.addEventListener('click', (event) => g.handleKeyPress(letter), false);
  return singleKey;
}

const keyMap = {};
function showKeyboard() {
  const keyboard = document.getElementsByClassName('keys')[0];
  for (var i = 0; i < KEYS.length; i++) {
    const row = document.createElement('div');
    row.className = 'keyrow';
    for (var j = 0; j < KEYS[i].length; j++) {
      const character = KEYS[i].charAt(j);
      const element = createKey(character);
      row.appendChild(element);
      keyMap[character] = element;
    }
    keyboard.appendChild(row);
  }
}

function encode(word) {
  let encoded = '';
  let achar = 'a'.charCodeAt(0);
  word = word.toLowerCase();
  for (let i = 0; i < word.length; i++) {
    let newLet = ((word.charCodeAt(i) - achar) + 11 + 13 * i + 17 * i * i) % 26;
    if (newLet < 10) {
      encoded += '0' + newLet;
    } else {
      encoded += newLet;
    }
  }
  return encoded;
}

function decode(word) {
  let decoded = '';
  let achar = 'a'.charCodeAt(0);
  word = word.toLowerCase();
  try {
    for (let i = 0; i < word.length; i += 2) {
      let newLet = (parseInt(word.substring(i, i + 2), 10) - 11 - 13 * (i / 2) - 17 * (i / 2) * (i / 2) + 260) % 26;
      decoded += String.fromCharCode(achar + newLet);
    }
  } catch (e) {
    return null;
  }
  return decoded;
}

const g = new Game();
function start() {
  showKeyboard();
  g.setup();
  g.newGame();
  if (window.location.hash) {
    const decoded = decode(window.location.hash.substring(1));
    if (decoded) {
      g.chooseWord(decoded);
    }
  }
  // g.chooseRandomWord(DEFAULT_WORD_SIZE);
}

document.addEventListener('keydown', (event) => {
  const keyName = event.key.toLowerCase();
  if (event.ctrlKey || event.metaKey || event.altKey) {
    return;
  }
  let letter = '';
  if (keyName.length === 1 && keyName[0] >= 'a' && keyName[0] <= 'z') {
    letter = keyName;
  } else if (keyName === 'backspace') {
    letter = BACKSPACE_KEY;
  } else if (keyName === 'enter') {
    letter = ENTER_KEY;
  }
  if (letter !== '') {
    g.handleKeyPress(letter);
  }
}, false);
<commit_msg>New URL<commit_after>const LetterState = {};
LetterState.UNKNOWN = 'empty';
LetterState.ABSENT = 'absent';
LetterState.ELSEWHERE = 'elsewhere';
LetterState.CORRECT = 'correct';
const START_HELP_TEXT = 'Enter a word for someone!\nOr choose a random word.';

const GameState = {};
GameState.CHOOSING_WORD = 'choose';
GameState.GUESSING_WORD = 'guess';
GameState.COMPLETE = 'complete';

const CORRECT_COLOR = '#F7A8B8';
const ELSEWHERE_COLOR = '#55CDFC';

const DEFAULT_WORD_SIZE = 4;

const ENTER_KEY = '\u21A9';
const BACKSPACE_KEY = '\u232B';
const KEYS = ['qwertyuiop', 'asdfghjkl', ENTER_KEY + 'zxcvbnm' + BACKSPACE_KEY];

const NUMBERS = ['\u24EA', '\u2460', '\u2461', '\u2462', '\u2463', '\u2464', '\u2465', '\u2466', '\u2467', '\u2468'];

class Game {
  constructor() {
  }

  newGame() {
    document.activeElement.blur();
    this.stateList = [];
    this.guessList = [];
    this.keyStates = {};
    this.pendingTarget = '';
    this.guess = '';
    this.board = document.getElementsByClassName('board')[0];
    while (this.board.firstChild) {
      this.board.removeChild(this.board.firstChild);
    }
    this.board.className = 'board';
    const share = document.getElementById('share');
    share.className = 'share';
    this.gameState = GameState.CHOOSING_WORD;

    const row = document.createElement('div');
    row.className = 'row';
    this.board.appendChild(row);
    const randomButton = document.getElementById('random');
    randomButton.style.display = 'unset';
    row.innerText = START_HELP_TEXT;
    this.updateKeys();
    this.showNotification(null);
  }

  chooseWord(target) {
    if (words.indexOf(target) < 0) {
      if (target.length == 0) {
        this.showNotification(START_HELP_TEXT);
      } else {
        this.showNotification('Unknown word ' + target.toUpperCase() + '');
      }
      return null;
    }
    this.pendingTarget = '';
    this.size = target.length;
    this.target = target;
    window.location.hash = '#' + encode(target);
    this.targetWordList = wordsByLength[this.target.length];
    this.board.removeChild(this.board.firstChild);
    this.startNewRow();
    this.gameState = GameState.GUESSING_WORD;
    const randomButton = document.getElementById('random');
    randomButton.style.display = 'none';
    this.updateGuess();
  }

  chooseRandomWord(size) {
    let target = '';
    if (size == 4) {
      let attemptedTarget = null;
      while (!attemptedTarget) {
        attemptedTarget = freq[Math.floor(Math.random() * freq.length)];
        if (wordsByLength[size].indexOf(attemptedTarget) < 0) {
          attemptedTarget = null;
        }
      }
      target = attemptedTarget;
    } else {
      const max = wordsByLength[size].length;
      target = wordsByLength[size][Math.floor(Math.random() * max)];
    }
    this.chooseWord(target);
  }

  startNewRow() {
    const row = document.createElement('div');
    row.className = 'row';
    this.board.appendChild(row);
    this.updateGuess();
  }

  letterCounts(word) {
    const counts = {};
    for (let i = 0; i < word.length; i++) {
      let count = counts[word[i]] || 0;
      counts[word[i]] = count + 1;
    }
    return counts;
  }

  showNotification(text, timeout = 10000) {
    const notif = document.getElementsByClassName('notification')[0];
    if (!text || text === '') {
      notif.style.display = 'none';
      if (this.timer_) {
        clearTimeout(this.timer_);
      }
    } else {
      notif.innerText = text;
      notif.style.display = 'unset';
      if (this.timer_) {
        clearTimeout(this.timer_);
      }
      this.timer_ = setTimeout(() => notif.style.display = 'none', timeout);
    }
  }
  commitWord() {
    this.chooseWord(this.pendingTarget);
  }

  guessWord() {
    document.activeElement.blur();
    const input = this.guess.toLowerCase();
    if (input.length !== this.size) {
      return;
    }
    const states = this.wordStates(input);
    if (states == null) {
      // Invalid word
      this.showNotification('Unknown word ' + input.toUpperCase());
      return;
    }
    this.showNotification(null);
    this.updateGuess(states);
    this.guessList.push(this.guess);
    this.stateList.push(states);

    this.updateKeys();
    if (this.guess === this.target) {
      this.board.className = 'board won';
      const share = document.getElementById('share');
      share.className = 'share won';
      this.gameState = GameState.COMPLETE;
      window.location.hash = '';
      this.showNotification('Got it in ' + this.stateList.length +'! Press R or Enter to restart.');
    } else {
      this.guess = '';
      this.startNewRow();
      window.scrollTo(0, document.body.scrollHeight);
    }
  }

  updateKeys() {
    for (let key in keyMap) {
      keyMap[key].className = 'key';
    }
    for (let i = 0; i < this.guessList.length; i++) {
      const guess = this.guessList[i];
      for (let j = 0; j < guess.length; j++) {
        const letter = guess.charAt(j);
        keyMap[letter].className = 'key used';
      }
    }
  }

  makeLetter(state, l) {
    const letter = document.createElement('div');
    letter.className = 'letter ' + state;
    if (l) {
      letter.appendChild(document.createTextNode(l.toUpperCase()));
    }
    return letter;
  }

  typeLetter(letter) {
    if (this.gameState == GameState.CHOOSING_WORD) {
      this.pendingTarget += letter;
    } else {
      if (this.guess.length < this.size) {
        this.guess += letter;
      }
    }
    this.updateGuess();

  }

  deleteLetterTarget() {
    if (this.pendingTarget.length >= 1) {
      this.pendingTarget = this.pendingTarget.substring(0, this.pendingTarget.length - 1);
    }
    this.updateGuess();
    if (this.pendingTarget.length === 0) {
      const row = this.board.lastChild;
      row.innerText = START_HELP_TEXT;
    }
  }

  deleteLetterGuess() {
    if (this.guess.length >= 1) {
      this.guess = this.guess.substring(0, this.guess.length - 1);
    }
    this.updateGuess();
  }

  updateGuess(states) {
    const row = this.board.lastChild;
    while (row.firstChild) {
      row.removeChild(row.firstChild);
    }
    if (this.gameState == GameState.CHOOSING_WORD) {
      for (let i = 0; i < this.pendingTarget.length; i++) {
        row.appendChild(this.makeLetter(LetterState.UNKNOWN, this.pendingTarget[i]));
      }
      return;
    }
    // const player = document.createElement('div');
    // player.className = 'counter';
    // player.appendChild(document.createTextNode(this.stateList.length + 1));
    // row.appendChild(player);
    for (let i = 0; i < this.target.length; i++) {
      // row.appendChild(this.makeLetter(states ? states[i] : LetterState.UNKNOWN, this.guess[i]));
      row.appendChild(this.makeLetter(LetterState.UNKNOWN, this.guess[i]));
    }
    let correct = '';
    let elsewhere = '';
    if (states) {
      correct = 0;
      elsewhere = 0;
      for (let i = 0; i < states.length; i++) {
        if (states[i] === LetterState.CORRECT) {
          correct++;
        } else if (states[i] === LetterState.ELSEWHERE) {
          elsewhere++;
        }
      }
    }
    row.appendChild(this.createCountNode(correct, 'right'));
    row.appendChild(this.createCountNode(elsewhere, 'else'));
  }

  createCountNode(count, kind) {
    const player = document.createElement('div');
    player.className = 'state ' + kind;
    player.appendChild(document.createTextNode(count));
    return player;
  }

  wordStates(input) {
    if (input.length !== this.target.length) {
      return null;
    } else if (this.targetWordList.indexOf(input)<0) {
      return null;
    }
    return this.wordMatches(input, this.target);
  }

  wordMatches(input, target) {
    const states = [];
    for (let i = 0; i < input.length; i++) {
      states[i] = LetterState.ABSENT;
    }
    const countsByLetter = this.letterCounts(this.target);
    // First check for exact matches
    for (let i = 0; i < input.length; i++) {
      if (input[i] === this.target[i]) {
        states[i] = LetterState.CORRECT;
        countsByLetter[input[i]]--;
      }
    }
    // Then check for right-letter-wrong-place
    for (let i = 0; i < input.length; i++) {
      if (countsByLetter[input[i]] > 0 && states[i] !== LetterState.CORRECT) {
        states[i] = LetterState.ELSEWHERE;
        countsByLetter[input[i]]--;
      }
    }
    return states;
  }

  showHelp(event) {
    this.showNotification('To start, enter a word for someone else to guess, or choose a random word.\n' +
    'Green (left): correct letter, correct location\n' +
        'Blue (right): correct letter, wrong location');
  }

  showSettings(event) {
    this.showNotification('Sorry no settings yet :)');
  }

  share(event) {
    let text = '';
    if (this.gameState === GameState.GUESSING_WORD) {
      text = 'Here you go! ' + window.location;
    } else if (this.gameState == GameState.COMPLETE) {
      for (let i = 0; i < this.stateList.length; i++) {
        const states = this.stateList[i];
        let correct = 0;
        let elsewhere = 0;
        for (let i = 0; i < states.length; i++) {
          if (states[i] === LetterState.CORRECT) {
            correct++;
          } else if (states[i] === LetterState.ELSEWHERE) {
            elsewhere++;
          }
        }
        text += NUMBERS[correct];
        text += NUMBERS[elsewhere];
        text += '\n';
      }
      text += '\n';
      text += 'https://jkadams.github.io/friendl/#' + encode(this.target);
    }
    if (navigator) {
      if (navigator.share) {
        navigator.share({
          title: 'Friendl',
          text: text
          // url: window.location + '#' + encode(this.target)
        });
      } else if (navigator.clipboard) {
        navigator.clipboard.writeText(text);
      } else {
        g.showNotification(text, 1000000);
      }
    }
  }

  setup() {
    const help = document.getElementById('help');
    help.addEventListener('click', (event) => this.showHelp(), false);
    // const settings = document.getElementById('settings');
    // settings.addEventListener('click', (event) => this.showSettings(), false);
    const share = document.getElementById('share');
    share.addEventListener('click', (event) => this.share(), false);
    const restart = document.getElementById('restart');
    restart.addEventListener('click', (event) => this.newGame(), false);
    const randomButton = document.getElementById('random');
    randomButton.addEventListener('click',
    (event) => this.chooseRandomWord(DEFAULT_WORD_SIZE), false);
  }

  handleKeyPress(letter) {
    if (g.gameState == GameState.COMPLETE) {
      if (letter === 'r' || letter === ENTER_KEY) {
        g.newGame(DEFAULT_WORD_SIZE);
      }
    } else if (g.gameState == GameState.GUESSING_WORD) {
      if (letter === BACKSPACE_KEY) {
        g.deleteLetterGuess();
      } else if (letter === ENTER_KEY) {
        g.guessWord();
      } else {
        g.typeLetter(letter);
      }
    } else {
      if (letter === BACKSPACE_KEY) {
        g.deleteLetterTarget();
      } else if (letter === ENTER_KEY) {
        g.commitWord();
      } else {
        g.typeLetter(letter);
      }
    }
  }
}

function createKey(letter) {
  const singleKey = document.createElement('button');
  singleKey.innerText = letter;
  singleKey.className = 'key';
  if (letter === BACKSPACE_KEY || letter === ENTER_KEY) {
      singleKey.style.width = '70px';
  }
  singleKey.addEventListener('click', (event) => g.handleKeyPress(letter), false);
  return singleKey;
}

const keyMap = {};
function showKeyboard() {
  const keyboard = document.getElementsByClassName('keys')[0];
  for (var i = 0; i < KEYS.length; i++) {
    const row = document.createElement('div');
    row.className = 'keyrow';
    for (var j = 0; j < KEYS[i].length; j++) {
      const character = KEYS[i].charAt(j);
      const element = createKey(character);
      row.appendChild(element);
      keyMap[character] = element;
    }
    keyboard.appendChild(row);
  }
}

function encode(word) {
  let encoded = '';
  let achar = 'a'.charCodeAt(0);
  word = word.toLowerCase();
  for (let i = 0; i < word.length; i++) {
    let newLet = ((word.charCodeAt(i) - achar) + 11 + 13 * i + 17 * i * i) % 26;
    if (newLet < 10) {
      encoded += '0' + newLet;
    } else {
      encoded += newLet;
    }
  }
  return encoded;
}

function decode(word) {
  let decoded = '';
  let achar = 'a'.charCodeAt(0);
  word = word.toLowerCase();
  try {
    for (let i = 0; i < word.length; i += 2) {
      let newLet = (parseInt(word.substring(i, i + 2), 10) - 11 - 13 * (i / 2) - 17 * (i / 2) * (i / 2) + 260) % 26;
      decoded += String.fromCharCode(achar + newLet);
    }
  } catch (e) {
    return null;
  }
  return decoded;
}

const g = new Game();
function start() {
  showKeyboard();
  g.setup();
  g.newGame();
  if (window.location.hash) {
    const decoded = decode(window.location.hash.substring(1));
    if (decoded) {
      g.chooseWord(decoded);
    }
  }
  // g.chooseRandomWord(DEFAULT_WORD_SIZE);
}

document.addEventListener('keydown', (event) => {
  const keyName = event.key.toLowerCase();
  if (event.ctrlKey || event.metaKey || event.altKey) {
    return;
  }
  let letter = '';
  if (keyName.length === 1 && keyName[0] >= 'a' && keyName[0] <= 'z') {
    letter = keyName;
  } else if (keyName === 'backspace') {
    letter = BACKSPACE_KEY;
  } else if (keyName === 'enter') {
    letter = ENTER_KEY;
  }
  if (letter !== '') {
    g.handleKeyPress(letter);
  }
}, false);
<|endoftext|>


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

//Pure JS based composition
define.class('$server/composition', function(
	$server$, service,
	$ui$, screen, view,
	$behaviors$, draggable){ this.render = function(){ return [

	service({
		name:'myservice',
		flowdata:{x:30,y:20},
		test: 10,
		dosomething: function(){
			console.log("dosomething called on server")
			this.test = 40
			this.test = function(value){
				console.log("TEST ATTRIBUTE SET ON SERVEr")
			}
		}
	}),
	screen({
		name:'mobile',
		flowdata:{x:10,y:10},
		// make an exportable attribute to something internal
		pointerpos: wire('this.main.pos')
		},
		view({
			name:'main',
			size: vec2(200, 200),
			bgcolor: vec4('yellow'),
			is: draggable()
		})
	),
	screen({
		name:'remote',
		flowdata:{x:30,y:00},
		movepos: wire('this.rpc.mobile.pointerpos')
		},
		view({
			size: vec2(200, 200),
			pos: wire('this.screen.movepos'),
			bgcolor: 'red',
			init: function(){
				console.log("screen2", this.rpc.server.test)
			}
		})
	)
]}})
<commit_msg>Fix rpcremote<commit_after>/* DreemGL is a collaboration between Teeming Society & Samsung Electronics, sponsored by Samsung and others.
   Copyright 2015-2016 Teeming Society. Licensed under the Apache License, Version 2.0 (the "License"); You may not use this file except in compliance with the License.
   You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and limitations under the License.*/

//Pure JS based composition
define.class('$server/composition', function(
	$server$, service,
	$ui$, screen, view,
	$behaviors$, draggable){ this.render = function(){ return [

	service({
		name:'myservice',
		flowdata:{x:30,y:20},
		test: 10,
		dosomething: function(){
			console.log("dosomething called on server")
			this.test = 40
			this.test = function(value){
				console.log("TEST ATTRIBUTE SET ON SERVEr")
			}
		}
	}),
	screen({
		name:'mobile',
		flowdata:{x:10,y:10},
		// make an exportable attribute to something internal
		pointerpos: Config({type:vec2, value:wire('find.main.pos')})
		},
		view({
			name:'main',
			size: vec2(200, 200),
			bgcolor: vec4('yellow'),
			is: draggable()
		})
	),
	screen({
		name:'remote',
		flowdata:{x:30,y:00},
		movepos: Config({type:vec2,value:wire('this.rpc.mobile.pointerpos')})
		},
		view({
			size: vec2(200, 200),
			pos: wire('this.screen.movepos'),
			bgcolor: 'red',
			init: function(){
				console.log("screen2", this.rpc.myservice.test)
			}
		})
	)
]}})
<|endoftext|>


<commit_before>/*
 * Contains integration tests for IRC mode events.
 */
const Promise = require("bluebird");

const envBundle = require("../util/env-bundle");

describe("IRC-to-Matrix mode bridging", function() {

    const {env, config, roomMapping, test} = envBundle();

    let sdk = null;

    const tFromNick = "mike";
    const tUserId = "@" + roomMapping.server + "_" + tFromNick + ":" +
                  config.homeserver.domain;

    const configJoinRule = config.ircService.servers[
        roomMapping.server
    ].dynamicChannels.joinRule;

    beforeEach(test.coroutine(function*() {
        yield test.beforeEach(env);

        sdk = env.clientMock._client(config._botUserId);
        // add registration mock impl:
        // registering should be for the irc user
        sdk._onHttpRegister({
            expectLocalpart: roomMapping.server + "_" + tFromNick,
            returnUserId: tUserId
        });

        env.ircMock._autoJoinChannels(
            roomMapping.server, roomMapping.botNick, roomMapping.server
        );
        env.ircMock._autoConnectNetworks(
            roomMapping.server, roomMapping.botNick, roomMapping.server
        );

        // do the init
        yield test.initEnv(env);
    }));

    afterEach(test.coroutine(function*() {
        yield test.afterEach(env);
    }));

    it("should set join_rules to 'invite' on +k.", (done) => {
        sdk.sendStateEvent.and.callFake(function(roomId, type, content, key) {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: "invite"
            });
            expect(key).toEqual("");
            done();
            return Promise.resolve();
        });

        env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick).then((client) => {
            client.emit("+mode", roomMapping.channel, "anIrcUser", "k");
        });
    });

    it("should set join_rules to 'invite' on +i.", (done) => {
        sdk.sendStateEvent.and.callFake(function(roomId, type, content, key) {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: "invite"
            });
            expect(key).toEqual("");
            done();
            return Promise.resolve();
        });

        env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick).then((client) => {
            client.emit("+mode", roomMapping.channel, "anIrcUser", "i");
        });
    });

    it("should revert join_rules to config value on -i.", (done) => {
        sdk.sendStateEvent.and.callFake(function(roomId, type, content, key) {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: configJoinRule
            });
            expect(key).toEqual("");
            done();
            return Promise.resolve();
        });

        env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick).then((client) => {
            client.emit("-mode", roomMapping.channel, "anIrcUser", "i");
        });
    });

    it("should revert join_rules to config value on -k.", (done) => {
        sdk.sendStateEvent.and.callFake(function(roomId, type, content, key) {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: configJoinRule
            });
            expect(key).toEqual("");
            done();
            return Promise.resolve();
        });

        env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick).then((client) => {
            client.emit("-mode", roomMapping.channel, "anIrcUser", "k");
        });
    });
});
<commit_msg>Make irc-modes work under the new world.<commit_after>/*
 * Contains integration tests for IRC mode events.
 */
const envBundle = require("../util/env-bundle");

describe("IRC-to-Matrix mode bridging", () => {

    const {env, config, roomMapping, test} = envBundle();

    let sdk = null;

    const tFromNick = "mike";
    const tUserId = "@" + roomMapping.server + "_" + tFromNick + ":" +
                  config.homeserver.domain;

    const configJoinRule = config.ircService.servers[
        roomMapping.server
    ].dynamicChannels.joinRule;

    beforeEach(async () => {
        await test.beforeEach(env);
        const intent = env.clientMock._intent(config._botUserId);
        sdk = intent.underlyingClient;
        // add registration mock impl:
        // registering should be for the irc user
        intent._onHttpRegister({
            expectLocalpart: roomMapping.server + "_" + tFromNick,
            returnUserId: tUserId
        });

        env.ircMock._autoJoinChannels(
            roomMapping.server, roomMapping.botNick, roomMapping.server
        );
        env.ircMock._autoConnectNetworks(
            roomMapping.server, roomMapping.botNick, roomMapping.server
        );

        // do the init
        await test.initEnv(env);
    });

    afterEach(() => test.afterEach(env));

    it("should set join_rules to 'invite' on +k.", async (done) => {
        sdk.sendStateEvent.and.callFake((roomId, type, key, content) => {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: "invite"
            });
            expect(key).toEqual("");
            done();
        });

        const client = await env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick);
        client.emit("+mode", roomMapping.channel, "anIrcUser", "k");
    });

    it("should set join_rules to 'invite' on +i.", async (done) => {
        sdk.sendStateEvent.and.callFake((roomId, type, key, content) => {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: "invite"
            });
            expect(key).toEqual("");
            done();
        });

        const client = await env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick);
        client.emit("+mode", roomMapping.channel, "anIrcUser", "i");
    });

    it("should revert join_rules to config value on -i.", async (done) => {
        sdk.sendStateEvent.and.callFake(function(roomId, type, key, content) {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: configJoinRule
            });
            expect(key).toEqual("");
            done();
        });

        const client = await env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick);
        client.emit("-mode", roomMapping.channel, "anIrcUser", "i");
    });

    it("should revert join_rules to config value on -k.", async (done) => {
        sdk.sendStateEvent.and.callFake(function(roomId, type, key, content) {
            expect(roomId).toEqual(roomMapping.roomId);
            expect(type).toEqual("m.room.join_rules");
            expect(content).toEqual({
                join_rule: configJoinRule
            });
            expect(key).toEqual("");
            done();
        });

        const client = await env.ircMock._findClientAsync(roomMapping.server, roomMapping.botNick);
        client.emit("-mode", roomMapping.channel, "anIrcUser", "k");
    });
});
<|endoftext|>


<commit_before>'use babel';

import linter from '../index';

describe('The lesshint provider for Linter', () => {
    const lint = linter.provideLinter().lint;

    beforeEach(() => {
        waitsForPromise(() => {
            atom.packages.activatePackage('linter-lesshint');

            return atom.packages.activatePackage('language-less');
        });
    });

    describe('lesshint-breaking files checks', () => {
        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                return atom.workspace.open(`${__dirname}/fixtures/lesshint-breaker.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('fails file that breaks lesshint', () => {
            waitsForPromise(() => {
                const priorNotificationsCount = atom.notifications.getNotifications().length;

                return lint(editor).then(() => {
                    const notifications = atom.notifications.getNotifications();

                    expect(notifications[priorNotificationsCount].getType()).toEqual('error');
                    expect(notifications[priorNotificationsCount].getMessage()).toEqual("lesshint couldn't check this file.");
                });
            });
        });
    });

    describe('invalid files checks', () => {
        const Range = require('atom').Range;

        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                return atom.workspace.open(`${__dirname}/fixtures/invalid.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('fails file with errors', () => {
            const errorMessage = "There shouldn't be any empty rules present.";
            const errorName = 'emptyRule';

            waitsForPromise(() => {
                return lint(editor).then((messages) => {
                    expect(messages[0].severity).toEqual('warning');
                    expect(messages[0].description).toEqual(`**${errorName}** ${errorMessage}`);
                    expect(messages[0].location.file).toMatch(/.+invalid\.less$/);
                    expect(messages[0].location.position).toEqual(new Range([1, 0], [1, 4]));
                });
            });
        });
    });

    describe('valid file checks', () => {
        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                return atom.workspace.open(`${__dirname}/fixtures/valid.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('allows file without errors', () => {
            waitsForPromise(() => {
                return lint(editor).then((messages) => {
                    expect(messages.length).toEqual(0);
                });
            });
        });
    });

    describe('onlyWithRc setting', () => {
        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                atom.config.set('linter-lesshint.onlyWithRc', true);

                return atom.workspace.open(`${__dirname}/fixtures/invalid.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('should not check anything when "onlyWithRc" is true and no ".lesshintrc" is found', () => {
            waitsForPromise(() => {
                return lint(editor).then((messages) => {
                    expect(messages.length).toEqual(0);
                });
            });
        });
    });

    describe('globalConfig setting', () => {
        let editor;

        beforeEach(() => {
            atom.config.set('linter-lesshint.globalConfigDir', `${__dirname}/fixtures/lesshintrc`);
        });

        describe('valid file', () => {
            beforeEach(() => {
                waitsForPromise(() => {
                    return atom.workspace.open(`${__dirname}/fixtures/valid-global.less`).then((openEditor) => {
                        editor = openEditor;
                    });
                });
            });

            it('checks with global config when enabled', () => {
                atom.config.set('linter-lesshint.globalConfig', true);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(0);
                    });
                });
            });

            it('does not check with global config when disabled', () => {
                atom.config.set('linter-lesshint.globalConfig', false);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(1);
                    });
                });
            });
        });

        describe('invalid file', () => {
            beforeEach(() => {
                waitsForPromise(() => {
                    return atom.workspace.open(`${__dirname}/fixtures/invalid-global.less`).then((openEditor) => {
                        editor = openEditor;
                    });
                });
            });

            it('checks with global config when enabled', () => {
                atom.config.set('linter-lesshint.globalConfig', true);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(1);
                    });
                });
            });

            it('does not check with global config when disabled', () => {
                atom.config.set('linter-lesshint.globalConfig', false);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(0);
                    });
                });
            });
        });
    });
});
<commit_msg>Correct tests<commit_after>'use babel';

import linter from '../index';

describe('The lesshint provider for Linter', () => {
    const lint = linter.provideLinter().lint;

    beforeEach(() => {
        waitsForPromise(() => {
            atom.packages.activatePackage('linter-lesshint');

            return atom.packages.activatePackage('language-less');
        });
    });

    describe('lesshint-breaking files checks', () => {
        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                return atom.workspace.open(`${__dirname}/fixtures/lesshint-breaker.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('fails file that breaks lesshint', () => {
            waitsForPromise(() => {
                const priorNotificationsCount = atom.notifications.getNotifications().length;

                return lint(editor).then(() => {
                    const notifications = atom.notifications.getNotifications();

                    expect(notifications[priorNotificationsCount].getType()).toEqual('error');
                    expect(notifications[priorNotificationsCount].getMessage()).toEqual("lesshint couldn't check this file.");
                });
            });
        });
    });

    describe('invalid files checks', () => {
        const Range = require('atom').Range;

        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                return atom.workspace.open(`${__dirname}/fixtures/invalid.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('fails file with errors', () => {
            const errorMessage = "There shouldn't be any empty rules present.";
            const errorName = 'emptyRule';

            waitsForPromise(() => {
                return lint(editor).then((messages) => {
                    expect(messages[0].severity).toEqual('warning');
                    expect(messages[0].excerpt).toEqual(`${errorName}: ${errorMessage}`);
                    expect(messages[0].location.file).toMatch(/.+invalid\.less$/);
                    expect(messages[0].location.position).toEqual(new Range([1, 0], [1, 4]));
                });
            });
        });
    });

    describe('valid file checks', () => {
        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                return atom.workspace.open(`${__dirname}/fixtures/valid.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('allows file without errors', () => {
            waitsForPromise(() => {
                return lint(editor).then((messages) => {
                    expect(messages.length).toEqual(0);
                });
            });
        });
    });

    describe('onlyWithRc setting', () => {
        let editor;

        beforeEach(() => {
            waitsForPromise(() => {
                atom.config.set('linter-lesshint.onlyWithRc', true);

                return atom.workspace.open(`${__dirname}/fixtures/invalid.less`).then((openEditor) => {
                    editor = openEditor;
                });
            });
        });

        it('should not check anything when "onlyWithRc" is true and no ".lesshintrc" is found', () => {
            waitsForPromise(() => {
                return lint(editor).then((messages) => {
                    expect(messages.length).toEqual(0);
                });
            });
        });
    });

    describe('globalConfig setting', () => {
        let editor;

        beforeEach(() => {
            atom.config.set('linter-lesshint.globalConfigDir', `${__dirname}/fixtures/lesshintrc`);
        });

        describe('valid file', () => {
            beforeEach(() => {
                waitsForPromise(() => {
                    return atom.workspace.open(`${__dirname}/fixtures/valid-global.less`).then((openEditor) => {
                        editor = openEditor;
                    });
                });
            });

            it('checks with global config when enabled', () => {
                atom.config.set('linter-lesshint.globalConfig', true);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(0);
                    });
                });
            });

            it('does not check with global config when disabled', () => {
                atom.config.set('linter-lesshint.globalConfig', false);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(1);
                    });
                });
            });
        });

        describe('invalid file', () => {
            beforeEach(() => {
                waitsForPromise(() => {
                    return atom.workspace.open(`${__dirname}/fixtures/invalid-global.less`).then((openEditor) => {
                        editor = openEditor;
                    });
                });
            });

            it('checks with global config when enabled', () => {
                atom.config.set('linter-lesshint.globalConfig', true);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(1);
                    });
                });
            });

            it('does not check with global config when disabled', () => {
                atom.config.set('linter-lesshint.globalConfig', false);

                waitsForPromise(() => {
                    return lint(editor).then((messages) => {
                        expect(messages.length).toEqual(0);
                    });
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>var YouTubePlayer = require('youtube-player');

var player = YouTubePlayer('youtube-player', {
  autoPlay: true,
  preferredQuality: 'default',
  allowFullScreen: 'true',
  videoId: window.initVid
});

player.on('ready', function(_event) {
  player.playVideo();
});

function playNextVid() {
  fetch('./api/getrandomvid').then(function(response) {
    return response.json();
  }).then(function(vid) {
    player.loadVideoById(vid.vidID);
    player.playVideo();
  }).catch(function(error) {
    console.error(error);
  });
}

document.getElementById('playerbutton').onclick = playNextVid;
<commit_msg>Autoplay next video<commit_after>var YouTubePlayer = require('youtube-player');

var player = YouTubePlayer('youtube-player', {
  autoPlay: true,
  preferredQuality: 'default',
  allowFullScreen: 'true',
  videoId: window.initVid
});

player.on('ready', function(_event) {
  player.playVideo();
});

player.on('stateChange', function(event) {
  // If video ended
  if(event.data === 0) {
    playNextVid();
  }
});

function playNextVid() {
  fetch('./api/getrandomvid').then(function(response) {
    return response.json();
  }).then(function(vid) {
    player.loadVideoById(vid.vidID);
    player.playVideo();
  }).catch(function(error) {
    console.error(error);
  });
}

document.getElementById('playerbutton').onclick = playNextVid;
<|endoftext|>


<commit_before>var buster         = require('buster')
  , RequestHandler = require(__dirname + '/../lib/request-handler.js')
  , exec           = require('child_process').exec

buster.spec.expose()
buster.testRunner.timeout = 10000

describe('RequestHandler', function() {
  before(function() {
    this.handler = new RequestHandler({})
  })

  describe('getImageProcessUrlMatch', function() {
    describe('without namespace', function() {
      it("returns a match array for valid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/resize/123/foo.jpg" })).toBeDefined()
      })

      it("returns no match array for invalid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/foo/123/foo.jpg" })).toBeNull()
      })
    })

    describe('with namespacing', function() {
      before(function() {
        this.handler = new RequestHandler({ namespace: 'foo' })
      })

      it("returns a match array for valid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/foo/resize/123/foo.jpg" })).toBeDefined()
      })

      it("returns no match array for invalid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/foo/bar/123/foo.jpg" })).toBeNull()
      })
    })
  })

  describe("isImageProcessUrl", function() {
    describe('without namespace', function() {
      it('returns a match array for valid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/resize/123/foo.jpg" })).toBeDefined()
      })

      it('returns no match array for invalid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/foo/123/foo.jpg" })).toBeFalsy()
      })
    })

    describe('with namespace', function() {
      before(function() {
        this.handler = new RequestHandler({ namespace: 'foo' })
      })

      it('returns a match array for valid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/foo/resize/123/foo.jpg" })).toBeDefined()
      })

      it('returns no match array for invalid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/foo/bar/123/foo.jpg" })).toBeFalsy()
      })
    })
  })

  describe('isImageSourceHostAllowed', function() {
    describe('with allowedHosts', function() {
      before(function() {
        this.handler = new RequestHandler({
          'whitelist': { 'allowedHosts': [/^.*\.example\.com$/] }
        })
      })

      it('returns true if image source is allowed', function() {
        var req = { query: {url: 'http://www.example.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostAllowed(req)).toBeDefined()
      })

      it('returns false if image source is not allowed', function() {
        var req = { query: {url: 'http://www.google.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostAllowed(req)).toBeFalsy()
      })
    })

    describe('without allowedHosts', function() {
      it("returns true for every url", function() {
        var req1 = { query: {url: 'http://www.google.com/foo.jpg'} }
          , req2 = { query: {url: 'http://www.example.com/foo.jpg'} }

        expect(this.handler.isImageSourceHostAllowed(req1)).toBeTruthy()
        expect(this.handler.isImageSourceHostAllowed(req2)).toBeTruthy()
      })
    })
  })

  describe('isImageSourceHostTrusted', function() {
    describe('with trustedHosts', function() {
      before(function() {
        this.handler = new RequestHandler({
          'whitelist': { 'trustedHosts': [/^.*\.example\.com$/] }
        })
      })

      it('returns true if image source is trusted', function() {
        var req = { query: {url: 'http://www.example.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeTruthy()
      })

      it('returns false if image source is not trusted', function() {
        var req = { query: {url: 'http://www.google.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeFalsy()
      })
    })

    describe('with trustedHosts as string', function() {
      before(function() {
        this.handler = new RequestHandler({
          'whitelist': {'trustedHosts': ["^.*\.example\.com$"]}
        })
      })

      it('returns true if image source is trusted', function() {
        var req = { query: {url: 'http://www.example.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeTruthy()
      })

      it('returns false if image source is not trusted', function() {
        var req = { query: {url: 'http://www.google.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeFalsy()
      })
    })

    describe('without trustedHosts', function() {
      it('returns false for every url', function() {
        var req1 = { query: {url: 'http://www.google.com/foo.jpg'} }
          , req2 = { query: {url: 'http://www.example.com/foo.jpg'} }

        expect(this.handler.isImageSourceHostTrusted(req1)).toBeFalsy()
        expect(this.handler.isImageSourceHostTrusted(req2)).toBeFalsy()
      })
    })
  })

  describe('_isValidHash', function() {
    before(function() {
      this.handler = new RequestHandler({
        secret:       "my-very-secret-secret",
        magicHash:    "magic",
        whitelist: { trustedHosts: [/^.*\.google\.com$/] }
      })
    })

    it('returns true for the magic hash', function() {
      var imgUrl = encodeURIComponent("http://www.example.com/intl/en_ALL/images/logo.gif")
        , hash   = this.handler.config.magicHash
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })

    it('returns true for the correct hash', function() {
      var imgUrl = encodeURIComponent("http://www.example.com/intl/en_ALL/images/logo.gif")
        , hash   = this.handler.utils.hash("url=" + imgUrl)
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })

    it('returns false for the incorrect hash', function() {
      var imgUrl = encodeURIComponent("http://www.example.com/intl/en_ALL/images/logo.gif")
        , hash   = "xxx"
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeFalsy()
    })

    it('returns true for trusted hosts', function() {
      var imgUrl = encodeURIComponent("http://www.google.com/intl/en_ALL/images/logo.gif")
        , hash   = "xxx"
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })

    it('returns true for trusted hosts without hash', function() {
      var imgUrl = encodeURIComponent("http://www.google.com/intl/en_ALL/images/logo.gif")
        , reqUrl = "http://host.com/resize/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })
  })

  describe('_afterResize', function() {
    before(function() {
      this.res = {
        send: function() {},
        contentType: function() {},
        sendfile: function(path, options, callback) { callback && callback() }
      }
    })

    it("returns a 500 if an error has occurred", function() {
      var mock = this.mock(this.res).expects('send').withArgs(500).once()

      new RequestHandler()._afterResize(new Error('barfooz'), null, this.res)

      mock.verify()
    })

    it("calls deleteTempfile if the option keepDownloads is false or not defined", function() {
      var handler = new RequestHandler()
        , path    = 'foo'
        , mock    = this.mock(handler).expects('deleteTempfile').withArgs(path).once()

      handler._afterResize(null, path, this.res)

      mock.verify()
    })

    it("doesn't call deleteTempfile if the option keepDownloads is false or not defined", function() {
      var handler = new RequestHandler({ keepDownloads: true })
        , path    = 'foo'
        , mock    = this.mock(handler).expects('deleteTempfile').withArgs(path).never()

      handler._afterResize(null, path, this.res)

      mock.verify()
    })

    it("checks the amount of used hdd space if the option keepDownloads is true and maxDownloadCacheSize is defiend", function() {
      var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000 })
        , path    = 'foo'
        , mock    = this.mock(handler).expects('checkDownloadCacheSize').once()

      handler._afterResize(null, path, this.res)

      mock.verify()
    })
  })

  describe('checkDownloadCacheSize', function() {
    it("deletes old tempfiles if the amount of used hdd space is greater than the defined maxDownloadCacheSize", function(done) {
      var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000 })
        , mock    = this.mock(handler).expects('_deleteOldDownloads').once().callsArg(0)

      this.stub(handler, '_getTempFolderSize', function(callback) { callback(1100) })

      handler.checkDownloadCacheSize(done)

      mock.verify()
    })

    it("deletes the files returned by _getOldTempFiles", function(done) {
      var files = ['a.txt', 'b.txt', 'c.txt'].map(function(f) { return __dirname + '/tmp/' + f })

      exec(files.map(function(f) { return 'touch ' + f }).join(";"), function(err) {
        var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000 })

        this.stub(handler, '_getTempFolderSize', function(callback) { callback(1100) })
        this.stub(handler, '_getOldTempFiles', function(callback) { callback(files) })

        handler.checkDownloadCacheSize(function() {
          exec('ls -ila ' + __dirname + '/tmp', function(err, stdout, stderr) {
            files.forEach(function(f) {
              expect(stdout).not.toMatch(f)
            })

            done()
          })
        })
      }.bind(this))
    })
  })

  describe('_getOldTempFiles', function() {
    it('returns one fifth of all available files', function(done) {
      var tmpPathRoot = __dirname + '/tmp/oldTempFileTest'
        , commands    = [
            'mkdir -p ' + tmpPathRoot,
            'touch ' + tmpPathRoot + '/1.txt',
            'touch ' + tmpPathRoot + '/2.txt',
            'touch ' + tmpPathRoot + '/3.txt',
            'touch ' + tmpPathRoot + '/4.txt',
            'touch ' + tmpPathRoot + '/5.txt'
          ]

      exec(commands.join(';'), function() {
        var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000, tmpPathRoot: tmpPathRoot })

        handler._getOldTempFiles(function(files) {
          expect(files).toEqual([ tmpPathRoot + '/1.txt' ])
          done()
        }.bind(this))
      }.bind(this))
    })
  })

  describe('_getTempFolderSize', function() {
    before(function() {
      this.tmpPathRoot = __dirname + '/tmp/oldTempFileTest' + (~~Math.random() * 9999)
      this.handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000, tmpPathRoot: this.tmpPathRoot })
    })

    it("returns 0 if the folder has less than 1mb of content", function(done) {
      this.handler._getTempFolderSize(function(size) {
        expect(size).toEqual(0)
        done()
      })
    })

    it("returns 1 if the folder has slightly more than 1mb of content", function(done) {
      exec('dd if=/dev/zero of=' + this.tmpPathRoot + '/big.file bs=1024 count=1024 conv=notrunc', function() {
        this.handler._getTempFolderSize(function(size) {
          expect(size).toEqual(1)
          done()
        })
      }.bind(this))

    })
  })
})
<commit_msg>random tmp folder<commit_after>var buster         = require('buster')
  , RequestHandler = require(__dirname + '/../lib/request-handler.js')
  , exec           = require('child_process').exec

buster.spec.expose()
buster.testRunner.timeout = 10000

describe('RequestHandler', function() {
  before(function() {
    this.handler = new RequestHandler({})
  })

  describe('getImageProcessUrlMatch', function() {
    describe('without namespace', function() {
      it("returns a match array for valid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/resize/123/foo.jpg" })).toBeDefined()
      })

      it("returns no match array for invalid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/foo/123/foo.jpg" })).toBeNull()
      })
    })

    describe('with namespacing', function() {
      before(function() {
        this.handler = new RequestHandler({ namespace: 'foo' })
      })

      it("returns a match array for valid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/foo/resize/123/foo.jpg" })).toBeDefined()
      })

      it("returns no match array for invalid urls", function() {
        expect(this.handler.getImageProcessUrlMatch({ originalUrl: "/foo/bar/123/foo.jpg" })).toBeNull()
      })
    })
  })

  describe("isImageProcessUrl", function() {
    describe('without namespace', function() {
      it('returns a match array for valid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/resize/123/foo.jpg" })).toBeDefined()
      })

      it('returns no match array for invalid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/foo/123/foo.jpg" })).toBeFalsy()
      })
    })

    describe('with namespace', function() {
      before(function() {
        this.handler = new RequestHandler({ namespace: 'foo' })
      })

      it('returns a match array for valid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/foo/resize/123/foo.jpg" })).toBeDefined()
      })

      it('returns no match array for invalid urls', function() {
        expect(this.handler.isImageProcessUrl({ originalUrl: "/foo/bar/123/foo.jpg" })).toBeFalsy()
      })
    })
  })

  describe('isImageSourceHostAllowed', function() {
    describe('with allowedHosts', function() {
      before(function() {
        this.handler = new RequestHandler({
          'whitelist': { 'allowedHosts': [/^.*\.example\.com$/] }
        })
      })

      it('returns true if image source is allowed', function() {
        var req = { query: {url: 'http://www.example.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostAllowed(req)).toBeDefined()
      })

      it('returns false if image source is not allowed', function() {
        var req = { query: {url: 'http://www.google.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostAllowed(req)).toBeFalsy()
      })
    })

    describe('without allowedHosts', function() {
      it("returns true for every url", function() {
        var req1 = { query: {url: 'http://www.google.com/foo.jpg'} }
          , req2 = { query: {url: 'http://www.example.com/foo.jpg'} }

        expect(this.handler.isImageSourceHostAllowed(req1)).toBeTruthy()
        expect(this.handler.isImageSourceHostAllowed(req2)).toBeTruthy()
      })
    })
  })

  describe('isImageSourceHostTrusted', function() {
    describe('with trustedHosts', function() {
      before(function() {
        this.handler = new RequestHandler({
          'whitelist': { 'trustedHosts': [/^.*\.example\.com$/] }
        })
      })

      it('returns true if image source is trusted', function() {
        var req = { query: {url: 'http://www.example.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeTruthy()
      })

      it('returns false if image source is not trusted', function() {
        var req = { query: {url: 'http://www.google.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeFalsy()
      })
    })

    describe('with trustedHosts as string', function() {
      before(function() {
        this.handler = new RequestHandler({
          'whitelist': {'trustedHosts': ["^.*\.example\.com$"]}
        })
      })

      it('returns true if image source is trusted', function() {
        var req = { query: {url: 'http://www.example.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeTruthy()
      })

      it('returns false if image source is not trusted', function() {
        var req = { query: {url: 'http://www.google.com/foo.jpg'} }
        expect(this.handler.isImageSourceHostTrusted(req)).toBeFalsy()
      })
    })

    describe('without trustedHosts', function() {
      it('returns false for every url', function() {
        var req1 = { query: {url: 'http://www.google.com/foo.jpg'} }
          , req2 = { query: {url: 'http://www.example.com/foo.jpg'} }

        expect(this.handler.isImageSourceHostTrusted(req1)).toBeFalsy()
        expect(this.handler.isImageSourceHostTrusted(req2)).toBeFalsy()
      })
    })
  })

  describe('_isValidHash', function() {
    before(function() {
      this.handler = new RequestHandler({
        secret:       "my-very-secret-secret",
        magicHash:    "magic",
        whitelist: { trustedHosts: [/^.*\.google\.com$/] }
      })
    })

    it('returns true for the magic hash', function() {
      var imgUrl = encodeURIComponent("http://www.example.com/intl/en_ALL/images/logo.gif")
        , hash   = this.handler.config.magicHash
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })

    it('returns true for the correct hash', function() {
      var imgUrl = encodeURIComponent("http://www.example.com/intl/en_ALL/images/logo.gif")
        , hash   = this.handler.utils.hash("url=" + imgUrl)
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })

    it('returns false for the incorrect hash', function() {
      var imgUrl = encodeURIComponent("http://www.example.com/intl/en_ALL/images/logo.gif")
        , hash   = "xxx"
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeFalsy()
    })

    it('returns true for trusted hosts', function() {
      var imgUrl = encodeURIComponent("http://www.google.com/intl/en_ALL/images/logo.gif")
        , hash   = "xxx"
        , reqUrl = "http://host.com/resize/" + hash + "/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })

    it('returns true for trusted hosts without hash', function() {
      var imgUrl = encodeURIComponent("http://www.google.com/intl/en_ALL/images/logo.gif")
        , reqUrl = "http://host.com/resize/foo.jpg?url=" + imgUrl
        , parsed = require("url").parse(reqUrl, true)
        , req    = { originalUrl: parsed.pathname + parsed.search, query: parsed.query }

      expect(this.handler._isValidHash(req)).toBeTruthy()
    })
  })

  describe('_afterResize', function() {
    before(function() {
      this.res = {
        send: function() {},
        contentType: function() {},
        sendfile: function(path, options, callback) { callback && callback() }
      }
    })

    it("returns a 500 if an error has occurred", function() {
      var mock = this.mock(this.res).expects('send').withArgs(500).once()

      new RequestHandler()._afterResize(new Error('barfooz'), null, this.res)

      mock.verify()
    })

    it("calls deleteTempfile if the option keepDownloads is false or not defined", function() {
      var handler = new RequestHandler()
        , path    = 'foo'
        , mock    = this.mock(handler).expects('deleteTempfile').withArgs(path).once()

      handler._afterResize(null, path, this.res)

      mock.verify()
    })

    it("doesn't call deleteTempfile if the option keepDownloads is false or not defined", function() {
      var handler = new RequestHandler({ keepDownloads: true })
        , path    = 'foo'
        , mock    = this.mock(handler).expects('deleteTempfile').withArgs(path).never()

      handler._afterResize(null, path, this.res)

      mock.verify()
    })

    it("checks the amount of used hdd space if the option keepDownloads is true and maxDownloadCacheSize is defiend", function() {
      var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000 })
        , path    = 'foo'
        , mock    = this.mock(handler).expects('checkDownloadCacheSize').once()

      handler._afterResize(null, path, this.res)

      mock.verify()
    })
  })

  describe('checkDownloadCacheSize', function() {
    it("deletes old tempfiles if the amount of used hdd space is greater than the defined maxDownloadCacheSize", function(done) {
      var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000 })
        , mock    = this.mock(handler).expects('_deleteOldDownloads').once().callsArg(0)

      this.stub(handler, '_getTempFolderSize', function(callback) { callback(1100) })

      handler.checkDownloadCacheSize(done)

      mock.verify()
    })

    it("deletes the files returned by _getOldTempFiles", function(done) {
      var files = ['a.txt', 'b.txt', 'c.txt'].map(function(f) { return __dirname + '/tmp/' + f })

      exec(files.map(function(f) { return 'touch ' + f }).join(";"), function(err) {
        var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000 })

        this.stub(handler, '_getTempFolderSize', function(callback) { callback(1100) })
        this.stub(handler, '_getOldTempFiles', function(callback) { callback(files) })

        handler.checkDownloadCacheSize(function() {
          exec('ls -ila ' + __dirname + '/tmp', function(err, stdout, stderr) {
            files.forEach(function(f) {
              expect(stdout).not.toMatch(f)
            })

            done()
          })
        })
      }.bind(this))
    })
  })

  describe('_getOldTempFiles', function() {
    it('returns one fifth of all available files', function(done) {
      var tmpPathRoot = __dirname + '/tmp/oldTempFileTest' + (~~Math.random() * 9999)
        , commands    = [
            'mkdir -p ' + tmpPathRoot,
            'touch ' + tmpPathRoot + '/1.txt',
            'touch ' + tmpPathRoot + '/2.txt',
            'touch ' + tmpPathRoot + '/3.txt',
            'touch ' + tmpPathRoot + '/4.txt',
            'touch ' + tmpPathRoot + '/5.txt'
          ]

      exec(commands.join(';'), function() {
        var handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000, tmpPathRoot: tmpPathRoot })

        handler._getOldTempFiles(function(files) {
          expect(files).toEqual([ tmpPathRoot + '/1.txt' ])
          done()
        }.bind(this))
      }.bind(this))
    })
  })

  describe('_getTempFolderSize', function() {
    before(function() {
      this.tmpPathRoot = __dirname + '/tmp/oldTempFileTest' + (~~Math.random() * 9999)
      this.handler = new RequestHandler({ keepDownloads: true, maxDownloadCacheSize: 1000, tmpPathRoot: this.tmpPathRoot })
    })

    it("returns 0 if the folder has less than 1mb of content", function(done) {
      this.handler._getTempFolderSize(function(size) {
        expect(size).toEqual(0)
        done()
      })
    })

    it("returns 1 if the folder has slightly more than 1mb of content", function(done) {
      exec('dd if=/dev/zero of=' + this.tmpPathRoot + '/big.file bs=1024 count=1024 conv=notrunc', function() {
        this.handler._getTempFolderSize(function(size) {
          expect(size).toEqual(1)
          done()
        })
      }.bind(this))

    })
  })
})
<|endoftext|>


<commit_before>describe("Screens", function() {
  var ScreensService = require('../../src/services/screens.js');
  var log, settings, s;

  beforeEach(function() {
    log = {
      info: function() {
      }
    };

    settings = {
      get: function(value) {
        return {};
      },
      set: function(value){
      }
    };

    spyOn(settings, 'set');

    s = new ScreensService(settings, log);
  });

  describe("parseScreen()", function(){
    it("should return empty object on empty string", function() {
      expect(s.parseScreen('')).toBeFalsy();
    });

    it("should parse screen number", function() {
      var parsed = {
        number: '778',
      };
      expect(s.parseScreen('778iddqd')).toEqual(parsed);
    });

    it("should parse Display Image File control", function() {
      var parsed = {
        number: '000',
        clear_screen: true,
        display_image_files_control: true,
        image_file: 'PIC000.jpg',
      };
      expect(s.parseScreen('000\x0c\x1bPEPIC000.jpg\x1b\x5c')).toEqual(parsed);
    });
  });

  describe("addScreen()", function(){
    it("should not add invalid screen", function() {
      expect(s.addScreen('')).toBeFalsy();
      expect(settings.set).not.toHaveBeenCalled();
    });

    it("should add valid screen", function() {
      expect(s.addScreen('000\x0c\x1bPEPIC000.jpg\x1b\x5c')).toBeTruthy();
      expect(settings.set).toHaveBeenCalled();
    });
  });

  describe("add()", function(){
    it("should not add screens", function() {
      screens = [];
      expect(s.add(screens)).toBeTruthy();
    });
  });

});
<commit_msg>added should parse Screen Blinking and Colour control<commit_after>describe("Screens", function() {
  var ScreensService = require('../../src/services/screens.js');
  var log, settings, s;

  beforeEach(function() {
    log = {
      info: function() {
      }
    };

    settings = {
      get: function(value) {
        return {};
      },
      set: function(value){
      }
    };

    spyOn(settings, 'set');

    s = new ScreensService(settings, log);
  });

  describe("parseScreen()", function(){
    it("should return empty object on empty string", function() {
      expect(s.parseScreen('')).toBeFalsy();
    });

    it("should parse screen number", function() {
      var parsed = {
        number: '778',
      };
      expect(s.parseScreen('778iddqd')).toEqual(parsed);
    });

    it("should parse Display Image File control", function() {
      var parsed = {
        number: '000',
        clear_screen: true,
        display_image_files_control: true,
        image_file: 'PIC000.jpg',
      };
      expect(s.parseScreen('000\x0c\x1bPEPIC000.jpg\x1b\x5c')).toEqual(parsed);
    });

    it("should parse Screen Blinking and Colour control", function() {
      var parsed = {
        number: '039',
        clear_screen: true,
        display_image_files_control: true,
        image_file: 'PIC039.jpg',
      };
      expect(s.parseScreen('039\x0c\x1bPEPIC039.jpg\x1b\x5c\x1b[27;80m')).toEqual(parsed);
    });
  });

  describe("addScreen()", function(){
    it("should not add invalid screen", function() {
      expect(s.addScreen('')).toBeFalsy();
      expect(settings.set).not.toHaveBeenCalled();
    });

    it("should add valid screen", function() {
      expect(s.addScreen('000\x0c\x1bPEPIC000.jpg\x1b\x5c')).toBeTruthy();
      expect(settings.set).toHaveBeenCalled();
    });
  });

  describe("add()", function(){
    it("should not add screens", function() {
      screens = [];
      expect(s.add(screens)).toBeTruthy();
    });
  });

});
<|endoftext|>