Skip to content

Commit 98aff7f

Browse files
authored
[server] clean up DB tests (#18333)
1 parent 83205e7 commit 98aff7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+194
-269
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ jobs:
240240
$TEST \
241241
-Dversion=$VERSION \
242242
--docker-build-options network=host \
243+
--max-concurrent-tasks 1 \
243244
-DlocalAppVersion=$VERSION \
244245
-DSEGMENT_IO_TOKEN=$SEGMENT_IO_TOKEN \
245246
-DpublishToNPM="${PUBLISH_TO_NPM}" \

components/gitpod-db/.vscode/launch.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,15 @@
88
"DB_PORT": "23306",
99
"DB_ENCRYPTION_KEYS": "[{\"name\":\"general\",\"version\":1,\"primary\":true,\"material\":\"5vRrp0H4oRgdkPnX1qQcS54Q0xggr6iyho42IQ1rO+c=\"}]"
1010
},
11-
"name": "Run Mocha Test in Editor",
11+
"name": "Run all Tests - in Editor",
1212
"program": "${workspaceFolder}/node_modules/.bin/_mocha",
1313
"args": [
1414
"--opts",
1515
"${workspaceFolder}/mocha.opts",
1616
"--colors",
1717
"--timeout",
1818
"999999",
19-
"${file}",
20-
"-g",
21-
"${selectedText}"
19+
"${file}"
2220
],
2321
"internalConsoleOptions": "openOnSessionStart"
2422
}

