<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

'use strict';

var async = require('async');
var parseArgs = require('minimist');

var grpc = require('..');
var testProto = grpc.load(__dirname + '/../interop/test.proto').grpc.testing;
var interop_server = require('../interop/interop_server.js');

function runTest(concurrent, seconds, callback) {
  var testServer = interop_server.getServer(0, false);
  testServer.server.listen();
  var client = new testProto.TestService('localhost:' + testServer.port);

  var warmup_num = 100;

  async.waterfall([
    function warmUp(callback) {
      var pending = warmup_num;
      function startCall() {
        client.emptyCall({}, function(err, resp) {
          pending--;
          if (pending === 0) {
            callback(null);
          }
        });
      }
      for (var i = 0; i < warmup_num; i++) {
        startCall();
      }
    }, function run(callback) {
      var running = 0;
      var count = 0;
      var start = process.hrtime();
      function responseCallback(err, resp) {
        if (process.hrtime(start)[0] < seconds) {
          count += 1;
          client.emptyCall({}, responseCallback);
        } else {
          running -= 1;
          if (running <= 0) {
            callback(null, count);
          }
        }
      }
      for (var i = 0; i < concurrent; i++) {
        running += 1;
        client.emptyCall({}, responseCallback);
      }
    }], function(err, count) {
      testServer.server.shutdown();
      callback(err, count);
    });
}

if (require.main === module) {
  var argv = parseArgs(process.argv.slice(2), {
    default: {'concurrent': 100,
              'time': 10}
  });
  runTest(argv.concurrent, argv.time, function(err, count) {
    if (err) {
      throw err;
    }
    console.log('Concurrent calls:', argv.concurrent);
    console.log('Time:', argv.time, 'seconds');
    console.log('QPS:', (count/argv.time));
  });
}
<commit_msg>Added requested comments<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/**
 * This script runs a QPS test. It sends requests for a specified length of time
 * with a specified number pending at any one time. It then outputs the measured
 * QPS. Usage:
 * node qps_test.js [--concurrent=count] [--time=seconds]
 * concurrent defaults to 100 and time defaults to 10
 */

'use strict';

var async = require('async');
var parseArgs = require('minimist');

var grpc = require('..');
var testProto = grpc.load(__dirname + '/../interop/test.proto').grpc.testing;
var interop_server = require('../interop/interop_server.js');

/**
 * Runs the QPS test. Sends requests constantly for the given number of seconds,
 * and keeps concurrent_calls requests pending at all times. When the test ends,
 * the callback is called with the number of calls that completed within the
 * time limit.
 * @param {number} concurrent_calls The number of calls to have pending
 *     simultaneously
 * @param {number} seconds The number of seconds to run the test for
 * @param {function(Error, number)} callback Callback for test completion
 */
function runTest(concurrent_calls, seconds, callback) {
  var testServer = interop_server.getServer(0, false);
  testServer.server.listen();
  var client = new testProto.TestService('localhost:' + testServer.port);

  var warmup_num = 100;

  /**
   * Warms up the client to avoid counting startup time in the test result
   * @param {function(Error)} callback Called when warmup is complete
   */
  function warmUp(callback) {
    var pending = warmup_num;
    function startCall() {
      client.emptyCall({}, function(err, resp) {
        if (err) {
          callback(err);
          return;
        }
        pending--;
        if (pending === 0) {
          callback(null);
        }
      });
    }
    for (var i = 0; i < warmup_num; i++) {
      startCall();
    }
  }
  /**
   * Run the QPS test. Starts concurrent_calls requests, then starts a new
   * request whenever one completes until time runs out.
   * @param {function(Error, number)} callback Called when the test is complete.
   *     The second argument is the number of calls that finished within the
   *     time limit
   */
  function run(callback) {
    var running = 0;
    var count = 0;
    var start = process.hrtime();
    function responseCallback(err, resp) {
      if (process.hrtime(start)[0] < seconds) {
        count += 1;
        client.emptyCall({}, responseCallback);
      } else {
        running -= 1;
        if (running <= 0) {
          callback(null, count);
        }
      }
    }
    for (var i = 0; i < concurrent_calls; i++) {
      running += 1;
      client.emptyCall({}, responseCallback);
    }
  }
  async.waterfall([warmUp, run], function(err, count) {
      testServer.server.shutdown();
      callback(err, count);
    });
}

if (require.main === module) {
  var argv = parseArgs(process.argv.slice(2), {
    default: {'concurrent': 100,
              'time': 10}
  });
  runTest(argv.concurrent, argv.time, function(err, count) {
    if (err) {
      throw err;
    }
    console.log('Concurrent calls:', argv.concurrent);
    console.log('Time:', argv.time, 'seconds');
    console.log('QPS:', (count/argv.time));
  });
}
<|endoftext|>


<commit_before>const fs = require('fs');
const AnsiColor = require('./util/ansi_color_codes.js');
const LogMessageBuilder = require('./util/log_message_builder');
const mkdirpSync = require('mkdirp').sync;
const path = require('path');

const LOG_FILE_PREFIX = 'log_';

function addPrecedingZero(timeString) {
  if (timeString.length === 1) {
    return `0${timeString}`;
  }
  return timeString;
}

function createTimestamp() {
  let now = new Date();
  let year = now.getFullYear().toString();
  let month = (now.getMonth() + 1).toString();
  let day = now.getDate().toString();
  let hour = now.getHours().toString();
  let minute = now.getMinutes().toString();
  let second = now.getSeconds().toString();
  hour = addPrecedingZero(hour);
  minute = addPrecedingZero(minute);
  second = addPrecedingZero(second);
  return `[${month}/${day}/${year} ${hour}:${minute}:${second}]`;
}

/**
 * Log events to the console and to the log file.
 * The Logger can be
 * accessed via {@link Monochrome~getLogger}.
 * @hideconstructor
 */
class Logger {
  constructor(logDirectoryPath, useAnsiColorsInLogFile, consoleOverride) {
    this.console_ = consoleOverride || console;
    this.closed_ = false;
    this.logToFile_ = !!logDirectoryPath;
    this.userAnsiColorsInLogFile_ = !!useAnsiColorsInLogFile;

    if (this.logToFile_) {
      try {
        mkdirpSync(logDirectoryPath);
      } catch (err) {
        this.console_.warn(`Error creating log directory: ${err}. Disabling logging to file.`);
        this.logToFile_ = false;
      }

      let logFilePath = path.join(logDirectoryPath, `${LOG_FILE_PREFIX}${new Date().toISOString()}.log`);
      this.fileStream_ = fs.createWriteStream(logFilePath);
      this.fileStream_.on('error', (err) => {
        this.logToFile_ = false;
        this.logFailure(LOGGER_TITLE, 'Error logging to file. Disabling logging to file.', err);
      });
    }
  }

  logInputReaction(title, msg, inputReactorTitle, succeeded, failureMessage) {
    let turnAroundTimeMs = Date.now() - msg.timestamp;
    let logMessageBuilder = new LogMessageBuilder();
    logMessageBuilder.setColor(AnsiColor.YELLOW);
    if (msg.channel.guild) {
      logMessageBuilder.append(msg.channel.guild.name);
      logMessageBuilder.setColor(AnsiColor.RESET);
      logMessageBuilder.append(' >> ');
      logMessageBuilder.setColor(AnsiColor.YELLOW);
      logMessageBuilder.append(msg.channel.name);
      logMessageBuilder.setColor(AnsiColor.RESET);
      logMessageBuilder.append(' >> ');
    }
    logMessageBuilder.setColor(AnsiColor.BLUE);
    logMessageBuilder.append(msg.author.username);
    logMessageBuilder.append('#');
    logMessageBuilder.append(msg.author.discriminator);
    logMessageBuilder.setColor(AnsiColor.RESET);
    logMessageBuilder.append(' >> ');
    if (inputReactorTitle) {
      logMessageBuilder.append(`[${inputReactorTitle}]`);
      logMessageBuilder.append(' ');
    }
    logMessageBuilder.setColor(AnsiColor.MAGENTA);
    logMessageBuilder.append(msg.content);

    if (succeeded) {
      logMessageBuilder.setColor(AnsiColor.RESET);
      logMessageBuilder.append(' ');
      logMessageBuilder.append(`(${turnAroundTimeMs}ms turnaround)`);
    }

    if (succeeded) {
      this.logSuccess(title, logMessageBuilder);
    } else {
      if (failureMessage) {
        logMessageBuilder.setColor(AnsiColor.RED);
        logMessageBuilder.append(' ');
        logMessageBuilder.append(`FAILED (${failureMessage})`);
      }
      this.logFailure(title, logMessageBuilder);
    }
  }

  /**
   * Log a message with a successful green color.
   * @param {string} title - The title of the message to log.
   * @param {string} message - The body of the message to log.
   */
  logSuccess(title, message) {
    this.checkState_();
    this.logMessage(title, '\u001b[32m', message);
  }

  /**
   * Log a message with an unsuccessful red color.
   * @param {string} title - The title of the message to log.
   * @param {string} message - The body of the message to log.
   * @param {Error} [err] - The exception that occurred, if applicable. Its stack trace will be logged.
   */
  logFailure(title, message, err) {
    this.checkState_();
    this.logMessage(title, '\u001b[31m', message, err);
  }

  logMessage(title, titleColor, message, err) {
    this.checkState_();

    let messageBuilder = new LogMessageBuilder();
    let timeStamp = createTimestamp();
    messageBuilder.append(timeStamp);
    messageBuilder.append(' ');
    messageBuilder.setColor(titleColor);
    messageBuilder.append(title);
    messageBuilder.append(' ');
    messageBuilder.setColor(AnsiColor.RESET);
    messageBuilder.append(message);
    messageBuilder.setColor(AnsiColor.RESET);

    if (err) {
      messageBuilder.append(' ');
      messageBuilder.setColor(AnsiColor.RED);
      messageBuilder.append(err.stack);
      messageBuilder.setColor(AnsiColor.RESET);
    }

    const messageWithFormatting = messageBuilder.getMessageWithFormatting();
    this.console_.log(messageWithFormatting);

    if (this.logToFile_) {
      if (this.useAnsiColorsInLogFile) {
        this.fileStream_.write(`${messageWithFormatting}\n`);
      } else {
        this.fileStream_.write(`${messageBuilder.getMessageWithoutFormatting()}\n`);
      }
    }
  }

