Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 229 additions & 0 deletions gen/rpc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package gen

import (
"bufio"
"bytes"
"os"
"path/filepath"
"strings"
"testing"
)

func TestBuildRpc(t *testing.T) {
const (
testPk = "test"
testGo = testPk + ".go"
)
var (
testDir = filepath.Join("testdata", "rpc")
testFile = testGo
genFile = testPk + "." + strings.ReplaceAll(t.Name(), "/", "_") + ".go"
)
pwd, err := os.Getwd()
if err != nil {
t.Errorf("getwd: %s", err)
return
}
defer func() {
if err = os.Chdir(pwd); err != nil {
t.Errorf("chdir: %s", err)
return
}
}()
if err = os.Chdir(testDir); err != nil {
t.Errorf("chdir: %s", err)
return
}
newBuilder := func(t *testing.T) (*CliBuilder, bool) {
doc, err := os.ReadFile(testFile)
if err != nil {
t.Errorf("build: error reading %s file => %s", testGo, err)
return nil, false
}
var pos int
lineScanner := bufio.NewScanner(bytes.NewReader(doc))
for i := 1; lineScanner.Scan(); i++ {
text := lineScanner.Text()
if strings.HasPrefix(text, "//go:generate") &&
strings.HasSuffix(text, t.Name()) {
pos = i
break
}
}
if err = lineScanner.Err(); err != nil {
t.Errorf("build: error scanning %s lines => %s", testGo, err)
return nil, false
}
if pos == 0 {
t.Errorf("build: unable to get pos in %s", testGo)
return nil, false
}
testDirAbs, err := os.Getwd()
if err != nil {
t.Errorf("getwd: %s", err)
return nil, false
}
return NewCliBuilder(ModeRpc).
WithPkg(testPk).
WithPwd(testDirAbs).
WithFile(testGo, doc).
WithPos(pos), true
}
t.Run("success", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err != nil {
t.Errorf("build: %s", err)
return
}
})
t.Run("success_pointer_reply", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err != nil {
t.Errorf("build: %s", err)
return
}
})
t.Run("fail_no_input", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"should have exactly 1 input parameter") {
t.Errorf("build: expects NoInput error, got => %s", err)
return
}
})
t.Run("fail_too_many_inputs", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"should have exactly 1 input parameter") {
t.Errorf("build: expects TooManyInputs error, got => %s", err)
return
}
})
t.Run("fail_no_output", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"should have exactly 2 output parameters") {
t.Errorf("build: expects NoOutput error, got => %s", err)
return
}
})
t.Run("fail_one_output", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"should have exactly 2 output parameters") {
t.Errorf("build: expects OneOutput error, got => %s", err)
return
}
})
t.Run("fail_too_many_outputs", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"should have exactly 2 output parameters") {
t.Errorf("build: expects TooManyOutputs error, got => %s", err)
return
}
})
t.Run("fail_no_error", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"should have an error as the second output parameter") {
t.Errorf("build: expects NoError error, got => %s", err)
return
}
})
t.Run("fail_no_name_type", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"should contain 'Name' and 'Type' both") {
t.Errorf("build: expects NoNameType error, got => %s", err)
return
}
})
t.Run("fail_no_type_decl", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"no available 'Interface' type declaration (*ast.GenDecl) found, ") {
t.Errorf("build: expects NoTypeDecl error, got => %s", err)
return
}
})
t.Run("fail_no_iface_type", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
if err := runTest(genFile, builder); err == nil {
t.Errorf("build: expects errors, got nil")
return
} else if !strings.Contains(err.Error(),
"no available 'Interface' type declaration (*ast.InterfaceType) found, ") {
t.Errorf("build: expects NoIfaceType error, got => %s", err)
return
}
})
t.Run("success_nort", func(t *testing.T) {
builder, ok := newBuilder(t)
if !ok {
return
}
builder = builder.WithFeats([]string{FeatureRpcNoRt})
if err := runTest(genFile, builder); err != nil {
t.Errorf("build: %s", err)
return
}
})
}
66 changes: 66 additions & 0 deletions gen/testdata/rpc/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//go:build !no_test
// +build !no_test

package test

//go:generate defc [mode] [output] [features...] TestBuildRpc/success
type Success interface {
Multiply(args chan int) (int, error)
unexported()
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/success_pointer_reply
type SuccessPointerReply interface {
GetUser(id int) (*User, error)
}

type User struct {
ID int
Name string
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_no_input
type FailNoInput interface {
NoInput() (int, error)
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_too_many_inputs
type FailTooManyInputs interface {
TooManyInputs(a, b int) (int, error)
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_no_output
type FailNoOutput interface {
NoOutput(a int)
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_one_output
type FailOneOutput interface {
OneOutput(a int) error
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_too_many_outputs
type FailTooManyOutputs interface {
TooManyOutputs(a int) (int, int, error)
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_no_error
type FailNoError interface {
NoError(a int) (int, int)
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_no_name_type
type FailNoNameType interface {
NoNameType(int) (int, error)
}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_no_type_decl
var FailNoTypeDecl struct{}

//go:generate defc [mode] [output] [features...] TestBuildRpc/fail_no_iface_type
type FailNoIfaceType struct{}

//go:generate defc [mode] [output] [features...] TestBuildRpc/success_nort
type SuccessNoRt interface {
Multiply(args chan int) (int, error)
}
2 changes: 1 addition & 1 deletion runtime/version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package defc

const Version = "v1.44.4"
const Version = "v1.44.5"
Loading