// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

var test = require('prova');
var vanadium = require('../../');
var serve = require('./serve');
var leafDispatcher = require('../../src/rpc/leaf-dispatcher');
var Deferred = require('../../src/lib/deferred');

var builtins = require('../../src/vdl/builtins');
var stringify = require('../../src/vdl/stringify');
var TypeUtil = require('../../src/vdl/type-util');
var typeServiceVdl =
  require('../vdl-out/javascript-test/services/type-service');
var typedStreamingServiceVdl =
  require('../vdl-out/javascript-test/services/typed-streaming-service');

var vdl = vanadium.vdl;

// TODO(bprosnitz) Combine CacheService and CacheServicePromises so there
// isn't as much duplicated code.

var CacheService = {
  cacheMap: {},
  set: function(context, serverCall, key, value, cb) {
    this.cacheMap[key] = value;

    process.nextTick(function() {
      cb(null, undefined);
    });
  },
  get: function(context, serverCall, key, cb) {
    var val = this.cacheMap[key];
    if (val === undefined) {
      var message = 'unknown key ' + JSON.stringify(key);
      var err = new Error(message);

      process.nextTick(function() {
        cb(err);
      });
    } else {
      process.nextTick(function() {
        cb(undefined, val);
      });
    }
  } ,
  // TODO(bprosnitz) Also test streaming with no return arg.
  multiGet: function(context, serverCall, $stream, cb) {
    var numReceived = 0;
    $stream.on('end', function close() {
      cb(null, numReceived);
    });
    $stream.on('error', function error(e) {
      cb(e);
    });
    var self = this;
    $stream.on('data', function(key) {
      numReceived++;
      if (key !== null) {
        var val = self.cacheMap[key];
        if (val === undefined) {
          cb(new Error('unknown key'));
        }
        $stream.write(val);
      }
    });
    $stream.read();
  },
  doNothingStream: function(ctx, serverCall, $stream, cb) {
    cb(null, undefined);
  },
  nonAsyncFunction: function(ctx, serverCall, cb) {
    cb(null, 'RESULT');
  }
};

var CacheServicePromises = {
  cacheMap: {},
  set: function(context, serverCall, key, value) {
    this.cacheMap[key] = value;
  },
  get: function(context, serverCall, key) {
    var def = new Deferred();
    var val = this.cacheMap[key];
    process.nextTick(function() {
      if (val === undefined) {
        // Since we're rejecting the promise before we've returned it
        // we'll register a catch handler now to avoid an unhandled rejection
        // warning.
        def.promise.catch(function() {});
        def.reject('unknown key');
      } else {
        def.resolve(val);
      }
    });
    return def.promise;
  } ,
  multiGet: function(context, serverCall, $stream) {
    var numReceived = 0;
    var def = new Deferred();
    $stream.on('end', function() {
      def.resolve(numReceived);
    });

    $stream.on('error', function(e) {
      def.reject(e);
    });
    var self = this;
    $stream.on('data', function(key) {
      numReceived++;
      if (key !== null) {
        var val = self.cacheMap[key];
        if (val === undefined) {
          def.reject('unknown key');
        }
        $stream.write(val);
      }
    });
    $stream.read();
    return def.promise;
  },
  doNothingStream: function(ctx, serverCall, $stream) {
  },
  nonAsyncFunction: function(ctx, serverCall) {
    return 'RESULT';
  }
};

runCache({
  testName: 'without VDL (JSValue) using callbacks',
  definition: CacheService,
  name: 'foo.Cache'
});

runCache({
  testName: 'without VDL (JSValue) using promises',
  definition: CacheServicePromises,
  name: 'foo.Cache'
});

