Improve code coverage.

This commit is contained in:
go-jet 2019-09-20 13:55:07 +02:00
parent acd9d20339
commit f5287628aa
15 changed files with 155 additions and 79 deletions

4
NOTICE
View file

@ -8,3 +8,7 @@ https://github.com/dropbox/godropbox/tree/master/database/sqlbuilder (BSD-3)
This product contains a modified portion of 'snaker' which can be obtained at: This product contains a modified portion of 'snaker' which can be obtained at:
https://github.com/serenize/snaker (MIT) https://github.com/serenize/snaker (MIT)
This product contains `FormatTimestamp` function from 'pq' which can be obtained at:
https://github.com/lib/pq (MIT)

View file

@ -91,9 +91,7 @@ func jsonSave(path string, v interface{}) {
err := ioutil.WriteFile(path, jsonText, 0644) err := ioutil.WriteFile(path, jsonText, 0644)
if err != nil { panicOnError(err)
panic(err)
}
} }
func printStatementInfo(stmt SelectStatement) { func printStatementInfo(stmt SelectStatement) {

View file

@ -813,9 +813,7 @@ func (s *scanContext) rowElem(index int) interface{} {
value, err := valuer.Value() value, err := valuer.Value()
if err != nil { utils.PanicOnError(err)
panic(err)
}
return value return value
} }

View file

@ -12,6 +12,7 @@ type SchemaMetaData struct {
EnumsMetaData []MetaData EnumsMetaData []MetaData
} }
// IsEmpty returns true if schema info does not contain any table, views or enums metadata
func (s SchemaMetaData) IsEmpty() bool { func (s SchemaMetaData) IsEmpty() bool {
return len(s.TablesMetaData) == 0 && len(s.ViewsMetaData) == 0 && len(s.EnumsMetaData) == 0 return len(s.TablesMetaData) == 0 && len(s.ViewsMetaData) == 0 && len(s.EnumsMetaData) == 0
} }

View file

@ -0,0 +1,42 @@
package pq
// Copyright (c) 2011-2013, 'pq' Contributors Portions Copyright (C) 2011 Blake Mizerany
import (
"strconv"
"time"
)
// FormatTimestamp formats t into Postgres' text format for timestamps. From: github.com/lib/pq
func FormatTimestamp(t time.Time) []byte {
// Need to send dates before 0001 A.D. with " BC" suffix, instead of the
// minus sign preferred by Go.
// Beware, "0000" in ISO is "1 BC", "-0001" is "2 BC" and so on
bc := false
if t.Year() <= 0 {
// flip year sign, and add 1, e.g: "0" will be "1", and "-10" will be "11"
t = t.AddDate((-t.Year())*2+1, 0, 0)
bc = true
}
b := []byte(t.Format("2006-01-02 15:04:05.999999999Z07:00"))
_, offset := t.Zone()
offset = offset % 60
if offset != 0 {
// RFC3339Nano already printed the minus sign
if offset < 0 {
offset = -offset
}
b = append(b, ':')
if offset < 10 {
b = append(b, '0')
}
b = strconv.AppendInt(b, int64(offset), 10)
}
if bc {
b = append(b, " BC"...)
}
return b
}

View file