  close() {
    if (this.closed_) {
      return Promise.resolve();
    }

    this.closed_ = true;

    return new Promise((fulfill, reject) => {
      if (!this.fileStream_) {
        fulfill();
      } else {
        this.fileStream_.end(err => {
          if (err) {
            this.console_.warn('Error closing log stream');
            return reject(err);
          }
          return fulfill();
        });
      }
    });
  }

  checkState_() {
    if (this.closed_) {
      throw new Error('The logger has been closed');
    }
  }
}

module.exports = Logger;
module.exports.LOG_FILE_PREFIX = LOG_FILE_PREFIX;
<commit_msg>require stack property to to be present, or don't append to logger message<commit_after>const fs = require('fs');
const AnsiColor = require('./util/ansi_color_codes.js');
const LogMessageBuilder = require('./util/log_message_builder');
const mkdirpSync = require('mkdirp').sync;
const path = require('path');

const LOG_FILE_PREFIX = 'log_';

function addPrecedingZero(timeString) {
  if (timeString.length === 1) {
    return `0${timeString}`;
  }
  return timeString;
}

function createTimestamp() {
  let now = new Date();
  let year = now.getFullYear().toString();
  let month = (now.getMonth() + 1).toString();
  let day = now.getDate().toString();
  let hour = now.getHours().toString();
  let minute = now.getMinutes().toString();
  let second = now.getSeconds().toString();
  hour = addPrecedingZero(hour);
  minute = addPrecedingZero(minute);
  second = addPrecedingZero(second);
  return `[${month}/${day}/${year} ${hour}:${minute}:${second}]`;
}

/**
 * Log events to the console and to the log file.
 * The Logger can be
 * accessed via {@link Monochrome~getLogger}.
 * @hideconstructor
 */
class Logger {
  constructor(logDirectoryPath, useAnsiColorsInLogFile, consoleOverride) {
    this.console_ = consoleOverride || console;
    this.closed_ = false;
    this.logToFile_ = !!logDirectoryPath;
    this.userAnsiColorsInLogFile_ = !!useAnsiColorsInLogFile;

    if (this.logToFile_) {
      try {
        mkdirpSync(logDirectoryPath);
      } catch (err) {
        this.console_.warn(`Error creating log directory: ${err}. Disabling logging to file.`);
        this.logToFile_ = false;
      }

      let logFilePath = path.join(logDirectoryPath, `${LOG_FILE_PREFIX}${new Date().toISOString()}.log`);
      this.fileStream_ = fs.createWriteStream(logFilePath);
      this.fileStream_.on('error', (err) => {
        this.logToFile_ = false;
        this.logFailure(LOGGER_TITLE, 'Error logging to file. Disabling logging to file.', err);
      });
    }
  }

  logInputReaction(title, msg, inputReactorTitle, succeeded, failureMessage) {
    let turnAroundTimeMs = Date.now() - msg.timestamp;
    let logMessageBuilder = new LogMessageBuilder();
    logMessageBuilder.setColor(AnsiColor.YELLOW);
    if (msg.channel.guild) {
      logMessageBuilder.append(msg.channel.guild.name);
      logMessageBuilder.setColor(AnsiColor.RESET);
      logMessageBuilder.append(' >> ');
      logMessageBuilder.setColor(AnsiColor.YELLOW);
      logMessageBuilder.append(msg.channel.name);
      logMessageBuilder.setColor(AnsiColor.RESET);
      logMessageBuilder.append(' >> ');
    }
    logMessageBuilder.setColor(AnsiColor.BLUE);
    logMessageBuilder.append(msg.author.username);
    logMessageBuilder.append('#');
    logMessageBuilder.append(msg.author.discriminator);
    logMessageBuilder.setColor(AnsiColor.RESET);
    logMessageBuilder.append(' >> ');
    if (inputReactorTitle) {
      logMessageBuilder.append(`[${inputReactorTitle}]`);
      logMessageBuilder.append(' ');
    }
    logMessageBuilder.setColor(AnsiColor.MAGENTA);
    logMessageBuilder.append(msg.content);

    if (succeeded) {
      logMessageBuilder.setColor(AnsiColor.RESET);
      logMessageBuilder.append(' ');
      logMessageBuilder.append(`(${turnAroundTimeMs}ms turnaround)`);
    }

    if (succeeded) {
      this.logSuccess(title, logMessageBuilder);
    } else {
      if (failureMessage) {
        logMessageBuilder.setColor(AnsiColor.RED);
        logMessageBuilder.append(' ');
        logMessageBuilder.append(`FAILED (${failureMessage})`);
      }
      this.logFailure(title, logMessageBuilder);
    }
  }

  /**
   * Log a message with a successful green color.
   * @param {string} title - The title of the message to log.
   * @param {string} message - The body of the message to log.
   */
  logSuccess(title, message) {
    this.checkState_();
    this.logMessage(title, '\u001b[32m', message);
  }

  /**
   * Log a message with an unsuccessful red color.
   * @param {string} title - The title of the message to log.
   * @param {string} message - The body of the message to log.
   * @param {Error} [err] - The exception that occurred, if applicable. Its stack trace will be logged.
   */
  logFailure(title, message, err) {
    this.checkState_();
    this.logMessage(title, '\u001b[31m', message, err);
  }

  logMessage(title, titleColor, message, err) {
    this.checkState_();

    let messageBuilder = new LogMessageBuilder();
    let timeStamp = createTimestamp();
    messageBuilder.append(timeStamp);
    messageBuilder.append(' ');
    messageBuilder.setColor(titleColor);
    messageBuilder.append(title);
    messageBuilder.append(' ');
    messageBuilder.setColor(AnsiColor.RESET);
    messageBuilder.append(message);
    messageBuilder.setColor(AnsiColor.RESET);

    if (err && err.stack) {
      messageBuilder.append(' ');
      messageBuilder.setColor(AnsiColor.RED);
      messageBuilder.append(err.stack);
      messageBuilder.setColor(AnsiColor.RESET);
    }

    const messageWithFormatting = messageBuilder.getMessageWithFormatting();
    this.console_.log(messageWithFormatting);

    if (this.logToFile_) {
      if (this.useAnsiColorsInLogFile) {
        this.fileStream_.write(`${messageWithFormatting}\n`);
      } else {
        this.fileStream_.write(`${messageBuilder.getMessageWithoutFormatting()}\n`);
      }
    }
  }

  close() {
    if (this.closed_) {
      return Promise.resolve();
    }

    this.closed_ = true;

    return new Promise((fulfill, reject) => {
      if (!this.fileStream_) {
        fulfill();
      } else {
        this.fileStream_.end(err => {
          if (err) {
            this.console_.warn('Error closing log stream');
            return reject(err);
          }
          return fulfill();
        });
      }
    });
  }

  checkState_() {
    if (this.closed_) {
      throw new Error('The logger has been closed');
    }
  }
}

module.exports = Logger;
module.exports.LOG_FILE_PREFIX = LOG_FILE_PREFIX;
<|endoftext|>


<commit_before><commit_msg>Add partial concatenation order to vendor scripts<commit_after><|endoftext|>


<commit_before>var colors = require('colors');
process.on('uncaughtException', function(err) {
	console.log('ERROR!!!', err);
	console.log(err.stack);
	process.exit();
});

/********************** Require tests *****************************************/
// Require LJM Versioning tests
// var load_specific_ljm_version = require('./load_specific_ljm_version');
// exports.load_specific_ljm_version = load_specific_ljm_version.tests;
// var get_ljm_version = require('./get_ljm_version');
// exports.get_ljm_version = get_ljm_version.tests;

// Require generic tests on mock devices
// var mock_device_test = require('./mock_device_test');
// var mock_device_defaults_cache_test = require('./mock_device_defaults_cache_test');
// var mock_device_attrs_test = require('./mock_device_attrs_test');
// var mock_device_upgrade_test = require('./mock_device_upgrade_test');
// var multiple_mock_device_upgrade_test = require('./multiple_mock_device_upgrade_test');

// Require T7 related tests
// var t7_basic_test = require('./t7_basic_test');
// var t7_array_test = require('./t7_array_test');
// var t7_check_calibration_test = require('./t7_check_calibration_test');
// var t7_read_recovery_fw_version_test = require('./t7_read_recovery_fw_version_test');
// var t7_upgrade_recovery_image_test = require('./t7_upgrade_recovery_image_test');
// var t7_upgrade_test = require('./t7_upgrade_test');
// var t7_error_test = require('./t7_error_test');
// var t7_open_close_test = require('./t7_open_close_test');
// var t7_basic_stream_test = require('./t7_basic_stream_test');
// var t7_single_channel_speed_test = require('./t7_single_channel_speed_test');
// var t7_multiple_device_upgrade_test = require('./t7_multiple_device_upgrade_test');

// Require ljm raw-handle usage tests (with ljm-ffi)
// var external_handle_test = require('./external_handle_test');

// Raw test of some labjack-nodejs stuff
// var t7_raw_test = require('./t7_raw_test');

// Thermocouple Tests
// var t7_thermocouple_speed_test = require('./t7_thermocouple_speed_test');

// Require Digit related tests
// var digit_basic_test = require('./digit_basic_test');
// var digit_variance_testing = require('./digit_variance_testing');

// Require Register Watcher tests
// var basic_watcher_test = require('./basic_watcher_test');
//

/********************** Perform tests *****************************************/
// Perform Generic tests on mock devices
// exports.mock_device_test = mock_device_test.tests;								// Passing
// exports.mock_device_defaults_cache_test = mock_device_defaults_cache_test.tests;// Passing
// exports.mock_device_attrs_test = mock_device_attrs_test.tests;
// exports.mock_device_upgrade_test = mock_device_upgrade_test.tests;
// exports.multiple_mock_device_upgrade_test = multiple_mock_device_upgrade_test.tests;

