aws-crt
Version:
NodeJS/browser bindings to the aws-c-* libraries
940 lines (660 loc) • 34.1 kB
text/typescript
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
import * as eventstream from './eventstream';
import * as cancel from '../common/cancel';
import {once} from "events";
import crt_native from "./binding";
import * as os from "os";
jest.setTimeout(10000);
function hasEchoServerEnvironment() : boolean {
if (process.env.AWS_TEST_EVENT_STREAM_ECHO_SERVER_HOST === undefined) {
return false;
}
if (process.env.AWS_TEST_EVENT_STREAM_ECHO_SERVER_PORT === undefined) {
return false;
}
return true;
}
const conditional_test = (condition : boolean) => condition ? it : it.skip;
function closeNativeConnectionInternal(connection: eventstream.ClientConnection) {
// invoke an internal close that bypasses the binding. The result is an invocation that simulates a network
// disruption from the binding's perspective
crt_native.event_stream_client_connection_close_internal(connection.native_handle());
}
function makeGoodConfig() : eventstream.ClientConnectionOptions {
let config : eventstream.ClientConnectionOptions = {
hostName: process.env.AWS_TEST_EVENT_STREAM_ECHO_SERVER_HOST ?? "",
port: parseInt(process.env.AWS_TEST_EVENT_STREAM_ECHO_SERVER_PORT ?? "0"),
};
return config;
}
/*
* successful connection setup/teardown tests include some short waits to try and shake out any native race conditions
* that might occur due to JS object finalization after close. For the same reason, we scope the connection object
* to a helper function, making finalization on the extern more likely.
*/
conditional_test(hasEchoServerEnvironment())('Eventstream transport connection success echo server - await connect, close, and forget', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
let cancelController : cancel.CancelController = new cancel.CancelController();
await connection.connect({
cancelController : cancelController
});
// @ts-ignore
expect(cancelController.emitter.listenerCount(cancel.EVENT_NAME)).toEqual(0);
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream transport connection success echo server - await connect, simulate remote close', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
let disconnected = once(connection, eventstream.ClientConnection.DISCONNECTION);
await connection.connect({});
// simulate a socket closed by the remote endpoint scenario
closeNativeConnectionInternal(connection);
await disconnected;
await new Promise(resolve => setTimeout(resolve, 200));
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream transport connection success echo server - start connect, close, and forget', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
// intentionally do not await to try and beat the native connection setup with a close call
connection.connect({});
connection.close();
await new Promise(resolve => setTimeout(resolve, 200));
});
async function doConnectionFailureTest(config : eventstream.ClientConnectionOptions) {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(config);
let controller : cancel.CancelController = new cancel.CancelController();
await expect(connection.connect({
cancelController : controller
})).rejects.toBeDefined();
// @ts-ignore
expect(controller.emitter.listenerCount(cancel.EVENT_NAME)).toEqual(0);
connection.close();
}
test('Eventstream transport connection failure echo server - bad host', async () => {
let badConfig : eventstream.ClientConnectionOptions = makeGoodConfig();
badConfig.hostName = "derp.notarealdomainseriously.org";
await doConnectionFailureTest(badConfig);
});
conditional_test(hasEchoServerEnvironment())('Eventstream transport connection failure echo server - bad port', async () => {
let badConfig : eventstream.ClientConnectionOptions = makeGoodConfig();
badConfig.port = 33333;
await doConnectionFailureTest(badConfig);
});
async function doProtocolConnectionSuccessTest1() {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
const connectResponse = once(connection, eventstream.ClientConnection.PROTOCOL_MESSAGE);
let connectMessage: eventstream.Message = {
type: eventstream.MessageType.Connect,
headers: [
eventstream.Header.newString(':version', '0.1.0'),
eventstream.Header.newString('client-name', 'accepted.testy_mc_testerson')
]
};
await connection.sendProtocolMessage({
message: connectMessage
});
let response : eventstream.MessageEvent = (await connectResponse)[0];
let message : eventstream.Message = response.message;
expect(message.type).toEqual(eventstream.MessageType.ConnectAck);
expect(message.flags).toBeDefined();
expect((message.flags ?? 0) & eventstream.MessageFlags.ConnectionAccepted).toEqual(eventstream.MessageFlags.ConnectionAccepted);
connection.close();
}
conditional_test(hasEchoServerEnvironment())('Eventstream protocol connection success Echo Server - happy path', async () => {
await doProtocolConnectionSuccessTest1();
await new Promise(resolve => setTimeout(resolve, 200));
});
async function doProtocolConnectionSuccessTest2() {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
let connectMessage: eventstream.Message = {
type: eventstream.MessageType.Connect,
headers: [
eventstream.Header.newString(':version', '0.1.0'),
eventstream.Header.newString('client-name', 'accepted.testy_mc_testerson')
]
};
connection.sendProtocolMessage({
message: connectMessage
});
connection.close();
await new Promise(resolve => setTimeout(resolve, 200));
}
conditional_test(hasEchoServerEnvironment())('Eventstream protocol connection success Echo Server - close while connecting', async () => {
await doProtocolConnectionSuccessTest2();
await new Promise(resolve => setTimeout(resolve, 200));
});
async function makeGoodConnection() : Promise<eventstream.ClientConnection> {
return new Promise<eventstream.ClientConnection>(async (resolve, reject) => {
try {
let connection: eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
const connectResponse = once(connection, eventstream.ClientConnection.PROTOCOL_MESSAGE);
let connectMessage: eventstream.Message = {
type: eventstream.MessageType.Connect,
headers: [
eventstream.Header.newString(':version', '0.1.0'),
eventstream.Header.newString('client-name', 'accepted.testy_mc_testerson')
]
};
await connection.sendProtocolMessage({
message: connectMessage
});
let response: eventstream.MessageEvent = (await connectResponse)[0];
let message: eventstream.Message = response.message;
if (((message.flags ?? 0) & eventstream.MessageFlags.ConnectionAccepted) == 0) {
reject();
}
resolve(connection);
} catch (e) {
reject();
}
});
}
function buildAllTypeHeaderSet() : Array<eventstream.Header> {
var encoder = new TextEncoder();
let buffer: ArrayBuffer = encoder.encode("Some test");
let uuid: ArrayBuffer = encoder.encode("0123456789ABCDEF");
let headers: Array<eventstream.Header> = [
eventstream.Header.newBoolean('boolTrue', true),
eventstream.Header.newBoolean('boolFalse', false),
eventstream.Header.newByte('byte', 8),
eventstream.Header.newInt16('int16', 32767),
eventstream.Header.newInt32('int32', -65537),
eventstream.Header.newInt64FromBigint('int64Bigint', BigInt(65536) * BigInt(65536) * BigInt(2)),
eventstream.Header.newInt64FromNumber('int64Number', 65536 * 65536 * 2),
eventstream.Header.newInt64FromNumber('int64NumberNegative1', -1),
eventstream.Header.newInt64FromNumber('int64NumberNegativeLarge', -123456789),
eventstream.Header.newString('string', 'Hello'),
eventstream.Header.newByteBuffer('binary', buffer),
eventstream.Header.newTimeStampFromDate('date', new Date()),
eventstream.Header.newTimeStampFromSecondsSinceEpoch('epochSeconds', Date.now()),
eventstream.Header.newUUID('uuid', uuid)
];
return headers;
}
function verifyEchoedHeaders(expectedHeaders : Array<eventstream.Header>, actualHeaders : Array<eventstream.Header>) {
expectedHeaders.forEach((header: eventstream.Header) => {
let actualHeader = actualHeaders.find((value: eventstream.Header) => { return value.name === header.name; });
expect(actualHeader).toBeDefined();
// @ts-ignore
expect(header.type).toEqual(actualHeader.type);
switch(header.type) {
case eventstream.HeaderType.BooleanFalse:
case eventstream.HeaderType.BooleanTrue:
break;
case eventstream.HeaderType.ByteBuffer:
case eventstream.HeaderType.UUID:
case eventstream.HeaderType.Int64:
// @ts-ignore
expect(Buffer.from(header.value as ArrayBuffer)).toEqual(Buffer.from(actualHeader.value as ArrayBuffer));
break;
default:
// @ts-ignore
expect(header.value).toEqual(actualHeader.value);
break;
}
});
}
async function verifyPingRoundTrip(connection : eventstream.ClientConnection) : Promise<void> {
return new Promise<void>(async (resolve, reject) => {
try {
const pingResponse = once(connection, eventstream.ClientConnection.PROTOCOL_MESSAGE);
var encoder = new TextEncoder();
let payload: ArrayBuffer = encoder.encode("A payload");
let headers: Array<eventstream.Header> = buildAllTypeHeaderSet();
let pingMessage: eventstream.Message = {
type: eventstream.MessageType.Ping,
headers: headers,
payload: payload
};
await connection.sendProtocolMessage({
message: pingMessage
});
let responseEvent: eventstream.MessageEvent = (await pingResponse)[0];
let response: eventstream.Message = responseEvent.message;
expect(response.type).toEqual(eventstream.MessageType.PingResponse);
expect(response.headers).toBeDefined();
verifyEchoedHeaders(headers, response.headers ?? []);
expect(Buffer.from(payload)).toEqual(Buffer.from(response.payload as ArrayBuffer));
resolve();
} catch (e) {
reject();
}
});
}
conditional_test(hasEchoServerEnvironment())('Eventstream connection success - send and receive all-header-types ping', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
await verifyPingRoundTrip(connection);
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream protocol connection failure Echo Server - bad version', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
const connectResponse = once(connection, eventstream.ClientConnection.PROTOCOL_MESSAGE);
const disconnected = once(connection, eventstream.ClientConnection.DISCONNECTION);
let connectMessage: eventstream.Message = {
type: eventstream.MessageType.Connect,
headers: [
eventstream.Header.newString(':version', '0.0.1'),
eventstream.Header.newString('client-name', 'accepted.testy_mc_testerson')
]
};
await connection.sendProtocolMessage({
message: connectMessage
});
/*
* Sigh.
* On Windows, our EchoTest server closes the connection in this case with an RST rather than a FIN. Searching
* the web hints at a possible timing issue (that affects Windows far more than other platforms) when closing
* server-side (listener-spawned) sockets that leads to an RST over a FIN:
*
* https://github.com/libuv/libuv/issues/3034 shows a similar problem, for example.
*
* A socket that is closed with an RST is not readable, despite the fact that there was previously received data.
* So we'll never be able to get the failed ConnAck because the attempt to read from the socket fails immediately.
*
* Alternatively, we could restrict these tests to domain/local sockets but that creates its own set of problems,
* requiring platform-specific permissions tweaks to allow communication between multiple processes.
*
* So in the interest of avoiding rabbit holes, we only verify the failed connack on non-Windows platforms.
*/
if (os.platform() !== 'win32') {
let response: eventstream.MessageEvent = (await connectResponse)[0];
let message: eventstream.Message = response.message;
expect(message.type).toEqual(eventstream.MessageType.ConnectAck);
expect(message.flags).toBeDefined();
expect((message.flags ?? 0) & eventstream.MessageFlags.ConnectionAccepted).toEqual(0);
}
await disconnected;
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection failure - create with undefined', async () => {
expect(() => {
// @ts-ignore
new eventstream.ClientConnection(undefined)
}).toThrow();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection failure - create with missing required property', async () => {
let config : eventstream.ClientConnectionOptions = makeGoodConfig();
// @ts-ignore
config.hostName = undefined;
expect(() => {
new eventstream.ClientConnection(config)
}).toThrow();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection failure - sendProtocolMessage with undefined', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
// @ts-ignore
await expect(connection.sendProtocolMessage(undefined )).rejects.toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection failure - sendProtocolMessage with missing required property', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
let controller : cancel.CancelController = new cancel.CancelController();
// @ts-ignore
await expect(connection.sendProtocolMessage({
cancelController: controller
} )).rejects.toThrow();
// @ts-ignore
expect(controller.emitter.listenerCount(cancel.EVENT_NAME)).toEqual(0);
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - newStream while not connected', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
expect(() => {connection.newStream();}).toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - sendProtocolMessage while not connected', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
let message : eventstream.Message = {
type: eventstream.MessageType.Connect
};
await expect(connection.sendProtocolMessage({message: message} )).rejects.toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - connect while connecting', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
let connected : Promise<void> = connection.connect({});
await expect(connection.connect({})).rejects.toThrow();
await connected;
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - connect while connected', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
await expect(connection.connect({})).rejects.toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - connect while disconnected', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
let disconnected = once(connection, eventstream.ClientConnection.DISCONNECTION);
await connection.connect({});
// simulate a socket closed by the remote endpoint scenario
closeNativeConnectionInternal(connection);
await disconnected;
await expect(connection.connect({})).rejects.toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - newStream while disconnected', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
let disconnected = once(connection, eventstream.ClientConnection.DISCONNECTION);
await connection.connect({});
// simulate a socket closed by the remote endpoint scenario
closeNativeConnectionInternal(connection);
await disconnected;
expect(() => {connection.newStream();}).toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - sendProtocolMessage while disconnected', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
let disconnected = once(connection, eventstream.ClientConnection.DISCONNECTION);
await connection.connect({});
// simulate a socket closed by the remote endpoint scenario
closeNativeConnectionInternal(connection);
await disconnected;
let message : eventstream.Message = {
type: eventstream.MessageType.Connect
};
await expect(connection.sendProtocolMessage({message: message} )).rejects.toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - connect while closed', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
connection.close();
await expect(connection.connect({})).rejects.toThrow();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - newStream while closed', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
connection.close();
expect(() => {connection.newStream();}).toThrow();
});
conditional_test(hasEchoServerEnvironment())('Eventstream connection state failure - sendProtocolMessage while closed', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
connection.close();
let message : eventstream.Message = {
type: eventstream.MessageType.Connect
};
await expect(connection.sendProtocolMessage({message: message} )).rejects.toThrow();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream success - create and close, no asserts', async () => {
let connection : eventstream.ClientConnection = new eventstream.ClientConnection(makeGoodConfig());
await connection.connect({});
let stream : eventstream.ClientStream = connection.newStream();
stream.close();
connection.close();
});
async function openPersistentEchoStream(connection: eventstream.ClientConnection) : Promise<eventstream.ClientStream> {
return new Promise<eventstream.ClientStream>(async (resolve, reject) => {
try {
let stream : eventstream.ClientStream = connection.newStream();
const activateResponse = once(stream, eventstream.ClientStream.MESSAGE);
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage
};
let controller : cancel.CancelController = new cancel.CancelController();
await stream.activate({
operation: "awstest#EchoStreamMessages",
message : message,
cancelController : controller
});
let responseEvent: eventstream.MessageEvent = (await activateResponse)[0];
let response: eventstream.Message = responseEvent.message;
expect(response.type).toEqual(eventstream.MessageType.ApplicationMessage);
// @ts-ignore
expect(controller.emitter.listenerCount(cancel.EVENT_NAME)).toEqual(0);
resolve(stream);
} catch (e) {
reject();
}
});
}
conditional_test(hasEchoServerEnvironment())('Eventstream stream success - activate persistent echo stream, wait for response, close properly', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream success - activate persistent echo stream, wait for response, close unexpectedly, verify stream ended event', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
let streamEnded = once(stream, eventstream.ClientStream.ENDED);
crt_native.event_stream_client_connection_close_internal(connection.native_handle());
await streamEnded;
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream success - activate one-time echo stream, verify response, verify stream ended', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = connection.newStream();
const activateResponse = once(stream, eventstream.ClientStream.MESSAGE);
const streamEnded = once(stream, eventstream.ClientStream.ENDED);
const payloadAsString = "{}";
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage,
payload: payloadAsString
};
await stream.activate({
operation: "awstest#EchoMessage",
message : message
});
let responseEvent: eventstream.MessageEvent = (await activateResponse)[0];
let response: eventstream.Message = responseEvent.message;
expect(response.type).toEqual(eventstream.MessageType.ApplicationMessage);
expect(response.flags).toBeDefined();
expect((response.flags ?? 0) & eventstream.MessageFlags.TerminateStream).toEqual(eventstream.MessageFlags.TerminateStream);
let payload : string = "";
if (response.payload !== undefined) {
var decoder = new TextDecoder();
payload = decoder.decode(Buffer.from(response.payload as ArrayBuffer));
}
expect(payload).toEqual(payloadAsString);
await streamEnded;
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream success - activate persistent echo stream, send message, verify echo response', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
const echoResponse = once(stream, eventstream.ClientStream.MESSAGE);
const payloadAsString = "{}";
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage,
payload: payloadAsString
};
await stream.sendMessage({ message : message });
let responseEvent: eventstream.MessageEvent = (await echoResponse)[0];
let response: eventstream.Message = responseEvent.message;
expect(response.type).toEqual(eventstream.MessageType.ApplicationMessage);
expect((response.flags ?? 0) & eventstream.MessageFlags.TerminateStream).toEqual(0);
let payload : string = "";
if (response.payload !== undefined) {
var decoder = new TextDecoder();
payload = decoder.decode(Buffer.from(response.payload as ArrayBuffer));
}
expect(payload).toEqual(payloadAsString);
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream success - client-side terminate a persistent echo stream', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
const streamEnded = once(stream, eventstream.ClientStream.ENDED);
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage,
flags: eventstream.MessageFlags.TerminateStream
};
await stream.sendMessage({ message : message });
await streamEnded;
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - activate invalid operation', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = connection.newStream();
const streamEnded = once(stream, eventstream.ClientStream.ENDED);
const activateResponse = once(stream, eventstream.ClientStream.MESSAGE);
const payloadAsString = "{}";
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage,
payload: payloadAsString
};
await stream.activate({
operation: "awstest#NotAValidOperation",
message : message
});
let responseEvent: eventstream.MessageEvent = (await activateResponse)[0];
let response: eventstream.Message = responseEvent.message;
expect(response.type).toEqual(eventstream.MessageType.ApplicationError);
await streamEnded;
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - send invalid payload', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
const streamEnded = once(stream, eventstream.ClientStream.ENDED);
const echoResponse = once(stream, eventstream.ClientStream.MESSAGE);
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage,
payload: "}"
};
await stream.sendMessage({ message : message });
let responseEvent: eventstream.MessageEvent = (await echoResponse)[0];
let response: eventstream.Message = responseEvent.message;
expect(response.type).toEqual(eventstream.MessageType.ApplicationError);
await streamEnded;
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - send message on unactivated stream', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = connection.newStream();
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage
};
await expect(stream.sendMessage({message: message} )).rejects.toThrow();
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - double activate stream', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage
};
await expect(stream.activate({operation: "awstest#EchoStreamMessages", message: message} )).rejects.toThrow();
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - send message on ended stream', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
const streamEnded = once(stream, eventstream.ClientStream.ENDED);
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage,
flags: eventstream.MessageFlags.TerminateStream
};
await stream.sendMessage({ message : message });
await streamEnded;
await expect(stream.sendMessage({message: message} )).rejects.toThrow();
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - activate a closed stream', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = connection.newStream();
stream.close();
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage
};
await expect(stream.activate({operation: "awstest#EchoStreamMessages", message: message} )).rejects.toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - send message on a closed stream', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
stream.close();
let message : eventstream.Message = {
type: eventstream.MessageType.ApplicationMessage
};
await expect(stream.sendMessage({message: message} )).rejects.toThrow();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - activate with undefined', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = connection.newStream();
// @ts-ignore
await expect(stream.activate(undefined)).rejects.toThrow();
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - activate with missing required property', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = connection.newStream();
let controller : cancel.CancelController = new cancel.CancelController();
// @ts-ignore
let activateOptions : eventstream.ActivateStreamOptions = {
message: {
type: eventstream.MessageType.ApplicationMessage
},
cancelController: controller
}
await expect(stream.activate(activateOptions)).rejects.toThrow();
// @ts-ignore
expect(controller.emitter.listenerCount(cancel.EVENT_NAME)).toEqual(0);
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - sendMessage with undefined', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
// @ts-ignore
await expect(stream.sendMessage(undefined)).rejects.toThrow();
stream.close();
connection.close();
});
conditional_test(hasEchoServerEnvironment())('Eventstream stream failure - sendMessage with missing required property', async () => {
let connection : eventstream.ClientConnection = await makeGoodConnection();
let stream : eventstream.ClientStream = await openPersistentEchoStream(connection);
let controller : cancel.CancelController = new cancel.CancelController();
// @ts-ignore
await expect(stream.sendMessage({
cancelController: controller
})).rejects.toThrow();
// @ts-ignore
expect(controller.emitter.listenerCount(cancel.EVENT_NAME)).toEqual(0);
stream.close();
connection.close();
});
test('Eventstream connection cancel - example.com, cancel after connect', async () => {
// hangs atm
let connection: eventstream.ClientConnection = new eventstream.ClientConnection({
hostName: "example.com",
port: 22
});
let controller : cancel.CancelController = new cancel.CancelController();
setTimeout(() => { controller.cancel(); }, 1000);
await expect(connection.connect({
cancelController : controller
})).rejects.toThrow("cancelled");
});
test('Eventstream connection cancel - example.com, cancel before connect', async () => {
// hangs atm
let connection: eventstream.ClientConnection = new eventstream.ClientConnection({
hostName: "example.com",
port: 22
});
let controller : cancel.CancelController = new cancel.CancelController();
controller.cancel();
await expect(connection.connect({
cancelController : controller
})).rejects.toThrow("cancelled");
});