<commit_before>/*
 * Copyright 2009, 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.
 */

/**
 * @fileoverview This file contains a basic utility library that simplifies the
 * creation of simple 2D Canvas surfaces for the purposes of drawing 2D elements
 * in O3D.
 *
 * Example
 *
 *

 * <html><body>
 * <script type="text/javascript" src="o3djs/all.js">
 * </script>
 * <script>
 * window.onload = init;
 *
 * function init() {
 *   o3djs.base.makeClients(initStep2);
 * }
 *
 * function initStep2(clientElements) {
 *   var clientElement = clientElements[0];
 *   var client = clientElement.client;
 *   var pack = client.createPack();
 *   var viewInfo = o3djs.rendergraph.createBasicView(
 *       pack,
 *       client.root,
 *       client.renderGraphRoot);
 *
 *   // Create an instance of the canvas utility library.
 *   var canvasLib = o3djs.canvas.create(
 *       pack, client.root, g_viewInfo);
 *
 *   // Create a 700x500 rectangle at (x,y,z) = (4, 10, 0)
 *   var canvasQuad = canvasLib.createXYQuad(4, 10, 0, 700, 500, false);
 *
 *   // Draw into the canvas.
 *   canvasQuad.canvas.clear([1, 0, 0, 1]);
 *   canvasQuad.canvas.drawText('Hello', 0, 10, canvasPaint);
 *   ...
 *   ...
 *
 *   // Update the o3d texture associated with the canvas.
 *   canvasQuad.updateTexture();
 * }
 * </script>
 * <div id="o3d" style="width: 600px; height: 600px"></div>
 * </body></html>
 *

 *
 */

o3djs.provide('o3djs.canvas');

o3djs.require('o3djs.effect');
o3djs.require('o3djs.primitives');

/**
 * A Module for using a 2d canvas.
 * @namespace
 */
o3djs.canvas = o3djs.canvas || {};

/**
 * Creates an o3djs.canvas library object through which CanvasQuad objects
 * can be created.
 * @param {!o3d.Pack} pack to manage objects created by this library.
 * @param {!o3d.Transform} root Default root for visual objects.
 * @param {!o3djs.rendergraph.ViewInfo} viewInfo A ViewInfo object as
 *  created by o3djs.createView which contains draw lists that the created
 *  quads will be placed into.
 * @return {!o3djs.canvas.CanvasInfo} A CanvasInfo object containing
 *         references to all the common O3D elements used by this instance
 *         of the library.
 */
o3djs.canvas.create = function(pack, root, viewInfo) {
  return new o3djs.canvas.CanvasInfo(pack, root, viewInfo);
};

/**
 * The shader code used by the canvas quads.  It only does two things:
 *   1. Transforms the shape to screen space via the worldViewProjection matrix.
 *   2. Performs a texture lookup to display the contents of the texture
 *      bound to texSampler0.
 * @type {string}
 */
o3djs.canvas.FX_STRING =
    'float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
    'sampler texSampler0;\n' +
    'struct VertexShaderInput {\n' +
    ' float4 position : POSITION;\n' +
    ' float2 texcoord : TEXCOORD0;\n' +
    '};\n'+
    'struct PixelShaderInput {\n' +
    '  float4 position : POSITION;\n' +
    '  float2 texcoord : TEXCOORD0;\n' +
    '};\n' +
    'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
    '  PixelShaderInput output;\n' +
    '  output.position = mul(input.position, worldViewProjection);\n' +
    '  output.texcoord = input.texcoord;\n' +
    '  return output;\n' +
    '}\n' +
    'float4 pixelShaderFunction(PixelShaderInput input): COLOR {\n' +
    '  return tex2D(texSampler0, input.texcoord);\n' +
    '}\n' +
    '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
    '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
    '// #o3d MatrixLoadOrder RowMajor\n';

/**
 * The CanvasInfo object creates and keeps references to the O3D objects
 * that are shared between all CanvasQuad objects created through it.
 * @constructor
 * @param {!o3d.Pack} pack Pack to manage CanvasInfo objects.
 * @param {!o3d.Transform} root Default root for visual objects.
 * @param {!o3djs.rendergraph.ViewInfo} viewInfo A ViewInfo object as
 *     created by o3djs.createView which contains draw lists that the
 *     created quads will be placed into.
 */
o3djs.canvas.CanvasInfo = function(pack, root, viewInfo) {
  /**
   * The pack being used to manage objects created by this CanvasInfo.
   * @type {!o3d.Pack}
   */
  this.pack = pack;

  /**
   * The ViewInfo this CanvasInfo uses for rendering.
   * @type {!o3djs.rendergraph.ViewInfo}
   */
  this.viewInfo = viewInfo;

  /**
   * The default root for objects created by this CanvasInfo.
   * @type {!o3d.Transform}
   */
  this.root = root;

  // Create the Effect object shared by all CanvasQuad instances.
  this.effect = this.pack.createObject('Effect');
  this.effect.loadFromFXString(o3djs.canvas.FX_STRING);

  // Create two materials:  One used for canvases with transparent content
  // and one for opaque canvases.
  this.transparentMaterial = this.pack.createObject('Material');
  this.opaqueMaterial = this.pack.createObject('Material');

  this.transparentMaterial.effect = this.effect;
  this.opaqueMaterial.effect = this.effect;

  this.transparentMaterial.drawList = viewInfo.zOrderedDrawList;
  this.opaqueMaterial.drawList = viewInfo.performanceDrawList;

  // Create a state object to handle the transparency blending mode
  // for transparent canvas quads.
  // The canvas bitmap already multiplies the color values by alpha.  In order
  // to avoid a black halo around text drawn on a transparent background we
  // need to set the blending mode as follows.
  this.transparentState = this.pack.createObject('State');
  this.transparentState.getStateParam('AlphaBlendEnable').value = true;
  this.transparentState.getStateParam('SourceBlendFunction').value =
      o3djs.base.o3d.State.BLENDFUNC_ONE;
  this.transparentState.getStateParam('DestinationBlendFunction').value =
      o3djs.base.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA;

  this.transparentMaterial.state = this.transparentState;

  // Create 2d plane shapes. createPlane makes an XZ plane by default
  // so we pass in matrix to rotate it to an XY plane. We could do
  // all our manipulations in XZ but most people seem to like XY for 2D.

  /**
   * A shape for transparent quads.
   * @type {!o3d.Shape}
   */
  this.transparentQuadShape = o3djs.primitives.createPlane(
      this.pack,
      this.transparentMaterial,
      1,
      1,
      1,
      1,
      [[1, 0, 0, 0],
       [0, 0, 1, 0],
       [0, -1, 0, 0],
       [0, 0, 0, 1]]);

  /**
   * A shape for opaque quads.
   * @type {!o3d.Shape}
   */
  this.opaqueQuadShape = o3djs.primitives.createPlane(
      this.pack,
      this.opaqueMaterial,
      1,
      1,
      1,
      1,
      [[1, 0, 0, 0],
       [0, 0, 1, 0],
       [0, -1, 0, 0],
       [0, 0, 0, 1]]);
};
/**
 * The CanvasQuad object encapsulates a Transform, a rectangle Shape,
 * an effect that applies a texture to render the quad, and a matching Canvas
 * object that can render into the texture.  The dimensions of the texture and
 * the canvas object match those of the quad in order to get pixel-accurate
 * results with the appropriate orthographic projection.
 * The resulting rectangle Shape is positioned at the origin.  It can be moved
 * around by setting the localMatrix on the Transform object referenced to by
 * the canvasQuad.transform property.
 * The Canvas associated with the returned CanvasQuad object can be retrieved
 * from the object's 'canvas' property.  After issuing any draw commands on the
 * Canvas, you need to call the updateTexture() method on the CanvasQuad to
 * update the contents of the quad surface.
 * @constructor
 * @param {!o3djs.canvas.CanvasInfo} canvasInfo The CanvasInfo object
 *     instance creating this CanvasQuad.
 * @param {number} width The width of the quad.
 * @param {number} height The height of the quad.
 * @param {boolean} transparent Set to true if the canvas will
 *     be transparent so that the appropriate blending modes are set.
 * @param {!o3d.Transform} opt_parent parent transform to parent
 *     the newly created quad under. If no parent transform is provided then
 *     the quad gets parented under the CanvasInfo's root.
 */
o3djs.canvas.CanvasQuad = function(canvasInfo,
                                   width,
                                   height,
                                   transparent,
                                   opt_parent) {
  this.canvasInfo = canvasInfo;
  var parentTransform = opt_parent || canvasInfo.root;

  // create a transform for positioning

  /**
   * A transform for this quad.
   * @type {!o3d.Transform}
   */
  this.transform = canvasInfo.pack.createObject('Transform');
  this.transform.parent = parentTransform;

  // create a transform for scaling to the size of the image just so
  // we don't have to manage that manually in the transform above.

  /**
   * A scale transform for this quad.
   * You can change the scale the quad without effecting its positon using
   * this transform.
   * @type {!o3d.Transform}
   */
  this.scaleTransform = canvasInfo.pack.createObject('Transform');
  this.scaleTransform.parent = this.transform;

  // create the texture the canvas will draw on.
  this.texture = canvasInfo.pack.createTexture2D(
      width,
      height,
      o3djs.base.o3d.Texture.ARGB8,
      1, // mipmap levels
      false);

  // Create a Canvas object to go with the quad.

  /**
   * The Canvas object used to draw on this quad.
   * @type {!o3d.Canvas}
   */
  this.canvas = canvasInfo.pack.createObject('Canvas');
  this.canvas.setSize(width, height);

  // setup the sampler for the texture
  this.sampler = canvasInfo.pack.createObject('Sampler');
  this.sampler.addressModeU = o3djs.base.o3d.Sampler.CLAMP;
  this.sampler.addressModeV = o3djs.base.o3d.Sampler.CLAMP;
  this.paramSampler = this.scaleTransform.createParam('texSampler0',
                                                      'ParamSampler');
  this.paramSampler.value = this.sampler;

  this.sampler.texture = this.texture;
  if (transparent) {
    this.scaleTransform.addShape(canvasInfo.transparentQuadShape);
  } else {
    this.scaleTransform.addShape(canvasInfo.opaqueQuadShape);
  }
  this.scaleTransform.translate(width / 2, height / 2, 0);
  this.scaleTransform.scale(width, -height, 1);
};