// Perform T7 related tests
// exports.t7_basic_test = t7_basic_test.tests;									// Passing
// exports.t7_array_test = t7_array_test.tests;
// exports.t7_check_calibration_test = t7_check_calibration_test.tests;			// Passing
// exports.t7_read_recovery_fw_version_test = t7_read_recovery_fw_version_test.tests;
// exports.t7_upgrade_recovery_image_test = t7_upgrade_recovery_image_test;
// exports.t7_upgrade_test = t7_upgrade_test.tests;								// Passing
// exports.t7_multiple_device_upgrade_test = t7_multiple_device_upgrade_test.tests;
// exports.t7_error_test = t7_error_test.tests;									// Passing
// exports.t7_open_close_test = t7_open_close_test.tests;						// Passing - This one takes a LONG time.  Opens and closes a device 310x.

// Tests for integrating externally with ljm-ffi.
// exports.external_handle_test = external_handle_test.tests;

// Tests for streaming
// exports.t7_basic_stream_test = t7_basic_stream_test.tests;						// Passing
// exports.t7_single_channel_speed_test = t7_single_channel_speed_test.tests;		// Passing
// exports.t7_single_channel_speed_testA = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testB = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testC = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testD = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testE = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testF = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testG = t7_single_channel_speed_test.tests;

// Raw tests
// exports.t7_raw_test = t7_raw_test.tests;

// Thermocouple Tests
// exports.t7_thermocouple_speed_test = t7_thermocouple_speed_test.tests;

// Perform Digit related tests
// exports.digit_basic_test = digit_basic_test.tests;
// exports.digit_variance_testing = digit_variance_testing.tests;

// Register Watcher tests
// exports.basic_watcher_test = basic_watcher_test.tests;

// var device_curator = require('../../lib/device_curator');
// var utils = require('../utils/utils');

var testGroups = {
	'get_ljm_version': true,
	'mock_device': {
		'mock_device_test': false,
		'mock_device_defaults_cache_test': false,
		'mock_device_attrs_test': false,
		'mock_device_upgrade_test': false,
		'multiple_mock_device_upgrade_test': false,
		'basic_watcher_test': false,
	},
	'digit': {
		'digit_basic_test': false,
		'digit_variance_testing': false,
	},

	// These are T7 specific tests.
	't7': {
		't7_basic_test': false,
		't7_multiple_dev_any_test': false,
		't7_array_test': false,
		't7_check_calibration_test': false,
		't7_read_recovery_fw_version_test': false,
		't7_upgrade_recovery_image_test': false,
		't7_upgrade_test': false,

		// These two tests should be enabled and disabled together.  The first
		// test loads and runs a lua script that creates a file.  The second
		// test verifies that the file was created and then deletes it.  They
		// are used together to test uSD card compatibility with the T7/T7-Pro.
		't7_load_and_run_lua_script': false, // Runs script & creates test file "log1.csv"
		't7_verify_lua_script_created_file': false, // Checks for and deletes file.

		// This test prints out what files are on the uSD card.
		't7_file_system_basic': false,

		// This test performs multiple readdir commands and two read file
		// commands to test file I/O commands.  Requires there to be a folder
		// called 'testDir' and a file '/testDir/txtFile.txt'.
		't7_file_system_mult_readdir': false, // ONLY ENABLE WHEN FOLDER/FILE EXISTS ON uSD CARD!

		// This test requires special files to be on the uSD card.
		// Folder named "Test Folder" in the root directory.
		// "Test Folder/JP2 period 2.txt"
		't7_file_system_verification': false, // ONLY ENABLE WHEN FOLDER/FILE EXISTS ON uSD CARD!

		// This test checks the ability to read the T7's manufacturing info
		// saved in flash.
		't7_manufacturing_info_test': false,

		// This test checks the ability to save and restore T7's power-up default
		// settings saved in flash.
		't7_startup_configs_save_and_restore': false, // Requires 2x T7s w/ specific SNs.  Same FW version.

		// Test cached reading functions. Requires one T7 via USB.
		't7_cached_values_test': false,

		// get available connections. Requires one T7 via USB.
		't7_available_connections_test': false,
	},
	// T7 over-ride tests...
	// 't7': {
	// 	't7_startup_configs_save_and_restore': false,
	// },

	// These are production-line tests.
	'production_line': {
		'check_t7_pro_versions': false,
		'check_t7_pro_versions_flex_fw': false,
		'mult_upgrade_recovery_firmware': false,
		'mult_upgrade_primary_firmware': false,
		'mult_install_calibration_firmware': false,
	},

	// These are T4 specific tests.
	't4': {
		't4_basic_test': false,
		't4_upgrade_test': false,
		't4_dac_and_ain_test': false,
		't4_flash_based_data_test': false,
		't4_is_auth_test': false,
		't4_check_auth_and_upgrade_test': false,
		't4_check_calibration_test': false,

		// This is a windows only test as LJLogM is required.
		't4_check_calibration_while_disconnected_test': false,

		't4_read_recovery_fw_version_test': false,
	},
	't4_mock_tests': {
		't4_basic_mock': true,
	},
	't5_mock_tests': {
		't5_basic_mock': true,
	},
	't8_mock_tests': {
		't8_basic_mock': true,
	},
	't8': {
		't8_basic_test': true,
	},
	'dashboard': {
		'basic_test': false,
	},
	'external_app_tests': {
		'basic_test': false, // Opens device and shares it with LJLogM and LJStreamM. (Starts and stops the apps to verify functionality)
		'check_connection_types': false, // This test checks the available connection types of the first found LJ USB device.
	},
};

if (process.platform !== 'win32') {
	console.warn('LJLogM-based test not supported on non-Windows platforms');
	testGroups.external_app_tests.basic_test = false;
}

var fileNameBase = './';

function requireTest(groupName, fileNamePartials, isEnabled, destObj) {
	var filePath = '';
	var i;
	var testName = '';
	filePath += fileNameBase;
	if(groupName) {
		if(groupName !== '') {
			filePath += groupName + '/';
		}
	}

	testName += fileNamePartials[0];
	for(i = 1; i < fileNamePartials.length; i ++) {
		testName += '_' + fileNamePartials[i];
	}
	filePath += testName;

	if(isEnabled) {
		console.log(' - Requiring test file', filePath, groupName, testName);

		var basicGroupName = 'test';
		if(groupName) {
			if(groupName !== '') {
				basicGroupName = groupName;
			}
		}
		if(typeof(exports[basicGroupName]) === 'undefined') {
			exports[basicGroupName] = {};
		}
		exports[basicGroupName][testName] = require(filePath);
		// if(groupName !== '') {
		// 	exports[groupName] = require(filePath);
		// } else {
		// 	exports[testName] = require(filePath);
		// }
	} else {
		console.log(' - Skipping Test:', filePath);
	}
}

var groupKeys = Object.keys(testGroups);
groupKeys.forEach(function(groupKey) {
	var testGroup = testGroups[groupKey];

	// For each test group check to see if they are a test or loop through their
	// group contents.
	if(typeof(testGroup) === 'boolean') {
		requireTest('', [groupKey], testGroup, exports);
	} else {
		var testKeys = Object.keys(testGroup);
		testKeys.forEach(function(testKey) {
			// For each test in a group, require enabled tests.
			var test = testGroup[testKey];
			requireTest(groupKey, [testKey], test, exports);
		});
	}
});
<commit_msg>enable tests<commit_after>var colors = require('colors');
process.on('uncaughtException', function(err) {
	console.log('ERROR!!!', err);
	console.log(err.stack);
	process.exit();
});

/********************** Require tests *****************************************/
// Require LJM Versioning tests
// var load_specific_ljm_version = require('./load_specific_ljm_version');
// exports.load_specific_ljm_version = load_specific_ljm_version.tests;
// var get_ljm_version = require('./get_ljm_version');
// exports.get_ljm_version = get_ljm_version.tests;

// Require generic tests on mock devices
// var mock_device_test = require('./mock_device_test');
// var mock_device_defaults_cache_test = require('./mock_device_defaults_cache_test');
// var mock_device_attrs_test = require('./mock_device_attrs_test');
// var mock_device_upgrade_test = require('./mock_device_upgrade_test');
// var multiple_mock_device_upgrade_test = require('./multiple_mock_device_upgrade_test');

// Require T7 related tests
// var t7_basic_test = require('./t7_basic_test');
// var t7_array_test = require('./t7_array_test');
// var t7_check_calibration_test = require('./t7_check_calibration_test');
// var t7_read_recovery_fw_version_test = require('./t7_read_recovery_fw_version_test');
// var t7_upgrade_recovery_image_test = require('./t7_upgrade_recovery_image_test');
// var t7_upgrade_test = require('./t7_upgrade_test');
// var t7_error_test = require('./t7_error_test');
// var t7_open_close_test = require('./t7_open_close_test');
// var t7_basic_stream_test = require('./t7_basic_stream_test');
// var t7_single_channel_speed_test = require('./t7_single_channel_speed_test');
// var t7_multiple_device_upgrade_test = require('./t7_multiple_device_upgrade_test');

// Require ljm raw-handle usage tests (with ljm-ffi)
// var external_handle_test = require('./external_handle_test');

// Raw test of some labjack-nodejs stuff
// var t7_raw_test = require('./t7_raw_test');

// Thermocouple Tests
// var t7_thermocouple_speed_test = require('./t7_thermocouple_speed_test');

// Require Digit related tests
// var digit_basic_test = require('./digit_basic_test');
// var digit_variance_testing = require('./digit_variance_testing');

// Require Register Watcher tests
// var basic_watcher_test = require('./basic_watcher_test');
//

