Skip to content

Commit

Permalink
Merge pull request #56 from JustSkiv/add-mysql-support-fixtures
Browse files Browse the repository at this point in the history
Add mysql support in fixtures
Denis authored Sep 3, 2020
2 parents 15b8a86 + cc25451 commit 526496b
Showing 11 changed files with 1,410 additions and 540 deletions.
518 changes: 43 additions & 475 deletions fixtures/loader.go

Large diffs are not rendered by default.

554 changes: 554 additions & 0 deletions fixtures/mysql/mysql.go

Large diffs are not rendered by default.

237 changes: 237 additions & 0 deletions fixtures/mysql/mysql_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package mysql

import (
"database/sql"
"database/sql/driver"
"fmt"
"io/ioutil"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/DATA-DOG/go-sqlmock.v1"
)

func TestBuildInsertQuery(t *testing.T) {

ymlFile, err := ioutil.ReadFile("../testdata/table.yaml")
require.NoError(t, err)

expected := []string{
"INSERT INTO `table` (`field1`, `field2`) VALUES ('value1', 1)",
"INSERT INTO `table` (`field1`, `field2`, `field3`) VALUES ('value2', 2, 2.5699477736545666)",
"INSERT INTO `table` (`field1`, `field4`, `field5`) VALUES ('\"', false, NULL)",
"INSERT INTO `table` (`field1`, `field5`) VALUES ('''', '[1,\"2\"]')",
}

ctx := loadContext{
refsDefinition: make(map[string]row),
refsInserted: make(map[string]row),
}

l := New(&sql.DB{}, "", false)

require.NoError(t,
l.loadYml(ymlFile, &ctx),
)

for i, row := range ctx.tables[0].Rows {
query, err := l.buildInsertQuery(&ctx, "table", row)
require.NoError(t, err)

assert.Equal(t, expected[i], query)
}
}

func TestLoadTablesShouldResolveRefs(t *testing.T) {
yml, err := ioutil.ReadFile("../testdata/table_refs.yaml")
require.NoError(t, err)

db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer func() { _ = db.Close() }()

ctx := loadContext{
refsDefinition: make(map[string]row),
refsInserted: make(map[string]row),
}

l := New(db, "", true)

if err = l.loadYml(yml, &ctx); err != nil {
t.Error(err)
t.Fail()
}

mock.ExpectBegin()

expectTruncate(mock, "table1")
expectTruncate(mock, "table2")
expectTruncate(mock, "table3")

// table1
expectInsert(t, mock,
"table1",
[]string{"f1", "f2"},
"\\('value1', 'value2'\\)",
[]string{"value1", "value2"},
)

// table2
expectInsert(t, mock,
"table2",
[]string{"f1", "f2"},
"\\('value2', 'value1'\\)",
[]string{"value2", "value1"},
)

// table1
expectInsert(t, mock,
"table3",
[]string{"f1", "f2"},
"\\('value1', 'value2'\\)",
[]string{"value1", "value2"},
)

mock.ExpectCommit()

err = l.loadTables(&ctx)
if err != nil {
t.Error(err)
t.Fail()
}

if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
t.Fail()
}
}

func TestLoadTablesShouldExtendRows(t *testing.T) {
yml, err := ioutil.ReadFile("../testdata/table_extend.yaml")
require.NoError(t, err)

db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer func() { _ = db.Close() }()

ctx := loadContext{
refsDefinition: make(map[string]row),
refsInserted: make(map[string]row),
}

l := New(db, "", true)

if err = l.loadYml(yml, &ctx); err != nil {
t.Error(err)
t.Fail()
}

mock.ExpectBegin()

expectTruncate(mock, "table1")
expectTruncate(mock, "table2")
expectTruncate(mock, "table3")

// table1
expectInsert(t, mock,
"table1",
[]string{"f1", "f2"},
"\\('value1', 'value2'\\)",
[]string{"value1", "value2"},
)

// table2
expectInsert(t, mock,
"table2",
[]string{"f1", "f2", "f3"},
"\\('value1 overwritten', 'value2', "+`\("1" \|\| "2" \|\| 3 \+ 5\)\)$`,
[]string{"value1 overwritten", "value2", `1`},
)

// table3, data 1
expectInsert(t, mock,
"table3",
[]string{"f1", "f2", "f3"},
"\\('value1 overwritten', 'value2', "+`\("1" \|\| "2" \|\| 3 \+ 5\)\)$`,
[]string{"value1 overwritten", "value2", `1`},
)

// table3, data 2
expectInsert(t, mock,
"table3",
[]string{"f1", "f2"},
"\\('tplVal1', 'tplVal2'\\)",
[]string{"tplVal1", "tplVal2"},
)

mock.ExpectCommit()

err = l.loadTables(&ctx)
if err != nil {
t.Error(err)
t.Fail()
}

if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
t.Fail()
}
}

var idCounter int64

func expectInsert(
t *testing.T,
mock sqlmock.Sqlmock,
table string,
fields []string,
valuesToInsert string,
valuesResult []string,
) {

t.Helper()

idCounter++

mock.ExpectExec(
fmt.Sprintf("^INSERT INTO `%s` %s VALUES %s$",
table,
fieldsToDbStr(fields),
valuesToInsert,
),
).
WillReturnResult(sqlmock.NewResult(idCounter, 1))

var valuesRow []driver.Value
for _, v := range valuesResult {
valuesRow = append(valuesRow, driver.Value(v))
}

mock.ExpectQuery(fmt.Sprintf("^SELECT \\* FROM `%s` WHERE `id` = \\?$", table)).
WithArgs(idCounter).
WillReturnRows(
sqlmock.NewRows(fields).
AddRow(valuesRow...),
)
}

func expectTruncate(mock sqlmock.Sqlmock, table string) {
mock.ExpectExec(fmt.Sprintf("^TRUNCATE TABLE `%s`$", table)).
WillReturnResult(sqlmock.NewResult(0, 0))
}

func fieldsToDbStr(values []string) string {
quotedVals := make([]string, len(values))

for i, val := range values {
quotedVals[i] = "`" + val + "`"
}

return "\\(" + strings.Join(quotedVals, ", ") + "\\)"
}
496 changes: 496 additions & 0 deletions fixtures/postgres/postgres.go

Large diffs are not rendered by default.

80 changes: 18 additions & 62 deletions fixtures/loader_test.go → fixtures/postgres/postgres_test.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
package fixtures
package postgres

import (
"database/sql"
"io/ioutil"
"testing"

"github.com/stretchr/testify/require"
"gopkg.in/DATA-DOG/go-sqlmock.v1"
)

func TestBuildInsertQuery(t *testing.T) {
yml := `
tables:
table:
- field1: "value1"
field2: 1
- field1: "value2"
field2: 2
field3: 2.569947773654566473
- field4: false
field5: null
field1: '"'
- field1: "'"
field5:
- 1
- '2'
`
yml, err := ioutil.ReadFile("../testdata/table.yaml")
require.NoError(t, err)

expected := "INSERT INTO \"table\" AS table_table_gonkey (\"field1\", \"field2\", \"field3\", \"field4\", \"field5\") VALUES " +
"('value1', 1, default, default, default), " +
"('value2', 2, 2.5699477736545666, default, default), " +
@@ -35,8 +25,9 @@ tables:
refsInserted: make(map[string]row),
}

l := NewLoader(&Config{})
l.loadYml([]byte(yml), &ctx)
l := New(&sql.DB{}, "", false)
err = l.loadYml(yml, &ctx)
require.NoError(t, err)

query, err := l.buildInsertQuery(&ctx, "table", ctx.tables[0].Rows)

@@ -52,35 +43,21 @@ tables:
}

