source: node_modules/pg-protocol/src/outbound-serializer.test.ts@ 2d1ec46

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

Project Handcraft Marketplace

  • Property mode set to 100644
File size: 11.1 KB
Line 
1import assert from 'assert'
2import { serialize } from './serializer'
3import BufferList from './testing/buffer-list'
4
5describe('serializer', () => {
6 it('builds startup message', function () {
7 const actual = serialize.startup({
8 user: 'brian',
9 database: 'bang',
10 })
11 assert.deepEqual(
12 actual,
13 new BufferList()
14 .addInt16(3)
15 .addInt16(0)
16 .addCString('user')
17 .addCString('brian')
18 .addCString('database')
19 .addCString('bang')
20 .addCString('client_encoding')
21 .addCString('UTF8')
22 .addCString('')
23 .join(true)
24 )
25 })
26
27 it('builds password message', function () {
28 const actual = serialize.password('!')
29 assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p'))
30 })
31
32 it('builds request ssl message', function () {
33 const actual = serialize.requestSsl()
34 const expected = new BufferList().addInt32(80877103).join(true)
35 assert.deepEqual(actual, expected)
36 })
37
38 it('builds SASLInitialResponseMessage message', function () {
39 const actual = serialize.sendSASLInitialResponseMessage('mech', 'data')
40 assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p'))
41 })
42
43 it('builds SCRAMClientFinalMessage message', function () {
44 const actual = serialize.sendSCRAMClientFinalMessage('data')
45 assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p'))
46 })
47
48 it('builds query message', function () {
49 const txt = 'select * from boom'
50 const actual = serialize.query(txt)
51 assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q'))
52 })
53
54 describe('parse message', () => {
55 it('builds parse message', function () {
56 const actual = serialize.parse({ text: '!' })
57 const expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P')
58 assert.deepEqual(actual, expected)
59 })
60
61 it('builds parse message with named query', function () {
62 const actual = serialize.parse({
63 name: 'boom',
64 text: 'select * from boom',
65 types: [],
66 })
67 const expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P')
68 assert.deepEqual(actual, expected)
69 })
70
71 it('with multiple parameters', function () {
72 const actual = serialize.parse({
73 name: 'force',
74 text: 'select * from bang where name = $1',
75 types: [1, 2, 3, 4],
76 })
77 const expected = new BufferList()
78 .addCString('force')
79 .addCString('select * from bang where name = $1')
80 .addInt16(4)
81 .addInt32(1)
82 .addInt32(2)
83 .addInt32(3)
84 .addInt32(4)
85 .join(true, 'P')
86 assert.deepEqual(actual, expected)
87 })
88 })
89
90 describe('bind messages', function () {
91 it('with no values', function () {
92 const actual = serialize.bind()
93
94 const expectedBuffer = new BufferList()
95 .addCString('')
96 .addCString('')
97 .addInt16(0)
98 .addInt16(0)
99 .addInt16(1)
100 .addInt16(0)
101 .join(true, 'B')
102 assert.deepEqual(actual, expectedBuffer)
103 })
104
105 it('with named statement, portal, and values', function () {
106 const actual = serialize.bind({
107 portal: 'bang',
108 statement: 'woo',
109 values: ['1', 'hi', null, 'zing'],
110 })
111 const expectedBuffer = new BufferList()
112 .addCString('bang') // portal name
113 .addCString('woo') // statement name
114 .addInt16(4)
115 .addInt16(0)
116 .addInt16(0)
117 .addInt16(0)
118 .addInt16(0)
119 .addInt16(4)
120 .addInt32(1)
121 .add(Buffer.from('1'))
122 .addInt32(2)
123 .add(Buffer.from('hi'))
124 .addInt32(-1)
125 .addInt32(4)
126 .add(Buffer.from('zing'))
127 .addInt16(1)
128 .addInt16(0)
129 .join(true, 'B')
130 assert.deepEqual(actual, expectedBuffer)
131 })
132
133 it('encodes a multi-byte string param with its UTF-8 byte length, not char length', function () {
134 // Guards the single-pass addInt32PrefixedString write path: the Int32
135 // length prefix must be the UTF-8 byte count, not String.length. 'héllo中🎉'
136 // is 7 code points / 8 UTF-16 code units but 13 UTF-8 bytes.
137 const value = 'héllo中🎉'
138 const bytes = Buffer.from(value, 'utf8')
139 assert.notEqual(bytes.length, value.length) // sanity: the divergence we're testing
140 const actual = serialize.bind({ values: [value] })
141 const expectedBuffer = new BufferList()
142 .addCString('') // portal
143 .addCString('') // statement
144 .addInt16(1) // param format code count
145 .addInt16(0) // format code for the one value (text)
146 .addInt16(1) // value count
147 .addInt32(bytes.length) // 13 — the UTF-8 byte length, NOT value.length (8)
148 .add(bytes)
149 .addInt16(1) // result format code count
150 .addInt16(0) // result format (text)
151 .join(true, 'B')
152 assert.deepEqual(actual, expectedBuffer)
153 })
154 })
155
156 it('with custom valueMapper', function () {
157 const actual = serialize.bind({
158 portal: 'bang',
159 statement: 'woo',
160 values: ['1', 'hi', null, 'zing'],
161 valueMapper: () => null,
162 })
163 const expectedBuffer = new BufferList()
164 .addCString('bang') // portal name
165 .addCString('woo') // statement name
166 .addInt16(4)
167 .addInt16(0)
168 .addInt16(0)
169 .addInt16(0)
170 .addInt16(0)
171 .addInt16(4)
172 .addInt32(-1)
173 .addInt32(-1)
174 .addInt32(-1)
175 .addInt32(-1)
176 .addInt16(1)
177 .addInt16(0)
178 .join(true, 'B')
179 assert.deepEqual(actual, expectedBuffer)
180 })
181
182 it('with named statement, portal, and buffer value', function () {
183 const actual = serialize.bind({
184 portal: 'bang',
185 statement: 'woo',
186 values: ['1', 'hi', null, Buffer.from('zing', 'utf8')],
187 })
188 const expectedBuffer = new BufferList()
189 .addCString('bang') // portal name
190 .addCString('woo') // statement name
191 .addInt16(4) // value count
192 .addInt16(0) // string
193 .addInt16(0) // string
194 .addInt16(0) // string
195 .addInt16(1) // binary
196 .addInt16(4)
197 .addInt32(1)
198 .add(Buffer.from('1'))
199 .addInt32(2)
200 .add(Buffer.from('hi'))
201 .addInt32(-1)
202 .addInt32(4)
203 .add(Buffer.from('zing', 'utf-8'))
204 .addInt16(1)
205 .addInt16(0)
206 .join(true, 'B')
207 assert.deepEqual(actual, expectedBuffer)
208 })
209
210 describe('builds execute message', function () {
211 it('for unamed portal with no row limit', function () {
212 const actual = serialize.execute()
213 const expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E')
214 assert.deepEqual(actual, expectedBuffer)
215 })
216
217 it('for named portal with row limit', function () {
218 const actual = serialize.execute({
219 portal: 'my favorite portal',
220 rows: 100,
221 })
222 const expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E')
223 assert.deepEqual(actual, expectedBuffer)
224 })
225 })
226
227 it('builds flush command', function () {
228 const actual = serialize.flush()
229 const expected = new BufferList().join(true, 'H')
230 assert.deepEqual(actual, expected)
231 })
232
233 it('builds sync command', function () {
234 const actual = serialize.sync()
235 const expected = new BufferList().join(true, 'S')
236 assert.deepEqual(actual, expected)
237 })
238
239 it('builds end command', function () {
240 const actual = serialize.end()
241 const expected = Buffer.from([0x58, 0, 0, 0, 4])
242 assert.deepEqual(actual, expected)
243 })
244
245 describe('builds describe command', function () {
246 it('describe statement', function () {
247 const actual = serialize.describe({ type: 'S', name: 'bang' })
248 const expected = new BufferList().addChar('S').addCString('bang').join(true, 'D')
249 assert.deepEqual(actual, expected)
250 })
251
252 it('describe unnamed portal', function () {
253 const actual = serialize.describe({ type: 'P' })
254 const expected = new BufferList().addChar('P').addCString('').join(true, 'D')
255 assert.deepEqual(actual, expected)
256 })
257 })
258
259 describe('builds close command', function () {
260 it('describe statement', function () {
261 const actual = serialize.close({ type: 'S', name: 'bang' })
262 const expected = new BufferList().addChar('S').addCString('bang').join(true, 'C')
263 assert.deepEqual(actual, expected)
264 })
265
266 it('describe unnamed portal', function () {
267 const actual = serialize.close({ type: 'P' })
268 const expected = new BufferList().addChar('P').addCString('').join(true, 'C')
269 assert.deepEqual(actual, expected)
270 })
271 })
272
273 describe('copy messages', function () {
274 it('builds copyFromChunk', () => {
275 const actual = serialize.copyData(Buffer.from([1, 2, 3]))
276 const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd')
277 assert.deepEqual(actual, expected)
278 })
279
280 it('builds copy fail', () => {
281 const actual = serialize.copyFail('err!')
282 const expected = new BufferList().addCString('err!').join(true, 'f')
283 assert.deepEqual(actual, expected)
284 })
285
286 it('builds copy done', () => {
287 const actual = serialize.copyDone()
288 const expected = new BufferList().join(true, 'c')
289 assert.deepEqual(actual, expected)
290 })
291 })
292
293 it('builds cancel message', () => {
294 const actual = serialize.cancel(3, 4)
295 const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true)
296 assert.deepEqual(actual, expected)
297 })
298
299 describe('bind error recovery', () => {
300 const throwingMapper = () => {
301 throw new Error('valueMapper error')
302 }
303
304 it('produces correct bind output after a valueMapper exception', () => {
305 assert.throws(() => {
306 serialize.bind({
307 values: ['fail'],
308 valueMapper: throwingMapper,
309 })
310 }, /valueMapper error/)
311
312 const actual = serialize.bind({
313 portal: 'bang',
314 statement: 'woo',
315 values: ['1', 'hi', null, 'zing'],
316 })
317 const expectedBuffer = new BufferList()
318 .addCString('bang')
319 .addCString('woo')
320 .addInt16(4)
321 .addInt16(0)
322 .addInt16(0)
323 .addInt16(0)
324 .addInt16(0)
325 .addInt16(4)
326 .addInt32(1)
327 .add(Buffer.from('1'))
328 .addInt32(2)
329 .add(Buffer.from('hi'))
330 .addInt32(-1)
331 .addInt32(4)
332 .add(Buffer.from('zing'))
333 .addInt16(1)
334 .addInt16(0)
335 .join(true, 'B')
336 assert.deepEqual(actual, expectedBuffer)
337 })
338
339 it('produces correct output from other serializer methods after a failed bind', () => {
340 assert.throws(() => {
341 serialize.bind({
342 values: ['fail'],
343 valueMapper: throwingMapper,
344 })
345 }, /valueMapper error/)
346
347 const parseActual = serialize.parse({ text: '!' })
348 const parseExpected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P')
349 assert.deepEqual(parseActual, parseExpected)
350
351 const queryActual = serialize.query('select 1')
352 const queryExpected = new BufferList().addCString('select 1').join(true, 'Q')
353 assert.deepEqual(queryActual, queryExpected)
354 })
355 })
356})
Note: See TracBrowser for help on using the repository browser.