// options: testName, definition, name
function runCache(options) {
  var namePrefix = 'Test JS client/server rpc ' + options.testName + ' - ';

  test(namePrefix + 'cache.set(key, string) -> cache.get(key)',
            function(t) {
    setup(options, function(err, ctx, cache, end) {
      t.error(err, 'should not error on setup');

      cache.set(ctx, 'foo', 'bar', function(err, res) {
        t.error(err, 'should not error on set(...)');
        t.notOk(res, 'should be null');

        cache.get(ctx, 'foo', function(err, res) {
          t.error(err, 'should not error on get(...)');
          t.equal(res, 'bar');
          end(t);
        });
      });
    });
  });

  test(namePrefix + 'cache.set(key, object, callback)', function(t) {
    setup(options, function(err, ctx, cache, end) {
      t.error(err, 'should not error on setup');

      // Expect a map as the JSValue.
      var expected = new Map([['a', 'foo'], ['b', 2]]);

      cache.set(ctx, 'myObject', expected, function(err, res) {
        t.error(err, 'should not error on set(...)');
        t.equal(res, null, 'should be null');

        cache.get(ctx, 'myObject', function(err, res) {
          t.error(err, 'should not error on get(...)');
          t.deepEqual(res, expected, 'should match object');
          end(t);
        });
      });
    });
  });

  test(namePrefix + 'cache.get("bad-key", callback) - failure',
            function(t) {
    setup(options, function(err, ctx, cache, end) {
      t.error(err, 'should not error on setup');

      cache.get(ctx, 'bad-key', function(err, res) {
        t.ok(err, 'should err on get(...)');
        // TODO(bjornick): Use the constant generated by the vdl generator.
        t.equal(err.id, 'v.io/v23/verror.Unknown');
        end(t);
      });
    });
  });

  test(namePrefix + 'cache.badMethod() - failure', function(t) {
    setup(options, function(err, ctx, cache, end) {
      t.error(err, 'should not error on setup');

      t.throws(function() {
        cache.badMethod();
      });

      end(t);
    });
  });

  test(namePrefix + 'cache.multiGet()', function(t) {
    // `cache.multiGet()` returns an object that has a "stream" attribute.
    // The way the streaming interface is implmented for cache.multiGet()
    // is that you use stream.write(key) to get the value of a key. The value
    // is emitted on the stream's data event. In this test there are a few
    //  steps to set this up:
    //
    // 1. Prime the cache by setting a bunch of key/values
    // 2. Add a listener or create a stream reader to receive the values
    // 3. Assert the values are correct
    // 4. End the stream.
    setup(options, function(err, ctx, cache, end){
      // 1. Prime the cache by setting a bunch of key/values

      // Build a map of items
      var items = {};
      var numItems = 3;

      for (var i = 0; i < numItems; ++i) {
        items[i] = {
          key: i,
          value: 'value: ' + i
        };
      }

      // Add them to the cache
      var jobs = Object.keys(items).map(function(key) {
        return cache.set(ctx, key, JSON.stringify(items[key]));
      });

      Promise
      .all(jobs)
      .then(function() {
        // 2. Add a listener or create a stream reader to receive the values
        var promise = cache.multiGet(ctx);
        var stream = promise.stream;
        var writes = 0;
        var reads = 0;

        // Error handling boilerplate
        promise.then(function(numReceived) {
          t.equal(numReceived, numItems, 'received correct number of items');
          t.equal(reads, numItems, 'had correct number of reads');
          t.equal(writes, numItems, 'has correct number of writes');
          end(t);
        }).catch(error);

        stream.on('error', error);

        // 3. Assert the values are correct
        // stream "data" event emits cached values
        stream.on('data', function(value) {
          var string = value.toString();
          var json = JSON.parse(string);
          var actual = json.value;
          var expected = items[json.key].value;

          t.equal(actual, expected);

          reads++;
        });

        Object.keys(items).forEach(function(key) {
          stream.write(key);

          writes++;
        });

        // 4. End the stream.
        stream.end();
      });

      function error(err) {
        t.error(err, 'should not error');
        end(t);
      }
    });
  });

  function setup(options, cb) {
    var dispatcher = leafDispatcher(options.definition);
    serve('testing/cache', dispatcher, function(err, res) {
      cb(err, res.runtime.getContext(), res.service, res.end);
    });
  }
}

function TypeService() {}
TypeService.prototype = new typeServiceVdl.TypeService();

TypeService.prototype.isTyped =  function(context, serverCall, any) {
  // We expect to receive the internally typed value of the any.
  // However, clients who send JSValue will not produce a typed value here.
  return TypeUtil.isTyped(any);
};
TypeService.prototype.isString = function(context, serverCall, str) {
  // We expect to receive a native string, if the client sent us one.
  return (typeof str === 'string');
};
TypeService.prototype.isStruct = function(context, serverCall, struct) {
  // A struct should always be typed.
  if (TypeUtil.isTyped(struct)) {
    return;
  }
  // If it was untyped (a JSValue object), then the code is incorrect.
  throw new Error('did not receive a typed struct' + stringify(struct));
};
TypeService.prototype.swap = function(context, serverCall, a, b) {
  return [b, a];
};