/********************** Perform tests *****************************************/
// Perform Generic tests on mock devices
// exports.mock_device_test = mock_device_test.tests;								// Passing
// exports.mock_device_defaults_cache_test = mock_device_defaults_cache_test.tests;// Passing
// exports.mock_device_attrs_test = mock_device_attrs_test.tests;
// exports.mock_device_upgrade_test = mock_device_upgrade_test.tests;
// exports.multiple_mock_device_upgrade_test = multiple_mock_device_upgrade_test.tests;

// Perform T7 related tests
// exports.t7_basic_test = t7_basic_test.tests;									// Passing
// exports.t7_array_test = t7_array_test.tests;
// exports.t7_check_calibration_test = t7_check_calibration_test.tests;			// Passing
// exports.t7_read_recovery_fw_version_test = t7_read_recovery_fw_version_test.tests;
// exports.t7_upgrade_recovery_image_test = t7_upgrade_recovery_image_test;
// exports.t7_upgrade_test = t7_upgrade_test.tests;								// Passing
// exports.t7_multiple_device_upgrade_test = t7_multiple_device_upgrade_test.tests;
// exports.t7_error_test = t7_error_test.tests;									// Passing
// exports.t7_open_close_test = t7_open_close_test.tests;						// Passing - This one takes a LONG time.  Opens and closes a device 310x.

// Tests for integrating externally with ljm-ffi.
// exports.external_handle_test = external_handle_test.tests;

// Tests for streaming
// exports.t7_basic_stream_test = t7_basic_stream_test.tests;						// Passing
// exports.t7_single_channel_speed_test = t7_single_channel_speed_test.tests;		// Passing
// exports.t7_single_channel_speed_testA = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testB = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testC = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testD = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testE = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testF = t7_single_channel_speed_test.tests;
// exports.t7_single_channel_speed_testG = t7_single_channel_speed_test.tests;

// Raw tests
// exports.t7_raw_test = t7_raw_test.tests;

// Thermocouple Tests
// exports.t7_thermocouple_speed_test = t7_thermocouple_speed_test.tests;

// Perform Digit related tests
// exports.digit_basic_test = digit_basic_test.tests;
// exports.digit_variance_testing = digit_variance_testing.tests;

// Register Watcher tests
// exports.basic_watcher_test = basic_watcher_test.tests;

// var device_curator = require('../../lib/device_curator');
// var utils = require('../utils/utils');

var testGroups = {
	/* START defining tests that are based off of mock-devices */
	'get_ljm_version': true,
	'mock_device': {
		'mock_device_test': true,
		'mock_device_defaults_cache_test': true,
		'mock_device_attrs_test': true,
		'mock_device_upgrade_test': true,
		'mock_t8_upgrade_test': true,
		'multiple_mock_device_upgrade_test': true,
		'basic_watcher_test': true,
	},
	't4_mock_tests': {
		't4_basic_mock': true,
	},
	't5_mock_tests': {
		't5_basic_mock': true,
	},
	't8_mock_tests': {
		't8_basic_mock': true,
	},

	/* END defining tests that use mock-devices */

	/* START defining tests that use live devices. */
	'digit': {
		'digit_basic_test': false,
		'digit_variance_testing': false,
	},

	// These are T7 specific tests.
	't7': {
		't7_basic_test': false,
		't7_multiple_dev_any_test': false,
		't7_array_test': false,
		't7_check_calibration_test': false,
		't7_read_recovery_fw_version_test': false,
		't7_upgrade_recovery_image_test': false,
		't7_upgrade_test': false,

		// These two tests should be enabled and disabled together.  The first
		// test loads and runs a lua script that creates a file.  The second
		// test verifies that the file was created and then deletes it.  They
		// are used together to test uSD card compatibility with the T7/T7-Pro.
		't7_load_and_run_lua_script': false, // Runs script & creates test file "log1.csv"
		't7_verify_lua_script_created_file': false, // Checks for and deletes file.

		// This test prints out what files are on the uSD card.
		't7_file_system_basic': false,

		// This test performs multiple readdir commands and two read file
		// commands to test file I/O commands.  Requires there to be a folder
		// called 'testDir' and a file '/testDir/txtFile.txt'.
		't7_file_system_mult_readdir': false, // ONLY ENABLE WHEN FOLDER/FILE EXISTS ON uSD CARD!

		// This test requires special files to be on the uSD card.
		// Folder named "Test Folder" in the root directory.
		// "Test Folder/JP2 period 2.txt"
		't7_file_system_verification': false, // ONLY ENABLE WHEN FOLDER/FILE EXISTS ON uSD CARD!

		// This test checks the ability to read the T7's manufacturing info
		// saved in flash.
		't7_manufacturing_info_test': false,

		// This test checks the ability to save and restore T7's power-up default
		// settings saved in flash.
		't7_startup_configs_save_and_restore': false, // Requires 2x T7s w/ specific SNs.  Same FW version.

		// Test cached reading functions. Requires one T7 via USB.
		't7_cached_values_test': false,

		// get available connections. Requires one T7 via USB.
		't7_available_connections_test': false,
	},
	// T7 over-ride tests...
	// 't7': {
	// 	't7_startup_configs_save_and_restore': false,
	// },

	// These are production-line tests.
	'production_line': {
		'check_t7_pro_versions': false,
		'check_t7_pro_versions_flex_fw': false,
		'mult_upgrade_recovery_firmware': false,
		'mult_upgrade_primary_firmware': false,
		'mult_install_calibration_firmware': false,
	},

	// These are T4 specific tests.
	't4': {
		't4_basic_test': false,
		't4_upgrade_test': false,
		't4_dac_and_ain_test': false,
		't4_flash_based_data_test': false,
		't4_is_auth_test': false,
		't4_check_auth_and_upgrade_test': false,
		't4_check_calibration_test': false,

		// This is a windows only test as LJLogM is required.
		't4_check_calibration_while_disconnected_test': false,

		't4_read_recovery_fw_version_test': false,
	},
	't8': {
		't8_basic_test': false,
		't8_read_flash_data': false,
		't8_upgrade_test': false,
	},
	'dashboard': {
		'basic_test': false,
	},
	'external_app_tests': {
		'basic_test': false, // Opens device and shares it with LJLogM and LJStreamM. (Starts and stops the apps to verify functionality)
		'check_connection_types': false, // This test checks the available connection types of the first found LJ USB device.
	},
};

if (process.platform !== 'win32') {
	console.warn('LJLogM-based test not supported on non-Windows platforms');
	testGroups.external_app_tests.basic_test = false;
}

var fileNameBase = './';

function requireTest(groupName, fileNamePartials, isEnabled, destObj) {
	var filePath = '';
	var i;
	var testName = '';
	filePath += fileNameBase;
	if(groupName) {
		if(groupName !== '') {
			filePath += groupName + '/';
		}
	}

	testName += fileNamePartials[0];
	for(i = 1; i < fileNamePartials.length; i ++) {
		testName += '_' + fileNamePartials[i];
	}
	filePath += testName;

	if(isEnabled) {
		console.log(' - Requiring test file', filePath, groupName, testName);

		var basicGroupName = 'test';
		if(groupName) {
			if(groupName !== '') {
				basicGroupName = groupName;
			}
		}
		if(typeof(exports[basicGroupName]) === 'undefined') {
			exports[basicGroupName] = {};
		}
		exports[basicGroupName][testName] = require(filePath);
		// if(groupName !== '') {
		// 	exports[groupName] = require(filePath);
		// } else {
		// 	exports[testName] = require(filePath);
		// }
	} else {
		console.log(' - Skipping Test:', filePath);
	}
}

var groupKeys = Object.keys(testGroups);
groupKeys.forEach(function(groupKey) {
	var testGroup = testGroups[groupKey];

	// For each test group check to see if they are a test or loop through their
	// group contents.
	if(typeof(testGroup) === 'boolean') {
		requireTest('', [groupKey], testGroup, exports);
	} else {
		var testKeys = Object.keys(testGroup);
		testKeys.forEach(function(testKey) {
			// For each test in a group, require enabled tests.
			var test = testGroup[testKey];
			requireTest(groupKey, [testKey], test, exports);
		});
	}
});
<|endoftext|>


<commit_before>var smash = require("smash");

module.exports = function() {
  var files = [].slice.call(arguments).map(function(d) { return "src/" + d; }),
      sandbox = null;
  files.unshift("src/start");
  files.push("src/end");

  function topic() {
    smash.load(files, "d3", sandbox, this.callback);
  }

  topic.sandbox = function(_) {
    sandbox = _;
    return topic;
  };

  return topic;
};
<commit_msg>Allow load expression to be overridden.<commit_after>var smash = require("smash");

module.exports = function() {
  var files = [].slice.call(arguments).map(function(d) { return "src/" + d; }),
      expression = "d3",
      sandbox = null;

  files.unshift("src/start");
  files.push("src/end");

  function topic() {
    smash.load(files, expression, sandbox, this.callback);
  }

  topic.expression = function(_) {
    expression = _;
    return topic;
  };

  topic.sandbox = function(_) {
    sandbox = _;
    return topic;
  };

  return topic;
};
<|endoftext|>


<commit_before>/**
 * ngAuth 0.0.1
 * (c) 2014 Sahat Yalkabov <sahat@me.com>
 * License: MIT
 */

