Skip to content

Commit

Permalink
test: 💍 use amqp for ticker reservation tests
Browse files Browse the repository at this point in the history
  • Loading branch information
polymath-eric committed Jan 17, 2024
1 parent a414570 commit 8b8cb1d
Show file tree
Hide file tree
Showing 16 changed files with 319 additions and 48 deletions.
20 changes: 19 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ services:
- vault
restart: 'no'

artemis:
image: apache/activemq-artemis:2.31.2
ports:
- 8161:8161 # Web Server
- 5672:5672 # AMQP
volumes:
- './docker/broker.xml:/var/lib/artemis-instance/etc-override/broker.xml'
environment:
ARTEMIS_USERNAME: artemis
ARTEMIS_PASSWORD: artemis
AMQ_EXTRA_ARGS: "--nio" # "aio" offers better performance, but less platforms support it

alice:
healthcheck:
test: "timeout 5 bash -c 'cat < /dev/null > /dev/tcp/localhost/9933' && exit 0 || exit 1"
Expand Down Expand Up @@ -53,7 +65,7 @@ services:
test: curl --fail http://localhost:3000/meta || exit 1
interval: 20s
retries: 30
start_period: 20s
start_period: 40s
timeout: 20s
restart: unless-stopped
depends_on:
Expand Down Expand Up @@ -112,6 +124,8 @@ services:
condition: service_started
subquery:
condition: service_healthy
artemis:
condition: service_started
ports:
- ${REST_PORT:-3004}:3000
environment:
Expand All @@ -121,3 +135,7 @@ services:
VAULT_TOKEN: 'root'
AUTH_STRATEGY: 'open'
DEVELOPER_UTILS: 'true'
ARTEMIS_HOST: artemis
ARTEMIS_USERNAME: artemis
ARTEMIS_PASSWORD: artemis
ARTEMIS_PORT: 5672
145 changes: 145 additions & 0 deletions docker/broker.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?xml version='1.0'?>

<configuration xmlns="urn:activemq"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xi="http://www.w3.org/2001/XInclude"
xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">

<core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:activemq:core ">

<name>0.0.0.0</name>


<persistence-enabled>true</persistence-enabled>

<!-- It is recommended to keep this value as 1, maximizing the number of records stored about redeliveries.
However if you must preserve state of individual redeliveries, you may increase this value or set it to -1 (infinite). -->
<max-redelivery-records>1</max-redelivery-records>

<acceptors>

<!-- useEpoll means: it will use Netty epoll if you are on a system (Linux) that supports it -->
<!-- amqpCredits: The number of credits sent to AMQP producers -->
<!-- amqpLowCredits: The server will send the # credits specified at amqpCredits at this low mark -->
<!-- amqpDuplicateDetection: If you are not using duplicate detection, set this to false
as duplicate detection requires applicationProperties to be parsed on the server. -->
<!-- amqpMinLargeMessageSize: Determines how many bytes are considered large, so we start using files to hold their data.
default: 102400, -1 would mean to disable large message control -->

<!-- Note: If an acceptor needs to be compatible with HornetQ and/or Artemis 1.x clients add
"anycastPrefix=jms.queue.;multicastPrefix=jms.topic." to the acceptor url.
See https://issues.apache.org/jira/browse/ARTEMIS-1644 for more information. -->


<!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic.-->
<acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpMinLargeMessageSize=102400;amqpDuplicateDetection=true</acceptor>



</acceptors>


<security-settings>
<security-setting match="#">
<permission type="createNonDurableQueue" roles="amq"/>
<permission type="deleteNonDurableQueue" roles="amq"/>
<permission type="createDurableQueue" roles="amq"/>
<permission type="deleteDurableQueue" roles="amq"/>
<permission type="createAddress" roles="amq"/>
<permission type="deleteAddress" roles="amq"/>
<permission type="consume" roles="amq"/>
<permission type="browse" roles="amq"/>
<permission type="send" roles="amq"/>
<!-- we need this otherwise ./artemis data imp wouldn't work -->
<permission type="manage" roles="amq"/>
</security-setting>
</security-settings>

<address-settings>
<address-setting match="activemq.management#">
<dead-letter-address>DLQ</dead-letter-address>
<expiry-address>ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
<!-- with -1 only the global-max-size is in use for limiting -->
<max-size-bytes>-1</max-size-bytes>
<message-counter-history-day-limit>10</message-counter-history-day-limit>
<address-full-policy>PAGE</address-full-policy>
<auto-create-queues>false</auto-create-queues>
<auto-create-addresses>false</auto-create-addresses>
</address-setting>
<!--default for catch all-->
<address-setting match="#">
<dead-letter-address>DLQ</dead-letter-address>
<expiry-address>ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
<max-delivery-attempts>3</max-delivery-attempts>

