source: node_modules/pg-protocol/dist/inbound-parser.test.js@ 62b2964

finki-main main
Last change on this file since 62b2964 was 62b2964, checked in by Klimentina Efremova <klimentina08642@…>, 2 weeks ago

Project Handcraft Marketplace

  • Property mode set to 100644
File size: 19.4 KB
Line 
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __importDefault = (this && this.__importDefault) || function (mod) {
12 return (mod && mod.__esModule) ? mod : { "default": mod };
13};
14Object.defineProperty(exports, "__esModule", { value: true });
15const test_buffers_1 = __importDefault(require("./testing/test-buffers"));
16const buffer_list_1 = __importDefault(require("./testing/buffer-list"));
17const _1 = require(".");
18const assert_1 = __importDefault(require("assert"));
19const stream_1 = require("stream");
20const parser_1 = require("./parser");
21const authOkBuffer = test_buffers_1.default.authenticationOk();
22const paramStatusBuffer = test_buffers_1.default.parameterStatus('client_encoding', 'UTF8');
23const readyForQueryBuffer = test_buffers_1.default.readyForQuery();
24const backendKeyDataBuffer = test_buffers_1.default.backendKeyData(1, 2);
25const commandCompleteBuffer = test_buffers_1.default.commandComplete('SELECT 3');
26const parseCompleteBuffer = test_buffers_1.default.parseComplete();
27const bindCompleteBuffer = test_buffers_1.default.bindComplete();
28const portalSuspendedBuffer = test_buffers_1.default.portalSuspended();
29const row1 = {
30 name: 'id',
31 tableID: 1,
32 attributeNumber: 2,
33 dataTypeID: 3,
34 dataTypeSize: 4,
35 typeModifier: 5,
36 formatCode: 0,
37};
38const oneRowDescBuff = test_buffers_1.default.rowDescription([row1]);
39row1.name = 'bang';
40const twoRowBuf = test_buffers_1.default.rowDescription([
41 row1,
42 {
43 name: 'whoah',
44 tableID: 10,
45 attributeNumber: 11,
46 dataTypeID: 12,
47 dataTypeSize: 13,
48 typeModifier: 14,
49 formatCode: 0,
50 },
51]);
52const rowWithBigOids = {
53 name: 'bigoid',
54 tableID: 3000000001,
55 attributeNumber: 2,
56 dataTypeID: 3000000003,
57 dataTypeSize: 4,
58 typeModifier: 5,
59 formatCode: 0,
60};
61const bigOidDescBuff = test_buffers_1.default.rowDescription([rowWithBigOids]);
62const emptyRowFieldBuf = test_buffers_1.default.dataRow([]);
63const oneFieldBuf = test_buffers_1.default.dataRow(['test']);
64const expectedAuthenticationOkayMessage = {
65 name: 'authenticationOk',
66 length: 8,
67};
68const expectedParameterStatusMessage = {
69 name: 'parameterStatus',
70 parameterName: 'client_encoding',
71 parameterValue: 'UTF8',
72 length: 25,
73};
74const expectedBackendKeyDataMessage = {
75 name: 'backendKeyData',
76 processID: 1,
77 secretKey: 2,
78};
79const expectedReadyForQueryMessage = {
80 name: 'readyForQuery',
81 length: 5,
82 status: 'I',
83};
84const expectedCommandCompleteMessage = {
85 name: 'commandComplete',
86 length: 13,
87 text: 'SELECT 3',
88};
89const emptyRowDescriptionBuffer = new buffer_list_1.default()
90 .addInt16(0) // number of fields
91 .join(true, 'T');
92const expectedEmptyRowDescriptionMessage = {
93 name: 'rowDescription',
94 length: 6,
95 fieldCount: 0,
96 fields: [],
97};
98const expectedOneRowMessage = {
99 name: 'rowDescription',
100 length: 27,
101 fieldCount: 1,
102 fields: [
103 {
104 name: 'id',
105 tableID: 1,
106 columnID: 2,
107 dataTypeID: 3,
108 dataTypeSize: 4,
109 dataTypeModifier: 5,
110 format: 'text',
111 },
112 ],
113};
114const expectedTwoRowMessage = {
115 name: 'rowDescription',
116 length: 53,
117 fieldCount: 2,
118 fields: [
119 {
120 name: 'bang',
121 tableID: 1,
122 columnID: 2,
123 dataTypeID: 3,
124 dataTypeSize: 4,
125 dataTypeModifier: 5,
126 format: 'text',
127 },
128 {
129 name: 'whoah',
130 tableID: 10,
131 columnID: 11,
132 dataTypeID: 12,
133 dataTypeSize: 13,
134 dataTypeModifier: 14,
135 format: 'text',
136 },
137 ],
138};
139const expectedBigOidMessage = {
140 name: 'rowDescription',
141 length: 31,
142 fieldCount: 1,
143 fields: [
144 {
145 name: 'bigoid',
146 tableID: 3000000001,
147 columnID: 2,
148 dataTypeID: 3000000003,
149 dataTypeSize: 4,
150 dataTypeModifier: 5,
151 format: 'text',
152 },
153 ],
154};
155const emptyParameterDescriptionBuffer = new buffer_list_1.default()
156 .addInt16(0) // number of parameters
157 .join(true, 't');
158const oneParameterDescBuf = test_buffers_1.default.parameterDescription([1111]);
159const twoParameterDescBuf = test_buffers_1.default.parameterDescription([2222, 3333]);
160const bigOidParameterDescBuf = test_buffers_1.default.parameterDescription([3000000003]);
161const expectedEmptyParameterDescriptionMessage = {
162 name: 'parameterDescription',
163 length: 6,
164 parameterCount: 0,
165 dataTypeIDs: [],
166};
167const expectedOneParameterMessage = {
168 name: 'parameterDescription',
169 length: 10,
170 parameterCount: 1,
171 dataTypeIDs: [1111],
172};
173const expectedTwoParameterMessage = {
174 name: 'parameterDescription',
175 length: 14,
176 parameterCount: 2,
177 dataTypeIDs: [2222, 3333],
178};
179const expectedBigOidParameterMessage = {
180 name: 'parameterDescription',
181 length: 10,
182 parameterCount: 1,
183 dataTypeIDs: [3000000003],
184};
185const testForMessage = function (buffer, expectedMessage) {
186 it('receives and parses ' + expectedMessage.name, () => __awaiter(this, void 0, void 0, function* () {
187 const messages = yield parseBuffers([buffer]);
188 const [lastMessage] = messages;
189 for (const key in expectedMessage) {
190 assert_1.default.deepEqual(lastMessage[key], expectedMessage[key]);
191 }
192 }));
193};
194const plainPasswordBuffer = test_buffers_1.default.authenticationCleartextPassword();
195const md5PasswordBuffer = test_buffers_1.default.authenticationMD5Password();
196const SASLBuffer = test_buffers_1.default.authenticationSASL();
197const SASLContinueBuffer = test_buffers_1.default.authenticationSASLContinue();
198const SASLFinalBuffer = test_buffers_1.default.authenticationSASLFinal();
199const expectedPlainPasswordMessage = {
200 name: 'authenticationCleartextPassword',
201};
202const expectedMD5PasswordMessage = {
203 name: 'authenticationMD5Password',
204 salt: Buffer.from([1, 2, 3, 4]),
205};
206const expectedSASLMessage = {
207 name: 'authenticationSASL',
208 mechanisms: ['SCRAM-SHA-256'],
209};
210const expectedSASLContinueMessage = {
211 name: 'authenticationSASLContinue',
212 data: 'data',
213};
214const expectedSASLFinalMessage = {
215 name: 'authenticationSASLFinal',
216 data: 'data',
217};
218const notificationResponseBuffer = test_buffers_1.default.notification(4, 'hi', 'boom');
219const expectedNotificationResponseMessage = {
220 name: 'notification',
221 processId: 4,
222 channel: 'hi',
223 payload: 'boom',
224};
225const parseBuffers = (buffers) => __awaiter(void 0, void 0, void 0, function* () {
226 const stream = new stream_1.PassThrough();
227 for (const buffer of buffers) {
228 stream.write(buffer);
229 }
230 stream.end();
231 const msgs = [];
232 yield (0, _1.parse)(stream, (msg) => msgs.push(msg));
233 return msgs;
234});
235describe('PgPacketStream', function () {
236 testForMessage(authOkBuffer, expectedAuthenticationOkayMessage);
237 testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage);
238 testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage);
239 testForMessage(SASLBuffer, expectedSASLMessage);
240 testForMessage(SASLContinueBuffer, expectedSASLContinueMessage);
241 // this exercises a found bug in the parser:
242 // https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084
243 // and adds a test which is deterministic, rather than relying on network packet chunking
244 const extendedSASLContinueBuffer = Buffer.concat([SASLContinueBuffer, Buffer.from([1, 2, 3, 4])]);
245 testForMessage(extendedSASLContinueBuffer, expectedSASLContinueMessage);
246 testForMessage(SASLFinalBuffer, expectedSASLFinalMessage);
247 // this exercises a found bug in the parser:
248 // https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084
249 // and adds a test which is deterministic, rather than relying on network packet chunking
250 const extendedSASLFinalBuffer = Buffer.concat([SASLFinalBuffer, Buffer.from([1, 2, 4, 5])]);
251 testForMessage(extendedSASLFinalBuffer, expectedSASLFinalMessage);
252 testForMessage(paramStatusBuffer, expectedParameterStatusMessage);
253 testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage);
254 testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage);
255 testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage);
256 testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage);
257 testForMessage(test_buffers_1.default.emptyQuery(), {
258 name: 'emptyQuery',
259 length: 4,
260 });
261 testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), {
262 name: 'noData',
263 });
264 describe('rowDescription messages', function () {
265 testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage);
266 testForMessage(oneRowDescBuff, expectedOneRowMessage);
267 testForMessage(twoRowBuf, expectedTwoRowMessage);
268 testForMessage(bigOidDescBuff, expectedBigOidMessage);
269 });
270 describe('parameterDescription messages', function () {
271 testForMessage(emptyParameterDescriptionBuffer, expectedEmptyParameterDescriptionMessage);
272 testForMessage(oneParameterDescBuf, expectedOneParameterMessage);
273 testForMessage(twoParameterDescBuf, expectedTwoParameterMessage);
274 testForMessage(bigOidParameterDescBuf, expectedBigOidParameterMessage);
275 });
276 describe('parsing rows', function () {
277 describe('parsing empty row', function () {
278 testForMessage(emptyRowFieldBuf, {
279 name: 'dataRow',
280 fieldCount: 0,
281 });
282 });
283 describe('parsing data row with fields', function () {
284 testForMessage(oneFieldBuf, {
285 name: 'dataRow',
286 fieldCount: 1,
287 fields: ['test'],
288 });
289 });
290 });
291 describe('notice message', function () {
292 // this uses the same logic as error message
293 const buff = test_buffers_1.default.notice([{ type: 'C', value: 'code' }]);
294 testForMessage(buff, {
295 name: 'notice',
296 code: 'code',
297 });
298 });
299 testForMessage(test_buffers_1.default.error([]), {
300 name: 'error',
301 });
302 describe('with all the fields', function () {
303 const buffer = test_buffers_1.default.error([
304 {
305 type: 'S',
306 value: 'ERROR',
307 },
308 {
309 type: 'C',
310 value: 'code',
311 },
312 {
313 type: 'M',
314 value: 'message',
315 },
316 {
317 type: 'D',
318 value: 'details',
319 },
320 {
321 type: 'H',
322 value: 'hint',
323 },
324 {
325 type: 'P',
326 value: '100',
327 },
328 {
329 type: 'p',
330 value: '101',
331 },
332 {
333 type: 'q',
334 value: 'query',
335 },
336 {
337 type: 'W',
338 value: 'where',
339 },
340 {
341 type: 'F',
342 value: 'file',
343 },
344 {
345 type: 'L',
346 value: 'line',
347 },
348 {
349 type: 'R',
350 value: 'routine',
351 },
352 {
353 type: 'Z', // ignored
354 value: 'alsdkf',
355 },
356 ]);
357 testForMessage(buffer, {
358 name: 'error',
359 severity: 'ERROR',
360 code: 'code',
361 message: 'message',
362 detail: 'details',
363 hint: 'hint',
364 position: '100',
365 internalPosition: '101',
366 internalQuery: 'query',
367 where: 'where',
368 file: 'file',
369 line: 'line',
370 routine: 'routine',
371 });
372 });
373 testForMessage(parseCompleteBuffer, {
374 name: 'parseComplete',
375 });
376 testForMessage(bindCompleteBuffer, {
377 name: 'bindComplete',
378 });
379 testForMessage(bindCompleteBuffer, {
380 name: 'bindComplete',
381 });
382 testForMessage(test_buffers_1.default.closeComplete(), {
383 name: 'closeComplete',
384 });
385 describe('parses portal suspended message', function () {
386 testForMessage(portalSuspendedBuffer, {
387 name: 'portalSuspended',
388 });
389 });
390 describe('parses replication start message', function () {
391 testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), {
392 name: 'replicationStart',
393 length: 4,
394 });
395 });
396 describe('copy', () => {
397 testForMessage(test_buffers_1.default.copyIn(0), {
398 name: 'copyInResponse',
399 length: 7,
400 binary: false,
401 columnTypes: [],
402 });
403 testForMessage(test_buffers_1.default.copyIn(2), {
404 name: 'copyInResponse',
405 length: 11,
406 binary: false,
407 columnTypes: [0, 1],
408 });
409 testForMessage(test_buffers_1.default.copyOut(0), {
410 name: 'copyOutResponse',
411 length: 7,
412 binary: false,
413 columnTypes: [],
414 });
415 testForMessage(test_buffers_1.default.copyOut(3), {
416 name: 'copyOutResponse',
417 length: 13,
418 binary: false,
419 columnTypes: [0, 1, 2],
420 });
421 testForMessage(test_buffers_1.default.copyDone(), {
422 name: 'copyDone',
423 length: 4,
424 });
425 testForMessage(test_buffers_1.default.copyData(Buffer.from([5, 6, 7])), {
426 name: 'copyData',
427 length: 7,
428 chunk: Buffer.from([5, 6, 7]),
429 });
430 });
431 // since the data message on a stream can randomly divide the incomming
432 // tcp packets anywhere, we need to make sure we can parse every single
433 // split on a tcp message
434 describe('split buffer, single message parsing', function () {
435 const fullBuffer = test_buffers_1.default.dataRow([null, 'bang', 'zug zug', null, '!']);
436 it('parses when full buffer comes in', function () {
437 return __awaiter(this, void 0, void 0, function* () {
438 const messages = yield parseBuffers([fullBuffer]);
439 const message = messages[0];
440 assert_1.default.equal(message.fields.length, 5);
441 assert_1.default.equal(message.fields[0], null);
442 assert_1.default.equal(message.fields[1], 'bang');
443 assert_1.default.equal(message.fields[2], 'zug zug');
444 assert_1.default.equal(message.fields[3], null);
445 assert_1.default.equal(message.fields[4], '!');
446 });
447 });
448 const testMessageReceivedAfterSplitAt = function (split) {
449 return __awaiter(this, void 0, void 0, function* () {
450 const firstBuffer = Buffer.alloc(fullBuffer.length - split);
451 const secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length);
452 fullBuffer.copy(firstBuffer, 0, 0);
453 fullBuffer.copy(secondBuffer, 0, firstBuffer.length);
454 const messages = yield parseBuffers([firstBuffer, secondBuffer]);
455 const message = messages[0];
456 assert_1.default.equal(message.fields.length, 5);
457 assert_1.default.equal(message.fields[0], null);
458 assert_1.default.equal(message.fields[1], 'bang');
459 assert_1.default.equal(message.fields[2], 'zug zug');
460 assert_1.default.equal(message.fields[3], null);
461 assert_1.default.equal(message.fields[4], '!');
462 });
463 };
464 it('parses when split in the middle', function () {
465 return testMessageReceivedAfterSplitAt(6);
466 });
467 it('parses when split at end', function () {
468 return testMessageReceivedAfterSplitAt(2);
469 });
470 it('parses when split at beginning', function () {
471 return Promise.all([
472 testMessageReceivedAfterSplitAt(fullBuffer.length - 2),
473 testMessageReceivedAfterSplitAt(fullBuffer.length - 1),
474 testMessageReceivedAfterSplitAt(fullBuffer.length - 5),
475 ]);
476 });
477 });
478 describe('split buffer, multiple message parsing', function () {
479 const dataRowBuffer = test_buffers_1.default.dataRow(['!']);
480 const readyForQueryBuffer = test_buffers_1.default.readyForQuery();
481 const fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length);
482 dataRowBuffer.copy(fullBuffer, 0, 0);
483 readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0);
484 const verifyMessages = function (messages) {
485 assert_1.default.strictEqual(messages.length, 2);
486 assert_1.default.deepEqual(messages[0], {
487 name: 'dataRow',
488 fieldCount: 1,
489 length: 11,
490 fields: ['!'],
491 });
492 assert_1.default.equal(messages[0].fields[0], '!');
493 assert_1.default.deepEqual(messages[1], {
494 name: 'readyForQuery',
495 length: 5,
496 status: 'I',
497 });
498 };
499 // sanity check
500 it('receives both messages when packet is not split', function () {
501 return __awaiter(this, void 0, void 0, function* () {
502 const messages = yield parseBuffers([fullBuffer]);
503 verifyMessages(messages);
504 });
505 });
506 const splitAndVerifyTwoMessages = function (split) {
507 return __awaiter(this, void 0, void 0, function* () {
508 const firstBuffer = Buffer.alloc(fullBuffer.length - split);
509 const secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length);
510 fullBuffer.copy(firstBuffer, 0, 0);
511 fullBuffer.copy(secondBuffer, 0, firstBuffer.length);
512 const messages = yield parseBuffers([firstBuffer, secondBuffer]);
513 verifyMessages(messages);
514 });
515 };
516 describe('receives both messages when packet is split', function () {
517 it('in the middle', function () {
518 return splitAndVerifyTwoMessages(11);
519 });
520 it('at the front', function () {
521 return Promise.all([
522 splitAndVerifyTwoMessages(fullBuffer.length - 1),
523 splitAndVerifyTwoMessages(fullBuffer.length - 4),
524 splitAndVerifyTwoMessages(fullBuffer.length - 6),
525 ]);
526 });
527 it('at the end', function () {
528 return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]);
529 });
530 });
531 });
532 it('cleans up the reader after handling a packet', function () {
533 const parser = new parser_1.Parser();
534 parser.parse(oneFieldBuf, () => { });
535 assert_1.default.strictEqual(parser.reader.buffer.byteLength, 0);
536 });
537});
538//# sourceMappingURL=inbound-parser.test.js.map
Note: See TracBrowser for help on using the repository browser.