runTypeService({
  testName: 'typed, non-async',
  definition: new TypeService(),
  name: 'foo.TypeService'
});

// options: testName, definition, name
function runTypeService(options) {
  var namePrefix = 'Test JS client/server rpc ' + options.testName + ' - ';
  // This test ensures that typed values are sent between JS server and client.
  // The server expects an input of the ANY type, which means that it ought to
  // receive a typed value, if we send a typed value.
  // If we send a JSValue, then it will not end up being wrapped.
  test(namePrefix + 'typeService.isTyped(...)', function(t) {
    setup(options, function(err, ctx, typeService, end) {
      t.error(err, 'should not error on setup');

      typeService.isTyped(ctx, 'foo', function(err, res) {
        t.error(err, 'should not error on isTyped(...)');
        // Use equal instead of notOk to ensure that res is not wrapped.
        t.equal(res, false, '\'foo\' is an untyped string');


        var VomStr = vdl.registry.lookupOrCreateConstructor(vdl.types.STRING);
        var typedString = new VomStr('food');
        typeService.isTyped(ctx, typedString, function(err, res) {
          t.error(err, 'should not error on isTyped(...)');
          // Use equal instead of ok to ensure that res is not wrapped.
          t.equal(res, true, 'VomStr(\'food\') is a typed string');
          end(t);
        });
      });
    });
  });

  test(namePrefix + 'typeService.isTyped(...) - promise', function(t) {
    setup(options, function(err, ctx, typeService, end) {
      t.error(err, 'should not error on setup');

      typeService.isTyped(ctx, 'glue').then(function(res) {
        t.error(err, 'should not error on isTyped(...)');
        // Use equal instead of notOk to ensure that res is not wrapped.
        t.equal(res, false, '\'glue\' is an untyped string');

        var VomStr = vdl.registry.lookupOrCreateConstructor(vdl.types.STRING);
        var typedString = new VomStr('glued');
        typeService.isTyped(ctx, typedString, function(err, res) {
          t.error(err, 'should not error on isTyped(...)');
          // Use equal instead of ok to ensure that res is not wrapped.
          t.equal(res, true, 'VomStr(\'glued\') is a typed string');
          end(t);
        });
      }).catch(function error(err) {
        t.error(err, 'should not error');
        end(t);
      });
    });
  });

  test(namePrefix + 'typeService.isTyped(undefined) - promise', function(t) {
    setup(options, function(err, ctx, typeService, end) {
      t.error(err, 'should not error on setup');

      // Check that you can leave an optional (or any) inArg as undefined.
      // It should not be mistaken for a callback.
      typeService.isTyped(ctx, undefined).then(function(res) {
        t.error(err, 'should not error on isTyped(undefined)');
        t.equal(res, false, 'undefined is treated like JSValue null');

        // Lenient: Having both arg and cb as undefined is fine too.
        typeService.isTyped(ctx, undefined, undefined).then(function(res) {
          t.error(err, 'should not error on isTyped(undefined, undefined)');
          t.equal(res, false, 'undefined is treated like JSValue null');

          // Having any more undefined's is an error (too many args).
          typeService.isTyped(ctx, undefined, undefined, undefined).then(
            function(res) {

            t.fail(err, 'should have errored');
            end(t);
          }).catch(function(err) {
            t.ok(err, 'should error');
            end(t);
          });
        });
      }).catch(function error(err) {
        t.error(err, 'should not error');
        end(t);
      });
    });
  });

  // This test ensures that typed values sent between JS server and client are
  // unwrapped when being processed. Further, the client disallows sending the
  // wrong type to the server.
  test(namePrefix + 'typeService.isString(str)', function(t) {
    setup(options, function(err, ctx, typeService, end) {
      t.error(err, 'should not error on setup');

      typeService.isString(ctx, 'foo', function(err, res) {
        t.error(err, 'should not error on isString(<a string>)');
        // Use equal instead of ok to ensure that res is not wrapped.
        t.equal(res, true, '\'foo\' is a string');

        typeService.isString(ctx, 0, function(err, res) {
          t.ok(err, 'should error on isString(<not a string>)');
          end(t);
        });
      });
    });
  });

  // This test ensures that a typed struct has its type on the other side.
  // That would prove that it was not decoded as a JSValue.
  test(namePrefix + 'typeService.isStruct(struct)', function(t) {
    setup(options, function(err, ctx, typeService, end) {
      t.error(err, 'should not error on setup');

      typeService.isStruct(ctx, {}, function(err, res) {
        t.error(err, 'should not error on isStruct(...)');
        end(t);
      });
    });
  });

  // This test ensures that multiple typed I/O arguments are possible in JS.
  test(namePrefix + 'typeService.swap(a, b)', function(t) {
    setup(options, function(err, ctx, typeService, end) {
      t.error(err, 'should not error on setup');

      // Start by swapping JSValue. There are no types attached when returned.
      var a = '33';
      var b = 33;
      typeService.swap(ctx, a, b, function(err, res1, res2) {
        t.error(err, 'should not error on swap(...)');
        t.deepEqual([res1, res2], [b, a], 'correctly swapped the 2 inputs');

        // Now, swap a typed value (aa) with a wrapped and typed value (bb).
        var simpleType = {
          name: 'SimpleStruct',
          kind: vdl.kind.STRUCT,
          fields: [
            {
              name: 'Foo',
              type: vdl.types.INT32
            },
            {
              name: 'Bar',
              type: vdl.types.BOOL
            }
          ]
        };
        var SimpleStruct = vdl.registry.lookupOrCreateConstructor(simpleType);
        var aa = new SimpleStruct({
          foo: 10,
          bar: true
        });
        var simpleTypeB = vdl.types.INT32;
        var SimpleInt32 = vdl.registry.lookupOrCreateConstructor(simpleTypeB);
        var bb = new SimpleInt32(-32);
        typeService.swap(ctx, aa, bb, function(err, res1, res2) {
          t.error(err, 'should not error on swap(...)');
          t.deepEqual([res1, res2], [bb, aa], 'correctly swapped the 2 inputs');

          // Verify that res2 (the original aa) still has the right type.
          t.ok(TypeUtil.isTyped(res2), 'aa is still typed');
          t.deepEqual(res2._type, simpleType, 'aa has the correct type');

          // Verify that res1 (the original bb) still has the right type.
          t.ok(TypeUtil.isTyped(res1), 'bb is still typed');
          t.deepEqual(res1._type, simpleTypeB, 'bb has the correct type');

          end(t);
        });
      });
    });
  });

  function setup(options, cb) {
    var dispatcher = leafDispatcher(options.definition);

    serve('testing/typeService', dispatcher, function(err, res) {
      cb(err, res.runtime.getContext(), res.service, res.end);
    });
  }
}

