<!--
Copyright 2013, 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.
-->

<html>
<head>
<title>WebSocket benchmark</title>
<script src="util_main.js"></script>
<script src="util.js"></script>
<script src="benchmark.js"></script>
<script>
var addressBox = null;

function getConfig() {
  return {
    prefixUrl: addressBox.value,
    printSize: getBoolFromCheckBox('printsize'),
    numSockets: getIntFromInput('numsockets'),
    // Initial size of messages.
    numIterations: getIntFromInput('numiterations'),
    numWarmUpIterations: getIntFromInput('numwarmupiterations'),
    startSize: getIntFromInput('startsize'),
    // Stops benchmark when the size of message exceeds this threshold.
    stopThreshold: getIntFromInput('stopthreshold'),
    // If the size of each message is small, send/receive multiple messages
    // until the sum of sizes reaches this threshold.
    minTotal: getIntFromInput('mintotal'),
    multipliers: getIntArrayFromInput('multipliers'),
    verifyData: getBoolFromCheckBox('verifydata')
  };
}

var worker = new Worker('benchmark.js');
worker.onmessage = onMessage;

function onSendBenchmark() {
  var config = getConfig();

  if (getBoolFromCheckBox('worker')) {
    worker.postMessage({type: 'sendBenchmark', config: config});
  } else {
    config.addToLog = addToLog;
    config.addToSummary = addToSummary;
    config.measureValue = measureValue;
    sendBenchmark(config);
  }
}

function onReceiveBenchmark() {
  var config = getConfig();

  if (getBoolFromCheckBox('worker')) {
    worker.postMessage({type: 'receiveBenchmark', config: config});
  } else {
    config.addToLog = addToLog;
    config.addToSummary = addToSummary;
    config.measureValue = measureValue;
    receiveBenchmark(config);
  }
}

function onBatchBenchmark() {
  var config = getConfig();

  if (getBoolFromCheckBox('worker')) {
    worker.postMessage({type: 'batchBenchmark', config: config});
  } else {
    config.addToLog = addToLog;
    config.addToSummary = addToSummary;
    config.measureValue = measureValue;
    batchBenchmark(config);
  }
}

function onStop() {
  var config = getConfig();

  if (getBoolFromCheckBox('worker')) {
    worker.postMessage({type: 'stop', config: config});
  } else {
    config.addToLog = addToLog;
    config.addToSummary = addToSummary;
    config.measureValue = measureValue;
    stop(config);
  }
}
function init() {
  addressBox = document.getElementById('address');
  logBox = document.getElementById('log');

  summaryBox = document.getElementById('summary');

  var scheme = window.location.protocol == 'https:' ? 'wss://' : 'ws://';
  var defaultAddress = scheme + window.location.host + '/benchmark_helper';

  addressBox.value = defaultAddress;

  addToLog(window.navigator.userAgent.toLowerCase());
  addToSummary(window.navigator.userAgent.toLowerCase());

  if (!('WebSocket' in window)) {
    addToLog('WebSocket is not available');
  }
}
</script>
</head>
<body onload="init()">

<div id="benchmark_div">
  url <input type="text" id="address" size="40">
  <input type="button" value="send" onclick="onSendBenchmark()">
  <input type="button" value="receive" onclick="onReceiveBenchmark()">
  <input type="button" value="batch" onclick="onBatchBenchmark()">
  <input type="button" value="stop" onclick="onStop()">

  <br/>

  <input type="checkbox" id="printsize" checked>
  <label for="printsize">Print size and time per message</label>
  <input type="checkbox" id="verifydata" checked>
  <label for="verifydata">Verify data</label>
  <input type="checkbox" id="worker">
  <label for="worker">Run on worker</label>

  <br/>

  Parameters:

  <br/>

  <table>
    <tr>
      <td>Num sockets</td>
      <td><input type="text" id="numsockets" value="1"></td>
    </tr>
    <tr>
      <td>Number of iterations</td>
      <td><input type="text" id="numiterations" value="1"></td>
    </tr>
    <tr>
      <td>Number of warm-up iterations</td>
      <td><input type="text" id="numwarmupiterations" value="0"></td>
    </tr>
    <tr>
      <td>Start size</td>
      <td><input type="text" id="startsize" value="10240"></td>
    </tr>
    <tr>
      <td>Stop threshold</td>
      <td><input type="text" id="stopthreshold" value="102400000"></td>
    </tr>
    <tr>
      <td>Minimum total</td>
      <td><input type="text" id="mintotal" value="102400000"></td>
    </tr>
    <tr>
      <td>Multipliers</td>
      <td><input type="text" id="multipliers" value="5, 2"></td>
    </tr>
  </table>
</div>

<div id="log_div">
  <textarea
      id="log" rows="20" style="width: 100%" readonly></textarea>
</div>
<div id="summary_div">
  Summary
  <textarea
      id="summary" rows="20" style="width: 100%" readonly></textarea>
</div>

Note: Effect of RTT is not eliminated.

</body>
</html>
