aws-crt
Version:
NodeJS/browser bindings to the aws-c-* libraries
1,394 lines (1,122 loc) • 71.3 kB
text/typescript
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
import * as subscription_manager from "./subscription_manager";
import {once} from "events";
import {newLiftedPromise} from "../../common/promise";
import {CrtError} from "../error";
import * as protocol_adapter_mock from "./protocol_adapter_mock";
jest.setTimeout(10000);
function createBasicSubscriptionManagerConfig() : subscription_manager.SubscriptionManagerConfig {
return {
maxRequestResponseSubscriptions: 2,
maxStreamingSubscriptions: 1,
operationTimeoutInSeconds: 30,
};
}
test('Subscription Manager - Acquire Subscribing Success', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let filter3 = "a/b/events";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter3,
timeoutInSeconds: 30
}
}
);
let subscribeSuccessPromise1 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
let subscribeSuccess1 = (await subscribeSuccessPromise1)[0];
expect(subscribeSuccess1.topicFilter).toEqual(filter1);
expect(subscribeSuccess1.operationId).toEqual(1);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
let subscribeSuccessPromise2 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter2);
let subscribeSuccess2 = (await subscribeSuccessPromise2)[0];
expect(subscribeSuccess2.topicFilter).toEqual(filter2);
expect(subscribeSuccess2.operationId).toEqual(2);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 2));
let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED);
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter3);
let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0];
expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter3);
expect(streamingSubscriptionEstablished.operationId).toEqual(3);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Multiple Subscribing Success', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/accepted";
let filter2 = "a/b/rejected";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
);
let allPromise = newLiftedPromise<void>();
let subscribeSuccesses = new Array<subscription_manager.SubscribeSuccessEvent>();
subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => {
subscribeSuccesses.push(event);
if (subscribeSuccesses.length == 2) {
allPromise.resolve();
}
});
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
adapter.completeSubscribe(filter2);
await allPromise.promise;
let expectedSubscribeSuccesses = new Array<subscription_manager.SubscribeSuccessEvent>(
{
topicFilter: filter1,
operationId: 1,
},
{
topicFilter: filter2,
operationId: 1,
}
);
expect(subscribeSuccesses).toEqual(expectedSubscribeSuccesses);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Existing Subscribing', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
}
);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 4,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Multi Existing Subscribing', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
}
);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Multi Partially Subscribed', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
}
);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Subscribed Success', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
);
let subscribeSuccessPromise1 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
let subscribeSuccess1 = (await subscribeSuccessPromise1)[0];
expect(subscribeSuccess1.topicFilter).toEqual(filter1);
expect(subscribeSuccess1.operationId).toEqual(1);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter2);
let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0];
expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter2);
expect(streamingSubscriptionEstablished.operationId).toEqual(2);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribed);
expect(subscriptionManager.acquireSubscription({
operationId: 4,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribed);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Multi Subscribed Success', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
);
let subscribeSuccessPromise1 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
let subscribeSuccess1 = (await subscribeSuccessPromise1)[0];
expect(subscribeSuccess1.topicFilter).toEqual(filter1);
expect(subscribeSuccess1.operationId).toEqual(1);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
let subscribeSuccessPromise2 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter2);
let subscribeSuccess2 = (await subscribeSuccessPromise2)[0];
expect(subscribeSuccess2.topicFilter).toEqual(filter2);
expect(subscribeSuccess2.operationId).toEqual(2);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribed);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Request-Response Blocked', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let filter3 = "fail/ure";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Multi Request-Response Partial Blocked', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let filter3 = "fail/ure";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter2, filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Streaming Blocked', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let filter2 = "hello/world";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'unsubscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0];
expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter1);
expect(streamingSubscriptionEstablished.operationId).toEqual(1);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
let subscriptionOrphanedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIPTION_ORPHANED);
subscriptionManager.releaseSubscription({
operationId: 1,
topicFilters: [filter1]
});
let subscriptionOrphaned = (await subscriptionOrphanedPromise)[0];
expect(subscriptionOrphaned.topicFilter).toEqual(filter1);
subscriptionManager.purge();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Multi Streaming Blocked', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
let config = createBasicSubscriptionManagerConfig();
config.maxStreamingSubscriptions = 2;
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config);
let filter1 = "a/b/+";
let filter2 = "hello/world";
let filter3 = "foo/bar";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'unsubscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0];
expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter1);
expect(streamingSubscriptionEstablished.operationId).toEqual(1);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
let subscriptionOrphanedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIPTION_ORPHANED);
subscriptionManager.releaseSubscription({
operationId: 1,
topicFilters: [filter1]
});
let subscriptionOrphaned = (await subscriptionOrphanedPromise)[0];
expect(subscriptionOrphaned.topicFilter).toEqual(filter1);
subscriptionManager.purge();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter2, filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Streaming NoCapacity, None Allowed', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
let config = createBasicSubscriptionManagerConfig();
config.maxStreamingSubscriptions = 0;
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config);
let filter1 = "a/b/+";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>();
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.NoCapacity);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Streaming NoCapacity, Too Many', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
let config = createBasicSubscriptionManagerConfig();
config.maxStreamingSubscriptions = 4;
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config);
for (let i = 0; i < 4; i++) {
let filter = `a/b/${i}`;
expect(subscriptionManager.acquireSubscription({
operationId: i + 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
}
let filter1 = "hello/world";
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.NoCapacity);
});
test('Subscription Manager - Acquire Multi Streaming NoCapacity', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
let config = createBasicSubscriptionManagerConfig();
config.maxStreamingSubscriptions = 2;
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config);
let filter1 = "a/b/+";
let filter2 = "hello/world";
let filter3 = "foo/bar";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0];
expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter1);
expect(streamingSubscriptionEstablished.operationId).toEqual(1);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter2, filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.NoCapacity);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Acquire Failure Mixed Subscription Types', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
let config = createBasicSubscriptionManagerConfig();
config.maxStreamingSubscriptions = 2;
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config);
let filter1 = "a/b/+";
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Failure);
});
test('Subscription Manager - Acquire Multi Failure Mixed Subscription Types', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
let config = createBasicSubscriptionManagerConfig();
config.maxStreamingSubscriptions = 2;
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config);
let filter1 = "a/b/+";
let filter2 = "c/d";
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Failure);
});
test('Subscription Manager - Acquire Failure Poisoned', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
let config = createBasicSubscriptionManagerConfig();
config.maxStreamingSubscriptions = 2;
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config);
let filter1 = "a/b/+";
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
let subscriptionHaltedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_HALTED);
adapter.completeSubscribe(filter1, new CrtError("Unrecoverable Error"));
let subscriptionHalted = (await subscriptionHaltedPromise)[0];
expect(subscriptionHalted.topicFilter).toEqual(filter1);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Failure);
});
test('Subscription Manager - RequestResponse Multi Acquire/Release triggers Unsubscribe', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/accepted";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'unsubscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
let allPromise = newLiftedPromise<void>();
let events = new Array<protocol_adapter_mock.SubscriptionManagerEvent>();
subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => {
events.push({
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: event
});
if (events.length == 2) {
allPromise.resolve();
}
});
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
await allPromise.promise;
let expectedSubscribeSuccesses : protocol_adapter_mock.SubscriptionManagerEvent[] = [
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter1,
operationId: 1,
}
},
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter1,
operationId: 2,
}
}
];
expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedSubscribeSuccesses)).toBeTruthy();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
subscriptionManager.releaseSubscription({
operationId: 1,
topicFilters: [filter1]
});
subscriptionManager.purge();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
subscriptionManager.releaseSubscription({
operationId: 2,
topicFilters: [filter1]
});
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
subscriptionManager.purge();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Multi Acquire/Release Multi triggers Unsubscribes', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/accepted";
let filter2 = "a/b/rejected";
let expectedSubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
];
let expectedUnsubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [
{
methodName: 'unsubscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'unsubscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
];
let allSubscribedPromise = newLiftedPromise<void>();
let events = new Array<protocol_adapter_mock.SubscriptionManagerEvent>();
subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => {
events.push({
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: event
});
if (events.length == 4) {
allSubscribedPromise.resolve();
}
});
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1, filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
adapter.completeSubscribe(filter2);
await allSubscribedPromise.promise;
let expectedSubscribeSuccesses : protocol_adapter_mock.SubscriptionManagerEvent[] = [
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter1,
operationId: 1,
}
},
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter1,
operationId: 2,
}
},
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter2,
operationId: 1,
}
},
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter2,
operationId: 2,
}
},
];
expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedSubscribeSuccesses)).toBeTruthy();
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedSubscribes)).toBeTruthy();
subscriptionManager.releaseSubscription({
operationId: 1,
topicFilters: [filter1, filter2]
});
subscriptionManager.purge();
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeFalsy();
subscriptionManager.releaseSubscription({
operationId: 2,
topicFilters: [filter1, filter2]
});
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeFalsy();
subscriptionManager.purge();
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeTruthy();
});
test('Subscription Manager - Streaming Multi Acquire/Release triggers Unsubscribe', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/accepted";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'unsubscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
let allPromise = newLiftedPromise<void>();
let events = new Array<protocol_adapter_mock.SubscriptionManagerEvent>();
subscriptionManager.addListener(subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED, (event) => {
events.push({
type: subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished,
data: event
});
if (events.length == 2) {
allPromise.resolve();
}
});
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
adapter.completeSubscribe(filter1);
await allPromise.promise;
let expectedStreamingSubscriptionEstablishments : protocol_adapter_mock.SubscriptionManagerEvent[] = [
{
type: subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished,
data: {
topicFilter: filter1,
operationId: 1,
}
},
{
type: subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished,
data: {
topicFilter: filter1,
operationId: 2,
}
}
];
expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedStreamingSubscriptionEstablishments)).toBeTruthy();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
subscriptionManager.releaseSubscription({
operationId: 1,
topicFilters: [filter1]
});
subscriptionManager.purge();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
subscriptionManager.releaseSubscription({
operationId: 2,
topicFilters: [filter1]
});
expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1));
subscriptionManager.purge();
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
async function doUnsubscribeMakesRoomTest(shouldUnsubscribeSucceed: boolean) {
let adapter = new protocol_adapter_mock.MockProtocolAdapter();
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/accepted";
let filter2 = "a/b/rejected";
let filter3 = "hello/world";
let expectedSubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
{
methodName: 'subscribe',
args: {
topicFilter: filter2,
timeoutInSeconds: 30
}
},
];
let blockedSubscribe = {
methodName: 'subscribe',
args: {
topicFilter: filter3,
timeoutInSeconds: 30
}
};
let expectedUnsubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [
{
methodName: 'unsubscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
];
let allSubscribedPromise = newLiftedPromise<void>();
let events = new Array<protocol_adapter_mock.SubscriptionManagerEvent>();
subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => {
events.push({
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: event
});
if (events.length == 2) {
allSubscribedPromise.resolve();
}
});
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 2,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter2]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing);
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
adapter.completeSubscribe(filter1);
adapter.completeSubscribe(filter2);
await allSubscribedPromise.promise;
let expectedSubscribeSuccesses : protocol_adapter_mock.SubscriptionManagerEvent[] = [
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter1,
operationId: 1,
}
},
{
type: subscription_manager.SubscriptionEventType.SubscribeSuccess,
data: {
topicFilter: filter2,
operationId: 2,
}
},
];
expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedSubscribeSuccesses)).toBeTruthy();
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedSubscribes)).toBeTruthy();
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
subscriptionManager.releaseSubscription({
operationId: 1,
topicFilters: [filter1]
});
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeFalsy();
subscriptionManager.purge();
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter3]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked);
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeTruthy();
if (shouldUnsubscribeSucceed) {
adapter.completeUnsubscribe(filter1);
} else {
adapter.completeUnsubscribe(filter1, new CrtError("Help"));
}
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCall(adapter.getApiCalls(), blockedSubscribe)).toBeFalsy();
subscriptionManager.purge();
let expectedAcquireResult = shouldUnsubscribeSucceed ? subscription_manager.AcquireSubscriptionResult.Subscribing : subscription_manager.AcquireSubscriptionResult.Blocked;
expect(subscriptionManager.acquireSubscription({
operationId: 3,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter3]
})).toEqual(expectedAcquireResult);
expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCall(adapter.getApiCalls(), blockedSubscribe)).toEqual(shouldUnsubscribeSucceed);
}
test('Subscription Manager - Successful Unsubscribe Frees Subscription Space', async () => {
await doUnsubscribeMakesRoomTest(true);
});
test('Subscription Manager - Unsuccessful Unsubscribe Does Not Free Subscription Space', async () => {
await doUnsubscribeMakesRoomTest(false);
});
test('Subscription Manager - Synchronous RequestResponse Subscribe Failure causes acquire failure', async () => {
let adapter = new protocol_adapter_mock.MockProtocolAdapter({
subscribeHandler: (subscribeOptions) => { throw new CrtError("Bad"); }
});
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.RequestResponse,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Failure);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
});
test('Subscription Manager - Synchronous Streaming Subscribe Failure causes acquire failure and poisons future acquires', async () => {
let attemptNumber = 0;
let adapter = new protocol_adapter_mock.MockProtocolAdapter({
subscribeHandler: (subscribeOptions) => {
attemptNumber++;
if (attemptNumber == 1) {
throw new CrtError("Bad");
}
}
});
adapter.connect();
// @ts-ignore
let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig());
let filter1 = "a/b/+";
let expectedApiCalls : Array<protocol_adapter_mock.ProtocolAdapterApiCall> = new Array<protocol_adapter_mock.ProtocolAdapterApiCall>(
{
methodName: 'subscribe',
args: {
topicFilter: filter1,
timeoutInSeconds: 30
}
},
);
expect(subscriptionManager.acquireSubscription({
operationId: 1,
type: subscription_manager.SubscriptionType.EventStream,
topicFilters: [filter1]
})).toEqual(subscription_manager.AcquireSubscriptionResult.Failure);
expect(adapter.getApiCalls()).toEqual(expectedApiCalls);
subscriptionManager.purge();
expect(subscriptionManager.acquireSubsc