summaryrefslogtreecommitdiffstats
path: root/libgo/go/exp/sql/fakedb_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/exp/sql/fakedb_test.go')
-rw-r--r--libgo/go/exp/sql/fakedb_test.go72
1 files changed, 62 insertions, 10 deletions
diff --git a/libgo/go/exp/sql/fakedb_test.go b/libgo/go/exp/sql/fakedb_test.go
index 2474a86f644..70aa68c1385 100644
--- a/libgo/go/exp/sql/fakedb_test.go
+++ b/libgo/go/exp/sql/fakedb_test.go
@@ -12,6 +12,7 @@ import (
"strconv"
"strings"
"sync"
+ "time"
"exp/sql/driver"
)
@@ -77,6 +78,17 @@ type fakeConn struct {
db *fakeDB // where to return ourselves to
currTx *fakeTx
+
+ // Stats for tests:
+ mu sync.Mutex
+ stmtsMade int
+ stmtsClosed int
+}
+
+func (c *fakeConn) incrStat(v *int) {
+ c.mu.Lock()
+ *v++
+ c.mu.Unlock()
}
type fakeTx struct {
@@ -110,25 +122,34 @@ func init() {
// Supports dsn forms:
// <dbname>
-// <dbname>;wipe
+// <dbname>;<opts> (no currently supported options)
func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
- d.mu.Lock()
- defer d.mu.Unlock()
- d.openCount++
- if d.dbs == nil {
- d.dbs = make(map[string]*fakeDB)
- }
parts := strings.Split(dsn, ";")
if len(parts) < 1 {
return nil, errors.New("fakedb: no database name")
}
name := parts[0]
+
+ db := d.getDB(name)
+
+ d.mu.Lock()
+ d.openCount++
+ d.mu.Unlock()
+ return &fakeConn{db: db}, nil
+}
+
+func (d *fakeDriver) getDB(name string) *fakeDB {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ if d.dbs == nil {
+ d.dbs = make(map[string]*fakeDB)
+ }
db, ok := d.dbs[name]
if !ok {
db = &fakeDB{name: name}
d.dbs[name] = db
}
- return &fakeConn{db: db}, nil
+ return db
}
func (db *fakeDB) wipe() {
@@ -200,7 +221,7 @@ func (c *fakeConn) Close() error {
func checkSubsetTypes(args []interface{}) error {
for n, arg := range args {
switch arg.(type) {
- case int64, float64, bool, nil, []byte, string:
+ case int64, float64, bool, nil, []byte, string, time.Time:
default:
return fmt.Errorf("fakedb_test: invalid argument #%d: %v, type %T", n+1, arg, arg)
}
@@ -297,6 +318,8 @@ func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, e
switch ctype {
case "string":
subsetVal = []byte(value)
+ case "blob":
+ subsetVal = []byte(value)
case "int32":
i, err := strconv.Atoi(value)
if err != nil {
@@ -327,6 +350,7 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
cmd := parts[0]
parts = parts[1:]
stmt := &fakeStmt{q: query, c: c, cmd: cmd}
+ c.incrStat(&c.stmtsMade)
switch cmd {
case "WIPE":
// Nothing
@@ -347,7 +371,10 @@ func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
}
func (s *fakeStmt) Close() error {
- s.closed = true
+ if !s.closed {
+ s.c.incrStat(&s.c.stmtsClosed)
+ s.closed = true
+ }
return nil
}
@@ -501,9 +528,19 @@ type rowsCursor struct {
pos int
rows []*row
closed bool
+
+ // a clone of slices to give out to clients, indexed by the
+ // the original slice's first byte address. we clone them
+ // just so we're able to corrupt them on close.
+ bytesClone map[*byte][]byte
}
func (rc *rowsCursor) Close() error {
+ if !rc.closed {
+ for _, bs := range rc.bytesClone {
+ bs[0] = 255 // first byte corrupted
+ }
+ }
rc.closed = true
return nil
}
@@ -528,6 +565,19 @@ func (rc *rowsCursor) Next(dest []interface{}) error {
// for ease of drivers, and to prevent drivers from
// messing up conversions or doing them differently.
dest[i] = v
+
+ if bs, ok := v.([]byte); ok {
+ if rc.bytesClone == nil {
+ rc.bytesClone = make(map[*byte][]byte)
+ }
+ clone, ok := rc.bytesClone[&bs[0]]
+ if !ok {
+ clone = make([]byte, len(bs))
+ copy(clone, bs)
+ rc.bytesClone[&bs[0]] = clone
+ }
+ dest[i] = clone
+ }
}
return nil
}
@@ -540,6 +590,8 @@ func converterForType(typ string) driver.ValueConverter {
return driver.Int32
case "string":
return driver.String
+ case "datetime":
+ return driver.DefaultParameterConverter
}
panic("invalid fakedb column type of " + typ)
}
OpenPOWER on IntegriCloud