<message-counter-history-day-limit>10</message-counter-history-day-limit>
<address-full-policy>PAGE</address-full-policy>
<auto-create-queues>false</auto-create-queues>
<auto-create-addresses>false</auto-create-addresses>
<auto-delete-queues>false</auto-delete-queues>
<auto-delete-addresses>false</auto-delete-addresses>
</address-setting>
</address-settings>

<addresses>
<address name="DLQ">
<anycast>
<queue name="DLQ" />
</anycast>
</address>

<address name="ExpiryQueue">
<anycast>
<queue name="ExpiryQueue" />
</anycast>
</address>

<address name="Requests">
<anycast>
<queue name="Requests"></queue>
</anycast>
</address>

<address name="Signatures">
<anycast>
<queue name="Signatures"></queue>
</anycast>
</address>

<address name="Finalizations">
<multicast>
</multicast>
</address>

<address name="EventsLog">
<anycast>
<queue name="EventsLog"></queue>
</anycast>
</address>
</addresses>

<diverts>
<divert name="RequestsRecorder">
<address>Requests</address>
<forwarding-address>EventsLog</forwarding-address>
<exclusive>false</exclusive>
</divert>

<divert name="SignaturesRecorder">
<address>Signatures</address>
<forwarding-address>EventsLog</forwarding-address>
<exclusive>false</exclusive>
</divert>

<divert name="FinalizationsRecorder">
<address>Finalizations</address>
<forwarding-address>EventsLog</forwarding-address>
<exclusive>false</exclusive>
</divert>
</diverts>

</core>
</configuration>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"prettier": "2.3.2",
"prettier-eslint": "13.0.0",
"prettier-eslint-cli": "5.0.1",
"rhea-promise": "^3.0.1",
"rimraf": "^4.1.2",
"semantic-release": "17.4.4",
"ts-jest": "27.0.4",
Expand Down
70 changes: 70 additions & 0 deletions src/__tests__/rest/amqp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { EventContext, ReceiverEvents } from 'rhea-promise';

import { expectBasicTxInfo, getRheaConnection } from '~/__tests__/rest/utils';

Check warning on line 3 in src/__tests__/rest/amqp.ts

View workflow job for this annotation

GitHub Actions / Linting

'expectBasicTxInfo' is defined but never used
import { AMQPTopics } from '~/consts';
import { TestFactory } from '~/helpers';
import { RestClient } from '~/rest';
import { createAssetParams } from '~/rest/assets/params';
import { ProcessMode } from '~/rest/common';
import { Identity } from '~/rest/identities/interfaces';

const handles = ['issuer', 'investor'];
let factory: TestFactory;

describe('Create and trading an Asset', () => {
let restClient: RestClient;
let signer: string;
let issuer: Identity;
let ticker: string;

beforeAll(async () => {
factory = await TestFactory.create({ handles });
({ restClient } = factory);
issuer = factory.getSignerIdentity(handles[0]);

ticker = factory.nextTicker();
signer = issuer.signer;
});

afterAll(async () => {
await factory.close();
});

it('should create and fetch the Asset', async (done) => {
const assetParams = createAssetParams(ticker, {
options: { processMode: ProcessMode.AMQP, signer },
});

const connection = await getRheaConnection();
const receiver = await connection.createReceiver({
name: 'AMQP-test',
credit_window: 1,
autoaccept: true,
source: {
address: AMQPTopics.Finalizations,
distribution_mode: 'copy',
},
});

const txData = (await restClient.assets.createAsset(assetParams)) as any;

Check warning on line 49 in src/__tests__/rest/amqp.ts

View workflow job for this annotation

GitHub Actions / Linting

Unexpected any. Specify a different type

expect(txData).toMatchObject({
payload: expect.objectContaining({
method: expect.any(String),
}),
metadata: {
internalTxId: expect.any(String),
},
});

const messageId = txData.metadata.internalTxId;
console.log('waiting for ', { messageId });

receiver.on(ReceiverEvents.message, async (context: EventContext) => {
if (context.message) {
console.log('got message', context.message);
done();
}
});
});
});
6 changes: 3 additions & 3 deletions src/__tests__/rest/assets/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expectBasicTxInfo } from '~/__tests__/rest/utils';
import { TestFactory } from '~/helpers';
import { RestClient } from '~/rest';
import { createAssetParams, setAssetDocumentParams } from '~/rest/assets';
import { Mode } from '~/rest/common';
import { ProcessMode } from '~/rest/common';
import { Identity } from '~/rest/identities/interfaces';

