Skip to content

Commit

Permalink
add unit tests for func cmd (#84)
Browse files Browse the repository at this point in the history
Co-authored-by: Rick <linuxsuren@users.noreply.github.com>
  • Loading branch information
LinuxSuRen and LinuxSuRen authored Jun 4, 2023
1 parent dc66784 commit b0b9bf8
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 7 deletions.
81 changes: 81 additions & 0 deletions cmd/function.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cmd

import (
"fmt"
"go/ast"
"go/doc"
"go/parser"
"go/token"
"path/filepath"
"reflect"
"runtime"
"strings"

"github.com/linuxsuren/api-testing/pkg/render"
"github.com/spf13/cobra"
)

func createFunctionCmd() (c *cobra.Command) {
c = &cobra.Command{
Use: "func",
Short: "Print all the supported functions",
RunE: func(cmd *cobra.Command, args []string) (err error) {
if len(args) > 0 {
name := args[0]
if fn, ok := render.FuncMap()[name]; ok {
cmd.Println(reflect.TypeOf(fn))
desc := FuncDescription(fn)
if desc != "" {
fmt.Println(desc)
}
} else {
cmd.Println("No such function")
}
} else {
for name, fn := range render.FuncMap() {
cmd.Println(name, reflect.TypeOf(fn))
}
}
return
},
}
return
}

// Get the name and path of a func
func FuncPathAndName(f interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
}

// Get the name of a func (with package path)
func FuncName(f interface{}) string {
splitFuncName := strings.Split(FuncPathAndName(f), ".")
return splitFuncName[len(splitFuncName)-1]
}

// Get description of a func
func FuncDescription(f interface{}) (desc string) {
fileName, _ := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).FileLine(0)
funcName := FuncName(f)
fset := token.NewFileSet()

// Parse src
parsedAst, err := parser.ParseFile(fset, fileName, nil, parser.ParseComments)
if err == nil {
pkg := &ast.Package{
Name: "Any",
Files: make(map[string]*ast.File),
}
pkg.Files[fileName] = parsedAst

importPath, _ := filepath.Abs("/")
myDoc := doc.New(pkg, importPath, doc.AllDecls)
for _, theFunc := range myDoc.Funcs {
if theFunc.Name == funcName {
desc = theFunc.Doc
break
}
}
}
return
}
52 changes: 52 additions & 0 deletions cmd/function_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cmd_test

import (
"bytes"
"testing"

"github.com/linuxsuren/api-testing/cmd"
fakeruntime "github.com/linuxsuren/go-fake-runtime"
"github.com/stretchr/testify/assert"
)

func TestCreateFunctionCommand(t *testing.T) {
tests := []struct {
name string
args []string
verify func(t *testing.T, output string)
}{{
name: "normal",
args: []string{"func"},
verify: func(t *testing.T, output string) {
assert.NotEmpty(t, output)
},
}, {
name: "with function name",
args: []string{"func", "clean"},
verify: func(t *testing.T, output string) {
assert.NotEmpty(t, output)
},
}, {
name: "with not exit function",
args: []string{"func", "fake"},
verify: func(t *testing.T, output string) {
assert.Equal(t, "No such function\n", output)
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := cmd.NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, cmd.NewFakeGRPCServer())

buf := new(bytes.Buffer)
c.SetOut(buf)
c.SetArgs(tt.args)

err := c.Execute()
assert.NoError(t, err)

if tt.verify != nil {
tt.verify(t, buf.String())
}
})
}
}
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer) (c *cobra.Comm
c.AddCommand(createInitCommand(execer),
createRunCommand(), createSampleCmd(),
createServerCmd(gRPCServer), createJSONSchemaCmd(),
createServiceCommand(execer))
createServiceCommand(execer), createFunctionCmd())
return
}

Expand Down
17 changes: 11 additions & 6 deletions pkg/render/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,21 @@ import (
func Render(name, text string, ctx interface{}) (result string, err error) {
var tpl *template.Template
if tpl, err = template.New(name).
Funcs(sprig.FuncMap()).
Funcs(template.FuncMap{
"randomKubernetesName": func() string {
return util.String(8)
},
}).Parse(text); err == nil {
Funcs(FuncMap()).
Parse(text); err == nil {
buf := new(bytes.Buffer)
if err = tpl.Execute(buf, ctx); err == nil {
result = strings.TrimSpace(buf.String())
}
}
return
}

// FuncMap reutrns all the supported functions
func FuncMap() template.FuncMap {
funcs := sprig.FuncMap()
funcs["randomKubernetesName"] = func() string {
return util.String(8)
}
return funcs
}

0 comments on commit b0b9bf8

Please sign in to comment.