Skip to content

Commit 18d563a

Browse files
authored
Create pipeline-tests.js
1 parent deb7f76 commit 18d563a

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

packages/pg/lib/pipeline-tests.js

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
'use strict'
2+
3+
const helper = require('../test-helper')
4+
const pg = helper.pg
5+
const assert = require('assert')
6+
7+
const suite = new helper.Suite()
8+
9+
suite.test('pipeline mode basic functionality', (cb) => {
10+
const client = new pg.Client(helper.config)
11+
client.connect((err) => {
12+
if (err) return cb(err)
13+
14+
// Initially not in pipeline mode
15+
assert.equal(client.pipelineStatus(), 'PIPELINE_OFF')
16+
assert.equal(client.pipelining, false)
17+
18+
// Enable pipeline mode
19+
client.pipelining = true
20+
assert.equal(client.pipelineStatus(), 'PIPELINE_ON')
21+
assert.equal(client.pipelining, true)
22+
23+
// Disable pipeline mode
24+
client.pipelining = false
25+
assert.equal(client.pipelineStatus(), 'PIPELINE_OFF')
26+
assert.equal(client.pipelining, false)
27+
28+
client.end(cb)
29+
})
30+
})
31+
32+
suite.test('cannot enable pipeline before connection', (cb) => {
33+
const client = new pg.Client(helper.config)
34+
35+
try {
36+
client.pipelining = true
37+
cb(new Error('Should have thrown error'))
38+
} catch (err) {
39+
assert.equal(err.message, 'Cannot enable pipelining before connection is established')
40+
cb()
41+
}
42+
})
43+
44+
suite.test('pipeline mode with multiple queries', (cb) => {
45+
const client = new pg.Client(helper.config)
46+
client.connect((err) => {
47+
if (err) return cb(err)
48+
49+
client.pipelining = true
50+
51+
let results = []
52+
let completed = 0
53+
54+
// Send multiple queries in pipeline mode
55+
client.query('SELECT 1 as num', (err, res) => {
56+
if (err) return cb(err)
57+
results[0] = res.rows[0].num
58+
completed++
59+
if (completed === 3) checkResults()
60+
})
61+
62+
client.query('SELECT 2 as num', (err, res) => {
63+
if (err) return cb(err)
64+
results[1] = res.rows[0].num
65+
completed++
66+
if (completed === 3) checkResults()
67+
})
68+
69+
client.query('SELECT 3 as num', (err, res) => {
70+
if (err) return cb(err)
71+
results[2] = res.rows[0].num
72+
completed++
73+
if (completed === 3) checkResults()
74+
})
75+
76+
function checkResults() {
77+
assert.equal(results[0], 1)
78+
assert.equal(results[1], 2)
79+
assert.equal(results[2], 3)
80+
client.end(cb)
81+
}
82+
})
83+
})
84+
85+
suite.test('pipeline mode rejects simple query protocol', (cb) => {
86+
const client = new pg.Client(helper.config)
87+
client.connect((err) => {
88+
if (err) return cb(err)
89+
90+
client.pipelining = true
91+
92+
try {
93+
client.query('SELECT 1', (err, res) => {
94+
// This should not be called
95+
cb(new Error('Simple query should have been rejected'))
96+
})
97+
} catch (err) {
98+
assert(err.message.includes('Simple query protocol is not allowed in pipeline mode'))
99+
client.end(cb)
100+
}
101+
})
102+
})
103+
104+
suite.test('pipeline mode rejects multiple SQL commands', (cb) => {
105+
const client = new pg.Client(helper.config)
106+
client.connect((err) => {
107+
if (err) return cb(err)
108+
109+
client.pipelining = true
110+
111+
try {
112+
client.query({ text: 'SELECT 1; SELECT 2;' }, (err, res) => {
113+
// This should not be called
114+
cb(new Error('Multiple SQL commands should have been rejected'))
115+
})
116+
} catch (err) {
117+
assert(err.message.includes('Multiple SQL commands in a single query are not allowed in pipeline mode'))
118+
client.end(cb)
119+
}
120+
})
121+
})
122+
123+
suite.test('pipeline mode with parameterized queries', (cb) => {
124+
const client = new pg.Client(helper.config)
125+
client.connect((err) => {
126+
if (err) return cb(err)
127+
128+
client.pipelining = true
129+
130+
let results = []
131+
let completed = 0
132+
133+
// Send parameterized queries in pipeline mode
134+
client.query({ text: 'SELECT $1::int as num', values: [10] }, (err, res) => {
135+
if (err) return cb(err)
136+
results[0] = res.rows[0].num
137+
completed++
138+
if (completed === 2) checkResults()
139+
})
140+
141+
client.query({ text: 'SELECT $1::text as str', values: ['hello'] }, (err, res) => {
142+
if (err) return cb(err)
143+
results[1] = res.rows[0].str
144+
completed++
145+
if (completed === 2) checkResults()
146+
})
147+
148+
function checkResults() {
149+
assert.equal(results[0], 10)
150+
assert.equal(results[1], 'hello')
151+
client.end(cb)
152+
}
153+
})
154+
})
155+
156+
suite.test('pipeline mode performance benefit', (cb) => {
157+
const client = new pg.Client(helper.config)
158+
client.connect((err) => {
159+
if (err) return cb(err)
160+
161+
const numQueries = 10
162+
163+
// Test without pipeline mode
164+
const startNormal = Date.now()
165+
let normalCompleted = 0
166+
167+
function runNormalQueries() {
168+
for (let i = 0; i < numQueries; i++) {
169+
client.query({ text: 'SELECT $1::int as num', values: [i] }, (err, res) => {
170+
if (err) return cb(err)
171+
normalCompleted++
172+
if (normalCompleted === numQueries) {
173+
const normalTime = Date.now() - startNormal
174+
runPipelineQueries(normalTime)
175+
}
176+
})
177+
}
178+
}
179+
180+
function runPipelineQueries(normalTime) {
181+
client.pipelining = true
182+
const startPipeline = Date.now()
183+
let pipelineCompleted = 0
184+
185+
for (let i = 0; i < numQueries; i++) {
186+
client.query({ text: 'SELECT $1::int as num', values: [i] }, (err, res) => {
187+
if (err) return cb(err)
188+
pipelineCompleted++
189+
if (pipelineCompleted === numQueries) {
190+
const pipelineTime = Date.now() - startPipeline
191+
192+
// Pipeline should be faster or at least not significantly slower
193+
// In real network conditions with latency, pipeline would show more benefit
194+
console.log(`Normal mode: ${normalTime}ms, Pipeline mode: ${pipelineTime}ms`)
195+
196+
client.end(cb)
197+
}
198+
})
199+
}
200+
}
201+
202+
runNormalQueries()
203+
})
204+
})
205+
206+
module.exports = suite

0 commit comments

Comments
 (0)