blob: 3b20290699fc2f93df54d5b484f30544fefc8f75 [file] [edit]
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package fakedb provides a minimal fake implementation for a database/sql database,
// to be used in tests.
package fakedb
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"io"
)
// Queries supported by the fake database. Each query will return a different number
// of rows, but no actual content.
const (
QueryNoRows = "SELECT 1 WHERE FALSE"
QueryOneRow = "SELECT 1"
QueryError = "INVALID QUERY"
ErrorMsg = "invalid query"
)
func init() {
sql.Register("fakedb", &fakeDriver{})
}
// FakeDB is a fake implementation of sql.DB.
type FakeDB struct{}
// Open creates a new sql.DB object that supports the queries defined in fakedb.
func Open(*FakeDB) (*sql.DB, error) {
return sql.Open("fakedb", "fakedsn")
}
// fakeDriver is a fake implementation of sql.Driver.
type fakeDriver struct{}
// Open is a fake implementation for the sql.Driver interface.
func (d *fakeDriver) Open(name string) (driver.Conn, error) {
return &fakeConn{&FakeDB{}}, nil
}
// fakeConn is a fake implementation of sql.Conn.
type fakeConn struct {
db *FakeDB
}
// Close is a fake implementation for the sql.Conn interface.
func (*fakeConn) Close() error { return nil }
// Begin is a fake implementation for the sql.Conn interface.
func (*fakeConn) Begin() (driver.Tx, error) { return nil, nil }
// Prepare is a fake implementation for the sql.Conn interface.
func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
return &fakeStmt{db: c.db, query: query}, nil
}
// fakeStmt is a fake implementation of driver.Stmt.
type fakeStmt struct {
db *FakeDB
query string
}
// Close is a fake implementation for the driver.Stmt interface.
func (*fakeStmt) Close() error { return nil }
// Exec is a fake implementation for the driver.Stmt interface.
func (*fakeStmt) Exec(args []driver.Value) (driver.Result, error) { return nil, nil }
// NumInput is a fake implementation for the driver.Stmt interface.
func (*fakeStmt) NumInput() int { return 0 }
// Query supports a few selected queries defined in the fakedb package.
func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
switch s.query {
case QueryNoRows:
return &fakeRows{rowsLeft: 0}, nil
case QueryOneRow:
return &fakeRows{rowsLeft: 1}, nil
case QueryError:
return nil, errors.New(ErrorMsg)
default:
return nil, fmt.Errorf("the query %q is not supported by fakeStmt", s.query)
}
}
// fakeRows is a fake implementation of driver.Rows.
// We only care about the number of returned rows, so we don't model their content.
type fakeRows struct {
rowsLeft int
}
// Close is a fake implementation for the driver.Rows interface.
func (*fakeRows) Close() error { return nil }
// Columns is a fake implementation for the driver.Rows interface.
func (*fakeRows) Columns() []string { return nil }
// Next is a fake implementation for the driver.Rows interface.
// The function iterates through the number of known rows, but returns no values.
func (r *fakeRows) Next(dst []driver.Value) error {
if r.rowsLeft > 0 {
r.rowsLeft--
return nil
}
return io.EOF
}