diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 7bf6b934d3d1..a241830a48ce 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -412,6 +412,24 @@ packages: - supports-color dev: false + /@azure/core-amqp/3.0.0: + resolution: {integrity: sha512-CThDTapwSE2jKr/m9ISHwynagFPkUslwPsyppuJkLaFvc9re5/Kvv5sEP2i5DTG41lxYi0SznqRKEqIBZBJYOw==} + engines: {node: '>=8.0.0'} + dependencies: + '@azure/abort-controller': 1.0.4 + '@azure/core-auth': 1.3.2 + '@azure/logger': 1.0.2 + buffer: 5.7.1 + events: 3.3.0 + jssha: 3.2.0 + process: 0.11.10 + rhea: 2.0.4 + rhea-promise: 2.1.0 + tslib: 2.3.1 + url: 0.11.0 + util: 0.12.4 + dev: false + /@azure/core-asynciterator-polyfill/1.0.0: resolution: {integrity: sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg==} dev: false @@ -993,6 +1011,29 @@ packages: - supports-color dev: false + /@azure/service-bus/7.3.0: + resolution: {integrity: sha512-uGgcC8Fnc4OPZTKEKTbWo42vZABqw8myNSMtrnSXWFrSn+JclRCnhBsc4WPldUHR41HpdWebphf9MbBvmB+K6w==} + engines: {node: '>=12.0.0'} + dependencies: + '@azure/abort-controller': 1.0.4 + '@azure/core-amqp': 3.0.0 + '@azure/core-asynciterator-polyfill': 1.0.0 + '@azure/core-auth': 1.3.2 + '@azure/core-http': 2.2.0 + '@azure/core-paging': 1.2.0 + '@azure/core-tracing': 1.0.0-preview.12 + '@azure/logger': 1.0.2 + '@types/is-buffer': 2.0.0 + '@types/long': 4.0.1 + buffer: 5.7.1 + is-buffer: 2.0.5 + jssha: 3.2.0 + long: 4.0.0 + process: 0.11.10 + rhea-promise: 2.1.0 + tslib: 2.3.1 + dev: false + /@babel/code-frame/7.12.11: resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} dependencies: @@ -10274,11 +10315,12 @@ packages: dev: false file:projects/eventgrid.tgz: - resolution: {integrity: sha512-8gU5FFbkNjNAarqfpkhmSf/agfq7aOZLTVsKRv81V7Gan+oKBq76y+uFqN1JXIqJgBo7dFkxqdqL/uDG27rtFQ==, tarball: file:projects/eventgrid.tgz} + resolution: {integrity: sha512-a7ok5XWs7nBhPSjqBoOpEyIADVTx3DCVxF6IBvx8nI9bQNJAgvMSEFQwQ0vkyqW2Xp9DXhXWBhBOrnx09hldqA==, tarball: file:projects/eventgrid.tgz} name: '@rush-temp/eventgrid' version: 0.0.0 dependencies: '@azure/core-tracing': 1.0.0-preview.13 + '@azure/service-bus': 7.3.0 '@microsoft/api-extractor': 7.18.11 '@rollup/plugin-commonjs': 11.0.2_rollup@1.32.1 '@rollup/plugin-json': 4.1.0_rollup@1.32.1 @@ -11465,10 +11507,11 @@ packages: dev: false file:projects/perf-service-bus.tgz: - resolution: {integrity: sha512-M3kETv0m40YuRP/zOegXkQ56pQECHNG9DjrGZl0xr8fMClhamKX6/eZGcYBkiYIU7MfDONudmhhfsqs9XchzNQ==, tarball: file:projects/perf-service-bus.tgz} + resolution: {integrity: sha512-9nT8nbSd5Xa1x3bt0xwidByYrBER6awoMpL/okQQ/i4SMl5z99bas3642B/Kda9zMhdCjY2q5zSYcPfKRj7Vaw==, tarball: file:projects/perf-service-bus.tgz} name: '@rush-temp/perf-service-bus' version: 0.0.0 dependencies: + '@azure/service-bus': 7.3.0 '@types/node': 12.20.27 '@types/uuid': 8.3.1 dotenv: 8.6.0 diff --git a/sdk/servicebus/service-bus/CHANGELOG.md b/sdk/servicebus/service-bus/CHANGELOG.md index c4a5d180941b..4b35d5e07f1a 100644 --- a/sdk/servicebus/service-bus/CHANGELOG.md +++ b/sdk/servicebus/service-bus/CHANGELOG.md @@ -1,9 +1,11 @@ # Release History -## 7.3.1 (Unreleased) +## 7.3.1-beta.1 (Unreleased) ### Features Added +- Adds new get/set property `maxMessageSizeInKilobytes` to `QueueProperties`, `TopicProperties`, `CreateQueueOptions`, and `CreateTopicOptions`. Only applicable for premium namespaces. Use this when creating or updating queues and topics. Added in [#17953](https://github.com/Azure/azure-sdk-for-js/pull/17953) + ### Breaking Changes ### Bugs Fixed diff --git a/sdk/servicebus/service-bus/package.json b/sdk/servicebus/service-bus/package.json index 501027a4a403..13985da46f5f 100644 --- a/sdk/servicebus/service-bus/package.json +++ b/sdk/servicebus/service-bus/package.json @@ -2,7 +2,7 @@ "name": "@azure/service-bus", "sdk-type": "client", "author": "Microsoft Corporation", - "version": "7.3.1", + "version": "7.3.1-beta.1", "license": "MIT", "description": "Azure Service Bus SDK for JavaScript", "homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/servicebus/service-bus/", diff --git a/sdk/servicebus/service-bus/review/service-bus.api.md b/sdk/servicebus/service-bus/review/service-bus.api.md index 94d3f287797a..96f80d049d5b 100644 --- a/sdk/servicebus/service-bus/review/service-bus.api.md +++ b/sdk/servicebus/service-bus/review/service-bus.api.md @@ -74,6 +74,7 @@ export interface CreateQueueOptions extends OperationOptions { forwardTo?: string; lockDuration?: string; maxDeliveryCount?: number; + maxMessageSizeInKilobytes?: number; maxSizeInMegabytes?: number; requiresDuplicateDetection?: boolean; requiresSession?: boolean; @@ -113,6 +114,7 @@ export interface CreateTopicOptions extends OperationOptions { enableBatchedOperations?: boolean; enableExpress?: boolean; enablePartitioning?: boolean; + maxMessageSizeInKilobytes?: number; maxSizeInMegabytes?: number; requiresDuplicateDetection?: boolean; status?: EntityStatus; @@ -199,6 +201,7 @@ export interface QueueProperties { forwardTo?: string; lockDuration: string; maxDeliveryCount: number; + maxMessageSizeInKilobytes: number; maxSizeInMegabytes: number; readonly name: string; readonly requiresDuplicateDetection: boolean; @@ -551,6 +554,7 @@ export interface TopicProperties { enableBatchedOperations: boolean; readonly enableExpress: boolean; readonly enablePartitioning: boolean; + maxMessageSizeInKilobytes: number; maxSizeInMegabytes: number; readonly name: string; readonly requiresDuplicateDetection: boolean; diff --git a/sdk/servicebus/service-bus/sample.env b/sdk/servicebus/service-bus/sample.env index c527b1c4fcbe..900f08118984 100644 --- a/sdk/servicebus/service-bus/sample.env +++ b/sdk/servicebus/service-bus/sample.env @@ -1,4 +1,4 @@ -# Used in most samples. Retrieve these values from a storage account in the Azure Portal. +# Used in most samples. Retrieve these values from a service-bus namespace in the Azure Portal. SERVICEBUS_ENDPOINT=".servicebus.windows.net" SERVICEBUS_CONNECTION_STRING="" @@ -23,4 +23,4 @@ AZURE_CLIENT_ID= AZURE_CLIENT_SECRET= # To run the useProxy sample, set up an HTTP proxy and enter your information: -# HTTP_PROXY=http://localhost:3128 \ No newline at end of file +# HTTP_PROXY=http://localhost:3128 diff --git a/sdk/servicebus/service-bus/src/serializers/queueResourceSerializer.ts b/sdk/servicebus/service-bus/src/serializers/queueResourceSerializer.ts index 1f5397293b03..e2e7ecf01354 100644 --- a/sdk/servicebus/service-bus/src/serializers/queueResourceSerializer.ts +++ b/sdk/servicebus/service-bus/src/serializers/queueResourceSerializer.ts @@ -55,7 +55,8 @@ export function buildQueueOptions(queue: CreateQueueOptions): InternalQueueOptio EnablePartitioning: getStringOrUndefined(queue.enablePartitioning), ForwardDeadLetteredMessagesTo: getStringOrUndefined(queue.forwardDeadLetteredMessagesTo), EntityAvailabilityStatus: getStringOrUndefined(queue.availabilityStatus), - EnableExpress: getStringOrUndefined(queue.enableExpress) + EnableExpress: getStringOrUndefined(queue.enableExpress), + MaxMessageSizeInKilobytes: getStringOrUndefined(queue.maxMessageSizeInKilobytes) }; } @@ -111,7 +112,12 @@ export function buildQueue(rawQueue: Record): QueueProperties { enableExpress: getBoolean(rawQueue[Constants.ENABLE_EXPRESS], "enableExpress"), - availabilityStatus: rawQueue[Constants.ENTITY_AVAILABILITY_STATUS] + availabilityStatus: rawQueue[Constants.ENTITY_AVAILABILITY_STATUS], + + maxMessageSizeInKilobytes: getInteger( + rawQueue[Constants.MAX_MESSAGE_SIZE_IN_KILOBYTES], + "maxMessageSizeInKilobytes" + ) }; } @@ -156,6 +162,13 @@ export interface CreateQueueOptions extends OperationOptions { */ maxSizeInMegabytes?: number; + /** + * The maximum message size in kilobytes for messages sent to this queue. + * + * (Configurable only for Premium Tier Service Bus namespace.) + */ + maxMessageSizeInKilobytes?: number; + /** * If enabled, the topic will detect duplicate messages within the time * span specified by the DuplicateDetectionHistoryTimeWindow property. @@ -299,6 +312,11 @@ export interface QueueProperties { */ maxSizeInMegabytes: number; + /** + * The maximum message size in kilobytes for messages sent to this queue. + */ + maxMessageSizeInKilobytes: number; + /** * If enabled, the topic will detect duplicate messages within the time * span specified by the DuplicateDetectionHistoryTimeWindow property. @@ -436,6 +454,11 @@ export interface InternalQueueOptions { */ MaxSizeInMegabytes?: string; + /** + * The maximum message size in kilobytes for messages sent to this queue/topic. + */ + MaxMessageSizeInKilobytes?: string; + /** * If enabled, the topic will detect duplicate messages within the time * span specified by the DuplicateDetectionHistoryTimeWindow property. diff --git a/sdk/servicebus/service-bus/src/serializers/topicResourceSerializer.ts b/sdk/servicebus/service-bus/src/serializers/topicResourceSerializer.ts index 339f844ee07d..c7a70da3586e 100644 --- a/sdk/servicebus/service-bus/src/serializers/topicResourceSerializer.ts +++ b/sdk/servicebus/service-bus/src/serializers/topicResourceSerializer.ts @@ -50,7 +50,8 @@ export function buildTopicOptions(topic: CreateTopicOptions): InternalTopicOptio AutoDeleteOnIdle: getStringOrUndefined(topic.autoDeleteOnIdle), EnablePartitioning: getStringOrUndefined(topic.enablePartitioning), EntityAvailabilityStatus: getStringOrUndefined(topic.availabilityStatus), - EnableExpress: getStringOrUndefined(topic.enableExpress) + EnableExpress: getStringOrUndefined(topic.enableExpress), + MaxMessageSizeInKilobytes: getStringOrUndefined(topic.maxMessageSizeInKilobytes) }; } @@ -93,7 +94,12 @@ export function buildTopic(rawTopic: Record): TopicProperties { enableExpress: getBoolean(rawTopic[Constants.ENABLE_EXPRESS], "enableExpress"), - availabilityStatus: rawTopic[Constants.ENTITY_AVAILABILITY_STATUS] + availabilityStatus: rawTopic[Constants.ENTITY_AVAILABILITY_STATUS], + + maxMessageSizeInKilobytes: getInteger( + rawTopic[Constants.MAX_MESSAGE_SIZE_IN_KILOBYTES], + "maxMessageSizeInKilobytes" + ) }; } @@ -142,6 +148,13 @@ export interface CreateTopicOptions extends OperationOptions { */ maxSizeInMegabytes?: number; + /** + * The maximum message size in kilobytes for messages sent to this topic. + * + * (Configurable only for Premium Tier Service Bus namespace.) + */ + maxMessageSizeInKilobytes?: number; + /** * If enabled, the topic will detect duplicate messages within the time span * specified by the DuplicateDetectionHistoryTimeWindow property. @@ -243,6 +256,11 @@ export interface TopicProperties { */ maxSizeInMegabytes: number; + /** + * The maximum message size in kilobytes for messages sent to this queue/topic. + */ + maxMessageSizeInKilobytes: number; + /** * If enabled, the topic will detect duplicate messages within the time span * specified by the DuplicateDetectionHistoryTimeWindow property. @@ -339,6 +357,12 @@ export interface InternalTopicOptions { */ MaxSizeInMegabytes?: string; + /** + * The maximum message size in kilobytes for messages sent to this queue/topic + * + */ + MaxMessageSizeInKilobytes?: string; + /** * If enabled, the topic will detect duplicate messages within the time span * specified by the DuplicateDetectionHistoryTimeWindow property. diff --git a/sdk/servicebus/service-bus/src/util/constants.ts b/sdk/servicebus/service-bus/src/util/constants.ts index 14f0d66d1c5a..562c3735ba77 100644 --- a/sdk/servicebus/service-bus/src/util/constants.ts +++ b/sdk/servicebus/service-bus/src/util/constants.ts @@ -6,7 +6,7 @@ */ export const packageJsonInfo = { name: "@azure/service-bus", - version: "7.3.1" + version: "7.3.1-beta.1" }; /** @@ -172,7 +172,12 @@ export const USER_METADATA = "UserMetadata"; * @internal */ export const MAX_SIZE_IN_MEGABYTES = "MaxSizeInMegabytes"; - +/** + * The maximum size in kilobytes. + * + * @internal + */ +export const MAX_MESSAGE_SIZE_IN_KILOBYTES = "MaxMessageSizeInKilobytes"; /** * The default message time to live. * This is specified in ISO-8601 duration format such as "PT1M" for 1 minute, "PT5S" for 5 seconds. @@ -273,7 +278,7 @@ export const API_VERSION_QUERY_KEY = "api-version"; * * @internal */ -export const CURRENT_API_VERSION = "2017-04"; +export const CURRENT_API_VERSION = "2021-05"; /** * Constant representing the Odata Error 'message' property diff --git a/sdk/servicebus/service-bus/test.env b/sdk/servicebus/service-bus/test.env new file mode 100644 index 000000000000..ef31eec5e5bd --- /dev/null +++ b/sdk/servicebus/service-bus/test.env @@ -0,0 +1,10 @@ +# Used in most tests. Retrieve this value from a service-bus namespace in the Azure Portal. +SERVICEBUS_CONNECTION_STRING="" + +# Used in a couple of tests +SERVICEBUS_CONNECTION_STRING_PREMIUM="" + +# Used to authenticate using Azure AD as a service principal for role-based authentication. +AZURE_TENANT_ID= +AZURE_CLIENT_ID= +AZURE_CLIENT_SECRET= diff --git a/sdk/servicebus/service-bus/test/public/atomManagement.spec.ts b/sdk/servicebus/service-bus/test/public/atomManagement.spec.ts index aceb779e5495..5e1333f4c3ab 100644 --- a/sdk/servicebus/service-bus/test/public/atomManagement.spec.ts +++ b/sdk/servicebus/service-bus/test/public/atomManagement.spec.ts @@ -15,7 +15,7 @@ import { CreateSubscriptionOptions, SubscriptionProperties } from "../../src"; import { CreateTopicOptions } from "../../src"; import { ServiceBusAdministrationClient, WithResponse } from "../../src"; import { EntityStatus, EntityAvailabilityStatus } from "../../src"; -import { EnvVarNames, getEnvVars } from "./utils/envVarUtils"; +import { EnvVarNames, getEnvVars, getEnvVarValue } from "./utils/envVarUtils"; import { recreateQueue, recreateSubscription, recreateTopic } from "./utils/managementUtils"; import { EntityNames, TestClientType } from "./utils/testUtils"; import { TestConstants } from "./fakeTestSecrets"; @@ -61,383 +61,522 @@ const newManagementEntity2 = EntityNames.MANAGEMENT_NEW_ENTITY_2; type AccessRights = ("Manage" | "Send" | "Listen")[]; const randomDate = new Date(); -/** - * These tests are just a sanity check that our updates are actually - * _doing_ something. We've run into some bugs where we've done things like - * enabled forwarding only to find that forwarding isn't happening even though - * we can _read_ the attributes back. - */ -describe("Atom management - forwarding", () => { - let serviceBusClient: ServiceBusClientForTests; - - before(() => { - serviceBusClient = createServiceBusClientForTests(); - }); - - after(() => serviceBusClient.test.after()); +describe("ATOM APIs", () => { + /** + * These tests are just a sanity check that our updates are actually + * _doing_ something. We've run into some bugs where we've done things like + * enabled forwarding only to find that forwarding isn't happening even though + * we can _read_ the attributes back. + */ + describe("Atom management - forwarding", () => { + let serviceBusClient: ServiceBusClientForTests; + + before(() => { + serviceBusClient = createServiceBusClientForTests(); + }); - afterEach(async () => { - serviceBusClient.test.afterEach(); - }); + after(() => serviceBusClient.test.after()); - it("queue: forwarding", async () => { - const willForward = await serviceBusClient.test.createTestEntities( - TestClientType.PartitionedQueue - ); - const willBeForwardedTo = await serviceBusClient.test.createTestEntities( - TestClientType.UnpartitionedQueue - ); + afterEach(async () => { + serviceBusClient.test.afterEach(); + }); - // make it so all messages from `willForward` are forwarded to `willBeForwardedTo` - const queueProperties = await serviceBusAtomManagementClient.getQueue(willForward.queue!); - queueProperties.forwardTo = willBeForwardedTo.queue!; - await serviceBusAtomManagementClient.updateQueue(queueProperties); + it("queue: forwarding", async () => { + const willForward = await serviceBusClient.test.createTestEntities( + TestClientType.PartitionedQueue + ); + const willBeForwardedTo = await serviceBusClient.test.createTestEntities( + TestClientType.UnpartitionedQueue + ); - const receiver = await serviceBusClient.test.createReceiveAndDeleteReceiver(willBeForwardedTo); - const sender = await serviceBusClient.test.createSender(willForward); + // make it so all messages from `willForward` are forwarded to `willBeForwardedTo` + const queueProperties = await serviceBusAtomManagementClient.getQueue(willForward.queue!); + queueProperties.forwardTo = willBeForwardedTo.queue!; + await serviceBusAtomManagementClient.updateQueue(queueProperties); - await sender.sendMessages({ - body: "forwarded message with queues!" - }); + const receiver = await serviceBusClient.test.createReceiveAndDeleteReceiver( + willBeForwardedTo + ); + const sender = await serviceBusClient.test.createSender(willForward); - const messages = await receiver.receiveMessages(1); - assert.deepEqual( - [{ body: "forwarded message with queues!" }], - messages.map((m) => ({ body: m.body })) - ); - }); + await sender.sendMessages({ + body: "forwarded message with queues!" + }); - it("subscription: forwarding", async () => { - const willForward = await serviceBusClient.test.createTestEntities( - TestClientType.PartitionedSubscription - ); - const willBeForwardedTo = await serviceBusClient.test.createTestEntities( - TestClientType.UnpartitionedQueue - ); - - // make it so all messages from `willForward` are forwarded to `willBeForwardedTo` - const subscriptionProperties = await serviceBusAtomManagementClient.getSubscription( - willForward.topic!, - willForward.subscription! - ); - subscriptionProperties.forwardTo = willBeForwardedTo.queue!; - await serviceBusAtomManagementClient.updateSubscription(subscriptionProperties); - - const receiver = await serviceBusClient.test.createReceiveAndDeleteReceiver(willBeForwardedTo); - const sender = await serviceBusClient.test.createSender(willForward); - - await sender.sendMessages({ - body: "forwarded message with subscriptions!" + const messages = await receiver.receiveMessages(1); + assert.deepEqual( + [{ body: "forwarded message with queues!" }], + messages.map((m) => ({ body: m.body })) + ); }); - const messages = await receiver.receiveMessages(1); - assert.deepEqual( - [{ body: "forwarded message with subscriptions!" }], - messages.map((m) => ({ body: m.body })) - ); - }); -}); - -describe("Atom management - Namespace", function(): void { - it("Get namespace properties", async () => { - const namespaceProperties = await serviceBusAtomManagementClient.getNamespaceProperties(); - assert.deepEqualExcluding( - namespaceProperties, - { messagingSku: "Standard", messagingUnits: undefined } as any, - ["_response", "createdAt", "modifiedAt", "name"] - ); - }); -}); - -describe("Listing methods - PagedAsyncIterableIterator", function(): void { - const baseName = "random"; - const queueNames: string[] = []; - const topicNames: string[] = []; - const subscriptionNames: string[] = []; - const ruleNames: string[] = []; - const numberOfEntities = 5; - - before(async () => { - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - for (let i = 0; i < numberOfEntities; i++) { - queueNames.push( - (await serviceBusAtomManagementClient.createQueue(baseName + "_queue_" + i)).name + it("subscription: forwarding", async () => { + const willForward = await serviceBusClient.test.createTestEntities( + TestClientType.PartitionedSubscription ); - topicNames.push( - (await serviceBusAtomManagementClient.createTopic(baseName + "_topic_" + i)).name + const willBeForwardedTo = await serviceBusClient.test.createTestEntities( + TestClientType.UnpartitionedQueue ); - subscriptionNames.push( - ( - await serviceBusAtomManagementClient.createSubscription( - managementTopic1, - baseName + "_subscription_" + i - ) - ).subscriptionName + + // make it so all messages from `willForward` are forwarded to `willBeForwardedTo` + const subscriptionProperties = await serviceBusAtomManagementClient.getSubscription( + willForward.topic!, + willForward.subscription! ); - ruleNames.push( - ( - await serviceBusAtomManagementClient.createRule( - managementTopic1, - managementSubscription1, - baseName + "_rule_" + i, - { sqlExpression: "1=1" } - ) - ).name + subscriptionProperties.forwardTo = willBeForwardedTo.queue!; + await serviceBusAtomManagementClient.updateSubscription(subscriptionProperties); + + const receiver = await serviceBusClient.test.createReceiveAndDeleteReceiver( + willBeForwardedTo ); - } + const sender = await serviceBusClient.test.createSender(willForward); + + await sender.sendMessages({ + body: "forwarded message with subscriptions!" + }); + + const messages = await receiver.receiveMessages(1); + assert.deepEqual( + [{ body: "forwarded message with subscriptions!" }], + messages.map((m) => ({ body: m.body })) + ); + }); }); - after(async () => { - for (let i = 0; i < numberOfEntities; i++) { - await serviceBusAtomManagementClient.deleteQueue(baseName + "_queue_" + i); - await serviceBusAtomManagementClient.deleteTopic(baseName + "_topic_" + i); - } - await serviceBusAtomManagementClient.deleteTopic(managementTopic1); + describe("Atom management - Namespace", function(): void { + it("Get namespace properties", async () => { + const namespaceProperties = await serviceBusAtomManagementClient.getNamespaceProperties(); + assert.deepEqualExcluding( + namespaceProperties, + { messagingSku: "Standard", messagingUnits: undefined } as any, + ["_response", "createdAt", "modifiedAt", "name"] + ); + }); }); - function verifyEntities(methodName: string, receivedNames: string[]): void { - let createdNames: string[]; - if (methodName.includes("Queue")) { - createdNames = queueNames; - } else if (methodName.includes("Topic")) { - createdNames = topicNames; - } else if (methodName.includes("Subscription")) { - createdNames = subscriptionNames; - } else { - createdNames = ruleNames; - } - const numberOfReceived = receivedNames.length; - createdNames.forEach((createdName) => { - receivedNames = receivedNames.filter((receivedName) => createdName !== receivedName); + describe("Listing methods - PagedAsyncIterableIterator", function(): void { + const baseName = "random"; + const queueNames: string[] = []; + const topicNames: string[] = []; + const subscriptionNames: string[] = []; + const ruleNames: string[] = []; + const numberOfEntities = 5; + + before(async () => { + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + for (let i = 0; i < numberOfEntities; i++) { + queueNames.push( + (await serviceBusAtomManagementClient.createQueue(baseName + "_queue_" + i)).name + ); + topicNames.push( + (await serviceBusAtomManagementClient.createTopic(baseName + "_topic_" + i)).name + ); + subscriptionNames.push( + ( + await serviceBusAtomManagementClient.createSubscription( + managementTopic1, + baseName + "_subscription_" + i + ) + ).subscriptionName + ); + ruleNames.push( + ( + await serviceBusAtomManagementClient.createRule( + managementTopic1, + managementSubscription1, + baseName + "_rule_" + i, + { sqlExpression: "1=1" } + ) + ).name + ); + } }); - should.equal( - numberOfReceived, - receivedNames.length + createdNames.length, - "Unexpected number of entities received" - ); - } - [ - "listQueues", - "listQueuesRuntimeProperties", - "listTopics", - "listTopicsRuntimeProperties", - "listSubscriptions", - "listSubscriptionsRuntimeProperties", - "listRules" - ].forEach((methodName) => { - describe(`${methodName}`, (): void => { - function getIter() { - let iterator; - if (methodName.includes("Subscription")) { - iterator = (serviceBusAtomManagementClient as any)[methodName](managementTopic1); - } else if (methodName.includes("Rule")) { - iterator = (serviceBusAtomManagementClient as any)[methodName]( - managementTopic1, - managementSubscription1 - ); - } else if (methodName.includes("Queue") || methodName.includes("Topic")) { - iterator = (serviceBusAtomManagementClient as any)[methodName](); - } else { - throw new Error("Invalid methodName"); - } - return iterator; + after(async () => { + for (let i = 0; i < numberOfEntities; i++) { + await serviceBusAtomManagementClient.deleteQueue(baseName + "_queue_" + i); + await serviceBusAtomManagementClient.deleteTopic(baseName + "_topic_" + i); } + await serviceBusAtomManagementClient.deleteTopic(managementTopic1); + }); - it("Verify PagedAsyncIterableIterator", async () => { - const receivedEntities = []; - const iter = getIter(); - for await (const entity of iter) { - receivedEntities.push( - methodName.includes("Subscription") ? entity.subscriptionName : entity.name - ); - } - verifyEntities(methodName, receivedEntities); + function verifyEntities(methodName: string, receivedNames: string[]): void { + let createdNames: string[]; + if (methodName.includes("Queue")) { + createdNames = queueNames; + } else if (methodName.includes("Topic")) { + createdNames = topicNames; + } else if (methodName.includes("Subscription")) { + createdNames = subscriptionNames; + } else { + createdNames = ruleNames; + } + const numberOfReceived = receivedNames.length; + createdNames.forEach((createdName) => { + receivedNames = receivedNames.filter((receivedName) => createdName !== receivedName); }); + should.equal( + numberOfReceived, + receivedNames.length + createdNames.length, + "Unexpected number of entities received" + ); + } - it("Verify PagedAsyncIterableIterator(byPage())", async () => { - const receivedEntities = []; - const iter = getIter().byPage({ - maxPageSize: 2 - }); - for await (const response of iter) { - for (const entity of response) { - receivedEntities.push( - methodName.includes("Subscription") ? entity.subscriptionName : entity.name + [ + "listQueues", + "listQueuesRuntimeProperties", + "listTopics", + "listTopicsRuntimeProperties", + "listSubscriptions", + "listSubscriptionsRuntimeProperties", + "listRules" + ].forEach((methodName) => { + describe(`${methodName}`, (): void => { + function getIter() { + let iterator; + if (methodName.includes("Subscription")) { + iterator = (serviceBusAtomManagementClient as any)[methodName](managementTopic1); + } else if (methodName.includes("Rule")) { + iterator = (serviceBusAtomManagementClient as any)[methodName]( + managementTopic1, + managementSubscription1 ); + } else if (methodName.includes("Queue") || methodName.includes("Topic")) { + iterator = (serviceBusAtomManagementClient as any)[methodName](); + } else { + throw new Error("Invalid methodName"); } + return iterator; } - verifyEntities(methodName, receivedEntities); - }); - it("Verify PagedAsyncIterableIterator(byPage() - continuationToken)", async () => { - const receivedEntities = []; - let iterator = getIter().byPage({ maxPageSize: 2 }); - let response = await iterator.next(); - // Prints 2 entity names - if (!response.done) { - for (const entity of response.value) { + it("Verify PagedAsyncIterableIterator", async () => { + const receivedEntities = []; + const iter = getIter(); + for await (const entity of iter) { receivedEntities.push( methodName.includes("Subscription") ? entity.subscriptionName : entity.name ); } - } - - // Gets next marker - let marker = response.value.continuationToken; - // Passing next marker as continuationToken - iterator = getIter().byPage({ - continuationToken: marker, - maxPageSize: 5 + verifyEntities(methodName, receivedEntities); }); - response = await iterator.next(); - // Gets up to 5 entity names - if (!response.done) { - for (const entity of response.value) { - receivedEntities.push( - methodName.includes("Subscription") ? entity.subscriptionName : entity.name - ); + + it("Verify PagedAsyncIterableIterator(byPage())", async () => { + const receivedEntities = []; + const iter = getIter().byPage({ + maxPageSize: 2 + }); + for await (const response of iter) { + for (const entity of response) { + receivedEntities.push( + methodName.includes("Subscription") ? entity.subscriptionName : entity.name + ); + } } - } - marker = response.value.continuationToken; - - // In case the namespace has too many entities and the newly created entities were not recovered - if (marker) { - for await (const pageResponse of getIter().byPage({ - continuationToken: marker - })) { - for (const entity of pageResponse) { + verifyEntities(methodName, receivedEntities); + }); + + it("Verify PagedAsyncIterableIterator(byPage() - continuationToken)", async () => { + const receivedEntities = []; + let iterator = getIter().byPage({ maxPageSize: 2 }); + let response = await iterator.next(); + // Prints 2 entity names + if (!response.done) { + for (const entity of response.value) { receivedEntities.push( methodName.includes("Subscription") ? entity.subscriptionName : entity.name ); } } - } - verifyEntities(methodName, receivedEntities); - }); - [2, "-1", [], null].forEach((token) => { - it(`Validate continuationToken ${token} - PagedAsyncIterableIterator(byPage())`, async () => { - const settings: PageSettings = { continuationToken: token as string }; - let errorWasThrown = false; - try { - getIter().byPage(settings); - } catch (error) { - errorWasThrown = true; - should.equal( - error.message, - `Invalid continuationToken ${token} provided`, - "Unexpected error message" - ); + // Gets next marker + let marker = response.value.continuationToken; + // Passing next marker as continuationToken + iterator = getIter().byPage({ + continuationToken: marker, + maxPageSize: 5 + }); + response = await iterator.next(); + // Gets up to 5 entity names + if (!response.done) { + for (const entity of response.value) { + receivedEntities.push( + methodName.includes("Subscription") ? entity.subscriptionName : entity.name + ); + } } - should.equal(errorWasThrown, true, "Error was not thrown"); + marker = response.value.continuationToken; + + // In case the namespace has too many entities and the newly created entities were not recovered + if (marker) { + for await (const pageResponse of getIter().byPage({ + continuationToken: marker + })) { + for (const entity of pageResponse) { + receivedEntities.push( + methodName.includes("Subscription") ? entity.subscriptionName : entity.name + ); + } + } + } + verifyEntities(methodName, receivedEntities); + }); + + [2, "-1", [], null].forEach((token) => { + it(`Validate continuationToken ${token} - PagedAsyncIterableIterator(byPage())`, async () => { + const settings: PageSettings = { continuationToken: token as string }; + let errorWasThrown = false; + try { + getIter().byPage(settings); + } catch (error) { + errorWasThrown = true; + should.equal( + error.message, + `Invalid continuationToken ${token} provided`, + "Unexpected error message" + ); + } + should.equal(errorWasThrown, true, "Error was not thrown"); + }); }); }); }); }); -}); -describe("Atom management - Authentication", function(): void { - if (isNode) { - it("Token credential - DefaultAzureCredential from `@azure/identity`", async () => { + describe("Atom management - Authentication", function(): void { + if (isNode) { + it("Token credential - DefaultAzureCredential from `@azure/identity`", async () => { + const connectionStringProperties = parseServiceBusConnectionString( + env[EnvVarNames.SERVICEBUS_CONNECTION_STRING] + ); + const host = connectionStringProperties.fullyQualifiedNamespace; + const endpoint = connectionStringProperties.endpoint; + const serviceBusAdministrationClient = new ServiceBusAdministrationClient( + host, + new DefaultAzureCredential() + ); + + should.equal( + (await serviceBusAdministrationClient.createQueue(managementQueue1)).name, + managementQueue1, + "Unexpected queue name in the createQueue response" + ); + const createQueue2Response = await serviceBusAdministrationClient.createQueue( + managementQueue2, + { + forwardTo: managementQueue1 + } + ); + should.equal( + createQueue2Response.name, + managementQueue2, + "Unexpected queue name in the createQueue response" + ); + should.equal( + createQueue2Response.forwardTo, + endpoint + managementQueue1, + "Unexpected name in the `forwardTo` field of createQueue response" + ); + const getQueueResponse = await serviceBusAdministrationClient.getQueue(managementQueue1); + should.equal( + getQueueResponse.name, + managementQueue1, + "Unexpected queue name in the getQueue response" + ); + should.equal( + (await serviceBusAdministrationClient.updateQueue(getQueueResponse)).name, + managementQueue1, + "Unexpected queue name in the updateQueue response" + ); + should.equal( + (await serviceBusAdministrationClient.getQueueRuntimeProperties(managementQueue1)).name, + managementQueue1, + "Unexpected queue name in the getQueueRuntimeProperties response" + ); + should.equal( + (await serviceBusAdministrationClient.getNamespaceProperties()).name, + (host.match("(.*).servicebus.windows.net") || [])[1], + "Unexpected namespace name in the getNamespaceProperties response" + ); + await serviceBusAdministrationClient.deleteQueue(managementQueue1); + await serviceBusAdministrationClient.deleteQueue(managementQueue2); + }); + } + + it("AzureNamedKeyCredential from `@azure/core-auth`", async () => { const connectionStringProperties = parseServiceBusConnectionString( env[EnvVarNames.SERVICEBUS_CONNECTION_STRING] ); const host = connectionStringProperties.fullyQualifiedNamespace; - const endpoint = connectionStringProperties.endpoint; const serviceBusAdministrationClient = new ServiceBusAdministrationClient( host, - new DefaultAzureCredential() + new AzureNamedKeyCredential( + connectionStringProperties.sharedAccessKeyName!, + connectionStringProperties.sharedAccessKey! + ) ); - should.equal( - (await serviceBusAdministrationClient.createQueue(managementQueue1)).name, - managementQueue1, - "Unexpected queue name in the createQueue response" - ); - const createQueue2Response = await serviceBusAdministrationClient.createQueue( - managementQueue2, - { - forwardTo: managementQueue1 - } - ); - should.equal( - createQueue2Response.name, - managementQueue2, - "Unexpected queue name in the createQueue response" - ); - should.equal( - createQueue2Response.forwardTo, - endpoint + managementQueue1, - "Unexpected name in the `forwardTo` field of createQueue response" - ); - const getQueueResponse = await serviceBusAdministrationClient.getQueue(managementQueue1); - should.equal( - getQueueResponse.name, - managementQueue1, - "Unexpected queue name in the getQueue response" - ); - should.equal( - (await serviceBusAdministrationClient.updateQueue(getQueueResponse)).name, - managementQueue1, - "Unexpected queue name in the updateQueue response" - ); - should.equal( - (await serviceBusAdministrationClient.getQueueRuntimeProperties(managementQueue1)).name, - managementQueue1, - "Unexpected queue name in the getQueueRuntimeProperties response" - ); should.equal( (await serviceBusAdministrationClient.getNamespaceProperties()).name, (host.match("(.*).servicebus.windows.net") || [])[1], "Unexpected namespace name in the getNamespaceProperties response" ); - await serviceBusAdministrationClient.deleteQueue(managementQueue1); - await serviceBusAdministrationClient.deleteQueue(managementQueue2); }); - } - - it("AzureNamedKeyCredential from `@azure/core-auth`", async () => { - const connectionStringProperties = parseServiceBusConnectionString( - env[EnvVarNames.SERVICEBUS_CONNECTION_STRING] - ); - const host = connectionStringProperties.fullyQualifiedNamespace; - const serviceBusAdministrationClient = new ServiceBusAdministrationClient( - host, - new AzureNamedKeyCredential( - connectionStringProperties.sharedAccessKeyName!, - connectionStringProperties.sharedAccessKey! - ) - ); - - should.equal( - (await serviceBusAdministrationClient.getNamespaceProperties()).name, - (host.match("(.*).servicebus.windows.net") || [])[1], - "Unexpected namespace name in the getNamespaceProperties response" - ); }); -}); -[EntityType.QUEUE, EntityType.TOPIC, EntityType.SUBSCRIPTION, EntityType.RULE].forEach( - (entityType) => { - describe(`Atom management - List on "${entityType}" entities`, function(): void { + [EntityType.QUEUE, EntityType.TOPIC, EntityType.SUBSCRIPTION, EntityType.RULE].forEach( + (entityType) => { + describe(`Atom management - List on "${entityType}" entities`, function(): void { + beforeEach(async () => { + switch (entityType) { + case EntityType.QUEUE: + await recreateQueue(managementQueue1); + await recreateQueue(managementQueue2); + break; + + case EntityType.TOPIC: + await recreateTopic(managementTopic1); + await recreateTopic(managementTopic2); + break; + + case EntityType.SUBSCRIPTION: + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + await recreateSubscription(managementTopic1, managementSubscription2); + break; + + case EntityType.RULE: + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + await createEntity( + EntityType.RULE, + managementRule1, + managementTopic1, + managementSubscription1 + ); + await createEntity( + EntityType.RULE, + managementRule2, + managementTopic1, + managementSubscription1 + ); + break; + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); + + afterEach(async () => { + switch (entityType) { + case EntityType.QUEUE: + await deleteEntity(EntityType.QUEUE, managementQueue1); + await deleteEntity(EntityType.QUEUE, managementQueue2); + break; + + case EntityType.TOPIC: + await deleteEntity(EntityType.TOPIC, managementTopic1); + await deleteEntity(EntityType.TOPIC, managementTopic2); + break; + case EntityType.SUBSCRIPTION: + case EntityType.RULE: + await deleteEntity(EntityType.TOPIC, managementTopic1); + break; + + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); + + it(`List on existing entities for type ${entityType} with top 1 returns the first entity`, async () => { + const topOneEntity = await listEntities( + entityType, + managementTopic1, + managementSubscription1, + undefined, + 1 + ); + + should.equal( + Array.isArray(topOneEntity), + true, + "Result must be any array for list requests" + ); + should.equal(topOneEntity.length, 1, "Result must be an empty array"); + }); + + it(`List on existing entities for type ${entityType} with skip 1 returns all entities skipping 1`, async () => { + const allEntitiesResult = await listEntities( + entityType, + managementTopic1, + managementSubscription1 + ); + + const skipEntitiesResult = await listEntities( + entityType, + managementTopic1, + managementSubscription1, + 1, + undefined + ); + + should.equal( + Array.isArray(skipEntitiesResult), + true, + "Result must be any array for list requests" + ); + + should.equal( + skipEntitiesResult.length, + allEntitiesResult.length - 1, + "Result array size should be exactly 1 less than all entities" + ); + }); + + it(`Lists available ${entityType} entities successfully`, async () => { + const response = await listEntities( + entityType, + managementTopic1, + managementSubscription1 + ); + + should.equal(Array.isArray(response), true, "Result must be any array for list requests"); + }); + }); + } + ); + + [ + { + entityType: EntityType.QUEUE, + alwaysBeExistingEntity: managementQueue1 + }, + { + entityType: EntityType.TOPIC, + alwaysBeExistingEntity: managementTopic1 + }, + { + entityType: EntityType.SUBSCRIPTION, + alwaysBeExistingEntity: managementSubscription1 + }, + { + entityType: EntityType.RULE, + alwaysBeExistingEntity: managementRule1 + } + ].forEach((testCase) => { + describe(`Atom management - Get on "${testCase.entityType}" entities`, function(): void { beforeEach(async () => { - switch (entityType) { + switch (testCase.entityType) { case EntityType.QUEUE: await recreateQueue(managementQueue1); - await recreateQueue(managementQueue2); break; case EntityType.TOPIC: await recreateTopic(managementTopic1); - await recreateTopic(managementTopic2); break; case EntityType.SUBSCRIPTION: await recreateTopic(managementTopic1); await recreateSubscription(managementTopic1, managementSubscription1); - await recreateSubscription(managementTopic1, managementSubscription2); break; case EntityType.RULE: @@ -449,12 +588,6 @@ describe("Atom management - Authentication", function(): void { managementTopic1, managementSubscription1 ); - await createEntity( - EntityType.RULE, - managementRule2, - managementTopic1, - managementSubscription1 - ); break; default: throw new Error("TestError: Unrecognized EntityType"); @@ -462,16 +595,12 @@ describe("Atom management - Authentication", function(): void { }); afterEach(async () => { - switch (entityType) { + switch (testCase.entityType) { case EntityType.QUEUE: await deleteEntity(EntityType.QUEUE, managementQueue1); - await deleteEntity(EntityType.QUEUE, managementQueue2); break; case EntityType.TOPIC: - await deleteEntity(EntityType.TOPIC, managementTopic1); - await deleteEntity(EntityType.TOPIC, managementTopic2); - break; case EntityType.SUBSCRIPTION: case EntityType.RULE: await deleteEntity(EntityType.TOPIC, managementTopic1); @@ -482,243 +611,25 @@ describe("Atom management - Authentication", function(): void { } }); - it(`List on existing entities for type ${entityType} with top 1 returns the first entity`, async () => { - const topOneEntity = await listEntities( - entityType, - managementTopic1, - managementSubscription1, - undefined, - 1 - ); - - should.equal( - Array.isArray(topOneEntity), - true, - "Result must be any array for list requests" - ); - should.equal(topOneEntity.length, 1, "Result must be an empty array"); - }); - - it(`List on existing entities for type ${entityType} with skip 1 returns all entities skipping 1`, async () => { - const allEntitiesResult = await listEntities( - entityType, + it(`Gets an existent ${testCase.entityType} entity successfully`, async () => { + const response = await getEntity( + testCase.entityType, + testCase.alwaysBeExistingEntity, managementTopic1, managementSubscription1 ); - - const skipEntitiesResult = await listEntities( - entityType, - managementTopic1, - managementSubscription1, - 1, - undefined - ); - - should.equal( - Array.isArray(skipEntitiesResult), - true, - "Result must be any array for list requests" - ); - should.equal( - skipEntitiesResult.length, - allEntitiesResult.length - 1, - "Result array size should be exactly 1 less than all entities" + response[testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], + testCase.alwaysBeExistingEntity, + "Entity name mismatch" ); }); - - it(`Lists available ${entityType} entities successfully`, async () => { - const response = await listEntities(entityType, managementTopic1, managementSubscription1); - - should.equal(Array.isArray(response), true, "Result must be any array for list requests"); - }); - }); - } -); - -[ - { - entityType: EntityType.QUEUE, - alwaysBeExistingEntity: managementQueue1 - }, - { - entityType: EntityType.TOPIC, - alwaysBeExistingEntity: managementTopic1 - }, - { - entityType: EntityType.SUBSCRIPTION, - alwaysBeExistingEntity: managementSubscription1 - }, - { - entityType: EntityType.RULE, - alwaysBeExistingEntity: managementRule1 - } -].forEach((testCase) => { - describe(`Atom management - Get on "${testCase.entityType}" entities`, function(): void { - beforeEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await recreateQueue(managementQueue1); - break; - - case EntityType.TOPIC: - await recreateTopic(managementTopic1); - break; - - case EntityType.SUBSCRIPTION: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - break; - - case EntityType.RULE: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - await createEntity( - EntityType.RULE, - managementRule1, - managementTopic1, - managementSubscription1 - ); - break; - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); - - afterEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await deleteEntity(EntityType.QUEUE, managementQueue1); - break; - - case EntityType.TOPIC: - case EntityType.SUBSCRIPTION: - case EntityType.RULE: - await deleteEntity(EntityType.TOPIC, managementTopic1); - break; - - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); - - it(`Gets an existent ${testCase.entityType} entity successfully`, async () => { - const response = await getEntity( - testCase.entityType, - testCase.alwaysBeExistingEntity, - managementTopic1, - managementSubscription1 - ); - should.equal( - response[testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], - testCase.alwaysBeExistingEntity, - "Entity name mismatch" - ); }); }); -}); -[ - { - entityType: EntityType.QUEUE, - alwaysBeExistingEntity: managementQueue1, - output: { - sizeInBytes: 0, - totalMessageCount: 0, - activeMessageCount: 0, - deadLetterMessageCount: 0, - scheduledMessageCount: 0, - transferMessageCount: 0, - transferDeadLetterMessageCount: 0, - name: managementQueue1 - } - }, - { - entityType: EntityType.TOPIC, - alwaysBeExistingEntity: managementTopic1, - output: { - sizeInBytes: 0, - subscriptionCount: 0, - scheduledMessageCount: 0, - name: managementTopic1 - } - }, - { - entityType: EntityType.SUBSCRIPTION, - alwaysBeExistingEntity: managementSubscription1, - output: { - totalMessageCount: 0, - activeMessageCount: 0, - deadLetterMessageCount: 0, - transferMessageCount: 0, - transferDeadLetterMessageCount: 0, - topicName: managementTopic1, - subscriptionName: managementSubscription1 - } - } -].forEach((testCase) => { - describe(`Atom management - Get runtime info on "${testCase.entityType}" entity`, function(): void { - beforeEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await recreateQueue(managementQueue1); - break; - - case EntityType.TOPIC: - await recreateTopic(managementTopic1); - break; - - case EntityType.SUBSCRIPTION: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - break; - - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); - - afterEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await deleteEntity(EntityType.QUEUE, managementQueue1); - break; - - case EntityType.TOPIC: - case EntityType.SUBSCRIPTION: - await deleteEntity(EntityType.TOPIC, managementTopic1); - break; - - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); - - it(`Gets runtime info for an existing ${testCase.entityType} entity(single) successfully`, async () => { - const response = await getEntityRuntimeProperties( - testCase.entityType, - testCase.alwaysBeExistingEntity, - managementTopic1 - ); - should.equal( - response[testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], - testCase.alwaysBeExistingEntity, - "Entity name mismatch" - ); - assert.deepEqualExcluding(response, testCase.output, [ - "_response", - "createdAt", - "modifiedAt", - "accessedAt" - ]); - }); - }); -}); - -[ - { - entityType: EntityType.QUEUE, - 1: { + [ + { + entityType: EntityType.QUEUE, alwaysBeExistingEntity: managementQueue1, output: { sizeInBytes: 0, @@ -731,23 +642,8 @@ describe("Atom management - Authentication", function(): void { name: managementQueue1 } }, - 2: { - alwaysBeExistingEntity: managementQueue2, - output: { - sizeInBytes: 0, - totalMessageCount: 0, - activeMessageCount: 0, - deadLetterMessageCount: 0, - scheduledMessageCount: 0, - transferMessageCount: 0, - transferDeadLetterMessageCount: 0, - name: managementQueue2 - } - } - }, - { - entityType: EntityType.TOPIC, - 1: { + { + entityType: EntityType.TOPIC, alwaysBeExistingEntity: managementTopic1, output: { sizeInBytes: 0, @@ -756,19 +652,8 @@ describe("Atom management - Authentication", function(): void { name: managementTopic1 } }, - 2: { - alwaysBeExistingEntity: managementTopic2, - output: { - sizeInBytes: 0, - subscriptionCount: 0, - scheduledMessageCount: 0, - name: managementTopic2 - } - } - }, - { - entityType: EntityType.SUBSCRIPTION, - 1: { + { + entityType: EntityType.SUBSCRIPTION, alwaysBeExistingEntity: managementSubscription1, output: { totalMessageCount: 0, @@ -779,289 +664,182 @@ describe("Atom management - Authentication", function(): void { topicName: managementTopic1, subscriptionName: managementSubscription1 } - }, - 2: { - alwaysBeExistingEntity: managementSubscription2, - output: { - totalMessageCount: 0, - activeMessageCount: 0, - deadLetterMessageCount: 0, - transferMessageCount: 0, - transferDeadLetterMessageCount: 0, - topicName: managementTopic1, - subscriptionName: managementSubscription2 - } } - } -].forEach((testCase) => { - describe(`Atom management - Get runtime info on "${testCase.entityType}" entities`, function(): void { - beforeEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await recreateQueue(managementQueue1); - await recreateQueue(managementQueue2); - break; - - case EntityType.TOPIC: - await recreateTopic(managementTopic1); - await recreateTopic(managementTopic2); - break; - - case EntityType.SUBSCRIPTION: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - await recreateSubscription(managementTopic1, managementSubscription2); - break; - - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); - - afterEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await deleteEntity(EntityType.QUEUE, managementQueue1); - await deleteEntity(EntityType.QUEUE, managementQueue2); - break; - - case EntityType.TOPIC: - await deleteEntity(EntityType.TOPIC, managementTopic1); - await deleteEntity(EntityType.TOPIC, managementTopic2); - break; + ].forEach((testCase) => { + describe(`Atom management - Get runtime info on "${testCase.entityType}" entity`, function(): void { + beforeEach(async () => { + switch (testCase.entityType) { + case EntityType.QUEUE: + await recreateQueue(managementQueue1); + break; - case EntityType.SUBSCRIPTION: - await deleteEntity(EntityType.TOPIC, managementTopic1); - break; + case EntityType.TOPIC: + await recreateTopic(managementTopic1); + break; - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); + case EntityType.SUBSCRIPTION: + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + break; - it(`Gets runtime info for existing ${testCase.entityType} entities(multiple) successfully`, async () => { - const response = await getEntitiesRuntimeProperties(testCase.entityType, managementTopic1); - const name = testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"; - const paramsToExclude = ["createdAt", "accessedAt", "modifiedAt"]; - for (const info of response) { - if (info[name] === testCase[1].alwaysBeExistingEntity) { - assert.deepEqualExcluding(info, testCase[1].output, paramsToExclude); - } else if (info[name] === testCase[2].alwaysBeExistingEntity) { - assert.deepEqualExcluding(info, testCase[2].output, paramsToExclude); + default: + throw new Error("TestError: Unrecognized EntityType"); } - } - }); - }); -}); - -[ - { - entityType: EntityType.QUEUE, - alwaysBeExistingEntity: managementQueue1 - }, - { - entityType: EntityType.TOPIC, - alwaysBeExistingEntity: managementTopic1 - }, - { - entityType: EntityType.SUBSCRIPTION, - alwaysBeExistingEntity: managementSubscription1 - }, - { - entityType: EntityType.RULE, - alwaysBeExistingEntity: managementRule1 - } -].forEach((testCase) => { - describe(`Atom management - "${testCase.entityType}" exists`, function(): void { - beforeEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await recreateQueue(managementQueue1); - break; - - case EntityType.TOPIC: - await recreateTopic(managementTopic1); - break; - - case EntityType.SUBSCRIPTION: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - break; - - case EntityType.RULE: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - await serviceBusAtomManagementClient.createRule( - managementTopic1, - managementSubscription1, - managementRule1, - { sqlExpression: "1=2" } - ); - break; - - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); + }); - afterEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await deleteEntity(EntityType.QUEUE, managementQueue1); - break; + afterEach(async () => { + switch (testCase.entityType) { + case EntityType.QUEUE: + await deleteEntity(EntityType.QUEUE, managementQueue1); + break; - case EntityType.TOPIC: - case EntityType.SUBSCRIPTION: - case EntityType.RULE: - await deleteEntity(EntityType.TOPIC, managementTopic1); - break; + case EntityType.TOPIC: + case EntityType.SUBSCRIPTION: + await deleteEntity(EntityType.TOPIC, managementTopic1); + break; - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); - it(`Returns true for an existing ${testCase.entityType} entity`, async () => { - should.equal( - await entityExists( + it(`Gets runtime info for an existing ${testCase.entityType} entity(single) successfully`, async () => { + const response = await getEntityRuntimeProperties( testCase.entityType, testCase.alwaysBeExistingEntity, - managementTopic1, - managementSubscription1 - ), - true, - "Returned `false` for an existing entity" - ); - }); - - it(`Returns false for a non-existing ${testCase.entityType} entity`, async () => { - should.equal( - await entityExists( - testCase.entityType, - "non-existing-entity-name", - managementTopic1, - managementSubscription1 - ), - false, - "Returned `true` for a non-existing entity" - ); + managementTopic1 + ); + should.equal( + response[testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], + testCase.alwaysBeExistingEntity, + "Entity name mismatch" + ); + assert.deepEqualExcluding(response, testCase.output, [ + "_response", + "createdAt", + "modifiedAt", + "accessedAt" + ]); + }); }); }); -}); -[ - { - entityType: EntityType.QUEUE, - alwaysBeExistingEntity: managementQueue1 - }, - { - entityType: EntityType.TOPIC, - alwaysBeExistingEntity: managementTopic1 - }, - { - entityType: EntityType.SUBSCRIPTION, - alwaysBeExistingEntity: managementSubscription1 - }, - { - entityType: EntityType.RULE, - alwaysBeExistingEntity: managementRule1 - } -].forEach((testCase) => { - describe(`Atom management - Update on "${testCase.entityType}" entities`, function(): void { - beforeEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await recreateQueue(managementQueue1); - break; - - case EntityType.TOPIC: - await recreateTopic(managementTopic1); - break; - - case EntityType.SUBSCRIPTION: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - break; - - case EntityType.RULE: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - await createEntity( - EntityType.RULE, - managementRule1, - managementTopic1, - managementSubscription1 - ); - break; - default: - throw new Error("TestError: Unrecognized EntityType"); + [ + { + entityType: EntityType.QUEUE, + 1: { + alwaysBeExistingEntity: managementQueue1, + output: { + sizeInBytes: 0, + totalMessageCount: 0, + activeMessageCount: 0, + deadLetterMessageCount: 0, + scheduledMessageCount: 0, + transferMessageCount: 0, + transferDeadLetterMessageCount: 0, + name: managementQueue1 + } + }, + 2: { + alwaysBeExistingEntity: managementQueue2, + output: { + sizeInBytes: 0, + totalMessageCount: 0, + activeMessageCount: 0, + deadLetterMessageCount: 0, + scheduledMessageCount: 0, + transferMessageCount: 0, + transferDeadLetterMessageCount: 0, + name: managementQueue2 + } } - }); - - afterEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await deleteEntity(EntityType.QUEUE, managementQueue1); - break; - - case EntityType.TOPIC: - case EntityType.SUBSCRIPTION: - case EntityType.RULE: - await deleteEntity(EntityType.TOPIC, managementTopic1); - break; - - default: - throw new Error("TestError: Unrecognized EntityType"); + }, + { + entityType: EntityType.TOPIC, + 1: { + alwaysBeExistingEntity: managementTopic1, + output: { + sizeInBytes: 0, + subscriptionCount: 0, + scheduledMessageCount: 0, + name: managementTopic1 + } + }, + 2: { + alwaysBeExistingEntity: managementTopic2, + output: { + sizeInBytes: 0, + subscriptionCount: 0, + scheduledMessageCount: 0, + name: managementTopic2 + } } - }); - - it(`Updates an existent ${testCase.entityType} entity successfully`, async () => { - const response = await updateEntity( - testCase.entityType, - testCase.alwaysBeExistingEntity, - managementTopic1, - managementSubscription1 - ); - should.equal( - response[testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], - testCase.alwaysBeExistingEntity, - "Entity name mismatch" - ); - }); - }); -}); - -[EntityType.QUEUE, EntityType.TOPIC, EntityType.SUBSCRIPTION, EntityType.RULE].forEach( - (entityType) => { - describe(`Atom management - Delete on "${entityType}" entities`, function(): void { + }, + { + entityType: EntityType.SUBSCRIPTION, + 1: { + alwaysBeExistingEntity: managementSubscription1, + output: { + totalMessageCount: 0, + activeMessageCount: 0, + deadLetterMessageCount: 0, + transferMessageCount: 0, + transferDeadLetterMessageCount: 0, + topicName: managementTopic1, + subscriptionName: managementSubscription1 + } + }, + 2: { + alwaysBeExistingEntity: managementSubscription2, + output: { + totalMessageCount: 0, + activeMessageCount: 0, + deadLetterMessageCount: 0, + transferMessageCount: 0, + transferDeadLetterMessageCount: 0, + topicName: managementTopic1, + subscriptionName: managementSubscription2 + } + } + } + ].forEach((testCase) => { + describe(`Atom management - Get runtime info on "${testCase.entityType}" entities`, function(): void { beforeEach(async () => { - switch (entityType) { + switch (testCase.entityType) { case EntityType.QUEUE: + await recreateQueue(managementQueue1); + await recreateQueue(managementQueue2); break; case EntityType.TOPIC: - break; - - case EntityType.SUBSCRIPTION: await recreateTopic(managementTopic1); + await recreateTopic(managementTopic2); break; - case EntityType.RULE: + case EntityType.SUBSCRIPTION: await recreateTopic(managementTopic1); await recreateSubscription(managementTopic1, managementSubscription1); + await recreateSubscription(managementTopic1, managementSubscription2); break; + default: throw new Error("TestError: Unrecognized EntityType"); } }); afterEach(async () => { - switch (entityType) { + switch (testCase.entityType) { case EntityType.QUEUE: + await deleteEntity(EntityType.QUEUE, managementQueue1); + await deleteEntity(EntityType.QUEUE, managementQueue2); + break; + case EntityType.TOPIC: + await deleteEntity(EntityType.TOPIC, managementTopic1); + await deleteEntity(EntityType.TOPIC, managementTopic2); break; + case EntityType.SUBSCRIPTION: - case EntityType.RULE: await deleteEntity(EntityType.TOPIC, managementTopic1); break; @@ -1070,148 +848,78 @@ describe("Atom management - Authentication", function(): void { } }); - it(`Deletes an existent ${entityType} entity successfully`, async () => { - await createEntity( - entityType, - newManagementEntity1, - managementTopic1, - managementSubscription1 - ); - - const response = await deleteEntity( - entityType, - newManagementEntity1, - managementTopic1, - managementSubscription1 - ); - - should.equal(response._response.status, 200); + it(`Gets runtime info for existing ${testCase.entityType} entities(multiple) successfully`, async () => { + const response = await getEntitiesRuntimeProperties(testCase.entityType, managementTopic1); + const name = testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"; + const paramsToExclude = ["createdAt", "accessedAt", "modifiedAt"]; + for (const info of response) { + if (info[name] === testCase[1].alwaysBeExistingEntity) { + assert.deepEqualExcluding(info, testCase[1].output, paramsToExclude); + } else if (info[name] === testCase[2].alwaysBeExistingEntity) { + assert.deepEqualExcluding(info, testCase[2].output, paramsToExclude); + } + } }); }); - } -); - -[ - { - entityType: EntityType.QUEUE, - alwaysBeExistingEntity: managementQueue1 - }, - { - entityType: EntityType.TOPIC, - alwaysBeExistingEntity: managementTopic1 - }, - { - entityType: EntityType.SUBSCRIPTION, - alwaysBeExistingEntity: managementSubscription1 - }, - { - entityType: EntityType.RULE, - alwaysBeExistingEntity: managementRule1 - } -].forEach((testCase) => { - describe(`Atom management - Create on "${testCase.entityType}" entities`, function(): void { - beforeEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await recreateQueue(managementQueue1); - break; - - case EntityType.TOPIC: - await recreateTopic(managementTopic1); - break; - - case EntityType.SUBSCRIPTION: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - break; - - case EntityType.RULE: - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - await createEntity( - EntityType.RULE, - managementRule1, - managementTopic1, - managementSubscription1 - ); - break; - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); - - afterEach(async () => { - switch (testCase.entityType) { - case EntityType.QUEUE: - await deleteEntity(EntityType.QUEUE, managementQueue1); - break; - - case EntityType.TOPIC: - case EntityType.SUBSCRIPTION: - case EntityType.RULE: - await deleteEntity(EntityType.TOPIC, managementTopic1); - break; - - default: - throw new Error("TestError: Unrecognized EntityType"); - } - }); - - it(`Creating an existent ${testCase.entityType} entity throws an error`, async () => { - let error; - try { - await createEntity( - testCase.entityType, - testCase.alwaysBeExistingEntity, - managementTopic1, - managementSubscription1 - ); - } catch (err) { - error = err; - } - - should.equal(error.statusCode, 409, "Unexpected status code found."); - should.equal(error.code, "MessageEntityAlreadyExistsError", `Unexpected error code found.`); - should.equal( - error.message.startsWith("The messaging entity") || - error.message.startsWith("Entity") || - error.message.startsWith("SubCode") || - error.message.startsWith("No service"), - true, - `Unexpected error message found.` - ); - }); }); -}); -[EntityType.QUEUE, EntityType.TOPIC, EntityType.SUBSCRIPTION, EntityType.RULE].forEach( - (entityType) => { - describe(`Atom management - CRUD on non-existent entities for type "${entityType}"`, function(): void { + [ + { + entityType: EntityType.QUEUE, + alwaysBeExistingEntity: managementQueue1 + }, + { + entityType: EntityType.TOPIC, + alwaysBeExistingEntity: managementTopic1 + }, + { + entityType: EntityType.SUBSCRIPTION, + alwaysBeExistingEntity: managementSubscription1 + }, + { + entityType: EntityType.RULE, + alwaysBeExistingEntity: managementRule1 + } + ].forEach((testCase) => { + describe(`Atom management - "${testCase.entityType}" exists`, function(): void { beforeEach(async () => { - switch (entityType) { + switch (testCase.entityType) { case EntityType.QUEUE: + await recreateQueue(managementQueue1); + break; + case EntityType.TOPIC: + await recreateTopic(managementTopic1); break; case EntityType.SUBSCRIPTION: await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); break; case EntityType.RULE: await recreateTopic(managementTopic1); await recreateSubscription(managementTopic1, managementSubscription1); + await serviceBusAtomManagementClient.createRule( + managementTopic1, + managementSubscription1, + managementRule1, + { sqlExpression: "1=2" } + ); break; + default: throw new Error("TestError: Unrecognized EntityType"); } }); afterEach(async () => { - switch (entityType) { + switch (testCase.entityType) { case EntityType.QUEUE: - case EntityType.TOPIC: + await deleteEntity(EntityType.QUEUE, managementQueue1); break; + case EntityType.TOPIC: case EntityType.SUBSCRIPTION: case EntityType.RULE: await deleteEntity(EntityType.TOPIC, managementTopic1); @@ -1222,112 +930,257 @@ describe("Atom management - Authentication", function(): void { } }); - it(`Creates a non-existent ${entityType} entity successfully`, async () => { - const response = await createEntity( - entityType, - newManagementEntity2, - managementTopic1, - managementSubscription1 - ); - - await deleteEntity( - entityType, - newManagementEntity2, - managementTopic1, - managementSubscription1 + it(`Returns true for an existing ${testCase.entityType} entity`, async () => { + should.equal( + await entityExists( + testCase.entityType, + testCase.alwaysBeExistingEntity, + managementTopic1, + managementSubscription1 + ), + true, + "Returned `false` for an existing entity" ); + }); + it(`Returns false for a non-existing ${testCase.entityType} entity`, async () => { should.equal( - response[entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], - newManagementEntity2, - "Entity name mismatch" + await entityExists( + testCase.entityType, + "non-existing-entity-name", + managementTopic1, + managementSubscription1 + ), + false, + "Returned `true` for a non-existing entity" ); }); + }); + }); - it(`Deletes a non-existent ${entityType} entity returns an error`, async () => { - let error; - try { - await deleteEntity(entityType, "notexisting", managementTopic1, managementSubscription1); - } catch (err) { - error = err; - } + [ + { + entityType: EntityType.QUEUE, + alwaysBeExistingEntity: managementQueue1 + }, + { + entityType: EntityType.TOPIC, + alwaysBeExistingEntity: managementTopic1 + }, + { + entityType: EntityType.SUBSCRIPTION, + alwaysBeExistingEntity: managementSubscription1 + }, + { + entityType: EntityType.RULE, + alwaysBeExistingEntity: managementRule1 + } + ].forEach((testCase) => { + describe(`Atom management - Update on "${testCase.entityType}" entities`, function(): void { + beforeEach(async () => { + switch (testCase.entityType) { + case EntityType.QUEUE: + await recreateQueue(managementQueue1); + break; - should.equal(error.code, "MessageEntityNotFoundError", `Unexpected error code found.`); - should.equal( - error.message.startsWith("The messaging entity") || - error.message.startsWith("Entity") || - error.message.startsWith("SubCode") || - error.message.startsWith("No service"), - true, - `Unexpected error message found.` - ); + case EntityType.TOPIC: + await recreateTopic(managementTopic1); + break; + + case EntityType.SUBSCRIPTION: + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + break; + + case EntityType.RULE: + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + await createEntity( + EntityType.RULE, + managementRule1, + managementTopic1, + managementSubscription1 + ); + break; + default: + throw new Error("TestError: Unrecognized EntityType"); + } }); - it(`Update on non-existent ${entityType} entity throws an error`, async () => { - let error; - try { - await updateEntity(entityType, "nonexisting", managementTopic1, managementSubscription1); - } catch (err) { - error = err; + afterEach(async () => { + switch (testCase.entityType) { + case EntityType.QUEUE: + await deleteEntity(EntityType.QUEUE, managementQueue1); + break; + + case EntityType.TOPIC: + case EntityType.SUBSCRIPTION: + case EntityType.RULE: + await deleteEntity(EntityType.TOPIC, managementTopic1); + break; + + default: + throw new Error("TestError: Unrecognized EntityType"); } + }); - should.equal(error.code, "MessageEntityNotFoundError", `Unexpected error code found.`); + it(`Updates an existent ${testCase.entityType} entity successfully`, async () => { + const response = await updateEntity( + testCase.entityType, + testCase.alwaysBeExistingEntity, + managementTopic1, + managementSubscription1 + ); should.equal( - error.message.startsWith("The messaging entity") || - error.message.startsWith("Entity") || - error.message.startsWith("SubCode") || - error.message.startsWith("No service"), - true, - `Unexpected error message found.` + response[testCase.entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], + testCase.alwaysBeExistingEntity, + "Entity name mismatch" ); }); + }); + }); + + [EntityType.QUEUE, EntityType.TOPIC, EntityType.SUBSCRIPTION, EntityType.RULE].forEach( + (entityType) => { + describe(`Atom management - Delete on "${entityType}" entities`, function(): void { + beforeEach(async () => { + switch (entityType) { + case EntityType.QUEUE: + break; + + case EntityType.TOPIC: + break; + + case EntityType.SUBSCRIPTION: + await recreateTopic(managementTopic1); + break; + + case EntityType.RULE: + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + break; + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); + + afterEach(async () => { + switch (entityType) { + case EntityType.QUEUE: + case EntityType.TOPIC: + break; + case EntityType.SUBSCRIPTION: + case EntityType.RULE: + await deleteEntity(EntityType.TOPIC, managementTopic1); + break; + + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); + + it(`Deletes an existent ${entityType} entity successfully`, async () => { + await createEntity( + entityType, + newManagementEntity1, + managementTopic1, + managementSubscription1 + ); + + const response = await deleteEntity( + entityType, + newManagementEntity1, + managementTopic1, + managementSubscription1 + ); + + should.equal(response._response.status, 200); + }); + }); + } + ); - it(`Get on non-existent ${entityType} entity throws an error`, async () => { - let error; - switch (entityType) { + [ + { + entityType: EntityType.QUEUE, + alwaysBeExistingEntity: managementQueue1 + }, + { + entityType: EntityType.TOPIC, + alwaysBeExistingEntity: managementTopic1 + }, + { + entityType: EntityType.SUBSCRIPTION, + alwaysBeExistingEntity: managementSubscription1 + }, + { + entityType: EntityType.RULE, + alwaysBeExistingEntity: managementRule1 + } + ].forEach((testCase) => { + describe(`Atom management - Create on "${testCase.entityType}" entities`, function(): void { + beforeEach(async () => { + switch (testCase.entityType) { case EntityType.QUEUE: - try { - await getEntity(entityType, "notexisting"); - } catch (err) { - error = err; - } + await recreateQueue(managementQueue1); break; case EntityType.TOPIC: - try { - error = await getEntity(entityType, "notexisting"); - } catch (err) { - error = err; - } - + await recreateTopic(managementTopic1); break; case EntityType.SUBSCRIPTION: - try { - error = await getEntity(entityType, "notexisting", managementTopic1); - } catch (err) { - error = err; - } + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); break; case EntityType.RULE: - try { - error = await getEntity( - entityType, - "notexisting", - managementTopic1, - managementSubscription1 - ); - } catch (err) { - error = err; - } + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + await createEntity( + EntityType.RULE, + managementRule1, + managementTopic1, + managementSubscription1 + ); + break; + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); + + afterEach(async () => { + switch (testCase.entityType) { + case EntityType.QUEUE: + await deleteEntity(EntityType.QUEUE, managementQueue1); + break; + + case EntityType.TOPIC: + case EntityType.SUBSCRIPTION: + case EntityType.RULE: + await deleteEntity(EntityType.TOPIC, managementTopic1); break; default: throw new Error("TestError: Unrecognized EntityType"); } + }); + + it(`Creating an existent ${testCase.entityType} entity throws an error`, async () => { + let error; + try { + await createEntity( + testCase.entityType, + testCase.alwaysBeExistingEntity, + managementTopic1, + managementSubscription1 + ); + } catch (err) { + error = err; + } - should.equal(error.code, "MessageEntityNotFoundError", `Unexpected error code found.`); + should.equal(error.statusCode, 409, "Unexpected status code found."); + should.equal(error.code, "MessageEntityAlreadyExistsError", `Unexpected error code found.`); should.equal( error.message.startsWith("The messaging entity") || error.message.startsWith("Entity") || @@ -1338,701 +1191,491 @@ describe("Atom management - Authentication", function(): void { ); }); }); - } -); + }); -// Topic tests -[ - { - testCaseTitle: "Undefined topic options", - input: undefined, - output: { - authorizationRules: undefined, - autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", - defaultMessageTimeToLive: "P10675199DT2H48M5.4775807S", - duplicateDetectionHistoryTimeWindow: "PT10M", - enableBatchedOperations: true, - enablePartitioning: false, - enableExpress: false, - maxSizeInMegabytes: 1024, - userMetadata: undefined, - requiresDuplicateDetection: false, - status: "Active", - supportOrdering: true, - name: managementTopic1, - availabilityStatus: "Available" - } - }, - { - testCaseTitle: "all properties", - input: { - requiresDuplicateDetection: true, - defaultMessageTimeToLive: "P2D", - deadLetteringOnMessageExpiration: true, - duplicateDetectionHistoryTimeWindow: "PT1M", - enableBatchedOperations: false, - status: "SendDisabled" as EntityStatus, - enablePartitioning: true, - enableExpress: false, - supportOrdering: false, - userMetadata: "test metadata", - availabilityStatus: "Available" as EntityAvailabilityStatus - }, - output: { - defaultMessageTimeToLive: "P2D", - duplicateDetectionHistoryTimeWindow: "PT1M", - status: "SendDisabled", - enableBatchedOperations: false, - supportOrdering: false, - requiresDuplicateDetection: true, - enablePartitioning: true, - enableExpress: false, - maxSizeInMegabytes: 16384, - autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", - authorizationRules: undefined, - userMetadata: "test metadata", - name: managementTopic1, - availabilityStatus: "Available" - } - } -].forEach((testCase) => { - describe(`createTopic() using different variations to the input parameter "topicOptions"`, function(): void { - afterEach(async () => { - await deleteEntity(EntityType.TOPIC, managementTopic1); - }); - it(`${testCase.testCaseTitle}`, async () => { - const response = await createEntity( - EntityType.TOPIC, - managementTopic1, - undefined, - undefined, - true, - undefined, - testCase.input - ); + [EntityType.QUEUE, EntityType.TOPIC, EntityType.SUBSCRIPTION, EntityType.RULE].forEach( + (entityType) => { + describe(`Atom management - CRUD on non-existent entities for type "${entityType}"`, function(): void { + beforeEach(async () => { + switch (entityType) { + case EntityType.QUEUE: + case EntityType.TOPIC: + break; + + case EntityType.SUBSCRIPTION: + await recreateTopic(managementTopic1); + break; + + case EntityType.RULE: + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + break; + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); - should.equal(response.name, managementTopic1, "Topic name mismatch"); - assert.deepEqualExcluding(response, testCase.output, [ - "_response", - "createdAt", - "modifiedAt", - "accessedAt" - ]); - }); - }); -}); + afterEach(async () => { + switch (entityType) { + case EntityType.QUEUE: + case EntityType.TOPIC: + break; + + case EntityType.SUBSCRIPTION: + case EntityType.RULE: + await deleteEntity(EntityType.TOPIC, managementTopic1); + break; + + default: + throw new Error("TestError: Unrecognized EntityType"); + } + }); + + it(`Creates a non-existent ${entityType} entity successfully`, async () => { + const response = await createEntity( + entityType, + newManagementEntity2, + managementTopic1, + managementSubscription1 + ); + + await deleteEntity( + entityType, + newManagementEntity2, + managementTopic1, + managementSubscription1 + ); + + should.equal( + response[entityType === EntityType.SUBSCRIPTION ? "subscriptionName" : "name"], + newManagementEntity2, + "Entity name mismatch" + ); + }); + + it(`Deletes a non-existent ${entityType} entity returns an error`, async () => { + let error; + try { + await deleteEntity( + entityType, + "notexisting", + managementTopic1, + managementSubscription1 + ); + } catch (err) { + error = err; + } + + should.equal(error.code, "MessageEntityNotFoundError", `Unexpected error code found.`); + should.equal( + error.message.startsWith("The messaging entity") || + error.message.startsWith("Entity") || + error.message.startsWith("SubCode") || + error.message.startsWith("No service"), + true, + `Unexpected error message found.` + ); + }); + + it(`Update on non-existent ${entityType} entity throws an error`, async () => { + let error; + try { + await updateEntity( + entityType, + "nonexisting", + managementTopic1, + managementSubscription1 + ); + } catch (err) { + error = err; + } + + should.equal(error.code, "MessageEntityNotFoundError", `Unexpected error code found.`); + should.equal( + error.message.startsWith("The messaging entity") || + error.message.startsWith("Entity") || + error.message.startsWith("SubCode") || + error.message.startsWith("No service"), + true, + `Unexpected error message found.` + ); + }); + + it(`Get on non-existent ${entityType} entity throws an error`, async () => { + let error; + switch (entityType) { + case EntityType.QUEUE: + try { + await getEntity(entityType, "notexisting"); + } catch (err) { + error = err; + } + break; + + case EntityType.TOPIC: + try { + error = await getEntity(entityType, "notexisting"); + } catch (err) { + error = err; + } + + break; + + case EntityType.SUBSCRIPTION: + try { + error = await getEntity(entityType, "notexisting", managementTopic1); + } catch (err) { + error = err; + } + break; + + case EntityType.RULE: + try { + error = await getEntity( + entityType, + "notexisting", + managementTopic1, + managementSubscription1 + ); + } catch (err) { + error = err; + } + break; + + default: + throw new Error("TestError: Unrecognized EntityType"); + } + + should.equal(error.code, "MessageEntityNotFoundError", `Unexpected error code found.`); + should.equal( + error.message.startsWith("The messaging entity") || + error.message.startsWith("Entity") || + error.message.startsWith("SubCode") || + error.message.startsWith("No service"), + true, + `Unexpected error message found.` + ); + }); + }); + } + ); -// Subscription tests -describe(`createSubscription() using different variations to the input parameter "subscriptionOptions"`, function(): void { - const createSubscriptionTestCases: { - testCaseTitle: string; - input?: CreateSubscriptionOptions; - output: SubscriptionProperties; - }[] = [ + // Topic tests + [ { - testCaseTitle: "Undefined subscription options", + testCaseTitle: "Undefined topic options", input: undefined, output: { + authorizationRules: undefined, autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", - deadLetteringOnMessageExpiration: false, - deadLetteringOnFilterEvaluationExceptions: true, defaultMessageTimeToLive: "P10675199DT2H48M5.4775807S", - forwardDeadLetteredMessagesTo: undefined, + duplicateDetectionHistoryTimeWindow: "PT10M", enableBatchedOperations: true, - forwardTo: undefined, + enablePartitioning: false, + enableExpress: false, + maxSizeInMegabytes: 1024, userMetadata: undefined, - lockDuration: "PT1M", - maxDeliveryCount: 10, - requiresSession: false, + requiresDuplicateDetection: false, status: "Active", - subscriptionName: managementSubscription1, - topicName: managementTopic1, + supportOrdering: true, + name: managementTopic1, availabilityStatus: "Available" } }, { - testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", + testCaseTitle: "all properties", input: { - lockDuration: "PT5M", - maxDeliveryCount: 20, + requiresDuplicateDetection: true, defaultMessageTimeToLive: "P2D", - autoDeleteOnIdle: "PT1H", - deadLetteringOnFilterEvaluationExceptions: false, deadLetteringOnMessageExpiration: true, + duplicateDetectionHistoryTimeWindow: "PT1M", enableBatchedOperations: false, - requiresSession: true, + status: "SendDisabled" as EntityStatus, + enablePartitioning: true, + enableExpress: false, + supportOrdering: false, userMetadata: "test metadata", - status: "ReceiveDisabled" as EntityStatus, availabilityStatus: "Available" as EntityAvailabilityStatus }, output: { - lockDuration: "PT5M", - maxDeliveryCount: 20, defaultMessageTimeToLive: "P2D", - autoDeleteOnIdle: "PT1H", - deadLetteringOnFilterEvaluationExceptions: false, - deadLetteringOnMessageExpiration: true, + duplicateDetectionHistoryTimeWindow: "PT1M", + status: "SendDisabled", enableBatchedOperations: false, - requiresSession: true, - forwardDeadLetteredMessagesTo: undefined, - forwardTo: undefined, + supportOrdering: false, + requiresDuplicateDetection: true, + enablePartitioning: true, + enableExpress: false, + maxSizeInMegabytes: 16384, + autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", + authorizationRules: undefined, userMetadata: "test metadata", - status: "ReceiveDisabled", - subscriptionName: managementSubscription1, - topicName: managementTopic1, + name: managementTopic1, availabilityStatus: "Available" } } - ]; - createSubscriptionTestCases.push({ - testCaseTitle: "case-2 with defaultRuleOptions", - input: { - ...createSubscriptionTestCases[1].input, - defaultRuleOptions: { - name: "rule", - filter: { - sqlExpression: "stringValue = @stringParam AND intValue = @intParam", - sqlParameters: { "@intParam": 1, "@stringParam": "b" } - }, - action: { sqlExpression: "SET a='b'", sqlParameters: undefined } - } - }, - output: { ...createSubscriptionTestCases[1].output } - }); - - beforeEach(async () => { - await createEntity(EntityType.TOPIC, managementTopic1); - }); - - afterEach(async () => { - await deleteEntity(EntityType.TOPIC, managementTopic1); - }); - - createSubscriptionTestCases.forEach((testCase) => { - it(`${testCase.testCaseTitle}`, async () => { - const response: WithResponse = await createEntity( - EntityType.SUBSCRIPTION, - managementSubscription1, - managementTopic1, - undefined, - true, - undefined, - undefined, - testCase.input - ); - - should.equal( - response.subscriptionName, - managementSubscription1, - "Subscription name mismatch" - ); - assert.deepEqual(response, testCase.output); - - if (testCase.input?.defaultRuleOptions) { - const ruleResponse = await serviceBusAtomManagementClient.getRule( - response.topicName, - response.subscriptionName, - testCase.input.defaultRuleOptions.name + ].forEach((testCase) => { + describe(`createTopic() using different variations to the input parameter "topicOptions"`, function(): void { + afterEach(async () => { + await deleteEntity(EntityType.TOPIC, managementTopic1); + }); + it(`${testCase.testCaseTitle}`, async () => { + const response = await createEntity( + EntityType.TOPIC, + managementTopic1, + undefined, + undefined, + true, + undefined, + testCase.input ); - assert.deepEqual(ruleResponse, testCase.input.defaultRuleOptions); - } - }); - }); -}); - -[ - { - testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: managementQueue1, - forwardTo: managementQueue1 - }, - output: { - lockDuration: "PT1M", - maxDeliveryCount: 10, - defaultMessageTimeToLive: "P10675199DT2H48M5.4775807S", - deadLetteringOnFilterEvaluationExceptions: true, - deadLetteringOnMessageExpiration: false, - enableBatchedOperations: true, - requiresSession: false, - - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, - forwardTo: `${endpointWithProtocol}${managementQueue1}`, - autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", - - defaultRuleDescription: undefined, - - messageCount: 0, - enablePartitioning: undefined, - enableExpress: undefined, - maxSizeInMegabytes: undefined, - sizeInBytes: undefined, - - userMetadata: undefined, - messageCountDetails: undefined, - status: "Active", - availabilityStatus: "Available", - subscriptionName: managementSubscription1, - topicName: managementTopic1 - } - }, - { - testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`.toUpperCase(), - forwardTo: `${endpointWithProtocol}${managementQueue1}`.toUpperCase() - }, - output: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1.toUpperCase()}`, - forwardTo: `${endpointWithProtocol}${managementQueue1.toUpperCase()}` - } - } -].forEach((testCase) => { - describe(`createSubscription() using different variations to message forwarding related parameters in "subscriptionOptions"`, function(): void { - beforeEach(async () => { - await recreateQueue(managementQueue1); - await recreateTopic(managementTopic1); - }); - - afterEach(async () => { - await deleteEntity(EntityType.TOPIC, managementTopic1); - await deleteEntity(EntityType.QUEUE, managementQueue1); - }); - - it(`${testCase.testCaseTitle}`, async () => { - const response = await createEntity( - EntityType.SUBSCRIPTION, - managementSubscription1, - managementTopic1, - undefined, - true, - undefined, - undefined, - testCase.input - ); - should.equal( - response.subscriptionName, - managementSubscription1, - "Subscription name mismatch" - ); - should.equal(response.forwardTo, testCase.output.forwardTo, "forwardTo value mismatch"); - should.equal( - response.forwardDeadLetteredMessagesTo, - testCase.output.forwardDeadLetteredMessagesTo, - "forwardDeadLetteredMessagesTo value mismatch" - ); + should.equal(response.name, managementTopic1, "Topic name mismatch"); + assert.deepEqualExcluding(response, testCase.output, [ + "_response", + "createdAt", + "modifiedAt", + "accessedAt", + "maxMessageSizeInKilobytes" + ]); + }); }); }); -}); -// Queue tests -[ - { - testCaseTitle: "Undefined queue options", - input: undefined, - output: { - authorizationRules: undefined, - autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", - deadLetteringOnMessageExpiration: false, - defaultMessageTimeToLive: "P10675199DT2H48M5.4775807S", - duplicateDetectionHistoryTimeWindow: "PT10M", - enableBatchedOperations: true, - enablePartitioning: false, - enableExpress: false, - forwardDeadLetteredMessagesTo: undefined, - lockDuration: "PT1M", - maxDeliveryCount: 10, - maxSizeInMegabytes: 1024, - name: managementQueue1, - requiresDuplicateDetection: false, - requiresSession: false, - status: "Active", - forwardTo: undefined, - userMetadata: undefined, - availabilityStatus: "Available" - } - }, - { - testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", - input: { - lockDuration: "PT45S", - requiresDuplicateDetection: true, - requiresSession: true, - defaultMessageTimeToLive: "P2D", - deadLetteringOnMessageExpiration: true, - duplicateDetectionHistoryTimeWindow: "PT1M", - maxDeliveryCount: 8, - enableBatchedOperations: false, - autoDeleteOnIdle: "PT1H", - authorizationRules: [ - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"] as AccessRights, - keyName: "allClaims_v2", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - }, - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"] as AccessRights, - keyName: "allClaims_v3", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey + // Subscription tests + describe(`createSubscription() using different variations to the input parameter "subscriptionOptions"`, function(): void { + const createSubscriptionTestCases: { + testCaseTitle: string; + input?: CreateSubscriptionOptions; + output: SubscriptionProperties; + }[] = [ + { + testCaseTitle: "Undefined subscription options", + input: undefined, + output: { + autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", + deadLetteringOnMessageExpiration: false, + deadLetteringOnFilterEvaluationExceptions: true, + defaultMessageTimeToLive: "P10675199DT2H48M5.4775807S", + forwardDeadLetteredMessagesTo: undefined, + enableBatchedOperations: true, + forwardTo: undefined, + userMetadata: undefined, + lockDuration: "PT1M", + maxDeliveryCount: 10, + requiresSession: false, + status: "Active", + subscriptionName: managementSubscription1, + topicName: managementTopic1, + availabilityStatus: "Available" } - ], - enablePartitioning: true, - enableExpress: false, - userMetadata: "test metadata", - status: "ReceiveDisabled" as EntityStatus, - availabilityStatus: "Available" as EntityAvailabilityStatus - }, - output: { - duplicateDetectionHistoryTimeWindow: "PT1M", - lockDuration: "PT45S", - defaultMessageTimeToLive: "P2D", - deadLetteringOnMessageExpiration: true, - enableBatchedOperations: false, - maxDeliveryCount: 8, - requiresDuplicateDetection: true, - requiresSession: true, - autoDeleteOnIdle: "PT1H", - authorizationRules: [ - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"] as AccessRights, - keyName: "allClaims_v2", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey + }, + { + testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", + input: { + lockDuration: "PT5M", + maxDeliveryCount: 20, + defaultMessageTimeToLive: "P2D", + autoDeleteOnIdle: "PT1H", + deadLetteringOnFilterEvaluationExceptions: false, + deadLetteringOnMessageExpiration: true, + enableBatchedOperations: false, + requiresSession: true, + userMetadata: "test metadata", + status: "ReceiveDisabled" as EntityStatus, + availabilityStatus: "Available" as EntityAvailabilityStatus }, - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"] as AccessRights, - keyName: "allClaims_v3", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey + output: { + lockDuration: "PT5M", + maxDeliveryCount: 20, + defaultMessageTimeToLive: "P2D", + autoDeleteOnIdle: "PT1H", + deadLetteringOnFilterEvaluationExceptions: false, + deadLetteringOnMessageExpiration: true, + enableBatchedOperations: false, + requiresSession: true, + forwardDeadLetteredMessagesTo: undefined, + forwardTo: undefined, + userMetadata: "test metadata", + status: "ReceiveDisabled", + subscriptionName: managementSubscription1, + topicName: managementTopic1, + availabilityStatus: "Available" } - ], - enablePartitioning: true, - enableExpress: false, - maxSizeInMegabytes: 16384, - forwardDeadLetteredMessagesTo: undefined, - forwardTo: undefined, - userMetadata: "test metadata", - status: "ReceiveDisabled", - name: managementQueue1, - availabilityStatus: "Available" - } - } -].forEach((testCase) => { - describe(`createQueue() using different variations to the input parameter "queueOptions"`, function(): void { - afterEach(async () => { - await deleteEntity(EntityType.QUEUE, managementQueue1); - }); - - it(`${testCase.testCaseTitle}`, async () => { - const response = await createEntity( - EntityType.QUEUE, - managementQueue1, - undefined, - undefined, - true, - testCase.input - ); - - should.equal(response.name, managementQueue1, "Queue name mismatch"); - - assert.deepEqualExcluding(response, testCase.output, [ - "_response", - "createdAt", - "modifiedAt", - "accessedAt" - ]); + } + ]; + createSubscriptionTestCases.push({ + testCaseTitle: "case-2 with defaultRuleOptions", + input: { + ...createSubscriptionTestCases[1].input, + defaultRuleOptions: { + name: "rule", + filter: { + sqlExpression: "stringValue = @stringParam AND intValue = @intParam", + sqlParameters: { "@intParam": 1, "@stringParam": "b" } + }, + action: { sqlExpression: "SET a='b'", sqlParameters: undefined } + } + }, + output: { ...createSubscriptionTestCases[1].output } }); - }); -}); -[ - { - testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: managementTopic1, - forwardTo: managementTopic1 - }, - output: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, - forwardTo: `${endpointWithProtocol}${managementTopic1}` - } - }, - { - testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, - forwardTo: `${endpointWithProtocol}${managementTopic1}` - }, - output: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, - forwardTo: `${endpointWithProtocol}${managementTopic1}` - } - } -].forEach((testCase) => { - describe(`createQueue() using different variations to message forwarding related parameters in "queueOptions"`, function(): void { beforeEach(async () => { await createEntity(EntityType.TOPIC, managementTopic1); }); afterEach(async () => { - await deleteEntity(EntityType.QUEUE, managementQueue1); await deleteEntity(EntityType.TOPIC, managementTopic1); }); - it(`${testCase.testCaseTitle}`, async () => { - const response = await createEntity( - EntityType.QUEUE, - managementQueue1, - undefined, - undefined, - true, - testCase.input - ); + createSubscriptionTestCases.forEach((testCase) => { + it(`${testCase.testCaseTitle}`, async () => { + const response: WithResponse = await createEntity( + EntityType.SUBSCRIPTION, + managementSubscription1, + managementTopic1, + undefined, + true, + undefined, + undefined, + testCase.input + ); - should.equal(response.forwardTo, testCase.output.forwardTo, "forwardTo value mismatch"); - should.equal( - response.forwardDeadLetteredMessagesTo, - testCase.output.forwardDeadLetteredMessagesTo, - "forwardDeadLetteredMessagesTo value mismatch" - ); - }); - }); -}); + should.equal( + response.subscriptionName, + managementSubscription1, + "Subscription name mismatch" + ); + assert.deepEqual(response, testCase.output); -describe(`createRule() using different variations to the input parameter "ruleOptions"`, function(): void { - beforeEach(async () => { - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - }); - afterEach(async () => { - await deleteEntity(EntityType.TOPIC, managementTopic1); + if (testCase.input?.defaultRuleOptions) { + const ruleResponse = await serviceBusAtomManagementClient.getRule( + response.topicName, + response.subscriptionName, + testCase.input.defaultRuleOptions.name + ); + assert.deepEqual(ruleResponse, testCase.input.defaultRuleOptions); + } + }); + }); }); - // Rule tests - const createRuleTests: { - testCaseTitle: string; - input: Omit["defaultRuleOptions"], "name"> | undefined; - output: RuleProperties; - }[] = [ - { - testCaseTitle: "Undefined rule options", - input: undefined, - output: { - filter: { - sqlExpression: "1=1", - sqlParameters: undefined - }, - action: { - sqlExpression: undefined, - sqlParameters: undefined - }, - name: managementRule1 - } - }, - { - testCaseTitle: "Sql Filter rule options", - input: { - filter: { - sqlExpression: "stringValue = @stringParam AND intValue = @intParam", - sqlParameters: { "@intParam": 1, "@stringParam": "b" } - }, - action: { sqlExpression: "SET a='b'" } - }, - output: { - filter: { - sqlExpression: "stringValue = @stringParam AND intValue = @intParam", - sqlParameters: { "@intParam": 1, "@stringParam": "b" } - }, - action: { - sqlExpression: "SET a='b'", - sqlParameters: undefined - }, - name: managementRule1 - } - }, + [ { - testCaseTitle: "Correlation Filter rule options with a single property", + testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", input: { - filter: { - correlationId: "abcd", - applicationProperties: { - randomState: "WA" - } - }, - action: { sqlExpression: "SET sys.label='GREEN'" } + forwardDeadLetteredMessagesTo: managementQueue1, + forwardTo: managementQueue1 }, output: { - filter: { - correlationId: "abcd", - contentType: undefined, - subject: undefined, - messageId: undefined, - replyTo: undefined, - replyToSessionId: undefined, - sessionId: undefined, - to: undefined, - applicationProperties: { - randomState: "WA" - } - }, - action: { - sqlExpression: "SET sys.label='GREEN'", - sqlParameters: undefined - }, - name: managementRule1 + lockDuration: "PT1M", + maxDeliveryCount: 10, + defaultMessageTimeToLive: "P10675199DT2H48M5.4775807S", + deadLetteringOnFilterEvaluationExceptions: true, + deadLetteringOnMessageExpiration: false, + enableBatchedOperations: true, + requiresSession: false, + + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, + forwardTo: `${endpointWithProtocol}${managementQueue1}`, + autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", + + defaultRuleDescription: undefined, + + messageCount: 0, + enablePartitioning: undefined, + enableExpress: undefined, + maxSizeInMegabytes: undefined, + sizeInBytes: undefined, + + userMetadata: undefined, + messageCountDetails: undefined, + status: "Active", + availabilityStatus: "Available", + subscriptionName: managementSubscription1, + topicName: managementTopic1 } }, { - testCaseTitle: "Correlation Filter rule options with multiple properties", + testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", input: { - filter: { - correlationId: "abcd", - applicationProperties: { - randomState: "WA", - randomCountry: "US", - randomInt: 25, - randomIntDisguisedAsDouble: 3.0, - randomDouble: 12.4, - randomBool: true, - randomDate: randomDate - } - }, - action: { sqlExpression: "SET sys.label='GREEN'" } + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`.toUpperCase(), + forwardTo: `${endpointWithProtocol}${managementQueue1}`.toUpperCase() }, output: { - filter: { - correlationId: "abcd", - contentType: undefined, - subject: undefined, - messageId: undefined, - replyTo: undefined, - replyToSessionId: undefined, - sessionId: undefined, - to: undefined, - applicationProperties: { - randomState: "WA", - randomCountry: "US", - randomInt: 25, - randomIntDisguisedAsDouble: 3.0, - randomDouble: 12.4, - randomBool: true, - randomDate: randomDate - } - }, - action: { - sqlExpression: "SET sys.label='GREEN'", - sqlParameters: undefined - }, - name: managementRule1 + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1.toUpperCase()}`, + forwardTo: `${endpointWithProtocol}${managementQueue1.toUpperCase()}` } } - ]; - createRuleTests.forEach((testCase) => { - it(`${testCase.testCaseTitle}`, async () => { - const response = await createEntity( - EntityType.RULE, - managementRule1, - managementTopic1, - managementSubscription1, - true, - undefined, - undefined, - undefined, - testCase.input - ); - should.equal(response.name, managementRule1, "Rule name mismatch"); - assert.deepEqualExcluding(response, testCase.output, [ - "_response", - "createdAt", - "modifiedAt", - "accessedAt" - ]); + ].forEach((testCase) => { + describe(`createSubscription() using different variations to message forwarding related parameters in "subscriptionOptions"`, function(): void { + beforeEach(async () => { + await recreateQueue(managementQueue1); + await recreateTopic(managementTopic1); + }); + + afterEach(async () => { + await deleteEntity(EntityType.TOPIC, managementTopic1); + await deleteEntity(EntityType.QUEUE, managementQueue1); + }); + + it(`${testCase.testCaseTitle}`, async () => { + const response = await createEntity( + EntityType.SUBSCRIPTION, + managementSubscription1, + managementTopic1, + undefined, + true, + undefined, + undefined, + testCase.input + ); + + should.equal( + response.subscriptionName, + managementSubscription1, + "Subscription name mismatch" + ); + should.equal(response.forwardTo, testCase.output.forwardTo, "forwardTo value mismatch"); + should.equal( + response.forwardDeadLetteredMessagesTo, + testCase.output.forwardDeadLetteredMessagesTo, + "forwardDeadLetteredMessagesTo value mismatch" + ); + }); }); }); -}); -// Queue tests -[ - { - testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", - input: { - lockDuration: "PT50S", - defaultMessageTimeToLive: "P1D", - deadLetteringOnMessageExpiration: true, - duplicateDetectionHistoryTimeWindow: "PT2M", - maxDeliveryCount: 5, - enableBatchedOperations: false, - autoDeleteOnIdle: "PT2H", - authorizationRules: [ - { - claimType: "SharedAccessKey", - accessRights: ["Send"] as AccessRights, - keyName: "allClaims_v2", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - }, - { - claimType: "SharedAccessKey", - accessRights: ["Listen"] as AccessRights, - keyName: "allClaims_v3", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - } - ], - enablePartitioning: true, - enableExpress: false, - userMetadata: "test metadata", - status: "ReceiveDisabled" as EntityStatus, - availabilityStatus: "Available" as EntityAvailabilityStatus + // Queue tests + [ + { + testCaseTitle: "Undefined queue options", + input: undefined, + output: { + authorizationRules: undefined, + autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", + deadLetteringOnMessageExpiration: false, + defaultMessageTimeToLive: "P10675199DT2H48M5.4775807S", + duplicateDetectionHistoryTimeWindow: "PT10M", + enableBatchedOperations: true, + enablePartitioning: false, + enableExpress: false, + forwardDeadLetteredMessagesTo: undefined, + lockDuration: "PT1M", + maxDeliveryCount: 10, + maxSizeInMegabytes: 1024, + name: managementQueue1, + requiresDuplicateDetection: false, + requiresSession: false, + status: "Active", + forwardTo: undefined, + userMetadata: undefined, + availabilityStatus: "Available" + } }, - output: { - duplicateDetectionHistoryTimeWindow: "PT2M", - lockDuration: "PT50S", - defaultMessageTimeToLive: "P1D", - deadLetteringOnMessageExpiration: true, - enableBatchedOperations: false, - requiresDuplicateDetection: true, - requiresSession: true, - authorizationRules: [ - { - claimType: "SharedAccessKey", - accessRights: ["Send"] as AccessRights, - keyName: "allClaims_v2", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - }, - { - claimType: "SharedAccessKey", - accessRights: ["Listen"] as AccessRights, - keyName: "allClaims_v3", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - } - ], - maxDeliveryCount: 5, - maxSizeInMegabytes: 16384, - autoDeleteOnIdle: "PT2H", - forwardDeadLetteredMessagesTo: undefined, - forwardTo: undefined, - userMetadata: "test metadata", - status: "ReceiveDisabled", - enablePartitioning: true, - enableExpress: false, - name: managementQueue1, - availabilityStatus: "Available" - } - } -].forEach((testCase) => { - describe(`updateQueue() using different variations to the input parameter "queueOptions"`, function(): void { - beforeEach(async () => { - await recreateQueue(managementQueue1, { + { + testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", + input: { lockDuration: "PT45S", requiresDuplicateDetection: true, requiresSession: true, @@ -2045,132 +1688,127 @@ describe(`createRule() using different variations to the input parameter "ruleOp authorizationRules: [ { claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"], + accessRights: ["Manage", "Send", "Listen"] as AccessRights, keyName: "allClaims_v2", primaryKey: TestConstants.primaryKey, secondaryKey: TestConstants.secondaryKey }, { claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"], + accessRights: ["Manage", "Send", "Listen"] as AccessRights, keyName: "allClaims_v3", primaryKey: TestConstants.primaryKey, secondaryKey: TestConstants.secondaryKey } ], enablePartitioning: true, - enableExpress: false - }); - }); - - afterEach(async () => { - await deleteEntity(EntityType.QUEUE, managementQueue1); - }); - - it(`${testCase.testCaseTitle}`, async () => { - try { - const response = await updateEntity( - EntityType.QUEUE, - managementQueue1, - undefined, - undefined, - true, - testCase.input - ); - - assert.deepEqualExcluding(response, testCase.output, [ - "_response", - "createdAt", - "modifiedAt", - "accessedAt" - ]); - } catch (err) { - checkForValidErrorScenario(err, testCase.output); - } - }); - }); -}); - -[ - { - testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: managementTopic1, - forwardTo: managementTopic1 - }, - output: { - duplicateDetectionHistoryTimeWindow: "PT1M", - lockDuration: "PT45S", - defaultMessageTimeToLive: "P2D", - deadLetteringOnMessageExpiration: true, - enableBatchedOperations: false, - - requiresDuplicateDetection: true, - requiresSession: true, - authorizationRules: [ - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"] as AccessRights, - keyName: "allClaims_v2", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - }, - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"] as AccessRights, - keyName: "allClaims_v3", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - } - ], - - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, - forwardTo: `${endpointWithProtocol}${managementTopic1}`, - autoDeleteOnIdle: "PT1H", - maxDeliveryCount: 8, - maxSizeInMegabytes: 16384, - - messageCount: undefined, - sizeInBytes: undefined, - status: "Active", - - userMetadata: undefined, + enableExpress: false, + userMetadata: "test metadata", + status: "ReceiveDisabled" as EntityStatus, + availabilityStatus: "Available" as EntityAvailabilityStatus + }, + output: { + duplicateDetectionHistoryTimeWindow: "PT1M", + lockDuration: "PT45S", + defaultMessageTimeToLive: "P2D", + deadLetteringOnMessageExpiration: true, + enableBatchedOperations: false, + maxDeliveryCount: 8, + requiresDuplicateDetection: true, + requiresSession: true, + autoDeleteOnIdle: "PT1H", + authorizationRules: [ + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"] as AccessRights, + keyName: "allClaims_v2", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + }, + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"] as AccessRights, + keyName: "allClaims_v3", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + } + ], + enablePartitioning: true, + enableExpress: false, + maxSizeInMegabytes: 16384, + forwardDeadLetteredMessagesTo: undefined, + forwardTo: undefined, + userMetadata: "test metadata", + status: "ReceiveDisabled", + name: managementQueue1, + availabilityStatus: "Available" + } + } + ].forEach((testCase) => { + describe(`createQueue() using different variations to the input parameter "queueOptions"`, function(): void { + afterEach(async () => { + await deleteEntity(EntityType.QUEUE, managementQueue1); + }); - messageCountDetails: undefined, + it(`${testCase.testCaseTitle}`, async () => { + const response = await createEntity( + EntityType.QUEUE, + managementQueue1, + undefined, + undefined, + true, + testCase.input + ); - enableExpress: undefined, - availabilityStatus: "Available", - isAnonymousAccessible: undefined, - supportOrdering: undefined, - enablePartitioning: true, - name: managementQueue1 - } - }, - { - testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, - forwardTo: `${endpointWithProtocol}${managementTopic1}` + should.equal(response.name, managementQueue1, "Queue name mismatch"); + + assert.deepEqualExcluding(response, testCase.output, [ + "_response", + "createdAt", + "modifiedAt", + "accessedAt", + "maxMessageSizeInKilobytes" + ]); + }); + }); + }); + + [ + { + testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", + input: { + forwardDeadLetteredMessagesTo: managementTopic1, + forwardTo: managementTopic1 + }, + output: { + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, + forwardTo: `${endpointWithProtocol}${managementTopic1}` + } }, - output: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, - forwardTo: `${endpointWithProtocol}${managementTopic1}` + { + testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", + input: { + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, + forwardTo: `${endpointWithProtocol}${managementTopic1}` + }, + output: { + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, + forwardTo: `${endpointWithProtocol}${managementTopic1}` + } } - } -].forEach((testCase) => { - describe(`updateQueue() using different variations to message forwarding related parameters in "queueOptions"`, function(): void { - beforeEach(async () => { - await recreateTopic(managementTopic1); - await recreateQueue(managementQueue1); - }); - afterEach(async () => { - await deleteEntity(EntityType.QUEUE, managementQueue1); - await deleteEntity(EntityType.QUEUE, managementTopic1); - }); + ].forEach((testCase) => { + describe(`createQueue() using different variations to message forwarding related parameters in "queueOptions"`, function(): void { + beforeEach(async () => { + await createEntity(EntityType.TOPIC, managementTopic1); + }); - it(`${testCase.testCaseTitle}`, async () => { - try { - const response = await updateEntity( + afterEach(async () => { + await deleteEntity(EntityType.QUEUE, managementQueue1); + await deleteEntity(EntityType.TOPIC, managementTopic1); + }); + + it(`${testCase.testCaseTitle}`, async () => { + const response = await createEntity( EntityType.QUEUE, managementQueue1, undefined, @@ -2185,777 +1823,1271 @@ describe(`createRule() using different variations to the input parameter "ruleOp testCase.output.forwardDeadLetteredMessagesTo, "forwardDeadLetteredMessagesTo value mismatch" ); - } catch (err) { - checkForValidErrorScenario(err, testCase.output); - } + }); }); }); -}); -// Topic tests -[ - { - topicName: managementTopic1, - testCaseTitle: "all properties", - input: { - status: "SendDisabled" as EntityStatus, - userMetadata: "test metadata", - requiresDuplicateDetection: false, - defaultMessageTimeToLive: "P1D", - duplicateDetectionHistoryTimeWindow: "PT2M", - autoDeleteOnIdle: "PT2H", - supportOrdering: true, - maxSizeInMegabytes: 3072, - availabilityStatus: "Available" as EntityAvailabilityStatus - }, - output: { - requiresDuplicateDetection: false, - defaultMessageTimeToLive: "P1D", - duplicateDetectionHistoryTimeWindow: "PT2M", - autoDeleteOnIdle: "PT2H", - supportOrdering: true, - maxSizeInMegabytes: 3072, - enableBatchedOperations: true, - enablePartitioning: false, - enableExpress: false, - authorizationRules: undefined, - status: "SendDisabled", - userMetadata: "test metadata", - name: managementTopic1, - availabilityStatus: "Available" - } - } -].forEach((testCase) => { - describe(`updateTopic() using different variations to the input parameter "topicOptions"`, function(): void { + describe(`createRule() using different variations to the input parameter "ruleOptions"`, function(): void { beforeEach(async () => { await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); }); afterEach(async () => { await deleteEntity(EntityType.TOPIC, managementTopic1); }); - it(`${testCase.testCaseTitle}`, async () => { - try { - const response = await updateEntity( - EntityType.TOPIC, + // Rule tests + const createRuleTests: { + testCaseTitle: string; + input: Omit["defaultRuleOptions"], "name"> | undefined; + output: RuleProperties; + }[] = [ + { + testCaseTitle: "Undefined rule options", + input: undefined, + output: { + filter: { + sqlExpression: "1=1", + sqlParameters: undefined + }, + action: { + sqlExpression: undefined, + sqlParameters: undefined + }, + name: managementRule1 + } + }, + { + testCaseTitle: "Sql Filter rule options", + input: { + filter: { + sqlExpression: "stringValue = @stringParam AND intValue = @intParam", + sqlParameters: { "@intParam": 1, "@stringParam": "b" } + }, + action: { sqlExpression: "SET a='b'" } + }, + output: { + filter: { + sqlExpression: "stringValue = @stringParam AND intValue = @intParam", + sqlParameters: { "@intParam": 1, "@stringParam": "b" } + }, + action: { + sqlExpression: "SET a='b'", + sqlParameters: undefined + }, + name: managementRule1 + } + }, + { + testCaseTitle: "Correlation Filter rule options with a single property", + input: { + filter: { + correlationId: "abcd", + applicationProperties: { + randomState: "WA" + } + }, + action: { sqlExpression: "SET sys.label='GREEN'" } + }, + output: { + filter: { + correlationId: "abcd", + contentType: undefined, + subject: undefined, + messageId: undefined, + replyTo: undefined, + replyToSessionId: undefined, + sessionId: undefined, + to: undefined, + applicationProperties: { + randomState: "WA" + } + }, + action: { + sqlExpression: "SET sys.label='GREEN'", + sqlParameters: undefined + }, + name: managementRule1 + } + }, + { + testCaseTitle: "Correlation Filter rule options with multiple properties", + input: { + filter: { + correlationId: "abcd", + applicationProperties: { + randomState: "WA", + randomCountry: "US", + randomInt: 25, + randomIntDisguisedAsDouble: 3.0, + randomDouble: 12.4, + randomBool: true, + randomDate: randomDate + } + }, + action: { sqlExpression: "SET sys.label='GREEN'" } + }, + output: { + filter: { + correlationId: "abcd", + contentType: undefined, + subject: undefined, + messageId: undefined, + replyTo: undefined, + replyToSessionId: undefined, + sessionId: undefined, + to: undefined, + applicationProperties: { + randomState: "WA", + randomCountry: "US", + randomInt: 25, + randomIntDisguisedAsDouble: 3.0, + randomDouble: 12.4, + randomBool: true, + randomDate: randomDate + } + }, + action: { + sqlExpression: "SET sys.label='GREEN'", + sqlParameters: undefined + }, + name: managementRule1 + } + } + ]; + createRuleTests.forEach((testCase) => { + it(`${testCase.testCaseTitle}`, async () => { + const response = await createEntity( + EntityType.RULE, + managementRule1, managementTopic1, + managementSubscription1, + true, undefined, undefined, - true, undefined, testCase.input ); - + should.equal(response.name, managementRule1, "Rule name mismatch"); assert.deepEqualExcluding(response, testCase.output, [ "_response", "createdAt", "modifiedAt", "accessedAt" ]); - } catch (err) { - checkForValidErrorScenario(err, testCase.output); - } + }); }); }); -}); -// Subscription tests -[ - { - testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", - input: { - lockDuration: "PT3M", - maxDeliveryCount: 10, - defaultMessageTimeToLive: "P1D", - autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", - deadLetteringOnFilterEvaluationExceptions: true, - deadLetteringOnMessageExpiration: false, - enableBatchedOperations: true, - requiresSession: false, - userMetadata: "test metadata", - status: "ReceiveDisabled" as EntityStatus, - availabilityStatus: "Available" as EntityAvailabilityStatus - }, - output: { - lockDuration: "PT3M", - maxDeliveryCount: 10, - defaultMessageTimeToLive: "P1D", - autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", - deadLetteringOnFilterEvaluationExceptions: true, - deadLetteringOnMessageExpiration: false, - enableBatchedOperations: true, - forwardDeadLetteredMessagesTo: undefined, - forwardTo: undefined, - requiresSession: false, - userMetadata: "test metadata", - status: "ReceiveDisabled", - subscriptionName: managementSubscription1, - topicName: managementTopic1, - availabilityStatus: "Available" + // Queue tests + [ + { + testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", + input: { + lockDuration: "PT50S", + defaultMessageTimeToLive: "P1D", + deadLetteringOnMessageExpiration: true, + duplicateDetectionHistoryTimeWindow: "PT2M", + maxDeliveryCount: 5, + enableBatchedOperations: false, + autoDeleteOnIdle: "PT2H", + authorizationRules: [ + { + claimType: "SharedAccessKey", + accessRights: ["Send"] as AccessRights, + keyName: "allClaims_v2", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + }, + { + claimType: "SharedAccessKey", + accessRights: ["Listen"] as AccessRights, + keyName: "allClaims_v3", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + } + ], + enablePartitioning: true, + enableExpress: false, + userMetadata: "test metadata", + status: "ReceiveDisabled" as EntityStatus, + availabilityStatus: "Available" as EntityAvailabilityStatus + }, + output: { + duplicateDetectionHistoryTimeWindow: "PT2M", + lockDuration: "PT50S", + defaultMessageTimeToLive: "P1D", + deadLetteringOnMessageExpiration: true, + enableBatchedOperations: false, + requiresDuplicateDetection: true, + requiresSession: true, + authorizationRules: [ + { + claimType: "SharedAccessKey", + accessRights: ["Send"] as AccessRights, + keyName: "allClaims_v2", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + }, + { + claimType: "SharedAccessKey", + accessRights: ["Listen"] as AccessRights, + keyName: "allClaims_v3", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + } + ], + maxDeliveryCount: 5, + maxSizeInMegabytes: 16384, + autoDeleteOnIdle: "PT2H", + forwardDeadLetteredMessagesTo: undefined, + forwardTo: undefined, + userMetadata: "test metadata", + status: "ReceiveDisabled", + enablePartitioning: true, + enableExpress: false, + name: managementQueue1, + availabilityStatus: "Available" + } } - } -].forEach((testCase) => { - describe(`updateSubscription() using different variations to the input parameter "subscriptionOptions"`, function(): void { - beforeEach(async () => { - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - }); + ].forEach((testCase) => { + describe(`updateQueue() using different variations to the input parameter "queueOptions"`, function(): void { + beforeEach(async () => { + await recreateQueue(managementQueue1, { + lockDuration: "PT45S", + requiresDuplicateDetection: true, + requiresSession: true, + defaultMessageTimeToLive: "P2D", + deadLetteringOnMessageExpiration: true, + duplicateDetectionHistoryTimeWindow: "PT1M", + maxDeliveryCount: 8, + enableBatchedOperations: false, + autoDeleteOnIdle: "PT1H", + authorizationRules: [ + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"], + keyName: "allClaims_v2", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + }, + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"], + keyName: "allClaims_v3", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + } + ], + enablePartitioning: true, + enableExpress: false + }); + }); - afterEach(async () => { - await deleteEntity(EntityType.TOPIC, managementTopic1); - }); + afterEach(async () => { + await deleteEntity(EntityType.QUEUE, managementQueue1); + }); - it(`${testCase.testCaseTitle}`, async () => { - try { - const response = await updateEntity( - EntityType.SUBSCRIPTION, - managementSubscription1, - managementTopic1, - undefined, - true, - undefined, - undefined, - testCase.input - ); + it(`${testCase.testCaseTitle}`, async () => { + try { + const response = await updateEntity( + EntityType.QUEUE, + managementQueue1, + undefined, + undefined, + true, + testCase.input + ); - assert.deepEqualExcluding(response, testCase.output, [ - "_response", - "createdAt", - "modifiedAt", - "accessedAt" - ]); - } catch (err) { - checkForValidErrorScenario(err, testCase.output); - } + assert.deepEqualExcluding(response, testCase.output, [ + "_response", + "createdAt", + "modifiedAt", + "accessedAt", + "maxMessageSizeInKilobytes" + ]); + } catch (err) { + checkForValidErrorScenario(err, testCase.output); + } + }); }); }); -}); -[ - { - testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: managementQueue1, - forwardTo: managementQueue1 - }, - output: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, - forwardTo: `${endpointWithProtocol}${managementQueue1}` - } - }, - { - testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", - input: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, - forwardTo: `${endpointWithProtocol}${managementQueue1}` + [ + { + testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", + input: { + forwardDeadLetteredMessagesTo: managementTopic1, + forwardTo: managementTopic1 + }, + output: { + duplicateDetectionHistoryTimeWindow: "PT1M", + lockDuration: "PT45S", + defaultMessageTimeToLive: "P2D", + deadLetteringOnMessageExpiration: true, + enableBatchedOperations: false, + + requiresDuplicateDetection: true, + requiresSession: true, + authorizationRules: [ + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"] as AccessRights, + keyName: "allClaims_v2", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + }, + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"] as AccessRights, + keyName: "allClaims_v3", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + } + ], + + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, + forwardTo: `${endpointWithProtocol}${managementTopic1}`, + autoDeleteOnIdle: "PT1H", + maxDeliveryCount: 8, + maxSizeInMegabytes: 16384, + + messageCount: undefined, + sizeInBytes: undefined, + status: "Active", + + userMetadata: undefined, + + messageCountDetails: undefined, + + enableExpress: undefined, + availabilityStatus: "Available", + isAnonymousAccessible: undefined, + supportOrdering: undefined, + enablePartitioning: true, + name: managementQueue1 + } }, - output: { - forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, - forwardTo: `${endpointWithProtocol}${managementQueue1}` + { + testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", + input: { + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, + forwardTo: `${endpointWithProtocol}${managementTopic1}` + }, + output: { + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementTopic1}`, + forwardTo: `${endpointWithProtocol}${managementTopic1}` + } } - } -].forEach((testCase) => { - describe(`updateSubscription() using different variations to message forwarding related parameters in "subscriptionOptions"`, function(): void { - beforeEach(async () => { - await recreateQueue(managementQueue1); - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - }); + ].forEach((testCase) => { + describe(`updateQueue() using different variations to message forwarding related parameters in "queueOptions"`, function(): void { + beforeEach(async () => { + await recreateTopic(managementTopic1); + await recreateQueue(managementQueue1); + }); + afterEach(async () => { + await deleteEntity(EntityType.QUEUE, managementQueue1); + await deleteEntity(EntityType.QUEUE, managementTopic1); + }); - afterEach(async () => { - await deleteEntity(EntityType.TOPIC, managementTopic1); - await deleteEntity(EntityType.QUEUE, managementQueue1); - }); + it(`${testCase.testCaseTitle}`, async () => { + try { + const response = await updateEntity( + EntityType.QUEUE, + managementQueue1, + undefined, + undefined, + true, + testCase.input + ); - it(`${testCase.testCaseTitle}`, async () => { - try { - const response = await updateEntity( - EntityType.SUBSCRIPTION, - managementSubscription1, - managementTopic1, - undefined, - true, - undefined, - undefined, - testCase.input - ); + should.equal(response.forwardTo, testCase.output.forwardTo, "forwardTo value mismatch"); + should.equal( + response.forwardDeadLetteredMessagesTo, + testCase.output.forwardDeadLetteredMessagesTo, + "forwardDeadLetteredMessagesTo value mismatch" + ); + } catch (err) { + checkForValidErrorScenario(err, testCase.output); + } + }); + }); + }); - should.equal(response.forwardTo, testCase.output.forwardTo, "forwardTo value mismatch"); - should.equal( - response.forwardDeadLetteredMessagesTo, - testCase.output.forwardDeadLetteredMessagesTo, - "forwardDeadLetteredMessagesTo value mismatch" - ); - } catch (err) { - checkForValidErrorScenario(err, testCase.output); + // Topic tests + [ + { + topicName: managementTopic1, + testCaseTitle: "all properties", + input: { + status: "SendDisabled" as EntityStatus, + userMetadata: "test metadata", + requiresDuplicateDetection: false, + defaultMessageTimeToLive: "P1D", + duplicateDetectionHistoryTimeWindow: "PT2M", + autoDeleteOnIdle: "PT2H", + supportOrdering: true, + maxSizeInMegabytes: 3072, + maxMessageSizeInKilobytes: 1036, + availabilityStatus: "Available" as EntityAvailabilityStatus + }, + output: { + requiresDuplicateDetection: false, + defaultMessageTimeToLive: "P1D", + duplicateDetectionHistoryTimeWindow: "PT2M", + autoDeleteOnIdle: "PT2H", + supportOrdering: true, + maxSizeInMegabytes: 3072, + enableBatchedOperations: true, + enablePartitioning: false, + enableExpress: false, + authorizationRules: undefined, + status: "SendDisabled", + userMetadata: "test metadata", + name: managementTopic1, + availabilityStatus: "Available" } + } + ].forEach((testCase) => { + describe(`updateTopic() using different variations to the input parameter "topicOptions"`, function(): void { + beforeEach(async () => { + await recreateTopic(managementTopic1); + }); + afterEach(async () => { + await deleteEntity(EntityType.TOPIC, managementTopic1); + }); + + it(`${testCase.testCaseTitle}`, async () => { + try { + const response = await updateEntity( + EntityType.TOPIC, + managementTopic1, + undefined, + undefined, + true, + undefined, + testCase.input + ); + + assert.deepEqualExcluding(response, testCase.output, [ + "_response", + "createdAt", + "modifiedAt", + "accessedAt", + "maxMessageSizeInKilobytes" + ]); + } catch (err) { + checkForValidErrorScenario(err, testCase.output); + } + }); }); }); -}); -// Rule tests -describe(`updateRule() using different variations to the input parameter "ruleOptions"`, function(): void { - beforeEach(async () => { - await recreateTopic(managementTopic1); - await recreateSubscription(managementTopic1, managementSubscription1); - await createEntity(EntityType.RULE, managementRule1, managementTopic1, managementSubscription1); - }); + // Subscription tests + [ + { + testCaseTitle: "all properties except forwardTo, forwardDeadLetteredMessagesTo", + input: { + lockDuration: "PT3M", + maxDeliveryCount: 10, + defaultMessageTimeToLive: "P1D", + autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", + deadLetteringOnFilterEvaluationExceptions: true, + deadLetteringOnMessageExpiration: false, + enableBatchedOperations: true, + requiresSession: false, + userMetadata: "test metadata", + status: "ReceiveDisabled" as EntityStatus, + availabilityStatus: "Available" as EntityAvailabilityStatus + }, + output: { + lockDuration: "PT3M", + maxDeliveryCount: 10, + defaultMessageTimeToLive: "P1D", + autoDeleteOnIdle: "P10675199DT2H48M5.4775807S", + deadLetteringOnFilterEvaluationExceptions: true, + deadLetteringOnMessageExpiration: false, + enableBatchedOperations: true, + forwardDeadLetteredMessagesTo: undefined, + forwardTo: undefined, + requiresSession: false, + userMetadata: "test metadata", + status: "ReceiveDisabled", + subscriptionName: managementSubscription1, + topicName: managementTopic1, + availabilityStatus: "Available" + } + } + ].forEach((testCase) => { + describe(`updateSubscription() using different variations to the input parameter "subscriptionOptions"`, function(): void { + beforeEach(async () => { + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + }); - afterEach(async () => { - await deleteEntity(EntityType.TOPIC, managementTopic1); + afterEach(async () => { + await deleteEntity(EntityType.TOPIC, managementTopic1); + }); + + it(`${testCase.testCaseTitle}`, async () => { + try { + const response = await updateEntity( + EntityType.SUBSCRIPTION, + managementSubscription1, + managementTopic1, + undefined, + true, + undefined, + undefined, + testCase.input + ); + + assert.deepEqualExcluding(response, testCase.output, [ + "_response", + "createdAt", + "modifiedAt", + "accessedAt" + ]); + } catch (err) { + checkForValidErrorScenario(err, testCase.output); + } + }); + }); }); + [ { - testCaseTitle: "Sql Filter rule options", + testCaseTitle: "pass in entity name for forwardTo and forwardDeadLetteredMessagesTo", input: { - filter: { - sqlExpression: "stringValue = @stringParam", - sqlParameters: { "@stringParam": "b" } - }, - action: { sqlExpression: "SET a='c'" } + forwardDeadLetteredMessagesTo: managementQueue1, + forwardTo: managementQueue1 }, output: { - filter: { - sqlExpression: "stringValue = @stringParam", - sqlParameters: { "@stringParam": "b" } - }, - action: { - sqlExpression: "SET a='c'", - sqlParameters: undefined - }, - - name: managementRule1 + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, + forwardTo: `${endpointWithProtocol}${managementQueue1}` } }, { - testCaseTitle: "Correlation Filter rule options", + testCaseTitle: "pass in absolute URI for forwardTo and forwardDeadLetteredMessagesTo", input: { - filter: { - correlationId: "defg" + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, + forwardTo: `${endpointWithProtocol}${managementQueue1}` + }, + output: { + forwardDeadLetteredMessagesTo: `${endpointWithProtocol}${managementQueue1}`, + forwardTo: `${endpointWithProtocol}${managementQueue1}` + } + } + ].forEach((testCase) => { + describe(`updateSubscription() using different variations to message forwarding related parameters in "subscriptionOptions"`, function(): void { + beforeEach(async () => { + await recreateQueue(managementQueue1); + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + }); + + afterEach(async () => { + await deleteEntity(EntityType.TOPIC, managementTopic1); + await deleteEntity(EntityType.QUEUE, managementQueue1); + }); + + it(`${testCase.testCaseTitle}`, async () => { + try { + const response = await updateEntity( + EntityType.SUBSCRIPTION, + managementSubscription1, + managementTopic1, + undefined, + true, + undefined, + undefined, + testCase.input + ); + + should.equal(response.forwardTo, testCase.output.forwardTo, "forwardTo value mismatch"); + should.equal( + response.forwardDeadLetteredMessagesTo, + testCase.output.forwardDeadLetteredMessagesTo, + "forwardDeadLetteredMessagesTo value mismatch" + ); + } catch (err) { + checkForValidErrorScenario(err, testCase.output); + } + }); + }); + }); + + // Rule tests + describe(`updateRule() using different variations to the input parameter "ruleOptions"`, function(): void { + beforeEach(async () => { + await recreateTopic(managementTopic1); + await recreateSubscription(managementTopic1, managementSubscription1); + await createEntity( + EntityType.RULE, + managementRule1, + managementTopic1, + managementSubscription1 + ); + }); + + afterEach(async () => { + await deleteEntity(EntityType.TOPIC, managementTopic1); + }); + [ + { + testCaseTitle: "Sql Filter rule options", + input: { + filter: { + sqlExpression: "stringValue = @stringParam", + sqlParameters: { "@stringParam": "b" } + }, + action: { sqlExpression: "SET a='c'" } }, - action: { sqlExpression: "SET sys.label='RED'" } + output: { + filter: { + sqlExpression: "stringValue = @stringParam", + sqlParameters: { "@stringParam": "b" } + }, + action: { + sqlExpression: "SET a='c'", + sqlParameters: undefined + }, + + name: managementRule1 + } }, - output: { - filter: { - correlationId: "defg", - contentType: undefined, - subject: undefined, - messageId: undefined, - replyTo: undefined, - replyToSessionId: undefined, - sessionId: undefined, - to: undefined, - applicationProperties: undefined - }, - action: { - sqlExpression: "SET sys.label='RED'", - sqlParameters: undefined + { + testCaseTitle: "Correlation Filter rule options", + input: { + filter: { + correlationId: "defg" + }, + action: { sqlExpression: "SET sys.label='RED'" } }, + output: { + filter: { + correlationId: "defg", + contentType: undefined, + subject: undefined, + messageId: undefined, + replyTo: undefined, + replyToSessionId: undefined, + sessionId: undefined, + to: undefined, + applicationProperties: undefined + }, + action: { + sqlExpression: "SET sys.label='RED'", + sqlParameters: undefined + }, - name: managementRule1 + name: managementRule1 + } } - } - ].forEach((testCase) => { - it(`${testCase.testCaseTitle}`, async () => { - try { - const response = await updateEntity( - EntityType.RULE, - managementRule1, - managementTopic1, - managementSubscription1, - true, - undefined, - undefined, - undefined, - testCase.input - ); + ].forEach((testCase) => { + it(`${testCase.testCaseTitle}`, async () => { + try { + const response = await updateEntity( + EntityType.RULE, + managementRule1, + managementTopic1, + managementSubscription1, + true, + undefined, + undefined, + undefined, + testCase.input + ); - assert.deepEqualExcluding(response, testCase.output, [ - "_response", - "createdAt", - "modifiedAt", - "accessedAt" - ]); - } catch (err) { - checkForValidErrorScenario(err, testCase.output); - } + assert.deepEqualExcluding(response, testCase.output, [ + "_response", + "createdAt", + "modifiedAt", + "accessedAt" + ]); + } catch (err) { + checkForValidErrorScenario(err, testCase.output); + } + }); }); }); -}); -function checkForValidErrorScenario(err: any, expectedtestOutput: any): void { - let isErrorExpected = false; + function checkForValidErrorScenario(err: any, expectedtestOutput: any): void { + let isErrorExpected = false; - if (expectedtestOutput.testErrorMessage) { - isErrorExpected = true; - should.equal( - err.message && err.message.startsWith(expectedtestOutput.testErrorMessage), - true, - `Unexpected error message prefix found.` - ); - } + if (expectedtestOutput.testErrorMessage) { + isErrorExpected = true; + should.equal( + err.message && err.message.startsWith(expectedtestOutput.testErrorMessage), + true, + `Unexpected error message prefix found.` + ); + } - if (expectedtestOutput.testErrorCode) { - isErrorExpected = true; - should.equal( - err.code && err.code.startsWith(expectedtestOutput.testErrorCode), - true, - `Unexpected error code found.` - ); - } + if (expectedtestOutput.testErrorCode) { + isErrorExpected = true; + should.equal( + err.code && err.code.startsWith(expectedtestOutput.testErrorCode), + true, + `Unexpected error code found.` + ); + } - if (!isErrorExpected) { - throw err; + if (!isErrorExpected) { + throw err; + } } -} -async function createEntity( - testEntityType: EntityType, - entityPath: string, - topicPath?: string, - subscriptionPath?: string, - overrideOptions?: boolean, // If this is false, then the default options will be populated as used for basic testing. - queueOptions?: Omit, - topicOptions?: Omit, - subscriptionOptions?: Omit, - ruleOptions?: Omit["defaultRuleOptions"], "name"> -): Promise { - if (!overrideOptions) { - if (queueOptions === undefined) { - queueOptions = { - lockDuration: "PT1M", - authorizationRules: [ - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"], - keyName: "allClaims_v1", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - } - ] - }; - } + async function createEntity( + testEntityType: EntityType, + entityPath: string, + topicPath?: string, + subscriptionPath?: string, + overrideOptions?: boolean, // If this is false, then the default options will be populated as used for basic testing. + queueOptions?: Omit, + topicOptions?: Omit, + subscriptionOptions?: Omit, + ruleOptions?: Omit["defaultRuleOptions"], "name">, + atomClient: ServiceBusAdministrationClient = serviceBusAtomManagementClient + ): Promise { + if (!overrideOptions) { + if (queueOptions === undefined) { + queueOptions = { + lockDuration: "PT1M", + authorizationRules: [ + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"], + keyName: "allClaims_v1", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + } + ] + }; + } - if (topicOptions === undefined) { - topicOptions = { - status: "Active" - }; - } + if (topicOptions === undefined) { + topicOptions = { + status: "Active" + }; + } - if (subscriptionOptions === undefined) { - subscriptionOptions = { - lockDuration: "PT1M" - }; - } + if (subscriptionOptions === undefined) { + subscriptionOptions = { + lockDuration: "PT1M" + }; + } - if (ruleOptions === undefined) { - ruleOptions = { - filter: { - sqlExpression: "stringValue = @stringParam AND intValue = @intParam", - sqlParameters: { "@intParam": 1, "@stringParam": "b" } - }, - action: { sqlExpression: "SET a='b'" } - }; + if (ruleOptions === undefined) { + ruleOptions = { + filter: { + sqlExpression: "stringValue = @stringParam AND intValue = @intParam", + sqlParameters: { "@intParam": 1, "@stringParam": "b" } + }, + action: { sqlExpression: "SET a='b'" } + }; + } } - } - switch (testEntityType) { - case EntityType.QUEUE: { - const queueResponse = await serviceBusAtomManagementClient.createQueue(entityPath, { - ...queueOptions - }); - return queueResponse; - } - case EntityType.TOPIC: { - const topicResponse = await serviceBusAtomManagementClient.createTopic(entityPath, { - ...topicOptions - }); - return topicResponse; - } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" - ); + switch (testEntityType) { + case EntityType.QUEUE: { + const queueResponse = await atomClient.createQueue(entityPath, { + ...queueOptions + }); + return queueResponse; + } + case EntityType.TOPIC: { + const topicResponse = await atomClient.createTopic(entityPath, { + ...topicOptions + }); + return topicResponse; } - const subscriptionResponse = await serviceBusAtomManagementClient.createSubscription( - topicPath, - entityPath, - { + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const subscriptionResponse = await atomClient.createSubscription(topicPath, entityPath, { ...subscriptionOptions + }); + return subscriptionResponse; + } + case EntityType.RULE: { + if (!topicPath || !subscriptionPath) { + throw new Error( + "TestError: Topic path AND subscription path must be passed when invoking tests on rules" + ); } - ); - return subscriptionResponse; - } - case EntityType.RULE: { - if (!topicPath || !subscriptionPath) { - throw new Error( - "TestError: Topic path AND subscription path must be passed when invoking tests on rules" + const ruleResponse = await atomClient.createRule( + topicPath, + subscriptionPath, + entityPath, + ruleOptions?.filter!, + ruleOptions?.action! ); + return ruleResponse; } - const ruleResponse = await serviceBusAtomManagementClient.createRule( - topicPath, - subscriptionPath, - entityPath, - ruleOptions?.filter!, - ruleOptions?.action! - ); - return ruleResponse; } + throw new Error("TestError: Unrecognized EntityType"); } - throw new Error("TestError: Unrecognized EntityType"); -} -async function getEntity( - testEntityType: EntityType, - entityPath: string, - topicPath?: string, - subscriptionPath?: string -): Promise { - switch (testEntityType) { - case EntityType.QUEUE: { - const queueResponse = await serviceBusAtomManagementClient.getQueue(entityPath); - return queueResponse; - } - case EntityType.TOPIC: { - const topicResponse = await serviceBusAtomManagementClient.getTopic(entityPath); - return topicResponse; - } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" - ); + async function getEntity( + testEntityType: EntityType, + entityPath: string, + topicPath?: string, + subscriptionPath?: string, + atomClient: ServiceBusAdministrationClient = serviceBusAtomManagementClient + ): Promise { + switch (testEntityType) { + case EntityType.QUEUE: { + const queueResponse = await atomClient.getQueue(entityPath); + return queueResponse; } - const subscriptionResponse = await serviceBusAtomManagementClient.getSubscription( - topicPath, - entityPath - ); - return subscriptionResponse; - } - case EntityType.RULE: { - if (!topicPath || !subscriptionPath) { - throw new Error( - "TestError: Topic path AND subscription path must be passed when invoking tests on rules" - ); + case EntityType.TOPIC: { + const topicResponse = await atomClient.getTopic(entityPath); + return topicResponse; + } + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const subscriptionResponse = await atomClient.getSubscription(topicPath, entityPath); + return subscriptionResponse; + } + case EntityType.RULE: { + if (!topicPath || !subscriptionPath) { + throw new Error( + "TestError: Topic path AND subscription path must be passed when invoking tests on rules" + ); + } + const ruleResponse = await atomClient.getRule(topicPath, subscriptionPath, entityPath); + return ruleResponse; } - const ruleResponse = await serviceBusAtomManagementClient.getRule( - topicPath, - subscriptionPath, - entityPath - ); - return ruleResponse; } + throw new Error("TestError: Unrecognized EntityType"); } - throw new Error("TestError: Unrecognized EntityType"); -} -async function getEntityRuntimeProperties( - testEntityType: EntityType, - entityPath: string, - topicPath?: string -): Promise { - switch (testEntityType) { - case EntityType.QUEUE: { - const queueResponse = await serviceBusAtomManagementClient.getQueueRuntimeProperties( - entityPath - ); - return queueResponse; - } - case EntityType.TOPIC: { - const topicResponse = await serviceBusAtomManagementClient.getTopicRuntimeProperties( - entityPath - ); - return topicResponse; - } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" + async function getEntityRuntimeProperties( + testEntityType: EntityType, + entityPath: string, + topicPath?: string + ): Promise { + switch (testEntityType) { + case EntityType.QUEUE: { + const queueResponse = await serviceBusAtomManagementClient.getQueueRuntimeProperties( + entityPath ); + return queueResponse; + } + case EntityType.TOPIC: { + const topicResponse = await serviceBusAtomManagementClient.getTopicRuntimeProperties( + entityPath + ); + return topicResponse; + } + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const subscriptionResponse = await serviceBusAtomManagementClient.getSubscriptionRuntimeProperties( + topicPath, + entityPath + ); + return subscriptionResponse; } - const subscriptionResponse = await serviceBusAtomManagementClient.getSubscriptionRuntimeProperties( - topicPath, - entityPath - ); - return subscriptionResponse; } + throw new Error("TestError: Unrecognized EntityType"); } - throw new Error("TestError: Unrecognized EntityType"); -} -async function getEntitiesRuntimeProperties( - testEntityType: EntityType, - topicPath?: string -): Promise { - switch (testEntityType) { - case EntityType.QUEUE: { - const queueResponse = await serviceBusAtomManagementClient["getQueuesRuntimeProperties"](); - return queueResponse; - } - case EntityType.TOPIC: { - const topicResponse = await serviceBusAtomManagementClient["getTopicsRuntimeProperties"](); - return topicResponse; - } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" - ); + async function getEntitiesRuntimeProperties( + testEntityType: EntityType, + topicPath?: string + ): Promise { + switch (testEntityType) { + case EntityType.QUEUE: { + const queueResponse = await serviceBusAtomManagementClient["getQueuesRuntimeProperties"](); + return queueResponse; + } + case EntityType.TOPIC: { + const topicResponse = await serviceBusAtomManagementClient["getTopicsRuntimeProperties"](); + return topicResponse; + } + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const subscriptionResponse = await serviceBusAtomManagementClient[ + "getSubscriptionsRuntimeProperties" + ](topicPath); + return subscriptionResponse; } - const subscriptionResponse = await serviceBusAtomManagementClient[ - "getSubscriptionsRuntimeProperties" - ](topicPath); - return subscriptionResponse; } + throw new Error("TestError: Unrecognized EntityType"); } - throw new Error("TestError: Unrecognized EntityType"); -} -async function entityExists( - testEntityType: EntityType, - entityPath: string, - topicPath?: string, - subscriptionPath?: string -): Promise { - switch (testEntityType) { - case EntityType.QUEUE: { - const queueResponse = await serviceBusAtomManagementClient.queueExists(entityPath); - return queueResponse; - } - case EntityType.TOPIC: { - const topicResponse = await serviceBusAtomManagementClient.topicExists(entityPath); - return topicResponse; - } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" - ); + async function entityExists( + testEntityType: EntityType, + entityPath: string, + topicPath?: string, + subscriptionPath?: string, + atomClient: ServiceBusAdministrationClient = serviceBusAtomManagementClient + ): Promise { + switch (testEntityType) { + case EntityType.QUEUE: { + const queueResponse = await atomClient.queueExists(entityPath); + return queueResponse; } - const subscriptionResponse = await serviceBusAtomManagementClient.subscriptionExists( - topicPath, - entityPath - ); - return subscriptionResponse; - } - case EntityType.RULE: { - if (!topicPath || !subscriptionPath) { - throw new Error( - "TestError: topic path and subscription path must be passed when invoking tests on rules" - ); + case EntityType.TOPIC: { + const topicResponse = await atomClient.topicExists(entityPath); + return topicResponse; + } + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const subscriptionResponse = await atomClient.subscriptionExists(topicPath, entityPath); + return subscriptionResponse; + } + case EntityType.RULE: { + if (!topicPath || !subscriptionPath) { + throw new Error( + "TestError: topic path and subscription path must be passed when invoking tests on rules" + ); + } + const ruleResponse = await atomClient.ruleExists(topicPath, subscriptionPath, entityPath); + return ruleResponse; } - const ruleResponse = await serviceBusAtomManagementClient.ruleExists( - topicPath, - subscriptionPath, - entityPath - ); - return ruleResponse; } + throw new Error("TestError: Unrecognized EntityType"); } - throw new Error("TestError: Unrecognized EntityType"); -} -async function updateEntity( - testEntityType: EntityType, - entityPath: string, - topicPath?: string, - subscriptionPath?: string, - overrideOptions?: boolean, // If this is false, then the default options will be populated as used for basic testing. - queueOptions?: Omit, - topicOptions?: Omit, - subscriptionOptions?: Omit, - ruleOptions?: Omit -): Promise { - if (!overrideOptions) { - if (queueOptions === undefined) { - queueOptions = { - lockDuration: "PT1M", - authorizationRules: [ - { - claimType: "SharedAccessKey", - accessRights: ["Manage", "Send", "Listen"], - keyName: "allClaims_v1", - primaryKey: TestConstants.primaryKey, - secondaryKey: TestConstants.secondaryKey - } - ] - }; - } + async function updateEntity( + testEntityType: EntityType, + entityPath: string, + topicPath?: string, + subscriptionPath?: string, + overrideOptions?: boolean, // If this is false, then the default options will be populated as used for basic testing. + queueOptions?: Omit, + topicOptions?: Omit, + subscriptionOptions?: Omit, + ruleOptions?: Omit, + atomClient: ServiceBusAdministrationClient = serviceBusAtomManagementClient + ): Promise { + if (!overrideOptions) { + if (queueOptions === undefined) { + queueOptions = { + lockDuration: "PT1M", + authorizationRules: [ + { + claimType: "SharedAccessKey", + accessRights: ["Manage", "Send", "Listen"], + keyName: "allClaims_v1", + primaryKey: TestConstants.primaryKey, + secondaryKey: TestConstants.secondaryKey + } + ] + }; + } - if (topicOptions === undefined) { - topicOptions = { - status: "Active" - }; - } + if (topicOptions === undefined) { + topicOptions = { + status: "Active" + }; + } - if (subscriptionOptions === undefined) { - subscriptionOptions = { - lockDuration: "PT1M" - }; - } + if (subscriptionOptions === undefined) { + subscriptionOptions = { + lockDuration: "PT1M" + }; + } - if (ruleOptions === undefined) { - ruleOptions = { - filter: { - sqlExpression: "stringValue = @stringParam AND intValue = @intParam", - sqlParameters: { - "@intParam": 1, - "@stringParam": "b" - } - }, - action: { sqlExpression: "SET a='b'" } - }; + if (ruleOptions === undefined) { + ruleOptions = { + filter: { + sqlExpression: "stringValue = @stringParam AND intValue = @intParam", + sqlParameters: { + "@intParam": 1, + "@stringParam": "b" + } + }, + action: { sqlExpression: "SET a='b'" } + }; + } } - } - switch (testEntityType) { - case EntityType.QUEUE: { - const getQueueResponse = await serviceBusAtomManagementClient.getQueue(entityPath); - const queueResponse = await serviceBusAtomManagementClient.updateQueue({ - ...getQueueResponse, - ...queueOptions - }); - return queueResponse; - } - case EntityType.TOPIC: { - const getTopicResponse = await serviceBusAtomManagementClient.getTopic(entityPath); - const topicResponse = await serviceBusAtomManagementClient.updateTopic({ - ...getTopicResponse, - ...topicOptions - }); - return topicResponse; - } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" - ); + switch (testEntityType) { + case EntityType.QUEUE: { + const getQueueResponse = await atomClient.getQueue(entityPath); + const queueResponse = await atomClient.updateQueue({ + ...getQueueResponse, + ...queueOptions + }); + return queueResponse; } - const getSubscriptionResponse = await serviceBusAtomManagementClient.getSubscription( - topicPath, - entityPath - ); - const subscriptionResponse = await serviceBusAtomManagementClient.updateSubscription({ - ...getSubscriptionResponse, - ...subscriptionOptions - }); - return subscriptionResponse; - } - case EntityType.RULE: { - if (!topicPath || !subscriptionPath) { - throw new Error( - "TestError: Topic path AND subscription path must be passed when invoking tests on rules" - ); + case EntityType.TOPIC: { + const getTopicResponse = await atomClient.getTopic(entityPath); + const topicResponse = await atomClient.updateTopic({ + ...getTopicResponse, + ...topicOptions + }); + return topicResponse; } - const getRuleResponse = await serviceBusAtomManagementClient.getRule( - topicPath, - subscriptionPath, - entityPath - ); - const ruleResponse = await serviceBusAtomManagementClient.updateRule( - topicPath, - subscriptionPath, - { + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const getSubscriptionResponse = await atomClient.getSubscription(topicPath, entityPath); + const subscriptionResponse = await atomClient.updateSubscription({ + ...getSubscriptionResponse, + ...subscriptionOptions + }); + return subscriptionResponse; + } + case EntityType.RULE: { + if (!topicPath || !subscriptionPath) { + throw new Error( + "TestError: Topic path AND subscription path must be passed when invoking tests on rules" + ); + } + const getRuleResponse = await atomClient.getRule(topicPath, subscriptionPath, entityPath); + const ruleResponse = await atomClient.updateRule(topicPath, subscriptionPath, { ...getRuleResponse, ...ruleOptions - } - ); - return ruleResponse; + }); + return ruleResponse; + } } } -} -async function deleteEntity( - testEntityType: EntityType, - entityPath: string, - topicPath?: string, - subscriptionPath?: string -): Promise { - switch (testEntityType) { - case EntityType.QUEUE: { - const queueResponse = await serviceBusAtomManagementClient.deleteQueue(entityPath); - return queueResponse; - } - case EntityType.TOPIC: { - const topicResponse = await serviceBusAtomManagementClient.deleteTopic(entityPath); - return topicResponse; + async function deleteEntity( + testEntityType: EntityType, + entityPath: string, + topicPath?: string, + subscriptionPath?: string, + atomClient: ServiceBusAdministrationClient = serviceBusAtomManagementClient + ): Promise { + switch (testEntityType) { + case EntityType.QUEUE: { + const queueResponse = await atomClient.deleteQueue(entityPath); + return queueResponse; + } + case EntityType.TOPIC: { + const topicResponse = await atomClient.deleteTopic(entityPath); + return topicResponse; + } + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const subscriptionResponse = await atomClient.deleteSubscription(topicPath, entityPath); + return subscriptionResponse; + } + case EntityType.RULE: { + if (!topicPath || !subscriptionPath) { + throw new Error( + "TestError: Topic path AND subscription path must be passed when invoking tests on rules" + ); + } + const ruleResponse = await atomClient.deleteRule(topicPath, subscriptionPath, entityPath); + return ruleResponse; + } } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" + throw new Error("TestError: Unrecognized EntityType"); + } + + async function listEntities( + testEntityType: EntityType, + topicPath?: string, + subscriptionPath?: string, + skip?: number, + maxCount?: number + ): Promise { + switch (testEntityType) { + case EntityType.QUEUE: { + const queueResponse = await serviceBusAtomManagementClient["getQueues"]({ + skip, + maxCount + }); + return queueResponse; + } + case EntityType.TOPIC: { + const topicResponse = await serviceBusAtomManagementClient["getTopics"]({ + skip, + maxCount + }); + return topicResponse; + } + case EntityType.SUBSCRIPTION: { + if (!topicPath) { + throw new Error( + "TestError: Topic path must be passed when invoking tests on subscriptions" + ); + } + const subscriptionResponse = await serviceBusAtomManagementClient[ + "getSubscriptions" + ](topicPath, { skip, maxCount }); + return subscriptionResponse; + } + case EntityType.RULE: { + if (!topicPath || !subscriptionPath) { + throw new Error( + "TestError: Topic path AND subscription path must be passed when invoking tests on rules" + ); + } + const ruleResponse = await serviceBusAtomManagementClient["getRules"]( + topicPath, + subscriptionPath, + { skip, maxCount } ); + return ruleResponse; } - const subscriptionResponse = await serviceBusAtomManagementClient.deleteSubscription( - topicPath, - entityPath - ); - return subscriptionResponse; } - case EntityType.RULE: { - if (!topicPath || !subscriptionPath) { - throw new Error( - "TestError: Topic path AND subscription path must be passed when invoking tests on rules" - ); + throw new Error("TestError: Unrecognized EntityType"); + } + + describe("Premium Namespaces", () => { + const premiumConnectionString = getEnvVarValue("SERVICEBUS_CONNECTION_STRING_PREMIUM"); + let atomClient: ServiceBusAdministrationClient; + let entityNameWithmaxSize: { entityName: string; maxSize: number }; + before(function() { + if (!premiumConnectionString) { + this.skip(); } - const ruleResponse = await serviceBusAtomManagementClient.deleteRule( - topicPath, - subscriptionPath, - entityPath + atomClient = new ServiceBusAdministrationClient(premiumConnectionString); + }); + + function setEntityNameWithMaxSize(type: EntityType.QUEUE | EntityType.TOPIC, maxSize?: number) { + entityNameWithmaxSize = { + entityName: `${type}-${maxSize}`, + maxSize: !maxSize ? Math.ceil(1024 + Math.random() * (102400 - 1024)) : maxSize // If not provided, we'll give one that follows - "> 1024" & "< 102400" + }; + } + + function getRandomEntityType(): EntityType.QUEUE | EntityType.TOPIC { + return Math.random() > 0.5 ? EntityType.QUEUE : EntityType.TOPIC; + } + + async function verifyAndDeleteEntity(type: EntityType.QUEUE | EntityType.TOPIC) { + assert.equal( + (await getEntity(type, entityNameWithmaxSize.entityName, undefined, undefined, atomClient)) + .maxMessageSizeInKilobytes, + entityNameWithmaxSize.maxSize, + "Unexpected size returned with getEntity" ); - return ruleResponse; + await deleteEntity(type, entityNameWithmaxSize.entityName, undefined, undefined, atomClient); } - } - throw new Error("TestError: Unrecognized EntityType"); -} -async function listEntities( - testEntityType: EntityType, - topicPath?: string, - subscriptionPath?: string, - skip?: number, - maxCount?: number -): Promise { - switch (testEntityType) { - case EntityType.QUEUE: { - const queueResponse = await serviceBusAtomManagementClient["getQueues"]({ - skip, - maxCount + [getRandomEntityType()].forEach((type) => { + it(`MaxMessageSizeInKilobytes - create and get ${type}`, async () => { + setEntityNameWithMaxSize(type); + const options: CreateQueueOptions | CreateTopicOptions = { + maxMessageSizeInKilobytes: entityNameWithmaxSize.maxSize + }; + assert.equal( + ( + await createEntity( + type, + entityNameWithmaxSize.entityName, + undefined, + undefined, + true, + options, + options, + undefined, + undefined, + atomClient + ) + ).maxMessageSizeInKilobytes, + options.maxMessageSizeInKilobytes, + "Unexpected size returned with createEntity" + ); + await verifyAndDeleteEntity(type); }); - return queueResponse; - } - case EntityType.TOPIC: { - const topicResponse = await serviceBusAtomManagementClient["getTopics"]({ - skip, - maxCount + + it(`MaxMessageSizeInKilobytes - create and update ${type}`, async () => { + setEntityNameWithMaxSize(type); + const options: CreateQueueOptions | CreateTopicOptions = { + maxMessageSizeInKilobytes: entityNameWithmaxSize.maxSize + }; + await createEntity( + type, + entityNameWithmaxSize.entityName, + undefined, + undefined, + false, + undefined, + undefined, + undefined, + undefined, + atomClient + ); + assert.equal( + ( + await updateEntity( + type, + entityNameWithmaxSize.entityName, + undefined, + undefined, + true, + options, + options, + undefined, + undefined, + atomClient + ) + ).maxMessageSizeInKilobytes, + options.maxMessageSizeInKilobytes, + "Unexpected size returned with updateEntity" + ); + await verifyAndDeleteEntity(type); }); - return topicResponse; - } - case EntityType.SUBSCRIPTION: { - if (!topicPath) { - throw new Error( - "TestError: Topic path must be passed when invoking tests on subscriptions" + + it(`MaxMessageSizeInKilobytes - create ${type} (size < 1024) or (size > 102400) throws error`, async () => { + setEntityNameWithMaxSize( + type, + Math.random() > 0.5 + ? Math.ceil(Math.random() * 1023) // < 1024 + : Math.ceil(102400 + Math.random() * 1024) // > 102400 ); - } - const subscriptionResponse = await serviceBusAtomManagementClient[ - "getSubscriptions" - ](topicPath, { skip, maxCount }); - return subscriptionResponse; - } - case EntityType.RULE: { - if (!topicPath || !subscriptionPath) { - throw new Error( - "TestError: Topic path AND subscription path must be passed when invoking tests on rules" + const options: CreateQueueOptions | CreateTopicOptions = { + maxMessageSizeInKilobytes: entityNameWithmaxSize.maxSize + }; + let error; + try { + await createEntity( + type, + entityNameWithmaxSize.entityName, + undefined, + undefined, + true, + options, + options, + undefined, + undefined, + atomClient + ); + } catch (err) { + error = err; + } + assert.include( + error.message, + "value for 'MaxMessageSizeInKilobytes' must be between 1024 and 102400", + "Did not get the error message that says 'MaxMessageSizeInKilobytes' must be between 1024 and 102400" ); - } - const ruleResponse = await serviceBusAtomManagementClient["getRules"]( - topicPath, - subscriptionPath, - { skip, maxCount } - ); - return ruleResponse; - } - } - throw new Error("TestError: Unrecognized EntityType"); -} + }); + }); + }); +}); diff --git a/sdk/servicebus/service-bus/test/public/utils/envVarUtils.ts b/sdk/servicebus/service-bus/test/public/utils/envVarUtils.ts index 3e95ac97e6a2..4fc537f08f40 100644 --- a/sdk/servicebus/service-bus/test/public/utils/envVarUtils.ts +++ b/sdk/servicebus/service-bus/test/public/utils/envVarUtils.ts @@ -17,7 +17,7 @@ export enum EnvVarNames { /** * Utility to retrieve the environment variable value with given name. */ -function getEnvVarValue(name: string): string | undefined { +export function getEnvVarValue(name: string): string | undefined { if (isNode) { return process.env[name]; } else { diff --git a/sdk/servicebus/test-resources.json b/sdk/servicebus/test-resources.json index 0ff1cbbf2ba3..6e616407cba2 100644 --- a/sdk/servicebus/test-resources.json +++ b/sdk/servicebus/test-resources.json @@ -20,7 +20,9 @@ "apiVersion": "2017-04-01", "location": "[resourceGroup().location]", "authorizationRuleName": "[concat(parameters('baseName'), '/RootManageSharedAccessKey')]", - "serviceBusDataOwnerRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419')]" + "serviceBusDataOwnerRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419')]", + "baseNamePremium":"[concat(parameters('baseName'), 'premium')]", + "authorizationRuleNamePremium": "[concat(parameters('baseName'), 'premium', '/RootManageSharedAccessKey')]" }, "resources": [ { @@ -36,6 +38,35 @@ "zoneRedundant": false } }, + { + "type": "Microsoft.ServiceBus/namespaces", + "apiVersion": "2018-01-01-preview", + "name": "[variables('baseNamePremium')]", + "location": "[variables('location')]", + "sku": { + "name": "Premium", + "tier": "Premium" + }, + "properties": { + "zoneRedundant": false + } + }, + { + "type": "Microsoft.ServiceBus/namespaces/AuthorizationRules", + "apiVersion": "2015-08-01", + "name": "[variables('authorizationRuleNamePremium')]", + "location": "[variables('location')]", + "dependsOn": [ + "[resourceId('Microsoft.ServiceBus/namespaces', variables('baseNamePremium'))]" + ], + "properties": { + "rights": [ + "Listen", + "Manage", + "Send" + ] + } + }, { "type": "Microsoft.ServiceBus/namespaces/AuthorizationRules", "apiVersion": "2015-08-01", @@ -112,6 +143,10 @@ "type": "string", "value": "[listKeys(resourceId('Microsoft.ServiceBus/namespaces/authorizationRules', parameters('baseName'), 'RootManageSharedAccessKey'), variables('apiVersion')).primaryConnectionString]" }, + "SERVICEBUS_CONNECTION_STRING_PREMIUM": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.ServiceBus/namespaces/authorizationRules', variables('baseNamePremium'), 'RootManageSharedAccessKey'), variables('apiVersion')).primaryConnectionString]" + }, "SERVICEBUS_ENDPOINT": { "type": "string", "value": "[replace(reference(resourceId('Microsoft.ServiceBus/namespaces', parameters('baseName'))).serviceBusEndpoint, ':443/', '')]" @@ -125,4 +160,4 @@ "value": "testQueueWithSessions" } } -} \ No newline at end of file +}