var boolListType = typedStreamingServiceVdl.BoolList.prototype._type;
var numStructType = typedStreamingServiceVdl.NumStruct.prototype._type;
var typeListType = typedStreamingServiceVdl.TypeList.prototype._type;

// TODO(alexfandrianto): Add a callback version of the typed streaming service.
// See each test case for what the service method tests.
function TypedStreamingService() {}
TypedStreamingService.prototype =
  new typedStreamingServiceVdl.TypedStreamingService();

// inStreamOnly verifies that typed inStreams work properly.
TypedStreamingService.prototype.inStreamOnly =
  function(ctx, serverCall, numTimes, $stream) {

  // Receive stream values numTimes
  var numReceived = 0;
  var def = new Deferred();
  $stream.on('end', function() {
    if (numReceived !== numTimes) {
      var err = new Error('Got ' + numReceived + '. Wanted ' + numTimes);
      def.reject(err);
    }
    def.resolve(numReceived);
  });

  $stream.on('error', function(e) {
    def.reject(e);
  });
  $stream.on('data', function(str) {
    if (typeof str !== 'string') {
      def.reject(new Error('Expected a string, but got ' + str));
    }
    numReceived++;
  });
  $stream.read();
  $stream.write('No outstream type; this cannot be sent');
  return def.promise;
};

