From 4a7d86e38eb0192f61eafdadbbe7d1a2a7de29df Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 15:20:42 +0800 Subject: [PATCH 01/14] Fix update ExcludeRegex to empty not work --- runner/config.go | 5 +++ runner/engine_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/runner/config.go b/runner/config.go index 2527437d..5e395a5a 100644 --- a/runner/config.go +++ b/runner/config.go @@ -100,10 +100,15 @@ func InitConfig(path string) (cfg *Config, err error) { return nil, err } } + oldCfg := *cfg err = mergo.Merge(cfg, defaultConfig()) if err != nil { return nil, err } + + // mergo.Merge will overwrite if it is Empty, so we need to do it manually + cfg.Build.ExcludeRegex = oldCfg.Build.ExcludeRegex + err = cfg.preprocess() return cfg, err } diff --git a/runner/engine_test.go b/runner/engine_test.go index b0a4ac48..ba9edf2b 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -5,7 +5,9 @@ import ( "fmt" "net" "os" + "os/exec" "os/signal" + "runtime" "strings" "syscall" "testing" @@ -640,3 +642,78 @@ func TestWriteDefaultConfig(t *testing.T) { assert.Equal(t, expect, *actual) } + +func TestShouldIncludeGoTestFile(t *testing.T) { + port, f := GetPort() + f() + t.Logf("port: %d", port) + + tmpDir := initTestEnv(t, port) + // change dir to tmpDir + if err := os.Chdir(tmpDir); err != nil { + t.Fatal(err) + } + writeDefaultConfig() + + // write go test file + file, err := os.Create("main_test.go") + if err != nil { + t.Fatal(err) + } + _, err = file.WriteString(`package main + +import "testing" + +func Test(t *testing.T) { + t.Log("testing") +} +`) + // run sed + // check the file is exist + if _, err := os.Stat(dftTOML); err != nil { + t.Fatal(err) + } + // check is MacOS + var cmd *exec.Cmd + if runtime.GOOS == "darwin" { + cmd = exec.Command("gsed", "-i", "s/\"_test.*go\"//g", ".air.toml") + } else { + cmd = exec.Command("sed", "-i", "s/\"_test.*go\"//g", ".air.toml") + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + t.Fatal(err) + } + + time.Sleep(time.Second * 3) + engine, err := NewEngine(".air.toml", false) + if err != nil { + t.Fatal(err) + } + go func() { + engine.Run() + }() + + t.Logf("start change main_test.go") + // change file of main_test.go + // just append a new empty line to main_test.go + if err = waitingPortReady(t, port, time.Second*40); err != nil { + t.Fatal(err) + } + go func() { + file, err := os.OpenFile("main_test.go", os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + t.Fatalf("Should not be fail: %s.", err) + } + defer file.Close() + _, err = file.WriteString("\n") + if err != nil { + t.Fatalf("Should not be fail: %s.", err) + } + }() + // should Have rebuild + if err = waitingPortConnectionRefused(t, port, time.Second*10); err != nil { + t.Fatal(err) + } +} From 95108b49156271b8ab19d8289ceffee82e0c5363 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 15:21:48 +0800 Subject: [PATCH 02/14] update comment --- runner/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runner/config.go b/runner/config.go index 5e395a5a..809c07f5 100644 --- a/runner/config.go +++ b/runner/config.go @@ -106,7 +106,7 @@ func InitConfig(path string) (cfg *Config, err error) { return nil, err } - // mergo.Merge will overwrite if it is Empty, so we need to do it manually + // mergo.Merge will overwrite the fields if it is Empty, so we need to do it manually cfg.Build.ExcludeRegex = oldCfg.Build.ExcludeRegex err = cfg.preprocess() From 5bb6739f040bd17083d71bb65a53930a200c8eda Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 15:28:28 +0800 Subject: [PATCH 03/14] install brew install --- runner/engine_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runner/engine_test.go b/runner/engine_test.go index ba9edf2b..eb1c3425 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -676,6 +676,11 @@ func Test(t *testing.T) { // check is MacOS var cmd *exec.Cmd if runtime.GOOS == "darwin" { + //brew install --default-names gnu-sed install gnu-sed + err = exec.Command("brew", "install", "--default-names", "gnu-sed").Run() + if err != nil { + t.Fatal(err) + } cmd = exec.Command("gsed", "-i", "s/\"_test.*go\"//g", ".air.toml") } else { cmd = exec.Command("sed", "-i", "s/\"_test.*go\"//g", ".air.toml") From 654e8a311227f06fe7d178d8f1fbdb139fde2e1d Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 15:41:37 +0800 Subject: [PATCH 04/14] install brew install --- .github/workflows/build.yml | 2 ++ runner/engine_test.go | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a23528a4..401cf988 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,8 @@ jobs: go-version: ^1.17 - name: build run: make build + - name: install dependency + run: if [ $(uname) == "Darwin" ]; then brew install gnu-sed ;fi - name: run Unit tests. run: go install github.com/go-delve/delve/cmd/dlv@latest && go test ./... -v -covermode=count -coverprofile=coverage.txt - name: upload Coverage report to CodeCov diff --git a/runner/engine_test.go b/runner/engine_test.go index eb1c3425..ba9edf2b 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -676,11 +676,6 @@ func Test(t *testing.T) { // check is MacOS var cmd *exec.Cmd if runtime.GOOS == "darwin" { - //brew install --default-names gnu-sed install gnu-sed - err = exec.Command("brew", "install", "--default-names", "gnu-sed").Run() - if err != nil { - t.Fatal(err) - } cmd = exec.Command("gsed", "-i", "s/\"_test.*go\"//g", ".air.toml") } else { cmd = exec.Command("sed", "-i", "s/\"_test.*go\"//g", ".air.toml") From 582608957680e697734982b0eb21ed66b6d0e932 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 16:14:22 +0800 Subject: [PATCH 05/14] zero value Transformer --- runner/config.go | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/runner/config.go b/runner/config.go index 809c07f5..129d2340 100644 --- a/runner/config.go +++ b/runner/config.go @@ -87,6 +87,23 @@ type cfgScreen struct { ClearOnRebuild bool `toml:"clear_on_rebuild"` } +type sliceTransformer struct { +} + +func (t sliceTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { + if typ.Kind() != reflect.Slice { + return func(dst, src reflect.Value) error { + if dst.CanSet() { + if dst.IsZero() { + dst.Set(src) + } + } + return nil + } + } + return nil +} + // InitConfig initializes the configuration. func InitConfig(path string) (cfg *Config, err error) { if path == "" { @@ -100,15 +117,16 @@ func InitConfig(path string) (cfg *Config, err error) { return nil, err } } - oldCfg := *cfg - err = mergo.Merge(cfg, defaultConfig()) + //oldCfg := *cfg + err = mergo.Merge(cfg, defaultConfig(), func(config *mergo.Config) { + // mergo.Merge will overwrite the fields if it is Empty + // So need use this to avoid that none-zero slice will be overwritten. + config.Transformers = sliceTransformer{} + }) if err != nil { return nil, err } - // mergo.Merge will overwrite the fields if it is Empty, so we need to do it manually - cfg.Build.ExcludeRegex = oldCfg.Build.ExcludeRegex - err = cfg.preprocess() return cfg, err } From 732d9473386298b94eb536966c08f14f8b0f0d1f Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 16:15:20 +0800 Subject: [PATCH 06/14] zero value Transformer --- runner/config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/runner/config.go b/runner/config.go index 129d2340..7eb7a5b1 100644 --- a/runner/config.go +++ b/runner/config.go @@ -121,6 +121,7 @@ func InitConfig(path string) (cfg *Config, err error) { err = mergo.Merge(cfg, defaultConfig(), func(config *mergo.Config) { // mergo.Merge will overwrite the fields if it is Empty // So need use this to avoid that none-zero slice will be overwritten. + // https://github.com/imdario/mergo#transformers config.Transformers = sliceTransformer{} }) if err != nil { From 869d09e7f44c838a4ce5b6990ec3760bc702a82f Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 16:16:46 +0800 Subject: [PATCH 07/14] zero value Transformer --- runner/config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/runner/config.go b/runner/config.go index 7eb7a5b1..be995bf9 100644 --- a/runner/config.go +++ b/runner/config.go @@ -94,6 +94,7 @@ func (t sliceTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Va if typ.Kind() != reflect.Slice { return func(dst, src reflect.Value) error { if dst.CanSet() { + // if it's a zero value of slice which is nil, then we need to overwrite it if dst.IsZero() { dst.Set(src) } From 7eb1a6fd5f542d125036f1e30c3677c321ca35d1 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 16:17:00 +0800 Subject: [PATCH 08/14] zero value Transformer --- runner/config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/runner/config.go b/runner/config.go index be995bf9..3b9120fe 100644 --- a/runner/config.go +++ b/runner/config.go @@ -118,7 +118,6 @@ func InitConfig(path string) (cfg *Config, err error) { return nil, err } } - //oldCfg := *cfg err = mergo.Merge(cfg, defaultConfig(), func(config *mergo.Config) { // mergo.Merge will overwrite the fields if it is Empty // So need use this to avoid that none-zero slice will be overwritten. From a7f2de597288a493c3711531d911f7649e779ae9 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 17:24:02 +0800 Subject: [PATCH 09/14] zero value Transformer --- runner/config.go | 18 +++++++++--------- runner/engine_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/runner/config.go b/runner/config.go index 3b9120fe..18e26cd3 100644 --- a/runner/config.go +++ b/runner/config.go @@ -91,13 +91,10 @@ type sliceTransformer struct { } func (t sliceTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { - if typ.Kind() != reflect.Slice { + if typ.Kind() == reflect.Slice { return func(dst, src reflect.Value) error { - if dst.CanSet() { - // if it's a zero value of slice which is nil, then we need to overwrite it - if dst.IsZero() { - dst.Set(src) - } + if !src.IsZero() { + dst.Set(src) } return nil } @@ -118,7 +115,10 @@ func InitConfig(path string) (cfg *Config, err error) { return nil, err } } - err = mergo.Merge(cfg, defaultConfig(), func(config *mergo.Config) { + config := defaultConfig() + // get addr + ret := &config + err = mergo.Merge(ret, cfg, func(config *mergo.Config) { // mergo.Merge will overwrite the fields if it is Empty // So need use this to avoid that none-zero slice will be overwritten. // https://github.com/imdario/mergo#transformers @@ -128,8 +128,8 @@ func InitConfig(path string) (cfg *Config, err error) { return nil, err } - err = cfg.preprocess() - return cfg, err + err = ret.preprocess() + return ret, err } func writeDefaultConfig() { diff --git a/runner/engine_test.go b/runner/engine_test.go index ba9edf2b..99800d77 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -3,6 +3,7 @@ package runner import ( "errors" "fmt" + "io/ioutil" "net" "os" "os/exec" @@ -643,6 +644,44 @@ func TestWriteDefaultConfig(t *testing.T) { assert.Equal(t, expect, *actual) } +func TestCheckNilSliceShouldBeenOverwrite(t *testing.T) { + port, f := GetPort() + f() + t.Logf("port: %d", port) + + tmpDir := initTestEnv(t, port) + + // change dir to tmpDir + if err := os.Chdir(tmpDir); err != nil { + t.Fatal(err) + } + + // write easy config file + + config := ` +[build] +cmd = "go build -o ./tmp/main ." +bin = "tmp/main" +exclude_regex = [] +exclude_dir = ["test"] +exclude_file = ["main.go"] + +` + if err := ioutil.WriteFile(dftTOML, []byte(config), 0644); err != nil { + t.Fatal(err) + } + engine, err := NewEngine(".air.toml", true) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, []string{"go", "tpl", "tmpl", "html"}, engine.config.Build.IncludeExt) + assert.Equal(t, []string{}, engine.config.Build.ExcludeRegex) + assert.Equal(t, []string{"test"}, engine.config.Build.ExcludeDir) + // add new config + assert.Equal(t, []string{"main.go"}, engine.config.Build.ExcludeFile) + +} + func TestShouldIncludeGoTestFile(t *testing.T) { port, f := GetPort() f() From 8956f65ab1159ddc50e0de8a48e4f62155cd76c2 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 17:44:10 +0800 Subject: [PATCH 10/14] zero value Transformer --- runner/config_test.go | 4 ++-- runner/engine_test.go | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/runner/config_test.go b/runner/config_test.go index 7fb36909..f09bf0f8 100644 --- a/runner/config_test.go +++ b/runner/config_test.go @@ -93,7 +93,7 @@ func TestDefaultPathConfig(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - _ = os.Setenv(airWd, tt.path) + t.Setenv(airWd, tt.path) c, err := defaultPathConfig() if err != nil { t.Fatalf("Should not be fail: %s.", err) @@ -115,7 +115,7 @@ func TestReadConfByName(t *testing.T) { } func TestConfPreprocess(t *testing.T) { - _ = os.Setenv(airWd, "_testdata/toml") + t.Setenv(airWd, "_testdata/toml") df := defaultConfig() err := df.preprocess() if err != nil { diff --git a/runner/engine_test.go b/runner/engine_test.go index 99800d77..bab33faa 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -35,18 +35,6 @@ func TestNewEngine(t *testing.T) { } } -func TestCheckRunEnv(t *testing.T) { - _ = os.Unsetenv(airWd) - engine, err := NewEngine("", true) - if err != nil { - t.Fatalf("Should not be fail: %s.", err) - } - err = engine.checkRunEnv() - if err == nil { - t.Fatal("should throw a err") - } -} - func TestWatching(t *testing.T) { engine, err := NewEngine("", true) if err != nil { From 5875f5809e0630db9b946a747bc2704db2ede9e7 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 18:01:47 +0800 Subject: [PATCH 11/14] zero value Transformer --- runner/engine_test.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/runner/engine_test.go b/runner/engine_test.go index bab33faa..8cd41bd2 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -744,3 +744,39 @@ func Test(t *testing.T) { t.Fatal(err) } } + +func TestCreateNewDir(t *testing.T) { + // generate a random port + port, f := GetPort() + f() + t.Logf("port: %d", port) + + tmpDir := initTestEnv(t, port) + // change dir to tmpDir + err := os.Chdir(tmpDir) + if err != nil { + t.Fatalf("Should not be fail: %s.", err) + } + engine, err := NewEngine("", true) + if err != nil { + t.Fatalf("Should not be fail: %s.", err) + } + + go func() { + engine.Run() + }() + time.Sleep(time.Second * 2) + assert.True(t, checkPortHaveBeenUsed(port)) + + // create a new dir make dir + if err = os.Mkdir(tmpDir+"/dir", 0644); err != nil { + t.Fatal(err) + } + + // no need reload + if err = waitingPortConnectionRefused(t, port, 3*time.Second); err == nil { + t.Fatal("should raise a error") + } + engine.Stop() + +} From cf8b355e1d7e04daf43f1c197b9b034428588bf9 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 18:16:53 +0800 Subject: [PATCH 12/14] zero value Transformer --- runner/config.go | 1 + runner/engine_test.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/runner/config.go b/runner/config.go index 18e26cd3..a4a86f37 100644 --- a/runner/config.go +++ b/runner/config.go @@ -123,6 +123,7 @@ func InitConfig(path string) (cfg *Config, err error) { // So need use this to avoid that none-zero slice will be overwritten. // https://github.com/imdario/mergo#transformers config.Transformers = sliceTransformer{} + config.Overwrite = true }) if err != nil { return nil, err diff --git a/runner/engine_test.go b/runner/engine_test.go index 8cd41bd2..24cd4369 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -648,7 +648,7 @@ func TestCheckNilSliceShouldBeenOverwrite(t *testing.T) { config := ` [build] -cmd = "go build -o ./tmp/main ." +cmd = "go build ." bin = "tmp/main" exclude_regex = [] exclude_dir = ["test"] @@ -667,6 +667,7 @@ exclude_file = ["main.go"] assert.Equal(t, []string{"test"}, engine.config.Build.ExcludeDir) // add new config assert.Equal(t, []string{"main.go"}, engine.config.Build.ExcludeFile) + assert.Equal(t, "go build .", engine.config.Build.Cmd) } From 43e45563808722d7b5660252937b69d748724e39 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 18:22:29 +0800 Subject: [PATCH 13/14] zero value Transformer --- runner/engine_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/runner/engine_test.go b/runner/engine_test.go index 24cd4369..c04c8ddc 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -779,5 +779,18 @@ func TestCreateNewDir(t *testing.T) { t.Fatal("should raise a error") } engine.Stop() + time.Sleep(2 * time.Second) } + +func TestCheckRunEnv(t *testing.T) { + _ = os.Unsetenv(airWd) + engine, err := NewEngine("", true) + if err != nil { + t.Fatalf("Should not be fail: %s.", err) + } + err = engine.checkRunEnv() + if err == nil { + t.Fatal("should throw a err") + } +} From 1c6818251981e135053e1f84e671f970480ef3e2 Mon Sep 17 00:00:00 2001 From: xiantang Date: Mon, 11 Jul 2022 18:38:19 +0800 Subject: [PATCH 14/14] zero value Transformer --- runner/engine_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/runner/engine_test.go b/runner/engine_test.go index c04c8ddc..dd6858b4 100644 --- a/runner/engine_test.go +++ b/runner/engine_test.go @@ -35,6 +35,18 @@ func TestNewEngine(t *testing.T) { } } +func TestCheckRunEnv(t *testing.T) { + _ = os.Unsetenv(airWd) + engine, err := NewEngine("", true) + if err != nil { + t.Fatalf("Should not be fail: %s.", err) + } + err = engine.checkRunEnv() + if err == nil { + t.Fatal("should throw a err") + } +} + func TestWatching(t *testing.T) { engine, err := NewEngine("", true) if err != nil { @@ -782,15 +794,3 @@ func TestCreateNewDir(t *testing.T) { time.Sleep(2 * time.Second) } - -func TestCheckRunEnv(t *testing.T) { - _ = os.Unsetenv(airWd) - engine, err := NewEngine("", true) - if err != nil { - t.Fatalf("Should not be fail: %s.", err) - } - err = engine.checkRunEnv() - if err == nil { - t.Fatal("should throw a err") - } -}