Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add grpc server support #22

Merged
merged 2 commits into from
Apr 4, 2023
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
2 changes: 2 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ jobs:
github_token: ${{ secrets.GH_PUBLISH_SECRETS }}
version: v1.14.0
args: release --skip-publish --rm-dist --snapshot
- name: Image
run: make build-image
34 changes: 34 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
tags:
- '*'

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
goreleaser:
runs-on: ubuntu-20.04
Expand All @@ -24,3 +28,33 @@ jobs:
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GH_PUBLISH_SECRETS }}

image:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3.0.0
- name: Setup Docker buildx
uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GH_PUBLISH_SECRETS }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
bin/
.idea/
coverage.out
dist/
4 changes: 4 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ builds:
- linux
- windows
- darwin
ldflags:
- -w
- -s
- -X github.com/linuxsuren/api-testing/cmd.version={{.Version}}
archives:
- name_template: "{{ .Binary }}-{{ .Os }}-{{ .Arch }}"
format_overrides:
Expand Down
16 changes: 1 addition & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,6 @@ LABEL "maintainer"="Rick <linuxsuren@gmail.com>"

LABEL "Name"="API testing"

ENV LC_ALL C.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8

RUN apk add --no-cache \
git \
openssh-client \
libc6-compat \
libstdc++

COPY entrypoint.sh /entrypoint.sh
COPY --from=builder /workspace/atest /usr/bin/atest
COPY --from=hd /usr/local/bin/hd /usr/local/bin/hd
RUN hd i kubernetes-sigs/kubectl && \
hd i k3d

ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT [atest, server]
19 changes: 18 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,26 @@ build:
mkdir -p bin
rm -rf bin/atest
go build -o bin/atest main.go

goreleaser:
goreleaser build --rm-dist --snapshot
build-image:
docker build -t ghcr.io/linuxsuren/api-testing:dev .
copy: build
sudo cp bin/atest /usr/local/bin/
test:
go test ./... -cover -v -coverprofile=coverage.out
go tool cover -func=coverage.out
grpc:
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pkg/server/server.proto
grpc-js:
protoc -I=pkg/server server.proto \
--js_out=import_style=commonjs:bin \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext:bin
grpc-java:
protoc --plugin=protoc-gen-grpc-java=/usr/local/bin/protoc-gen-grpc-java \
--grpc-java_out=bin --proto_path=pkg/server server.proto
install-tool:
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
7 changes: 6 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package cmd

import "github.com/spf13/cobra"

// should be injected during the build process
var version string

// NewRootCmd creates the root command
func NewRootCmd() (c *cobra.Command) {
c = &cobra.Command{
Use: "atest",
Short: "API testing tool",
}
c.Version = version
c.AddCommand(createInitCommand(),
createRunCommand(), createSampleCmd())
createRunCommand(), createSampleCmd(),
createServerCmd())
return
}
4 changes: 4 additions & 0 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ func TestCreateRunCommand(t *testing.T) {

init := createInitCommand()
assert.Equal(t, "init", init.Use)

server := createServerCmd()
assert.NotNil(t, server)
assert.Equal(t, "server", server.Use)
}
25 changes: 18 additions & 7 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type runOption struct {
reporter runner.TestReporter
reportWriter runner.ReportResultWriter
report string
reportIgnore bool
}

func newDefaultRunOption() *runOption {
Expand Down Expand Up @@ -71,14 +72,22 @@ See also https://github.com/LinuxSuRen/api-testing/tree/master/sample`,
flags.Int64VarP(&opt.thread, "thread", "", 1, "Threads of the execution")
flags.Int32VarP(&opt.qps, "qps", "", 5, "QPS")
flags.Int32VarP(&opt.burst, "burst", "", 5, "burst")
flags.StringVarP(&opt.report, "report", "", "", "The type of target report")
flags.StringVarP(&opt.report, "report", "", "", "The type of target report. Supported: markdown, md, discard, std")
return
}

func (o *runOption) preRunE(cmd *cobra.Command, args []string) (err error) {
writer := cmd.OutOrStdout()

switch o.report {
case "markdown", "md":
o.reportWriter = runner.NewMarkdownResultWriter(cmd.OutOrStdout())
o.reportWriter = runner.NewMarkdownResultWriter(writer)
case "discard":
o.reportWriter = runner.NewDiscardResultWriter()
case "", "std":
o.reportWriter = runner.NewResultWriter(writer)
default:
err = fmt.Errorf("not supported report type: '%s'", o.report)
}
return
}
Expand All @@ -97,17 +106,18 @@ func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
for i := range files {
item := files[i]
if err = o.runSuiteWithDuration(item); err != nil {
return
break
}
}
}

