Test all supported databases in CI (#2000)
* add mysql and postgres tests to CI
This commit is contained in:
parent
bf22a6faf9
commit
7af9e18a49
8 changed files with 172 additions and 25 deletions
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
@ -43,9 +43,15 @@ jobs:
|
|||
name: focalboard-server-linux-amd64.tar.gz
|
||||
path: ${{ github.workspace }}/dist/focalboard-server-linux-amd64.tar.gz
|
||||
|
||||
- name: Test server
|
||||
- name: "Test server: sqlite"
|
||||
run: make server-test
|
||||
|
||||
- name: "Test server: mysql"
|
||||
run: make server-test-mysql
|
||||
|
||||
- name: "Test server: postgres"
|
||||
run: make server-test-postgres
|
||||
|
||||
- name: "Test webapp: Jest"
|
||||
run: cd webapp; npm run test
|
||||
|
||||
|
|
22
Makefile
22
Makefile
|
@ -105,6 +105,28 @@ watch-server-test: modd-precheck ## Run server tests watching for changes
|
|||
server-test: ## Run server tests
|
||||
cd server; go test -race -v -count=1 ./...
|
||||
|
||||
|
||||
|
||||
server-test-mysql: export FB_UNIT_TESTING=1
|
||||
server-test-mysql: export FB_STORE_TEST_DB_TYPE=mysql
|
||||
server-test-mysql: export FB_STORE_TEST_DOCKER_PORT=44445
|
||||
|
||||
server-test-mysql: ## Run server tests using mysql
|
||||
@echo Starting docker container for mysql
|
||||
docker-compose -f ./docker-testing/docker-compose-mysql.yml run start_dependencies
|
||||
cd server; go test -race -v -count=1 ./...
|
||||
docker-compose -f ./docker-testing/docker-compose-mysql.yml down -v --remove-orphans
|
||||
|
||||
server-test-postgres: export FB_UNIT_TESTING=1
|
||||
server-test-postgres: export FB_STORE_TEST_DB_TYPE=postgres
|
||||
server-test-postgres: export FB_STORE_TEST_DOCKER_PORT=44446
|
||||
|
||||
server-test-postgres: ## Run server tests using postgres
|
||||
@echo Starting docker container for postgres
|
||||
docker-compose -f ./docker-testing/docker-compose-postgres.yml run start_dependencies
|
||||
cd server; go test -race -v -count=1 ./...
|
||||
docker-compose -f ./docker-testing/docker-compose-postgres.yml down -v --remove-orphans
|
||||
|
||||
webapp: ## Build webapp.
|
||||
cd webapp; npm run pack
|
||||
|
||||
|
|
25
docker-testing/docker-compose-mysql.yml
Normal file
25
docker-testing/docker-compose-mysql.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
version: '2.4'
|
||||
services:
|
||||
mysql:
|
||||
image: "mysql/mysql-server:5.7.12"
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_HOST: "%"
|
||||
MYSQL_ROOT_PASSWORD: mostest
|
||||
MYSQL_PASSWORD: mostest
|
||||
MYSQL_USER: mmuser
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
tmpfs: /var/lib/mysql
|
||||
ports:
|
||||
- 44445:3306
|
||||
|
||||
start_dependencies:
|
||||
image: mattermost/mattermost-wait-for-dep:latest
|
||||
depends_on:
|
||||
- mysql
|
||||
command: mysql
|
||||
|
23
docker-testing/docker-compose-postgres.yml
Normal file
23
docker-testing/docker-compose-postgres.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
version: '2.4'
|
||||
services:
|
||||
postgres:
|
||||
image: "postgres:10"
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: mmuser
|
||||
POSTGRES_PASSWORD: mostest
|
||||
healthcheck:
|
||||
test: [ "CMD", "pg_isready", "-h", "localhost" ]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
tmpfs: /var/lib/postgresql/data
|
||||
ports:
|
||||
- 44446:5432
|
||||
|
||||
start_dependencies:
|
||||
image: mattermost/mattermost-wait-for-dep:latest
|
||||
depends_on:
|
||||
- postgres
|
||||
command: postgres:5432
|
||||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/mattermost/focalboard/server/client"
|
||||
"github.com/mattermost/focalboard/server/server"
|
||||
"github.com/mattermost/focalboard/server/services/config"
|
||||
"github.com/mattermost/focalboard/server/services/store/sqlstore"
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
@ -21,15 +22,10 @@ type TestHelper struct {
|
|||
Client2 *client.Client
|
||||
}
|
||||
|
||||
func getTestConfig() *config.Configuration {
|
||||
dbType := os.Getenv("FB_STORE_TEST_DB_TYPE")
|
||||
if dbType == "" {
|
||||
dbType = "sqlite3"
|
||||
}
|
||||
|
||||
connectionString := os.Getenv("FB_STORE_TEST_CONN_STRING")
|
||||
if connectionString == "" {
|
||||
connectionString = ":memory:"
|
||||
func getTestConfig() (*config.Configuration, error) {
|
||||
dbType, connectionString, err := sqlstore.PrepareNewTestDatabase()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logging := `
|
||||
|
@ -66,15 +62,19 @@ func getTestConfig() *config.Configuration {
|
|||
LoggingCfgJSON: logging,
|
||||
SessionExpireTime: int64(30 * time.Second),
|
||||
AuthMode: "native",
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newTestServer(singleUserToken string) *server.Server {
|
||||
logger, _ := mlog.NewLogger()
|
||||
if err := logger.Configure("", getTestConfig().LoggingCfgJSON, nil); err != nil {
|
||||
cfg, err := getTestConfig()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logger, _ := mlog.NewLogger()
|
||||
if err = logger.Configure("", cfg.LoggingCfgJSON, nil); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cfg := getTestConfig()
|
||||
db, err := server.NewStore(cfg, logger)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -182,7 +182,7 @@ func (s *SQLStore) getSubTree3(db sq.BaseRunner, c store.Container, blockID stri
|
|||
Join(s.tablePrefix + "blocks" + " as l3 on l3.parent_id = l2.id or l3.id = l2.id").
|
||||
Where(sq.Eq{"l1.id": blockID}).
|
||||
Where(sq.Eq{"COALESCE(l3.workspace_id, '0')": c.WorkspaceID}).
|
||||
OrderBy("l3.insert_at")
|
||||
OrderBy("l3.id, l3.insert_at")
|
||||
|
||||
if opts.BeforeUpdateAt != 0 {
|
||||
query = query.Where(sq.LtOrEq{"update_at": opts.BeforeUpdateAt})
|
||||
|
|
|
@ -2,7 +2,6 @@ package sqlstore
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
|
@ -12,15 +11,8 @@ import (
|
|||
)
|
||||
|
||||
func SetupTests(t *testing.T) (store.Store, func()) {
|
||||
dbType := os.Getenv("FB_STORE_TEST_DB_TYPE")
|
||||
if dbType == "" {
|
||||
dbType = sqliteDBType
|
||||
}
|
||||
|
||||
connectionString := os.Getenv("FB_STORE_TEST_CONN_STRING")
|
||||
if connectionString == "" {
|
||||
connectionString = ":memory:"
|
||||
}
|
||||
dbType, connectionString, err := PrepareNewTestDatabase()
|
||||
require.NoError(t, err)
|
||||
|
||||
logger := mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)
|
||||
|
||||
|
|
|
@ -2,8 +2,12 @@ package sqlstore
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
@ -17,3 +21,78 @@ func (s *SQLStore) CloseRows(rows *sql.Rows) {
|
|||
func (s *SQLStore) IsErrNotFound(err error) bool {
|
||||
return store.IsErrNotFound(err)
|
||||
}
|
||||
|
||||
func PrepareNewTestDatabase() (dbType string, connectionString string, err error) {
|
||||
dbType = strings.TrimSpace(os.Getenv("FB_STORE_TEST_DB_TYPE"))
|
||||
if dbType == "" {
|
||||
dbType = sqliteDBType
|
||||
}
|
||||
|
||||
var dbName string
|
||||
var rootUser string
|
||||
|
||||
if dbType == sqliteDBType {
|
||||
connectionString = ":memory:"
|
||||
} else if port := strings.TrimSpace(os.Getenv("FB_STORE_TEST_DOCKER_PORT")); port != "" {
|
||||
// docker unit tests take priority over any DSN env vars
|
||||
var template string
|
||||
switch dbType {
|
||||
case mysqlDBType:
|
||||
template = "%s:mostest@tcp(localhost:%s)/%s?charset=utf8mb4,utf8&writeTimeout=30s"
|
||||
rootUser = "root"
|
||||
case postgresDBType:
|
||||
template = "postgres://%s:mostest@localhost:%s/%s?sslmode=disable\u0026connect_timeout=10"
|
||||
rootUser = "mmuser"
|
||||
default:
|
||||
return "", "", newErrInvalidDBType(dbType)
|
||||
}
|
||||
|
||||
connectionString = fmt.Sprintf(template, rootUser, port, "")
|
||||
|
||||
// create a new database each run
|
||||
sqlDB, err := sql.Open(dbType, connectionString)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("cannot connect to %s database: %w", dbType, err)
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
|
||||
err = sqlDB.Ping()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("cannot ping %s database: %w", dbType, err)
|
||||
}
|
||||
|
||||
dbName = "testdb_" + utils.NewID(utils.IDTypeNone)[:8]
|
||||
_, err = sqlDB.Exec(fmt.Sprintf("CREATE DATABASE %s;", dbName))
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("cannot create %s database %s: %w", dbType, dbName, err)
|
||||
}
|
||||
|
||||
if dbType != postgresDBType {
|
||||
_, err = sqlDB.Exec(fmt.Sprintf("GRANT ALL PRIVILEGES ON %s.* TO mmuser;", dbName))
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("cannot grant permissions on %s database %s: %w", dbType, dbName, err)
|
||||
}
|
||||
}
|
||||
|
||||
connectionString = fmt.Sprintf(template, "mmuser", port, dbName)
|
||||
} else {
|
||||
// mysql or postgres need a DSN (connection string)
|
||||
connectionString = strings.TrimSpace(os.Getenv("FB_STORE_TEST_CONN_STRING"))
|
||||
}
|
||||
|
||||
return dbType, connectionString, nil
|
||||
}
|
||||
|
||||
type ErrInvalidDBType struct {
|
||||
dbType string
|
||||
}
|
||||
|
||||
func newErrInvalidDBType(dbType string) error {
|
||||
return ErrInvalidDBType{
|
||||
dbType: dbType,
|
||||
}
|
||||
}
|
||||
|
||||
func (e ErrInvalidDBType) Error() string {
|
||||
return "unsupported database type: " + e.dbType
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue