change: add exit code

This commit is contained in:
debugtalk
2022-10-21 21:39:18 +08:00
parent 4a8fcd4fd9
commit c200ef6900
14 changed files with 137 additions and 71 deletions
+5 -4
View File
@@ -14,6 +14,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/builtin"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
"github.com/httprunner/httprunner/v4/hrp/internal/json" "github.com/httprunner/httprunner/v4/hrp/internal/json"
"github.com/httprunner/httprunner/v4/hrp/internal/sdk" "github.com/httprunner/httprunner/v4/hrp/internal/sdk"
"github.com/httprunner/httprunner/v4/hrp/pkg/boomer" "github.com/httprunner/httprunner/v4/hrp/pkg/boomer"
@@ -121,7 +122,7 @@ func (b *HRPBoomer) ConvertTestCasesToBoomerTasks(testcases ...ITestCase) (taskS
testCases, err := LoadTestCases(testcases...) testCases, err := LoadTestCases(testcases...)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to load testcases") log.Error().Err(err).Msg("failed to load testcases")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
for _, testcase := range testCases { for _, testcase := range testCases {
@@ -139,7 +140,7 @@ func (b *HRPBoomer) ParseTestCases(testCases []*TestCase) []*TCase {
caseRunner, err := b.hrpRunner.NewCaseRunner(tc) caseRunner, err := b.hrpRunner.NewCaseRunner(tc)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to create runner") log.Error().Err(err).Msg("failed to create runner")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
caseRunner.parsedConfig.Parameters = caseRunner.parametersIterator.outParameters() caseRunner.parsedConfig.Parameters = caseRunner.parametersIterator.outParameters()
parsedTestCases = append(parsedTestCases, &TCase{ parsedTestCases = append(parsedTestCases, &TCase{
@@ -155,7 +156,7 @@ func (b *HRPBoomer) TestCasesToBytes(testcases ...ITestCase) []byte {
testCases, err := LoadTestCases(testcases...) testCases, err := LoadTestCases(testcases...)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to load testcases") log.Error().Err(err).Msg("failed to load testcases")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
tcs := b.ParseTestCases(testCases) tcs := b.ParseTestCases(testCases)
testCasesBytes, err := json.Marshal(tcs) testCasesBytes, err := json.Marshal(tcs)
@@ -318,7 +319,7 @@ func (b *HRPBoomer) convertBoomerTask(testcase *TestCase, rendezvousList []*Rend
caseRunner, err := b.hrpRunner.NewCaseRunner(testcase) caseRunner, err := b.hrpRunner.NewCaseRunner(testcase)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to create runner") log.Error().Err(err).Msg("failed to create runner")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
if caseRunner.parser.plugin != nil { if caseRunner.parser.plugin != nil {
b.pluginsMutex.Lock() b.pluginsMutex.Lock()
+20 -9
View File
@@ -15,6 +15,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/builtin"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
"github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/myexec"
"github.com/httprunner/httprunner/v4/hrp/internal/version" "github.com/httprunner/httprunner/v4/hrp/internal/version"
) )
@@ -175,11 +176,11 @@ func buildGo(path string, output string) error {
content, err := os.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to read file") log.Error().Err(err).Msg("failed to read file")
return errors.Wrap(err, "read file failed") return errors.Wrap(code.LoadFileError, err.Error())
} }
functionNames, err := regexGoFunctionName.findAllFunctionNames(string(content)) functionNames, err := regexGoFunctionName.findAllFunctionNames(string(content))
if err != nil { if err != nil {
return err return errors.Wrap(code.InvalidPluginFile, err.Error())
} }
templateContent := &pluginTemplate{ templateContent := &pluginTemplate{
@@ -187,7 +188,11 @@ func buildGo(path string, output string) error {
Version: version.VERSION, Version: version.VERSION,
FunctionNames: functionNames, FunctionNames: functionNames,
} }
return templateContent.generateGo(output) err = templateContent.generateGo(output)
if err != nil {
return errors.Wrap(code.BuildGoPluginFailed, err.Error())
}
return nil
} }
// buildPy completes funppy information in debugtalk.py // buildPy completes funppy information in debugtalk.py
@@ -196,17 +201,18 @@ func buildPy(path string, output string) error {
// check the syntax of debugtalk.py // check the syntax of debugtalk.py
err := myexec.ExecPython3Command("py_compile", path) err := myexec.ExecPython3Command("py_compile", path)
if err != nil { if err != nil {
return errors.Wrap(err, "python plugin syntax invalid") return errors.Wrap(code.InvalidPluginFile,
fmt.Sprintf("python plugin syntax invalid: %s", err.Error()))
} }
content, err := os.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to read file") log.Error().Err(err).Msg("failed to read file")
return errors.Wrap(err, "read file failed") return errors.Wrap(code.LoadFileError, err.Error())
} }
functionNames, err := regexPyFunctionName.findAllFunctionNames(string(content)) functionNames, err := regexPyFunctionName.findAllFunctionNames(string(content))
if err != nil { if err != nil {
return err return errors.Wrap(code.InvalidPluginFile, err.Error())
} }
templateContent := &pluginTemplate{ templateContent := &pluginTemplate{
@@ -214,7 +220,11 @@ func buildPy(path string, output string) error {
Version: version.VERSION, Version: version.VERSION,
FunctionNames: functionNames, FunctionNames: functionNames,
} }
return templateContent.generatePy(output) err = templateContent.generatePy(output)
if err != nil {
return errors.Wrap(code.BuildPyPluginFailed, err.Error())
}
return nil
} }
func BuildPlugin(path string, output string) (err error) { func BuildPlugin(path string, output string) (err error) {
@@ -225,11 +235,12 @@ func BuildPlugin(path string, output string) (err error) {
case ".go": case ".go":
err = buildGo(path, output) err = buildGo(path, output)
default: default:
return errors.New("type error, expected .py or .go") return errors.Wrap(code.UnsupportedFileExtension,
"type error, expected .py or .go")
} }
if err != nil { if err != nil {
log.Error().Err(err).Str("path", path).Msg("build plugin failed") log.Error().Err(err).Str("path", path).Msg("build plugin failed")
os.Exit(1) return err
} }
return nil return nil
} }
+6 -6
View File
@@ -1,7 +1,6 @@
package cmd package cmd
import ( import (
"os"
"strings" "strings"
"time" "time"
@@ -30,7 +29,7 @@ var boomCmd = &cobra.Command{
} }
setLogLevel(logLevel) setLogLevel(logLevel)
}, },
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
var paths []hrp.ITestCase var paths []hrp.ITestCase
for _, arg := range args { for _, arg := range args {
path := hrp.TestCasePath(arg) path := hrp.TestCasePath(arg)
@@ -42,7 +41,7 @@ var boomCmd = &cobra.Command{
err := builtin.LoadFile(boomArgs.profile, &boomArgs.Profile) err := builtin.LoadFile(boomArgs.profile, &boomArgs.Profile)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to load profile") log.Error().Err(err).Msg("failed to load profile")
os.Exit(1) return err
} }
} }
@@ -89,6 +88,7 @@ var boomCmd = &cobra.Command{
hrpBoomer.InitBoomer() hrpBoomer.InitBoomer()
hrpBoomer.Run(paths...) hrpBoomer.Run(paths...)
} }
return nil
}, },
} }
@@ -141,13 +141,13 @@ func init() {
boomCmd.Flags().IntVar(&boomArgs.expectWorkersMaxWait, "expect-workers-max-wait", 120, "How many workers master should expect to connect before starting the test (only when --autostart is used") boomCmd.Flags().IntVar(&boomArgs.expectWorkersMaxWait, "expect-workers-max-wait", 120, "How many workers master should expect to connect before starting the test (only when --autostart is used")
} }
func makeHRPBoomer() *hrp.HRPBoomer { func makeHRPBoomer() (*hrp.HRPBoomer, error) {
// if set profile, the priority is higher than the other commands // if set profile, the priority is higher than the other commands
if boomArgs.profile != "" { if boomArgs.profile != "" {
err := builtin.LoadFile(boomArgs.profile, &boomArgs) err := builtin.LoadFile(boomArgs.profile, &boomArgs)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to load profile") log.Error().Err(err).Msg("failed to load profile")
os.Exit(1) return nil, err
} }
} }
hrpBoomer := hrp.NewStandaloneBoomer(boomArgs.SpawnCount, boomArgs.SpawnRate) hrpBoomer := hrp.NewStandaloneBoomer(boomArgs.SpawnCount, boomArgs.SpawnRate)
@@ -157,5 +157,5 @@ func makeHRPBoomer() *hrp.HRPBoomer {
hrpBoomer.SetProfile(&boomArgs.Profile) hrpBoomer.SetProfile(&boomArgs.Profile)
hrpBoomer.EnableGracefulQuit(context.Background()) hrpBoomer.EnableGracefulQuit(context.Background())
hrpBoomer.InitBoomer() hrpBoomer.InitBoomer()
return hrpBoomer return hrpBoomer, nil
} }
+8 -6
View File
@@ -21,11 +21,9 @@ var runCurlCmd = &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
setLogLevel(logLevel) setLogLevel(logLevel)
}, },
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
runner := makeHRPRunner() runner := makeHRPRunner()
if runner.Run(makeCurlTestCase(args)) != nil { return runner.Run(makeCurlTestCase(args))
os.Exit(1)
}
}, },
} }
@@ -41,9 +39,13 @@ var boomCurlCmd = &cobra.Command{
} }
setLogLevel(logLevel) setLogLevel(logLevel)
}, },
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
boomer := makeHRPBoomer() boomer, err := makeHRPBoomer()
if err != nil {
return err
}
boomer.Run(makeCurlTestCase(args)) boomer.Run(makeCurlTestCase(args))
return nil
}, },
} }
+1 -2
View File
@@ -2,7 +2,6 @@ package cmd
import ( import (
"errors" "errors"
"os"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@@ -37,7 +36,7 @@ var scaffoldCmd = &cobra.Command{
err := scaffold.CreateScaffold(args[0], pluginType, venv, force) err := scaffold.CreateScaffold(args[0], pluginType, venv, force)
if err != nil { if err != nil {
log.Error().Err(err).Msg("create scaffold project failed") log.Error().Err(err).Msg("create scaffold project failed")
os.Exit(1) return err
} }
log.Info().Str("projectName", args[0]).Msg("create scaffold success") log.Info().Str("projectName", args[0]).Msg("create scaffold success")
return nil return nil
+10 -8
View File
@@ -22,6 +22,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
"github.com/httprunner/httprunner/v4/hrp/internal/json" "github.com/httprunner/httprunner/v4/hrp/internal/json"
) )
@@ -235,8 +236,6 @@ func InterfaceType(raw interface{}) string {
return reflect.TypeOf(raw).String() return reflect.TypeOf(raw).String()
} }
var ErrUnsupportedFileExt = fmt.Errorf("unsupported file extension")
// LoadFile loads file content with file extension and assigns to structObj // LoadFile loads file content with file extension and assigns to structObj
func LoadFile(path string, structObj interface{}) (err error) { func LoadFile(path string, structObj interface{}) (err error) {
log.Info().Str("path", path).Msg("load file") log.Info().Str("path", path).Msg("load file")
@@ -252,12 +251,15 @@ func LoadFile(path string, structObj interface{}) (err error) {
decoder := json.NewDecoder(bytes.NewReader(file)) decoder := json.NewDecoder(bytes.NewReader(file))
decoder.UseNumber() decoder.UseNumber()
err = decoder.Decode(structObj) err = decoder.Decode(structObj)
err = errors.Wrap(code.LoadJSONError, err.Error())
case ".yaml", ".yml": case ".yaml", ".yml":
err = yaml.Unmarshal(file, structObj) err = yaml.Unmarshal(file, structObj)
err = errors.Wrap(code.LoadYAMLError, err.Error())
case ".env": case ".env":
err = parseEnvContent(file, structObj) err = parseEnvContent(file, structObj)
err = errors.Wrap(code.LoadEnvError, err.Error())
default: default:
err = ErrUnsupportedFileExt err = code.UnsupportedFileExtension
} }
return err return err
} }
@@ -297,14 +299,14 @@ func loadFromCSV(path string) []map[string]interface{} {
file, err := ReadFile(path) file, err := ReadFile(path)
if err != nil { if err != nil {
log.Error().Err(err).Msg("read csv file failed") log.Error().Err(err).Msg("read csv file failed")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
r := csv.NewReader(strings.NewReader(string(file))) r := csv.NewReader(strings.NewReader(string(file)))
content, err := r.ReadAll() content, err := r.ReadAll()
if err != nil { if err != nil {
log.Error().Err(err).Msg("parse csv file failed") log.Error().Err(err).Msg("parse csv file failed")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
firstLine := content[0] // parameter names firstLine := content[0] // parameter names
var result []map[string]interface{} var result []map[string]interface{}
@@ -323,7 +325,7 @@ func loadMessage(path string) []byte {
file, err := ReadFile(path) file, err := ReadFile(path)
if err != nil { if err != nil {
log.Error().Err(err).Msg("read message file failed") log.Error().Err(err).Msg("read message file failed")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
return file return file
} }
@@ -333,13 +335,13 @@ func ReadFile(path string) ([]byte, error) {
path, err = filepath.Abs(path) path, err = filepath.Abs(path)
if err != nil { if err != nil {
log.Error().Err(err).Str("path", path).Msg("convert absolute path failed") log.Error().Err(err).Str("path", path).Msg("convert absolute path failed")
return nil, err return nil, errors.Wrap(code.LoadFileError, err.Error())
} }
file, err := os.ReadFile(path) file, err := os.ReadFile(path)
if err != nil { if err != nil {
log.Error().Err(err).Msg("read file failed") log.Error().Err(err).Msg("read file failed")
return nil, err return nil, errors.Wrap(code.LoadFileError, err.Error())
} }
return file, nil return file, nil
} }
+43 -13
View File
@@ -12,24 +12,40 @@ const (
) )
// environment: [2, 10) // environment: [2, 10)
var (
InvalidPython3Venv = errors.New("prepare python3 venv failed") // 9
)
// loader: [10, 20) // loader: [10, 20)
var ( var (
LoadError = errors.New("load error") // 10 LoadFileError = errors.New("load file error") // 10
LoadJSONError = errors.New("load json error") // 11 LoadJSONError = errors.New("load json error") // 11
LoadYAMLError = errors.New("load yaml error") // 12 LoadYAMLError = errors.New("load yaml error") // 12
LoadEnvError = errors.New("load .env error") // 13
LoadCSVError = errors.New("load csv error") // 14
InvalidCaseFormat = errors.New("invalid case format") // 15
UnsupportedFileExtension = errors.New("unsupported file extension") // 16
ReferencedFileNotFound = errors.New("referenced file not found") // 17
InvalidPluginFile = errors.New("invalid plugin file") // 18
) )
// parser: [20, 30) // parser: [20, 30)
var ( var (
ParseError = errors.New("parse error") // 20 ParseError = errors.New("parse error") // 20
ParseStringError = errors.New("parse string failed") // 21 VariableNotFound = errors.New("variable not found") // 21
ParseVariablesError = errors.New("parse variables failed") // 22 ParseFunctionError = errors.New("parse function failed") // 22
ParseConfigError = errors.New("parse config error") // 25 CallFunctionError = errors.New("call function failed") // 23
ParseVariablesError = errors.New("parse variables failed") // 24
) )
// runner: [30, 40) // runner: [30, 40)
var (
InitPluginFailed = errors.New("init plugin failed") // 31
BuildGoPluginFailed = errors.New("build go plugin failed") // 32
BuildPyPluginFailed = errors.New("build py plugin failed") // 33
)
// summary: [40, 50) // summary: [40, 50)
// ios device related: [50, 60) // ios device related: [50, 60)
@@ -67,16 +83,31 @@ var (
// CV related: [90, 100) // CV related: [90, 100)
var errorsMap = map[error]int{ var errorsMap = map[error]int{
// environment
InvalidPython3Venv: 9,
// loader // loader
LoadError: 10, LoadFileError: 10,
LoadJSONError: 11, LoadJSONError: 11,
LoadYAMLError: 12, LoadYAMLError: 12,
LoadEnvError: 13,
LoadCSVError: 14,
InvalidCaseFormat: 15,
UnsupportedFileExtension: 16,
ReferencedFileNotFound: 17,
InvalidPluginFile: 18,
// parser // parser
ParseError: 20, ParseError: 20,
ParseStringError: 21, VariableNotFound: 21,
ParseVariablesError: 22, ParseFunctionError: 22,
ParseConfigError: 25, CallFunctionError: 23,
ParseVariablesError: 24,
// runner
InitPluginFailed: 31,
BuildGoPluginFailed: 32,
BuildPyPluginFailed: 33,
// ios related // ios related
IOSDeviceConnectionError: 50, IOSDeviceConnectionError: 50,
@@ -105,7 +136,6 @@ var errorsMap = map[error]int{
func GetErrorCode(err error) (exitCode int) { func GetErrorCode(err error) (exitCode int) {
if err == nil { if err == nil {
log.Info().Int("code", Success).Msg("hrp exit")
return Success return Success
} }
+2 -1
View File
@@ -10,6 +10,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
"github.com/httprunner/httprunner/v4/hrp/internal/env" "github.com/httprunner/httprunner/v4/hrp/internal/env"
) )
@@ -39,7 +40,7 @@ func EnsurePython3Venv(venv string, packages ...string) (python3 string, err err
} }
python3, err = ensurePython3Venv(venv, packages...) python3, err = ensurePython3Venv(venv, packages...)
if err != nil { if err != nil {
return "", errors.Wrap(err, "prepare python3 venv failed") return "", errors.Wrap(code.InvalidPython3Venv, err.Error())
} }
python3Executable = python3 python3Executable = python3
log.Info().Str("Python3Executable", python3Executable).Msg("set python3 executable path") log.Info().Str("Python3Executable", python3Executable).Msg("set python3 executable path")
+1 -1
View File
@@ -54,7 +54,7 @@ func LoadTestCases(iTestCases ...ITestCase) ([]*TestCase, error) {
tc, err := testCasePath.ToTestCase() tc, err := testCasePath.ToTestCase()
if err != nil { if err != nil {
log.Warn().Err(err).Str("path", path).Msg("load testcase failed") log.Warn().Err(err).Str("path", path).Msg("load testcase failed")
return nil return err
} }
testCases = append(testCases, tc) testCases = append(testCases, tc)
return nil return nil
+12 -7
View File
@@ -125,14 +125,19 @@ func (p *Parser) Parse(raw interface{}, variablesMapping map[string]interface{})
} }
} }
func parseJSONNumber(raw builtinJSON.Number) (interface{}, error) { func parseJSONNumber(raw builtinJSON.Number) (value interface{}, err error) {
if strings.Contains(raw.String(), ".") { if strings.Contains(raw.String(), ".") {
// float64 // float64
return raw.Float64() value, err = raw.Float64()
} else { } else {
// int64 // int64
return raw.Int64() value, err = raw.Int64()
} }
if err != nil {
return nil, errors.Wrap(code.ParseError,
fmt.Sprintf("parse json number failed: %v", err))
}
return value, nil
} }
const ( const (
@@ -185,18 +190,18 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{}
argsStr := funcMatched[2] argsStr := funcMatched[2]
arguments, err := parseFunctionArguments(argsStr) arguments, err := parseFunctionArguments(argsStr)
if err != nil { if err != nil {
return raw, errors.Wrap(code.ParseStringError, err.Error()) return raw, errors.Wrap(code.ParseFunctionError, err.Error())
} }
parsedArgs, err := p.Parse(arguments, variablesMapping) parsedArgs, err := p.Parse(arguments, variablesMapping)
if err != nil { if err != nil {
return raw, errors.Wrap(code.ParseStringError, err.Error()) return raw, err
} }
result, err := p.callFunc(funcName, parsedArgs.([]interface{})...) result, err := p.callFunc(funcName, parsedArgs.([]interface{})...)
if err != nil { if err != nil {
log.Error().Str("funcName", funcName).Interface("arguments", arguments). log.Error().Str("funcName", funcName).Interface("arguments", arguments).
Err(err).Msg("call function failed") Err(err).Msg("call function failed")
return raw, errors.Wrap(code.ParseStringError, err.Error()) return raw, errors.Wrap(code.CallFunctionError, err.Error())
} }
log.Info().Str("funcName", funcName).Interface("arguments", arguments). log.Info().Str("funcName", funcName).Interface("arguments", arguments).
Interface("output", result).Msg("call function success") Interface("output", result).Msg("call function success")
@@ -228,7 +233,7 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{}
} }
varValue, ok := variablesMapping[varName] varValue, ok := variablesMapping[varName]
if !ok { if !ok {
return raw, errors.Wrap(code.ParseStringError, return raw, errors.Wrap(code.VariableNotFound,
fmt.Sprintf("variable %s not found", varName)) fmt.Sprintf("variable %s not found", varName))
} }
+4 -1
View File
@@ -9,8 +9,10 @@ import (
"github.com/httprunner/funplugin" "github.com/httprunner/funplugin"
"github.com/httprunner/funplugin/fungo" "github.com/httprunner/funplugin/fungo"
"github.com/pkg/errors"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
"github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/myexec"
"github.com/httprunner/httprunner/v4/hrp/internal/sdk" "github.com/httprunner/httprunner/v4/hrp/internal/sdk"
) )
@@ -52,7 +54,7 @@ func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err er
err = BuildPlugin(pluginPath, genPyPluginPath) err = BuildPlugin(pluginPath, genPyPluginPath)
if err != nil { if err != nil {
log.Error().Err(err).Str("path", pluginPath).Msg("build plugin failed") log.Error().Err(err).Str("path", pluginPath).Msg("build plugin failed")
return nil, nil return nil, err
} }
pluginPath = genPyPluginPath pluginPath = genPyPluginPath
@@ -73,6 +75,7 @@ func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err er
plugin, err = funplugin.Init(pluginPath, pluginOptions...) plugin, err = funplugin.Init(pluginPath, pluginOptions...)
if err != nil { if err != nil {
log.Error().Err(err).Msgf("init plugin failed: %s", pluginPath) log.Error().Err(err).Msgf("init plugin failed: %s", pluginPath)
err = errors.Wrap(code.InitPluginFailed, err.Error())
return return
} }
+3 -2
View File
@@ -7,6 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -16,7 +17,7 @@ func buildHashicorpGoPlugin() {
err := BuildPlugin(tmpl("plugin/debugtalk.go"), tmpl("debugtalk.bin")) err := BuildPlugin(tmpl("plugin/debugtalk.go"), tmpl("debugtalk.bin"))
if err != nil { if err != nil {
log.Error().Err(err).Msg("build hashicorp go plugin failed") log.Error().Err(err).Msg("build hashicorp go plugin failed")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
} }
@@ -33,7 +34,7 @@ func buildHashicorpPyPlugin() {
err := ioutil.WriteFile(tmpl("debugtalk.py"), src, 0o644) err := ioutil.WriteFile(tmpl("debugtalk.py"), src, 0o644)
if err != nil { if err != nil {
log.Error().Err(err).Msg("copy hashicorp python plugin failed") log.Error().Err(err).Msg("copy hashicorp python plugin failed")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
} }
+3 -2
View File
@@ -21,6 +21,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/builtin"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
"github.com/httprunner/httprunner/v4/hrp/internal/json" "github.com/httprunner/httprunner/v4/hrp/internal/json"
"github.com/httprunner/httprunner/v4/hrp/pkg/httpstat" "github.com/httprunner/httprunner/v4/hrp/pkg/httpstat"
) )
@@ -683,7 +684,7 @@ func (s *StepRequest) CallRefCase(tc ITestCase) *StepTestCaseWithOptionalArgs {
s.step.TestCase, err = tc.ToTestCase() s.step.TestCase, err = tc.ToTestCase()
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to load testcase") log.Error().Err(err).Msg("failed to load testcase")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
return &StepTestCaseWithOptionalArgs{ return &StepTestCaseWithOptionalArgs{
step: s.step, step: s.step,
@@ -696,7 +697,7 @@ func (s *StepRequest) CallRefAPI(api IAPI) *StepAPIWithOptionalArgs {
s.step.API, err = api.ToAPI() s.step.API, err = api.ToAPI()
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to load api") log.Error().Err(err).Msg("failed to load api")
os.Exit(1) os.Exit(code.GetErrorCode(err))
} }
return &StepAPIWithOptionalArgs{ return &StepAPIWithOptionalArgs{
step: s.step, step: s.step,
+19 -9
View File
@@ -10,6 +10,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/builtin"
"github.com/httprunner/httprunner/v4/hrp/internal/code"
) )
// ITestCase represents interface for testcases, // ITestCase represents interface for testcases,
@@ -117,7 +118,8 @@ func (tc *TCase) MakeCompat() (err error) {
func (tc *TCase) ToTestCase(casePath string) (*TestCase, error) { func (tc *TCase) ToTestCase(casePath string) (*TestCase, error) {
if tc.TestSteps == nil { if tc.TestSteps == nil {
return nil, errors.New("invalid testcase format, missing teststeps!") return nil, errors.Wrap(code.InvalidCaseFormat,
"invalid testcase format, missing teststeps!")
} }
if tc.Config == nil { if tc.Config == nil {
@@ -169,7 +171,8 @@ func (tc *TCase) toTestCase() (*TestCase, error) {
if ok { if ok {
path := filepath.Join(projectRootDir, apiPath) path := filepath.Join(projectRootDir, apiPath)
if !builtin.IsFilePathExists(path) { if !builtin.IsFilePathExists(path) {
return nil, errors.New("referenced api file not found: " + path) return nil, errors.Wrap(code.ReferencedFileNotFound,
fmt.Sprintf("referenced api file not found: %s", path))
} }
refAPI := APIPath(path) refAPI := APIPath(path)
@@ -181,7 +184,8 @@ func (tc *TCase) toTestCase() (*TestCase, error) {
} else { } else {
apiMap, ok := step.API.(map[string]interface{}) apiMap, ok := step.API.(map[string]interface{})
if !ok { if !ok {
return nil, fmt.Errorf("referenced api should be map or path(string), got %v", step.API) return nil, errors.Wrap(code.InvalidCaseFormat,
fmt.Sprintf("referenced api should be map or path(string), got %v", step.API))
} }
api := &API{} api := &API{}
err = mapstructure.Decode(apiMap, api) err = mapstructure.Decode(apiMap, api)
@@ -192,7 +196,8 @@ func (tc *TCase) toTestCase() (*TestCase, error) {
} }
_, ok = step.API.(*API) _, ok = step.API.(*API)
if !ok { if !ok {
return nil, fmt.Errorf("failed to handle referenced API, got %v", step.TestCase) return nil, errors.Wrap(code.InvalidCaseFormat,
fmt.Sprintf("failed to handle referenced API, got %v", step.TestCase))
} }
testCase.TestSteps = append(testCase.TestSteps, &StepAPIWithOptionalArgs{ testCase.TestSteps = append(testCase.TestSteps, &StepAPIWithOptionalArgs{
step: step, step: step,
@@ -202,7 +207,8 @@ func (tc *TCase) toTestCase() (*TestCase, error) {
if ok { if ok {
path := filepath.Join(projectRootDir, casePath) path := filepath.Join(projectRootDir, casePath)
if !builtin.IsFilePathExists(path) { if !builtin.IsFilePathExists(path) {
return nil, errors.New("referenced testcase file not found: " + path) return nil, errors.Wrap(code.ReferencedFileNotFound,
fmt.Sprintf("referenced testcase file not found: %s", path))
} }
refTestCase := TestCasePath(path) refTestCase := TestCasePath(path)
@@ -214,7 +220,8 @@ func (tc *TCase) toTestCase() (*TestCase, error) {
} else { } else {
testCaseMap, ok := step.TestCase.(map[string]interface{}) testCaseMap, ok := step.TestCase.(map[string]interface{})
if !ok { if !ok {
return nil, fmt.Errorf("referenced testcase should be map or path(string), got %v", step.TestCase) return nil, errors.Wrap(code.InvalidCaseFormat,
fmt.Sprintf("referenced testcase should be map or path(string), got %v", step.TestCase))
} }
tCase := &TCase{} tCase := &TCase{}
err = mapstructure.Decode(testCaseMap, tCase) err = mapstructure.Decode(testCaseMap, tCase)
@@ -229,7 +236,8 @@ func (tc *TCase) toTestCase() (*TestCase, error) {
} }
_, ok = step.TestCase.(*TestCase) _, ok = step.TestCase.(*TestCase)
if !ok { if !ok {
return nil, fmt.Errorf("failed to handle referenced testcase, got %v", step.TestCase) return nil, errors.Wrap(code.InvalidCaseFormat,
fmt.Sprintf("failed to handle referenced testcase, got %v", step.TestCase))
} }
testCase.TestSteps = append(testCase.TestSteps, &StepTestCaseWithOptionalArgs{ testCase.TestSteps = append(testCase.TestSteps, &StepTestCaseWithOptionalArgs{
step: step, step: step,
@@ -317,7 +325,8 @@ func convertCompatValidator(Validators []interface{}) (err error) {
for assertMethod, iValidatorContent := range validatorMap { for assertMethod, iValidatorContent := range validatorMap {
validatorContent := iValidatorContent.([]interface{}) validatorContent := iValidatorContent.([]interface{})
if len(validatorContent) > 3 { if len(validatorContent) > 3 {
return fmt.Errorf("unexpected validator format: %v", validatorMap) return errors.Wrap(code.InvalidCaseFormat,
fmt.Sprintf("unexpected validator format: %v", validatorMap))
} }
validator.Check = validatorContent[0].(string) validator.Check = validatorContent[0].(string)
validator.Assert = assertMethod validator.Assert = assertMethod
@@ -330,7 +339,8 @@ func convertCompatValidator(Validators []interface{}) (err error) {
Validators[i] = validator Validators[i] = validator
continue continue
} }
return fmt.Errorf("unexpected validator format: %v", validatorMap) return errors.Wrap(code.InvalidCaseFormat,
fmt.Sprintf("unexpected validator format: %v", validatorMap))
} }
return nil return nil
} }