/**
 * Copies the current contents of the Canvas object to the texture associated
 * with the quad.  This method should be called after any new draw calls have
 * been issued to the CanvasQuad's Canvas object.
 */
o3djs.canvas.CanvasQuad.prototype.updateTexture = function() {
  this.canvas.copyToTexture(this.texture);
};

/**
 * Creates a CanvasQuad object on the XY plane at the specified position.
 * @param {number} topX The x coordinate of the top left corner of the quad.
 * @param {number} topY The y coordinate of the top left corner of the quad.
 * @param {number} z The z coordinate of the quad.  z values are negative
 *     numbers, the smaller the number the further back the quad will be.
 * @param {number} width The width of the quad.
 * @param {number} height The height of the quad.
 * @param {boolean} transparent Set to true if the canvas bitmap uses
 *     transparency so that the appropriate blending modes are set.
 * @param {!o3d.Transform} opt_parent parent transform to parent the newly
 *     created quad under.  If no parent transform is provided then the quad
 *     gets parented under the CanvasInfo's root.
 * @return {!o3djs.canvas.CanvasQuad} The newly created CanvasQuad object.
 */
o3djs.canvas.CanvasInfo.prototype.createXYQuad = function(topX,
                                                          topY,
                                                          z,
                                                          width,
                                                          height,
                                                          transparent,
                                                          opt_parent) {
  var canvasQuad = new o3djs.canvas.CanvasQuad(this,
                                               width,
                                               height,
                                               transparent,
                                               opt_parent);

  canvasQuad.transform.translate(topX, topY, z);
  return canvasQuad;
};

/**
 * Creates a CanvasQuad object of the given size. The resulting rectangle Shape
 * is centered at the origin.  It can be moved around by setting the
 * localMatrix on the Transform object referenced to by the canvasQuad.transform
 * property.
 * @param {number} width The width of the quad.
 * @param {number} height The height of the quad.
 * @param {boolean} transparent Set to true if the canvas bitmap uses
 *     transparency so that the appropriate blending modes are set.
 * @param {!o3d.Transform} opt_parent parent transform to parent the newly
 *     created quad under.  If no parent transform is provided then the quad
 *     gets parented under the CanvasInfo's root.
 * @return {!o3djs.canvas.CanvasQuad} The newly created CanvasQuad object.
 */
o3djs.canvas.CanvasInfo.prototype.createQuad = function(width,
                                                        height,
                                                        transparent,
                                                        opt_parent) {
  return new o3djs.canvas.CanvasQuad(this,
                                     width,
                                     height,
                                     transparent,
                                     opt_parent);
};
<commit_msg>Some minor JS fixes<commit_after>/*
 * Copyright 2009, 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.
 */

/**
 * @fileoverview This file contains a basic utility library that simplifies the
 * creation of simple 2D Canvas surfaces for the purposes of drawing 2D elements
 * in O3D.
 *
 * Example
 *
 *

 * <html><body>
 * <script type="text/javascript" src="o3djs/all.js">
 * </script>
 * <script>
 * window.onload = init;
 *
 * function init() {
 *   o3djs.base.makeClients(initStep2);
 * }
 *
 * function initStep2(clientElements) {
 *   var clientElement = clientElements[0];
 *   var client = clientElement.client;
 *   var pack = client.createPack();
 *   var viewInfo = o3djs.rendergraph.createBasicView(
 *       pack,
 *       client.root,
 *       client.renderGraphRoot);
 *
 *   // Create an instance of the canvas utility library.
 *   var canvasLib = o3djs.canvas.create(
 *       pack, client.root, g_viewInfo);
 *
 *   // Create a 700x500 rectangle at (x,y,z) = (4, 10, 0)
 *   var canvasQuad = canvasLib.createXYQuad(4, 10, 0, 700, 500, false);
 *
 *   // Draw into the canvas.
 *   canvasQuad.canvas.clear([1, 0, 0, 1]);
 *   canvasQuad.canvas.drawText('Hello', 0, 10, canvasPaint);
 *   ...
 *   ...
 *
 *   // Update the o3d texture associated with the canvas.
 *   canvasQuad.updateTexture();
 * }
 * </script>
 * <div id="o3d" style="width: 600px; height: 600px"></div>
 * </body></html>
 *

 *
 */

o3djs.provide('o3djs.canvas');

o3djs.require('o3djs.effect');
o3djs.require('o3djs.primitives');

/**
 * A Module for using a 2d canvas.
 * @namespace
 */
o3djs.canvas = o3djs.canvas || {};

/**
 * Creates an o3djs.canvas library object through which CanvasQuad objects
 * can be created.
 * @param {!o3d.Pack} pack to manage objects created by this library.
 * @param {!o3d.Transform} root Default root for visual objects.
 * @param {!o3djs.rendergraph.ViewInfo} viewInfo A ViewInfo object as
 *  created by o3djs.createView which contains draw lists that the created
 *  quads will be placed into.
 * @return {!o3djs.canvas.CanvasInfo} A CanvasInfo object containing
 *         references to all the common O3D elements used by this instance
 *         of the library.
 */
o3djs.canvas.create = function(pack, root, viewInfo) {
  return new o3djs.canvas.CanvasInfo(pack, root, viewInfo);
};

/**
 * The shader code used by the canvas quads.  It only does two things:
 *   1. Transforms the shape to screen space via the worldViewProjection matrix.
 *   2. Performs a texture lookup to display the contents of the texture
 *      bound to texSampler0.
 * @type {string}
 */
o3djs.canvas.FX_STRING =
    'float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
    'sampler texSampler0;\n' +
    'struct VertexShaderInput {\n' +
    ' float4 position : POSITION;\n' +
    ' float2 texcoord : TEXCOORD0;\n' +
    '};\n'+
    'struct PixelShaderInput {\n' +
    '  float4 position : POSITION;\n' +
    '  float2 texcoord : TEXCOORD0;\n' +
    '};\n' +
    'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
    '  PixelShaderInput output;\n' +
    '  output.position = mul(input.position, worldViewProjection);\n' +
    '  output.texcoord = input.texcoord;\n' +
    '  return output;\n' +
    '}\n' +
    'float4 pixelShaderFunction(PixelShaderInput input): COLOR {\n' +
    '  return tex2D(texSampler0, input.texcoord);\n' +
    '}\n' +
    '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
    '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
    '// #o3d MatrixLoadOrder RowMajor\n';

/**
 * The CanvasInfo object creates and keeps references to the O3D objects
 * that are shared between all CanvasQuad objects created through it.
 * @constructor
 * @param {!o3d.Pack} pack Pack to manage CanvasInfo objects.
 * @param {!o3d.Transform} root Default root for visual objects.
 * @param {!o3djs.rendergraph.ViewInfo} viewInfo A ViewInfo object as
 *     created by o3djs.createView which contains draw lists that the
 *     created quads will be placed into.
 */
o3djs.canvas.CanvasInfo = function(pack, root, viewInfo) {
  /**
   * The pack being used to manage objects created by this CanvasInfo.
   * @type {!o3d.Pack}
   */
  this.pack = pack;

  /**
   * The ViewInfo this CanvasInfo uses for rendering.
   * @type {!o3djs.rendergraph.ViewInfo}
   */
  this.viewInfo = viewInfo;

  /**
   * The default root for objects created by this CanvasInfo.
   * @type {!o3d.Transform}
   */
  this.root = root;

  // Create the Effect object shared by all CanvasQuad instances.
  this.effect = this.pack.createObject('Effect');
  this.effect.loadFromFXString(o3djs.canvas.FX_STRING);

  // Create two materials:  One used for canvases with transparent content
  // and one for opaque canvases.
  this.transparentMaterial = this.pack.createObject('Material');
  this.opaqueMaterial = this.pack.createObject('Material');

  this.transparentMaterial.effect = this.effect;
  this.opaqueMaterial.effect = this.effect;

  this.transparentMaterial.drawList = viewInfo.zOrderedDrawList;
  this.opaqueMaterial.drawList = viewInfo.performanceDrawList;

  // Create a state object to handle the transparency blending mode
  // for transparent canvas quads.
  // The canvas bitmap already multiplies the color values by alpha.  In order
  // to avoid a black halo around text drawn on a transparent background we
  // need to set the blending mode as follows.
  this.transparentState = this.pack.createObject('State');
  this.transparentState.getStateParam('AlphaBlendEnable').value = true;
  this.transparentState.getStateParam('SourceBlendFunction').value =
      o3djs.base.o3d.State.BLENDFUNC_ONE;
  this.transparentState.getStateParam('DestinationBlendFunction').value =
      o3djs.base.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA;

  this.transparentMaterial.state = this.transparentState;

  // Create 2d plane shapes. createPlane makes an XZ plane by default
  // so we pass in matrix to rotate it to an XY plane. We could do
  // all our manipulations in XZ but most people seem to like XY for 2D.

  /**
   * A shape for transparent quads.
   * @type {!o3d.Shape}
   */
  this.transparentQuadShape = o3djs.primitives.createPlane(
      this.pack,
      this.transparentMaterial,
      1,
      1,
      1,
      1,
      [[1, 0, 0, 0],
       [0, 0, 1, 0],
       [0, -1, 0, 0],
       [0, 0, 0, 1]]);

  /**
   * A shape for opaque quads.
   * @type {!o3d.Shape}
   */
  this.opaqueQuadShape = o3djs.primitives.createPlane(
      this.pack,
      this.opaqueMaterial,
      1,
      1,
      1,
      1,
      [[1, 0, 0, 0],
       [0, 0, 1, 0],
       [0, -1, 0, 0],
       [0, 0, 0, 1]]);
};
/**
 * The CanvasQuad object encapsulates a Transform, a rectangle Shape,
 * an effect that applies a texture to render the quad, and a matching Canvas
 * object that can render into the texture.  The dimensions of the texture and
 * the canvas object match those of the quad in order to get pixel-accurate
 * results with the appropriate orthographic projection.
 * The resulting rectangle Shape is positioned at the origin.  It can be moved
 * around by setting the localMatrix on the Transform object referenced to by
 * the canvasQuad.transform property.
 * The Canvas associated with the returned CanvasQuad object can be retrieved
 * from the object's 'canvas' property.  After issuing any draw commands on the
 * Canvas, you need to call the updateTexture() method on the CanvasQuad to
 * update the contents of the quad surface.
 * @constructor
 * @param {!o3djs.canvas.CanvasInfo} canvasInfo The CanvasInfo object
 *     instance creating this CanvasQuad.
 * @param {number} width The width of the quad.
 * @param {number} height The height of the quad.
 * @param {boolean} transparent Set to true if the canvas will
 *     be transparent so that the appropriate blending modes are set.
 * @param {!o3d.Transform} opt_parent parent transform to parent
 *     the newly created quad under. If no parent transform is provided then
 *     the quad gets parented under the CanvasInfo's root.
 */
