Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 337 lines (272 sloc) 5.655 kb
df1f131 @bmizerany init
bmizerany authored
1 package pq
2
3 import (
4 "database/sql"
5 "database/sql/driver"
6 "io"
6c7918f Implement many libpq environment variables
Dan Farina authored
7 "os"
df1f131 @bmizerany init
bmizerany authored
8 "reflect"
9 "testing"
10 "time"
11 )
12
6c7918f Implement many libpq environment variables
Dan Farina authored
13 func openTestConn(t *testing.T) *sql.DB {
14 datname := os.Getenv("PGDATABASE")
15 sslmode := os.Getenv("PGSSLMODE")
df1f131 @bmizerany init
bmizerany authored
16
6c7918f Implement many libpq environment variables
Dan Farina authored
17 if datname == "" {
18 os.Setenv("PGDATABASE", "pqgotest")
19 }
20
21 if sslmode == "" {
22 os.Setenv("PGSSLMODE", "disable")
23 }
24
25 conn, err := sql.Open("postgres", "")
df1f131 @bmizerany init
bmizerany authored
26 if err != nil {
27 t.Fatal(err)
28 }
6c7918f Implement many libpq environment variables
Dan Farina authored
29
30 return conn
31 }
32
33 func TestExec(t *testing.T) {
34 db := openTestConn(t)
df1f131 @bmizerany init
bmizerany authored
35 defer db.Close()
36
6c7918f Implement many libpq environment variables
Dan Farina authored
37 _, err := db.Exec("CREATE TEMP TABLE temp (a int)")
570d458 Make tests independent of table "temp"
Dan Farina authored
38 if err != nil {
39 t.Fatal(err)
40 }
df1f131 @bmizerany init
bmizerany authored
41
42 r, err := db.Exec("INSERT INTO temp VALUES (1)")
43 if err != nil {
44 t.Fatal(err)
45 }
46
47 if n, _ := r.RowsAffected(); n != 1 {
48 t.Fatalf("expected 1 row affected, not %d", n)
49 }
50 }
51
52 func TestStatment(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
53 db := openTestConn(t)
df1f131 @bmizerany init
bmizerany authored
54 defer db.Close()
55
56 st, err := db.Prepare("SELECT 1")
57 if err != nil {
58 t.Fatal(err)
59 }
60
61 st1, err := db.Prepare("SELECT 2")
62 if err != nil {
63 t.Fatal(err)
64 }
65
66 r, err := st.Query()
67 if err != nil {
68 t.Fatal(err)
69 }
391c322 @benburkert Close Rows in tests.
authored
70 defer r.Close()
df1f131 @bmizerany init
bmizerany authored
71
72 if !r.Next() {
73 t.Fatal("expected row")
74 }
75
76 var i int
77 err = r.Scan(&i)
78 if err != nil {
79 t.Fatal(err)
80 }
81
82 if i != 1 {
83 t.Fatalf("expected 1, got %d", i)
84 }
85
86 // st1
87
391c322 @benburkert Close Rows in tests.
authored
88 r1, err := st1.Query()
df1f131 @bmizerany init
bmizerany authored
89 if err != nil {
90 t.Fatal(err)
91 }
391c322 @benburkert Close Rows in tests.
authored
92 defer r1.Close()
df1f131 @bmizerany init
bmizerany authored
93
391c322 @benburkert Close Rows in tests.
authored
94 if !r1.Next() {
df1f131 @bmizerany init
bmizerany authored
95 if r.Err() != nil {
391c322 @benburkert Close Rows in tests.
authored
96 t.Fatal(r1.Err())
df1f131 @bmizerany init
bmizerany authored
97 }
98 t.Fatal("expected row")
99 }
100
391c322 @benburkert Close Rows in tests.
authored
101 err = r1.Scan(&i)
df1f131 @bmizerany init
bmizerany authored
102 if err != nil {
103 t.Fatal(err)
104 }
105
106 if i != 2 {
107 t.Fatalf("expected 2, got %d", i)
108 }
109 }
110
111 func TestRowsCloseBeforeDone(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
112 db := openTestConn(t)
113 defer db.Close()
df1f131 @bmizerany init
bmizerany authored
114
115 r, err := db.Query("SELECT 1")
116 if err != nil {
117 t.Fatal(err)
118 }
119
120 err = r.Close()
121 if err != nil {
122 t.Fatal(err)
123 }
124
125 if r.Next() {
126 t.Fatal("unexpected row")
127 }
128
129 if r.Err() != nil {
130 t.Fatal(r.Err())
131 }
132 }
133
134 func TestEncodeDecode(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
135 db := openTestConn(t)
df1f131 @bmizerany init
bmizerany authored
136 defer db.Close()
137
138 q := `
139 SELECT
140 '\x000102'::bytea,
141 'foobar'::text,
142 NULL::integer,
143 '2000-1-1 01:02:03.04-7'::timestamptz
144 WHERE
145 '\x000102'::bytea = $1
146 AND 'foobar'::text = $2
147 AND $3::integer is NULL
148 `
149 // AND '2000-1-1 12:00:00.000000-7'::timestamp = $3
150
151 exp1 := []byte{0, 1, 2}
152 exp2 := "foobar"
153
154 r, err := db.Query(q, exp1, exp2, nil)
155 if err != nil {
156 t.Fatal(err)
157 }
158 defer r.Close()
159
160 if !r.Next() {
161 if r.Err() != nil {
162 t.Fatal(r.Err())
163 }
164 t.Fatal("expected row")
165 }
166
167 var got1 []byte
168 var got2 string
169 var got3 = sql.NullInt64{Valid: true}
170 var got4 time.Time
171
172 err = r.Scan(&got1, &got2, &got3, &got4)
173 if err != nil {
174 t.Fatal(err)
175 }
176
177 if !reflect.DeepEqual(exp1, got1) {
178 t.Errorf("expected %q byte: %q", exp1, got1)
179 }
180
181 if !reflect.DeepEqual(exp2, got2) {
182 t.Errorf("expected %q byte: %q", exp2, got2)
183 }
184
185 if got3.Valid {
186 t.Fatal("expected invalid")
187 }
188
189 if got4.Year() != 2000 {
190 t.Fatal("wrong year")
191 }
192 }
193
194 func TestNoData(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
195 db := openTestConn(t)
df1f131 @bmizerany init
bmizerany authored
196 defer db.Close()
197
198 st, err := db.Prepare("SELECT 1 WHERE true = false")
199 if err != nil {
200 t.Fatal(err)
201 }
202 defer st.Close()
203
204 r, err := st.Query()
205 if err != nil {
206 t.Fatal(err)
207 }
208 defer r.Close()
209
210 if r.Next() {
211 if r.Err() != nil {
212 t.Fatal(r.Err())
213 }
214 t.Fatal("unexpected row")
215 }
216 }
217
218 func TestPGError(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
219 // Don't use the normal connection setup, this is intended to
220 // blow up in the startup packet from a non-existent user.
221 db, err := sql.Open("postgres", "user=thisuserreallydoesntexist")
df1f131 @bmizerany init
bmizerany authored
222 if err != nil {
223 t.Fatal(err)
224 }
225 defer db.Close()
226
227 _, err = db.Begin()
228 if err == nil {
229 t.Fatal("expected error")
230 }
231
232 if err != driver.ErrBadConn {
233 t.Fatalf("expected a PGError, got: %v", err)
234 }
235 }
236
237 func TestBadConn(t *testing.T) {
238 var err error
239
240 func() {
241 defer errRecover(&err)
242 panic(io.EOF)
243 }()
244
245 if err != driver.ErrBadConn {
246 t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
247 }
248
249 func() {
250 defer errRecover(&err)
251 e := &PGError{c: make(map[byte]string)}
252 e.c['S'] = Efatal
253 panic(e)
254 }()
255
256 if err != driver.ErrBadConn {
257 t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
258 }
259 }
b2be164 @bmizerany test for non-fatal error
bmizerany authored
260
261 func TestErrorOnExec(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
262 db := openTestConn(t)
b2be164 @bmizerany test for non-fatal error
bmizerany authored
263 defer db.Close()
264
265 sql := "DO $$BEGIN RAISE unique_violation USING MESSAGE='foo'; END; $$;"
6c7918f Implement many libpq environment variables
Dan Farina authored
266 _, err := db.Exec(sql)
12654ac @bmizerany better error test
bmizerany authored
267 _, ok := err.(*PGError)
268 if !ok {
269 t.Fatalf("expected PGError, was: %#v", err)
b2be164 @bmizerany test for non-fatal error
bmizerany authored
270 }
271
272 _, err = db.Exec("SELECT 1 WHERE true = false") // returns no rows
273 if err != nil {
12654ac @bmizerany better error test
bmizerany authored
274 t.Fatal(err)
b2be164 @bmizerany test for non-fatal error
bmizerany authored
275 }
276 }
6a5c551 @bmizerany ensure correct error handling in Query
bmizerany authored
277
278 func TestErrorOnQuery(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
279 db := openTestConn(t)
6a5c551 @bmizerany ensure correct error handling in Query
bmizerany authored
280 defer db.Close()
281
282 sql := "DO $$BEGIN RAISE unique_violation USING MESSAGE='foo'; END; $$;"
283 r, err := db.Query(sql)
284 if err != nil {
285 t.Fatal(err)
286 }
391c322 @benburkert Close Rows in tests.
authored
287 defer r.Close()
6a5c551 @bmizerany ensure correct error handling in Query
bmizerany authored
288
289 if r.Next() {
290 t.Fatal("unexpected row, want error")
291 }
292
293 _, ok := r.Err().(*PGError)
294 if !ok {
295 t.Fatalf("expected PGError, was: %#v", r.Err())
296 }
297
298 r, err = db.Query("SELECT 1 WHERE true = false") // returns no rows
299 if err != nil {
300 t.Fatal(err)
301 }
302
303 if r.Next() {
304 t.Fatal("unexpected row")
305 }
306 }
29bcb7e @bmizerany fix #8 - handle bind error earlier
bmizerany authored
307
308 func TestBindError(t *testing.T) {
6c7918f Implement many libpq environment variables
Dan Farina authored
309 db := openTestConn(t)
310 defer db.Close()
29bcb7e @bmizerany fix #8 - handle bind error earlier
bmizerany authored
311
6c7918f Implement many libpq environment variables
Dan Farina authored
312 _, err := db.Exec("create temp table test (i integer)")
29bcb7e @bmizerany fix #8 - handle bind error earlier
bmizerany authored
313 if err != nil {
314 t.Fatal(err)
315 }
316
317 _, err = db.Query("select * from test where i=$1", "hhh")
318 if err == nil {
319 t.Fatal("expected an error")
320 }
321
322 // Should not get error here
391c322 @benburkert Close Rows in tests.
authored
323 r, err := db.Query("select * from test where i=$1", 1)
29bcb7e @bmizerany fix #8 - handle bind error earlier
bmizerany authored
324 if err != nil {
325 t.Fatal(err)
326 }
391c322 @benburkert Close Rows in tests.
authored
327 defer r.Close()
29bcb7e @bmizerany fix #8 - handle bind error earlier
bmizerany authored
328 }
6c7918f Implement many libpq environment variables
Dan Farina authored
329
330 func TestParseEnviron(t *testing.T) {
331 expected := map[string]string{"dbname": "hello", "user": "goodbye"}
332 results := parseEnviron([]string{"PGDATABASE=hello", "PGUSER=goodbye"})
333 if !reflect.DeepEqual(expected, results) {
334 t.Fatalf("Expected: %#v Got: %#v", expected, results)
335 }
336 }
Something went wrong with that request. Please try again.