angular.module('ngAuth', [])
  .provider('Auth', function() {

    var config = this.config = {
      logoutRedirect: '/',
      loginRedirect: '/',
      loginUrl: '/auth/login',
      signupUrl: '/auth/signup',
      signupRedirect: '/login',
      userGlobal: 'currentUser',
      providers: {
        facebook: {
          baseUrl: 'https://www.facebook.com/dialog/oauth',
          scope: 'scope, email',
          requiredUrlParams: { display: 'popup' }
        }
      }
    };

    return {
      setProvider: function(params) {
        config.providers[params.name] = config.providers[params.name] || {};
        angular.extend(config.providers[params.name], params);
      },

      $get: function($interval, $timeout, $http, $location, $rootScope, $alert, $q, $injector, $window, $document, $cookieStore) {

        // BEGIN OAUTH

        function parseKeyValue(keyValue) {
          var obj = {}, key_value, key;
          angular.forEach((keyValue || "").split('&'), function(keyValue) {
            if (keyValue) {
              key_value = keyValue.split('=');
              key = decodeURIComponent(key_value[0]);
              obj[key] = angular.isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;
            }
          });
          return obj;
        }

        var Popup = function() {
          this.popup = null;
        };

        Popup.prototype.open = function(url, keys, options) {
          var deferred = $q.defer();
          var lastPopup = this.popup;

          if (lastPopup) {
            this.close();
          }

          var optionsString = stringifyOptions(prepareOptions(options || {}));
          this.popup = window.open(url, 'ng-auth', optionsString);

          if (this.popup && !this.popup.closed) {
            this.popup.focus();
          } else {
            deferred.reject('Popup could not open or was closed');
          }

          $window.addEventListener('message', function(event) {
            console.log('handling postMessage');
            console.log(event);
            if (event.data.message === 'deliverCredenrials') {
              delete event.data.message;
            }
            deferred.resolve(event.data);
          }, false);

          var self = this;

          this.polling = $interval(function() {
            self.requestCredentials(self.popup);
          }, 35);

          return deferred.promise;
        };

        Popup.prototype.close = function() {
          if (this.popup) {
            this.popup.close();
            this.popup = null;
            $rootScope.$emit('didClose');
          }
        };

        Popup.prototype.pollPopup = function() {
          console.log('pollin');
          if (!this.popup) {
            return;
          }
          if (this.popup.closed) {
            $timeout.cancel(this.polling);
          }
        };

        Popup.prototype.requestCredentials = function(authWindow) {
          var search = authWindow.location.search;
          if (search.match('code') || search.match('token')) {
            console.log('found code or token');
            var data = parseKeyValue(authWindow.location.search.substring(1));
            $window.postMessage(data, $window.location.origin);
            $interval.cancel(this.polling);
          }
          console.log('requesting creds!!')

        };

        function prepareOptions(options) {
          var width = options.width || 500;
          var height = options.height || 500;
          return angular.extend({
            left: ((screen.width / 2) - (width / 2)),
            top: ((screen.height / 2) - (height / 2)),
            width: width,
            height: height
          }, options);
        }

        function stringifyOptions(options) {
          var optionsStrings = [];
          for (var key in options) {
            if (options.hasOwnProperty(key)) {
              var value;
              switch (options[key]) {
                case true:
                  value = '1';
                  break;
                case false:
                  value = '0';
                  break;
                default:
                  value = options[key];
              }
              optionsStrings.push(
                  key + '=' + value
              );
            }
          }
          return optionsStrings.join(',');
        }

        var getRedirectUri = function() {
          return $window.location.href;
        };

        var oauthKeys = ['code', 'access_token', 'expires_in'];

        var OAuth2 = function() {
          this.name = null;
          this.clientId = null;
          this.scope = null;
          this.baseUrl = null;
          this.responseType = 'code';
        };

        OAuth2.prototype.getDefaultRequiredUrlParams = function() {
          return {
            response_type: this.responseType,
            client_id: this.clientId,
            redirect_uri: getRedirectUri()
          }
        };

        OAuth2.prototype.buildQueryString = function(obj) {
          var str = [];
          angular.forEach(obj, function(value, key) {
            str.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
          });
          return str.join('&');
        };

        OAuth2.prototype.open = function() {
          var name = this.name;
          var url = this.buildUrl();
          var redirectUri = $window.location.href;

          var popup = new Popup();

          return popup.open(url, oauthKeys).then(function(authData) {
            return {
              authorizationCode: authData.code,
              provider: name,
              getRedirectUri: redirectUri
            }
          });
        };

        OAuth2.prototype.buildUrl = function(optionalUrlParams) {
          var defaultRequiredUrlParams = this.getDefaultRequiredUrlParams();
          if (this.requiredUrlParams) {
            angular.extend(defaultRequiredUrlParams, this.requiredUrlParams);
          }
          var base = this.baseUrl;
          var params = angular.extend(defaultRequiredUrlParams, optionalUrlParams);
          var qs = this.buildQueryString(params);
          return [base, qs].join('?');
        };
        function providerLookup(providerName) {
          var providerOptions = config.providers[providerName];
          var oauth2 = new OAuth2();
          var provider = angular.extend(oauth2, providerOptions);
          return provider;
        }

        // END OAUTH

        var token = $window.localStorage.token;
        if (token) {
          var payload = JSON.parse($window.atob(token.split('.')[1]));
          $rootScope[config.userGlobal] = payload.user;
        }

        return {
          authenticate: function(provider, options) {
            var deferred = $q.defer;
            if (!provider) {
              throw new Error('Expected a provider named \'' + provider + '\', did you forget to add it?');
            } else {
              provider = providerLookup(provider);
            }
            provider.open(options);
          },

          loginOauth: function(provider) {
            provider = provider.trim().toLowerCase();

            switch (provider) {
              case 'facebook':
                var scope = config.providers.facebook.scope.join(',');
                FB.login(function(response) {
                  FB.api('/me', function(profile) {
                    // TODO normalize return properties like passport
                    var data = {
                      accessToken: response.authResponse.accessToken,
                      signedRequest: response.authResponse.signedRequest,
                      profile: profile
                    };
                    $http.post(config.providers.facebook.url, data).success(function(token) {
                      var payload = JSON.parse($window.atob(token.split('.')[1]));
                      $window.localStorage.token = token;
                      $rootScope[config.userGlobal] = payload.user;
                      $location.path(config.loginRedirect);
                    });
                  });
                }, { scope: scope });
                break;
              case 'google':
                gapi.auth.authorize({
                  client_id: config.providers.google.clientId,
                  scope: config.providers.google.scope,
                  immediate: false
                }, function(token) {
                  gapi.client.load('plus', 'v1', function() {
                    var request = gapi.client.plus.people.get({
                      userId: 'me'
                    });
                    request.execute(function(response) {
                      var data = {
                        accessToken: token.access_token,
                        profile: response
                      };
                      $http.post(config.providers.google.url, data).success(function(token) {
                        var payload = JSON.parse($window.atob(token.split('.')[1]));
                        $window.localStorage.token = token;
                        $rootScope.currentUser = payload.user;
                        $location.path(config.loginRedirect);
                      });
                    });
                  });
                });
                break;
              case 'linkedin':
                IN.UI.Authorize().place();
                IN.Event.on(IN, 'auth', function() {
                    IN.API.Profile('me').result(function(result) {
                      var profile = result.values[0];
                      $http.post(config.providers.linkedin.url, { profile: profile }).success(function(token) {
                        var payload = JSON.parse($window.atob(token.split('.')[1]));
                        $window.localStorage.token = token;
                        $rootScope.currentUser = payload.user;
                        $location.path(config.loginRedirect);
                      });
                    });
                  }
                );
                break;
              default:
                break;
            }
          },
          login: function(user) {
            return $http.post(config.loginUrl, user).success(function(data) {
              $window.localStorage.token = data.token;
              var payload = JSON.parse($window.atob(data.token.split('.')[1]));
              $rootScope[config.userGlobal] = payload.user;
              $location.path(config.loginRedirect);
            });
          },
          signup: function(user) {
            return $http.post(config.signupUrl, user).success(function() {
              $location.path(config.signupRedirect);
            });
          },
          logout: function() {
            delete $window.localStorage.token;
            $rootScope[config.userGlobal] = null;
            $location.path(config.logoutRedirect);
          },
          isAuthenticated: function() {
            return $rootScope[config.userGlobal];
          }
        };
      }
    };
  })
  .factory('authInterceptor', function($q, $window, $location) {
    return {
      request: function(config) {
        if ($window.localStorage.token) {
          config.headers.Authorization = 'Bearer ' + $window.localStorage.token;
        }
        return config;
      },
      responseError: function(response) {
        if (response.status === 401 || response.status === 403) {
          $location.path('/login');
        }
        return $q.reject(response);
      }
    }
  })
  .config(function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  })
  .run(function($rootScope, $location) {
    $rootScope.$on('$routeChangeStart', function(event, current, previous) {
      if ($rootScope.currentUser &&
        (current.originalPath === '/login' || current.originalPath === '/signup')) {
        $location.path('/');
      }
      if (current.authenticated && !$rootScope.currentUser) {
        $location.path('/login');
      }
    });
  });
<commit_msg>providerLookup moved to OAuth2 function constructor<commit_after>/**
 * ngAuth 0.0.1
 * (c) 2014 Sahat Yalkabov <sahat@me.com>
 * License: MIT
 */