o3djs.canvas.CanvasQuad = function(canvasInfo,
                                   width,
                                   height,
                                   transparent,
                                   opt_parent) {
  this.canvasInfo = canvasInfo;
  var parentTransform = opt_parent || canvasInfo.root;

  // create a transform for positioning

  /**
   * A transform for this quad.
   * @type {!o3d.Transform}
   */
  this.transform = canvasInfo.pack.createObject('Transform');
  this.transform.parent = parentTransform;

  // create a transform for scaling to the size of the image just so
  // we don't have to manage that manually in the transform above.

  /**
   * A scale transform for this quad.
   * You can change the scale the quad without effecting its positon using
   * this transform.
   * @type {!o3d.Transform}
   */
  this.scaleTransform = canvasInfo.pack.createObject('Transform');
  this.scaleTransform.parent = this.transform;

  /**
   * The texture the canvas will draw on.
   * @type {!o3d.Texture2D}
   */
  this.texture = /** @type {!o3d.Texture2D} */ (canvasInfo.pack.createTexture2D(
      width,
      height,
      o3djs.base.o3d.Texture.ARGB8,
      1, // mipmap levels
      false));

  // Create a Canvas object to go with the quad.

  /**
   * The Canvas object used to draw on this quad.
   * @type {!o3d.Canvas}
   */
  this.canvas = canvasInfo.pack.createObject('Canvas');
  this.canvas.setSize(width, height);

  /**
   * The sampler for the texture.
   * @type {!o3d.Sampler}
   */
  this.sampler = canvasInfo.pack.createObject('Sampler');
  this.sampler.addressModeU = o3djs.base.o3d.Sampler.CLAMP;
  this.sampler.addressModeV = o3djs.base.o3d.Sampler.CLAMP;

  /**
   * The param sampler for this transform.
   * @private
   * @type {!o3d.ParamSampler}
   */
  this.paramSampler_ = this.scaleTransform.createParam('texSampler0',
                                                       'ParamSampler');
  this.paramSampler_.value = this.sampler;

  this.sampler.texture = this.texture;
  if (transparent) {
    this.scaleTransform.addShape(canvasInfo.transparentQuadShape);
  } else {
    this.scaleTransform.addShape(canvasInfo.opaqueQuadShape);
  }
  this.scaleTransform.translate(width / 2, height / 2, 0);
  this.scaleTransform.scale(width, -height, 1);
};

/**
 * Copies the current contents of the Canvas object to the texture associated
 * with the quad.  This method should be called after any new draw calls have
 * been issued to the CanvasQuad's Canvas object.
 */
o3djs.canvas.CanvasQuad.prototype.updateTexture = function() {
  this.canvas.copyToTexture(this.texture);
};

/**
 * Creates a CanvasQuad object on the XY plane at the specified position.
 * @param {number} topX The x coordinate of the top left corner of the quad.
 * @param {number} topY The y coordinate of the top left corner of the quad.
 * @param {number} z The z coordinate of the quad.  z values are negative
 *     numbers, the smaller the number the further back the quad will be.
 * @param {number} width The width of the quad.
 * @param {number} height The height of the quad.
 * @param {boolean} transparent Set to true if the canvas bitmap uses
 *     transparency so that the appropriate blending modes are set.
 * @param {!o3d.Transform} opt_parent parent transform to parent the newly
 *     created quad under.  If no parent transform is provided then the quad
 *     gets parented under the CanvasInfo's root.
 * @return {!o3djs.canvas.CanvasQuad} The newly created CanvasQuad object.
 */
o3djs.canvas.CanvasInfo.prototype.createXYQuad = function(topX,
                                                          topY,
                                                          z,
                                                          width,
                                                          height,
                                                          transparent,
                                                          opt_parent) {
  var canvasQuad = new o3djs.canvas.CanvasQuad(this,
                                               width,
                                               height,
                                               transparent,
                                               opt_parent);

  canvasQuad.transform.translate(topX, topY, z);
  return canvasQuad;
};

/**
 * Creates a CanvasQuad object of the given size. The resulting rectangle Shape
 * is centered at the origin.  It can be moved around by setting the
 * localMatrix on the Transform object referenced to by the canvasQuad.transform
 * property.
 * @param {number} width The width of the quad.
 * @param {number} height The height of the quad.
 * @param {boolean} transparent Set to true if the canvas bitmap uses
 *     transparency so that the appropriate blending modes are set.
 * @param {!o3d.Transform} opt_parent parent transform to parent the newly
 *     created quad under.  If no parent transform is provided then the quad
 *     gets parented under the CanvasInfo's root.
 * @return {!o3djs.canvas.CanvasQuad} The newly created CanvasQuad object.
 */
o3djs.canvas.CanvasInfo.prototype.createQuad = function(width,
                                                        height,
                                                        transparent,
                                                        opt_parent) {
  return new o3djs.canvas.CanvasQuad(this,
                                     width,
                                     height,
                                     transparent,
                                     opt_parent);
};
<|endoftext|>


<commit_before>// Karma configuration

var fs = require("fs");
module.exports = function(config) {
  var customLaunchers = {
    'SL_Chrome_Latest': {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'OS X 10.10'
    },
    'SL_Chrome_48': {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'OS X 10.10',
      version: '48'
    },
    'SL_Chrome_41': { // Fetch support added in Chrome 42
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'OS X 10.10',
      version: '41'
    },
    'SL_Firefox_Latest': {
      base: 'SauceLabs',
      browserName: 'firefox',
      platform: 'OS X 10.10'
    },
    'SL_Firefox_52': {
      base: 'SauceLabs',
      browserName: 'firefox',
      platform: 'OS X 10.10',
      version: '52'
    },
    'SL_Firefox_38': { // Fetch support added in Firefox 39
      base: 'SauceLabs',
      browserName: 'firefox',
      platform: 'OS X 10.10',
      version: '38'
    }
  };

  var reporters = ['dots'];
  var browsers = [];
  var singlerun = false;
  var concurrency = Infinity;

  if (process.env.SAUCE_USERNAME) {
    reporters.push('saucelabs');
    Array.prototype.push.apply(browsers, Object.keys(customLaunchers));
    singlerun = true;
    concurrency = 2;
  }

  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    sauceLabs: {
      recordScreenshots: false,
      avoidProxy: true,
      connectOptions: {
        port: 5757,
        logfile: 'sauce_connect.log'
      },
      public: 'public'
    },
    files: [
      'ts/build/integration-tests.js'
    ],
    preprocessors: {
      '**/*.js': ['sourcemap']
    },
    reporters: reporters,
    port: 9876,
    protocol: "https",
    httpsServerOptions: {
      key: fs.readFileSync('../misc/localhost.key', 'utf8'),
      cert: fs.readFileSync('../misc/localhost.crt', 'utf8')
    },
    colors: true,
    client: {
      captureConsole: true,
      runInParent: true,
      useIframe: false,
    },
    autoWatch: true,
    browsers: browsers,
    captureTimeout: 120000,
    customLaunchers: customLaunchers,
    singleRun: singlerun,
    concurrency: concurrency
  })
};
<commit_msg>Using OS X 10.12<commit_after>// Karma configuration

var fs = require("fs");
module.exports = function(config) {
  var customLaunchers = {
    'SL_Chrome_Latest': {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'OS X 10.12'
    },
    'SL_Chrome_48': {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'OS X 10.12',
      version: '48'
    },
    'SL_Chrome_41': { // Fetch support added in Chrome 42
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'OS X 10.12',
      version: '41'
    },
    'SL_Firefox_Latest': {
      base: 'SauceLabs',
      browserName: 'firefox',
      platform: 'OS X 10.12'
    },
    'SL_Firefox_52': {
      base: 'SauceLabs',
      browserName: 'firefox',
      platform: 'OS X 10.12',
      version: '52'
    },
    'SL_Firefox_38': { // Fetch support added in Firefox 39
      base: 'SauceLabs',
      browserName: 'firefox',
      platform: 'OS X 10.12',
      version: '38'
    }
  };

  var reporters = ['dots'];
  var browsers = [];
  var singlerun = false;
  var concurrency = Infinity;

  if (process.env.SAUCE_USERNAME) {
    reporters.push('saucelabs');
    Array.prototype.push.apply(browsers, Object.keys(customLaunchers));
    singlerun = true;
    concurrency = 2;
  }

  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    sauceLabs: {
      recordScreenshots: false,
      avoidProxy: true,
      connectOptions: {
        port: 5757,
        logfile: 'sauce_connect.log'
      },
      public: 'public'
    },
    files: [
      'ts/build/integration-tests.js'
    ],
    preprocessors: {
      '**/*.js': ['sourcemap']
    },
    reporters: reporters,
    port: 9876,
    protocol: "https",
    httpsServerOptions: {
      key: fs.readFileSync('../misc/localhost.key', 'utf8'),
      cert: fs.readFileSync('../misc/localhost.crt', 'utf8')
    },
    colors: true,
    client: {
      captureConsole: true,
      runInParent: true,
      useIframe: false,
    },
    autoWatch: true,
    browsers: browsers,
    captureTimeout: 120000,
    customLaunchers: customLaunchers,
    singleRun: singlerun,
    concurrency: concurrency
  })
};
<|endoftext|>


