feat:support command line arguments when user not want use config file (#180)
Co-authored-by: jingdi.zhu <jingd.zhu@shopee.com>
This commit is contained in:
@@ -24,6 +24,15 @@ NOTE: This tool has nothing to do with hot-deploy for production.
|
||||
* Allow watching new directories after Air started
|
||||
* Better building process
|
||||
|
||||
### ✨ beta feature
|
||||
Support air config fields as arguments:
|
||||
|
||||
if you just want to config build command and run command, you can use like following command without config file:
|
||||
|
||||
`air --build.cmd "go build -o bin/api cmd/run.go" --build.bin "./api"`
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Prefer install.sh
|
||||
|
||||
@@ -7,13 +7,12 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/pelletier/go-toml v1.8.1
|
||||
github.com/stretchr/testify v1.7.1
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||
)
|
||||
|
||||
require github.com/creack/pty v1.1.11
|
||||
|
||||
require github.com/stretchr/testify v1.7.1
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
|
||||
@@ -15,6 +15,7 @@ var (
|
||||
cfgPath string
|
||||
debugMode bool
|
||||
showVersion bool
|
||||
cmdArgs map[string]runner.TomlInfo
|
||||
runArgs []string
|
||||
)
|
||||
|
||||
@@ -29,11 +30,17 @@ func helpMessage() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
parseFlag(os.Args[1:])
|
||||
}
|
||||
|
||||
func parseFlag(args []string) {
|
||||
flag.Usage = helpMessage
|
||||
flag.StringVar(&cfgPath, "c", "", "config path")
|
||||
flag.BoolVar(&debugMode, "d", false, "debug mode")
|
||||
flag.BoolVar(&showVersion, "v", false, "show version")
|
||||
flag.Parse()
|
||||
cmd := flag.CommandLine
|
||||
cmdArgs = runner.ParseConfigFlag(cmd)
|
||||
flag.CommandLine.Parse(args)
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -51,12 +58,17 @@ func main() {
|
||||
if debugMode {
|
||||
fmt.Println("[debug] mode")
|
||||
}
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
var err error
|
||||
r, err := runner.NewEngine(cfgPath, debugMode)
|
||||
cfg, err := runner.InitConfig(cfgPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
}
|
||||
cfg.WithArgs(cmdArgs)
|
||||
r, err := runner.NewEngineWithConfig(cfg, debugMode)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package runner
|
||||
+30
-17
@@ -6,6 +6,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"time"
|
||||
@@ -20,7 +21,8 @@ const (
|
||||
airWd = "air_wd"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
// Config is the main configuration structure for Air.
|
||||
type Config struct {
|
||||
Root string `toml:"root"`
|
||||
TmpDir string `toml:"tmp_dir"`
|
||||
TestDataDir string `toml:"testdata_dir"`
|
||||
@@ -85,7 +87,8 @@ type cfgScreen struct {
|
||||
ClearOnRebuild bool `toml:"clear_on_rebuild"`
|
||||
}
|
||||
|
||||
func initConfig(path string) (cfg *config, err error) {
|
||||
// InitConfig initializes the configuration.
|
||||
func InitConfig(path string) (cfg *Config, err error) {
|
||||
if path == "" {
|
||||
cfg, err = defaultPathConfig()
|
||||
if err != nil {
|
||||
@@ -140,7 +143,7 @@ func writeDefaultConfig() {
|
||||
fmt.Printf("%s file created to the current directory with the default settings\n", dftTOML)
|
||||
}
|
||||
|
||||
func defaultPathConfig() (*config, error) {
|
||||
func defaultPathConfig() (*Config, error) {
|
||||
// when path is blank, first find `.air.toml`, `.air.conf` in `air_wd` and current working directory, if not found, use defaults
|
||||
for _, name := range []string{dftTOML, dftConf} {
|
||||
cfg, err := readConfByName(name)
|
||||
@@ -156,7 +159,7 @@ func defaultPathConfig() (*config, error) {
|
||||
return &dftCfg, nil
|
||||
}
|
||||
|
||||
func readConfByName(name string) (*config, error) {
|
||||
func readConfByName(name string) (*Config, error) {
|
||||
var path string
|
||||
if wd := os.Getenv(airWd); wd != "" {
|
||||
path = filepath.Join(wd, name)
|
||||
@@ -171,7 +174,7 @@ func readConfByName(name string) (*config, error) {
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
func defaultConfig() config {
|
||||
func defaultConfig() Config {
|
||||
build := cfgBuild{
|
||||
Cmd: "go build -o ./tmp/main .",
|
||||
Bin: "./tmp/main",
|
||||
@@ -201,7 +204,7 @@ func defaultConfig() config {
|
||||
misc := cfgMisc{
|
||||
CleanOnExit: false,
|
||||
}
|
||||
return config{
|
||||
return Config{
|
||||
Root: ".",
|
||||
TmpDir: "tmp",
|
||||
TestDataDir: "testdata",
|
||||
@@ -212,13 +215,13 @@ func defaultConfig() config {
|
||||
}
|
||||
}
|
||||
|
||||
func readConfig(path string) (*config, error) {
|
||||
func readConfig(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := new(config)
|
||||
cfg := new(Config)
|
||||
if err = toml.Unmarshal(data, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -226,7 +229,7 @@ func readConfig(path string) (*config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func readConfigOrDefault(path string) (*config, error) {
|
||||
func readConfigOrDefault(path string) (*Config, error) {
|
||||
dftCfg := defaultConfig()
|
||||
cfg, err := readConfig(path)
|
||||
if err != nil {
|
||||
@@ -236,7 +239,7 @@ func readConfigOrDefault(path string) (*config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (c *config) preprocess() error {
|
||||
func (c *Config) preprocess() error {
|
||||
var err error
|
||||
cwd := os.Getenv(airWd)
|
||||
if cwd != "" {
|
||||
@@ -278,7 +281,7 @@ func (c *config) preprocess() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *config) colorInfo() map[string]string {
|
||||
func (c *Config) colorInfo() map[string]string {
|
||||
return map[string]string{
|
||||
"main": c.Color.Main,
|
||||
"build": c.Color.Build,
|
||||
@@ -287,30 +290,40 @@ func (c *config) colorInfo() map[string]string {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *config) buildLogPath() string {
|
||||
func (c *Config) buildLogPath() string {
|
||||
return filepath.Join(c.tmpPath(), c.Build.Log)
|
||||
}
|
||||
|
||||
func (c *config) buildDelay() time.Duration {
|
||||
func (c *Config) buildDelay() time.Duration {
|
||||
return time.Duration(c.Build.Delay) * time.Millisecond
|
||||
}
|
||||
|
||||
func (c *config) binPath() string {
|
||||
func (c *Config) binPath() string {
|
||||
return filepath.Join(c.Root, c.Build.Bin)
|
||||
}
|
||||
|
||||
func (c *config) tmpPath() string {
|
||||
func (c *Config) tmpPath() string {
|
||||
return filepath.Join(c.Root, c.TmpDir)
|
||||
}
|
||||
|
||||
func (c *config) TestDataPath() string {
|
||||
func (c *Config) testDataPath() string {
|
||||
return filepath.Join(c.Root, c.TestDataDir)
|
||||
}
|
||||
|
||||
func (c *config) rel(path string) string {
|
||||
func (c *Config) rel(path string) string {
|
||||
s, err := filepath.Rel(c.Root, path)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// WithArgs returns a new config with the given arguments added to the configuration.
|
||||
func (c *Config) WithArgs(args map[string]TomlInfo) {
|
||||
for _, value := range args {
|
||||
if value.Value != nil && *value.Value != "" {
|
||||
v := reflect.ValueOf(c)
|
||||
setValue2Struct(v, value.fieldPath, *value.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const (
|
||||
cmd = "go build -o ./tmp/main ."
|
||||
)
|
||||
|
||||
func getWindowsConfig() config {
|
||||
func getWindowsConfig() Config {
|
||||
build := cfgBuild{
|
||||
Cmd: "go build -o ./tmp/main .",
|
||||
Bin: "./tmp/main",
|
||||
@@ -28,7 +28,7 @@ func getWindowsConfig() config {
|
||||
build.Cmd = cmd
|
||||
}
|
||||
|
||||
return config{
|
||||
return Config{
|
||||
Root: ".",
|
||||
TmpDir: "tmp",
|
||||
TestDataDir: "testdata",
|
||||
@@ -110,7 +110,7 @@ func TestReadConfByName(t *testing.T) {
|
||||
_ = os.Unsetenv(airWd)
|
||||
config, _ := readConfByName(dftTOML)
|
||||
if config != nil {
|
||||
t.Fatalf("expect config is nil,but get a not nil config")
|
||||
t.Fatalf("expect Config is nil,but get a not nil Config")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-9
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
// Engine ...
|
||||
type Engine struct {
|
||||
config *config
|
||||
config *Config
|
||||
logger *logger
|
||||
watcher *fsnotify.Watcher
|
||||
debugMode bool
|
||||
@@ -37,14 +37,8 @@ type Engine struct {
|
||||
ll sync.Mutex // lock for logger
|
||||
}
|
||||
|
||||
// NewEngine ...
|
||||
func NewEngine(cfgPath string, debugMode bool) (*Engine, error) {
|
||||
var err error
|
||||
cfg, err := initConfig(cfgPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// NewEngineWithConfig ...
|
||||
func NewEngineWithConfig(cfg *Config, debugMode bool) (*Engine, error) {
|
||||
logger := newLogger(cfg)
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
@@ -70,6 +64,16 @@ func NewEngine(cfgPath string, debugMode bool) (*Engine, error) {
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
// NewEngine ...
|
||||
func NewEngine(cfgPath string, debugMode bool) (*Engine, error) {
|
||||
var err error
|
||||
cfg, err := InitConfig(cfgPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewEngineWithConfig(cfg, debugMode)
|
||||
}
|
||||
|
||||
// Run run run
|
||||
func (e *Engine) Run() {
|
||||
if len(os.Args) > 1 && os.Args[1] == "init" {
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestNewEngine(t *testing.T) {
|
||||
t.Fatal("logger should not be nil")
|
||||
}
|
||||
if engine.config == nil {
|
||||
t.Fatal("config should not be nil")
|
||||
t.Fatal("Config should not be nil")
|
||||
}
|
||||
if engine.watcher == nil {
|
||||
t.Fatal("watcher should not be nil")
|
||||
@@ -200,7 +200,7 @@ func TestCtrlCWhenHaveKillDelay(t *testing.T) {
|
||||
// fix https://github.com/cosmtrek/air/issues/278
|
||||
// generate a random port
|
||||
data := []byte("[build]\n kill_delay = \"2s\"")
|
||||
c := config{}
|
||||
c := Config{}
|
||||
if err := toml.Unmarshal(data, &c); err != nil {
|
||||
t.Fatalf("Should not be fail: %s.", err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"flag"
|
||||
)
|
||||
|
||||
// ParseConfigFlag parse toml information for flag
|
||||
func ParseConfigFlag(f *flag.FlagSet) map[string]TomlInfo {
|
||||
c := Config{}
|
||||
m := flatConfig(c)
|
||||
for k, v := range m {
|
||||
f.StringVar(v.Value, k, "", "")
|
||||
}
|
||||
return m
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFlag(t *testing.T) {
|
||||
// table driven tests
|
||||
type testCase struct {
|
||||
name string
|
||||
args []string
|
||||
expected string
|
||||
key string
|
||||
}
|
||||
testCases := []testCase{
|
||||
{
|
||||
name: "test1",
|
||||
args: []string{"--build.cmd", "go build -o ./tmp/main ."},
|
||||
expected: "go build -o ./tmp/main .",
|
||||
key: "build.cmd",
|
||||
},
|
||||
{
|
||||
name: "tmp dir test",
|
||||
args: []string{"--tmp_dir", "test"},
|
||||
expected: "test",
|
||||
key: "tmp_dir",
|
||||
},
|
||||
{
|
||||
name: "check bool",
|
||||
args: []string{"--build.exclude_unchanged", "true"},
|
||||
expected: "true",
|
||||
key: "build.exclude_unchanged",
|
||||
},
|
||||
{
|
||||
name: "check int",
|
||||
args: []string{"--build.kill_delay", "1000"},
|
||||
expected: "1000",
|
||||
key: "build.kill_delay",
|
||||
},
|
||||
{
|
||||
name: "check exclude_regex",
|
||||
args: []string{"--build.exclude_regex", `["_test.go"]`},
|
||||
expected: `["_test.go"]`,
|
||||
key: "build.exclude_regex",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
flag := flag.NewFlagSet(t.Name(), flag.ExitOnError)
|
||||
cmdArgs := ParseConfigFlag(flag)
|
||||
flag.Parse(tc.args)
|
||||
assert.Equal(t, tc.expected, *cmdArgs[tc.key].Value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigRuntimeArgs(t *testing.T) {
|
||||
// table driven tests
|
||||
type testCase struct {
|
||||
name string
|
||||
args []string
|
||||
key string
|
||||
check func(t *testing.T, conf *Config)
|
||||
}
|
||||
testCases := []testCase{
|
||||
{
|
||||
name: "test1",
|
||||
args: []string{"--build.cmd", "go build -o ./tmp/main ."},
|
||||
key: "build.cmd",
|
||||
check: func(t *testing.T, conf *Config) {
|
||||
assert.Equal(t, "go build -o ./tmp/main .", conf.Build.Cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tmp dir test",
|
||||
args: []string{"--tmp_dir", "test"},
|
||||
key: "tmp_dir",
|
||||
check: func(t *testing.T, conf *Config) {
|
||||
assert.Equal(t, "test", conf.TmpDir)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "check int64",
|
||||
args: []string{"--build.kill_delay", "1000"},
|
||||
key: "build.kill_delay",
|
||||
check: func(t *testing.T, conf *Config) {
|
||||
assert.Equal(t, time.Duration(1000), conf.Build.KillDelay)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "check bool",
|
||||
args: []string{"--build.exclude_unchanged", "true"},
|
||||
key: "build.exclude_unchanged",
|
||||
check: func(t *testing.T, conf *Config) {
|
||||
assert.Equal(t, true, conf.Build.ExcludeUnchanged)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "check exclude_regex",
|
||||
args: []string{"--build.exclude_regex", `["_test.go"]`},
|
||||
check: func(t *testing.T, conf *Config) {
|
||||
assert.Equal(t, []string{"_test.go"}, conf.Build.ExcludeRegex)
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
os.Chdir(dir)
|
||||
flag := flag.NewFlagSet(t.Name(), flag.ExitOnError)
|
||||
cmdArgs := ParseConfigFlag(flag)
|
||||
flag.Parse(tc.args)
|
||||
cfg, err := InitConfig("")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
}
|
||||
cfg.WithArgs(cmdArgs)
|
||||
tc.check(t, cfg)
|
||||
})
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -26,12 +26,12 @@ var (
|
||||
type logFunc func(string, ...interface{})
|
||||
|
||||
type logger struct {
|
||||
config *config
|
||||
config *Config
|
||||
colors map[string]string
|
||||
loggers map[string]logFunc
|
||||
}
|
||||
|
||||
func newLogger(cfg *config) *logger {
|
||||
func newLogger(cfg *Config) *logger {
|
||||
if cfg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
+89
-3
@@ -4,9 +4,12 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -54,7 +57,7 @@ func (e *Engine) isTmpDir(path string) bool {
|
||||
}
|
||||
|
||||
func (e *Engine) isTestDataDir(path string) bool {
|
||||
return path == e.config.TestDataPath()
|
||||
return path == e.config.testDataPath()
|
||||
}
|
||||
|
||||
func isHiddenDirectory(path string) bool {
|
||||
@@ -199,7 +202,7 @@ func cmdPath(path string) string {
|
||||
return strings.Split(path, " ")[0]
|
||||
}
|
||||
|
||||
func adaptToVariousPlatforms(c *config) {
|
||||
func adaptToVariousPlatforms(c *Config) {
|
||||
// Fix the default configuration is not used in Windows
|
||||
// Use the unix configuration on Windows
|
||||
if runtime.GOOS == PlatformWindows {
|
||||
@@ -207,7 +210,7 @@ func adaptToVariousPlatforms(c *config) {
|
||||
runName := "start"
|
||||
extName := ".exe"
|
||||
originBin := c.Build.Bin
|
||||
|
||||
|
||||
if 0 < len(c.Build.FullBin) {
|
||||
|
||||
if !strings.HasSuffix(c.Build.FullBin, extName) {
|
||||
@@ -265,3 +268,86 @@ func (a *checksumMap) updateFileChecksum(filename, newChecksum string) (ok bool)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TomlInfo is a struct for toml config file
|
||||
type TomlInfo struct {
|
||||
fieldPath string
|
||||
field reflect.StructField
|
||||
Value *string
|
||||
}
|
||||
|
||||
func setValue2Struct(v reflect.Value, fieldName string, value string) {
|
||||
index := strings.Index(fieldName, ".")
|
||||
if index == -1 && len(fieldName) == 0 {
|
||||
return
|
||||
}
|
||||
fields := strings.Split(fieldName, ".")
|
||||
var addressableVal reflect.Value
|
||||
switch v.Type().String() {
|
||||
case "*runner.Config":
|
||||
addressableVal = v.Elem()
|
||||
default:
|
||||
addressableVal = v
|
||||
}
|
||||
if len(fields) == 1 {
|
||||
// string slice int switch case
|
||||
field := addressableVal.FieldByName(fieldName)
|
||||
switch field.Kind() {
|
||||
case reflect.String:
|
||||
field.SetString(value)
|
||||
case reflect.Slice:
|
||||
if field.Len() == 0 {
|
||||
field.Set(reflect.Append(field, reflect.ValueOf(value)))
|
||||
}
|
||||
case reflect.Int64:
|
||||
i, _ := strconv.ParseInt(value, 10, 64)
|
||||
field.SetInt(i)
|
||||
case reflect.Int:
|
||||
i, _ := strconv.Atoi(value)
|
||||
field.SetInt(int64(i))
|
||||
case reflect.Bool:
|
||||
b, _ := strconv.ParseBool(value)
|
||||
field.SetBool(b)
|
||||
case reflect.Ptr:
|
||||
field.SetString(value)
|
||||
default:
|
||||
log.Fatalf("unsupported type %s", v.FieldByName(fields[0]).Kind())
|
||||
}
|
||||
} else if len(fields) == 0 {
|
||||
return
|
||||
} else {
|
||||
field := addressableVal.FieldByName(fields[0])
|
||||
s2 := fieldName[index+1:]
|
||||
setValue2Struct(field, s2, value)
|
||||
}
|
||||
}
|
||||
|
||||
// flatConfig ...
|
||||
func flatConfig(stut interface{}) map[string]TomlInfo {
|
||||
m := make(map[string]TomlInfo)
|
||||
t := reflect.TypeOf(stut)
|
||||
setTage2Map("", t, m, "")
|
||||
return m
|
||||
}
|
||||
|
||||
func setTage2Map(root string, t reflect.Type, m map[string]TomlInfo, fieldPath string) {
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
tomlVal := field.Tag.Get("toml")
|
||||
switch field.Type.Kind() {
|
||||
case reflect.Struct:
|
||||
path := fieldPath + field.Name + "."
|
||||
setTage2Map(root+tomlVal+".", field.Type, m, path)
|
||||
default:
|
||||
if tomlVal == "" {
|
||||
continue
|
||||
}
|
||||
tomlPath := root + tomlVal
|
||||
path := fieldPath + field.Name
|
||||
var v *string
|
||||
str := ""
|
||||
v = &str
|
||||
m[tomlPath] = TomlInfo{field: field, Value: v, fieldPath: path}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+29
-3
@@ -2,16 +2,20 @@ package runner
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIsDirRootPath(t *testing.T) {
|
||||
@@ -134,7 +138,7 @@ func TestChecksumMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAdaptToVariousPlatforms(t *testing.T) {
|
||||
config := &config{
|
||||
config := &Config{
|
||||
Build: cfgBuild{
|
||||
Bin: "tmp\\main.exe -dev",
|
||||
},
|
||||
@@ -147,7 +151,7 @@ func TestAdaptToVariousPlatforms(t *testing.T) {
|
||||
|
||||
func Test_killCmd_no_process(t *testing.T) {
|
||||
e := Engine{
|
||||
config: &config{
|
||||
config: &Config{
|
||||
Build: cfgBuild{
|
||||
SendInterrupt: false,
|
||||
},
|
||||
@@ -180,7 +184,7 @@ func Test_killCmd_SendInterrupt_false(t *testing.T) {
|
||||
os.Remove("pid")
|
||||
defer os.Remove("pid")
|
||||
e := Engine{
|
||||
config: &config{
|
||||
config: &Config{
|
||||
Build: cfgBuild{
|
||||
SendInterrupt: false,
|
||||
},
|
||||
@@ -230,3 +234,25 @@ func Test_killCmd_SendInterrupt_false(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStructureFieldTagMap(t *testing.T) {
|
||||
c := Config{}
|
||||
tagMap := flatConfig(c)
|
||||
for _, i2 := range tagMap {
|
||||
fmt.Printf("%v\n", i2.fieldPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetStructValue(t *testing.T) {
|
||||
c := Config{}
|
||||
v := reflect.ValueOf(&c)
|
||||
setValue2Struct(v, "TmpDir", "asdasd")
|
||||
assert.Equal(t, "asdasd", c.TmpDir)
|
||||
}
|
||||
|
||||
func TestNestStructValue(t *testing.T) {
|
||||
c := Config{}
|
||||
v := reflect.ValueOf(&c)
|
||||
setValue2Struct(v, "Build.Cmd", "asdasd")
|
||||
assert.Equal(t, "asdasd", c.Build.Cmd)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user