angular.module('ngAuth', [])
  .provider('Auth', function() {

    var config = this.config = {
      logoutRedirect: '/',
      loginRedirect: '/',
      loginUrl: '/auth/login',
      signupUrl: '/auth/signup',
      signupRedirect: '/login',
      userGlobal: 'currentUser',
      providers: {
        facebook: {
          baseUrl: 'https://www.facebook.com/dialog/oauth',
          scope: 'scope, email',
          requiredUrlParams: { display: 'popup' }
        }
      }
    };

    return {
      setProvider: function(params) {
        config.providers[params.name] = config.providers[params.name] || {};
        angular.extend(config.providers[params.name], params);
      },

      $get: function($interval, $timeout, $http, $location, $rootScope, $alert, $q, $injector, $window, $document, $cookieStore) {

        // BEGIN OAUTH

        function parseKeyValue(keyValue) {
          var obj = {}, key_value, key;
          angular.forEach((keyValue || "").split('&'), function(keyValue) {
            if (keyValue) {
              key_value = keyValue.split('=');
              key = decodeURIComponent(key_value[0]);
              obj[key] = angular.isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;
            }
          });
          return obj;
        }

        var Popup = function() {
          this.popup = null;
        };

        Popup.prototype.open = function(url, keys, options) {
          var deferred = $q.defer();
          var lastPopup = this.popup;

          if (lastPopup) {
            this.close();
          }

          var optionsString = stringifyOptions(prepareOptions(options || {}));
          this.popup = window.open(url, 'ng-auth', optionsString);

          if (this.popup && !this.popup.closed) {
            this.popup.focus();
          } else {
            deferred.reject('Popup could not open or was closed');
          }

          $window.addEventListener('message', function(event) {
            console.log('handling postMessage');
            console.log(event);
            if (event.data.message === 'deliverCredenrials') {
              delete event.data.message;
            }
            deferred.resolve(event.data);
          }, false);

          var self = this;

          this.polling = $interval(function() {
            self.requestCredentials(self.popup);
          }, 35);

          return deferred.promise;
        };

        Popup.prototype.close = function() {
          if (this.popup) {
            this.popup.close();
            this.popup = null;
            $rootScope.$emit('didClose');
          }
        };

        Popup.prototype.pollPopup = function() {
          console.log('pollin');
          if (!this.popup) {
            return;
          }
          if (this.popup.closed) {
            $timeout.cancel(this.polling);
          }
        };

        Popup.prototype.requestCredentials = function(authWindow) {
          var search = authWindow.location.search;
          if (search.match('code') || search.match('token')) {
            console.log('found code or token');
            var data = parseKeyValue(authWindow.location.search.substring(1));
            $window.postMessage(data, $window.location.origin);
            $interval.cancel(this.polling);
            // angular lifecycle before page loads
            authWindow.close();
          }
          console.log('requesting creds!!')

        };

        function prepareOptions(options) {
          var width = options.width || 500;
          var height = options.height || 500;
          return angular.extend({
            left: ((screen.width / 2) - (width / 2)),
            top: ((screen.height / 2) - (height / 2)),
            width: width,
            height: height
          }, options);
        }

        function stringifyOptions(options) {
          var optionsStrings = [];
          for (var key in options) {
            if (options.hasOwnProperty(key)) {
              var value;
              switch (options[key]) {
                case true:
                  value = '1';
                  break;
                case false:
                  value = '0';
                  break;
                default:
                  value = options[key];
              }
              optionsStrings.push(
                  key + '=' + value
              );
            }
          }
          return optionsStrings.join(',');
        }

        var getRedirectUri = function() {
          return $window.location.href;
        };

        var oauthKeys = ['code', 'access_token', 'expires_in'];

        var OAuth2 = function() {
          this.name = null;
          this.clientId = null;
          this.scope = null;
          this.baseUrl = null;
          this.responseType = 'code';
        };

        OAuth2.prototype.getDefaultRequiredUrlParams = function() {
          return {
            response_type: this.responseType,
            client_id: this.clientId,
            redirect_uri: getRedirectUri()
          }
        };

        OAuth2.prototype.buildQueryString = function(obj) {
          var str = [];
          angular.forEach(obj, function(value, key) {
            str.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
          });
          return str.join('&');
        };

        OAuth2.prototype.open = function() {
          var name = this.name;
          var url = this.buildUrl();
          var redirectUri = $window.location.href;

          var popup = new Popup();

          return popup.open(url, oauthKeys).then(function(authData) {
            return {
              authorizationCode: authData.code,
              provider: name,
              getRedirectUri: redirectUri
            }
          });
        };

        OAuth2.prototype.buildUrl = function(optionalUrlParams) {
          var defaultRequiredUrlParams = this.getDefaultRequiredUrlParams();
          if (this.requiredUrlParams) {
            angular.extend(defaultRequiredUrlParams, this.requiredUrlParams);
          }
          var base = this.baseUrl;
          var params = angular.extend(defaultRequiredUrlParams, optionalUrlParams);
          var qs = this.buildQueryString(params);
          return [base, qs].join('?');
        };

        OAuth2.createProvider = function(providerName) {
          var providerOptions = config.providers[providerName];
          var oauth2 = new OAuth2();
          var provider = angular.extend(oauth2, providerOptions);
          return provider;
        };

        // END OAUTH

        var token = $window.localStorage.token;
        if (token) {
          var payload = JSON.parse($window.atob(token.split('.')[1]));
          $rootScope[config.userGlobal] = payload.user;
        }

        return {
          authenticate: function(providerName, options) {
            var deferred = $q.defer;
            if (!providerName) {
              deferred.reject('Expected a provider named \'' + providerName + '\', did you forget to add it?');
              return;
            }
            var provider = OAuth2.createProvider(providerName);
            provider.open(options);
          },

          loginOauth: function(provider) {
            provider = provider.trim().toLowerCase();

            switch (provider) {
              case 'facebook':
                var scope = config.providers.facebook.scope.join(',');
                FB.login(function(response) {
                  FB.api('/me', function(profile) {
                    // TODO normalize return properties like passport
                    var data = {
                      accessToken: response.authResponse.accessToken,
                      signedRequest: response.authResponse.signedRequest,
                      profile: profile
                    };
                    $http.post(config.providers.facebook.url, data).success(function(token) {
                      var payload = JSON.parse($window.atob(token.split('.')[1]));
                      $window.localStorage.token = token;
                      $rootScope[config.userGlobal] = payload.user;
                      $location.path(config.loginRedirect);
                    });
                  });
                }, { scope: scope });
                break;
              case 'google':
                gapi.auth.authorize({
                  client_id: config.providers.google.clientId,
                  scope: config.providers.google.scope,
                  immediate: false
                }, function(token) {
                  gapi.client.load('plus', 'v1', function() {
                    var request = gapi.client.plus.people.get({
                      userId: 'me'
                    });
                    request.execute(function(response) {
                      var data = {
                        accessToken: token.access_token,
                        profile: response
                      };
                      $http.post(config.providers.google.url, data).success(function(token) {
                        var payload = JSON.parse($window.atob(token.split('.')[1]));
                        $window.localStorage.token = token;
                        $rootScope.currentUser = payload.user;
                        $location.path(config.loginRedirect);
                      });
                    });
                  });
                });
                break;
              case 'linkedin':
                IN.UI.Authorize().place();
                IN.Event.on(IN, 'auth', function() {
                    IN.API.Profile('me').result(function(result) {
                      var profile = result.values[0];
                      $http.post(config.providers.linkedin.url, { profile: profile }).success(function(token) {
                        var payload = JSON.parse($window.atob(token.split('.')[1]));
                        $window.localStorage.token = token;
                        $rootScope.currentUser = payload.user;
                        $location.path(config.loginRedirect);
                      });
                    });
                  }
                );
                break;
              default:
                break;
            }
          },
          login: function(user) {
            return $http.post(config.loginUrl, user).success(function(data) {
              $window.localStorage.token = data.token;
              var payload = JSON.parse($window.atob(data.token.split('.')[1]));
              $rootScope[config.userGlobal] = payload.user;
              $location.path(config.loginRedirect);
            });
          },
          signup: function(user) {
            return $http.post(config.signupUrl, user).success(function() {
              $location.path(config.signupRedirect);
            });
          },
          logout: function() {
            delete $window.localStorage.token;
            $rootScope[config.userGlobal] = null;
            $location.path(config.logoutRedirect);
          },
          isAuthenticated: function() {
            return $rootScope[config.userGlobal];
          }
        };
      }
    };
  })
  .factory('authInterceptor', function($q, $window, $location) {
    return {
      request: function(config) {
        if ($window.localStorage.token) {
          config.headers.Authorization = 'Bearer ' + $window.localStorage.token;
        }
        return config;
      },
      responseError: function(response) {
        if (response.status === 401 || response.status === 403) {
          $location.path('/login');
        }
        return $q.reject(response);
      }
    }
  })
  .config(function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  })
  .run(function($rootScope, $location) {
    $rootScope.$on('$routeChangeStart', function(event, current, previous) {
      if ($rootScope.currentUser &&
        (current.originalPath === '/login' || current.originalPath === '/signup')) {
        $location.path('/');
      }
      if (current.authenticated && !$rootScope.currentUser) {
        $location.path('/login');
      }
    });
  });
<|endoftext|>


<commit_before>//A TDD test suite to check for correctness
//and accuracy of an OOP Model of a bank account

//fat arrows not allowed inside mocha test suite
//see ---> mochajs.org/#arrow-functions

const expect = require("chai").expect;
const Ade = require("../bank.js").Ade;
const Victoria = require("../bank.js").Victoria;

describe("Bank Account Suite", function(){
	//assert that INITIAL BALANCE is 5000
	describe("INITIAL account balance should be N5000", function() {
    	it("should be 5000", function() {
      expect(Ade._balance).to.equal(5000);
  	})});
	//assert that the DEPOSIT METHOD works correctly
  	describe("DEPOSIT method for class account", function() {
    	it("should return success msg", function() {
      expect(Ade.deposit(5000)).to.equal("TRANSACTION SUCCESSFUL: You have deposited 5000");
  	})});
  	//assert that the WITHDRAW METHOD works correctly
  	describe("WITHDRAW method for class account", function() {
    	it("should return success msg", function() {
      expect(Ade.withdraw(5000)).to.equal("TRANSACTION SUCCESSFUL: You have withdrawn 5000");
  	})});
  	//assert that BALANCE METHOD works correctly
  	describe("BALANCE method for class account", function() {
    	it("should return success msg", function() {
      expect(Ade.balance()).to.equal("TRANSACTION SUCCESSFUL: You have 5000 in your account");
  	})});

  	//proove that the SAVINGS ACCOUNT CLASS works as intented
  	describe("SAVINGS Account class working correctly", function() {
    	it("should return savings account balance", function() {
      expect(Victoria._balance).to.equal(50000);
  	})});

  	//proove that the  WITHDRAW METHOD has a correct implentation
  	describe("WITHDRAW Method for Savings Account class", function() {
    	it("should return Transaction sucess", function() {
      expect(Victoria.withdraw(20000)).to.equal("TRANSACTION SUCCESSFUL: You have withdrawn 20000 in your account");
  	})});

})<commit_msg>implement test for current account class<commit_after>//A TDD test suite to check for correctness
//and accuracy of an OOP Model of a bank account

//fat arrows not allowed inside mocha test suite
//see ---> mochajs.org/#arrow-functions