// outStreamOnly verifies that typed outStreams work properly.
TypedStreamingService.prototype.outStreamOnly =
  function(ctx, serverCall, numTimes, $stream, cb) {

  // Send stream values numTimes
  var numSent = 0;
  while (numSent < numTimes) {
    $stream.write(numSent); // Despite sending int, we autoconvert to BigInt.
    numSent++;
  }
  return cb(null, numSent);
};

// bidirBoolListNegationsStream tests that bidirectional streams can send
// composite types back and forth, as well as modify the data items streamed.
TypedStreamingService.prototype.bidirBoolListNegationStream =
  function(ctx, serverCall, $stream) {

  // Given a list of bool, send the opposite bools back.
  var numReceived = 0;
  var def = new Deferred();
  $stream.on('end', function() {
    def.resolve(numReceived);
  });

  $stream.on('error', function(e) {
    def.reject(e);
  });
  $stream.on('data', function(boolList) {
    numReceived++;
    var oppList = boolList.map(function(b) {
      return !b;
    });
    $stream.write(oppList);
  });
  $stream.read();
  return def.promise;
};

// structValueStream converts a number to a struct based on that number.
// Ensures that custom-defined types can be sent across the stream.
TypedStreamingService.prototype.structValueStream =
  function(ctx, serverCall, $stream) {

  // Given a number, send a number struct back.
  var numReceived = 0;
  var def = new Deferred();
  $stream.on('end', function() {
    def.resolve(numReceived);
  });
  $stream.on('error', function(e) {
    def.reject(e);
  });
  $stream.on('data', function(num) {
    numReceived++;
    $stream.write({
      'number': num,
      'bigInt': vdl.BigInt.fromNativeNumber(num),
      'string': '' + num
    });
  });
  $stream.read();
  return def.promise;
};

// anyStream tests that typed values can pass through a bidirectional stream.
TypedStreamingService.prototype.anyStream =
  function(ctx, serverCall, types, $stream) {

  // Given a list of types, listen to a stream of values.
  // Errors if any of the values received did not match their expected type.
  // Stream those values back directly.
  var typesReceived = [];
  var def = new Deferred();
  $stream.on('end', function() {
    def.resolve(typesReceived);
  });
  $stream.on('error', function(e) {
    def.reject(e);
  });
  $stream.on('data', function(val) {
    // Verify that the value has no type if native, or matches, otherwise.
    var expectedType = types[typesReceived.length];
    if (expectedType.equals(vdl.types.JSVALUE) && val._type !== undefined) {
      def.reject(new Error('Native value had a type: ' +
        JSON.stringify(val)));
    }
    if (!expectedType.equals(vdl.types.JSVALUE) &&
      !expectedType.equals(val._type)) {
      def.reject(new Error('Value had wrong type: ' +
        JSON.stringify(val)));
    }

    // The value had the corerct type. Write the same value back.
    // Note: Native values lack types, so use the JSValue type instead.
    typesReceived.push(val._type || vdl.types.JSVALUE);
    $stream.write(val);
  });
  $stream.read();
  return def.promise;
};

runTypedStreamingService({
  testName: 'typed, streaming, non-async',
  definition: new TypedStreamingService(),
  name: 'foo.TypedStreamingService'
});

