~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/database/sql/fakedb_test.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
        "strconv"
14
14
        "strings"
15
15
        "sync"
 
16
        "testing"
16
17
        "time"
17
18
)
18
19
 
31
32
//   INSERT|<tablename>|col=val,col2=val2,col3=?
32
33
//   SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
33
34
//
34
 
// When opening a a fakeDriver's database, it starts empty with no
 
35
// When opening a fakeDriver's database, it starts empty with no
35
36
// tables.  All tables and data are stored in memory only.
36
37
type fakeDriver struct {
37
 
        mu        sync.Mutex
38
 
        openCount int
39
 
        dbs       map[string]*fakeDB
 
38
        mu         sync.Mutex // guards 3 following fields
 
39
        openCount  int        // conn opens
 
40
        closeCount int        // conn closes
 
41
        dbs        map[string]*fakeDB
40
42
}
41
43
 
42
44
type fakeDB struct {
43
45
        name string
44
46
 
45
 
        mu     sync.Mutex
46
 
        free   []*fakeConn
47
 
        tables map[string]*table
 
47
        mu      sync.Mutex
 
48
        free    []*fakeConn
 
49
        tables  map[string]*table
 
50
        badConn bool
48
51
}
49
52
 
50
53
type table struct {
83
86
        stmtsMade   int
84
87
        stmtsClosed int
85
88
        numPrepare  int
 
89
        bad         bool
86
90
}
87
91
 
