Skip to content

Commit 91082ba

Browse files
committed
Begin integration test suite for appservice.
1 parent 62f9f17 commit 91082ba

File tree

7 files changed

+114
-3
lines changed

7 files changed

+114
-3
lines changed

.github/workflows/mjolnir.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,25 @@ jobs:
5656
run: RUST_LOG=debug,hyper=info,rusttls=info mx-tester run
5757
- name: Cleanup
5858
run: mx-tester down
59+
appservice-integration:
60+
name: Application Service Integration tests
61+
runs-on: ubuntu-latest
62+
timeout-minutes: 30
63+
steps:
64+
- uses: actions/checkout@v3
65+
- uses: actions/setup-node@v3
66+
with:
67+
node-version: '16'
68+
- name: Fetch and build mx-tester (cached across runs)
69+
uses: baptiste0928/cargo-install@v1
70+
with:
71+
crate: mx-tester
72+
version: "0.3.3"
73+
- name: Setup image
74+
run: RUST_LOG=debug,hyper=info,rusttls=info mx-tester build up
75+
- name: Setup dependencies
76+
run: yarn install
77+
- name: Run tests
78+
run: yarn test:appservice:integration
79+
- name: Cleanup
80+
run: mx-tester down

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"start:dev": "yarn build && node --async-stack-traces lib/index.js",
1515
"test": "ts-mocha --project ./tsconfig.json test/commands/**/*.ts",
1616
"test:integration": "NODE_ENV=harness ts-mocha --async-stack-traces --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json \"test/integration/**/*Test.ts\"",
17+
"test:appservice:integration": "NODE_ENV=harness ts-mocha --async-stack-traces --exit --timeout 300000 --project ./tsconfig.json \"test/appservice/integration/**/*Test.ts\"",
1718
"test:manual": "NODE_ENV=harness ts-node test/integration/manualLaunchScript.ts",
1819
"version": "sed -i '/# version automated/s/[0-9][0-9]*\\.[0-9][0-9]*\\.[0-9][0-9]*/'$npm_package_version'/' synapse_antispam/setup.py && git add synapse_antispam/setup.py && cat synapse_antispam/setup.py"
1920
},