const expect = require("chai").expect;
const Ade = require("../bank.js").Ade;
const Victoria = require("../bank.js").Victoria;

describe("Bank Account Suite", function(){
	//assert that INITIAL BALANCE is 5000
	describe("INITIAL account balance should be N5000", function() {
    	it("should be 5000", function() {
      expect(Ade._balance).to.equal(5000);
  	})});
	//assert that the DEPOSIT METHOD works correctly
  	describe("DEPOSIT method for class account", function() {
    	it("should return success msg", function() {
      expect(Ade.deposit(5000)).to.equal("TRANSACTION SUCCESSFUL: You have deposited 5000");
  	})});
  	//assert that the WITHDRAW METHOD works correctly
  	describe("WITHDRAW method for class account", function() {
    	it("should return success msg", function() {
      expect(Ade.withdraw(5000)).to.equal("TRANSACTION SUCCESSFUL: You have withdrawn 5000");
  	})});
  	//assert that BALANCE METHOD works correctly
  	describe("BALANCE method for class account", function() {
    	it("should return success msg", function() {
      expect(Ade.balance()).to.equal("TRANSACTION SUCCESSFUL: You have 5000 in your account");
  	})});

  	//proove that the SAVINGS ACCOUNT CLASS works as intented
  	describe("SAVINGS Account class working correctly", function() {
    	it("should return savings account balance", function() {
      expect(Victoria._balance).to.equal(50000);
  	})});

  	//proove that the  WITHDRAW METHOD has a correct implentation
  	describe("WITHDRAW Method for Savings Account class", function() {
    	it("should return Transaction sucess", function() {
      expect(Victoria.withdraw(20000)).to.equal("TRANSACTION SUCCESSFUL: You have withdrawn 20000 in your account");
  	})});

  	//proove that CURRENT ACCOUNT CLASS has a correct implentation
  	describe("CURRENT Account class is implemented", function() {
    	it("should return Current account balance", function() {
      expect(Tomi._balance).to.equal(1000000);
  	})});

})<|endoftext|>


<commit_before><commit_msg>Removes is sent check: The error is caused by the emulator itself on lost connection timeout.<commit_after><|endoftext|>


<commit_before>'use strict';

const DatabaseHelper = require('Server/Helpers/DatabaseHelper');
const SettingsHelperCommon = require('Common/Helpers/SettingsHelper');

/**
 * The helper class for settings
 *
 * @memberof HashBrown.Server.Helpers
 */
class SettingsHelper extends SettingsHelperCommon {
    /**
     * Migrates old settings format
     *
     * @param {String} project
     * @param {Boolean} commitChanges
     *
     * @returns {Promise} Promise
     */
    static migrateOldSettings(
        project = requiredParam('project'),
        commitChanges = false
    ) {
        debug.log('Migrating old settings for project "' + project + '"...', this);

        let collection = [];

        let newProjectSettings = {
            usedBy: 'project'
        };

        collection.push(newProjectSettings);

        // First check if project exists
        return DatabaseHelper.databaseExists(project)
        .then((doesExist) => {
            if(!doesExist) {
                return Promise.reject(new Error('Project by id "' + project + '" not found'));
            }

            debug.log('Getting project settings...', this, 3);

            // Then get project settings
            return DatabaseHelper.find(
                project,
                'settings',
                {}
            );
        })
        .then((projectSettings) => {
            if(!projectSettings) {
                return Promise.reject(new Error('Project settings for "' + project + '" not found'));
            }

            // Make sure there is a "live" environment
            if(!projectSettings.environments) {
                projectSettings.environments = { names: [ 'live' ] };
            }

            for(let section of projectSettings) {
                let sectionKey = section.section;

                // We're handling environments a little differently now, so skip this key
                if(sectionKey === 'environments') { continue; }

                delete section.section;

                newProjectSettings[sectionKey] = section;
            }

            // Then parse all environments
            let parseNextEnvironment = () => {
                let environment = projectSettings.environments.names.pop();

                if(!environment) {
                    return Promise.resolve();
                }

                debug.log('Getting settings for environment "' + environment + '"...', this, 3);

                return DatabaseHelper.find(
                    project,
                    environment + '.settings',
                    {}
                ).then((environmentSettings) => {
                    if(!environmentSettings) {
                        return Promise.reject(new Error('Environment settings for "' + project + '/' + environment + '" not found'));
                    }

                    let newEnvironmentSettings = {
                        usedBy: environment
                    };

                    collection.push(newEnvironmentSettings);

                    for(let section of environmentSettings) {
                        let sectionKey = section.section;

                        delete section.section;

                        if(sectionKey === 'sync') {
                            newProjectSettings.sync = {
                                project: section.project,
                                url: section.url,
                                token: section.token
                            }
                        } else {
                            newEnvironmentSettings[sectionKey] = section;
                        }
                    }

                    // Delete old docs
                    debug.log('Deleting old settings for "' + project + '/' + environment + '"...', this, 3);

                    if(!commitChanges) { return Promise.resolve(); }

                    return DatabaseHelper.remove(
                        project,
                        environment + '.settings',
                        {}
                    );
                })
                .then(() => {
                    return parseNextEnvironment();
                });
            };

            return parseNextEnvironment();
        })

        // Delete old project settings
        .then(() => {
            debug.log('Deleting old project settings...', this, 3);

            if(!commitChanges) { return Promise.resolve(); }

            return DatabaseHelper.remove(
                project,
                'settings',
                {}
            );
        })

        // Insert new collections
        .then(() => {
            debug.log('Inserting new collections...', this, 3);

            let insertNextSetting = () => {
                let setting = collection.pop();

                if(!setting) {
                    return Promise.resolve();
                }

                debug.log('Inserting "' + setting.usedBy + '": ' + JSON.stringify(setting) + '...', this, 3);

                if(!commitChanges) { return insertNextSetting(); }

                return DatabaseHelper.insertOne(
                    project,
                    'settings',
                    setting
                ).then(() => {
                    return insertNextSetting();
                });
            };

            return insertNextSetting();
        })

        // Done
        .then(() => {
            debug.log('Done migrating settings for project "' + project + '"!', this);
        });
    }

    /**
     * Checks if migration is needed
     * This is determined by the existence of the "section" key within any setting
     *
     * @param {String} project
     *
     * @returns {Boolean} Migration is needed or not
     */
    static checkIfNeedsMigration(
        project = requiredParam('project')
    ) {
        return DatabaseHelper.findOne(
            project,
            'settings',
            { section: { $exists: true } }
        ).then((projectSettings) => {
            if(projectSettings && Object.keys(projectSettings).length > 0) {
                return Promise.resolve(true);
            }

            return Promise.resolve(false);
        });
    }

    /**
     * Migration check for all projects
     *
     * @returns {Promise} Result
     */
    static migrationCheck() {
        return HashBrown.Helpers.ProjectHelper.getAllProjects()
        .then((projects) => {
            let checkNext = () => {
                let project = projects.pop();

                if(!project) {
                    return Promise.resolve();
                }

                return this.checkIfNeedsMigration(project)
                .then((needsMigration) => {
                    if(!needsMigration) {
                        return Promise.resolve();
                    }

                    return this.migrateOldSettings(project, true);
                })
                .then(() => {
                    return checkNext();
                });
            };

            return checkNext();
        });
    }

    /**
     * Gets all settings
     *
     * @param {String} project
     * @param {String} environment
     * @param {String} section
     *
     * @return {Promise} Settings
     */
    static getSettings(
        project = requiredParam('project'),
        environment = null,
        section = null
    ) {
        // Is the environment is a wildcard, just discard it
        if(environment === '*') {
            environment = null;
        }

        // If the requested section is "sync", always return the local setting
        if(section === 'sync') {
            return DatabaseHelper.findOne(project, 'settings', { usedBy: 'project' })
            .then((projectSettings) => {
                if(!projectSettings) {
                    projectSettings = {};
                }

                return Promise.resolve(projectSettings.sync || {});
            });
        }

        // Find the remote resource, if applicable
        return HashBrown.Helpers.SyncHelper.getResource(project, environment, 'settings')

        // Process local settings, if applicable
        .then((remoteSettings) => {
            // If the remote settings were found, return it
            if(remoteSettings && !Array.isArray(remoteSettings)) {
                return Promise.resolve(remoteSettings);
            }

            // If not, get the local settings instead
            let query = { usedBy: 'project' };

            if(environment) {
                query.usedBy = environment;
            }

            return DatabaseHelper.findOne(project, 'settings', query);
        })

        // Return appropriate section or all settings
        .then((settings) => {
            if(!settings) {
                settings = {};
            }

            // If a section was specified, only return this content
            if(section) {
                return Promise.resolve(settings[section]);
            }

            return Promise.resolve(settings);
        });
    }

    /**
     * Sets settings
     *
     * @param {String} project
     * @param {String} environment
     * @param {String} section
     * @param {Object} settings
     * @param {Boolean} upsertEnvironment
     *
     * @return {Promise} promise
     */
    static setSettings(
        project = requiredParam('project'),
        environment = null,
        section = null,
        settings = requiredParam('settings'),
        upsertEnvironment = false
    ) {
        debug.log('Setting "' + section + '" to ' + JSON.stringify(settings), this, 3);

        // Check if the environment exists
        return HashBrown.Helpers.ProjectHelper.environmentExists(project, environment)
        .then((environmentExists) => {
            if(environment && !environmentExists && !upsertEnvironment) {
                return Promise.reject(new Error('Environment "' + environment + '" of project "' + project + '" could not be found'));
            }

            // First get the existing settings object
            return this.getSettings(project, environment);
        })
        .then((oldSettings) => {
            if(!oldSettings) {
                oldSettings = {};
            }

            // If the section is "sync", always set the local setting
            if(section === 'sync') {
                oldSettings.sync = settings;

                return DatabaseHelper.updateOne(project, 'settings', { usedBy: 'project' }, oldSettings);
            }

            // Set the remote setting, if applicable
            return HashBrown.Helpers.SyncHelper.setResourceItem(project, environment, 'settings', section, settings)
            .then((isSyncEnabled) => {
                // If the setting was synced, resolve immediately
                if(isSyncEnabled) {
                    return Promise.resolve();
                }

                // If sync was not enabled, set the local setting instead
                let query = {};
                let newSettings = oldSettings;

                // If a section was provided, only set that setting
                if(section) {
                    newSettings[section] = settings;

                    // The field isn't necessary here, so remove it if it was set somewhere
                    delete newSettings[section].usedBy;

                // If not, replace all settings
                } else {
                    newSettings = settings;
                }

                // Set the environment/project that this setting is used by
                if(environment) {
                    newSettings.usedBy = environment;
                    query.usedBy = environment;
                } else {
                    newSettings.usedBy = 'project';
                    query.usedBy = 'project';
                }

                // Update the database
                return DatabaseHelper.updateOne(
                    project,
                    'settings',
                    query,
                    newSettings,
                    { upsert: true }
                );
            });
        });
    }
}