// options: testName, definition, name
function runTypedStreamingService(options) {
  var namePrefix = 'Test JS client/server rpc ' + options.testName + ' - ';

  // typedStreamingService.inStreamOnly tests:
  // - correct # of values sent to server
  // - values received by server have correct type
  // - outStream is null
  // - client never gets data, even though server tries to send on outStream
  test(namePrefix + 'typedStreamingService.inStreamOnly(...)',
    function(t) {

    setup(options, function(err, ctx, typedStreamingService, end) {
      t.error(err, 'should not error on setup');

      // The # of strings we intend to send.
      var strList = ['asdf', ';lkj', 'qwer', 'poiu'];
      var numStrs = strList.length;

      // Prepare and run the stream test.
      var testdata = {
        inArg: numStrs,
        inData: strList,
        serviceMethod: typedStreamingService.inStreamOnly,
        writeType: vdl.types.STRING,
        readType: null,
        onResolveFunc: function(numReceived) {
          t.equal(numReceived, numStrs,
            'service received correct # of strings');
          end(t);
        },
        onDataFunc: function(value, dataIndex) {
          t.fail('received data from the stream: ' + JSON.stringify(value));
        }
      };
      streamTest(t, ctx, testdata, end);
    });
  });

  // This test verifies that the stream promise rejects normally.
  // We send 4 items, but we claim to the server that we will send 6.
  // Note: the stream also passes the same reject error to the error stream.
  test(namePrefix + 'typedStreamingService.inStreamOnly(...) - failure',
    function(t) {

    setup(options, function(err, ctx, typedStreamingService, end) {
      t.error(err, 'should not error on setup');

      // The # of strings we intend to send.
      var strList = ['asdf', ';lkj', 'qwer', 'poiu'];
      var numStrs = strList.length + 2; // mismatch

      // The stream will send an error on the error stream just before the
      // Promise rejects.
      var onErrorFunc = function(err) {
        t.ok(err, 'should error');
        t.ok(err.message.indexOf('Got 4. Wanted 6') !== -1,
          'has correct error message');
      };

      // Prepare and run the stream test.
      var testdata = {
        inArg: numStrs,
        inData: strList,
        serviceMethod: typedStreamingService.inStreamOnly,
        writeType: vdl.types.STRING,
        readType: null,
        onResolveFunc: function(numReceived) {
          t.fail('should have errored; did not send correct # of strings');
          end(t);
        },
        onDataFunc: function(value, dataIndex) {
          t.fail('received data from the stream: ' + JSON.stringify(value));
        },
        onErrorFunc: onErrorFunc,
        onRejectFunc: function(err) {
          onErrorFunc(err);
          end(t);
        }
      };
      streamTest(t, ctx, testdata, end);
    });
  });

  // This test verifies that the client cannot send a bad type onto the stream.
  // It also verifies that this bad value is not sent to the server.
  // Thus, the promise rejects, and the client gets an error while attempting to
  // write the bad value (write an int instead of a string).
  // Note: the stream also passes the same reject error to the error stream.
  test(namePrefix + 'typedStreamingService.inStreamOnly(...) - failure 2',
    function(t) {

    setup(options, function(err, ctx, typedStreamingService, end) {
      t.error(err, 'should not error on setup');

      // The # of strings we intend to send.
      var strList = [6];
      var numStrs = strList.length;

      // The stream will send an error on the error stream just before the
      // Promise rejects.
      var onErrorFunc = function(err) {
        t.ok(err, 'should error');
        t.ok(err.message.indexOf('Got 0. Wanted 1') !== -1,
          'has correct error message');
      };

      // Prepare and run the stream test.
      var testdata = {
        inArg: numStrs,
        inData: strList,
        serviceMethod: typedStreamingService.inStreamOnly,
        writeType: vdl.types.STRING,
        readType: null,
        onResolveFunc: function(numReceived) {
          t.fail('should have errored; sent an int');
          end(t);
        },
        onDataFunc: function(value, dataIndex) {
          t.fail('received data from the stream: ' + JSON.stringify(value));
        },
        inDataThrowRegexp: /.*cannot convert to string.*/,
        onErrorFunc: onErrorFunc,
        onRejectFunc: function(err) {
          onErrorFunc(err);
          end(t);
        }
      };
      streamTest(t, ctx, testdata, end);
    });
  });

  // typedStreamingService.outStreamOnly tests:
  // - correct # of values read and outputted
  // - values received by server have the correct type
  // - inStream is null
  test(namePrefix + 'typedStreamingService.outStreamOnly(...)', function(t) {

    setup(options, function(err, ctx, typedStreamingService, end) {
      t.error(err, 'should not error on setup');

      // The # of BigInts we want to receive and # received so far.
      var numInts = 3;
      var numOutStream = 0;

      // Prepare and run the stream test.
      var testdata = {
        inArg: numInts,
        inData: [],
        serviceMethod: typedStreamingService.outStreamOnly,
        writeType: null,
        readType: vdl.types.INT64,
        onResolveFunc: function(numSent) {
          t.equal(numSent, numInts, 'service knows # of values sent');
          t.equal(numOutStream, numInts, 'service sent correct # of values');
          end(t);
        },
        onDataFunc: function(value, dataIndex) {
          t.ok(value instanceof vdl.BigInt, 'value is a BigInt');
          numOutStream++;
        }
      };
      streamTest(t, ctx, testdata, end);
    });
  });

  // typedStreamingService.bidirBoolListNegationStream tests:
  // - custom defined type (simple) can be sent and received properly
  // - the values can be modified and returned (each bool is negated)
  test(namePrefix + 'typedStreamingService.bidirBoolListNegationStream()',
    function(t) {

    setup(options, function(err, ctx, typedStreamingService, end){
      t.error(err, 'should not error on setup');

      // These are the testcases.
      var boolLists = [
        undefined,          // Note: undefined autoconverts to empty list.
        [],
        [true],
        [false, true, true],
        [undefined, false], // Note: undefined autoconverts to false.
      ];
      var expectedLists = [
        [],
        [],
        [false],
        [true, false, false],
        [true, true]
      ];

      // Prepare and run the stream test.
      var testdata = {
        inArg: undefined,
        inData: boolLists,
        serviceMethod: typedStreamingService.bidirBoolListNegationStream,
        writeType: boolListType,
        readType: boolListType,
        onResolveFunc: function(numReceived) {
          t.deepEqual(numReceived, boolLists.length,
            'service sent correct # of values');
          end(t);
        },
        onDataFunc: function(actual, dataIndex) {
          t.ok(Array.isArray(actual), 'value is an array');
          t.deepEqual(actual, expectedLists[dataIndex],
            'bools were flipped');
        }
      };
      streamTest(t, ctx, testdata, end);
    });
  });

  // typedStreamingService.structValueStream tests:
  // - values with a named struct type can be received properly
  test(namePrefix + 'typedStreamingService.structValueStream()', function(t) {
    setup(options, function(err, ctx, typedStreamingService, end){
      t.error(err, 'should not error on setup');

      // These are the testcases.
      var numbers = [
        undefined, // Note: undefined autoconverts to 0
        3,
        -500000
      ];
      var NumStruct = vdl.registry.lookupOrCreateConstructor(numStructType);
      var expectedNumStructs = [
        new NumStruct({
          string: '0'
        }),
        new NumStruct({
          number: 3,
          bigInt: vdl.BigInt.fromNativeNumber(3),
          string: '3'
        }),
        new NumStruct({
          number: -500000,
          bigInt: vdl.BigInt.fromNativeNumber(-500000),
          string: '-500000'
        })
      ];

      // Prepare and run the stream test.
      var testdata = {
        inArg: undefined,
        inData: numbers,
        serviceMethod: typedStreamingService.structValueStream,
        writeType: vdl.types.FLOAT64,
        readType: numStructType,
        onResolveFunc: function(numReceived) {
          t.deepEqual(numReceived, numbers.length,
            'service sent correct # of values');
          end(t);
        },
        onDataFunc: function(actual, dataIndex) {
          t.ok(actual instanceof NumStruct, 'value is a NumStruct');
          t.deepEqual(actual, expectedNumStructs[dataIndex],
            'number converted to NumStruct');
        }
      };
      streamTest(t, ctx, testdata, end);
    });
  });

  // typedStreamingService.anyStream tests:
  // - the any stream succeeds in both directions
  // - complicated types can be sent across the stream in both directions
  // - the types received by the server match the expected types
  // - the types received by the client match the expected types
  test(namePrefix + 'typedStreamingService.anyStream()', function(t) {
    setup(options, function(err, ctx, typedStreamingService, end){
      t.error(err, 'should not error on setup');

      // These are the testcases.
      var typesSent = [
        vdl.types.JSVALUE,
        vdl.types.INT32,
        vdl.types.INT64,
        vdl.types.COMPLEX128,
        vdl.types.STRING,
        vdl.types.BOOL,
        numStructType,
        boolListType,
        typeListType
      ];

      var NumStruct = vdl.registry.lookupOrCreateConstructor(numStructType);
      var BoolList = vdl.registry.lookupOrCreateConstructor(boolListType);
      var TypeList = vdl.registry.lookupOrCreateConstructor(typeListType);

      var sendList = [
        3.14,
        new builtins.INT32(5),
        new builtins.INT64(-15),
        new builtins.COMPLEX128(new vdl.Complex(5, -5)),
        new builtins.STRING('abc'),
        new builtins.BOOL(true),
        new NumStruct({
          number: -0.5
        }),
        new BoolList([true, true, false, false]),
        new TypeList(typesSent)
      ];

      // Prepare and run the stream test.
      var testdata = {
        inArg: typesSent,
        inData: sendList,
        serviceMethod: typedStreamingService.anyStream,
        writeType: vdl.types.ANY,
        readType: vdl.types.ANY,
        onResolveFunc: function(typesReceived) {
          t.deepEqual(typesReceived, typesSent,
          'service sent back the correct types');
          end(t);
        },
        onDataFunc: function(actual, dataIndex) {
          if (actual._type === undefined) {
            t.ok(typesSent[dataIndex].equals(vdl.types.JSVALUE),
              'value is native');
          } else {
            t.deepEqual(actual._type, typesSent[dataIndex], 'type matches');
          }
          t.deepEqual(actual, sendList[dataIndex], 'received correct value');
        }
      };
      streamTest(t, ctx, testdata, end);
    });
  });

  function setup(options, cb) {
    var dispatcher = leafDispatcher(options.definition);

    serve('testing/typeService', dispatcher, function(err, res) {
      cb(err, res.runtime.getContext(), res.service, res.end);
    });
  }
}