src/appservice/AppService.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ export class MjolnirAppService {
2727

2828
private constructor(
2929
public readonly config: IConfig,
30-
private readonly bridge: Bridge,
30+
public readonly bridge: Bridge,
3131
private readonly mjolnirManager: MjolnirManager,
3232
private readonly accessControl: AccessControl,
33+
private readonly dataStore: DataStore,
3334
) {
3435
this.api = new Api(config.homeserver.url, mjolnirManager);
3536
}
@@ -56,7 +57,8 @@ export class MjolnirAppService {
5657
config,
5758
bridge,
5859
mjolnirManager,
59-
accessControl
60+
accessControl,
61+
dataStore
6062
);
6163
bridge.opts.controller = {
6264
onUserQuery: appService.onUserQuery.bind(appService),
@@ -89,12 +91,17 @@ export class MjolnirAppService {
8991
this.mjolnirManager.onEvent(request, context);
9092
}
9193

92-
private async start(port: number) {
94+
public async start(port: number) {
9395
console.log("Matrix-side listening on port %s", port);
9496
this.api.start(this.config.webAPI.port);
9597
await this.bridge.listen(port);
9698
}
9799

100+
public async close(): Promise<void> {
101+
await this.bridge.close();
102+
await this.dataStore.close();
103+
}
104+
98105
public static generateRegistration(reg: AppServiceRegistration, callback: (finalRegisration: AppServiceRegistration) => void) {
99106
reg.setId(AppServiceRegistration.generateToken());
100107
reg.setHomeserverToken(AppServiceRegistration.generateToken());

src/appservice/datastore.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export interface MjolnirRecord {
99
export interface DataStore {
1010
init(): Promise<void>;
1111

12+
close(): Promise<void>;
13+
1214
list(): Promise<MjolnirRecord[]>;
1315

1416
store(mjolnirRecord: MjolnirRecord): Promise<void>;
@@ -29,6 +31,10 @@ export class PgDataStore implements DataStore {
2931
await this.pgClient.connect();
3032
}
3133

34+
public async close(): Promise<void> {
35+
await this.pgClient.end()
36+
}
37+
3238
public async list(): Promise<MjolnirRecord[]> {
3339
const result = await this.pgClient.query<MjolnirRecord>("SELECT local_part, owner, management_room FROM mjolnir");
3440

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { readTestConfig, setupHarness } from "../utils/harness";
2+
import { newTestUser } from "../../integration/clientHelper";
3+
import { getFirstReply } from "../../integration/commands/commandUtils";
4+
import { MatrixClient } from "matrix-bot-sdk";
5+
import { MjolnirAppService } from "../../../src/appservice/AppService";
6+
import PolicyList from "../../../src/models/PolicyList";
7+
import { CreateEvent } from "matrix-bot-sdk";
8+
9+
interface Context extends Mocha.Context {
10+
user?: MatrixClient,
11+
appservice?: MjolnirAppService
12+
}
13+
14+
afterEach(function(this: Context) {
15+
this.user?.stop();
16+
// something still runs, and i'm not sure what? -- ignoring with --exit.
17+
this.appservice?.close();
18+
});
19+
20+
async function isPolicyRoom(user: MatrixClient, roomId: string): Promise<boolean> {
21+
const createEvent = new CreateEvent(await user.getRoomStateEvent(roomId, "m.room.create", ""));
22+
return PolicyList.ROOM_TYPE_VARIANTS.includes(createEvent.type);
23+
}
24+
25+
describe("Test that the app service can provision a mjolnir on invite of the appservice bot", function () {
26+
it("", async function (this: Context) {
27+
const config = readTestConfig();
28+
this.appservice = await setupHarness();
29+
// create a user
30+
const user = await newTestUser(config.homeserver.url, { name: { contains: "test" } });
31+
const roomWeWantProtecting = await user.createRoom();
32+
// have the user invite the appservice bot
33+
this.user = user;
34+
const roomsInvitedTo: string[] = [];
35+
await new Promise(async resolve => {
36+
user.on('room.invite', (roomId: string) => {
37+
roomsInvitedTo.push(roomId)
38+
// the appservice should invite it to a policy room and a management room.
39+
if (roomsInvitedTo.length === 2) {
40+
resolve(null);
41+
}
42+
});
43+
await user.start();
44+
await user.inviteUser(this.appservice!.bridge.getBot().getUserId(), roomWeWantProtecting);
45+
});
46+
await Promise.all(roomsInvitedTo.map(roomId => user.joinRoom(roomId)));
47+
const managementRoomId = roomsInvitedTo.filter(async roomId => !(await isPolicyRoom(user, roomId)))[0];
48+
await getFirstReply(user, managementRoomId, () => {
49+
return user.sendMessage(managementRoomId, { body: `!mjolnir status`, msgtype: 'm.text' });
50+
})
51+
})
52+
})

test/appservice/utils/harness.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import path from "path";
2+
import { MjolnirAppService } from "../../../src/appservice/AppService";
3+
import { ensureAliasedRoomExists } from "../../integration/mjolnirSetupUtils";
4+
import { read as configRead, IConfig } from "../../../src/appservice/config/config";
5+
import { PgDataStore } from "../../../src/appservice/datastore";
6+
import { newTestUser } from "../../integration/clientHelper";
7+
8+
export function readTestConfig(): IConfig {
9+
return configRead(path.join(__dirname, "../../../src/appservice/config/config.harness.yaml"));
10+
}
11+
12+
// FIXME: do we need to tear these down? Well yes.
13+
export async function setupHarness(): Promise<MjolnirAppService> {
14+
const config = readTestConfig();
15+
const utilityUser = await newTestUser(config.homeserver.url, { name: { contains: "utility" }});
16+
await ensureAliasedRoomExists(utilityUser, config.accessControlList);
17+
const dataStore = new PgDataStore(config.db.connectionString);
18+
await dataStore.init();
19+
const appservice = await MjolnirAppService.makeMjolnirAppService(config, dataStore);
20+
await appservice.start(9000);
21+
return appservice;
22+
}

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
},
2222
"include": [
2323
"./src/**/*",
24+
"./test/appservice/*",
2425
"./test/integration/manualLaunchScript.ts",
2526
"./test/integration/roomMembersTest.ts",
2627
"./test/integration/banListTest.ts",

0 commit comments

Comments
 (0)