<commit_before>'use strict'

const { Application } = require('spectron')
const assert = require('assert')
const tmp = require('tmp')

describe('Logging in', function() {
  this.timeout(15000)

  beforeEach(function() {
    // Start each test with a blank user profile
    this.userData = tmp.dirSync()
    this.app = new Application({
      args: [ 'app/main.js' ],
      env: {
        NODE_ENV: 'test',
        SOUNDCLEOD_USER_DATA_PATH: this.userData.name
      },
      path: 'node_modules/.bin/electron',
      waitTimeout: 10000
    })
    return this.app.start()
  })

  afterEach(function() {
    if (this.app && this.app.isRunning())
      return this.app.stop()
  })

  it('shows Facebook login in the main window', function() {
    return this.app.client
      .waitForVisible('#content')
      .element('#content')
      .click('button=Sign in')
      .waitForVisible('=Continue with Facebook')
      .click('=Continue with Facebook')
      .waitForVisible('span=Log into Facebook')
      .then(() => this.app.client.getUrl())
      .then(url => assertFacebookLogin(url))
      .then(() => this.app.client.getWindowCount())
      .then(windowCount => assert.equal(windowCount, 1, 'No popup is open'))
  })

  it('shows Google login in a popup', function() {
    return this.app.client
      .waitForVisible('#content')
      .element('#content')
      .click('button=Sign in')
      .waitForVisible('button=Continue with Google')
      .click('button=Continue with Google')
      .waitUntil(() => this.app.client.getWindowCount().then(count => count > 1))
      .then(() => this.app.client.getWindowCount())
      .then(windowCount => assert.equal(windowCount, 2, 'Opened a popup'))
  })

  function assertFacebookLogin(url) {
    assert.ok(url.includes('www.facebook.com/login'), `'${url}' looks like a Facebook url`)
  }
})
<commit_msg>More flaky test attempts<commit_after>'use strict'

const { Application } = require('spectron')
const assert = require('assert')
const tmp = require('tmp')

describe('Logging in', function() {
  this.timeout(15000)

  beforeEach(function() {
    // Start each test with a blank user profile
    this.userData = tmp.dirSync()
    this.app = new Application({
      args: [ 'app/main.js' ],
      env: {
        NODE_ENV: 'test',
        SOUNDCLEOD_USER_DATA_PATH: this.userData.name
      },
      path: 'node_modules/.bin/electron',
      waitTimeout: 10000
    })
    return this.app.start()
  })

  afterEach(function() {
    if (this.app && this.app.isRunning())
      return this.app.stop()
  })

  it('shows Facebook login in the main window', function() {
    return this.app.client
      .waitForVisible('button=Sign in')
      .element('#content')
      .click('button=Sign in')
      .waitForVisible('=Continue with Facebook')
      .click('=Continue with Facebook')
      .waitForVisible('span=Log into Facebook')
      .then(() => this.app.client.getUrl())
      .then(url => assertFacebookLogin(url))
      .then(() => this.app.client.getWindowCount())
      .then(windowCount => assert.equal(windowCount, 1, 'No popup is open'))
  })

  it('shows Google login in a popup', function() {
    return this.app.client
      .waitForVisible('button=Sign in')
      .element('#content')
      .click('button=Sign in')
      .waitForVisible('button=Continue with Google')
      .click('button=Continue with Google')
      .waitUntil(() => this.app.client.getWindowCount().then(count => count > 1))
      .then(() => this.app.client.getWindowCount())
      .then(windowCount => assert.equal(windowCount, 2, 'Opened a popup'))
  })

  function assertFacebookLogin(url) {
    assert.ok(url.includes('www.facebook.com/login'), `'${url}' looks like a Facebook url`)
  }
})
<|endoftext|>


<commit_before>var ejs = require('ejs');
var path = require('path');
var bodyParser = require('body-parser');
var lactate = require('lactate');
var routers = require('./router/routersIndex');
var connect = require('connect');
var getIPlist = require('./lib').getIPlist;
var forward = require('../src');
let env = process.env.NODE_ENV || 'dev';
//bind to global var
global.$g = global.$g || {};
global.$g.port = require('./package.json').config.port;
global.$g.ips = getIPlist();
global.$g.hosts = global.$g.ips.map(x => `${x}:${global.$g.port}`);
module.exports = function(app) {
    app.engine('html', ejs.renderFile);
    app.set('view engine', 'html');
    // app.use(lactate.static(path.join(__dirname, '../')));
    console.log(path.join(__dirname, 'views/dist'));
    app.use('/static', lactate.static(path.join(__dirname, 'views/dist')));
    app.use(function() {
        var args = arguments;
        var isErr = args[0] instanceof Error;
        if (isErr) {
            args[2].status(500).send(args[0]);
        } else {
            args[2]();
        }
    });
    app.use(bodyParser.json({ limit: '50mb' }));
    //parse application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({
        limit: '50mb',
        extended: false
    }));
    //parse application/json
    app.use(bodyParser.json());
    app.use(forward({
        filterFunc(html) {
            // 移除统计脚本
            return html.replace(/<script[\S]+?uba-sdk[\S]+?<\/script>/, '');
        },
        filterCookie(cookie) {
            return cookie.replace(/DataPlatform.*?=.+?;/gi, '')
        },
        filterJs(js) {
            // 改变关于location的脚本
            return js && js.replace(/\.assign\(([^,]+?)\)/g, '.$assign($1)');
        },
        prefix: '/databp'
    }));
    routers.forEach(function(router) {
        app.use(router);
    });
    //return error
    app.use(function(err, req, res, next) {
        console.log(err);
        res.end(JSON.stringify(err));
    });
};
<commit_msg>fix test<commit_after>var ejs = require('ejs');
var path = require('path');
var bodyParser = require('body-parser');
var lactate = require('lactate');
var routers = require('./router/routersIndex');
var connect = require('connect');
var getIPlist = require('./lib').getIPlist;
var forward = require('../src');
let env = process.env.NODE_ENV || 'dev';
//bind to global var
global.$g = global.$g || {};
global.$g.port = require('./package.json').config.port;
global.$g.ips = getIPlist();
global.$g.hosts = global.$g.ips.map(x => `${x}:${global.$g.port}`);
module.exports = function(app) {
    app.engine('html', ejs.renderFile);
    app.set('view engine', 'html');
    // app.use(lactate.static(path.join(__dirname, '../')));
    console.log(path.join(__dirname, 'views/dist'));
    app.use('/static', lactate.static(path.join(__dirname, 'views/dist')));
    app.use(function() {
        var args = arguments;
        var isErr = args[0] instanceof Error;
        if (isErr) {
            args[2].status(500).send(args[0]);
        } else {
            args[2]();
        }
    });
    app.use(bodyParser.json({ limit: '50mb' }));
    //parse application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({
        limit: '50mb',
        extended: false
    }));
    //parse application/json
    app.use(bodyParser.json());
    forward({
        filterFunc(html) {
            // 移除统计脚本
            return html.replace(/<script[\S]+?uba-sdk[\S]+?<\/script>/, '');
        },
        filterCookie(cookie) {
            return cookie.replace(/DataPlatform.*?=.+?;/gi, '')
        },
        filterJs(js) {
            // 改变关于location的脚本
            return js && js.replace(/\.assign\(([^,]+?)\)/g, '.$assign($1)');
        },
        prefix: '/databp'
    })(app);
    routers.forEach(function(router) {
        app.use(router);
    });
    //return error
    app.use(function(err, req, res, next) {
        console.log(err);
        res.end(JSON.stringify(err));
    });
};
<|endoftext|>


<commit_before>const expect = require('expect.js');
const Money = require('../dist/money');

describe('Money', function() {

  describe('when constructing money', function() {
    it('returns correct integer value', function() {
      const num = 1200;
      const money = new Money(num);
      expect(money.cents).to.be(1200);
    });

    it('returns correct string value', function() {
      const string = '22';
      const money = new Money(string);
      expect(money.cents).to.be(2200);
    });

    it('returns correct money string value', function() {
      const moneyString = '$1.00';
      const money = new Money(moneyString);
      expect(money.cents).to.be(100);
    });

    it('returns correct money object value', function() {
      const num = {
        cents: 1000
      };
      const money = new Money(num);
      expect(money.cents).to.be(1000);
    });

    it('returns correct object value', function() {
      const object = {
        key: 1000
      };
      const money = new Money(object);
      expect(money.cents).to.be(0);
    });

    it('returns correct array value', function() {
      const array = [10];
      const money = new Money(array);
      expect(money.cents).to.be(0);
    });

    it('returns correct NaN value', function() {
      const aNaNValue = 10 / 'a';
      const money = new Money(aNaNValue);
      expect(money.cents).to.be(0);
    });

  });

  describe('when calcalating multiplications', function() {
    const operand = .015;
    it('rounds the positive amount conventionally', function() {
      const money = new Money(3900);
      expect(money.multiply(operand).cents).to.be(59);
    });

    it('rounds the negative amount symmetrically', function() {
      const money = new Money(-3900);
      expect(money.multiply(operand).cents).to.be(-59);
    });

  });
});
<commit_msg>increase coverage to 100%<commit_after>const expect = require('expect.js');
const Money = require('../dist/money');