const handles = ['issuer'];
Expand All @@ -24,7 +24,7 @@ describe('AssetDocument', () => {
signer = issuer.signer;

assetParams = createAssetParams(asset, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
await restClient.assets.createAsset(assetParams);
});
Expand All @@ -34,7 +34,7 @@ describe('AssetDocument', () => {
});

it('should set Asset Documents', async () => {
const params = setAssetDocumentParams({ options: { processMode: Mode.Submit, signer } });
const params = setAssetDocumentParams({ options: { processMode: ProcessMode.Submit, signer } });
const txData = await restClient.assets.setDocuments(asset, params);

expect(txData).toMatchObject({
Expand Down
12 changes: 6 additions & 6 deletions src/__tests__/rest/assets/redeem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expectBasicTxInfo } from '~/__tests__/rest/utils';
import { TestFactory } from '~/helpers';
import { RestClient } from '~/rest';
import { createAssetParams, redeemTokenParams } from '~/rest/assets';
import { Mode } from '~/rest/common';
import { ProcessMode } from '~/rest/common';
import { Identity } from '~/rest/identities/interfaces';
import { moveAssetParams, portfolioParams } from '~/rest/portfolios';

Expand All @@ -25,7 +25,7 @@ describe('Redeem', () => {
signer = issuer.signer;

assetParams = createAssetParams(asset, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
await restClient.assets.createAsset(assetParams);
});
Expand All @@ -35,7 +35,7 @@ describe('Redeem', () => {
});

it('should redeem tokens from default Portfolio', async () => {
const params = redeemTokenParams('0', { options: { processMode: Mode.Submit, signer } });
const params = redeemTokenParams('0', { options: { processMode: ProcessMode.Submit, signer } });
const txData = await restClient.assets.redeem(asset, params);

expect(txData).toMatchObject({
Expand All @@ -52,18 +52,18 @@ describe('Redeem', () => {
it('should redeem tokens from specified Portfolio', async () => {
const portfolioName = factory.nextPortfolio();
const createPortfolioParams = portfolioParams(portfolioName, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
const result = await restClient.portfolios.create(createPortfolioParams);
const createdPortfolio = result.portfolio.id;

const moveFundParams = moveAssetParams(asset, '0', createdPortfolio, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
await restClient.portfolios.moveFunds(issuer.did, moveFundParams);

const params = redeemTokenParams(createdPortfolio, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
const txData = await restClient.assets.redeem(asset, params);

Expand Down
12 changes: 6 additions & 6 deletions src/__tests__/rest/createAndTrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expectBasicTxInfo } from '~/__tests__/rest/utils';
import { TestFactory } from '~/helpers';
import { RestClient } from '~/rest';
import { createAssetParams } from '~/rest/assets/params';
import { Mode } from '~/rest/common';
import { ProcessMode } from '~/rest/common';
import { complianceRestrictionParams } from '~/rest/compliance';
import { Identity } from '~/rest/identities/interfaces';
import { fungibleInstructionParams, venueParams } from '~/rest/settlements';
Expand All @@ -28,7 +28,7 @@ describe('Create and trading an Asset', () => {
signer = issuer.signer;

assetParams = createAssetParams(ticker, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
});

Expand Down Expand Up @@ -58,7 +58,7 @@ describe('Create and trading an Asset', () => {

it('should create compliance rules for the Asset', async () => {
const params = complianceRestrictionParams(ticker, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
const txData = await restClient.compliance.createRestriction(ticker, params);

Expand All @@ -84,7 +84,7 @@ describe('Create and trading an Asset', () => {
let venueId: string;
it('should create a Venue to trade the Asset', async () => {
const params = venueParams({
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
const txData = await restClient.settlements.createVenue(params);

Expand All @@ -106,7 +106,7 @@ describe('Create and trading an Asset', () => {
const sender = issuer.did;
const receiver = investor.did;
const params = fungibleInstructionParams(ticker, sender, receiver, {
options: { processMode: Mode.Submit, signer },
options: { processMode: ProcessMode.Submit, signer },
});
const instructionData = await restClient.settlements.createInstruction(venueId, params);

Expand All @@ -130,7 +130,7 @@ describe('Create and trading an Asset', () => {
expect(pendingInstructionId).not.toBeUndefined();

const affirmResult = await restClient.settlements.affirmInstruction(pendingInstructionId, {
options: { processMode: Mode.Submit, signer: investor.signer },
options: { processMode: ProcessMode.Submit, signer: investor.signer },
});

expect(affirmResult).toMatchObject({
Expand Down
Loading

0 comments on commit 8b8cb1d

Please sign in to comment.