Skip to content

Commit 40e8e94

Browse files
authored
Merge pull request #7 from herculesinc/test
[ #154578064 ] - some updates
2 parents adf1fe3 + f352450 commit 40e8e94

File tree

6 files changed

+275
-141
lines changed

6 files changed

+275
-141
lines changed

bin/lib/Database.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/Database.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Logger, buildLogger, DbLogger } from './util';
1010

1111
// MODULE VARIABLES
1212
// ================================================================================================
13-
const ERROR_EVENT = 'error';
13+
export const ERROR_EVENT = 'error';
1414

1515
// INTERFACES
1616
// ================================================================================================

lib/Pool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface PoolOptions {
2020
connectionTimeout? : number;
2121
}
2222

23-
const enum PoolState {
23+
export const enum PoolState {
2424
active = 2, closing = 3, closed = 4
2525
}
2626

tests/database.spec.ts

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
import * as os from 'os';
2+
import {exec} from 'child_process';
3+
import {expect} from 'chai';
4+
5+
import {Database, ERROR_EVENT} from '../lib/Database';
6+
import {Session} from '../lib/Session';
7+
import {PoolState} from '../lib/Pool';
8+
import {wait} from './helpers';
9+
10+
import {prepareDatabase} from './setup';
11+
import {settings} from './settings';
12+
13+
const isWin = os.type().search('Windows') > -1;
14+
15+
let database, pool;
16+
const pgServiceName = process.env.PG_SERVICE_NAME;
17+
18+
describe('Database;', function () {
19+
this.timeout(45000);
20+
21+
before(async done => {
22+
try {
23+
database = new Database(settings);
24+
pool = database.pool;
25+
done();
26+
} catch (err) {
27+
done(err);
28+
}
29+
});
30+
31+
after(async done => {
32+
try {
33+
await database.close();
34+
done();
35+
} catch (err) {
36+
done(err);
37+
}
38+
});
39+
40+
describe('Loss connection;', () => {
41+
42+
it('db pool should be empty', async done => {
43+
try {
44+
checkPoolState(0, 0, PoolState.active);
45+
46+
done();
47+
48+
} catch (err) {
49+
done(err);
50+
}
51+
});
52+
53+
it('should return result without an error', async done => {
54+
try {
55+
const session = await connectToDatabase(database);
56+
await session.startTransaction();
57+
const user = await getUsers(session, 1);
58+
59+
expect(user).to.not.be.undefined;
60+
expect(user.id).to.equal(1);
61+
62+
checkPoolState(1, 0, PoolState.active);
63+
64+
await session.close('commit');
65+
66+
done();
67+
} catch (err) {
68+
done(err);
69+
}
70+
});
71+
72+
it('db pool should be empty after idleTimeout time', async done => {
73+
try {
74+
await wait(settings.pool.idleTimeout);
75+
76+
checkPoolState(0, 0, PoolState.active);
77+
78+
done();
79+
80+
} catch (err) {
81+
done(err);
82+
}
83+
});
84+
85+
it('should return an error when connection is terminated', async done => {
86+
process.on('uncaughtException', done);
87+
88+
database.on(ERROR_EVENT, function dbErrorHandler(err) {
89+
try {
90+
expect(err).to.be.an.instanceof(Error);
91+
expect(err.message).to.include('terminating connection');
92+
93+
checkPoolState(0, 0, PoolState.active);
94+
95+
done();
96+
} catch (error) {
97+
done(error);
98+
} finally {
99+
process.removeListener('uncaughtException', done);
100+
database.removeListener('error', dbErrorHandler);
101+
}
102+
});
103+
104+
try {
105+
const session = await connectToDatabase(database);
106+
await session.startTransaction();
107+
108+
checkPoolState(1, 0, PoolState.active);
109+
110+
await stopPostgresql();
111+
} catch (err) {
112+
done(err);
113+
}
114+
});
115+
116+
it('should return ECONNREFUSED error', async done => {
117+
let session;
118+
119+
try {
120+
checkPoolState(0, 0, PoolState.active);
121+
122+
session = await connectToDatabase(database);
123+
} catch (err) {
124+
try {
125+
expect(session).to.be.undefined;
126+
expect(err).to.be.an.instanceof(Error);
127+
expect(err.message).to.include(isWin ? 'shutting down' : 'ECONNREFUSED');
128+
129+
checkPoolState(0, 0, PoolState.active);
130+
131+
done();
132+
} catch (error) {
133+
done(error);
134+
}
135+
}
136+
});
137+
138+
if (isWin) {
139+
it('waiting of pg service', async done => {
140+
await wait(20000);
141+
done();
142+
});
143+
}
144+
145+
it('should return result without an error', async done => {
146+
try {
147+
await startPostgresql();
148+
const session = await connectToDatabase(database);
149+
await session.startTransaction();
150+
const user = await getUsers(session, 1);
151+
152+
expect(user).to.not.be.undefined;
153+
expect(user.id).to.equal(1);
154+
155+
checkPoolState(1, 0, PoolState.active);
156+
157+
await session.close('commit');
158+
159+
done();
160+
} catch (err) {
161+
done(err);
162+
}
163+
});
164+
165+
it('db pool should be empty after idleTimeout time', async done => {
166+
try {
167+
await wait(settings.pool.idleTimeout);
168+
169+
checkPoolState(0, 0, PoolState.active);
170+
171+
done();
172+
173+
} catch (err) {
174+
done(err);
175+
}
176+
});
177+
});
178+
});
179+
180+
// helpers
181+
function checkPoolState(totalCount, idleCount, state) {
182+
expect(pool.idleCount).to.equal(idleCount);
183+
expect(pool.totalCount).to.equal(totalCount);
184+
expect(pool.state).to.equal(state);
185+
}
186+
187+
function connectToDatabase(db: Database): Promise<Session> {
188+
return db.connect();
189+
}
190+
191+
async function getUsers(session: Session, userId: number): Promise<any> {
192+
await prepareDatabase(session);
193+
194+
const query = {
195+
text: `SELECT * FROM tmp_users WHERE id=${userId};`,
196+
mask: 'single'
197+
};
198+
199+
return await session.execute(query);
200+
}
201+
202+
function execCommand(command: string): Promise<void> {
203+
return new Promise((resolve, reject) => {
204+
exec(command, (err, stdout, stderr) => {
205+
const error = err || stderr;
206+
207+
error ? reject(error) : resolve();
208+
});
209+
});
210+
}
211+
212+
async function startPostgresql(): Promise<void> {
213+
const command = isWin
214+
? `NET START "${pgServiceName}"`
215+
: 'brew services start postgresql';
216+
217+
await execCommand(command);
218+
await wait(2000);
219+
}
220+
221+
async function stopPostgresql(): Promise<void> {
222+
const command = isWin
223+
? `NET STOP ${pgServiceName}`
224+
: 'brew services stop postgresql';
225+
226+
await execCommand(command);
227+
await wait(2000);
228+
}

tests/poolState.spec.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {expect} from 'chai';
2+
3+
import {ConnectionPool, PoolState} from '../lib/Pool';
4+
import {createNewPool} from './helpers';
5+
6+
describe('Pool State;', () => {
7+
it('should return valid state', done => {
8+
const pool = createNewPool();
9+
10+
checkState(pool, PoolState.active);
11+
12+
pool.acquire((err, client) => {
13+
checkState(pool, PoolState.active);
14+
15+
pool.shutdown(() => {
16+
checkState(pool, PoolState.closed);
17+
done();
18+
});
19+
20+
checkState(pool, PoolState.closing);
21+
22+
client.release();
23+
});
24+
});
25+
26+
it('should return valid state', done => {
27+
const pool = createNewPool();
28+
29+
checkState(pool, PoolState.active);
30+
31+
pool.shutdown(() => {
32+
checkState(pool, PoolState.closed);
33+
done();
34+
});
35+
36+
checkState(pool, PoolState.closed);
37+
});
38+
});
39+
40+
// helpers
41+
function checkState(pool: ConnectionPool, shouldBeState: PoolState): void {
42+
expect((pool as any).state).to.equal(shouldBeState);
43+
}

0 commit comments

Comments
 (0)