// print the report
if err == nil {
var results []runner.ReportResult
if results, err = o.reporter.ExportAllReportResults(); err == nil {
err = o.reportWriter.Output(results)
if results, reportErr := o.reporter.ExportAllReportResults(); reportErr == nil {
if reportErr = o.reportWriter.Output(results); reportErr != nil {
cmd.Println("failed to Output all reports", reportErr)
}
} else {
cmd.Println("failed to export all reports", reportErr)
}
return
}
Expand Down Expand Up @@ -205,6 +215,7 @@ func (o *runOption) runSuite(suite string, dataContext map[string]interface{}, c
simpleRunner := runner.NewSimpleTestCaseRunner()
simpleRunner.WithTestReporter(o.reporter)
if output, err = simpleRunner.RunTestCase(&testCase, dataContext, ctxWithTimeout); err != nil && !o.requestIgnoreError {
err = fmt.Errorf("failed to run '%s', %v", testCase.Name, err)
return
} else {
err = nil
Expand Down
69 changes: 69 additions & 0 deletions cmd/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,72 @@ func TestRootCmd(t *testing.T) {
assert.NotNil(t, c)
assert.Equal(t, "atest", c.Use)
}

func TestPreRunE(t *testing.T) {
tests := []struct {
name string
opt *runOption
verify func(*testing.T, *runOption, error)
}{{
name: "markdown report",
opt: &runOption{
report: "markdown",
},
verify: func(t *testing.T, ro *runOption, err error) {
assert.Nil(t, err)
assert.NotNil(t, ro.reportWriter)
},
}, {
name: "md report",
opt: &runOption{
report: "md",
},
verify: func(t *testing.T, ro *runOption, err error) {
assert.Nil(t, err)
assert.NotNil(t, ro.reportWriter)
},
}, {
name: "discard report",
opt: &runOption{
report: "discard",
},
verify: func(t *testing.T, ro *runOption, err error) {
assert.Nil(t, err)
assert.NotNil(t, ro.reportWriter)
},
}, {
name: "std report",
opt: &runOption{
report: "std",
},
verify: func(t *testing.T, ro *runOption, err error) {
assert.Nil(t, err)
assert.NotNil(t, ro.reportWriter)
},
}, {
name: "empty report",
opt: &runOption{
report: "",
},
verify: func(t *testing.T, ro *runOption, err error) {
assert.Nil(t, err)
assert.NotNil(t, ro.reportWriter)
},
}, {
name: "invalid report",
opt: &runOption{
report: "fake",
},
verify: func(t *testing.T, ro *runOption, err error) {
assert.NotNil(t, err)
assert.Nil(t, ro.reportWriter)
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &cobra.Command{}
err := tt.opt.preRunE(c, nil)
tt.verify(t, tt.opt, err)
})
}
}
51 changes: 51 additions & 0 deletions cmd/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Package cmd provides all the commands
package cmd

import (
"fmt"
"log"
"net"

"github.com/linuxsuren/api-testing/pkg/server"
"github.com/spf13/cobra"
"google.golang.org/grpc"
)

func createServerCmd() (c *cobra.Command) {
opt := &serverOption{}
c = &cobra.Command{
Use: "server",
Short: "Run as a server mode",
RunE: opt.runE,
}
flags := c.Flags()
flags.IntVarP(&opt.port, "port", "p", 9090, "The RPC server port")
flags.BoolVarP(&opt.printProto, "print-proto", "", false, "Print the proto content and exit")
return
}

type serverOption struct {
port int
printProto bool
}

func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
if o.printProto {
for _, val := range server.GetProtos() {
cmd.Println(val)
}
return
}

var lis net.Listener
lis, err = net.Listen("tcp", fmt.Sprintf(":%d", o.port))
if err != nil {
return
}

s := grpc.NewServer()
server.RegisterRunnerServer(s, server.NewRemoteServer())
log.Printf("server listening at %v", lis.Addr())
s.Serve(lis)
return
}
40 changes: 40 additions & 0 deletions cmd/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cmd

import (
"bytes"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

func TestPrintProto(t *testing.T) {
tests := []struct {
name string
args []string
verify func(*testing.T, *bytes.Buffer, error)
}{{
name: "print ptoto only",
args: []string{"server", "--print-proto"},
verify: func(t *testing.T, buf *bytes.Buffer, err error) {
assert.Nil(t, err)
assert.True(t, strings.HasPrefix(buf.String(), `syntax = "proto3";`))
},
}, {
name: "invalid port",
args: []string{"server", "-p=-1"},
verify: func(t *testing.T, buf *bytes.Buffer, err error) {
assert.NotNil(t, err)
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
buf := new(bytes.Buffer)
root := NewRootCmd()
root.SetOut(buf)
root.SetArgs(tt.args)
err := root.Execute()
tt.verify(t, buf, err)
})
}
}
7 changes: 0 additions & 7 deletions entrypoint.sh

This file was deleted.

Loading