components/gitpod-db/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"devDependencies": {
3636
"@testdeck/mocha": "^0.3.3",
3737
"@types/chai": "^4.2.2",
38+
"@types/mocha": "^2.2.45",
3839
"@types/mysql": "^2.15.0",
3940
"@types/uuid": "^8.3.1",
4041
"@typescript-eslint/eslint-plugin": "^4.5.0",

components/gitpod-db/src/auth-provider-entry.spec.db.ts

Lines changed: 53 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,30 @@
44
* See License.AGPL.txt in the project root for license information.
55
*/
66

7-
import { suite, test, timeout } from "@testdeck/mocha";
87
import { testContainer } from "./test-container";
98
import { TypeORM } from "./typeorm/typeorm";
10-
import { AuthProviderEntryDB } from ".";
119
import { DBAuthProviderEntry } from "./typeorm/entity/db-auth-provider-entry";
1210
import { DeepPartial } from "@gitpod/gitpod-protocol/lib/util/deep-partial";
13-
import * as chai from "chai";
14-
const expect = chai.expect;
11+
import { resetDB } from "./test/reset-db";
12+
import { AuthProviderEntryDB } from "./auth-provider-entry-db";
13+
import { expect } from "chai";
14+
import "mocha";
1515

16-
@suite(timeout(10000))
17-
export class AuthProviderEntryDBSpec {
18-
private readonly db = testContainer.get<AuthProviderEntryDB>(AuthProviderEntryDB);
16+
const container = testContainer.createChild();
1917

20-
// TODO(gpl) Since the upgrade to ts-node 10.4.0 establishing the inital connection takes up to 25s
21-
@timeout(30000)
22-
async before() {
23-
await this.clear();
24-
}
18+
describe("AuthProviderEntryDBSpec", async () => {
19+
let db: AuthProviderEntryDB;
2520

26-
async after() {
27-
await this.clear();
28-
}
21+
beforeEach(async () => {
22+
db = container.get<AuthProviderEntryDB>(AuthProviderEntryDB);
23+
});
2924

30-
async clear() {
31-
const typeorm = testContainer.get<TypeORM>(TypeORM);
32-
const manager = await typeorm.getConnection();
33-
console.log("before delete");
34-
await manager.getRepository(DBAuthProviderEntry).delete({});
35-
console.log("after delete");
36-
}
25+
afterEach(async () => {
26+
const typeorm = container.get<TypeORM>(TypeORM);
27+
await resetDB(typeorm);
28+
});
3729

38-
protected authProvider(ap: DeepPartial<DBAuthProviderEntry> = {}): DBAuthProviderEntry {
30+
function authProvider(ap: DeepPartial<DBAuthProviderEntry> = {}): DBAuthProviderEntry {
3931
const ownerId = "1234";
4032
const host = "github.com";
4133
return {
@@ -63,66 +55,63 @@ export class AuthProviderEntryDBSpec {
6355
};
6456
}
6557

66-
@test() public async testFindAll() {
67-
console.log("start findAll");
68-
const ap1 = this.authProvider({ id: "1", oauthRevision: "rev1" });
69-
const ap2 = this.authProvider({ id: "2", oauthRevision: "rev2" });
70-
await this.db.storeAuthProvider(ap1, false);
71-
await this.db.storeAuthProvider(ap2, false);
58+
it("should findAll", async () => {
59+
const ap1 = authProvider({ id: "1", oauthRevision: "rev1" });
60+
const ap2 = authProvider({ id: "2", oauthRevision: "rev2" });
61+
await db.storeAuthProvider(ap1, false);
62+
await db.storeAuthProvider(ap2, false);
7263

73-
const all = await this.db.findAll();
64+
const all = await db.findAll();
7465
expect(all, "findAll([])").to.deep.equal([ap1, ap2]);
75-
expect(await this.db.findAll([ap1.oauthRevision!, ap2.oauthRevision!]), "findAll([ap1, ap2])").to.be.empty;
76-
expect(await this.db.findAll([ap1.oauthRevision!]), "findAll([ap1])").to.deep.equal([ap2]);
77-
}
66+
expect(await db.findAll([ap1.oauthRevision!, ap2.oauthRevision!]), "findAll([ap1, ap2])").to.be.empty;
67+
expect(await db.findAll([ap1.oauthRevision!]), "findAll([ap1])").to.deep.equal([ap2]);
68+
}).timeout(30000); // this test is sometimes slow because it is the first one and ts-node needs to compile
7869

79-
@test() public async findAllHosts() {
80-
const ap1 = this.authProvider({ id: "1", oauthRevision: "rev1", host: "foo" });
81-
const ap2 = this.authProvider({ id: "2", oauthRevision: "rev2", host: "BAR" });
82-
await this.db.storeAuthProvider(ap1, false);
83-
await this.db.storeAuthProvider(ap2, false);
70+
it("should findAllHosts", async () => {
71+
const ap1 = authProvider({ id: "1", oauthRevision: "rev1", host: "foo" });
72+
const ap2 = authProvider({ id: "2", oauthRevision: "rev2", host: "BAR" });
73+
await db.storeAuthProvider(ap1, false);
74+
await db.storeAuthProvider(ap2, false);
8475

85-
const all = await this.db.findAllHosts();
76+
const all = await db.findAllHosts();
8677
expect(all, "findAllHosts([])").to.deep.equal(["foo", "bar"]);
87-
}
78+
});
8879

89-
@test() public async oauthRevision() {
90-
const ap = this.authProvider({ id: "1" });
91-
await this.db.storeAuthProvider(ap, true);
80+
it("should oauthRevision", async () => {
81+
const ap = authProvider({ id: "1" });
82+
await db.storeAuthProvider(ap, true);
9283

93-
const loadedAp = await this.db.findByHost(ap.host);
84+
const loadedAp = await db.findByHost(ap.host);
9485
expect(loadedAp, "findByHost()").to.deep.equal(ap);
9586
expect(loadedAp?.oauthRevision, "findByHost()").to.equal(
9687
"3d1390670fd19c27157d046960c3d7c46df81db642302dea1a9fe86cf0594361",
9788
);
98-
}
89+
});
9990

100-
@test() public async findByOrgId() {
101-
const ap1 = this.authProvider({ id: "1", organizationId: "O1", host: "H1" });
102-
const ap2 = this.authProvider({ id: "2", organizationId: "O1", host: "H2" });
103-
const ap3 = this.authProvider({ id: "3", organizationId: "O2", host: "H1" });
91+
it("should findByOrgId()", async () => {
92+
const ap1 = authProvider({ id: "1", organizationId: "O1", host: "H1" });
93+
const ap2 = authProvider({ id: "2", organizationId: "O1", host: "H2" });
94+
const ap3 = authProvider({ id: "3", organizationId: "O2", host: "H1" });
10495

105-
await this.db.storeAuthProvider(ap1, false);
106-
await this.db.storeAuthProvider(ap2, false);
107-
await this.db.storeAuthProvider(ap3, false);
96+
await db.storeAuthProvider(ap1, false);
97+
await db.storeAuthProvider(ap2, false);
98+
await db.storeAuthProvider(ap3, false);
10899

109-
const results = await this.db.findByOrgId("O1");
100+
const results = await db.findByOrgId("O1");
110101
expect(results.length).to.equal(2);
111102
expect(results).to.deep.contain(ap1);
112103
expect(results).to.deep.contain(ap2);
113-
}
104+
});
114105

115-
@test() public async findByUserId() {
116-
const ap1 = this.authProvider({ id: "1", ownerId: "owner1" });
117-
const ap2 = this.authProvider({ id: "2", ownerId: "owner1", organizationId: "org1" });
106+
it("should findByUserId", async () => {
107+
const ap1 = authProvider({ id: "1", ownerId: "owner1" });
108+
const ap2 = authProvider({ id: "2", ownerId: "owner1", organizationId: "org1" });
118109

119-
await this.db.storeAuthProvider(ap1, false);
120-
await this.db.storeAuthProvider(ap2, false);
110+
await db.storeAuthProvider(ap1, false);
111+
await db.storeAuthProvider(ap2, false);
121112

122-
const results = await this.db.findByUserId("owner1");
113+
const results = await db.findByUserId("owner1");
123114
expect(results.length).to.equal(1);
124115
expect(results).to.deep.contain(ap1);
125-
}
126-
}
127-
128-
module.exports = AuthProviderEntryDBSpec;
116+
});
117+
});

components/gitpod-db/src/blocked-repository-db.spec.db.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { suite, test, timeout } from "@testdeck/mocha";
1111
import { testContainer } from "./test-container";
1212
import { TypeORMBlockedRepositoryDBImpl } from "./typeorm/blocked-repository-db-impl";
1313
import { TypeORM } from "./typeorm/typeorm";
14-
import { DBBlockedRepository } from "./typeorm/entity/db-blocked-repository";
14+
import { resetDB } from "./test/reset-db";
1515

1616
@suite
1717
class BlockedRepositoryDBSpec {
@@ -79,8 +79,7 @@ class BlockedRepositoryDBSpec {
7979

8080
async wipeRepo() {
8181
const typeorm = testContainer.get<TypeORM>(TypeORM);
82-
const manager = await typeorm.getConnection();
83-
await manager.getRepository(DBBlockedRepository).delete({});
82+
await resetDB(typeorm);
8483
}
8584
}
8685

components/gitpod-db/src/container-module.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,20 @@ import { LinkedInProfileDBImpl } from "./typeorm/linked-in-profile-db-impl";
4646
import { LinkedInProfileDB } from "./linked-in-profile-db";
4747
import { DataCache, DataCacheNoop } from "./data-cache";
4848
import { TracingManager } from "@gitpod/gitpod-protocol/lib/util/tracing";
49+
import { EncryptionService, GlobalEncryptionService } from "@gitpod/gitpod-protocol/lib/encryption/encryption-service";
4950

5051
// THE DB container module that contains all DB implementations
5152
export const dbContainerModule = (cacheClass = DataCacheNoop) =>
5253
new ContainerModule((bind, unbind, isBound, rebind, unbindAsync, onActivation, onDeactivation) => {
5354
bind(Config).toSelf().inSingletonScope();
54-
bind(TypeORM).toSelf().inSingletonScope();
55+
bind(TypeORM)
56+
.toSelf()
57+
.inSingletonScope()
58+
.onActivation((ctx, orm) => {
59+
// HACK we need to initialize the global encryption service.
60+
GlobalEncryptionService.encryptionService = ctx.container.get(EncryptionService);
61+
return orm;
62+
});
5563
bind(DBWithTracing).toSelf().inSingletonScope();
5664
bind(TracingManager).toSelf().inSingletonScope();
5765
bind(DataCache).to(cacheClass).inSingletonScope();

components/gitpod-db/src/email-domain-filter-db.spec.db.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { suite, test, timeout } from "@testdeck/mocha";
99
import { testContainer } from "./test-container";
1010
import { TypeORM } from "./typeorm/typeorm";
1111
import { EmailDomainFilterDB } from "./email-domain-filter-db";
12-
import { DBEmailDomainFilterEntry } from "./typeorm/entity/db-email-domain-filter-entry";
12+
import { resetDB } from "./test/reset-db";
1313
const expect = chai.expect;
1414

1515
@suite
@@ -27,9 +27,7 @@ export class EmailDomainFilterDBSpec {
2727
}
2828

2929
protected async clear() {
30-
const connection = await this.typeORM.getConnection();
31-
const manager = connection.manager;
32-
await manager.clear(DBEmailDomainFilterEntry);
30+
await resetDB(this.typeORM);
3331
}
3432

3533
@test public async filterSimple() {

components/gitpod-db/src/project-db.spec.db.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@
44
* See License.AGPL.txt in the project root for license information.
55
*/
66

7-
import * as chai from "chai";
8-
const expect = chai.expect;
7+
import { Project } from "@gitpod/gitpod-protocol";
98
import { suite, test } from "@testdeck/mocha";
10-
import { TypeORM } from "./typeorm/typeorm";
11-
import { TypeORMUserDBImpl } from "./typeorm/user-db-impl";
9+
import * as chai from "chai";
1210
import { testContainer } from "./test-container";
11+
import { resetDB } from "./test/reset-db";
1312
import { ProjectDBImpl } from "./typeorm/project-db-impl";
14-
import { DBProject } from "./typeorm/entity/db-project";
15-
import { DBUser } from "./typeorm/entity/db-user";
16-
import { Project } from "@gitpod/gitpod-protocol";
13+
import { TypeORM } from "./typeorm/typeorm";
14+
import { TypeORMUserDBImpl } from "./typeorm/user-db-impl";
15+
const expect = chai.expect;
1716

1817
@suite
1918
class ProjectDBSpec {
@@ -30,9 +29,7 @@ class ProjectDBSpec {
3029

3130
async wipeRepo() {
3231
const typeorm = testContainer.get<TypeORM>(TypeORM);
33-
const manager = await typeorm.getConnection();
34-
await manager.getRepository(DBProject).delete({});
35-
await manager.getRepository(DBUser).delete({});
32+
await resetDB(typeorm);
3633
}
3734

3835
@test()

components/gitpod-db/src/team-db.spec.db.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@ import { testContainer } from "./test-container";
1313
import { TeamDBImpl } from "./typeorm/team-db-impl";
1414
import { TypeORMUserDBImpl } from "./typeorm/user-db-impl";
1515
import { TypeORM } from "./typeorm/typeorm";
16-
import { DBTeam } from "./typeorm/entity/db-team";
17-
import { DBTeamMembership } from "./typeorm/entity/db-team-membership";
18-
import { DBUser } from "./typeorm/entity/db-user";
19-
import { DBIdentity } from "./typeorm/entity/db-identity";
2016
import { Connection } from "typeorm";
17+
import { resetDB } from "./test/reset-db";
2118

2219
@suite
2320
class TeamDBSpec {
@@ -34,12 +31,7 @@ class TeamDBSpec {
3431

3532
async wipeRepo() {
3633
const typeorm = testContainer.get<TypeORM>(TypeORM);
37-
const manager = await typeorm.getConnection();
38-
await manager.getRepository(DBTeam).delete({});
39-
await manager.getRepository(DBTeamMembership).delete({});
40-
await manager.getRepository(DBUser).delete({});
41-
await manager.getRepository(DBIdentity).delete({});
42-
await manager.query("delete from d_b_oidc_client_config;");
34+
await resetDB(typeorm);
4335
}
4436

4537
@test(timeout(10000))
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { DBUser } from "../typeorm/entity/db-user";
8+
import { TypeORM } from "../typeorm/typeorm";
9+
import { isBuiltinUser } from "../user-db";
10+
11+
export async function resetDB(typeorm: TypeORM) {
12+
const conn = await typeorm.getConnection();
13+
const users = await conn.getRepository(DBUser).find();
14+
// delete all users except the builtin users
15+
conn.getRepository(DBUser).remove(users.filter((u) => !isBuiltinUser(u.id)));
16+
17+
const deletions = conn.entityMetadatas
18+
.filter((meta) => meta.tableName !== "d_b_user")
19+
.map((meta) => {
20+
return conn.getRepository(meta.name).clear();
21+
});
22+
23+
await Promise.all([
24+
// delete all other entities
25+
...deletions,
26+
27+
// we don't have a typeorm entity for this table
28+
conn.query("DELETE FROM d_b_oidc_client_config;"),
29+
]);
30+
}

components/gitpod-db/src/typeorm/auth-code-repository-db.spec.db.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import { AuthCodeRepositoryDB } from "./auth-code-repository-db";
1010
import { UserDB } from "../user-db";
1111
import { DBOAuthAuthCodeEntry } from "./entity/db-oauth-auth-code";
1212
import { TypeORM } from "./typeorm";
13-
import { DBUser } from "./entity/db-user";
1413
import * as chai from "chai";
1514
import { User } from "@gitpod/gitpod-protocol";
15+
import { resetDB } from "../test/reset-db";
1616
const expect = chai.expect;
1717

1818
@suite(timeout(10000))
@@ -30,9 +30,7 @@ export class AuthCodeRepositoryDBSpec {
3030

3131
async wipeRepo() {
3232
const typeorm = testContainer.get<TypeORM>(TypeORM);
33-
const manager = await typeorm.getConnection();
34-
await manager.getRepository(DBOAuthAuthCodeEntry).delete({});
35-
await manager.getRepository(DBUser).delete({});
33+
await resetDB(typeorm);
3634
}
3735

3836
@test()

components/gitpod-db/src/typeorm/code-sync-resource-db.spec.db.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { suite, test, timeout } from "@testdeck/mocha";
1010
import { testContainer } from "../test-container";
1111
import { CodeSyncResourceDB } from "./code-sync-resource-db";
1212
import { IUserDataManifest, SyncResource } from "./entity/db-code-sync-resource";
13+
import { resetDB } from "../test/reset-db";
14+
import { TypeORM } from "./typeorm";
1315
const expect = chai.expect;
1416

1517
@suite(timeout(10000))
@@ -23,8 +25,7 @@ export class CodeSyncResourceDBSpec {
2325
}
2426

2527
async after(): Promise<void> {
26-
await this.db.deleteSettingsSyncResources(this.userId, () => Promise.resolve());
27-
await this.db.deleteCollection(this.userId, undefined, () => Promise.resolve());
28+
await resetDB(testContainer.get<TypeORM>(TypeORM));
2829
}
2930

3031
@test()

0 commit comments

Comments
 (0)