You need to sign in or sign up before continuing.
提交 62d227bb 编写于 作者: martianzhang's avatar martianzhang

for test coverage

上级 1fece192
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
## 2018-12 ## 2018-12
- DOING: english translation - DOING: english translation
- replace mysql database driver mymysql with go-sql-driver
- add new -report-type [ast-json, tiast-json]
- command line dsn args support '@', '/', ':' in password
- add new heuristic rule RES.009, "SELECT * FROM tbl WHERE col = col = 'abc'"
- add new heuristic rule RuleColumnNotAllowType COL.018
- fix #58 sampling not deal with NULL able string
- fix #172 compatible with mysql 5.1, which explain has no Index_Comment column
- fix #163 column.Tp may be nil, which may raise panic
- fix #151 bit type not config as int, when two columns compare will give ARG.003 suggestion.
-
## 2018-11 ## 2018-11
......
...@@ -60,7 +60,7 @@ func Test_Main_More(_ *testing.T) { ...@@ -60,7 +60,7 @@ func Test_Main_More(_ *testing.T) {
orgRerportType := common.Config.ReportType orgRerportType := common.Config.ReportType
for _, typ := range []string{ for _, typ := range []string{
"json", "html", "markdown", "fingerprint", "compress", "pretty", "rewrite", "json", "html", "markdown", "fingerprint", "compress", "pretty", "rewrite",
"ast", "tiast", "ast-json", "tiast-json", "tokenize", "ast", "tiast", "ast-json", "tiast-json", "tokenize", "lint",
} { } {
common.Config.ReportType = typ common.Config.ReportType = typ
main() main()
...@@ -104,3 +104,43 @@ func Test_Main_reportTool(t *testing.T) { ...@@ -104,3 +104,43 @@ func Test_Main_reportTool(t *testing.T) {
common.Config.ReportType = orgRerportType common.Config.ReportType = orgRerportType
common.Log.Debug("Exiting function: %s", common.GetFunctionName()) common.Log.Debug("Exiting function: %s", common.GetFunctionName())
} }
func Test_Main_helpTools(t *testing.T) {
common.Log.Debug("Entering function: %s", common.GetFunctionName())
orgConfig := common.CheckConfig
common.CheckConfig = true
helpTools()
common.CheckConfig = orgConfig
orgConfig = common.PrintVersion
common.PrintVersion = true
helpTools()
common.PrintVersion = orgConfig
orgConfig = common.PrintConfig
common.PrintConfig = true
helpTools()
common.PrintConfig = orgConfig
orgConfig = common.Config.ListHeuristicRules
common.Config.ListHeuristicRules = true
helpTools()
common.Config.ListHeuristicRules = orgConfig
orgConfig = common.Config.ListRewriteRules
common.Config.ListRewriteRules = true
helpTools()
common.Config.ListRewriteRules = orgConfig
orgConfig = common.Config.ListTestSqls
common.Config.ListTestSqls = true
helpTools()
common.Config.ListTestSqls = orgConfig
orgConfig = common.Config.ListReportTypes
common.Config.ListReportTypes = true
helpTools()
common.Config.ListReportTypes = orgConfig
common.Log.Debug("Exiting function: %s", common.GetFunctionName())
}
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
) )
func TestChardet(t *testing.T) { func TestChardet(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
charsets := []string{ charsets := []string{
"GB-18030", "GB-18030",
"UTF-8", "UTF-8",
...@@ -38,9 +39,11 @@ func TestChardet(t *testing.T) { ...@@ -38,9 +39,11 @@ func TestChardet(t *testing.T) {
t.Errorf("file: %s, Want: %s, Get: %s", fileName, c, name) t.Errorf("file: %s, Want: %s, Get: %s", fileName, c, name)
} }
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestRemoveBOM(t *testing.T) { func TestRemoveBOM(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
fileName := DevPath + "/common/testdata/UTF-8.bom.sql" fileName := DevPath + "/common/testdata/UTF-8.bom.sql"
buf, err := ioutil.ReadFile(fileName) buf, err := ioutil.ReadFile(fileName)
if err != nil { if err != nil {
...@@ -49,9 +52,11 @@ func TestRemoveBOM(t *testing.T) { ...@@ -49,9 +52,11 @@ func TestRemoveBOM(t *testing.T) {
GoldenDiff(func() { GoldenDiff(func() {
fmt.Println(RemoveBOM(buf)) fmt.Println(RemoveBOM(buf))
}, t.Name(), update) }, t.Name(), update)
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestCheckCharsetByBOM(t *testing.T) { func TestCheckCharsetByBOM(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
fileName := DevPath + "/common/testdata/UTF-8.bom.sql" fileName := DevPath + "/common/testdata/UTF-8.bom.sql"
buf, err := ioutil.ReadFile(fileName) buf, err := ioutil.ReadFile(fileName)
if err != nil { if err != nil {
...@@ -61,4 +66,5 @@ func TestCheckCharsetByBOM(t *testing.T) { ...@@ -61,4 +66,5 @@ func TestCheckCharsetByBOM(t *testing.T) {
if CheckCharsetByBOM(buf) != "UTF-8" { if CheckCharsetByBOM(buf) != "UTF-8" {
t.Errorf("checkCharsetByBOM Want: UTF-8, Get: %s", CheckCharsetByBOM(buf)) t.Errorf("checkCharsetByBOM Want: UTF-8, Get: %s", CheckCharsetByBOM(buf))
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
...@@ -30,6 +30,9 @@ var update = flag.Bool("update", false, "update .golden files") ...@@ -30,6 +30,9 @@ var update = flag.Bool("update", false, "update .golden files")
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
// 初始化 init // 初始化 init
BaseDir = DevPath BaseDir = DevPath
err := ParseConfig("")
LogIfError(err, "init ParseConfig")
Log.Debug("mysql_test init")
// 分割线 // 分割线
flag.Parse() flag.Parse()
...@@ -40,20 +43,25 @@ func TestMain(m *testing.M) { ...@@ -40,20 +43,25 @@ func TestMain(m *testing.M) {
} }
func TestParseConfig(t *testing.T) { func TestParseConfig(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
err := ParseConfig("") err := ParseConfig("")
if err != nil { if err != nil {
t.Error("sqlparser.Parse Error:", err) t.Error("sqlparser.Parse Error:", err)
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestReadConfigFile(t *testing.T) { func TestReadConfigFile(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
if Config == nil { if Config == nil {
Config = new(Configuration) Config = new(Configuration)
} }
Config.readConfigFile(filepath.Join(DevPath, "etc/soar.yaml")) Config.readConfigFile(filepath.Join(DevPath, "etc/soar.yaml"))
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestParseDSN(t *testing.T) { func TestParseDSN(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
var dsns = []string{ var dsns = []string{
"", "",
"user:password@hostname:3307/database", "user:password@hostname:3307/database",
...@@ -82,16 +90,20 @@ func TestParseDSN(t *testing.T) { ...@@ -82,16 +90,20 @@ func TestParseDSN(t *testing.T) {
if nil != err { if nil != err {
t.Fatal(err) t.Fatal(err)
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestListReportTypes(t *testing.T) { func TestListReportTypes(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
err := GoldenDiff(func() { ListReportTypes() }, t.Name(), update) err := GoldenDiff(func() { ListReportTypes() }, t.Name(), update)
if nil != err { if nil != err {
t.Fatal(err) t.Fatal(err)
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestArgConfig(t *testing.T) { func TestArgConfig(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
testArgs1 := [][]string{ testArgs1 := [][]string{
{"soar", "-config", "=", "soar.yaml"}, {"soar", "-config", "=", "soar.yaml"},
{"soar", "-print-config", "-config", "soar.yaml"}, {"soar", "-print-config", "-config", "soar.yaml"},
...@@ -115,9 +127,11 @@ func TestArgConfig(t *testing.T) { ...@@ -115,9 +127,11 @@ func TestArgConfig(t *testing.T) {
t.Errorf("should return soar.yaml, but got %s", configFile) t.Errorf("should return soar.yaml, but got %s", configFile)
} }
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestPrintConfiguration(t *testing.T) { func TestPrintConfiguration(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
Config.readConfigFile(filepath.Join(DevPath, "etc/soar.yaml")) Config.readConfigFile(filepath.Join(DevPath, "etc/soar.yaml"))
oldLogOutput := Config.LogOutput oldLogOutput := Config.LogOutput
Config.LogOutput = "soar.log" Config.LogOutput = "soar.log"
...@@ -128,4 +142,5 @@ func TestPrintConfiguration(t *testing.T) { ...@@ -128,4 +142,5 @@ func TestPrintConfiguration(t *testing.T) {
t.Error(err) t.Error(err)
} }
Config.LogOutput = oldLogOutput Config.LogOutput = oldLogOutput
Log.Debug("Exiting function: %s", GetFunctionName())
} }
...@@ -19,6 +19,7 @@ package common ...@@ -19,6 +19,7 @@ package common
import "fmt" import "fmt"
func ExampleFormatDSN() { func ExampleFormatDSN() {
Log.Debug("Entering function: %s", GetFunctionName())
dsxExp := &Dsn{ dsxExp := &Dsn{
Addr: "127.0.0.1:3306", Addr: "127.0.0.1:3306",
Schema: "mysql", Schema: "mysql",
...@@ -32,9 +33,11 @@ func ExampleFormatDSN() { ...@@ -32,9 +33,11 @@ func ExampleFormatDSN() {
fmt.Println(FormatDSN(dsxExp)) fmt.Println(FormatDSN(dsxExp))
// Output: root:1t'sB1g3rt@127.0.0.1:3306/mysql?charset=utf8mb4 // Output: root:1t'sB1g3rt@127.0.0.1:3306/mysql?charset=utf8mb4
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func ExampleIsColsPart() { func ExampleIsColsPart() {
Log.Debug("Entering function: %s", GetFunctionName())
// IsColsPart() 会 按照顺序 检查两个Column队列是否是包含(或相等)关系。 // IsColsPart() 会 按照顺序 检查两个Column队列是否是包含(或相等)关系。
a := []*Column{{Name: "1"}, {Name: "2"}, {Name: "3"}} a := []*Column{{Name: "1"}, {Name: "2"}, {Name: "3"}}
b := []*Column{{Name: "1"}, {Name: "2"}} b := []*Column{{Name: "1"}, {Name: "2"}}
...@@ -47,9 +50,11 @@ func ExampleIsColsPart() { ...@@ -47,9 +50,11 @@ func ExampleIsColsPart() {
fmt.Println(ab, ac, ad) fmt.Println(ab, ac, ad)
// Output: true false true // Output: true false true
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func ExampleSortedKey() { func ExampleSortedKey() {
Log.Debug("Entering function: %s", GetFunctionName())
ages := map[string]int{ ages := map[string]int{
"a": 1, "a": 1,
"c": 3, "c": 3,
...@@ -60,4 +65,5 @@ func ExampleSortedKey() { ...@@ -60,4 +65,5 @@ func ExampleSortedKey() {
fmt.Print(ages[name]) fmt.Print(ages[name])
} }
// Output: 1234 // Output: 1234
Log.Debug("Exiting function: %s", GetFunctionName())
} }
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
) )
func TestMarkdownEscape(_ *testing.T) { func TestMarkdownEscape(_ *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
var strs = []string{ var strs = []string{
"a`bc", "a`bc",
"abc", "abc",
...@@ -35,9 +36,11 @@ func TestMarkdownEscape(_ *testing.T) { ...@@ -35,9 +36,11 @@ func TestMarkdownEscape(_ *testing.T) {
for _, str := range strs { for _, str := range strs {
fmt.Println(MarkdownEscape(str)) fmt.Println(MarkdownEscape(str))
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestMarkdown2Html(t *testing.T) { func TestMarkdown2Html(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
md := filepath.Join("testdata", t.Name()+".md") md := filepath.Join("testdata", t.Name()+".md")
buf, err := ioutil.ReadFile(md) buf, err := ioutil.ReadFile(md)
if err != nil { if err != nil {
...@@ -60,16 +63,28 @@ func TestMarkdown2Html(t *testing.T) { ...@@ -60,16 +63,28 @@ func TestMarkdown2Html(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
io.Copy(html, gd) io.Copy(html, gd)
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestScore(t *testing.T) { func TestScore(t *testing.T) {
score := Score(50) Log.Debug("Entering function: %s", GetFunctionName())
if score != "★ ★ ☆ ☆ ☆ 50分" { scores := map[int]string{
t.Error(score) 50: "★ ★ ☆ ☆ ☆ 50分",
100: "★ ★ ★ ★ ★ 100分",
-1: "☆ ☆ ☆ ☆ ☆ 0分",
101: "★ ★ ★ ★ ★ 100分",
} }
for score, want := range scores {
get := Score(score)
if want != get {
t.Error(score, want, get)
}
}
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestLoadExternalResource(t *testing.T) { func TestLoadExternalResource(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
buf := loadExternalResource("../doc/themes/github.css") buf := loadExternalResource("../doc/themes/github.css")
if buf == "" { if buf == "" {
t.Error("loadExternalResource local error") t.Error("loadExternalResource local error")
...@@ -78,13 +93,16 @@ func TestLoadExternalResource(t *testing.T) { ...@@ -78,13 +93,16 @@ func TestLoadExternalResource(t *testing.T) {
if buf == "" { if buf == "" {
t.Error("loadExternalResource http error") t.Error("loadExternalResource http error")
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestMarkdownHTMLHeader(t *testing.T) { func TestMarkdownHTMLHeader(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
err := GoldenDiff(func() { err := GoldenDiff(func() {
MarkdownHTMLHeader() MarkdownHTMLHeader()
}, t.Name(), update) }, t.Name(), update)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
) )
func TestGetDataTypeLength(t *testing.T) { func TestGetDataTypeLength(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
typeList := map[string][]int{ typeList := map[string][]int{
"varchar(20)": {20}, "varchar(20)": {20},
"int(2)": {2}, "int(2)": {2},
...@@ -37,10 +38,11 @@ func TestGetDataTypeLength(t *testing.T) { ...@@ -37,10 +38,11 @@ func TestGetDataTypeLength(t *testing.T) {
} }
} }
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestGetDataTypeBase(t *testing.T) { func TestGetDataTypeBase(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
typeList := map[string]string{ typeList := map[string]string{
"varchar(20)": "varchar", "varchar(20)": "varchar",
"int(2)": "int", "int(2)": "int",
...@@ -52,10 +54,11 @@ func TestGetDataTypeBase(t *testing.T) { ...@@ -52,10 +54,11 @@ func TestGetDataTypeBase(t *testing.T) {
t.Errorf("Not match, want %s, got %s", typeList[typ], got) t.Errorf("Not match, want %s, got %s", typeList[typ], got)
} }
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
func TestGetDataBytes(t *testing.T) { func TestGetDataBytes(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
cols50604 := map[*Column]int{ cols50604 := map[*Column]int{
// numeric type // numeric type
{Name: "col000", DataType: "tinyint", Character: "utf8"}: 1, {Name: "col000", DataType: "tinyint", Character: "utf8"}: 1,
...@@ -137,4 +140,5 @@ func TestGetDataBytes(t *testing.T) { ...@@ -137,4 +140,5 @@ func TestGetDataBytes(t *testing.T) {
t.Errorf("Version: 5.5.0, %s Not match, want %d, got %d", col.Name, bytes, got) t.Errorf("Version: 5.5.0, %s Not match, want %d, got %d", col.Name, bytes, got)
} }
} }
Log.Debug("Exiting function: %s", GetFunctionName())
} }
...@@ -22,7 +22,9 @@ import ( ...@@ -22,7 +22,9 @@ import (
) )
func TestHandleSignal(t *testing.T) { func TestHandleSignal(t *testing.T) {
Log.Debug("Entering function: %s", GetFunctionName())
HandleSignal(func() { HandleSignal(func() {
fmt.Println("done") fmt.Println("done")
}) })
Log.Debug("Exiting function: %s", GetFunctionName())
} }
...@@ -21,3 +21,7 @@ ...@@ -21,3 +21,7 @@
* 语法检查 * 语法检查
* 模拟执行 * 模拟执行
* 索引建议/去重 * 索引建议/去重
## 注意
* 测试环境 MySQL 版本必须高于或等于线上环境
* 测试环境需要所有权限(建议通过[docker](https://hub.docker.com/_/mysql/)启动),线上环境至少需要只读权限
...@@ -101,7 +101,7 @@ func BuildEnv() (*VirtualEnv, *database.Connector) { ...@@ -101,7 +101,7 @@ func BuildEnv() (*VirtualEnv, *database.Connector) {
// 判断测试环境与remote环境版本是否一致 // 判断测试环境与remote环境版本是否一致
if vEnvVersion < rEnvVersion { if vEnvVersion < rEnvVersion {
common.Log.Warning("TestDSN MySQL version older than OnlineDSN, TestDSN will not be used", vEnvVersion, rEnvVersion) common.Log.Warning("TestDSN MySQL version older than OnlineDSN(%d), TestDSN(%d) will not be used", vEnvVersion, rEnvVersion)
common.Config.TestDSN.Disable = true common.Config.TestDSN.Disable = true
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册