describe('Money', function() {

  describe('when constructing money', function() {
    it('returns correct integer value', function() {
      const num = 1200;
      const money = new Money(num);
      expect(money.cents).to.be(1200);
    });

    it('returns correct string value', function() {
      const string = '22';
      const money = new Money(string);
      expect(money.cents).to.be(2200);
    });

    it('returns correct money string value', function() {
      const moneyString = '$1.00';
      const money = new Money(moneyString);
      expect(money.cents).to.be(100);
    });

    it('returns correct money from invalid string value', function() {
      const money = new Money("abc");
      expect(money.cents).to.be(0);
    });

    it('returns correct money object value', function() {
      const num = {
        cents: 1000
      };
      const money = new Money(num);
      expect(money.cents).to.be(1000);
    });

    it('returns correct object value', function() {
      const object = {
        key: 1000
      };
      const money = new Money(object);
      expect(money.cents).to.be(0);
    });

    it('returns correct array value', function() {
      const array = [10];
      const money = new Money(array);
      expect(money.cents).to.be(0);
    });

    it('returns correct NaN value', function() {
      const aNaNValue = 10 / 'a';
      const money = new Money(aNaNValue);
      expect(money.cents).to.be(0);
    });
  });

  describe('when calcalating multiplications', function() {
    const operand = .015;
    it('rounds the positive amount conventionally', function() {
      const money = new Money(3900);
      expect(money.multiply(operand).cents).to.be(59);
    });

    it('rounds the negative amount symmetrically', function() {
      const money = new Money(-3900);
      expect(money.multiply(operand).cents).to.be(-59);
    });
  });

  describe('comparison', function() {
    it('Should not equal an object with different cents', function() {
      const money = new Money(3000)
      expect(money.equals(new Money(20))).to.be(false);
    });

    it('Should equal an object with same cents value', function() {
      const money = new Money(3000)
      expect(money.equals(new Money(3000))).to.be(true);
    });
  });

  describe('add', function() {
    it('should add money values', function() {
      expect(new Money(3000).add(new Money(3000)).cents).to.be(6000);
    })
  });

  describe('subtract', function() {
    it('should subtract money values', function() {
      expect(new Money(3000).subtract(new Money(3000)).cents).to.be(0);
    })
  });

  describe('isNegative', function() {
    it('should detect negative values', function() {
      expect(new Money(3000).isNegative()).to.be(false);
      expect(new Money(0).isNegative()).to.be(false);
      expect(new Money(-3000).isNegative()).to.be(true);
    });
  });

  describe('isPositive', function() {
    it('should detect positive values', function() {
      expect(new Money(3000).isPositive()).to.be(true);
      expect(new Money(0).isPositive()).to.be(false);
      expect(new Money(-3000).isPositive()).to.be(false);
    });
  });

  describe('isZero', function() {
    it('should detect zero values', function() {
      expect(new Money(3000).isZero()).to.be(false);
      expect(new Money(0).isZero()).to.be(true);
      expect(new Money(-3000).isZero()).to.be(false);
    });
  });

  describe('formatting', function() {
    it('formats to html with positive', function() {
      const money = new Money(3000)
      expect(money.render()).to.be('$30.00');
    });

    it('formats to html with negative', function() {
      const money = new Money(-3000)
      expect(money.render()).to.be('-$30.00');
    });

    it('formats to html with zero value', function() {
      const money = new Money(0)
      expect(money.render()).to.be('$0.00');
    });

    it('converts to string', function() {
      const money = new Money(3000)
      expect(money.toString()).to.be('30.00');
    });
  })
});
<|endoftext|>


<commit_before>var spawn = require('child_process').spawn;
var path = require('path');
var series = require('run-series');

function test(filename) {
  return function(cb) {
    var proc = spawn(process.argv[0], [ filename ], { stdio: 'inherit' });
    proc.on('close', function (code) {
      cb(code !== 0 ? new Error('test ' + path.basename(filename) + ' failed') : null);
    });
  };
}

series([
  test(require.resolve('./debug')),
  test(require.resolve('./format')),
  test(require.resolve('./inspect')),
  test(require.resolve('./log')),
  test(require.resolve('./promisify')),
  test(require.resolve('./callbackify')),
  test(require.resolve('./types'))
]);
<commit_msg>Throw when a test fails<commit_after>var spawn = require('child_process').spawn;
var path = require('path');
var series = require('run-series');

function test(filename) {
  return function(cb) {
    var proc = spawn(process.argv[0], [ filename ], { stdio: 'inherit' });
    proc.on('close', function (code) {
      cb(code !== 0 ? new Error('test ' + path.basename(filename) + ' failed') : null);
    });
  };
}

series([
  test(require.resolve('./debug')),
  test(require.resolve('./format')),
  test(require.resolve('./inspect')),
  test(require.resolve('./log')),
  test(require.resolve('./promisify')),
  test(require.resolve('./callbackify')),
  test(require.resolve('./types'))
], function (err) {
  if (err) throw err
});
<|endoftext|>


<commit_before>// oauth-test.js
//
// Test the client registration API
//
// Copyright 2012, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var assert = require('assert'),
    vows = require('vows'),
    Step = require('step'),
    _ = require('underscore'),
    querystring = require('querystring'),
    OAuth = require('oauth').OAuth,
    httputil = require('./lib/http');

var suite = vows.describe('user API');

suite.addBatch({
    'When we set up the app': {
        topic: function() {
            var cb = this.callback,
                config = {port: 4815,
                          hostname: 'localhost',
                          driver: 'memory',
                          params: {},
                          nologger: true
                         },
                makeApp = require('../lib/app').makeApp;

            process.env.NODE_ENV = 'test';

            makeApp(config, function(err, app) {
                if (err) {
                    cb(err, null);
                } else {
                    app.run(function(err) {
                        if (err) {
                            cb(err, null);
                        } else {
                            cb(null, app);
                        }
                    });
                }
            });
        },
        teardown: function(app) {
            app.close();
        },
        'it works': function(err, app) {
            assert.ifError(err);
        },
        'and we create a client using the api': {
            topic: function() {
                var cb = this.callback;
                httputil.post('localhost', 4815, '/api/client/register', {type: 'client_associate'}, function(err, res, body) {
                    var cl;
                    if (err) {
                        cb(err, null);
                    } else {
                        try {
                            cl = JSON.parse(body);
                            cb(null, cl);
                        } catch (err) {
                            cb(err, null);
                        }
                    }
                });
            },
            'it works': function(err, cl) {
                assert.ifError(err);
                assert.isObject(cl);
                assert.isString(cl.client_id);
                assert.isString(cl.client_secret);
            },
            'and we request a request token': {
                topic: function(cl) {
                    var cb = this.callback,
                        oa = new OAuth('http://localhost:4815/oauth/request_token',
                                       'http://localhost:4815/oauth/access_token',
                                       cl.client_id,
                                       cl.client_secret,
                                       "1.0",
                                       "oob",
                                       "HMAC-SHA1",
                                       null, // nonce size; use default
                                       {"User-Agent": "activitypump-test/0.1.0"});

                    oa.getOAuthRequestToken(function(err, token, secret) {
                        if (err) {
                            cb(new Error(err.data), null);
                        } else {
                            cb({token: token, token_secret: secret});
                        }
                    });
                },
                'it works': function(err, cred) {
                    assert.ifError(err);
                    assert.isObject(cred);
                },
                'it has the right results': function(err, cred) {
                    assert.include(cred, 'token');
                    assert.isString(cred.token);
                    assert.include(cred, 'token_secret');
                    assert.isString(cred.token_secret);
                }
            }
        }
    }
});

suite['export'](module);<commit_msg>Forgot to pass null for the err<commit_after>// oauth-test.js
//
// Test the client registration API
//
// Copyright 2012, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var assert = require('assert'),
    vows = require('vows'),
    Step = require('step'),
    _ = require('underscore'),
    querystring = require('querystring'),
    OAuth = require('oauth').OAuth,
    httputil = require('./lib/http');

var suite = vows.describe('user API');

suite.addBatch({
    'When we set up the app': {
        topic: function() {
            var cb = this.callback,
                config = {port: 4815,
                          hostname: 'localhost',
                          driver: 'memory',
                          params: {},
                          nologger: true
                         },
                makeApp = require('../lib/app').makeApp;

            process.env.NODE_ENV = 'test';

            makeApp(config, function(err, app) {
                if (err) {
                    cb(err, null);
                } else {
                    app.run(function(err) {
                        if (err) {
                            cb(err, null);
                        } else {
                            cb(null, app);
                        }
                    });
                }
            });
        },
        teardown: function(app) {
            app.close();
        },
        'it works': function(err, app) {
            assert.ifError(err);
        },
        'and we create a client using the api': {
            topic: function() {
                var cb = this.callback;
                httputil.post('localhost', 4815, '/api/client/register', {type: 'client_associate'}, function(err, res, body) {
                    var cl;
                    if (err) {
                        cb(err, null);
                    } else {
                        try {
                            cl = JSON.parse(body);
                            cb(null, cl);
                        } catch (err) {
                            cb(err, null);
                        }
                    }
                });
            },
            'it works': function(err, cl) {
                assert.ifError(err);
                assert.isObject(cl);
                assert.isString(cl.client_id);
                assert.isString(cl.client_secret);
            },
            'and we request a request token': {
                topic: function(cl) {
                    var cb = this.callback,
                        oa = new OAuth('http://localhost:4815/oauth/request_token',
                                       'http://localhost:4815/oauth/access_token',
                                       cl.client_id,
                                       cl.client_secret,
                                       "1.0",
                                       "oob",
                                       "HMAC-SHA1",
                                       null, // nonce size; use default
                                       {"User-Agent": "activitypump-test/0.1.0"});

                    oa.getOAuthRequestToken(function(err, token, secret) {
                        if (err) {
                            cb(new Error(err.data), null);
                        } else {
                            cb(null, {token: token, token_secret: secret});
                        }
                    });
                },
                'it works': function(err, cred) {
                    assert.ifError(err);
                    assert.isObject(cred);
                },
                'it has the right results': function(err, cred) {
                    assert.include(cred, 'token');
                    assert.isString(cred.token);
                    assert.include(cred, 'token_secret');
                    assert.isString(cred.token_secret);
                }
            }
        }
    }
});

suite['export'](module);<|endoftext|>


<commit_before>
var pg = require('okdoki/lib/POSTGRESQL');
var assert = require('assert');

describe( '.on_error', function () {

  it( 'executes on error', function (done) {
    var db = new pg.query('SELECT * FROM "no-table";');
    db.on_error(function (err) {
      assert.equal(err.toString(), "error: relation \"no-table\" does not exist");
      done();
    });
    db.run();
  });

}); // === describe
<commit_msg>Added: .on_end test for POSTGRESQL abstraction layer.<commit_after>
var pg = require('okdoki/lib/POSTGRESQL');
var assert = require('assert');