88
92
func (c *fakeConn) incrStat(v *int) {
122
126
 
123
127
// Supports dsn forms:
124
128
//    <dbname>
125
 
//    <dbname>;<opts>  (no currently supported options)
 
129
//    <dbname>;<opts>  (only currently supported option is `badConn`,
 
130
//                      which causes driver.ErrBadConn to be returned on
 
131
//                      every other conn.Begin())
126
132
func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
127
133
        parts := strings.Split(dsn, ";")
128
134
        if len(parts) < 1 {
135
141
        d.mu.Lock()
136
142
        d.openCount++
137
143
        d.mu.Unlock()
138
 
        return &fakeConn{db: db}, nil
 
144
        conn := &fakeConn{db: db}
 
145
 
 
146
        if len(parts) >= 2 && parts[1] == "badConn" {
 
147
                conn.bad = true
 
148
        }
 
149
        return conn, nil
139
150
}
140
151
 
141
152
func (d *fakeDriver) getDB(name string) *fakeDB {
199
210
        return "", false
200
211
}
201
212
 
 
213
func (c *fakeConn) isBad() bool {
 
214
        // if not simulating bad conn, do nothing
 
215
        if !c.bad {
 
216
                return false
 
217
        }
 
218
        // alternate between bad conn and not bad conn
 
219
        c.db.badConn = !c.db.badConn
 
220
        return c.db.badConn
 
221
}
 
222
 
202
223
func (c *fakeConn) Begin() (driver.Tx, error) {
 
224
        if c.isBad() {
 
225
                return nil, driver.ErrBadConn
 
226
        }
203
227
        if c.currTx != nil {
204
228
                return nil, errors.New("already in a transaction")
205
229
        }
207
231
        return c.currTx, nil
208
232
}
209
233
 
210
 
func (c *fakeConn) Close() error {
 
234
var hookPostCloseConn struct {
 
235
        sync.Mutex
 
236
        fn func(*fakeConn, error)
 
237
}
 
238
 
 
239
func setHookpostCloseConn(fn func(*fakeConn, error)) {
 
240
        hookPostCloseConn.Lock()
 
241
        defer hookPostCloseConn.Unlock()
 
242
        hookPostCloseConn.fn = fn
 
243
}
 
244
 
 
245
var testStrictClose *testing.T
 
246
 
 
247
// setStrictFakeConnClose sets the t to Errorf on when fakeConn.Close
 
248
// fails to close. If nil, the check is disabled.
 
249
func setStrictFakeConnClose(t *testing.T) {
 
250
        testStrictClose = t
 
251
}
 
252
 
 
253
func (c *fakeConn) Close() (err error) {
 
254
        drv := fdriver.(*fakeDriver)
 
255
        defer func() {
 
256
                if err != nil && testStrictClose != nil {
 
257
                        testStrictClose.Errorf("failed to close a test fakeConn: %v", err)
 
258
                }
 
259
                hookPostCloseConn.Lock()
 
260
                fn := hookPostCloseConn.fn
 
261
                hookPostCloseConn.Unlock()
 
262
                if fn != nil {
 
263
                        fn(c, err)
 
264
                }
 
265
                if err == nil {
 
266
                        drv.mu.Lock()
 
267
                        drv.closeCount++
 
268
                        drv.mu.Unlock()
 
269
                }
 
270
        }()
211
271
        if c.currTx != nil {
212
272
                return errors.New("can't close fakeConn; in a Transaction")
213
273
        }
234
294
 
235
295
func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error) {
236
296
        // This is an optional interface, but it's implemented here
237
 
        // just to check that all the args of of the proper types.
 
297
        // just to check that all the args are of the proper types.
 
298
        // ErrSkip is returned so the caller acts as if we didn't
 
299
        // implement this at all.
 
300
        err := checkSubsetTypes(args)
 
301
        if err != nil {
 
302
                return nil, err
 
303
        }
 
304
        return nil, driver.ErrSkip
 
305
}
 
306
 
 
307
func (c *fakeConn) Query(query string, args []driver.Value) (driver.Rows, error) {
 
308
        // This is an optional interface, but it's implemented here
 
309
        // just to check that all the args are of the proper types.
238
310
        // ErrSkip is returned so the caller acts as if we didn't
239
311
        // implement this at all.
240
312
        err := checkSubsetTypes(args)
249
321
}
250
322
 
251
323
// parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
252
 
// (note that where where columns must always contain ? marks,
 
324
// (note that where columns must always contain ? marks,
253
325
//  just a limitation for fakedb)
254
326
func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
255
327
        if len(parts) != 3 {
383
455
}
384
456
 
385
457
func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
 
458
        if len(s.placeholderConverter) == 0 {
 
459
                return driver.DefaultParameterConverter
 
460
        }
386
461
        return s.placeholderConverter[idx]
387
462
}
388
463
 
389
464
func (s *fakeStmt) Close() error {
 
465
        if s.c == nil {
 
466
                panic("nil conn in fakeStmt.Close")
 
467
        }
 
468
        if s.c.db == nil {
 
469
                panic("in fakeStmt.Close, conn's db is nil (already closed)")
 
470
        }
390
471
        if !s.closed {
391
472
                s.c.incrStat(&s.c.stmtsClosed)
392
473
                s.closed = true
478
559
        if !ok {
479
560
                return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
480
561
        }
 
562
 
 
563
        if s.table == "magicquery" {
 
564
                if len(s.whereCol) == 2 && s.whereCol[0] == "op" && s.whereCol[1] == "millis" {
 
565
                        if args[0] == "sleep" {
 
566
                                time.Sleep(time.Duration(args[1].(int64)) * time.Millisecond)
 
567
                        }
 
568
                }
 
569
        }
 
570
 
481
571
        t.mu.Lock()
482
572
        defer t.mu.Unlock()
483
573
 
598
688
        return nil
599
689
}
600
690
 
 
691
// fakeDriverString is like driver.String, but indirects pointers like
 
692
// DefaultValueConverter.
 
693
//
 
694
// This could be surprising behavior to retroactively apply to
 
695
// driver.String now that Go1 is out, but this is convenient for
 
696
// our TestPointerParamsAndScans.
 
697
//
 
698
type fakeDriverString struct{}
 
699
 
 
700
func (fakeDriverString) ConvertValue(v interface{}) (driver.Value, error) {
 
701
        switch c := v.(type) {
 
702
        case string, []byte:
 
703
                return v, nil
 
704
        case *string:
 
705
                if c == nil {
 
706
                        return nil, nil
 
707
                }
 
708
                return *c, nil
 
709
        }
 
710
        return fmt.Sprintf("%v", v), nil
 
711
}
 
712
 
601
713
func converterForType(typ string) driver.ValueConverter {
602
714
        switch typ {
603
715
        case "bool":
607
719
        case "int32":
608
720
                return driver.Int32
609
721
        case "string":
610
 
                return driver.NotNull{Converter: driver.String}
 
722
                return driver.NotNull{Converter: fakeDriverString{}}
611
723
        case "nullstring":
612
 
                return driver.Null{Converter: driver.String}
 
724
                return driver.Null{Converter: fakeDriverString{}}
613
725
        case "int64":
614
726
                // TODO(coopernurse): add type-specific converter
615
727
                return driver.NotNull{Converter: driver.DefaultParameterConverter}