/*
 * Performs a stream test that assumes <= 1 input arg to the service method.
 * testdata contains inArg, inData, serviceMethod, writeType, readType,
 * onResolveFunc, onDataFunc
 * Note: onResolveFunc and onDataFunc should end the test.
 * Optional testdata fields: inDataThrowRegexp, onErrorFunc, and onRejectFunc;
 * these are most useful for error test cases.
 */
function streamTest(t, ctx, testdata, end) {
  // The Error function is optional; successful test cases never need it.
  function error(err) {
    t.error(err, 'should not error');
    end(t);
  }

  // Determine the correct onRejectFunc and onErrorFunc handlers.
  var onRejectFunc = testdata.onRejectFunc || error;
  var onErrorFunc = testdata.onErrorFunc || error;

  // 1. Create a stream reader/writer to receive the values
  var promise = testdata.serviceMethod(ctx, testdata.inArg);
  var stream = promise.stream;
  t.deepEqual(stream.writeType, testdata.writeType, 'inStream matches type');
  t.deepEqual(stream.readType, testdata.readType, 'outStream matches type');

  // 2. Handle RPC
  promise.then(testdata.onResolveFunc).catch(onRejectFunc);

  // 3. Setup listeners for the stream. Data should be NumStructs
  stream.on('error', onErrorFunc);

  var dataIndex = 0;
  stream.on('data', function(actual) {
    testdata.onDataFunc(actual, dataIndex);
    dataIndex++;
  });

  // 4. Send data through the stream.
  for (var i = 0; i < testdata.inData.length; i++) {
    if (testdata.inDataThrowRegexp) {
      t.throws(stream.write.bind(stream, testdata.inData[i]),
        testdata.inDataThrowRegexp, 'stream write throws on bad input');
    } else {
      stream.write(testdata.inData[i]);
    }
  }

  // 5. End the stream.
  stream.end();
}

test('Test server stream exception handling', function(assert) {
  var exception;

  if (typeof window === 'undefined') {
    process.on('uncaughtException', function setexception(err) {
      exception = err;
      process.removeListener('uncaughtException', setexception);
    });
  } else {
    window.onerror = function(message, url, line, column, err) {
      exception = err;
      // Put it back to the default
      window.onerror = null;
    };
  }

  var service = {
    get: function get(context, serverCall, $stream, cb) {
      $stream.on('end', cb.bind(null, null, {}));
      $stream.on('error', cb);
      $stream.on('data', function ondata(buffer) {
        throw new Error('Woah!');
      });
    }
  };

  setup(service, function ready(err, context, remote, end) {
    assert.error(err, 'should not error on setup');

    var stream = remote.get(context, function(err) {
      assert.error(err);
      assert.ok(exception, 'stream exceptions should be raised');
      end(assert);
    }).stream;

    stream.write('foo');
    stream.end();
  });

  function setup(service, cb) {
    var dispatcher = leafDispatcher(service);
    var name = 'test/server-stream-exception';

    serve(name, dispatcher, function(err, res) {
      cb(err, res.runtime.getContext(), res.service, res.end);
    });
  }
});