describe( '.on_error', function () {

  it( 'executes on error', function (done) {
    var db = new pg.query();
    db.q('SELECT now() AS TIME');
    db.q('SELECT * FROM "no-table";');
    db.on_error(function (err) {
      assert.equal(err.toString(), "error: relation \"no-table\" does not exist");
      done();
    });
    db.run();
  });

}); // === describe

describe( '.on_end', function () {

  it( 'executes on end of all queries', function (done) {
    var db = new pg.query();
    db.q('SELECT now() AS TIME');
    db.q('SELECT current_database() AS NAME');
    db.on_end(function (meta) {
      assert.equal(meta.rows.length, 1);
      done();
    });
    db.run();

  });
}); // === describe
<|endoftext|>


<commit_before>import chai from 'chai'
import * as F from '../src/regex'
chai.expect()
const expect = chai.expect

describe('Regexp Functions', () => {
  it('testRegex', () => {
    expect(F.testRegex(/smart/i)('SmartProcure')).to.equal(true)
    expect(F.testRegex(/smart/)('SmartProcure')).to.equal(false)
  })

  it('makeRegExp', () => {
    const reText = 'Some text'
    const options = 'gi'

    expect(F.makeRegex(options)(reText)).to.deep.equal(RegExp(reText, options))
  })

  it('makeAndTest', () => {
    const reText = 'Some text'
    const options = 'gi'
    const text = 'Here is some text to test'
    const regex = RegExp(reText, options)

    expect(F.makeAndTest(options)(reText)(text)).to.deep.equal(regex.test(text))
  })

  it('matchAnyWord', () => {
    const reText = 'Some text'
    const text = 'Here is some text to test'
    const match = F.matchAnyWord(reText)

    expect(match(text)).to.equal(true)
  })

  it('matchAllWords', () => {
    const reText = 'Some text'
    const text = 'Here is some to test'
    const match = F.matchAllWords(reText)

    expect(match(text)).to.equal(false)
  })

  it('should return all matched results', () => {
    const re = '(\\d+)'
    const text = `1 22 333 a bb ccc 4444`
    const matches = F.allMatches(re, text)
    expect(matches).to.deep.equal([
      { text: '1', start: 0, end: 1 },
      { text: '22', start: 2, end: 4 },
      { text: '333', start: 5, end: 8 },
      { text: '4444', start: 18, end: 22 },
    ])
  })
})

describe('Posting Highlight Functions', () => {
  it('should get postings', () => {
    var result = F.postings(RegExp('p', 'gi'), 'pretty please')
    expect(result).to.deep.equal([
      [0, 1],
      [7, 8],
    ])
  })
  it('should get postings by word', () => {
    var result = F.postingsForWords('pret pr t ', 'pretty prease')
    expect(result).to.deep.equal([
      [[0, 4]],
      [
        [0, 2],
        [7, 9],
      ],
      [
        [3, 4],
        [4, 5],
      ],
    ])
  })
  var start = ''
  var end = ''

  it('should highlight', () => {
    let input = 'pretty please'
    let postings = F.postings(RegExp('p', 'gi'), input)
    let expected =
      'pretty please'
    expect(F.highlightFromPostings(start, end, postings, input)).to.equal(
      expected
    )
  })
  it('should highlight backwards postings', () => {
    let input = 'pretty please'
    let expected =
      'pretty please'
    expect(
      F.highlightFromPostings(
        start,
        end,
        [
          [7, 8],
          [0, 1],
        ],
        input
      )
    ).to.equal(expected)
  })
  it('should high level highlight', () => {
    let input = 'pretty please'
    let pattern = 'pr pl'
    let expected =
      'pretty please'
    expect(F.highlight(start, end, pattern, input)).to.deep.equal(expected)
  })
  it('should highlight from regexp', () => {
    let input = 'pretty please nope'
    let pattern = /\bp\w/g
    let expected =
      'pretty please nope'
    expect(F.highlight(start, end, pattern, input)).to.deep.equal(expected)
  })
})
<commit_msg>work in progress<commit_after>import chai from 'chai'
import * as F from '../src/regex'
chai.expect()
const expect = chai.expect

describe('Regexp Functions', () => {
  it('testRegex', () => {
    expect(F.testRegex(/smart/i)('SmartProcure')).to.equal(true)
    expect(F.testRegex(/smart/)('SmartProcure')).to.equal(false)
  })

  it('makeRegExp', () => {
    const reText = 'Some text'
    const options = 'gi'

    expect(F.makeRegex(options)(reText)).to.deep.equal(RegExp(reText, options))
  })

  it('makeAndTest', () => {
    const reText = 'Some text'
    const options = 'gi'
    const text = 'Here is some text to test'
    const regex = RegExp(reText, options)

    expect(F.makeAndTest(options)(reText)(text)).to.deep.equal(regex.test(text))
  })
  it('anyWordToRegexp -pending', () => {})

  it('wordsToRegexp -pending', () => {})

  it('matchWords -pending', () => {})

  it('matchAllWords', () => {
    const reText = 'Some text'
    const text = 'Here is some to test'
    const match = F.matchAllWords(reText)

    expect(match(text)).to.equal(false)
  })

  it('matchAnyWord', () => {
    const reText = 'Some text'
    const text = 'Here is some text to test'
    const match = F.matchAnyWord(reText)

    expect(match(text)).to.equal(true)
  })

  it('allMatches', () => {
    const re = '(\\d+)'
    const text = `1 22 333 a bb ccc 4444`
    const matches = F.allMatches(re, text)
    expect(matches).to.deep.equal([
      { text: '1', start: 0, end: 1 },
      { text: '22', start: 2, end: 4 },
      { text: '333', start: 5, end: 8 },
      { text: '4444', start: 18, end: 22 },
    ])
  })
})

describe('Posting Highlight Functions', () => {
  it('postings', () => {
    var result = F.postings(RegExp('p', 'gi'), 'pretty please')
    expect(result).to.deep.equal([
      [0, 1],
      [7, 8],
    ])
  })
  it('postingsForWords', () => {
    var result = F.postingsForWords('pret pr t ', 'pretty prease')
    expect(result).to.deep.equal([
      [[0, 4]],
      [
        [0, 2],
        [7, 9],
      ],
      [
        [3, 4],
        [4, 5],
      ],
    ])
  })

  describe('highlightFromPostings', () => {
    let start = ''
    let end = ''

    it('highlightFromPostings', () => {
      let input = 'pretty please'
      let postings = F.postings(RegExp('p', 'gi'), input)
      let expected =
        'pretty please'
      expect(F.highlightFromPostings(start, end, postings, input)).to.equal(
        expected
      )
    })
    it('should highlight backwards postings', () => {
      let input = 'pretty please'
      let expected =
        'pretty please'
      expect(
        F.highlightFromPostings(
          start,
          end,
          [
            [7, 8],
            [0, 1],
          ],
          input
        )
      ).to.equal(expected)
      })
  })
  describe('highlight', () => {
    it('highlight', () => {
      let start = ''
      let end = ''
      let input = 'pretty please'
      let pattern = 'pr pl'
      let expected =
        'pretty please'
      expect(F.highlight(start, end, pattern, input)).to.deep.equal(expected)
    })
    it('should highlight from regexp', () => {
      let start = ''
      let end = ''
      let input = 'pretty please nope'
      let pattern = /\bp\w/g
      let expected =
        'pretty please nope'
      expect(F.highlight(start, end, pattern, input)).to.deep.equal(expected)
    })
  })
})
<|endoftext|>


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

'use strict';

var allocCluster = require('./lib/alloc-cluster');
var TChannel = require('../channel');
var RelayHandler = require('../relay_handler');