module.exports = SettingsHelper;
<commit_msg>Fixed upsert issue with settings helper<commit_after>'use strict';

const DatabaseHelper = require('Server/Helpers/DatabaseHelper');
const SettingsHelperCommon = require('Common/Helpers/SettingsHelper');

/**
 * The helper class for settings
 *
 * @memberof HashBrown.Server.Helpers
 */
class SettingsHelper extends SettingsHelperCommon {
    /**
     * Migrates old settings format
     *
     * @param {String} project
     * @param {Boolean} commitChanges
     *
     * @returns {Promise} Promise
     */
    static migrateOldSettings(
        project = requiredParam('project'),
        commitChanges = false
    ) {
        debug.log('Migrating old settings for project "' + project + '"...', this);

        let collection = [];

        let newProjectSettings = {
            usedBy: 'project'
        };

        collection.push(newProjectSettings);

        // First check if project exists
        return DatabaseHelper.databaseExists(project)
        .then((doesExist) => {
            if(!doesExist) {
                return Promise.reject(new Error('Project by id "' + project + '" not found'));
            }

            debug.log('Getting project settings...', this, 3);

            // Then get project settings
            return DatabaseHelper.find(
                project,
                'settings',
                {}
            );
        })
        .then((projectSettings) => {
            if(!projectSettings) {
                return Promise.reject(new Error('Project settings for "' + project + '" not found'));
            }

            // Make sure there is a "live" environment
            if(!projectSettings.environments) {
                projectSettings.environments = { names: [ 'live' ] };
            }

            for(let section of projectSettings) {
                let sectionKey = section.section;

                // We're handling environments a little differently now, so skip this key
                if(sectionKey === 'environments') { continue; }

                delete section.section;

                newProjectSettings[sectionKey] = section;
            }

            // Then parse all environments
            let parseNextEnvironment = () => {
                let environment = projectSettings.environments.names.pop();

                if(!environment) {
                    return Promise.resolve();
                }

                debug.log('Getting settings for environment "' + environment + '"...', this, 3);

                return DatabaseHelper.find(
                    project,
                    environment + '.settings',
                    {}
                ).then((environmentSettings) => {
                    if(!environmentSettings) {
                        return Promise.reject(new Error('Environment settings for "' + project + '/' + environment + '" not found'));
                    }

                    let newEnvironmentSettings = {
                        usedBy: environment
                    };

                    collection.push(newEnvironmentSettings);

                    for(let section of environmentSettings) {
                        let sectionKey = section.section;

                        delete section.section;

                        if(sectionKey === 'sync') {
                            newProjectSettings.sync = {
                                project: section.project,
                                url: section.url,
                                token: section.token
                            }
                        } else {
                            newEnvironmentSettings[sectionKey] = section;
                        }
                    }

                    // Delete old docs
                    debug.log('Deleting old settings for "' + project + '/' + environment + '"...', this, 3);

                    if(!commitChanges) { return Promise.resolve(); }

                    return DatabaseHelper.remove(
                        project,
                        environment + '.settings',
                        {}
                    );
                })
                .then(() => {
                    return parseNextEnvironment();
                });
            };

            return parseNextEnvironment();
        })

        // Delete old project settings
        .then(() => {
            debug.log('Deleting old project settings...', this, 3);

            if(!commitChanges) { return Promise.resolve(); }

            return DatabaseHelper.remove(
                project,
                'settings',
                {}
            );
        })

        // Insert new collections
        .then(() => {
            debug.log('Inserting new collections...', this, 3);

            let insertNextSetting = () => {
                let setting = collection.pop();

                if(!setting) {
                    return Promise.resolve();
                }

                debug.log('Inserting "' + setting.usedBy + '": ' + JSON.stringify(setting) + '...', this, 3);

                if(!commitChanges) { return insertNextSetting(); }

                return DatabaseHelper.insertOne(
                    project,
                    'settings',
                    setting
                ).then(() => {
                    return insertNextSetting();
                });
            };

            return insertNextSetting();
        })

        // Done
        .then(() => {
            debug.log('Done migrating settings for project "' + project + '"!', this);
        });
    }

    /**
     * Checks if migration is needed
     * This is determined by the existence of the "section" key within any setting
     *
     * @param {String} project
     *
     * @returns {Boolean} Migration is needed or not
     */
    static checkIfNeedsMigration(
        project = requiredParam('project')
    ) {
        return DatabaseHelper.findOne(
            project,
            'settings',
            { section: { $exists: true } }
        ).then((projectSettings) => {
            if(projectSettings && Object.keys(projectSettings).length > 0) {
                return Promise.resolve(true);
            }

            return Promise.resolve(false);
        });
    }

    /**
     * Migration check for all projects
     *
     * @returns {Promise} Result
     */
    static migrationCheck() {
        return HashBrown.Helpers.ProjectHelper.getAllProjects()
        .then((projects) => {
            let checkNext = () => {
                let project = projects.pop();

                if(!project) {
                    return Promise.resolve();
                }

                return this.checkIfNeedsMigration(project)
                .then((needsMigration) => {
                    if(!needsMigration) {
                        return Promise.resolve();
                    }

                    return this.migrateOldSettings(project, true);
                })
                .then(() => {
                    return checkNext();
                });
            };

            return checkNext();
        });
    }

    /**
     * Gets all settings
     *
     * @param {String} project
     * @param {String} environment
     * @param {String} section
     *
     * @return {Promise} Settings
     */
    static getSettings(
        project = requiredParam('project'),
        environment = null,
        section = null
    ) {
        // Is the environment is a wildcard, just discard it
        if(environment === '*') {
            environment = null;
        }

        // If the requested section is "sync", always return the local setting
        if(section === 'sync') {
            return DatabaseHelper.findOne(project, 'settings', { usedBy: 'project' })
            .then((projectSettings) => {
                if(!projectSettings) {
                    projectSettings = {};
                }

                return Promise.resolve(projectSettings.sync || {});
            });
        }

        // Find the remote resource, if applicable
        return HashBrown.Helpers.SyncHelper.getResource(project, environment, 'settings')

        // Process local settings, if applicable
        .then((remoteSettings) => {
            // If the remote settings were found, return it
            if(remoteSettings && !Array.isArray(remoteSettings)) {
                return Promise.resolve(remoteSettings);
            }

            // If not, get the local settings instead
            let query = { usedBy: 'project' };

            if(environment) {
                query.usedBy = environment;
            }

            return DatabaseHelper.findOne(project, 'settings', query);
        })

        // Return appropriate section or all settings
        .then((settings) => {
            if(!settings) {
                settings = {};
            }

            // If a section was specified, only return this content
            if(section) {
                return Promise.resolve(settings[section]);
            }

            return Promise.resolve(settings);
        });
    }

    /**
     * Sets settings
     *
     * @param {String} project
     * @param {String} environment
     * @param {String} section
     * @param {Object} settings
     * @param {Boolean} upsertEnvironment
     *
     * @return {Promise} promise
     */
    static setSettings(
        project = requiredParam('project'),
        environment = null,
        section = null,
        settings = requiredParam('settings'),
        upsertEnvironment = false
    ) {
        debug.log('Setting "' + section + '" to ' + JSON.stringify(settings), this, 3);

        // Check if the environment exists
        return HashBrown.Helpers.ProjectHelper.environmentExists(project, environment)
        .then((environmentExists) => {
            if(environment && !environmentExists && !upsertEnvironment) {
                return Promise.reject(new Error('Environment "' + environment + '" of project "' + project + '" could not be found'));
            }

            // First get the existing settings object
            return this.getSettings(project, environment);
        })
        .then((oldSettings) => {
            if(!oldSettings) {
                oldSettings = {};
            }

            // If the section is "sync", always set the local setting
            if(section === 'sync') {
                oldSettings.sync = settings;

                return DatabaseHelper.updateOne(project, 'settings', { usedBy: 'project' }, oldSettings, { upsert: true });
            }

            // Set the remote setting, if applicable
            return HashBrown.Helpers.SyncHelper.setResourceItem(project, environment, 'settings', section, settings)
            .then((isSyncEnabled) => {
                // If the setting was synced, resolve immediately
                if(isSyncEnabled) {
                    return Promise.resolve();
                }

                // If sync was not enabled, set the local setting instead
                let query = {};
                let newSettings = oldSettings;

                // If a section was provided, only set that setting
                if(section) {
                    newSettings[section] = settings;

                    // The field isn't necessary here, so remove it if it was set somewhere
                    delete newSettings[section].usedBy;

                // If not, replace all settings
                } else {
                    newSettings = settings;
                }

                // Set the environment/project that this setting is used by
                if(environment) {
                    newSettings.usedBy = environment;
                    query.usedBy = environment;
                } else {
                    newSettings.usedBy = 'project';
                    query.usedBy = 'project';
                }

                // Update the database
                return DatabaseHelper.updateOne(
                    project,
                    'settings',
                    query,
                    newSettings,
                    { upsert: true }
                );
            });
        });
    }
}

module.exports = SettingsHelper;
<|endoftext|>