@ -0,0 +1,39 @@
package pq
// Copyright (c) 2011-2013, 'pq' Contributors Portions Copyright (C) 2011 Blake Mizerany
import (
"testing"
"time"
)
var formatTimeTests = []struct {
time time.Time
expected string
}{
{time.Time{}, "0001-01-01 00:00:00Z"},
{time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "2001-02-03 04:05:06.123456789Z"},
{time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "2001-02-03 04:05:06.123456789+02:00"},
{time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "2001-02-03 04:05:06.123456789-06:00"},
{time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "2001-02-03 04:05:06-07:30:09"},
{time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z"},
{time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00"},
{time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00"},
{time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z BC"},
{time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00 BC"},
{time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00 BC"},
{time.Date(1, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09"},
{time.Date(0, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09 BC"},
}
func TestFormatTs(t *testing.T) {
for i, tt := range formatTimeTests {
val := string(FormatTimestamp(tt.time))
if val != tt.expected {
t.Errorf("%d: incorrect time format %q, want %q", i, val, tt.expected)
}
}
}

View file

@ -2,6 +2,7 @@ package jet
import ( import (
"bytes" "bytes"
"github.com/go-jet/jet/internal/3rdparty/pq"
"github.com/go-jet/jet/internal/utils" "github.com/go-jet/jet/internal/utils"
"github.com/google/uuid" "github.com/google/uuid"
"strconv" "strconv"
@ -173,7 +174,7 @@ func argToString(value interface{}) string {
case uuid.UUID: case uuid.UUID:
return stringQuote(bindVal.String()) return stringQuote(bindVal.String())
case time.Time: case time.Time:
return stringQuote(string(utils.FormatTimestamp(bindVal))) return stringQuote(string(pq.FormatTimestamp(bindVal)))
default: default:
return "[Unsupported type]" return "[Unsupported type]"
} }

View file

@ -19,15 +19,17 @@ type Table interface {
} }
// NewTable creates new table with schema Name, table Name and list of columns // NewTable creates new table with schema Name, table Name and list of columns
func NewTable(schemaName, name string, columns ...ColumnExpression) SerializerTable { func NewTable(schemaName, name string, column ColumnExpression, columns ...ColumnExpression) SerializerTable {
columnList := append([]ColumnExpression{column}, columns...)
t := tableImpl{ t := tableImpl{
schemaName: schemaName, schemaName: schemaName,
name: name, name: name,
columnList: columns, columnList: columnList,
} }
for _, c := range columns { for _, c := range columnList {
c.setTableName(name) c.setTableName(name)
} }

View file

@ -0,0 +1,33 @@
package jet
import (
"gotest.tools/assert"
"testing"
)
func TestNewTable(t *testing.T) {
newTable := NewTable("schema", "table", IntegerColumn("intCol"))
assert.Equal(t, newTable.SchemaName(), "schema")
assert.Equal(t, newTable.TableName(), "table")
assert.Equal(t, len(newTable.columns()), 1)
assert.Equal(t, newTable.columns()[0].Name(), "intCol")
}
func TestNewJoinTable(t *testing.T) {
newTable1 := NewTable("schema", "table", IntegerColumn("intCol1"))
newTable2 := NewTable("schema", "table2", IntegerColumn("intCol2"))
joinTable := NewJoinTable(newTable1, newTable2, InnerJoin, IntegerColumn("intCol1").EQ(IntegerColumn("intCol2")))
assertClauseSerialize(t, joinTable, `schema.table
INNER JOIN schema.table2 ON ("intCol1" = "intCol2")`)
assert.Equal(t, joinTable.SchemaName(), "schema")
assert.Equal(t, joinTable.TableName(), "")
assert.Equal(t, len(joinTable.columns()), 2)
assert.Equal(t, joinTable.columns()[0].Name(), "intCol1")
assert.Equal(t, joinTable.columns()[1].Name(), "intCol2")
}

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/go-jet/jet/execution" "github.com/go-jet/jet/execution"
"github.com/go-jet/jet/internal/jet" "github.com/go-jet/jet/internal/jet"
"github.com/go-jet/jet/internal/utils"
"gotest.tools/assert" "gotest.tools/assert"
"io/ioutil" "io/ioutil"
"os" "os"
@ -60,9 +61,7 @@ func SaveJSONFile(v interface{}, testRelativePath string) {
filePath := getFullPath(testRelativePath) filePath := getFullPath(testRelativePath)
err := ioutil.WriteFile(filePath, jsonText, 0644) err := ioutil.WriteFile(filePath, jsonText, 0644)
if err != nil { utils.PanicOnError(err)
panic(err)
}
} }
// AssertJSONFile check if data json representation is the same as json at testRelativePath // AssertJSONFile check if data json representation is the same as json at testRelativePath
@ -160,6 +159,7 @@ func AssertQueryPanicErr(t *testing.T, stmt jet.Statement, db execution.DB, dest
stmt.Query(db, dest) stmt.Query(db, dest)
} }
// AssertFileContent check if file content at filePath contains expectedContent text.
func AssertFileContent(t *testing.T, filePath string, contentBegin string, expectedContent string) { func AssertFileContent(t *testing.T, filePath string, contentBegin string, expectedContent string) {
enumFileData, err := ioutil.ReadFile(filePath) enumFileData, err := ioutil.ReadFile(filePath)
@ -172,6 +172,7 @@ func AssertFileContent(t *testing.T, filePath string, contentBegin string, expec
assert.DeepEqual(t, string(enumFileData[beginIndex:]), expectedContent) assert.DeepEqual(t, string(enumFileData[beginIndex:]), expectedContent)
} }
// AssertFileNamesEqual check if all filesInfos are contained in fileNames
func AssertFileNamesEqual(t *testing.T, fileInfos []os.FileInfo, fileNames ...string) { func AssertFileNamesEqual(t *testing.T, fileInfos []os.FileInfo, fileNames ...string) {
assert.Equal(t, len(fileInfos), len(fileNames)) assert.Equal(t, len(fileInfos), len(fileNames))

View file

@ -1,6 +1,7 @@
package testutils package testutils
import ( import (
"github.com/go-jet/jet/internal/utils"
"strings" "strings"
"time" "time"
) )
@ -9,9 +10,7 @@ import (
func Date(t string) *time.Time { func Date(t string) *time.Time {
newTime, err := time.Parse("2006-01-02", t) newTime, err := time.Parse("2006-01-02", t)
if err != nil { utils.PanicOnError(err)
panic(err)
}
return &newTime return &newTime
} }
@ -27,9 +26,7 @@ func TimestampWithoutTimeZone(t string, precision int) *time.Time {
newTime, err := time.Parse("2006-01-02 15:04:05"+precisionStr+" +0000", t+" +0000") newTime, err := time.Parse("2006-01-02 15:04:05"+precisionStr+" +0000", t+" +0000")
if err != nil { utils.PanicOnError(err)
panic(err)
}
return &newTime return &newTime
} }
@ -38,9 +35,7 @@ func TimestampWithoutTimeZone(t string, precision int) *time.Time {
func TimeWithoutTimeZone(t string) *time.Time { func TimeWithoutTimeZone(t string) *time.Time {
newTime, err := time.Parse("15:04:05", t) newTime, err := time.Parse("15:04:05", t)
if err != nil { utils.PanicOnError(err)
panic(err)
}
return &newTime return &newTime
} }
@ -49,9 +44,7 @@ func TimeWithoutTimeZone(t string) *time.Time {
func TimeWithTimeZone(t string) *time.Time { func TimeWithTimeZone(t string) *time.Time {
newTimez, err := time.Parse("15:04:05 -0700", t) newTimez, err := time.Parse("15:04:05 -0700", t)
if err != nil { utils.PanicOnError(err)
panic(err)
}
return &newTimez return &newTimez
} }
@ -67,9 +60,7 @@ func TimestampWithTimeZone(t string, precision int) *time.Time {
newTime, err := time.Parse("2006-01-02 15:04:05"+precisionStr+" -0700 MST", t) newTime, err := time.Parse("2006-01-02 15:04:05"+precisionStr+" -0700 MST", t)
if err != nil { utils.PanicOnError(err)
panic(err)
}
return &newTime return &newTime
} }

View file

@ -7,9 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"reflect" "reflect"
"strconv"
"strings" "strings"
"time"
) )
// ToGoIdentifier converts database to Go identifier. // ToGoIdentifier converts database to Go identifier.
@ -109,40 +107,6 @@ func replaceInvalidChars(str string) string {
return str return str
} }
// FormatTimestamp formats t into Postgres' text format for timestamps. From: github.com/lib/pq
func FormatTimestamp(t time.Time) []byte {
// Need to send dates before 0001 A.D. with " BC" suffix, instead of the
// minus sign preferred by Go.
// Beware, "0000" in ISO is "1 BC", "-0001" is "2 BC" and so on
bc := false
if t.Year() <= 0 {
// flip year sign, and add 1, e.g: "0" will be "1", and "-10" will be "11"
t = t.AddDate((-t.Year())*2+1, 0, 0)
bc = true
}
b := []byte(t.Format("2006-01-02 15:04:05.999999999Z07:00"))
_, offset := t.Zone()
offset = offset % 60
if offset != 0 {
// RFC3339Nano already printed the minus sign
if offset < 0 {
offset = -offset
}
b = append(b, ':')
if offset < 10 {
b = append(b, '0')
}
b = strconv.AppendInt(b, int64(offset), 10)
}
if bc {
b = append(b, " BC"...)
}
return b
}
// IsNil check if v is nil // IsNil check if v is nil
func IsNil(v interface{}) bool { func IsNil(v interface{}) bool {
return v == nil || (reflect.ValueOf(v).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil()) return v == nil || (reflect.ValueOf(v).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil())
@ -175,3 +139,10 @@ func MustBeInitializedPtr(val interface{}, errorStr string) {
panic(errorStr) panic(errorStr)
} }
} }
// PanicOnError panics if err is not nil
func PanicOnError(err error) {
if err != nil {
panic(err)
}
}

View file

@ -77,9 +77,9 @@ func (r *readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) joinSelectU
} }
// NewTable creates new table with schema Name, table Name and list of columns // NewTable creates new table with schema Name, table Name and list of columns
func NewTable(schemaName, name string, columns ...jet.ColumnExpression) Table { func NewTable(schemaName, name string, column jet.ColumnExpression, columns ...jet.ColumnExpression) Table {
t := &tableImpl{ t := &tableImpl{
SerializerTable: jet.NewTable(schemaName, name, columns...), SerializerTable: jet.NewTable(schemaName, name, column, columns...),
} }
t.readableTableInterfaceImpl.parent = t t.readableTableInterfaceImpl.parent = t

View file

@ -109,10 +109,10 @@ type tableImpl struct {
} }
// NewTable creates new table with schema Name, table Name and list of columns // NewTable creates new table with schema Name, table Name and list of columns
func NewTable(schemaName, name string, columns ...jet.ColumnExpression) Table { func NewTable(schemaName, name string, column jet.ColumnExpression, columns ...jet.ColumnExpression) Table {
t := &tableImpl{ t := &tableImpl{
SerializerTable: jet.NewTable(schemaName, name, columns...), SerializerTable: jet.NewTable(schemaName, name, column, columns...),
} }
t.readableTableInterfaceImpl.parent = t t.readableTableInterfaceImpl.parent = t

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/go-jet/jet/generator/mysql" "github.com/go-jet/jet/generator/mysql"
"github.com/go-jet/jet/generator/postgres" "github.com/go-jet/jet/generator/postgres"
"github.com/go-jet/jet/internal/utils"
"github.com/go-jet/jet/tests/dbconfig" "github.com/go-jet/jet/tests/dbconfig"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq" _ "github.com/lib/pq"
@ -60,7 +61,7 @@ func initMySQLDB() {
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
err := cmd.Run() err := cmd.Run()
panicOnError(err) utils.PanicOnError(err)
err = mysql.Generate("./.gentestdata/mysql", mysql.DBConnection{ err = mysql.Generate("./.gentestdata/mysql", mysql.DBConnection{
Host: dbconfig.MySqLHost, Host: dbconfig.MySqLHost,
@ -70,7 +71,7 @@ func initMySQLDB() {
DBName: dbName, DBName: dbName,
}) })
panicOnError(err) utils.PanicOnError(err)
} }
} }
@ -104,22 +105,16 @@ func initPostgresDB() {
SchemaName: schemaName, SchemaName: schemaName,
SslMode: "disable", SslMode: "disable",
}) })
panicOnError(err) utils.PanicOnError(err)
} }
} }
func execFile(db *sql.DB, sqlFilePath string) { func execFile(db *sql.DB, sqlFilePath string) {
testSampleSql, err := ioutil.ReadFile(sqlFilePath) testSampleSql, err := ioutil.ReadFile(sqlFilePath)
panicOnError(err) utils.PanicOnError(err)
_, err = db.Exec(string(testSampleSql)) _, err = db.Exec(string(testSampleSql))
panicOnError(err) utils.PanicOnError(err)
}
func panicOnError(err error) {
if err != nil {
panic(err)
}
} }
func printOnError(err error) { func printOnError(err error) {