allocCluster.test('send lazy relay requests', {
    numPeers: 2
}, function t(cluster, assert) {
    var one = cluster.channels[0];
    var two = cluster.channels[1];

    one.setLazyHandling(true);
    var oneToTwo = one.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort]
    });
    oneToTwo.handler = new RelayHandler(oneToTwo);
    oneToTwo.handler.handleRequest = failWrap(
         oneToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    var twoSvc = two.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc.register('echo', echo);

    var client = TChannel({
        logger: one.logger,
        timeoutFuzz: 0
    });
    var twoClient = client.makeSubChannel({
        serviceName: 'two',
        peers: [one.hostPort],
        requestDefaults: {
            serviceName: 'two',
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    twoClient.request({
        hasNoParent: true
    }).send('echo', 'foo', 'bar', function done(err, res, arg2, arg3) {
        assert.ifError(err, 'no unexpected error');
        assert.equal(String(arg2), 'foo', 'expected arg2');
        assert.equal(String(arg3), 'bar', 'expected arg3');

        client.close();
        assert.end();
    });
});

allocCluster.test('send relay with tiny timeout', {
    numPeers: 2
}, function t(cluster, assert) {
    var one = cluster.channels[0];
    var two = cluster.channels[1];

    one.setLazyHandling(true);
    var oneToTwo = one.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort]
    });
    oneToTwo.handler = new RelayHandler(oneToTwo);
    oneToTwo.handler.handleRequest = failWrap(
         oneToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    var twoSvc = two.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc.register('echo', echo);

    var client = TChannel({
        logger: one.logger,
        timeoutFuzz: 0
    });
    var twoClient = client.makeSubChannel({
        serviceName: 'two',
        peers: [one.hostPort],
        requestDefaults: {
            serviceName: 'two',
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    twoClient.waitForIdentified({
        host: one.hostPort
    }, onIdentified);

    function onIdentified(err1) {
        assert.ifError(err1);

        twoClient.request({
            hasNoParent: true,
            host: one.hostPort,
            timeout: 15
        }).send('echo', 'foo', 'bar', function done(err2, res, arg2, arg3) {
            assert.ifError(err2, 'no unexpected error');
            assert.equal(String(arg2), 'foo', 'expected arg2');
            assert.equal(String(arg3), 'bar', 'expected arg3');

            client.close();
            assert.end();
        });
    }
});

allocCluster.test('relay respects ttl', {
    numPeers: 3
}, function t(cluster, assert) {
    var relay = cluster.channels[0];
    var source = cluster.channels[1];
    var dest = cluster.channels[2];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: [dest.hostPort]
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var destChan = dest.makeSubChannel({
        serviceName: 'dest'
    });
    destChan.register('echoTTL', echoTTL);

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 250
    }).send('echoTTL', null, null, onResponse);

    function onResponse(err, res, arg2, arg3) {
        assert.ifError(err);
        assert.ok(res.ok);

        var ttl = Number(String(arg3));
        assert.ok(ttl >= 200 && ttl <= 250);

        assert.end();
    }
});

allocCluster.test('relay an error frame', {
    numPeers: 4
}, function t(cluster, assert) {
    cluster.logger.whitelist('warn', 'forwarding error frame');

    var one = cluster.channels[0];
    var two = cluster.channels[1];
    var three = cluster.channels[2];
    var four = cluster.channels[3];

    one.setLazyHandling(true);
    var oneToTwo = one.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort, three.hostPort]
    });
    oneToTwo.handler = new RelayHandler(oneToTwo);
    oneToTwo.handler.handleRequest = failWrap(
         oneToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    four.setLazyHandling(true);
    var fourToTwo = four.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort, three.hostPort]
    });
    fourToTwo.handler = new RelayHandler(fourToTwo);
    fourToTwo.handler.handleRequest = failWrap(
         fourToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    var twoSvc2 = three.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc2.register('decline', declineError);

    var twoSvc = two.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc.register('decline', declineError);

    var client = TChannel({
        logger: one.logger,
        timeoutFuzz: 0
    });
    var twoClient = client.makeSubChannel({
        serviceName: 'two',
        peers: [one.hostPort, four.hostPort],
        requestDefaults: {
            serviceName: 'two',
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    twoClient.request({
        hasNoParent: true,
        headers: {
            as: 'raw',
            cn: 'wat'
        }
    }).send('decline', 'foo', 'bar', function done(err, res, arg2, arg3) {
        assert.equal(err.type, 'tchannel.declined', 'expected declined error');

        assert.ok(cluster.logger.items().length >= 1, 'expected some logs');
        client.close();
        assert.end();
    });
});

allocCluster.test('relay request times out', {
    numPeers: 3
}, function t(cluster, assert) {
    var relay = cluster.channels[0];
    var source = cluster.channels[1];
    var dest = cluster.channels[2];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: [dest.hostPort]
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var destChan = dest.makeSubChannel({
        serviceName: 'dest'
    });
    destChan.register('limbo', limbo);

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    // Try to ensure a timeout in the relay by injecting delay into peer
    // identification... still not 100% deterministic, but the test does pass
    // always... even if it doesn't always hit the timeout path
    var relayOutPeer = relayChan.peers.get(dest.hostPort);
    var waitForIdentified = relayOutPeer.waitForIdentified;
    relayOutPeer.waitForIdentified = function punchWaitForIdentified(callback) {
        var self = this;

        relay.timers.setTimeout(function delayIt() {
            waitForIdentified.call(self, callback);
        }, 5);
    };

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 100
    }).send('limbo', null, null, onResponse);

    function onResponse(err, res, arg2, arg3) {
        assert.equal(err && err.type,
                     'tchannel.request.timeout',
                     'expected timeout error');
        assert.notOk(res, 'expected no response');
        assert.end();
    }
});

allocCluster.test('relay request declines on no peer', {
    numPeers: 2
}, function t(cluster, assert) {
    // TODO: address the warn logs
    var relay = cluster.channels[0];
    var source = cluster.channels[1];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: []
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 100
    }).send('echo', null, null, onResponse);

    function onResponse(err, res, arg2, arg3) {
        assert.equal(err && err.type,
                     'tchannel.declined',
                     'expected declined error');
        assert.notOk(res, 'expected no response');
        assert.end();
    }
});

allocCluster.test('relay request handles channel close correctly', {
    numPeers: 3
}, function t(cluster, assert) {
    // TODO: address the warn logs

    var relay = cluster.channels[0];
    var source = cluster.channels[1];
    var dest = cluster.channels[2];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: [dest.hostPort]
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var destChan = dest.makeSubChannel({
        serviceName: 'dest'
    });
    destChan.register('killRelay', killRelay);

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 100
    }).send('killRelay', null, null, onResponse);

    function killRelay() {
        relay.close();
    }

    function onResponse(err, res, arg2, arg3) {
        assert.equal(err && err.type,
                     'tchannel.connection.reset',
                     'expected timeout error');
        assert.notOk(res, 'expected no response');
        assert.end();
    }
});

function declineError(req, res, arg2, arg3) {
    res.sendError('Declined', 'lul');
}

function echo(req, res, arg2, arg3) {
    res.headers.as = 'raw';
    res.sendOk(arg2, arg3);
}

function echoTTL(req, res) {
    res.headers.as = 'raw';
    res.sendOk(null, String(req.timeout));
}

function limbo() {
}

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

'use strict';

var allocCluster = require('./lib/alloc-cluster');
var TChannel = require('../channel');
var RelayHandler = require('../relay_handler');

allocCluster.test('send lazy relay requests', {
    numPeers: 2
}, function t(cluster, assert) {
    var one = cluster.channels[0];
    var two = cluster.channels[1];

    one.setLazyHandling(true);
    var oneToTwo = one.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort]
    });
    oneToTwo.handler = new RelayHandler(oneToTwo);
    oneToTwo.handler.handleRequest = failWrap(
         oneToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    var twoSvc = two.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc.register('echo', echo);

    var client = TChannel({
        logger: one.logger,
        timeoutFuzz: 0
    });
    var twoClient = client.makeSubChannel({
        serviceName: 'two',
        peers: [one.hostPort],
        requestDefaults: {
            serviceName: 'two',
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    twoClient.request({
        hasNoParent: true
    }).send('echo', 'foo', 'bar', function done(err, res, arg2, arg3) {
        assert.ifError(err, 'no unexpected error');
        assert.equal(String(arg2), 'foo', 'expected arg2');
        assert.equal(String(arg3), 'bar', 'expected arg3');

        client.close();
        assert.end();
    });
});

allocCluster.test('send relay with tiny timeout', {
    numPeers: 2
}, function t(cluster, assert) {
    var one = cluster.channels[0];
    var two = cluster.channels[1];

    one.setLazyHandling(true);
    var oneToTwo = one.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort]
    });
    oneToTwo.handler = new RelayHandler(oneToTwo);
    oneToTwo.handler.handleRequest = failWrap(
         oneToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    var twoSvc = two.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc.register('echo', echo);

    var client = TChannel({
        logger: one.logger,
        timeoutFuzz: 0
    });
    var twoClient = client.makeSubChannel({
        serviceName: 'two',
        peers: [one.hostPort],
        requestDefaults: {
            serviceName: 'two',
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    twoClient.waitForIdentified({
        host: one.hostPort
    }, onIdentified);

    function onIdentified(err1) {
        assert.ifError(err1);

        twoClient.request({
            hasNoParent: true,
            host: one.hostPort,
            timeout: 15
        }).send('echo', 'foo', 'bar', function done(err2, res, arg2, arg3) {
            assert.ifError(err2, 'no unexpected error');
            assert.equal(String(arg2), 'foo', 'expected arg2');
            assert.equal(String(arg3), 'bar', 'expected arg3');

            client.close();
            assert.end();
        });
    }
});

allocCluster.test('relay respects ttl', {
    numPeers: 3
}, function t(cluster, assert) {
    var relay = cluster.channels[0];
    var source = cluster.channels[1];
    var dest = cluster.channels[2];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: [dest.hostPort]
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var destChan = dest.makeSubChannel({
        serviceName: 'dest'
    });
    destChan.register('echoTTL', echoTTL);

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 250
    }).send('echoTTL', null, null, onResponse);

    function onResponse(err, res, arg2, arg3) {
        assert.ifError(err);
        assert.ok(res.ok);

        var ttl = Number(String(arg3));
        assert.ok(ttl >= 200 && ttl <= 250);

        assert.end();
    }
});

allocCluster.test('relay an error frame', {
    numPeers: 4
}, function t(cluster, assert) {
    cluster.logger.whitelist('warn', 'forwarding error frame');

    var one = cluster.channels[0];
    var two = cluster.channels[1];
    var three = cluster.channels[2];
    var four = cluster.channels[3];

    one.setLazyHandling(true);
    var oneToTwo = one.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort, three.hostPort]
    });
    oneToTwo.handler = new RelayHandler(oneToTwo);
    oneToTwo.handler.handleRequest = failWrap(
         oneToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    four.setLazyHandling(true);
    var fourToTwo = four.makeSubChannel({
        serviceName: 'two',
        peers: [two.hostPort, three.hostPort]
    });
    fourToTwo.handler = new RelayHandler(fourToTwo);
    fourToTwo.handler.handleRequest = failWrap(
         fourToTwo.handler.handleRequest,
         assert, 'handle requests eagerly');

    var twoSvc2 = three.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc2.register('decline', declineError);

    var twoSvc = two.makeSubChannel({
        serviceName: 'two'
    });
    twoSvc.register('decline', declineError);

    var client = TChannel({
        logger: one.logger,
        timeoutFuzz: 0
    });
    var twoClient = client.makeSubChannel({
        serviceName: 'two',
        peers: [one.hostPort, four.hostPort],
        requestDefaults: {
            serviceName: 'two',
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    twoClient.request({
        hasNoParent: true,
        headers: {
            as: 'raw',
            cn: 'wat'
        }
    }).send('decline', 'foo', 'bar', function done(err, res, arg2, arg3) {
        assert.equal(err.type, 'tchannel.declined', 'expected declined error');

        assert.ok(cluster.logger.items().length >= 1, 'expected some logs');
        client.close();
        assert.end();
    });
});

allocCluster.test('relay request times out', {
    numPeers: 3
}, function t(cluster, assert) {
    // TODO: address the warn logs
    var relay = cluster.channels[0];
    var source = cluster.channels[1];
    var dest = cluster.channels[2];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: [dest.hostPort]
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var destChan = dest.makeSubChannel({
        serviceName: 'dest'
    });
    destChan.register('limbo', limbo);

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    // Try to ensure a timeout in the relay by injecting delay into peer
    // identification... still not 100% deterministic, but the test does pass
    // always... even if it doesn't always hit the timeout path
    var relayOutPeer = relayChan.peers.get(dest.hostPort);
    var waitForIdentified = relayOutPeer.waitForIdentified;
    relayOutPeer.waitForIdentified = function punchWaitForIdentified(callback) {
        var self = this;

        relay.timers.setTimeout(function delayIt() {
            waitForIdentified.call(self, callback);
        }, 5);
    };

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 100
    }).send('limbo', null, null, onResponse);

    function onResponse(err, res, arg2, arg3) {
        assert.equal(err && err.type,
                     'tchannel.request.timeout',
                     'expected timeout error');
        assert.notOk(res, 'expected no response');
        assert.end();
    }
});

