mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-22 01:57:12 -05:00
fix commands issues (#492)
* fix api commands output * remove unused code * fix convert always has -r * update merge err to locate failed file
This commit is contained in:
parent
8702812735
commit
a5e24544a2
@ -18,6 +18,7 @@ package merge
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"v2ray.com/core/common/cmdarg"
|
"v2ray.com/core/common/cmdarg"
|
||||||
@ -73,14 +74,14 @@ func loadFiles(args []string) (map[string]interface{}, error) {
|
|||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
r, err := cmdarg.LoadArg(arg)
|
r, err := cmdarg.LoadArg(arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("fail to load %s: %s", arg, err)
|
||||||
}
|
}
|
||||||
m, err := decode(r)
|
m, err := decode(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("fail to decode %s: %s", arg, err)
|
||||||
}
|
}
|
||||||
if err = mergeMaps(c, m); err != nil {
|
if err = mergeMaps(c, m); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("fail to merge %s: %s", arg, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
|
@ -2,7 +2,10 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -11,8 +14,6 @@ import (
|
|||||||
"v2ray.com/core/main/commands/base"
|
"v2ray.com/core/main/commands/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
type serviceHandler func(ctx context.Context, conn *grpc.ClientConn, cmd *base.Command, args []string) string
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
apiServerAddrPtr string
|
apiServerAddrPtr string
|
||||||
apiTimeout int
|
apiTimeout int
|
||||||
@ -39,16 +40,55 @@ func dialAPIServer() (conn *grpc.ClientConn, ctx context.Context, close func())
|
|||||||
}
|
}
|
||||||
|
|
||||||
func showResponese(m proto.Message) {
|
func showResponese(m proto.Message) {
|
||||||
msg := ""
|
if isEmpty(m) {
|
||||||
bs, err := proto.Marshal(m)
|
// avoid outputs like `{}`, `{"key":{}}`
|
||||||
if err != nil {
|
|
||||||
msg = err.Error()
|
|
||||||
} else {
|
|
||||||
msg = string(bs)
|
|
||||||
msg = strings.TrimSpace(msg)
|
|
||||||
}
|
|
||||||
if msg == "" {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println(msg)
|
b := new(strings.Builder)
|
||||||
|
e := json.NewEncoder(b)
|
||||||
|
e.SetIndent("", " ")
|
||||||
|
e.SetEscapeHTML(false)
|
||||||
|
err := e.Encode(m)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stdout, "%v\n", m)
|
||||||
|
base.Fatalf("error encode json: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(strings.TrimSpace(b.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// isEmpty checks if the response is empty (all zero values).
|
||||||
|
// proto.Message types always "omitempty" on fields,
|
||||||
|
// there's no chance for a response to show zero-value messages,
|
||||||
|
// so we can perform isZero test here
|
||||||
|
func isEmpty(response interface{}) bool {
|
||||||
|
s := reflect.Indirect(reflect.ValueOf(response))
|
||||||
|
if s.Kind() == reflect.Invalid {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
switch s.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < s.NumField(); i++ {
|
||||||
|
f := s.Type().Field(i)
|
||||||
|
if f.Name[0] < 65 || f.Name[0] > 90 {
|
||||||
|
// continue if not exported.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
field := s.Field(i)
|
||||||
|
if !isEmpty(field.Interface()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
for i := 0; i < s.Len(); i++ {
|
||||||
|
if !isEmpty(s.Index(i).Interface()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if !s.IsZero() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
140
main/commands/all/api/shared_test.go
Normal file
140
main/commands/all/api/shared_test.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
statsService "v2ray.com/core/app/stats/command"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEmptyResponese_0(t *testing.T) {
|
||||||
|
r := &statsService.QueryStatsResponse{
|
||||||
|
Stat: []*statsService.Stat{
|
||||||
|
{
|
||||||
|
Name: "1>>2",
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "1>>2>>3",
|
||||||
|
Value: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_1(t *testing.T) {
|
||||||
|
r := (*statsService.QueryStatsResponse)(nil)
|
||||||
|
assert(t, isEmpty(r), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_2(t *testing.T) {
|
||||||
|
r := &statsService.QueryStatsResponse{
|
||||||
|
Stat: nil,
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_3(t *testing.T) {
|
||||||
|
r := &statsService.QueryStatsResponse{
|
||||||
|
Stat: []*statsService.Stat{},
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_4(t *testing.T) {
|
||||||
|
r := &statsService.QueryStatsResponse{
|
||||||
|
Stat: []*statsService.Stat{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Value: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_5(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
Value *statsService.QueryStatsResponse
|
||||||
|
}
|
||||||
|
r := &test{
|
||||||
|
Value: &statsService.QueryStatsResponse{
|
||||||
|
Stat: []*statsService.Stat{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_6(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
Value *statsService.QueryStatsResponse
|
||||||
|
}
|
||||||
|
r := &test{
|
||||||
|
Value: &statsService.QueryStatsResponse{
|
||||||
|
Stat: []*statsService.Stat{
|
||||||
|
{
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_7(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
Value *int
|
||||||
|
}
|
||||||
|
v := 1
|
||||||
|
r := &test{
|
||||||
|
Value: &v,
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_8(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
Value *int
|
||||||
|
}
|
||||||
|
v := 0
|
||||||
|
r := &test{
|
||||||
|
Value: &v,
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_9(t *testing.T) {
|
||||||
|
assert(t, isEmpty(0), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_10(t *testing.T) {
|
||||||
|
assert(t, isEmpty(1), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_11(t *testing.T) {
|
||||||
|
r := []*statsService.Stat{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyResponese_12(t *testing.T) {
|
||||||
|
r := []*statsService.Stat{
|
||||||
|
{
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert(t, isEmpty(r), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func assert(t *testing.T, value, expected bool) {
|
||||||
|
if value != expected {
|
||||||
|
t.Fatalf("Expected: %v, actual: %v", expected, value)
|
||||||
|
}
|
||||||
|
}
|
@ -72,7 +72,7 @@ func setConfArgs(cmd *base.Command) {
|
|||||||
cmd.Flag.StringVar(&inputFormat, "i", "json", "")
|
cmd.Flag.StringVar(&inputFormat, "i", "json", "")
|
||||||
cmd.Flag.StringVar(&outputFormat, "output", "json", "")
|
cmd.Flag.StringVar(&outputFormat, "output", "json", "")
|
||||||
cmd.Flag.StringVar(&outputFormat, "o", "json", "")
|
cmd.Flag.StringVar(&outputFormat, "o", "json", "")
|
||||||
cmd.Flag.BoolVar(&confDirRecursively, "r", true, "")
|
cmd.Flag.BoolVar(&confDirRecursively, "r", false, "")
|
||||||
}
|
}
|
||||||
func executeConvert(cmd *base.Command, args []string) {
|
func executeConvert(cmd *base.Command, args []string) {
|
||||||
setConfArgs(cmd)
|
setConfArgs(cmd)
|
||||||
|
Loading…
Reference in New Issue
Block a user