func TestLoadTablesShouldResolveRefs(t *testing.T) {
yml := `
tables:
table1:
- $name: ref1
f1: value1
f2: value2
table2:
- $name: ref2
f1: $ref1.f2
f2: $ref1.f1
table3:
- f1: $ref1.f1
f2: $ref2.f1
`
yml, err := ioutil.ReadFile("../testdata/table_refs.yaml")
require.NoError(t, err)

db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()
defer func() { _ = db.Close() }()

ctx := loadContext{
refsDefinition: make(map[string]row),
refsInserted: make(map[string]row),
}

l := NewLoader(&Config{DB: db, Debug: true})
l := New(db, "", true)

err = l.loadYml([]byte(yml), &ctx)
if err != nil {
@@ -147,42 +124,21 @@ tables:
}

func TestLoadTablesShouldExtendRows(t *testing.T) {
yml := `
templates:
baseTpl:
f1: tplVal1
ref3:
$extend: baseTpl
f2: tplVal2
tables:
table1:
- $name: ref1
f1: value1
f2: value2
table2:
- $name: ref2
$extend: ref1
f1: value1 overwritten
f3: $eval("1" || "2" || 3 + 5)
table3:
- $extend: ref2
- $extend: ref3
`
yml, err := ioutil.ReadFile("../testdata/table_extend.yaml")
require.NoError(t, err)

db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()
defer func() { _ = db.Close() }()

ctx := loadContext{
refsDefinition: make(map[string]row),
refsInserted: make(map[string]row),
}

l := NewLoader(&Config{DB: db, Debug: true})
l := New(db, "", true)

err = l.loadYml([]byte(yml), &ctx)
if err != nil {
14 changes: 14 additions & 0 deletions fixtures/testdata/table.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
tables:
table:
- field1: "value1"
field2: 1
- field1: "value2"
field2: 2
field3: 2.569947773654566473
- field4: false
field5: null
field1: '"'
- field1: "'"
field5:
- 1
- '2'
21 changes: 21 additions & 0 deletions fixtures/testdata/table_extend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
templates:
baseTpl:
f1: tplVal1
ref3:
$extend: baseTpl
f2: tplVal2
tables:
table1:
- $name: ref1
f1: value1
f2: value2

table2:
- $name: ref2
$extend: ref1
f1: value1 overwritten
f3: $eval("1" || "2" || 3 + 5)

table3:
- $extend: ref2
- $extend: ref3
14 changes: 14 additions & 0 deletions fixtures/testdata/table_refs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
tables:
table1:
- $name: ref1
f1: value1
f2: value2

table2:
- $name: ref2
f1: $ref1.f2
f2: $ref1.f1

table3:
- f1: $ref1.f1
f2: $ref2.f1
10 changes: 9 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ func main() {
Allure bool
Verbose bool
Debug bool
DbType string
}

flag.StringVar(&config.Host, "host", "", "Target system hostname")
@@ -43,6 +44,12 @@ func main() {
flag.BoolVar(&config.Allure, "allure", true, "Make Allure report")
flag.BoolVar(&config.Verbose, "v", false, "Verbose output")
flag.BoolVar(&config.Debug, "debug", false, "Debug output")
flag.StringVar(
&config.EnvFile,
"db-type",
fixtures.PostgresParam,
"Type of database (options: postgres, mysql)",
)

flag.Parse()

@@ -68,12 +75,13 @@ func main() {
}
}

var fixturesLoader *fixtures.Loader
var fixturesLoader fixtures.Loader
if db != nil && config.FixturesLocation != "" {
fixturesLoader = fixtures.NewLoader(&fixtures.Config{
DB: db,
Location: config.FixturesLocation,
Debug: config.Debug,
DbType: fixtures.FetchDbType(config.DbType),
})
} else if config.FixturesLocation != "" {
log.Fatal(errors.New("you should specify db_dsn to load fixtures"))
2 changes: 1 addition & 1 deletion runner/runner.go
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ import (

type Config struct {
Host string
FixturesLoader *fixtures.Loader
FixturesLoader fixtures.Loader
Mocks *mocks.Mocks
MocksLoader *mocks.Loader
Variables *variables.Variables
4 changes: 3 additions & 1 deletion runner/runner_testing.go
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ type RunWithTestingParams struct {
Mocks *mocks.Mocks
FixturesDir string
DB *sql.DB
DbType fixtures.DbType
EnvFilePath string
}

@@ -44,12 +45,13 @@ func RunWithTesting(t *testing.T, params *RunWithTestingParams) {

debug := os.Getenv("GONKEY_DEBUG") != ""

var fixturesLoader *fixtures.Loader
var fixturesLoader fixtures.Loader
if params.DB != nil {
fixturesLoader = fixtures.NewLoader(&fixtures.Config{
Location: params.FixturesDir,
DB: params.DB,
Debug: debug,
DbType: params.DbType,
})
}

0 comments on commit 526496b

Please sign in to comment.