allocCluster.test('relay request declines on no peer', {
    numPeers: 2
}, function t(cluster, assert) {
    // TODO: address the warn logs
    var relay = cluster.channels[0];
    var source = cluster.channels[1];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: []
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 100
    }).send('echo', null, null, onResponse);

    function onResponse(err, res, arg2, arg3) {
        assert.equal(err && err.type,
                     'tchannel.declined',
                     'expected declined error');
        assert.notOk(res, 'expected no response');
        assert.end();
    }
});

allocCluster.test('relay request handles channel close correctly', {
    numPeers: 3
}, function t(cluster, assert) {
    // TODO: address the warn logs

    var relay = cluster.channels[0];
    var source = cluster.channels[1];
    var dest = cluster.channels[2];

    relay.setLazyHandling(true);
    var relayChan = relay.makeSubChannel({
        serviceName: 'dest',
        peers: [dest.hostPort]
    });
    relayChan.handler = new RelayHandler(relayChan);
    relayChan.handler.handleRequest = failWrap(
         relayChan.handler.handleRequest,
         assert, 'handle requests eagerly');

    var destChan = dest.makeSubChannel({
        serviceName: 'dest'
    });
    destChan.register('killRelay', killRelay);

    var sourceChan = source.makeSubChannel({
        serviceName: 'dest',
        peers: [relay.hostPort],
        requestDefaults: {
            headers: {
                as: 'raw',
                cn: 'wat'
            }
        }
    });

    sourceChan.request({
        serviceName: 'dest',
        hasNoParent: true,
        timeout: 100
    }).send('killRelay', null, null, onResponse);

    function killRelay() {
        relay.close();
    }

    function onResponse(err, res, arg2, arg3) {
        assert.equal(err && err.type,
                     'tchannel.connection.reset',
                     'expected timeout error');
        assert.notOk(res, 'expected no response');
        assert.end();
    }
});

function declineError(req, res, arg2, arg3) {
    res.sendError('Declined', 'lul');
}

function echo(req, res, arg2, arg3) {
    res.headers.as = 'raw';
    res.sendOk(arg2, arg3);
}

function echoTTL(req, res) {
    res.headers.as = 'raw';
    res.sendOk(null, String(req.timeout));
}

function limbo() {
}

function failWrap(method, assert, desc) {
    return function failWrapper() {
        assert.fail('should not ' + desc);
        method.apply(this, arguments);
    };
}
<|endoftext|>


<commit_before>
var test = require('tape');
var path = require('path');
var fork = require('../fork');
var child = path.join(__dirname, 'fixtures', 'retry.js');

test('test request response when using retry functionality and failing child process', function (t) {
  t.plan(3);

  var message = { action: 'woooo', doc: 'document' };
  fork({
    path: child,
    retries: 2
  })
  .fork(message)
  .on('error', function (err) {
    t.ok(err, 'Failed after attempting retry with ' + err.message);
    t.end();
  })
  .on('retry', function (yo) { t.ok(yo, 'retry attempt') })
  .on('response', function (msg) {
    t.fail(msg, 'We should not receive a message with a determinstically failing child process');
    t.end();
  })
})
<commit_msg>[test minor] test title edit<commit_after>
var test = require('tape');
var path = require('path');
var fork = require('../fork');
var child = path.join(__dirname, 'fixtures', 'retry.js');

test('test request response when using 2 retries functionality and failing child process', function (t) {
  t.plan(3);

  var message = { action: 'woooo', doc: 'document' };
  fork({
    path: child,
    retries: 2
  })
  .fork(message)
  .on('error', function (err) {
    t.ok(err, 'Failed after attempting retry with ' + err.message);
    t.end();
  })
  .on('retry', function (yo) { t.ok(yo, 'retry attempt') })
  .on('response', function (msg) {
    t.fail(msg, 'We should not receive a message with a determinstically failing child process');
    t.end();
  })
})
<|endoftext|>


<commit_before>`use strict`

process.env.NODE_ENV = 'test'

const chai = require('chai')
const should = chai.should()
const chaiHttp = require('chai-http')
const server = require('../app')
const { knex } = require('../db/database')
chai.use(chaiHttp)

describe('abc routes', ()=>{
  // does a rollback on test db and then migration and seed before each test run so we know what is in db
  beforeEach(() =>{
    return knex.migrate.rollback()
      .then (()=>{
        return knex.migrate.latest()
      })
      .then (()=>{
        return knex.seed.run()
      })
  });

  // test for getting the api root
  describe('get root route', ()=>{
    it('should have all routes',() =>{
      return chai.request(server)
        .get('/api/v1/')
        .then((res) => {
          res.should.have.status(200)
          res.should.be.json
          res.should.be.a.object
          res.body.should.have.key(['games','userAndTheirGames'])
        })
    })
  });

  // tests getting all games
  describe(`GET /api/v1/games`, function() {
    it(`should return all games`, function() {
      return chai.request(server)
        .get(`/api/v1/games`).then(res => {
          res.should.have.status(200)
          res.should.be.json
          res.body.should.be.a.object
          res.body.should.have.key('games')
          res.body.games.should.be.a.array
          res.body.games[0].number_correct.should.equal('4')
        })
    })
  })

  // tests getting all games for logged in user
  describe(`GET /api/v1/games`, function() {
    it(`should return all games`, function() {
      return chai.request(server)
        .get(`/api/v1/users/games?userID=1`).then(res => {
          res.should.have.status(200)
          // res.should.be.json
          // res.body.should.be.a.object
          // res.body.should.have.key('games')
          // res.body.games.should.be.a.array
          // res.body.games[0].number_correct.should.equal('4')
        })
    })
  })
})
<commit_msg>adjusted test<commit_after>`use strict`

process.env.NODE_ENV = 'test'

const chai = require('chai')
const should = chai.should()
const chaiHttp = require('chai-http')
const server = require('../app')
const { knex } = require('../db/database')
chai.use(chaiHttp)

describe('abc routes', ()=>{
  // does a rollback on test db and then migration and seed before each test run so we know what is in db
  beforeEach(() =>{
    return knex.migrate.rollback()
      .then (()=>{
        return knex.migrate.latest()
      })
      .then (()=>{
        return knex.seed.run()
      })
  });

  // test for getting the api root
  describe('get root route', ()=>{
    it('should have all routes',() =>{
      return chai.request(server)
        .get('/api/v1/')
        .then((res) => {
          res.should.have.status(200)
          res.should.be.json
          res.should.be.a.object
          res.body.should.have.key(['games','userAndTheirGames'])
        })
    })
  });

  // tests getting all games
  describe(`GET /api/v1/games`, function() {
    it(`should return all games`, function() {
      return chai.request(server)
        .get(`/api/v1/games`).then(res => {
          res.should.have.status(200)
          res.should.be.json
          res.body.should.be.a.object
          res.body.should.have.key('games')
          res.body.games.should.be.a.array
          res.body.games[0].number_correct.should.equal('4')
        })
    })
  })

  // tests getting all games for logged in user
  describe(`GET /api/v1/games`, function() {
    it(`should return all games for user 1`, function() {
      return chai.request(server)
        .get(`/api/v1/users/games?userId=1`).then(res => {
          res.should.have.status(200)
          res.should.be.json
          res.body.should.be.a.object
          res.body.should.have.key(["admin", "created_at", "games", "id", "password", "username"])
          res.body.games.should.be.a.array
          res.body.games[0].number_correct.should.equal('4')
        })
    })
  })
})
<|endoftext|>


<commit_before>var webdriver = require('selenium-webdriver');
var test = require('selenium-webdriver/testing');
var server = require('node-http-server');
var path = require('path');
var chai = require('chai');
var chaiDriver = require('chai-webdriver');

var expect = chai.expect;
var it = test.it;
var describe = test.describe;
var by = webdriver.By;

var driver = new webdriver.Builder().
    withCapabilities(webdriver.Capabilities.chrome()).
    build();

chai.use(chaiDriver(driver));

server.deploy(
    {
        port: 8000,
        root: path.resolve('./')
    }
);

describe('test suite for helloWorld jQuery plugin', function() {
    it('should go to index.html and set the window size', function() {
        driver.get('http://localhost:8000');
        driver.manage().window().setSize(480, 800);
    });

    //@TODO: Dammit Ty, stop being lazy and write some damn tests.
    //@RESPONSE: i don't want to u can't control me
    //@RESPONSE: it works i swear

    it('should close the browser', function() {
         driver.quit();
    });
});<commit_msg>who needs tests<commit_after>var webdriver = require('selenium-webdriver');
var test = require('selenium-webdriver/testing');
var server = require('node-http-server');
var path = require('path');
var chai = require('chai');
var chaiDriver = require('chai-webdriver');

var expect = chai.expect;
var it = test.it;
var describe = test.describe;
var by = webdriver.By;

var driver = new webdriver.Builder().
    withCapabilities(webdriver.Capabilities.chrome()).
    build();

chai.use(chaiDriver(driver));

server.deploy(
    {
        port: 8000,
        root: path.resolve('./')
    }
);

describe('test suite for Kanye Ipsum jQuery plugin', function() {
    it('should go to index.html and set the window size', function() {
        driver.get('http://localhost:8000');
        driver.manage().window().setSize(480, 800);
    });

    //@TODO: Dammit Ty, stop being lazy and write some damn tests.
    //@RESPONSE: i don't want to u can't control me
    //@RESPONSE: it works i swear

    it('should close the browser', function() {
         driver.quit();
    });
});<|endoftext|>