Skip to content

Commit

Permalink
Add compatibility tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Dec 10, 2020
1 parent cc08ed9 commit 12b9df2
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 31 deletions.
33 changes: 33 additions & 0 deletions compat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package sqltest

var (
// DriversByProduct maps a Product to the Driver implementations that it is
// compatible with.
DriversByProduct = map[Product][]Driver{}

// ProductsByDriver maps a Driver to the Product implementations that it is
// compatible with.
ProductsByDriver = map[Driver][]Product{}

// CompatiblePairs contains all compatible driver/product pairs.
CompatiblePairs []Pair
)

// Pair is a struct containing a driver and product that are compatible with
// each other.
type Pair struct {
Driver Driver
Product Product
}

func init() {
for _, d := range Drivers {
for _, p := range Products {
if p.IsCompatibleWith(d) {
DriversByProduct[p] = append(DriversByProduct[p], d)
ProductsByDriver[d] = append(ProductsByDriver[d], p)
CompatiblePairs = append(CompatiblePairs, Pair{d, p})
}
}
}
}
16 changes: 8 additions & 8 deletions database.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ func (db *Database) Close() error {
// It first checks for an environment variable containing a DSN. If that is not
// present it askes the product to generate a default DSN.
func dataSource(d Driver, p Product) (DataSource, error) {
if !p.IsCompatibleWith(d) {
return nil, fmt.Errorf(
"%s is incompatible with the '%s' driver",
p.Name(),
d.Name(),
)
}

key := strings.ToUpper(fmt.Sprintf("DOGMATIQ_TEST_DSN_%s_%s", p.Name(), d.Name()))
dsn := os.Getenv(key)

Expand All @@ -159,14 +167,6 @@ func dataSource(d Driver, p Product) (DataSource, error) {

ds, err := p.DefaultDataSource(d)

if errors.Is(err, ErrIncompatibleDriver) {
return nil, fmt.Errorf(
"%s is incompatible with the '%s' driver",
p.Name(),
d.Name(),
)
}

if err != nil {
return nil, fmt.Errorf(
"can not build a default %s DSN using the '%s' driver: %w",
Expand Down
8 changes: 8 additions & 0 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,12 @@ var (

// SQLite3Driver is the "sqlite3" driver (github.com/mattn/go-sqlite3).
SQLite3Driver Driver = sqlite3Driver{}

// Drivers is a slice containing all known products.
Drivers = []Driver{
MySQLDriver,
PGXDriver,
PostgresDriver,
SQLite3Driver,
}
)
16 changes: 11 additions & 5 deletions product.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@ package sqltest
import (
"context"
"database/sql"
"errors"
)

// ErrIncompatibleDriver indicates that a specific driver can not be used to
// connect to a specific product.
var ErrIncompatibleDriver = errors.New("the driver is not compatible with the product")

// Product is a specific database product such as MySQL or MariaDB.
//
// The product correlates with a running service that tests are run against.
Expand All @@ -18,6 +13,9 @@ type Product interface {
// Name returns the human-readable name of the product.
Name() string

// IsCompatibleWith return true if the product is compatible with d.
IsCompatibleWith(d Driver) bool

// DefaultDataSource returns the default data source to use to connect to
// the product.
//
Expand Down Expand Up @@ -64,4 +62,12 @@ var (

// SQLite is the Product for SQLite (https://www.sqlite.org).
SQLite Product = sqliteProduct{}

// Products is a slice containing all known products.
Products = []Product{
MySQL,
MariaDB,
PostgreSQL,
SQLite,
}
)
13 changes: 7 additions & 6 deletions productmysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ func (p MySQLCompatibleProduct) Name() string {
return p.ProductName
}

// IsCompatibleWith return true if the product is compatible with d.
func (p MySQLCompatibleProduct) IsCompatibleWith(d Driver) bool {
_, ok := d.(MySQLProtocol)
return ok
}

// DefaultDataSource returns the default data source to use to connect to the
// product.
func (p MySQLCompatibleProduct) DefaultDataSource(d Driver) (DataSource, error) {
proto, ok := d.(MySQLProtocol)
if !ok {
return nil, ErrIncompatibleDriver
}

return proto.DataSourceForMySQL(
return d.(MySQLProtocol).DataSourceForMySQL(
"root", "rootpass",
"127.0.0.1", p.DefaultPort,
"mysql",
Expand Down
13 changes: 7 additions & 6 deletions productpostgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ func (p PostgresCompatibleProduct) Name() string {
return p.ProductName
}

// IsCompatibleWith return true if the product is compatible with d.
func (p PostgresCompatibleProduct) IsCompatibleWith(d Driver) bool {
_, ok := d.(PostgresProtocol)
return ok
}

// DefaultDataSource returns the default data source to use to connect to the
// product.
func (p PostgresCompatibleProduct) DefaultDataSource(d Driver) (DataSource, error) {
proto, ok := d.(PostgresProtocol)
if !ok {
return nil, ErrIncompatibleDriver
}

return proto.DataSourceForPostgres(
return d.(PostgresProtocol).DataSourceForPostgres(
"postgres", "rootpass",
"127.0.0.1", p.DefaultPort,
"", // default database
Expand Down
12 changes: 6 additions & 6 deletions productsqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ func (sqliteProduct) Name() string {
return "SQLite"
}

func (sqliteProduct) DefaultDataSource(d Driver) (DataSource, error) {
proto, ok := d.(SQLiteProtocol)
if !ok {
return nil, ErrIncompatibleDriver
}
func (sqliteProduct) IsCompatibleWith(d Driver) bool {
_, ok := d.(SQLiteProtocol)
return ok
}

return proto.DataSourceForSQLite(
func (sqliteProduct) DefaultDataSource(d Driver) (DataSource, error) {
return d.(SQLiteProtocol).DataSourceForSQLite(
filepath.Join(os.TempDir(), "dogmatiq.sqlite3"),
)
}

0 comments on commit 12b9df2

Please sign in to comment.