feat: support add multiple stores (#147)

This commit is contained in:
Rick 2023-07-29 22:14:58 +08:00 committed by GitHub
parent 470ef8e337
commit 8d459a9eed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 2926 additions and 1550 deletions

3
.gitpod.yml Normal file
View File

@ -0,0 +1,3 @@
tasks:
- init: make build
command: docker run --pull always --network host ghcr.io/linuxsuren/api-testing:master

View File

@ -52,13 +52,11 @@ install-precheck:
cp .github/pre-commit .git/hooks/pre-commit cp .github/pre-commit .git/hooks/pre-commit
grpc: grpc:
protoc --go_out=. --go_opt=paths=source_relative \ protoc --proto_path=. \
--go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \
pkg/server/server.proto pkg/server/server.proto \
pkg/testing/remote/loader.proto
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pkg/testing/remote/loader.proto
grpc-gw: grpc-gw:
protoc -I . --grpc-gateway_out . \ protoc -I . --grpc-gateway_out . \
--grpc-gateway_opt logtostderr=true \ --grpc-gateway_opt logtostderr=true \

View File

@ -20,7 +20,7 @@ func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer,
c.Version = version.GetVersion() c.Version = version.GetVersion()
c.AddCommand(createInitCommand(execer), c.AddCommand(createInitCommand(execer),
createRunCommand(), createSampleCmd(), createRunCommand(), createSampleCmd(),
createServerCmd(gRPCServer, httpServer), createJSONSchemaCmd(), createServerCmd(execer, gRPCServer, httpServer), createJSONSchemaCmd(),
createServiceCommand(execer), createFunctionCmd()) createServiceCommand(execer), createFunctionCmd())
return return
} }

View File

@ -10,17 +10,19 @@ import (
) )
func TestCreateRunCommand(t *testing.T) { func TestCreateRunCommand(t *testing.T) {
execer := fakeruntime.FakeExecer{}
cmd := createRunCommand() cmd := createRunCommand()
assert.Equal(t, "run", cmd.Use) assert.Equal(t, "run", cmd.Use)
init := createInitCommand(fakeruntime.FakeExecer{}) init := createInitCommand(execer)
assert.Equal(t, "init", init.Use) assert.Equal(t, "init", init.Use)
s := createServerCmd(&fakeGRPCServer{}, server.NewFakeHTTPServer()) s := createServerCmd(execer, &fakeGRPCServer{}, server.NewFakeHTTPServer())
assert.NotNil(t, s) assert.NotNil(t, s)
assert.Equal(t, "server", s.Use) assert.Equal(t, "server", s.Use)
root := NewRootCmd(fakeruntime.FakeExecer{}, NewFakeGRPCServer(), server.NewFakeHTTPServer()) root := NewRootCmd(execer, NewFakeGRPCServer(), server.NewFakeHTTPServer())
root.SetArgs([]string{"init", "-k=demo.yaml", "--wait-namespace", "demo", "--wait-resource", "demo"}) root.SetArgs([]string{"init", "-k=demo.yaml", "--wait-namespace", "demo", "--wait-resource", "demo"})
err := root.Execute() err := root.Execute()
assert.Nil(t, err) assert.Nil(t, err)

View File

@ -3,11 +3,11 @@ package cmd
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"log" "log"
"net" "net"
"net/http" "net/http"
"os"
"path" "path"
"strings" "strings"
"time" "time"
@ -19,43 +19,51 @@ import (
"github.com/linuxsuren/api-testing/pkg/testing" "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/linuxsuren/api-testing/pkg/testing/remote" "github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/linuxsuren/api-testing/pkg/util" "github.com/linuxsuren/api-testing/pkg/util"
fakeruntime "github.com/linuxsuren/go-fake-runtime"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/reflection" "google.golang.org/grpc/reflection"
) )
func createServerCmd(gRPCServer gRPCServer, httpServer server.HTTPServer) (c *cobra.Command) { func createServerCmd(execer fakeruntime.Execer, gRPCServer gRPCServer, httpServer server.HTTPServer) (c *cobra.Command) {
opt := &serverOption{ opt := &serverOption{
gRPCServer: gRPCServer, gRPCServer: gRPCServer,
httpServer: httpServer, httpServer: httpServer,
execer: execer,
} }
c = &cobra.Command{ c = &cobra.Command{
Use: "server", Use: "server",
Short: "Run as a server mode", Short: "Run as a server mode",
RunE: opt.runE, PreRunE: opt.preRunE,
RunE: opt.runE,
} }
flags := c.Flags() flags := c.Flags()
flags.IntVarP(&opt.port, "port", "p", 7070, "The RPC server port") flags.IntVarP(&opt.port, "port", "p", 7070, "The RPC server port")
flags.IntVarP(&opt.httpPort, "http-port", "", 8080, "The HTTP server port") flags.IntVarP(&opt.httpPort, "http-port", "", 8080, "The HTTP server port")
flags.BoolVarP(&opt.printProto, "print-proto", "", false, "Print the proto content and exit") flags.BoolVarP(&opt.printProto, "print-proto", "", false, "Print the proto content and exit")
flags.StringVarP(&opt.storage, "storage", "", "local", "The storage type, local or etcd")
flags.StringArrayVarP(&opt.localStorage, "local-storage", "", []string{"*.yaml"}, "The local storage path") flags.StringArrayVarP(&opt.localStorage, "local-storage", "", []string{"*.yaml"}, "The local storage path")
flags.StringVarP(&opt.grpcStorage, "grpc-storage", "", "", "The grpc storage address")
flags.StringVarP(&opt.consolePath, "console-path", "", "", "The path of the console") flags.StringVarP(&opt.consolePath, "console-path", "", "", "The path of the console")
flags.StringVarP(&opt.configDir, "config-dir", "", "$HOME/.config/atest", "The config directory")
return return
} }
type serverOption struct { type serverOption struct {
gRPCServer gRPCServer gRPCServer gRPCServer
httpServer server.HTTPServer httpServer server.HTTPServer
execer fakeruntime.Execer
port int port int
httpPort int httpPort int
printProto bool printProto bool
storage string
localStorage []string localStorage []string
grpcStorage string
consolePath string consolePath string
configDir string
}
func (o *serverOption) preRunE(cmd *cobra.Command, args []string) (err error) {
o.configDir = os.ExpandEnv(o.configDir)
err = o.execer.MkdirAll(o.configDir, 0755)
return
} }
func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) { func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
@ -79,30 +87,15 @@ func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
return return
} }
var loader testing.Writer loader := testing.NewFileWriter("")
switch o.storage { for _, storage := range o.localStorage {
case "local": if loadErr := loader.Put(storage); loadErr != nil {
loader = testing.NewFileWriter("") cmd.PrintErrf("failed to load %s, error: %v\n", storage, loadErr)
for _, storage := range o.localStorage { continue
if err = loader.Put(storage); err != nil {
break
}
} }
case "grpc":
if o.grpcStorage == "" {
err = errors.New("grpc storage address is required")
return
}
loader, err = remote.NewGRPCLoader(o.grpcStorage)
default:
err = errors.New("invalid storage type")
} }
if err != nil { removeServer := server.NewRemoteServer(loader, remote.NewGRPCloaderFromStore(), o.configDir)
return
}
removeServer := server.NewRemoteServer(loader)
s := o.gRPCServer s := o.gRPCServer
go func() { go func() {
if gRPCServer, ok := s.(reflection.GRPCServer); ok { if gRPCServer, ok := s.(reflection.GRPCServer); ok {
@ -113,13 +106,14 @@ func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
s.Serve(lis) s.Serve(lis)
}() }()
mux := runtime.NewServeMux() mux := runtime.NewServeMux(runtime.WithMetadata(server.MetadataStoreFunc)) // runtime.WithIncomingHeaderMatcher(func(key string) (s string, b bool) {
err = server.RegisterRunnerHandlerServer(cmd.Context(), mux, removeServer) err = server.RegisterRunnerHandlerServer(cmd.Context(), mux, removeServer)
if err == nil { if err == nil {
mux.HandlePath(http.MethodGet, "/", frontEndHandlerWithLocation(o.consolePath)) mux.HandlePath(http.MethodGet, "/", frontEndHandlerWithLocation(o.consolePath))
mux.HandlePath(http.MethodGet, "/assets/{asset}", frontEndHandlerWithLocation(o.consolePath)) mux.HandlePath(http.MethodGet, "/assets/{asset}", frontEndHandlerWithLocation(o.consolePath))
mux.HandlePath(http.MethodGet, "/healthz", frontEndHandlerWithLocation(o.consolePath)) mux.HandlePath(http.MethodGet, "/healthz", frontEndHandlerWithLocation(o.consolePath))
o.httpServer.WithHandler(mux) o.httpServer.WithHandler(mux)
log.Printf("HTTP server listening at %v", httplis.Addr())
err = o.httpServer.Serve(httplis) err = o.httpServer.Serve(httplis)
} }
return return

View File

@ -9,6 +9,7 @@ import (
_ "embed" _ "embed"
"github.com/linuxsuren/api-testing/cmd/service"
"github.com/linuxsuren/api-testing/pkg/version" "github.com/linuxsuren/api-testing/pkg/version"
fakeruntime "github.com/linuxsuren/go-fake-runtime" fakeruntime "github.com/linuxsuren/go-fake-runtime"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -272,26 +273,23 @@ type linuxService struct {
commonService commonService
} }
const systemCtl = "systemctl"
const serviceName = "atest"
func (s *linuxService) Start() (output string, err error) { func (s *linuxService) Start() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "start", serviceName) output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "start", service.ServiceName)
return return
} }
func (s *linuxService) Stop() (output string, err error) { func (s *linuxService) Stop() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "stop", serviceName) output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "stop", service.ServiceName)
return return
} }
func (s *linuxService) Restart() (output string, err error) { func (s *linuxService) Restart() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "restart", serviceName) output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "restart", service.ServiceName)
return return
} }
func (s *linuxService) Status() (output string, err error) { func (s *linuxService) Status() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "status", serviceName) output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "status", service.ServiceName)
if err != nil && err.Error() == "exit status 3" { if err != nil && err.Error() == "exit status 3" {
// this is normal case // this is normal case
err = nil err = nil
@ -301,13 +299,13 @@ func (s *linuxService) Status() (output string, err error) {
func (s *linuxService) Install() (output string, err error) { func (s *linuxService) Install() (output string, err error) {
if err = os.WriteFile(s.scriptPath, []byte(s.script), os.ModeAppend); err == nil { if err = os.WriteFile(s.scriptPath, []byte(s.script), os.ModeAppend); err == nil {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "enable", serviceName) output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "enable", service.ServiceName)
} }
return return
} }
func (s *linuxService) Uninstall() (output string, err error) { func (s *linuxService) Uninstall() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "disable", serviceName) output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "disable", service.ServiceName)
return return
} }
@ -324,7 +322,7 @@ type containerService struct {
const defaultImage = "ghcr.io/linuxsuren/api-testing" const defaultImage = "ghcr.io/linuxsuren/api-testing"
func newContainerService(execer fakeruntime.Execer, client, image, tag, localStorage string, writer io.Writer) (service Service) { func newContainerService(execer fakeruntime.Execer, client, image, tag, localStorage string, writer io.Writer) (svc Service) {
if tag == "" { if tag == "" {
tag = "latest" tag = "latest"
} }
@ -335,7 +333,7 @@ func newContainerService(execer fakeruntime.Execer, client, image, tag, localSto
containerServer := &containerService{ containerServer := &containerService{
Execer: execer, Execer: execer,
client: client, client: client,
name: serviceName, name: service.ServiceName,
image: image, image: image,
tag: tag, tag: tag,
localStorage: localStorage, localStorage: localStorage,
@ -344,11 +342,11 @@ func newContainerService(execer fakeruntime.Execer, client, image, tag, localSto
} }
if strings.HasSuffix(client, ServiceModePodman.String()) { if strings.HasSuffix(client, ServiceModePodman.String()) {
service = &podmanService{ svc = &podmanService{
containerService: containerServer, containerService: containerServer,
} }
} else { } else {
service = containerServer svc = containerServer
} }
return return
} }
@ -426,14 +424,19 @@ func (s *podmanService) Start() (output string, err error) {
return return
} }
func (s *podmanService) Stop() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "stop", service.PodmanServiceName)
return
}
func (s *podmanService) installService() (output string, err error) { func (s *podmanService) installService() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(s.client, "", "generate", "systemd", "--new", "--files", "--name", s.name) output, err = s.Execer.RunCommandAndReturn(s.client, "", "generate", "systemd", "--new", "--files", "--name", s.name)
if err == nil { if err == nil {
var result string var result string
result, err = s.Execer.RunCommandAndReturn("mv", "", "container-atest.service", "/etc/systemd/system") result, err = s.Execer.RunCommandAndReturn("mv", "", service.PodmanServiceName, "/etc/systemd/system")
if err == nil { if err == nil {
output = fmt.Sprintf("%s\n%s", output, result) output = fmt.Sprintf("%s\n%s", output, result)
if result, err = s.Execer.RunCommandAndReturn("systemctl", "", "enable", "container-atest.service"); err == nil { if result, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "enable", service.PodmanServiceName); err == nil {
output = fmt.Sprintf("%s\n%s", output, result) output = fmt.Sprintf("%s\n%s", output, result)
} }
} }
@ -453,6 +456,6 @@ func (s *podmanService) Uninstall() (output string, err error) {
} }
func (s *podmanService) uninstallService() (output string, err error) { func (s *podmanService) uninstallService() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn("systemctl", "", "disable", "container-atest.service") output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "disable", service.PodmanServiceName)
return return
} }

9
cmd/service/constant.go Normal file
View File

@ -0,0 +1,9 @@
package service
const (
// PodmanServiceName is the service name of podman service
PodmanServiceName = "container-atest.service"
SystemCtl = "systemctl"
ServiceName = "atest"
)

View File

@ -155,6 +155,12 @@ func TestService(t *testing.T) {
targetOS: fakeruntime.OSLinux, targetOS: fakeruntime.OSLinux,
mode: ServiceModePodman.String(), mode: ServiceModePodman.String(),
expectOutput: "", expectOutput: "",
}, {
name: "stop in podman",
action: "stop",
targetOS: fakeruntime.OSLinux,
mode: ServiceModePodman.String(),
expectOutput: "",
}} }}
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {

View File

@ -4,6 +4,7 @@
console.log(Cypress.browser) console.log(Cypress.browser)
describe('Suite Manage', () => { describe('Suite Manage', () => {
const suiteName = userID_Alpha() const suiteName = userID_Alpha()
const store = "local"
const sampleAPIAddress = "http://foo" const sampleAPIAddress = "http://foo"
console.log(sampleAPIAddress) console.log(sampleAPIAddress)
@ -13,6 +14,11 @@ describe('Suite Manage', () => {
cy.get('[test-id="open-new-suite-dialog"]').click() cy.get('[test-id="open-new-suite-dialog"]').click()
const storeSelect = cy.get('[test-id=suite-form-store] input')
storeSelect.click()
storeSelect.type(store)
storeSelect.trigger('keydown', {key: 'Enter'})
cy.get('[test-id=suite-form-name]').should('be.visible').type(suiteName) cy.get('[test-id=suite-form-name]').should('be.visible').type(suiteName)
cy.get('[test-id=suite-form-api]').should('be.visible').type(sampleAPIAddress) cy.get('[test-id=suite-form-api]').should('be.visible').type(sampleAPIAddress)
cy.get('[test-id=suite-form-submit]').should('be.visible').click() cy.get('[test-id=suite-form-submit]').should('be.visible').click()

View File

@ -4,25 +4,32 @@ import TestSuite from './views/TestSuite.vue'
import TemplateFunctions from './views/TemplateFunctions.vue' import TemplateFunctions from './views/TemplateFunctions.vue'
import { reactive, ref, watch } from 'vue' import { reactive, ref, watch } from 'vue'
import { ElTree } from 'element-plus' import { ElTree } from 'element-plus'
import type { FormInstance } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { Edit } from '@element-plus/icons-vue' import { Edit } from '@element-plus/icons-vue'
import type { Suite } from './types'
interface Tree { interface Tree {
id: string id: string
label: string label: string
parent: string parent: string
store: string
children?: Tree[] children?: Tree[]
} }
const testCaseName = ref('') const testCaseName = ref('')
const testSuite = ref('') const testSuite = ref('')
const store = ref('')
const handleNodeClick = (data: Tree) => { const handleNodeClick = (data: Tree) => {
if (data.children) { if (data.children) {
viewName.value = 'testsuite' viewName.value = 'testsuite'
testSuite.value = data.label testSuite.value = data.label
store.value = data.store
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': data.store
},
body: JSON.stringify({ body: JSON.stringify({
name: data.label name: data.label
}) })
@ -36,6 +43,7 @@ const handleNodeClick = (data: Tree) => {
data.children?.push({ data.children?.push({
id: data.label + item.name, id: data.label + item.name,
label: item.name, label: item.name,
store: data.store,
parent: data.label parent: data.label
} as Tree) } as Tree)
}) })
@ -44,6 +52,7 @@ const handleNodeClick = (data: Tree) => {
} else { } else {
testCaseName.value = data.label testCaseName.value = data.label
testSuite.value = data.parent testSuite.value = data.parent
store.value = data.store
viewName.value = 'testcase' viewName.value = 'testcase'
} }
} }
@ -52,14 +61,16 @@ const data = ref([] as Tree[])
const treeRef = ref<InstanceType<typeof ElTree>>() const treeRef = ref<InstanceType<typeof ElTree>>()
const currentNodekey = ref('') const currentNodekey = ref('')
function loadTestSuites() { function loadTestSuites(store: string) {
const requestOptions = { const requestOptions = {
method: 'POST' method: 'POST',
headers: {
'X-Store-Name': store
},
} }
fetch('/server.Runner/GetSuites', requestOptions) fetch('/server.Runner/GetSuites', requestOptions)
.then((response) => response.json()) .then((response) => response.json())
.then((d) => { .then((d) => {
data.value = [] as Tree[]
if (!d.data) { if (!d.data) {
return return
} }
@ -67,6 +78,7 @@ function loadTestSuites() {
let suite = { let suite = {
id: k, id: k,
label: k, label: k,
store: store,
children: [] as Tree[] children: [] as Tree[]
} as Tree } as Tree
@ -74,6 +86,7 @@ function loadTestSuites() {
suite.children?.push({ suite.children?.push({
id: k + item, id: k + item,
label: item, label: item,
store: store,
parent: k parent: k
} as Tree) } as Tree)
}) })
@ -95,40 +108,76 @@ function loadTestSuites() {
} }
}) })
} }
loadTestSuites()
interface Store {
name: string,
description: string,
}
const stores = ref([] as Store[])
function loadStores() {
const requestOptions = {
method: 'POST',
}
fetch('/server.Runner/GetStores', requestOptions)
.then((response) => response.json())
.then((d) => {
stores.value = d.data
data.value = [] as Tree[]
d.data.forEach((item: any) => {
loadTestSuites(item.name)
})
})
}
loadStores()
const dialogVisible = ref(false) const dialogVisible = ref(false)
const suiteCreatingLoading = ref(false) const suiteCreatingLoading = ref(false)
const suiteFormRef = ref<FormInstance>() const suiteFormRef = ref<FormInstance>()
const testSuiteForm = reactive({ const testSuiteForm = reactive({
name: '', name: '',
api: '' api: '',
store: ''
}) })
function openTestSuiteCreateDialog() { function openTestSuiteCreateDialog() {
dialogVisible.value = true dialogVisible.value = true
} }
const submitForm = (formEl: FormInstance | undefined) => { const rules = reactive<FormRules<Suite>>({
name: [{ required: true, message: 'Name is required', trigger: 'blur' }],
store: [{ required: true, message: 'Location is required', trigger: 'blur' }]
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
suiteCreatingLoading.value = true console.log(formEl)
await formEl.validate((valid: boolean, fields) => {
console.log(valid, fields)
if (valid) {
suiteCreatingLoading.value = true
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
body: JSON.stringify({ headers: {
name: testSuiteForm.name, 'X-Store-Name': testSuiteForm.store
api: testSuiteForm.api },
}) body: JSON.stringify({
} name: testSuiteForm.name,
api: testSuiteForm.api
})
}
fetch('/server.Runner/CreateTestSuite', requestOptions) fetch('/server.Runner/CreateTestSuite', requestOptions)
.then((response) => response.json()) .then((response) => response.json())
.then(() => { .then(() => {
suiteCreatingLoading.value = false suiteCreatingLoading.value = false
loadTestSuites() loadStores()
}) dialogVisible.value = false
formEl.resetFields()
dialogVisible.value = false })
}
})
} }
const filterText = ref('') const filterText = ref('')
@ -166,14 +215,16 @@ const viewName = ref('testcase')
<el-main> <el-main>
<TestCase <TestCase
v-if="viewName === 'testcase'" v-if="viewName === 'testcase'"
:store="store"
:suite="testSuite" :suite="testSuite"
:name="testCaseName" :name="testCaseName"
@updated="loadTestSuites" @updated="loadStores"
/> />
<TestSuite <TestSuite
v-else-if="viewName === 'testsuite'" v-else-if="viewName === 'testsuite'"
:name="testSuite" :name="testSuite"
@updated="loadTestSuites" :store="store"
@updated="loadStores"
/> />
</el-main> </el-main>
</el-container> </el-container>
@ -182,7 +233,25 @@ const viewName = ref('testcase')
<el-dialog v-model="dialogVisible" title="Create Test Suite" width="30%" draggable> <el-dialog v-model="dialogVisible" title="Create Test Suite" width="30%" draggable>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-form ref="suiteFormRef" status-icon label-width="120px" class="demo-ruleForm"> <el-form
:rules="rules"
:model="testSuiteForm"
ref="suiteFormRef"
status-icon label-width="120px">
<el-form-item label="Location" prop="store">
<el-select v-model="testSuiteForm.store" class="m-2"
test-id="suite-form-store"
filterable=true
default-first-option=true
placeholder="Storage Location" size="middle">
<el-option
v-for="item in stores"
:key="item.name"
:label="item.name"
:value="item.name"
/>
</el-select>
</el-form-item>
<el-form-item label="Name" prop="name"> <el-form-item label="Name" prop="name">
<el-input v-model="testSuiteForm.name" test-id="suite-form-name" /> <el-input v-model="testSuiteForm.name" test-id="suite-form-name" />
</el-form-item> </el-form-item>

View File

@ -9,7 +9,8 @@ import { NewSuggestedAPIsQuery, CreateFilter, GetHTTPMethods, FlattenObject } fr
const props = defineProps({ const props = defineProps({
name: String, name: String,
suite: String suite: String,
store: String
}) })
const emit = defineEmits(['updated']) const emit = defineEmits(['updated'])
@ -23,6 +24,9 @@ function sendRequest() {
const suite = props.suite const suite = props.suite
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify({ body: JSON.stringify({
suite: suite, suite: suite,
testcase: name testcase: name
@ -114,6 +118,9 @@ function load() {
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify({ body: JSON.stringify({
suite: suite, suite: suite,
testcase: name testcase: name
@ -198,6 +205,9 @@ function saveTestCase() {
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify(testCaseWithSuite.value) body: JSON.stringify(testCaseWithSuite.value)
} }
fetch('/server.Runner/UpdateTestCase', requestOptions).then((e) => { fetch('/server.Runner/UpdateTestCase', requestOptions).then((e) => {
@ -218,6 +228,9 @@ function deleteTestCase() {
const suite = props.suite const suite = props.suite
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify({ body: JSON.stringify({
suite: suite, suite: suite,
testcase: name testcase: name
@ -336,7 +349,10 @@ function insertOrUpdateIntoMap(pair: Pair, pairs: Pair[]) {
const pupularHeaders = ref([] as Pair[]) const pupularHeaders = ref([] as Pair[])
const requestOptions = { const requestOptions = {
method: 'POST' method: 'POST',
headers: {
'X-Store-Name': props.store
},
} }
fetch('/server.Runner/PopularHeaders', requestOptions) fetch('/server.Runner/PopularHeaders', requestOptions)
.then((response) => response.json()) .then((response) => response.json())

View File

@ -7,7 +7,8 @@ import type { Suite, TestCase, Pair } from './types'
import { NewSuggestedAPIsQuery } from './types' import { NewSuggestedAPIsQuery } from './types'
const props = defineProps({ const props = defineProps({
name: String name: String,
store: String,
}) })
const emit = defineEmits(['updated']) const emit = defineEmits(['updated'])
let querySuggestedAPIs = NewSuggestedAPIsQuery(props.name!) let querySuggestedAPIs = NewSuggestedAPIsQuery(props.name!)
@ -24,6 +25,9 @@ const suite = ref({
function load() { function load() {
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify({ body: JSON.stringify({
name: props.name name: props.name
}) })
@ -51,6 +55,9 @@ watch(props, () => {
function save() { function save() {
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify(suite.value) body: JSON.stringify(suite.value)
} }
fetch('/server.Runner/UpdateTestSuite', requestOptions) fetch('/server.Runner/UpdateTestSuite', requestOptions)
@ -91,6 +98,9 @@ const submitForm = async (formEl: FormInstance | undefined) => {
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify({ body: JSON.stringify({
suiteName: props.name, suiteName: props.name,
data: { data: {
@ -118,6 +128,9 @@ const submitForm = async (formEl: FormInstance | undefined) => {
function del() { function del() {
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {
'X-Store-Name': props.store
},
body: JSON.stringify({ body: JSON.stringify({
name: props.name name: props.name
}) })
@ -214,7 +227,6 @@ function paramChange() {
ref="testcaseFormRef" ref="testcaseFormRef"
status-icon status-icon
label-width="60px" label-width="60px"
class="demo-ruleForm"
> >
<el-form-item label="Name" prop="name"> <el-form-item label="Name" prop="name">
<el-input v-model="testCaseForm.name" test-id="case-form-name"/> <el-input v-model="testCaseForm.name" test-id="case-form-name"/>

View File

@ -74,16 +74,29 @@ tiup playground --db.host 0.0.0.0
``` ```
```shell ```shell
# create a network # create a config file
# start the server with gRPC storage mkdir bin
podman run -p 8080:8080 ghcr.io/linuxsuren/api-testing:master \ echo "- name: db
atest server --storage grpc --grpc-storage 192.168.1.98:7071 --console-path=/var/www/html kind:
# start the gRPC storage which connect to an ORM database name: database
podman run -p 7071:7071 ghcr.io/linuxsuren/api-testing:master \ url: localhost:7071
atest-store-orm --address 192.168.1.98:4000 --user root --database test url: localhost:4000
``` username: root
properties:
database: test" > bin/stores.yaml
> Please don't forget to replace `192.168.1.98` to your own IP address. # start the server with gRPC storage
podman run -p 8080:8080 -v bin:var/data/atest \
--network host \
ghcr.io/linuxsuren/api-testing:master \
atest server --console-path=/var/www/html \
--config-dir=/var/data/atest
# start the gRPC storage which ready to connect to an ORM database
podman run -p 7071:7071 \
--network host \
ghcr.io/linuxsuren/api-testing:master atest-store-orm
```
## Extensions ## Extensions
Developers could have a storage extension. Implement a gRPC server according to [loader.proto](../pkg/testing/remote/loader.proto) is required. Developers could have a storage extension. Implement a gRPC server according to [loader.proto](../pkg/testing/remote/loader.proto) is required.

View File

@ -2,11 +2,13 @@ package main
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"net" "net"
"os" "os"
"github.com/linuxsuren/api-testing/extensions/store-orm/pkg" "github.com/linuxsuren/api-testing/extensions/store-orm/pkg"
"github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing/remote" "github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -23,9 +25,6 @@ func main() {
RunE: opt.runE, RunE: opt.runE,
} }
flags := cmd.Flags() flags := cmd.Flags()
flags.StringVarP(&opt.user, "user", "u", "root", "The user name of database")
flags.StringVarP(&opt.address, "address", "", "127.0.0.1:4000", "The address of database")
flags.StringVarP(&opt.database, "database", "", "test", "The database name")
flags.IntVarP(&opt.port, "port", "p", 7071, "The port of gRPC server") flags.IntVarP(&opt.port, "port", "p", 7071, "The port of gRPC server")
if err := cmd.Execute(); err != nil { if err := cmd.Execute(); err != nil {
os.Exit(1) os.Exit(1)
@ -34,7 +33,7 @@ func main() {
func (o *option) runE(cmd *cobra.Command, args []string) (err error) { func (o *option) runE(cmd *cobra.Command, args []string) (err error) {
var removeServer remote.LoaderServer var removeServer remote.LoaderServer
if removeServer, err = NewRemoteServer(o.user, o.address, o.database); err != nil { if removeServer, err = NewRemoteServer(); err != nil {
return return
} }
@ -51,30 +50,27 @@ func (o *option) runE(cmd *cobra.Command, args []string) (err error) {
} }
type option struct { type option struct {
user, address, database string port int
port int
} }
type server struct { type dbserver struct {
remote.UnimplementedLoaderServer remote.UnimplementedLoaderServer
db *gorm.DB
} }
// NewRemoteServer creates a remote server instance // NewRemoteServer creates a remote server instance
func NewRemoteServer(user, address, database string) (s remote.LoaderServer, err error) { func NewRemoteServer() (s remote.LoaderServer, err error) {
var db *gorm.DB s = &dbserver{}
if db, err = createDB(user, address, database); err == nil {
s = &server{db: db}
}
return return
} }
func createDB(user, address, database string) (db *gorm.DB, err error) { func createDB(user, address, database string) (db *gorm.DB, err error) {
dsn := fmt.Sprintf("%s:@tcp(%s)/%s?charset=utf8mb4", user, address, database) dsn := fmt.Sprintf("%s:@tcp(%s)/%s?charset=utf8mb4", user, address, database)
fmt.Println("try to connect to", dsn)
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{ db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info), Logger: logger.Default.LogMode(logger.Info),
}) })
if err != nil { if err != nil {
err = fmt.Errorf("failed to connect to %s, %v", dsn, err)
return return
} }
@ -83,10 +79,40 @@ func createDB(user, address, database string) (db *gorm.DB, err error) {
return return
} }
func (s *server) ListTestSuite(context.Context, *remote.Empty) (suites *remote.TestSuites, err error) { var dbCache map[string]*gorm.DB = make(map[string]*gorm.DB)
items := make([]*pkg.TestSuite, 0)
s.db.Find(&items)
func (s *dbserver) getClient(ctx context.Context) (db *gorm.DB, err error) {
store := remote.GetStoreFromContext(ctx)
if store == nil {
err = errors.New("no connect to database")
} else {
var ok bool
if db, ok = dbCache[store.Name]; ok && db != nil {
return
}
database := "atest"
for key, val := range store.Properties {
if key == "database" {
database = val
}
}
db, err = createDB(store.Username, store.URL, database)
dbCache[store.Name] = db
}
return
}
func (s *dbserver) ListTestSuite(ctx context.Context, _ *server.Empty) (suites *remote.TestSuites, err error) {
items := make([]*pkg.TestSuite, 0)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&items)
suites = &remote.TestSuites{} suites = &remote.TestSuites{}
for i := range items { for i := range items {
suites.Data = append(suites.Data, pkg.ConvertToGRPCTestSuite(items[i])) suites.Data = append(suites.Data, pkg.ConvertToGRPCTestSuite(items[i]))
@ -94,21 +120,31 @@ func (s *server) ListTestSuite(context.Context, *remote.Empty) (suites *remote.T
return return
} }
func (s *server) CreateTestSuite(ctx context.Context, testSuite *remote.TestSuite) (reply *remote.Empty, err error) { func (s *dbserver) CreateTestSuite(ctx context.Context, testSuite *remote.TestSuite) (reply *server.Empty, err error) {
reply = &remote.Empty{} reply = &server.Empty{}
s.db.Create(pkg.ConvertToDBTestSuite(testSuite)) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Create(pkg.ConvertToDBTestSuite(testSuite))
return return
} }
const nameQuery = `name = ?` const nameQuery = `name = ?`
func (s *server) GetTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) { func (s *dbserver) GetTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) {
query := &pkg.TestSuite{} query := &pkg.TestSuite{}
s.db.Find(&query, nameQuery, suite.Name) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&query, nameQuery, suite.Name)
reply = pkg.ConvertToGRPCTestSuite(query) reply = pkg.ConvertToGRPCTestSuite(query)
if suite.Full { if suite.Full {
var testcases *remote.TestCases var testcases *server.TestCases
if testcases, err = s.ListTestCases(ctx, &remote.TestSuite{ if testcases, err = s.ListTestCases(ctx, &remote.TestSuite{
Name: suite.Name, Name: suite.Name,
}); err == nil && testcases != nil { }); err == nil && testcases != nil {
@ -118,9 +154,15 @@ func (s *server) GetTestSuite(ctx context.Context, suite *remote.TestSuite) (rep
return return
} }
func (s *server) UpdateTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) { func (s *dbserver) UpdateTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) {
reply = &remote.TestSuite{}
input := pkg.ConvertToDBTestSuite(suite) input := pkg.ConvertToDBTestSuite(suite)
testSuiteIdentity(s.db, input).Updates(input) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testSuiteIdentity(db, input).Updates(input)
return return
} }
@ -128,41 +170,63 @@ func testSuiteIdentity(db *gorm.DB, suite *pkg.TestSuite) *gorm.DB {
return db.Model(suite).Where(nameQuery, suite.Name) return db.Model(suite).Where(nameQuery, suite.Name)
} }
func (s *server) DeleteTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.Empty, err error) { func (s *dbserver) DeleteTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *server.Empty, err error) {
reply = &remote.Empty{} reply = &server.Empty{}
s.db.Delete(suite, nameQuery, suite.Name) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Delete(suite, nameQuery, suite.Name)
return return
} }
func (s *server) ListTestCases(ctx context.Context, suite *remote.TestSuite) (result *remote.TestCases, err error) { func (s *dbserver) ListTestCases(ctx context.Context, suite *remote.TestSuite) (result *server.TestCases, err error) {
items := make([]*pkg.TestCase, 0) items := make([]*pkg.TestCase, 0)
s.db.Find(&items, "suite_name = ?", suite.Name) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&items, "suite_name = ?", suite.Name)
result = &remote.TestCases{} result = &server.TestCases{}
for i := range items { for i := range items {
result.Data = append(result.Data, pkg.ConvertToRemoteTestCase(items[i])) result.Data = append(result.Data, pkg.ConvertToRemoteTestCase(items[i]))
} }
return return
} }
func (s *server) CreateTestCase(ctx context.Context, testcase *remote.TestCase) (reply *remote.Empty, err error) { func (s *dbserver) CreateTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.Empty, err error) {
payload := pkg.ConverToDBTestCase(testcase) payload := pkg.ConverToDBTestCase(testcase)
s.db.Create(&payload) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
reply = &server.Empty{}
db.Create(&payload)
return return
} }
func (s *server) GetTestCase(ctx context.Context, testcase *remote.TestCase) (result *remote.TestCase, err error) { func (s *dbserver) GetTestCase(ctx context.Context, testcase *server.TestCase) (result *server.TestCase, err error) {
item := &pkg.TestCase{} item := &pkg.TestCase{}
s.db.Find(&item, "suite_name = ? AND name = ?", testcase.SuiteName, testcase.Name) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&item, "suite_name = ? AND name = ?", testcase.SuiteName, testcase.Name)
result = pkg.ConvertToRemoteTestCase(item) result = pkg.ConvertToRemoteTestCase(item)
return return
} }
func (s *server) UpdateTestCase(ctx context.Context, testcase *remote.TestCase) (reply *remote.TestCase, err error) { func (s *dbserver) UpdateTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.TestCase, err error) {
reply = &remote.TestCase{} reply = &server.TestCase{}
input := pkg.ConverToDBTestCase(testcase) input := pkg.ConverToDBTestCase(testcase)
testCaseIdentiy(s.db, input).Updates(input) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testCaseIdentiy(db, input).Updates(input)
data := make(map[string]interface{}) data := make(map[string]interface{})
if input.ExpectBody == "" { if input.ExpectBody == "" {
@ -173,15 +237,19 @@ func (s *server) UpdateTestCase(ctx context.Context, testcase *remote.TestCase)
} }
if len(data) > 0 { if len(data) > 0 {
testCaseIdentiy(s.db, input).Updates(data) testCaseIdentiy(db, input).Updates(data)
} }
return return
} }
func (s *server) DeleteTestCase(ctx context.Context, testcase *remote.TestCase) (reply *remote.Empty, err error) { func (s *dbserver) DeleteTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.Empty, err error) {
reply = &remote.Empty{} reply = &server.Empty{}
input := pkg.ConverToDBTestCase(testcase) input := pkg.ConverToDBTestCase(testcase)
testCaseIdentiy(s.db, input).Delete(input) var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testCaseIdentiy(db, input).Delete(input)
return return
} }

View File

@ -3,10 +3,11 @@ package pkg
import ( import (
"encoding/json" "encoding/json"
"github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing/remote" "github.com/linuxsuren/api-testing/pkg/testing/remote"
) )
func ConverToDBTestCase(testcase *remote.TestCase) (result *TestCase) { func ConverToDBTestCase(testcase *server.TestCase) (result *TestCase) {
result = &TestCase{ result = &TestCase{
Name: testcase.Name, Name: testcase.Name,
SuiteName: testcase.SuiteName, SuiteName: testcase.SuiteName,
@ -28,16 +29,16 @@ func ConverToDBTestCase(testcase *remote.TestCase) (result *TestCase) {
result.ExpectStatusCode = int(resp.StatusCode) result.ExpectStatusCode = int(resp.StatusCode)
result.ExpectHeader = pairToJSON(resp.Header) result.ExpectHeader = pairToJSON(resp.Header)
result.ExpectBodyFields = pairToJSON(resp.BodyFieldsExpect) result.ExpectBodyFields = pairToJSON(resp.BodyFieldsExpect)
result.ExpectVerify = sliceToJSON(resp.Verify) result.ExpectVerify = SliceToJSON(resp.Verify)
} }
return return
} }
func ConvertToRemoteTestCase(testcase *TestCase) (result *remote.TestCase) { func ConvertToRemoteTestCase(testcase *TestCase) (result *server.TestCase) {
result = &remote.TestCase{ result = &server.TestCase{
Name: testcase.Name, Name: testcase.Name,
Request: &remote.Request{ Request: &server.Request{
Api: testcase.API, Api: testcase.API,
Method: testcase.Method, Method: testcase.Method,
Body: testcase.Body, Body: testcase.Body,
@ -46,7 +47,7 @@ func ConvertToRemoteTestCase(testcase *TestCase) (result *remote.TestCase) {
Form: jsonToPair(testcase.Form), Form: jsonToPair(testcase.Form),
}, },
Response: &remote.Response{ Response: &server.Response{
StatusCode: int32(testcase.ExpectStatusCode), StatusCode: int32(testcase.ExpectStatusCode),
Body: testcase.ExpectBody, Body: testcase.ExpectBody,
Schema: testcase.ExpectSchema, Schema: testcase.ExpectSchema,
@ -67,6 +68,9 @@ func ConvertToDBTestSuite(suite *remote.TestSuite) (result *TestSuite) {
result.SpecKind = suite.Spec.Kind result.SpecKind = suite.Spec.Kind
result.SpecURL = suite.Spec.Url result.SpecURL = suite.Spec.Url
} }
if suite.Param != nil {
result.Param = pairToJSON(suite.Param)
}
return return
} }
@ -74,24 +78,30 @@ func ConvertToGRPCTestSuite(suite *TestSuite) (result *remote.TestSuite) {
result = &remote.TestSuite{ result = &remote.TestSuite{
Name: suite.Name, Name: suite.Name,
Api: suite.API, Api: suite.API,
Spec: &remote.APISpec{ Spec: &server.APISpec{
Kind: suite.SpecKind, Kind: suite.SpecKind,
Url: suite.SpecURL, Url: suite.SpecURL,
}, },
Param: jsonToPair(suite.Param),
} }
return return
} }
func sliceToJSON(slice []string) (result string) { func SliceToJSON(slice []string) (result string) {
var data []byte var data []byte
var err error var err error
if data, err = json.Marshal(slice); err == nil { if slice != nil {
result = string(data) if data, err = json.Marshal(slice); err == nil {
result = string(data)
}
}
if result == "" {
result = "[]"
} }
return return
} }
func pairToJSON(pair []*remote.Pair) (result string) { func pairToJSON(pair []*server.Pair) (result string) {
var obj = make(map[string]string) var obj = make(map[string]string)
for i := range pair { for i := range pair {
k := pair[i].Key k := pair[i].Key
@ -107,12 +117,12 @@ func pairToJSON(pair []*remote.Pair) (result string) {
return return
} }
func jsonToPair(jsonStr string) (pairs []*remote.Pair) { func jsonToPair(jsonStr string) (pairs []*server.Pair) {
pairMap := make(map[string]string, 0) pairMap := make(map[string]string, 0)
err := json.Unmarshal([]byte(jsonStr), &pairMap) err := json.Unmarshal([]byte(jsonStr), &pairMap)
if err == nil { if err == nil {
for k, v := range pairMap { for k, v := range pairMap {
pairs = append(pairs, &remote.Pair{ pairs = append(pairs, &server.Pair{
Key: k, Value: v, Key: k, Value: v,
}) })
} }

View File

@ -4,6 +4,7 @@ import (
"testing" "testing"
"github.com/linuxsuren/api-testing/extensions/store-orm/pkg" "github.com/linuxsuren/api-testing/extensions/store-orm/pkg"
"github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing/remote" "github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -25,9 +26,9 @@ func TestConvertToRemoteTestCase(t *testing.T) {
ExpectBodyFields: sampleJSONMap, ExpectBodyFields: sampleJSONMap,
ExpectVerify: `["one"]`, ExpectVerify: `["one"]`,
}) })
assert.Equal(t, &remote.TestCase{ assert.Equal(t, &server.TestCase{
Name: "name", Name: "name",
Request: &remote.Request{ Request: &server.Request{
Api: "api", Api: "api",
Method: "get", Method: "get",
Body: "body", Body: "body",
@ -35,7 +36,7 @@ func TestConvertToRemoteTestCase(t *testing.T) {
Header: samplePairs, Header: samplePairs,
Form: samplePairs, Form: samplePairs,
}, },
Response: &remote.Response{ Response: &server.Response{
StatusCode: 1, StatusCode: 1,
BodyFieldsExpect: samplePairs, BodyFieldsExpect: samplePairs,
Verify: []string{"one"}, Verify: []string{"one"},
@ -48,13 +49,13 @@ func TestConvertToRemoteTestCase(t *testing.T) {
func TestConverToDBTestCase(t *testing.T) { func TestConverToDBTestCase(t *testing.T) {
t.Run("without request and response", func(t *testing.T) { t.Run("without request and response", func(t *testing.T) {
result := pkg.ConverToDBTestCase(&remote.TestCase{}) result := pkg.ConverToDBTestCase(&server.TestCase{})
assert.Equal(t, &pkg.TestCase{}, result) assert.Equal(t, &pkg.TestCase{}, result)
}) })
t.Run("only have request", func(t *testing.T) { t.Run("only have request", func(t *testing.T) {
result := pkg.ConverToDBTestCase(&remote.TestCase{ result := pkg.ConverToDBTestCase(&server.TestCase{
Request: &remote.Request{ Request: &server.Request{
Api: "api", Api: "api",
Method: "get", Method: "get",
Body: "body", Body: "body",
@ -74,8 +75,8 @@ func TestConverToDBTestCase(t *testing.T) {
}) })
t.Run("only have response", func(t *testing.T) { t.Run("only have response", func(t *testing.T) {
result := pkg.ConverToDBTestCase(&remote.TestCase{ result := pkg.ConverToDBTestCase(&server.TestCase{
Response: &remote.Response{ Response: &server.Response{
StatusCode: 1, StatusCode: 1,
Body: "body", Body: "body",
Schema: "schema", Schema: "schema",
@ -98,12 +99,18 @@ func TestConverToDBTestCase(t *testing.T) {
func TestConvertTestSuite(t *testing.T) { func TestConvertTestSuite(t *testing.T) {
t.Run("ConvertToDBTestSuite", func(t *testing.T) { t.Run("ConvertToDBTestSuite", func(t *testing.T) {
result := pkg.ConvertToDBTestSuite(&remote.TestSuite{ result := pkg.ConvertToDBTestSuite(&remote.TestSuite{
Name: "name", Name: "name",
Api: "api", Api: "api",
Param: samplePairs,
Spec: &server.APISpec{
Kind: "kind",
},
}) })
assert.Equal(t, &pkg.TestSuite{ assert.Equal(t, &pkg.TestSuite{
Name: "name", Name: "name",
API: "api", API: "api",
SpecKind: "kind",
Param: `{"key":"value"}`,
}, result) }, result)
}) })
@ -115,14 +122,18 @@ func TestConvertTestSuite(t *testing.T) {
assert.Equal(t, &remote.TestSuite{ assert.Equal(t, &remote.TestSuite{
Name: "name", Name: "name",
Api: "api", Api: "api",
Spec: &remote.APISpec{}, Spec: &server.APISpec{},
}, result) }, result)
}) })
t.Run("sliceToJSON", func(t *testing.T) {
assert.Equal(t, "[]", pkg.SliceToJSON(nil))
})
} }
const sampleJSONMap = `{"key":"value"}` const sampleJSONMap = `{"key":"value"}`
var samplePairs []*remote.Pair = []*remote.Pair{{ var samplePairs []*server.Pair = []*server.Pair{{
Key: "key", Key: "key",
Value: "value", Value: "value",
}} }}

View File

@ -23,4 +23,5 @@ type TestSuite struct {
API string API string
SpecKind string SpecKind string
SpecURL string SpecURL string
Param string
} }

2
go.mod
View File

@ -8,6 +8,7 @@ require (
github.com/antonmedv/expr v1.12.1 github.com/antonmedv/expr v1.12.1
github.com/cucumber/godog v0.12.6 github.com/cucumber/godog v0.12.6
github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml v1.0.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0
github.com/h2non/gock v1.2.0 github.com/h2non/gock v1.2.0
github.com/invopop/jsonschema v0.7.0 github.com/invopop/jsonschema v0.7.0
@ -57,6 +58,7 @@ require (
golang.org/x/net v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect

61
go.sum
View File

@ -1,3 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
@ -6,8 +9,12 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antonmedv/expr v1.12.1 h1:GTGrGN1kxxb+le0uQKaFRK8By4cvq1sleUCGE/U6hHg= github.com/antonmedv/expr v1.12.1 h1:GTGrGN1kxxb+le0uQKaFRK8By4cvq1sleUCGE/U6hHg=
github.com/antonmedv/expr v1.12.1/go.mod h1:FPC8iWArxls7axbVLsW+kpg1mz29A1b2M6jt+hZfDkU= github.com/antonmedv/expr v1.12.1/go.mod h1:FPC8iWArxls7axbVLsW+kpg1mz29A1b2M6jt+hZfDkU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@ -21,22 +28,36 @@ github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
@ -86,6 +107,8 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@ -132,22 +155,41 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -165,16 +207,32 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw=
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
@ -186,6 +244,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
@ -193,3 +252,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

5
pkg/server/constant.go Normal file
View File

@ -0,0 +1,5 @@
package server
const (
HeaderKeyStoreName = "X-Store-Name"
)

43
pkg/server/convert.go Normal file
View File

@ -0,0 +1,43 @@
/**
MIT License
Copyright (c) 2023 Rick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package server
import "github.com/linuxsuren/api-testing/pkg/testing"
func ToGRPCStore(store testing.Store) (result *Store) {
result = &Store{
Name: store.Name,
Kind: &StoreKind{
Name: store.Kind.Name,
Url: store.Kind.URL,
},
Description: store.Description,
Url: store.URL,
Username: store.Username,
Password: store.Password,
Properties: mapToPair(store.Properties),
}
return
}

View File

@ -0,0 +1,62 @@
/**
MIT License
Copyright (c) 2023 Rick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package server
import (
"testing"
atest "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/stretchr/testify/assert"
)
func TestToGRPCStore(t *testing.T) {
assert.Equal(t, &Store{
Name: "test",
Description: "desc",
Kind: &StoreKind{
Name: "test",
Url: urlFoo,
},
Url: urlFoo,
Username: "user",
Password: "pass",
Properties: []*Pair{{
Key: "foo", Value: "bar",
}},
}, ToGRPCStore(atest.Store{
Name: "test",
Description: "desc",
Kind: atest.StoreKind{
Name: "test",
URL: urlFoo,
},
URL: urlFoo,
Username: "user",
Password: "pass",
Properties: map[string]string{
"foo": "bar",
},
}))
}

15
pkg/server/gateway.go Normal file
View File

@ -0,0 +1,15 @@
package server
import (
context "context"
"net/http"
"google.golang.org/grpc/metadata"
)
// MetadataStoreFunc is a function that extracts metadata from a request.
func MetadataStoreFunc(ctx context.Context, r *http.Request) (md metadata.MD) {
store := r.Header.Get(HeaderKeyStoreName)
md = metadata.Pairs(HeaderKeyStoreName, store)
return
}

View File

@ -0,0 +1,20 @@
package server
import (
"context"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
func TestMetadataStoreFunc(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, "/", nil)
req.Header.Set(HeaderKeyStoreName, "test")
if !assert.NoError(t, err) {
return
}
md := MetadataStoreFunc(context.TODO(), req)
assert.Equal(t, "test", md.Get(HeaderKeyStoreName)[0])
}

View File

@ -19,17 +19,24 @@ import (
"github.com/linuxsuren/api-testing/pkg/testing" "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/linuxsuren/api-testing/pkg/version" "github.com/linuxsuren/api-testing/pkg/version"
"github.com/linuxsuren/api-testing/sample" "github.com/linuxsuren/api-testing/sample"
"google.golang.org/grpc/metadata"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
type server struct { type server struct {
UnimplementedRunnerServer UnimplementedRunnerServer
loader testing.Writer loader testing.Writer
storeWriterFactory testing.StoreWriterFactory
configDir string
} }
// NewRemoteServer creates a remote server instance // NewRemoteServer creates a remote server instance
func NewRemoteServer(loader testing.Writer) RunnerServer { func NewRemoteServer(loader testing.Writer, storeWriterFactory testing.StoreWriterFactory, configDir string) RunnerServer {
return &server{loader: loader} return &server{
loader: loader,
storeWriterFactory: storeWriterFactory,
configDir: configDir,
}
} }
func withDefaultValue(old, defVal any) any { func withDefaultValue(old, defVal any) any {
@ -92,6 +99,33 @@ func resetEnv(oldEnv map[string]string) {
} }
} }
func (s *server) getLoader(ctx context.Context) (loader testing.Writer) {
var ok bool
loader = s.loader
var mdd metadata.MD
if mdd, ok = metadata.FromIncomingContext(ctx); ok {
storeNameMeta := mdd.Get(HeaderKeyStoreName)
if len(storeNameMeta) > 0 {
storeName := storeNameMeta[0]
if storeName == "local" {
return
}
store, err := testing.NewStoreFactory(s.configDir).GetStore(storeName)
if err == nil && store != nil {
loader, err = s.storeWriterFactory.NewInstance(*store)
if err != nil {
fmt.Println("failed to new grpc loader from store", store.Name, err)
}
} else {
fmt.Println("failed to get store", storeName, err)
}
}
}
return
}
// Run start to run the test task // Run start to run the test task
func (s *server) Run(ctx context.Context, task *TestTask) (reply *TestResult, err error) { func (s *server) Run(ctx context.Context, task *TestTask) (reply *TestResult, err error) {
task.Level = withDefaultValue(task.Level, "info").(string) task.Level = withDefaultValue(task.Level, "info").(string)
@ -171,12 +205,13 @@ func (s *server) GetVersion(ctx context.Context, in *Empty) (reply *HelloReply,
} }
func (s *server) GetSuites(ctx context.Context, in *Empty) (reply *Suites, err error) { func (s *server) GetSuites(ctx context.Context, in *Empty) (reply *Suites, err error) {
loader := s.getLoader(ctx)
reply = &Suites{ reply = &Suites{
Data: make(map[string]*Items), Data: make(map[string]*Items),
} }
var suites []testing.TestSuite var suites []testing.TestSuite
if suites, err = s.loader.ListTestSuite(); err == nil && suites != nil { if suites, err = loader.ListTestSuite(); err == nil && suites != nil {
for _, suite := range suites { for _, suite := range suites {
items := &Items{} items := &Items{}
for _, item := range suite.Items { for _, item := range suite.Items {
@ -190,13 +225,15 @@ func (s *server) GetSuites(ctx context.Context, in *Empty) (reply *Suites, err e
} }
func (s *server) CreateTestSuite(ctx context.Context, in *TestSuiteIdentity) (reply *HelloReply, err error) { func (s *server) CreateTestSuite(ctx context.Context, in *TestSuiteIdentity) (reply *HelloReply, err error) {
err = s.loader.CreateSuite(in.Name, in.Api) loader := s.getLoader(ctx)
err = loader.CreateSuite(in.Name, in.Api)
return return
} }
func (s *server) GetTestSuite(ctx context.Context, in *TestSuiteIdentity) (result *TestSuite, err error) { func (s *server) GetTestSuite(ctx context.Context, in *TestSuiteIdentity) (result *TestSuite, err error) {
loader := s.getLoader(ctx)
var suite *testing.TestSuite var suite *testing.TestSuite
if suite, _, err = s.loader.GetSuite(in.Name); err == nil && suite != nil { if suite, _, err = loader.GetSuite(in.Name); err == nil && suite != nil {
result = &TestSuite{ result = &TestSuite{
Name: suite.Name, Name: suite.Name,
Api: suite.API, Api: suite.API,
@ -227,19 +264,22 @@ func convertToTestingTestSuite(in *TestSuite) (suite *testing.TestSuite) {
func (s *server) UpdateTestSuite(ctx context.Context, in *TestSuite) (reply *HelloReply, err error) { func (s *server) UpdateTestSuite(ctx context.Context, in *TestSuite) (reply *HelloReply, err error) {
reply = &HelloReply{} reply = &HelloReply{}
err = s.loader.UpdateSuite(*convertToTestingTestSuite(in)) loader := s.getLoader(ctx)
err = loader.UpdateSuite(*convertToTestingTestSuite(in))
return return
} }
func (s *server) DeleteTestSuite(ctx context.Context, in *TestSuiteIdentity) (reply *HelloReply, err error) { func (s *server) DeleteTestSuite(ctx context.Context, in *TestSuiteIdentity) (reply *HelloReply, err error) {
reply = &HelloReply{} reply = &HelloReply{}
err = s.loader.DeleteSuite(in.Name) loader := s.getLoader(ctx)
err = loader.DeleteSuite(in.Name)
return return
} }
func (s *server) ListTestCase(ctx context.Context, in *TestSuiteIdentity) (result *Suite, err error) { func (s *server) ListTestCase(ctx context.Context, in *TestSuiteIdentity) (result *Suite, err error) {
var items []testing.TestCase var items []testing.TestCase
if items, err = s.loader.ListTestCase(in.Name); err == nil { loader := s.getLoader(ctx)
if items, err = loader.ListTestCase(in.Name); err == nil {
result = &Suite{} result = &Suite{}
for _, item := range items { for _, item := range items {
result.Items = append(result.Items, convertToGRPCTestCase(item)) result.Items = append(result.Items, convertToGRPCTestCase(item))
@ -250,7 +290,8 @@ func (s *server) ListTestCase(ctx context.Context, in *TestSuiteIdentity) (resul
func (s *server) GetTestCase(ctx context.Context, in *TestCaseIdentity) (reply *TestCase, err error) { func (s *server) GetTestCase(ctx context.Context, in *TestCaseIdentity) (reply *TestCase, err error) {
var result testing.TestCase var result testing.TestCase
if result, err = s.loader.GetTestCase(in.Suite, in.Testcase); err == nil { loader := s.getLoader(ctx)
if result, err = loader.GetTestCase(in.Suite, in.Testcase); err == nil {
reply = convertToGRPCTestCase(result) reply = convertToGRPCTestCase(result)
} }
return return
@ -286,7 +327,8 @@ func convertToGRPCTestCase(testCase testing.TestCase) (result *TestCase) {
func (s *server) RunTestCase(ctx context.Context, in *TestCaseIdentity) (result *TestCaseResult, err error) { func (s *server) RunTestCase(ctx context.Context, in *TestCaseIdentity) (result *TestCaseResult, err error) {
var targetTestSuite testing.TestSuite var targetTestSuite testing.TestSuite
targetTestSuite, err = s.loader.GetTestSuite(in.Suite, true) loader := s.getLoader(ctx)
targetTestSuite, err = loader.GetTestSuite(in.Suite, true)
if err != nil { if err != nil {
err = nil err = nil
result = &TestCaseResult{ result = &TestCaseResult{
@ -397,7 +439,8 @@ func convertToTestingTestCase(in *TestCase) (result testing.TestCase) {
func (s *server) CreateTestCase(ctx context.Context, in *TestCaseWithSuite) (reply *HelloReply, err error) { func (s *server) CreateTestCase(ctx context.Context, in *TestCaseWithSuite) (reply *HelloReply, err error) {
reply = &HelloReply{} reply = &HelloReply{}
err = s.loader.CreateTestCase(in.SuiteName, convertToTestingTestCase(in.Data)) loader := s.getLoader(ctx)
err = loader.CreateTestCase(in.SuiteName, convertToTestingTestCase(in.Data))
return return
} }
@ -407,12 +450,14 @@ func (s *server) UpdateTestCase(ctx context.Context, in *TestCaseWithSuite) (rep
err = errors.New("data is required") err = errors.New("data is required")
return return
} }
err = s.loader.UpdateTestCase(in.SuiteName, convertToTestingTestCase(in.Data)) loader := s.getLoader(ctx)
err = loader.UpdateTestCase(in.SuiteName, convertToTestingTestCase(in.Data))
return return
} }
func (s *server) DeleteTestCase(ctx context.Context, in *TestCaseIdentity) (reply *HelloReply, err error) { func (s *server) DeleteTestCase(ctx context.Context, in *TestCaseIdentity) (reply *HelloReply, err error) {
err = s.loader.DeleteTestCase(in.Suite, in.Testcase) loader := s.getLoader(ctx)
err = loader.DeleteTestCase(in.Suite, in.Testcase)
return return
} }
@ -437,7 +482,8 @@ func (s *server) GetSuggestedAPIs(ctx context.Context, in *TestSuiteIdentity) (r
reply = &TestCases{} reply = &TestCases{}
var suite *testing.TestSuite var suite *testing.TestSuite
if suite, _, err = s.loader.GetSuite(in.Name); err != nil { loader := s.loader
if suite, _, err = loader.GetSuite(in.Name); err != nil {
return return
} }
@ -483,6 +529,29 @@ func (s *server) FunctionsQuery(ctx context.Context, in *SimpleQuery) (reply *Pa
return return
} }
func (s *server) GetStores(ctx context.Context, in *Empty) (reply *Stores, err error) {
storeFactory := testing.NewStoreFactory(s.configDir)
var stores []testing.Store
if stores, err = storeFactory.GetStores(); err == nil {
reply = &Stores{
Data: make([]*Store, 0),
}
for _, item := range stores {
reply.Data = append(reply.Data, ToGRPCStore(item))
}
}
return
}
func (s *server) CreateStore(ctx context.Context, in *Store) (reply *Store, err error) {
return
}
func (s *server) DeleteStore(ctx context.Context, in *Store) (reply *Store, err error) {
return
}
func (s *server) VerifyStore(ctx context.Context, in *SimpleQuery) (reply *CommonResult, err error) {
return
}
//go:embed data/headers.yaml //go:embed data/headers.yaml
var popularHeaders string var popularHeaders string

View File

@ -22,7 +22,7 @@ const (
func TestRemoteServer(t *testing.T) { func TestRemoteServer(t *testing.T) {
loader := atesting.NewFileWriter("") loader := atesting.NewFileWriter("")
loader.Put("testdata/simple.yaml") loader.Put("testdata/simple.yaml")
server := NewRemoteServer(loader) server := NewRemoteServer(loader, nil, "")
_, err := server.Run(context.TODO(), &TestTask{ _, err := server.Run(context.TODO(), &TestTask{
Kind: "fake", Kind: "fake",
}) })
@ -93,7 +93,7 @@ func TestRemoteServer(t *testing.T) {
func TestRunTestCase(t *testing.T) { func TestRunTestCase(t *testing.T) {
loader := atesting.NewFileWriter("") loader := atesting.NewFileWriter("")
loader.Put("testdata/simple.yaml") loader.Put("testdata/simple.yaml")
server := NewRemoteServer(loader) server := NewRemoteServer(loader, nil, "")
defer gock.Clean() defer gock.Clean()
gock.New(urlFoo).Get("/").MatchHeader("key", "value"). gock.New(urlFoo).Get("/").MatchHeader("key", "value").
@ -266,7 +266,7 @@ func TestUpdateTestCase(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
ctx := context.Background() ctx := context.Background()
server := NewRemoteServer(writer) server := NewRemoteServer(writer, nil, "")
_, err = server.UpdateTestCase(ctx, &TestCaseWithSuite{ _, err = server.UpdateTestCase(ctx, &TestCaseWithSuite{
SuiteName: "simple", SuiteName: "simple",
Data: &TestCase{ Data: &TestCase{
@ -338,7 +338,7 @@ func TestListTestCase(t *testing.T) {
writer := atesting.NewFileWriter(os.TempDir()) writer := atesting.NewFileWriter(os.TempDir())
writer.Put(tmpFile.Name()) writer.Put(tmpFile.Name())
server := NewRemoteServer(writer) server := NewRemoteServer(writer, nil, "")
ctx := context.Background() ctx := context.Background()
t.Run("get two testcases", func(t *testing.T) { t.Run("get two testcases", func(t *testing.T) {
@ -471,7 +471,7 @@ func TestFunctionsQuery(t *testing.T) {
func getRemoteServerInTempDir() (server RunnerServer) { func getRemoteServerInTempDir() (server RunnerServer) {
writer := atesting.NewFileWriter(os.TempDir()) writer := atesting.NewFileWriter(os.TempDir())
server = NewRemoteServer(writer) server = NewRemoteServer(writer, nil, "")
return return
} }

View File

@ -717,9 +717,10 @@ type TestCase struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Request *Request `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` SuiteName string `protobuf:"bytes,2,opt,name=suiteName,proto3" json:"suiteName,omitempty"`
Response *Response `protobuf:"bytes,3,opt,name=response,proto3" json:"response,omitempty"` Request *Request `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"`
Response *Response `protobuf:"bytes,4,opt,name=response,proto3" json:"response,omitempty"`
} }
func (x *TestCase) Reset() { func (x *TestCase) Reset() {
@ -761,6 +762,13 @@ func (x *TestCase) GetName() string {
return "" return ""
} }
func (x *TestCase) GetSuiteName() string {
if x != nil {
return x.SuiteName
}
return ""
}
func (x *TestCase) GetRequest() *Request { func (x *TestCase) GetRequest() *Request {
if x != nil { if x != nil {
return x.Request return x.Request
@ -1185,6 +1193,305 @@ func (x *SimpleQuery) GetName() string {
return "" return ""
} }
type Stores struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data []*Store `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"`
}
func (x *Stores) Reset() {
*x = Stores{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_server_server_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Stores) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Stores) ProtoMessage() {}
func (x *Stores) ProtoReflect() protoreflect.Message {
mi := &file_pkg_server_server_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Stores.ProtoReflect.Descriptor instead.
func (*Stores) Descriptor() ([]byte, []int) {
return file_pkg_server_server_proto_rawDescGZIP(), []int{19}
}
func (x *Stores) GetData() []*Store {
if x != nil {
return x.Data
}
return nil
}
type Store struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"`
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
Password string `protobuf:"bytes,5,opt,name=password,proto3" json:"password,omitempty"`
Properties []*Pair `protobuf:"bytes,6,rep,name=properties,proto3" json:"properties,omitempty"`
Kind *StoreKind `protobuf:"bytes,7,opt,name=kind,proto3" json:"kind,omitempty"`
}
func (x *Store) Reset() {
*x = Store{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_server_server_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Store) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Store) ProtoMessage() {}
func (x *Store) ProtoReflect() protoreflect.Message {
mi := &file_pkg_server_server_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Store.ProtoReflect.Descriptor instead.
func (*Store) Descriptor() ([]byte, []int) {
return file_pkg_server_server_proto_rawDescGZIP(), []int{20}
}
func (x *Store) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Store) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *Store) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
func (x *Store) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *Store) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
func (x *Store) GetProperties() []*Pair {
if x != nil {
return x.Properties
}
return nil
}
func (x *Store) GetKind() *StoreKind {
if x != nil {
return x.Kind
}
return nil
}
type StoreKinds struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data []*StoreKind `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"`
}
func (x *StoreKinds) Reset() {
*x = StoreKinds{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_server_server_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StoreKinds) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StoreKinds) ProtoMessage() {}
func (x *StoreKinds) ProtoReflect() protoreflect.Message {
mi := &file_pkg_server_server_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StoreKinds.ProtoReflect.Descriptor instead.
func (*StoreKinds) Descriptor() ([]byte, []int) {
return file_pkg_server_server_proto_rawDescGZIP(), []int{21}
}
func (x *StoreKinds) GetData() []*StoreKind {
if x != nil {
return x.Data
}
return nil
}
type StoreKind struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
}
func (x *StoreKind) Reset() {
*x = StoreKind{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_server_server_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StoreKind) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StoreKind) ProtoMessage() {}
func (x *StoreKind) ProtoReflect() protoreflect.Message {
mi := &file_pkg_server_server_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StoreKind.ProtoReflect.Descriptor instead.
func (*StoreKind) Descriptor() ([]byte, []int) {
return file_pkg_server_server_proto_rawDescGZIP(), []int{22}
}
func (x *StoreKind) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *StoreKind) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
type CommonResult struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
}
func (x *CommonResult) Reset() {
*x = CommonResult{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_server_server_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CommonResult) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CommonResult) ProtoMessage() {}
func (x *CommonResult) ProtoReflect() protoreflect.Message {
mi := &file_pkg_server_server_proto_msgTypes[23]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CommonResult.ProtoReflect.Descriptor instead.
func (*CommonResult) Descriptor() ([]byte, []int) {
return file_pkg_server_server_proto_rawDescGZIP(), []int{23}
}
func (x *CommonResult) GetSuccess() bool {
if x != nil {
return x.Success
}
return false
}
func (x *CommonResult) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
type Empty struct { type Empty struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -1194,7 +1501,7 @@ type Empty struct {
func (x *Empty) Reset() { func (x *Empty) Reset() {
*x = Empty{} *x = Empty{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_pkg_server_server_proto_msgTypes[19] mi := &file_pkg_server_server_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1207,7 +1514,7 @@ func (x *Empty) String() string {
func (*Empty) ProtoMessage() {} func (*Empty) ProtoMessage() {}
func (x *Empty) ProtoReflect() protoreflect.Message { func (x *Empty) ProtoReflect() protoreflect.Message {
mi := &file_pkg_server_server_proto_msgTypes[19] mi := &file_pkg_server_server_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1220,7 +1527,7 @@ func (x *Empty) ProtoReflect() protoreflect.Message {
// Deprecated: Use Empty.ProtoReflect.Descriptor instead. // Deprecated: Use Empty.ProtoReflect.Descriptor instead.
func (*Empty) Descriptor() ([]byte, []int) { func (*Empty) Descriptor() ([]byte, []int) {
return file_pkg_server_server_proto_rawDescGZIP(), []int{19} return file_pkg_server_server_proto_rawDescGZIP(), []int{24}
} }
var File_pkg_server_server_proto protoreflect.FileDescriptor var File_pkg_server_server_proto protoreflect.FileDescriptor
@ -1295,126 +1602,171 @@ var file_pkg_server_server_proto_rawDesc = []byte{
0x64, 0x61, 0x74, 0x61, 0x22, 0x31, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x64, 0x61, 0x74, 0x61, 0x22, 0x31, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65,
0x73, 0x12, 0x24, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x73, 0x12, 0x24, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73,
0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x77, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x43, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x95, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74,
0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x43, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x69, 0x74,
0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x69,
0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20,
0x22, 0xb3, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73,
0x61, 0x70, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x70, 0x69, 0x12, 0x16, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0xb3, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61,
0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x24, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x70, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x70, 0x69, 0x12, 0x16, 0x0a,
0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d,
0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x24, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50,
0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x05, 0x71,
0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12,
0x20, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x66, 0x6f, 0x72,
0x6d, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xce, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f,
0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x24, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x05, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x10,
0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x62, 0x6f, 0x64, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x12, 0x20, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x10, 0x62, 0x6f, 0x64, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x66, 0x6f, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79,
0x72, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x16,
0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xce, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xa8, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x43,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61,
0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73,
0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x24, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64,
0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x24, 0x0a,
0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
0x10, 0x62, 0x6f, 0x64, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61,
0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x64, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01,
0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x10, 0x62, 0x6f, 0x64, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74,
0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x70, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75,
0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x74, 0x22, 0x2e, 0x0a, 0x04, 0x50, 0x61, 0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xa8, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
0x43, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x65, 0x22, 0x29, 0x0a, 0x05, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x20, 0x0a, 0x04, 0x64, 0x61,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x24, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x21, 0x0a, 0x0b,
0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22,
0x61, 0x64, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x2b, 0x0a, 0x06, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x04, 0x64, 0x61, 0x74,
0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xdc, 0x01, 0x0a,
0x74, 0x70, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x05, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x75, 0x74, 0x22, 0x2e, 0x0a, 0x04, 0x50, 0x61, 0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03,
0x75, 0x65, 0x22, 0x29, 0x0a, 0x05, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x20, 0x0a, 0x04, 0x64, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a,
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x21, 0x0a, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61,
0x0b, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x2c, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72,
0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xfd, 0x07, 0x0a, 0x06, 0x52, 0x75, 0x74, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72,
0x6e, 0x6e, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x1a, 0x12, 0x2e, 0x74, 0x69, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x07, 0x20, 0x01,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72,
0x74, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x0d, 0x2e, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x33, 0x0a, 0x0a, 0x53,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x61, 0x74,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x22, 0x00, 0x12, 0x31, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x22, 0x31, 0x0a, 0x09, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a,
0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x2c, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x65, 0x73, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x75, 0x72, 0x6c, 0x22, 0x42, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73,
0x79, 0x1a, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x75, 0x69, 0x74, 0x65, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01,
0x73, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x79, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x32, 0xfb, 0x09, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x03, 0x52,
0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, 0x65, 0x75, 0x6e, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74,
0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65,
0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x2c, 0x0a, 0x09, 0x47, 0x65,
0x74, 0x79, 0x1a, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61,
0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x12, 0x2e, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64,
0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c,
0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73,
0x79, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49,
0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0f,
0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12,
0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x75, 0x69, 0x74, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69,
0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x74, 0x65, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c,
0x73, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65,
0x43, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x73, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x52, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64,
0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0c,
0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x73,
0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49,
0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x2e, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53,
0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75, 0x69, 0x74, 0x65, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x50, 0x49, 0x73, 0x12, 0x19, 0x2e, 0x73,
0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49,
0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x73, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0b,
0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75, 0x52, 0x75, 0x6e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x65,
0x69, 0x74, 0x65, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c,
0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0e, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54,
0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x30, 0x0a, 0x0e, 0x50, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12,
0x6f, 0x70, 0x75, 0x6c, 0x61, 0x72, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x0d, 0x2e, 0x3b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x18,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
0x10, 0x47, 0x65, 0x74, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x50, 0x49, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0e,
0x73, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x19,
0x75, 0x69, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x73, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x73, 0x22, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x00, 0x12, 0x36, 0x0a, 0x0e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x51, 0x75, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12,
0x65, 0x72, 0x79, 0x12, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x41, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73,
0x70, 0x6c, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43,
0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x12, 0x2e, 0x73,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x73, 0x75, 0x72, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79,
0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74,
0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x43, 0x61, 0x73, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65,
0x33, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x12,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70,
0x6c, 0x79, 0x22, 0x00, 0x12, 0x30, 0x0a, 0x0e, 0x50, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x72, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50,
0x61, 0x69, 0x72, 0x73, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x0d, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x00, 0x12, 0x31,
0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22,
0x00, 0x12, 0x2d, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00,
0x12, 0x34, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64,
0x73, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b,
0x69, 0x6e, 0x64, 0x73, 0x22, 0x00, 0x12, 0x2c, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f,
0x72, 0x65, 0x73, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x1a, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72,
0x65, 0x73, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74,
0x6f, 0x72, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f,
0x72, 0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72,
0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x6f,
0x72, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72,
0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65,
0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x74, 0x6f, 0x72,
0x65, 0x12, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c,
0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x42, 0x2e,
0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e,
0x75, 0x78, 0x73, 0x75, 0x72, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x74, 0x65, 0x73, 0x74,
0x69, 0x6e, 0x67, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -1429,7 +1781,7 @@ func file_pkg_server_server_proto_rawDescGZIP() []byte {
return file_pkg_server_server_proto_rawDescData return file_pkg_server_server_proto_rawDescData
} }
var file_pkg_server_server_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_pkg_server_server_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
var file_pkg_server_server_proto_goTypes = []interface{}{ var file_pkg_server_server_proto_goTypes = []interface{}{
(*Suites)(nil), // 0: server.Suites (*Suites)(nil), // 0: server.Suites
(*Items)(nil), // 1: server.Items (*Items)(nil), // 1: server.Items
@ -1450,15 +1802,20 @@ var file_pkg_server_server_proto_goTypes = []interface{}{
(*Pair)(nil), // 16: server.Pair (*Pair)(nil), // 16: server.Pair
(*Pairs)(nil), // 17: server.Pairs (*Pairs)(nil), // 17: server.Pairs
(*SimpleQuery)(nil), // 18: server.SimpleQuery (*SimpleQuery)(nil), // 18: server.SimpleQuery
(*Empty)(nil), // 19: server.Empty (*Stores)(nil), // 19: server.Stores
nil, // 20: server.Suites.DataEntry (*Store)(nil), // 20: server.Store
nil, // 21: server.TestTask.EnvEntry (*StoreKinds)(nil), // 21: server.StoreKinds
(*StoreKind)(nil), // 22: server.StoreKind
(*CommonResult)(nil), // 23: server.CommonResult
(*Empty)(nil), // 24: server.Empty
nil, // 25: server.Suites.DataEntry
nil, // 26: server.TestTask.EnvEntry
} }
var file_pkg_server_server_proto_depIdxs = []int32{ var file_pkg_server_server_proto_depIdxs = []int32{
20, // 0: server.Suites.data:type_name -> server.Suites.DataEntry 25, // 0: server.Suites.data:type_name -> server.Suites.DataEntry
16, // 1: server.TestSuite.param:type_name -> server.Pair 16, // 1: server.TestSuite.param:type_name -> server.Pair
4, // 2: server.TestSuite.spec:type_name -> server.APISpec 4, // 2: server.TestSuite.spec:type_name -> server.APISpec
21, // 3: server.TestTask.env:type_name -> server.TestTask.EnvEntry 26, // 3: server.TestTask.env:type_name -> server.TestTask.EnvEntry
15, // 4: server.TestResult.testCaseResult:type_name -> server.TestCaseResult 15, // 4: server.TestResult.testCaseResult:type_name -> server.TestCaseResult
12, // 5: server.Suite.items:type_name -> server.TestCase 12, // 5: server.Suite.items:type_name -> server.TestCase
12, // 6: server.TestCaseWithSuite.data:type_name -> server.TestCase 12, // 6: server.TestCaseWithSuite.data:type_name -> server.TestCase
@ -1472,46 +1829,60 @@ var file_pkg_server_server_proto_depIdxs = []int32{
16, // 14: server.Response.bodyFieldsExpect:type_name -> server.Pair 16, // 14: server.Response.bodyFieldsExpect:type_name -> server.Pair
16, // 15: server.TestCaseResult.header:type_name -> server.Pair 16, // 15: server.TestCaseResult.header:type_name -> server.Pair
16, // 16: server.Pairs.data:type_name -> server.Pair 16, // 16: server.Pairs.data:type_name -> server.Pair
1, // 17: server.Suites.DataEntry.value:type_name -> server.Items 20, // 17: server.Stores.data:type_name -> server.Store
6, // 18: server.Runner.Run:input_type -> server.TestTask 16, // 18: server.Store.properties:type_name -> server.Pair
19, // 19: server.Runner.Sample:input_type -> server.Empty 22, // 19: server.Store.kind:type_name -> server.StoreKind
19, // 20: server.Runner.GetVersion:input_type -> server.Empty 22, // 20: server.StoreKinds.data:type_name -> server.StoreKind
19, // 21: server.Runner.GetSuites:input_type -> server.Empty 1, // 21: server.Suites.DataEntry.value:type_name -> server.Items
5, // 22: server.Runner.CreateTestSuite:input_type -> server.TestSuiteIdentity 6, // 22: server.Runner.Run:input_type -> server.TestTask
5, // 23: server.Runner.GetTestSuite:input_type -> server.TestSuiteIdentity 24, // 23: server.Runner.GetSuites:input_type -> server.Empty
3, // 24: server.Runner.UpdateTestSuite:input_type -> server.TestSuite 5, // 24: server.Runner.CreateTestSuite:input_type -> server.TestSuiteIdentity
5, // 25: server.Runner.DeleteTestSuite:input_type -> server.TestSuiteIdentity 5, // 25: server.Runner.GetTestSuite:input_type -> server.TestSuiteIdentity
5, // 26: server.Runner.ListTestCase:input_type -> server.TestSuiteIdentity 3, // 26: server.Runner.UpdateTestSuite:input_type -> server.TestSuite
2, // 27: server.Runner.RunTestCase:input_type -> server.TestCaseIdentity 5, // 27: server.Runner.DeleteTestSuite:input_type -> server.TestSuiteIdentity
2, // 28: server.Runner.GetTestCase:input_type -> server.TestCaseIdentity 5, // 28: server.Runner.ListTestCase:input_type -> server.TestSuiteIdentity
10, // 29: server.Runner.CreateTestCase:input_type -> server.TestCaseWithSuite 5, // 29: server.Runner.GetSuggestedAPIs:input_type -> server.TestSuiteIdentity
10, // 30: server.Runner.UpdateTestCase:input_type -> server.TestCaseWithSuite 2, // 30: server.Runner.RunTestCase:input_type -> server.TestCaseIdentity
2, // 31: server.Runner.DeleteTestCase:input_type -> server.TestCaseIdentity 2, // 31: server.Runner.GetTestCase:input_type -> server.TestCaseIdentity
19, // 32: server.Runner.PopularHeaders:input_type -> server.Empty 10, // 32: server.Runner.CreateTestCase:input_type -> server.TestCaseWithSuite
5, // 33: server.Runner.GetSuggestedAPIs:input_type -> server.TestSuiteIdentity 10, // 33: server.Runner.UpdateTestCase:input_type -> server.TestCaseWithSuite
18, // 34: server.Runner.FunctionsQuery:input_type -> server.SimpleQuery 2, // 34: server.Runner.DeleteTestCase:input_type -> server.TestCaseIdentity
7, // 35: server.Runner.Run:output_type -> server.TestResult 24, // 35: server.Runner.PopularHeaders:input_type -> server.Empty
8, // 36: server.Runner.Sample:output_type -> server.HelloReply 18, // 36: server.Runner.FunctionsQuery:input_type -> server.SimpleQuery
8, // 37: server.Runner.GetVersion:output_type -> server.HelloReply 24, // 37: server.Runner.GetVersion:input_type -> server.Empty
0, // 38: server.Runner.GetSuites:output_type -> server.Suites 24, // 38: server.Runner.Sample:input_type -> server.Empty
8, // 39: server.Runner.CreateTestSuite:output_type -> server.HelloReply 24, // 39: server.Runner.GetStoreKinds:input_type -> server.Empty
3, // 40: server.Runner.GetTestSuite:output_type -> server.TestSuite 24, // 40: server.Runner.GetStores:input_type -> server.Empty
8, // 41: server.Runner.UpdateTestSuite:output_type -> server.HelloReply 20, // 41: server.Runner.CreateStore:input_type -> server.Store
8, // 42: server.Runner.DeleteTestSuite:output_type -> server.HelloReply 20, // 42: server.Runner.DeleteStore:input_type -> server.Store
9, // 43: server.Runner.ListTestCase:output_type -> server.Suite 18, // 43: server.Runner.VerifyStore:input_type -> server.SimpleQuery
15, // 44: server.Runner.RunTestCase:output_type -> server.TestCaseResult 7, // 44: server.Runner.Run:output_type -> server.TestResult
12, // 45: server.Runner.GetTestCase:output_type -> server.TestCase 0, // 45: server.Runner.GetSuites:output_type -> server.Suites
8, // 46: server.Runner.CreateTestCase:output_type -> server.HelloReply 8, // 46: server.Runner.CreateTestSuite:output_type -> server.HelloReply
8, // 47: server.Runner.UpdateTestCase:output_type -> server.HelloReply 3, // 47: server.Runner.GetTestSuite:output_type -> server.TestSuite
8, // 48: server.Runner.DeleteTestCase:output_type -> server.HelloReply 8, // 48: server.Runner.UpdateTestSuite:output_type -> server.HelloReply
17, // 49: server.Runner.PopularHeaders:output_type -> server.Pairs 8, // 49: server.Runner.DeleteTestSuite:output_type -> server.HelloReply
11, // 50: server.Runner.GetSuggestedAPIs:output_type -> server.TestCases 9, // 50: server.Runner.ListTestCase:output_type -> server.Suite
17, // 51: server.Runner.FunctionsQuery:output_type -> server.Pairs 11, // 51: server.Runner.GetSuggestedAPIs:output_type -> server.TestCases
35, // [35:52] is the sub-list for method output_type 15, // 52: server.Runner.RunTestCase:output_type -> server.TestCaseResult
18, // [18:35] is the sub-list for method input_type 12, // 53: server.Runner.GetTestCase:output_type -> server.TestCase
18, // [18:18] is the sub-list for extension type_name 8, // 54: server.Runner.CreateTestCase:output_type -> server.HelloReply
18, // [18:18] is the sub-list for extension extendee 8, // 55: server.Runner.UpdateTestCase:output_type -> server.HelloReply
0, // [0:18] is the sub-list for field type_name 8, // 56: server.Runner.DeleteTestCase:output_type -> server.HelloReply
17, // 57: server.Runner.PopularHeaders:output_type -> server.Pairs
17, // 58: server.Runner.FunctionsQuery:output_type -> server.Pairs
8, // 59: server.Runner.GetVersion:output_type -> server.HelloReply
8, // 60: server.Runner.Sample:output_type -> server.HelloReply
21, // 61: server.Runner.GetStoreKinds:output_type -> server.StoreKinds
19, // 62: server.Runner.GetStores:output_type -> server.Stores
20, // 63: server.Runner.CreateStore:output_type -> server.Store
20, // 64: server.Runner.DeleteStore:output_type -> server.Store
23, // 65: server.Runner.VerifyStore:output_type -> server.CommonResult
44, // [44:66] is the sub-list for method output_type
22, // [22:44] is the sub-list for method input_type
22, // [22:22] is the sub-list for extension type_name
22, // [22:22] is the sub-list for extension extendee
0, // [0:22] is the sub-list for field type_name
} }
func init() { file_pkg_server_server_proto_init() } func init() { file_pkg_server_server_proto_init() }
@ -1749,6 +2120,66 @@ func file_pkg_server_server_proto_init() {
} }
} }
file_pkg_server_server_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { file_pkg_server_server_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Stores); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_server_server_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Store); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_server_server_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StoreKinds); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_server_server_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StoreKind); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_server_server_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CommonResult); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_server_server_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Empty); i { switch v := v.(*Empty); i {
case 0: case 0:
return &v.state return &v.state
@ -1767,7 +2198,7 @@ func file_pkg_server_server_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pkg_server_server_proto_rawDesc, RawDescriptor: file_pkg_server_server_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 22, NumMessages: 27,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

File diff suppressed because it is too large Load Diff

View File

@ -5,27 +5,36 @@ option go_package = "github.com/linuxsuren/api-testing/pkg/server";
package server; package server;
service Runner { service Runner {
// belong to a specific store
rpc Run (TestTask) returns (TestResult) {} rpc Run (TestTask) returns (TestResult) {}
rpc Sample(Empty) returns (HelloReply) {}
rpc GetVersion(Empty) returns (HelloReply) {}
rpc GetSuites(Empty) returns (Suites) {} rpc GetSuites(Empty) returns (Suites) {}
rpc CreateTestSuite(TestSuiteIdentity) returns (HelloReply) {} rpc CreateTestSuite(TestSuiteIdentity) returns (HelloReply) {}
rpc GetTestSuite(TestSuiteIdentity) returns (TestSuite) {} rpc GetTestSuite(TestSuiteIdentity) returns (TestSuite) {}
rpc UpdateTestSuite(TestSuite) returns (HelloReply) {} rpc UpdateTestSuite(TestSuite) returns (HelloReply) {}
rpc DeleteTestSuite(TestSuiteIdentity) returns (HelloReply) {} rpc DeleteTestSuite(TestSuiteIdentity) returns (HelloReply) {}
// test cases related
rpc ListTestCase(TestSuiteIdentity) returns (Suite) {} rpc ListTestCase(TestSuiteIdentity) returns (Suite) {}
rpc GetSuggestedAPIs(TestSuiteIdentity) returns (TestCases) {}
rpc RunTestCase(TestCaseIdentity) returns (TestCaseResult) {} rpc RunTestCase(TestCaseIdentity) returns (TestCaseResult) {}
rpc GetTestCase(TestCaseIdentity) returns (TestCase) {} rpc GetTestCase(TestCaseIdentity) returns (TestCase) {}
rpc CreateTestCase(TestCaseWithSuite) returns (HelloReply) {} rpc CreateTestCase(TestCaseWithSuite) returns (HelloReply) {}
rpc UpdateTestCase(TestCaseWithSuite) returns (HelloReply) {} rpc UpdateTestCase(TestCaseWithSuite) returns (HelloReply) {}
rpc DeleteTestCase(TestCaseIdentity) returns (HelloReply) {} rpc DeleteTestCase(TestCaseIdentity) returns (HelloReply) {}
// common services
rpc PopularHeaders(Empty) returns (Pairs) {} rpc PopularHeaders(Empty) returns (Pairs) {}
rpc GetSuggestedAPIs(TestSuiteIdentity) returns (TestCases) {}
rpc FunctionsQuery(SimpleQuery) returns (Pairs) {} rpc FunctionsQuery(SimpleQuery) returns (Pairs) {}
rpc GetVersion(Empty) returns (HelloReply) {}
rpc Sample(Empty) returns (HelloReply) {}
// stores related interfaces
rpc GetStoreKinds(Empty) returns (StoreKinds) {}
rpc GetStores(Empty) returns (Stores) {}
rpc CreateStore(Store) returns (Store) {}
rpc DeleteStore(Store) returns (Store) {}
rpc VerifyStore(SimpleQuery) returns (CommonResult) {}
} }
message Suites { message Suites {
@ -49,8 +58,8 @@ message TestSuite {
} }
message APISpec { message APISpec {
string kind = 1; string kind = 1;
string url = 2; string url = 2;
} }
message TestSuiteIdentity { message TestSuiteIdentity {
@ -59,11 +68,11 @@ message TestSuiteIdentity {
} }
message TestTask { message TestTask {
string data = 1; string data = 1;
string kind = 2; string kind = 2;
string caseName = 3; string caseName = 3;
string level = 4; string level = 4;
map<string, string> env = 5; map<string, string> env = 5;
} }
message TestResult { message TestResult {
@ -94,8 +103,9 @@ message TestCases {
message TestCase { message TestCase {
string name = 1; string name = 1;
Request request = 2; string suiteName = 2;
Response response = 3; Request request = 3;
Response response = 4;
} }
message Request { message Request {
@ -138,5 +148,33 @@ message SimpleQuery {
string name = 1; string name = 1;
} }
message Stores {
repeated Store data = 1;
}
message Store {
string name = 1;
string description = 2;
string url = 3;
string username = 4;
string password = 5;
repeated Pair properties = 6;
StoreKind kind = 7;
}
message StoreKinds {
repeated StoreKind data = 1;
}
message StoreKind {
string name = 1;
string url = 2;
}
message CommonResult {
bool success = 1;
string message = 2;
}
message Empty { message Empty {
} }

View File

@ -22,23 +22,32 @@ const _ = grpc.SupportPackageIsVersion7
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type RunnerClient interface { type RunnerClient interface {
// belong to a specific store
Run(ctx context.Context, in *TestTask, opts ...grpc.CallOption) (*TestResult, error) Run(ctx context.Context, in *TestTask, opts ...grpc.CallOption) (*TestResult, error)
Sample(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error)
GetVersion(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error)
GetSuites(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Suites, error) GetSuites(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Suites, error)
CreateTestSuite(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*HelloReply, error) CreateTestSuite(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*HelloReply, error)
GetTestSuite(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*TestSuite, error) GetTestSuite(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*TestSuite, error)
UpdateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*HelloReply, error) UpdateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*HelloReply, error)
DeleteTestSuite(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*HelloReply, error) DeleteTestSuite(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*HelloReply, error)
// test cases related
ListTestCase(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*Suite, error) ListTestCase(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*Suite, error)
GetSuggestedAPIs(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*TestCases, error)
RunTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCaseResult, error) RunTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCaseResult, error)
GetTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCase, error) GetTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCase, error)
CreateTestCase(ctx context.Context, in *TestCaseWithSuite, opts ...grpc.CallOption) (*HelloReply, error) CreateTestCase(ctx context.Context, in *TestCaseWithSuite, opts ...grpc.CallOption) (*HelloReply, error)
UpdateTestCase(ctx context.Context, in *TestCaseWithSuite, opts ...grpc.CallOption) (*HelloReply, error) UpdateTestCase(ctx context.Context, in *TestCaseWithSuite, opts ...grpc.CallOption) (*HelloReply, error)
DeleteTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*HelloReply, error) DeleteTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*HelloReply, error)
// common services
PopularHeaders(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Pairs, error) PopularHeaders(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Pairs, error)
GetSuggestedAPIs(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*TestCases, error)
FunctionsQuery(ctx context.Context, in *SimpleQuery, opts ...grpc.CallOption) (*Pairs, error) FunctionsQuery(ctx context.Context, in *SimpleQuery, opts ...grpc.CallOption) (*Pairs, error)
GetVersion(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error)
Sample(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error)
// stores related interfaces
GetStoreKinds(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StoreKinds, error)
GetStores(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Stores, error)
CreateStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error)
DeleteStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error)
VerifyStore(ctx context.Context, in *SimpleQuery, opts ...grpc.CallOption) (*CommonResult, error)
} }
type runnerClient struct { type runnerClient struct {
@ -58,24 +67,6 @@ func (c *runnerClient) Run(ctx context.Context, in *TestTask, opts ...grpc.CallO
return out, nil return out, nil
} }
func (c *runnerClient) Sample(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error) {
out := new(HelloReply)
err := c.cc.Invoke(ctx, "/server.Runner/Sample", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) GetVersion(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error) {
out := new(HelloReply)
err := c.cc.Invoke(ctx, "/server.Runner/GetVersion", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) GetSuites(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Suites, error) { func (c *runnerClient) GetSuites(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Suites, error) {
out := new(Suites) out := new(Suites)
err := c.cc.Invoke(ctx, "/server.Runner/GetSuites", in, out, opts...) err := c.cc.Invoke(ctx, "/server.Runner/GetSuites", in, out, opts...)
@ -130,6 +121,15 @@ func (c *runnerClient) ListTestCase(ctx context.Context, in *TestSuiteIdentity,
return out, nil return out, nil
} }
func (c *runnerClient) GetSuggestedAPIs(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*TestCases, error) {
out := new(TestCases)
err := c.cc.Invoke(ctx, "/server.Runner/GetSuggestedAPIs", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) RunTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCaseResult, error) { func (c *runnerClient) RunTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCaseResult, error) {
out := new(TestCaseResult) out := new(TestCaseResult)
err := c.cc.Invoke(ctx, "/server.Runner/RunTestCase", in, out, opts...) err := c.cc.Invoke(ctx, "/server.Runner/RunTestCase", in, out, opts...)
@ -184,18 +184,72 @@ func (c *runnerClient) PopularHeaders(ctx context.Context, in *Empty, opts ...gr
return out, nil return out, nil
} }
func (c *runnerClient) GetSuggestedAPIs(ctx context.Context, in *TestSuiteIdentity, opts ...grpc.CallOption) (*TestCases, error) { func (c *runnerClient) FunctionsQuery(ctx context.Context, in *SimpleQuery, opts ...grpc.CallOption) (*Pairs, error) {
out := new(TestCases) out := new(Pairs)
err := c.cc.Invoke(ctx, "/server.Runner/GetSuggestedAPIs", in, out, opts...) err := c.cc.Invoke(ctx, "/server.Runner/FunctionsQuery", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return out, nil return out, nil
} }
func (c *runnerClient) FunctionsQuery(ctx context.Context, in *SimpleQuery, opts ...grpc.CallOption) (*Pairs, error) { func (c *runnerClient) GetVersion(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error) {
out := new(Pairs) out := new(HelloReply)
err := c.cc.Invoke(ctx, "/server.Runner/FunctionsQuery", in, out, opts...) err := c.cc.Invoke(ctx, "/server.Runner/GetVersion", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) Sample(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error) {
out := new(HelloReply)
err := c.cc.Invoke(ctx, "/server.Runner/Sample", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) GetStoreKinds(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StoreKinds, error) {
out := new(StoreKinds)
err := c.cc.Invoke(ctx, "/server.Runner/GetStoreKinds", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) GetStores(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Stores, error) {
out := new(Stores)
err := c.cc.Invoke(ctx, "/server.Runner/GetStores", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) CreateStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error) {
out := new(Store)
err := c.cc.Invoke(ctx, "/server.Runner/CreateStore", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) DeleteStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error) {
out := new(Store)
err := c.cc.Invoke(ctx, "/server.Runner/DeleteStore", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *runnerClient) VerifyStore(ctx context.Context, in *SimpleQuery, opts ...grpc.CallOption) (*CommonResult, error) {
out := new(CommonResult)
err := c.cc.Invoke(ctx, "/server.Runner/VerifyStore", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -206,23 +260,32 @@ func (c *runnerClient) FunctionsQuery(ctx context.Context, in *SimpleQuery, opts
// All implementations must embed UnimplementedRunnerServer // All implementations must embed UnimplementedRunnerServer
// for forward compatibility // for forward compatibility
type RunnerServer interface { type RunnerServer interface {
// belong to a specific store
Run(context.Context, *TestTask) (*TestResult, error) Run(context.Context, *TestTask) (*TestResult, error)
Sample(context.Context, *Empty) (*HelloReply, error)
GetVersion(context.Context, *Empty) (*HelloReply, error)
GetSuites(context.Context, *Empty) (*Suites, error) GetSuites(context.Context, *Empty) (*Suites, error)
CreateTestSuite(context.Context, *TestSuiteIdentity) (*HelloReply, error) CreateTestSuite(context.Context, *TestSuiteIdentity) (*HelloReply, error)
GetTestSuite(context.Context, *TestSuiteIdentity) (*TestSuite, error) GetTestSuite(context.Context, *TestSuiteIdentity) (*TestSuite, error)
UpdateTestSuite(context.Context, *TestSuite) (*HelloReply, error) UpdateTestSuite(context.Context, *TestSuite) (*HelloReply, error)
DeleteTestSuite(context.Context, *TestSuiteIdentity) (*HelloReply, error) DeleteTestSuite(context.Context, *TestSuiteIdentity) (*HelloReply, error)
// test cases related
ListTestCase(context.Context, *TestSuiteIdentity) (*Suite, error) ListTestCase(context.Context, *TestSuiteIdentity) (*Suite, error)
GetSuggestedAPIs(context.Context, *TestSuiteIdentity) (*TestCases, error)
RunTestCase(context.Context, *TestCaseIdentity) (*TestCaseResult, error) RunTestCase(context.Context, *TestCaseIdentity) (*TestCaseResult, error)
GetTestCase(context.Context, *TestCaseIdentity) (*TestCase, error) GetTestCase(context.Context, *TestCaseIdentity) (*TestCase, error)
CreateTestCase(context.Context, *TestCaseWithSuite) (*HelloReply, error) CreateTestCase(context.Context, *TestCaseWithSuite) (*HelloReply, error)
UpdateTestCase(context.Context, *TestCaseWithSuite) (*HelloReply, error) UpdateTestCase(context.Context, *TestCaseWithSuite) (*HelloReply, error)
DeleteTestCase(context.Context, *TestCaseIdentity) (*HelloReply, error) DeleteTestCase(context.Context, *TestCaseIdentity) (*HelloReply, error)
// common services
PopularHeaders(context.Context, *Empty) (*Pairs, error) PopularHeaders(context.Context, *Empty) (*Pairs, error)
GetSuggestedAPIs(context.Context, *TestSuiteIdentity) (*TestCases, error)
FunctionsQuery(context.Context, *SimpleQuery) (*Pairs, error) FunctionsQuery(context.Context, *SimpleQuery) (*Pairs, error)
GetVersion(context.Context, *Empty) (*HelloReply, error)
Sample(context.Context, *Empty) (*HelloReply, error)
// stores related interfaces
GetStoreKinds(context.Context, *Empty) (*StoreKinds, error)
GetStores(context.Context, *Empty) (*Stores, error)
CreateStore(context.Context, *Store) (*Store, error)
DeleteStore(context.Context, *Store) (*Store, error)
VerifyStore(context.Context, *SimpleQuery) (*CommonResult, error)
mustEmbedUnimplementedRunnerServer() mustEmbedUnimplementedRunnerServer()
} }
@ -233,12 +296,6 @@ type UnimplementedRunnerServer struct {
func (UnimplementedRunnerServer) Run(context.Context, *TestTask) (*TestResult, error) { func (UnimplementedRunnerServer) Run(context.Context, *TestTask) (*TestResult, error) {
return nil, status.Errorf(codes.Unimplemented, "method Run not implemented") return nil, status.Errorf(codes.Unimplemented, "method Run not implemented")
} }
func (UnimplementedRunnerServer) Sample(context.Context, *Empty) (*HelloReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Sample not implemented")
}
func (UnimplementedRunnerServer) GetVersion(context.Context, *Empty) (*HelloReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented")
}
func (UnimplementedRunnerServer) GetSuites(context.Context, *Empty) (*Suites, error) { func (UnimplementedRunnerServer) GetSuites(context.Context, *Empty) (*Suites, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSuites not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetSuites not implemented")
} }
@ -257,6 +314,9 @@ func (UnimplementedRunnerServer) DeleteTestSuite(context.Context, *TestSuiteIden
func (UnimplementedRunnerServer) ListTestCase(context.Context, *TestSuiteIdentity) (*Suite, error) { func (UnimplementedRunnerServer) ListTestCase(context.Context, *TestSuiteIdentity) (*Suite, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListTestCase not implemented") return nil, status.Errorf(codes.Unimplemented, "method ListTestCase not implemented")
} }
func (UnimplementedRunnerServer) GetSuggestedAPIs(context.Context, *TestSuiteIdentity) (*TestCases, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSuggestedAPIs not implemented")
}
func (UnimplementedRunnerServer) RunTestCase(context.Context, *TestCaseIdentity) (*TestCaseResult, error) { func (UnimplementedRunnerServer) RunTestCase(context.Context, *TestCaseIdentity) (*TestCaseResult, error) {
return nil, status.Errorf(codes.Unimplemented, "method RunTestCase not implemented") return nil, status.Errorf(codes.Unimplemented, "method RunTestCase not implemented")
} }
@ -275,12 +335,30 @@ func (UnimplementedRunnerServer) DeleteTestCase(context.Context, *TestCaseIdenti
func (UnimplementedRunnerServer) PopularHeaders(context.Context, *Empty) (*Pairs, error) { func (UnimplementedRunnerServer) PopularHeaders(context.Context, *Empty) (*Pairs, error) {
return nil, status.Errorf(codes.Unimplemented, "method PopularHeaders not implemented") return nil, status.Errorf(codes.Unimplemented, "method PopularHeaders not implemented")
} }
func (UnimplementedRunnerServer) GetSuggestedAPIs(context.Context, *TestSuiteIdentity) (*TestCases, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSuggestedAPIs not implemented")
}
func (UnimplementedRunnerServer) FunctionsQuery(context.Context, *SimpleQuery) (*Pairs, error) { func (UnimplementedRunnerServer) FunctionsQuery(context.Context, *SimpleQuery) (*Pairs, error) {
return nil, status.Errorf(codes.Unimplemented, "method FunctionsQuery not implemented") return nil, status.Errorf(codes.Unimplemented, "method FunctionsQuery not implemented")
} }
func (UnimplementedRunnerServer) GetVersion(context.Context, *Empty) (*HelloReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented")
}
func (UnimplementedRunnerServer) Sample(context.Context, *Empty) (*HelloReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Sample not implemented")
}
func (UnimplementedRunnerServer) GetStoreKinds(context.Context, *Empty) (*StoreKinds, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetStoreKinds not implemented")
}
func (UnimplementedRunnerServer) GetStores(context.Context, *Empty) (*Stores, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetStores not implemented")
}
func (UnimplementedRunnerServer) CreateStore(context.Context, *Store) (*Store, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateStore not implemented")
}
func (UnimplementedRunnerServer) DeleteStore(context.Context, *Store) (*Store, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteStore not implemented")
}
func (UnimplementedRunnerServer) VerifyStore(context.Context, *SimpleQuery) (*CommonResult, error) {
return nil, status.Errorf(codes.Unimplemented, "method VerifyStore not implemented")
}
func (UnimplementedRunnerServer) mustEmbedUnimplementedRunnerServer() {} func (UnimplementedRunnerServer) mustEmbedUnimplementedRunnerServer() {}
// UnsafeRunnerServer may be embedded to opt out of forward compatibility for this service. // UnsafeRunnerServer may be embedded to opt out of forward compatibility for this service.
@ -312,42 +390,6 @@ func _Runner_Run_Handler(srv interface{}, ctx context.Context, dec func(interfac
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Runner_Sample_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).Sample(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/Sample",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).Sample(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).GetVersion(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/GetVersion",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).GetVersion(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_GetSuites_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Runner_GetSuites_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty) in := new(Empty)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@ -456,6 +498,24 @@ func _Runner_ListTestCase_Handler(srv interface{}, ctx context.Context, dec func
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Runner_GetSuggestedAPIs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestSuiteIdentity)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).GetSuggestedAPIs(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/GetSuggestedAPIs",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).GetSuggestedAPIs(ctx, req.(*TestSuiteIdentity))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_RunTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Runner_RunTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestCaseIdentity) in := new(TestCaseIdentity)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@ -564,24 +624,6 @@ func _Runner_PopularHeaders_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Runner_GetSuggestedAPIs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestSuiteIdentity)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).GetSuggestedAPIs(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/GetSuggestedAPIs",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).GetSuggestedAPIs(ctx, req.(*TestSuiteIdentity))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_FunctionsQuery_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Runner_FunctionsQuery_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SimpleQuery) in := new(SimpleQuery)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@ -600,6 +642,132 @@ func _Runner_FunctionsQuery_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Runner_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).GetVersion(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/GetVersion",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).GetVersion(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_Sample_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).Sample(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/Sample",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).Sample(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_GetStoreKinds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).GetStoreKinds(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/GetStoreKinds",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).GetStoreKinds(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_GetStores_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).GetStores(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/GetStores",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).GetStores(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_CreateStore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Store)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).CreateStore(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/CreateStore",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).CreateStore(ctx, req.(*Store))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_DeleteStore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Store)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).DeleteStore(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/DeleteStore",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).DeleteStore(ctx, req.(*Store))
}
return interceptor(ctx, in, info, handler)
}
func _Runner_VerifyStore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SimpleQuery)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RunnerServer).VerifyStore(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/server.Runner/VerifyStore",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RunnerServer).VerifyStore(ctx, req.(*SimpleQuery))
}
return interceptor(ctx, in, info, handler)
}
// Runner_ServiceDesc is the grpc.ServiceDesc for Runner service. // Runner_ServiceDesc is the grpc.ServiceDesc for Runner service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@ -611,14 +779,6 @@ var Runner_ServiceDesc = grpc.ServiceDesc{
MethodName: "Run", MethodName: "Run",
Handler: _Runner_Run_Handler, Handler: _Runner_Run_Handler,
}, },
{
MethodName: "Sample",
Handler: _Runner_Sample_Handler,
},
{
MethodName: "GetVersion",
Handler: _Runner_GetVersion_Handler,
},
{ {
MethodName: "GetSuites", MethodName: "GetSuites",
Handler: _Runner_GetSuites_Handler, Handler: _Runner_GetSuites_Handler,
@ -643,6 +803,10 @@ var Runner_ServiceDesc = grpc.ServiceDesc{
MethodName: "ListTestCase", MethodName: "ListTestCase",
Handler: _Runner_ListTestCase_Handler, Handler: _Runner_ListTestCase_Handler,
}, },
{
MethodName: "GetSuggestedAPIs",
Handler: _Runner_GetSuggestedAPIs_Handler,
},
{ {
MethodName: "RunTestCase", MethodName: "RunTestCase",
Handler: _Runner_RunTestCase_Handler, Handler: _Runner_RunTestCase_Handler,
@ -667,14 +831,38 @@ var Runner_ServiceDesc = grpc.ServiceDesc{
MethodName: "PopularHeaders", MethodName: "PopularHeaders",
Handler: _Runner_PopularHeaders_Handler, Handler: _Runner_PopularHeaders_Handler,
}, },
{
MethodName: "GetSuggestedAPIs",
Handler: _Runner_GetSuggestedAPIs_Handler,
},
{ {
MethodName: "FunctionsQuery", MethodName: "FunctionsQuery",
Handler: _Runner_FunctionsQuery_Handler, Handler: _Runner_FunctionsQuery_Handler,
}, },
{
MethodName: "GetVersion",
Handler: _Runner_GetVersion_Handler,
},
{
MethodName: "Sample",
Handler: _Runner_Sample_Handler,
},
{
MethodName: "GetStoreKinds",
Handler: _Runner_GetStoreKinds_Handler,
},
{
MethodName: "GetStores",
Handler: _Runner_GetStores_Handler,
},
{
MethodName: "CreateStore",
Handler: _Runner_CreateStore_Handler,
},
{
MethodName: "DeleteStore",
Handler: _Runner_DeleteStore_Handler,
},
{
MethodName: "VerifyStore",
Handler: _Runner_VerifyStore_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "pkg/server/server.proto", Metadata: "pkg/server/server.proto",

View File

@ -73,13 +73,16 @@ func (l *fileLoader) ListTestSuite() (suites []TestSuite, err error) {
for l.HasMore() { for l.HasMore() {
var data []byte var data []byte
if data, err = l.Load(); err != nil { var loadErr error
if data, loadErr = l.Load(); err != nil {
fmt.Println("failed to load data", loadErr)
continue continue
} }
var testSuite *TestSuite var testSuite *TestSuite
if testSuite, err = Parse(data); err != nil { if testSuite, loadErr = Parse(data); loadErr != nil {
return fmt.Println("failed to parse data", loadErr)
continue
} }
suites = append(suites, *testSuite) suites = append(suites, *testSuite)
} }

View File

@ -0,0 +1,53 @@
/**
MIT License
Copyright (c) 2023 Rick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package remote
import (
context "context"
"github.com/linuxsuren/api-testing/pkg/testing"
"google.golang.org/grpc/metadata"
)
func WithStoreContext(ctx context.Context, store *testing.Store) context.Context {
return metadata.NewOutgoingContext(ctx, metadata.New(store.ToMap()))
}
func GetStoreFromContext(ctx context.Context) (store *testing.Store) {
if md, ok := metadata.FromIncomingContext(ctx); ok {
store = MDToStore(md)
}
return
}
func MDToStore(md metadata.MD) *testing.Store {
data := make(map[string]string)
for key, val := range md {
data[key] = val[0]
}
store := testing.MapToStore(data)
return &store
}

View File

@ -0,0 +1,52 @@
/**
MIT License
Copyright (c) 2023 Rick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package remote
import (
context "context"
"testing"
atest "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/metadata"
)
func TestWithStoreContext(t *testing.T) {
ctx := WithStoreContext(context.Background(), sampleStore)
md, ok := metadata.FromOutgoingContext(ctx)
assert.True(t, ok)
assert.Equal(t, sampleStore, MDToStore(md))
}
func TestGetStoreFromContext(t *testing.T) {
ctx := metadata.NewIncomingContext(context.Background(), metadata.New(sampleStore.ToMap()))
assert.Equal(t, sampleStore, GetStoreFromContext(ctx))
}
var sampleStore = &atest.Store{
Properties: make(map[string]string),
}

View File

@ -3,6 +3,7 @@ package remote
import ( import (
"fmt" "fmt"
server "github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing" "github.com/linuxsuren/api-testing/pkg/testing"
) )
@ -27,7 +28,7 @@ func convertToGRPCTestSuite(suite *testing.TestSuite) (result *TestSuite) {
Name: suite.Name, Name: suite.Name,
Api: suite.API, Api: suite.API,
Param: mapToPair(suite.Param), Param: mapToPair(suite.Param),
Spec: &APISpec{ Spec: &server.APISpec{
Kind: suite.Spec.Kind, Kind: suite.Spec.Kind,
Url: suite.Spec.URL, Url: suite.Spec.URL,
}, },
@ -35,7 +36,7 @@ func convertToGRPCTestSuite(suite *testing.TestSuite) (result *TestSuite) {
return return
} }
func convertToNormalTestCase(testcase *TestCase) (result testing.TestCase) { func convertToNormalTestCase(testcase *server.TestCase) (result testing.TestCase) {
result = testing.TestCase{ result = testing.TestCase{
Name: testcase.Name, Name: testcase.Name,
} }
@ -62,10 +63,10 @@ func convertToNormalTestCase(testcase *TestCase) (result testing.TestCase) {
return return
} }
func convertToGRPCTestCase(testcase testing.TestCase) (result *TestCase) { func convertToGRPCTestCase(testcase testing.TestCase) (result *server.TestCase) {
result = &TestCase{ result = &server.TestCase{
Name: testcase.Name, Name: testcase.Name,
Request: &Request{ Request: &server.Request{
Api: testcase.Request.API, Api: testcase.Request.API,
Method: testcase.Request.Method, Method: testcase.Request.Method,
Body: testcase.Request.Body, Body: testcase.Request.Body,
@ -73,7 +74,7 @@ func convertToGRPCTestCase(testcase testing.TestCase) (result *TestCase) {
Query: mapToPair(testcase.Request.Query), Query: mapToPair(testcase.Request.Query),
Form: mapToPair(testcase.Request.Form), Form: mapToPair(testcase.Request.Form),
}, },
Response: &Response{ Response: &server.Response{
Body: testcase.Expect.Body, Body: testcase.Expect.Body,
StatusCode: int32(testcase.Expect.StatusCode), StatusCode: int32(testcase.Expect.StatusCode),
Schema: testcase.Expect.Schema, Schema: testcase.Expect.Schema,
@ -85,10 +86,10 @@ func convertToGRPCTestCase(testcase testing.TestCase) (result *TestCase) {
return return
} }
func mapToPair(data map[string]string) (pairs []*Pair) { func mapToPair(data map[string]string) (pairs []*server.Pair) {
pairs = make([]*Pair, 0) pairs = make([]*server.Pair, 0)
for k, v := range data { for k, v := range data {
pairs = append(pairs, &Pair{ pairs = append(pairs, &server.Pair{
Key: k, Key: k,
Value: v, Value: v,
}) })
@ -96,10 +97,10 @@ func mapToPair(data map[string]string) (pairs []*Pair) {
return return
} }
func mapInterToPair(data map[string]interface{}) (pairs []*Pair) { func mapInterToPair(data map[string]interface{}) (pairs []*server.Pair) {
pairs = make([]*Pair, 0) pairs = make([]*server.Pair, 0)
for k, v := range data { for k, v := range data {
pairs = append(pairs, &Pair{ pairs = append(pairs, &server.Pair{
Key: k, Key: k,
Value: fmt.Sprintf("%v", v), Value: fmt.Sprintf("%v", v),
}) })
@ -107,7 +108,7 @@ func mapInterToPair(data map[string]interface{}) (pairs []*Pair) {
return return
} }
func pairToMap(pairs []*Pair) (data map[string]string) { func pairToMap(pairs []*server.Pair) (data map[string]string) {
data = make(map[string]string) data = make(map[string]string)
for _, pair := range pairs { for _, pair := range pairs {
data[pair.Key] = pair.Value data[pair.Key] = pair.Value
@ -115,7 +116,7 @@ func pairToMap(pairs []*Pair) (data map[string]string) {
return return
} }
func pairToInterMap(pairs []*Pair) (data map[string]interface{}) { func pairToInterMap(pairs []*server.Pair) (data map[string]interface{}) {
data = make(map[string]interface{}) data = make(map[string]interface{})
for _, pair := range pairs { for _, pair := range pairs {
data[pair.Key] = pair.Value data[pair.Key] = pair.Value

View File

@ -3,6 +3,7 @@ package remote
import ( import (
"testing" "testing"
server "github.com/linuxsuren/api-testing/pkg/server"
atest "github.com/linuxsuren/api-testing/pkg/testing" atest "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -23,7 +24,7 @@ func TestConvert(t *testing.T) {
}, },
}, convertToNormalTestSuite(&TestSuite{ }, convertToNormalTestSuite(&TestSuite{
Param: defaultPairs, Param: defaultPairs,
Spec: &APISpec{ Spec: &server.APISpec{
Url: "/v1", Url: "/v1",
Kind: "http", Kind: "http",
}, },
@ -51,12 +52,12 @@ func TestConvert(t *testing.T) {
BodyFieldsExpect: defaultInterMap, BodyFieldsExpect: defaultInterMap,
Header: map[string]string{}, Header: map[string]string{},
}, },
}, convertToNormalTestCase(&TestCase{ }, convertToNormalTestCase(&server.TestCase{
Request: &Request{ Request: &server.Request{
Api: "/v1", Api: "/v1",
Header: defaultPairs, Header: defaultPairs,
}, },
Response: &Response{ Response: &server.Response{
BodyFieldsExpect: defaultPairs, BodyFieldsExpect: defaultPairs,
}, },
})) }))
@ -79,4 +80,4 @@ func TestConvert(t *testing.T) {
var defaultInterMap = map[string]interface{}{"foo": "bar"} var defaultInterMap = map[string]interface{}{"foo": "bar"}
var defaultMap map[string]string = map[string]string{"foo": "bar"} var defaultMap map[string]string = map[string]string{"foo": "bar"}
var defaultPairs []*Pair = []*Pair{{Key: "foo", Value: "bar"}} var defaultPairs []*server.Pair = []*server.Pair{{Key: "foo", Value: "bar"}}

View File

@ -3,22 +3,30 @@ package remote
import ( import (
context "context" context "context"
server "github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing" "github.com/linuxsuren/api-testing/pkg/testing"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
type gRPCLoader struct { type gRPCLoader struct {
address string store *testing.Store
client LoaderClient client LoaderClient
ctx context.Context
} }
// NewGRPCLoader creates a new gRPC loader func NewGRPCloaderFromStore() testing.StoreWriterFactory {
func NewGRPCLoader(address string) (writer testing.Writer, err error) { return &gRPCLoader{}
}
func (g *gRPCLoader) NewInstance(store testing.Store) (writer testing.Writer, err error) {
address := store.Kind.URL
var conn *grpc.ClientConn var conn *grpc.ClientConn
if conn, err = grpc.Dial(address, grpc.WithInsecure()); err == nil { if conn, err = grpc.Dial(address, grpc.WithInsecure()); err == nil {
writer = &gRPCLoader{ writer = &gRPCLoader{
address: address, store: &store,
client: NewLoaderClient(conn), ctx: WithStoreContext(context.Background(), &store),
client: NewLoaderClient(conn),
} }
} }
return return
@ -54,8 +62,8 @@ func (g *gRPCLoader) Reset() {
} }
func (g *gRPCLoader) ListTestCase(suite string) (testcases []testing.TestCase, err error) { func (g *gRPCLoader) ListTestCase(suite string) (testcases []testing.TestCase, err error) {
var testCases *TestCases var testCases *server.TestCases
testCases, err = g.client.ListTestCases(context.Background(), &TestSuite{ testCases, err = g.client.ListTestCases(g.ctx, &TestSuite{
Name: suite, Name: suite,
}) })
@ -70,8 +78,8 @@ func (g *gRPCLoader) ListTestCase(suite string) (testcases []testing.TestCase, e
return return
} }
func (g *gRPCLoader) GetTestCase(suite, name string) (testcase testing.TestCase, err error) { func (g *gRPCLoader) GetTestCase(suite, name string) (testcase testing.TestCase, err error) {
var result *TestCase var result *server.TestCase
result, err = g.client.GetTestCase(context.Background(), &TestCase{ result, err = g.client.GetTestCase(g.ctx, &server.TestCase{
Name: name, Name: name,
SuiteName: suite, SuiteName: suite,
}) })
@ -84,19 +92,19 @@ func (g *gRPCLoader) GetTestCase(suite, name string) (testcase testing.TestCase,
func (g *gRPCLoader) CreateTestCase(suite string, testcase testing.TestCase) (err error) { func (g *gRPCLoader) CreateTestCase(suite string, testcase testing.TestCase) (err error) {
payload := convertToGRPCTestCase(testcase) payload := convertToGRPCTestCase(testcase)
payload.SuiteName = suite payload.SuiteName = suite
_, err = g.client.CreateTestCase(context.Background(), payload) _, err = g.client.CreateTestCase(g.ctx, payload)
return return
} }
func (g *gRPCLoader) UpdateTestCase(suite string, testcase testing.TestCase) (err error) { func (g *gRPCLoader) UpdateTestCase(suite string, testcase testing.TestCase) (err error) {
payload := convertToGRPCTestCase(testcase) payload := convertToGRPCTestCase(testcase)
payload.SuiteName = suite payload.SuiteName = suite
_, err = g.client.UpdateTestCase(context.Background(), payload) _, err = g.client.UpdateTestCase(g.ctx, payload)
return return
} }
func (g *gRPCLoader) DeleteTestCase(suite, testcase string) (err error) { func (g *gRPCLoader) DeleteTestCase(suite, testcase string) (err error) {
_, err = g.client.DeleteTestCase(context.Background(), &TestCase{ _, err = g.client.DeleteTestCase(g.ctx, &server.TestCase{
Name: testcase, Name: testcase,
SuiteName: suite, SuiteName: suite,
}) })
@ -105,7 +113,7 @@ func (g *gRPCLoader) DeleteTestCase(suite, testcase string) (err error) {
func (g *gRPCLoader) ListTestSuite() (suites []testing.TestSuite, err error) { func (g *gRPCLoader) ListTestSuite() (suites []testing.TestSuite, err error) {
var items *TestSuites var items *TestSuites
items, err = g.client.ListTestSuite(context.Background(), &Empty{}) items, err = g.client.ListTestSuite(g.ctx, &server.Empty{})
if err == nil && items != nil { if err == nil && items != nil {
for _, item := range items.Data { for _, item := range items.Data {
suites = append(suites, *convertToNormalTestSuite(item)) suites = append(suites, *convertToNormalTestSuite(item))
@ -116,7 +124,7 @@ func (g *gRPCLoader) ListTestSuite() (suites []testing.TestSuite, err error) {
func (g *gRPCLoader) GetTestSuite(name string, full bool) (suite testing.TestSuite, err error) { func (g *gRPCLoader) GetTestSuite(name string, full bool) (suite testing.TestSuite, err error) {
var result *TestSuite var result *TestSuite
if result, err = g.client.GetTestSuite(context.Background(), if result, err = g.client.GetTestSuite(g.ctx,
&TestSuite{Name: name, Full: full}); err == nil { &TestSuite{Name: name, Full: full}); err == nil {
suite = testing.TestSuite{ suite = testing.TestSuite{
Name: result.Name, Name: result.Name,
@ -133,7 +141,7 @@ func (g *gRPCLoader) GetTestSuite(name string, full bool) (suite testing.TestSui
} }
func (g *gRPCLoader) CreateSuite(name, api string) (err error) { func (g *gRPCLoader) CreateSuite(name, api string) (err error) {
_, err = g.client.CreateTestSuite(context.Background(), &TestSuite{ _, err = g.client.CreateTestSuite(g.ctx, &TestSuite{
Name: name, Name: name,
Api: api, Api: api,
}) })
@ -142,7 +150,7 @@ func (g *gRPCLoader) CreateSuite(name, api string) (err error) {
func (g *gRPCLoader) GetSuite(name string) (reply *testing.TestSuite, _ string, err error) { func (g *gRPCLoader) GetSuite(name string) (reply *testing.TestSuite, _ string, err error) {
var suite *TestSuite var suite *TestSuite
if suite, err = g.client.GetTestSuite(context.Background(), if suite, err = g.client.GetTestSuite(g.ctx,
&TestSuite{Name: name}); err != nil { &TestSuite{Name: name}); err != nil {
return return
} }
@ -152,12 +160,12 @@ func (g *gRPCLoader) GetSuite(name string) (reply *testing.TestSuite, _ string,
} }
func (g *gRPCLoader) UpdateSuite(suite testing.TestSuite) (err error) { func (g *gRPCLoader) UpdateSuite(suite testing.TestSuite) (err error) {
_, err = g.client.UpdateTestSuite(context.Background(), convertToGRPCTestSuite(&suite)) _, err = g.client.UpdateTestSuite(g.ctx, convertToGRPCTestSuite(&suite))
return return
} }
func (g *gRPCLoader) DeleteSuite(name string) (err error) { func (g *gRPCLoader) DeleteSuite(name string) (err error) {
_, err = g.client.DeleteTestSuite(context.Background(), &TestSuite{ _, err = g.client.DeleteTestSuite(g.ctx, &TestSuite{
Name: name, Name: name,
}) })
return return

View File

@ -3,18 +3,25 @@ package remote
import ( import (
"testing" "testing"
atest "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestNewGRPCLoader(t *testing.T) { func TestNewGRPCLoader(t *testing.T) {
factory := NewGRPCloaderFromStore()
t.Run("invalid address", func(t *testing.T) { t.Run("invalid address", func(t *testing.T) {
writer, err := NewGRPCLoader("") writer, err := factory.NewInstance(atest.Store{})
assert.Error(t, err) assert.Error(t, err)
assert.Nil(t, writer) assert.Nil(t, writer)
}) })
t.Run("valid address", func(t *testing.T) { t.Run("valid address", func(t *testing.T) {
writer, err := NewGRPCLoader("localhost:8907") writer, err := factory.NewInstance(atest.Store{
Kind: atest.StoreKind{
URL: "localhost:7070",
},
})
assert.NoError(t, err) assert.NoError(t, err)
assert.NotNil(t, writer) assert.NotNil(t, writer)
@ -31,4 +38,8 @@ func TestNewGRPCLoader(t *testing.T) {
assert.Equal(t, 0, writer.GetCount()) assert.Equal(t, 0, writer.GetCount())
writer.Reset() writer.Reset()
}) })
t.Run("NewGRPCloaderFromStore", func(t *testing.T) {
assert.NotNil(t, NewGRPCloaderFromStore())
})
} }

View File

@ -7,6 +7,7 @@
package remote package remote
import ( import (
server "github.com/linuxsuren/api-testing/pkg/server"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect" reflect "reflect"
@ -72,12 +73,12 @@ type TestSuite struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Api string `protobuf:"bytes,2,opt,name=api,proto3" json:"api,omitempty"` Api string `protobuf:"bytes,2,opt,name=api,proto3" json:"api,omitempty"`
Param []*Pair `protobuf:"bytes,3,rep,name=param,proto3" json:"param,omitempty"` Param []*server.Pair `protobuf:"bytes,3,rep,name=param,proto3" json:"param,omitempty"`
Spec *APISpec `protobuf:"bytes,4,opt,name=spec,proto3" json:"spec,omitempty"` Spec *server.APISpec `protobuf:"bytes,4,opt,name=spec,proto3" json:"spec,omitempty"`
Items []*TestCase `protobuf:"bytes,5,rep,name=items,proto3" json:"items,omitempty"` Items []*server.TestCase `protobuf:"bytes,5,rep,name=items,proto3" json:"items,omitempty"`
Full bool `protobuf:"varint,6,opt,name=full,proto3" json:"full,omitempty"` Full bool `protobuf:"varint,6,opt,name=full,proto3" json:"full,omitempty"`
} }
func (x *TestSuite) Reset() { func (x *TestSuite) Reset() {
@ -126,21 +127,21 @@ func (x *TestSuite) GetApi() string {
return "" return ""
} }
func (x *TestSuite) GetParam() []*Pair { func (x *TestSuite) GetParam() []*server.Pair {
if x != nil { if x != nil {
return x.Param return x.Param
} }
return nil return nil
} }
func (x *TestSuite) GetSpec() *APISpec { func (x *TestSuite) GetSpec() *server.APISpec {
if x != nil { if x != nil {
return x.Spec return x.Spec
} }
return nil return nil
} }
func (x *TestSuite) GetItems() []*TestCase { func (x *TestSuite) GetItems() []*server.TestCase {
if x != nil { if x != nil {
return x.Items return x.Items
} }
@ -154,550 +155,68 @@ func (x *TestSuite) GetFull() bool {
return false return false
} }
type APISpec struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"`
Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
}
func (x *APISpec) Reset() {
*x = APISpec{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *APISpec) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*APISpec) ProtoMessage() {}
func (x *APISpec) ProtoReflect() protoreflect.Message {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use APISpec.ProtoReflect.Descriptor instead.
func (*APISpec) Descriptor() ([]byte, []int) {
return file_pkg_testing_remote_loader_proto_rawDescGZIP(), []int{2}
}
func (x *APISpec) GetKind() string {
if x != nil {
return x.Kind
}
return ""
}
func (x *APISpec) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
type TestCases struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data []*TestCase `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"`
}
func (x *TestCases) Reset() {
*x = TestCases{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *TestCases) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TestCases) ProtoMessage() {}
func (x *TestCases) ProtoReflect() protoreflect.Message {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TestCases.ProtoReflect.Descriptor instead.
func (*TestCases) Descriptor() ([]byte, []int) {
return file_pkg_testing_remote_loader_proto_rawDescGZIP(), []int{3}
}
func (x *TestCases) GetData() []*TestCase {
if x != nil {
return x.Data
}
return nil
}
type TestCase struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
SuiteName string `protobuf:"bytes,2,opt,name=suiteName,proto3" json:"suiteName,omitempty"`
Request *Request `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"`
Response *Response `protobuf:"bytes,4,opt,name=response,proto3" json:"response,omitempty"`
}
func (x *TestCase) Reset() {
*x = TestCase{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *TestCase) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TestCase) ProtoMessage() {}
func (x *TestCase) ProtoReflect() protoreflect.Message {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TestCase.ProtoReflect.Descriptor instead.
func (*TestCase) Descriptor() ([]byte, []int) {
return file_pkg_testing_remote_loader_proto_rawDescGZIP(), []int{4}
}
func (x *TestCase) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *TestCase) GetSuiteName() string {
if x != nil {
return x.SuiteName
}
return ""
}
func (x *TestCase) GetRequest() *Request {
if x != nil {
return x.Request
}
return nil
}
func (x *TestCase) GetResponse() *Response {
if x != nil {
return x.Response
}
return nil
}
type Request struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Api string `protobuf:"bytes,1,opt,name=api,proto3" json:"api,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
Header []*Pair `protobuf:"bytes,3,rep,name=header,proto3" json:"header,omitempty"`
Query []*Pair `protobuf:"bytes,4,rep,name=query,proto3" json:"query,omitempty"`
Form []*Pair `protobuf:"bytes,5,rep,name=form,proto3" json:"form,omitempty"`
Body string `protobuf:"bytes,6,opt,name=body,proto3" json:"body,omitempty"`
}
func (x *Request) Reset() {
*x = Request{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Request) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Request) ProtoMessage() {}
func (x *Request) ProtoReflect() protoreflect.Message {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Request.ProtoReflect.Descriptor instead.
func (*Request) Descriptor() ([]byte, []int) {
return file_pkg_testing_remote_loader_proto_rawDescGZIP(), []int{5}
}
func (x *Request) GetApi() string {
if x != nil {
return x.Api
}
return ""
}
func (x *Request) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (x *Request) GetHeader() []*Pair {
if x != nil {
return x.Header
}
return nil
}
func (x *Request) GetQuery() []*Pair {
if x != nil {
return x.Query
}
return nil
}
func (x *Request) GetForm() []*Pair {
if x != nil {
return x.Form
}
return nil
}
func (x *Request) GetBody() string {
if x != nil {
return x.Body
}
return ""
}
type Response struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StatusCode int32 `protobuf:"varint,1,opt,name=statusCode,proto3" json:"statusCode,omitempty"`
Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"`
Header []*Pair `protobuf:"bytes,3,rep,name=header,proto3" json:"header,omitempty"`
BodyFieldsExpect []*Pair `protobuf:"bytes,4,rep,name=bodyFieldsExpect,proto3" json:"bodyFieldsExpect,omitempty"`
Verify []string `protobuf:"bytes,5,rep,name=verify,proto3" json:"verify,omitempty"`
Schema string `protobuf:"bytes,6,opt,name=schema,proto3" json:"schema,omitempty"`
}
func (x *Response) Reset() {
*x = Response{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Response) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Response) ProtoMessage() {}
func (x *Response) ProtoReflect() protoreflect.Message {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Response.ProtoReflect.Descriptor instead.
func (*Response) Descriptor() ([]byte, []int) {
return file_pkg_testing_remote_loader_proto_rawDescGZIP(), []int{6}
}
func (x *Response) GetStatusCode() int32 {
if x != nil {
return x.StatusCode
}
return 0
}
func (x *Response) GetBody() string {
if x != nil {
return x.Body
}
return ""
}
func (x *Response) GetHeader() []*Pair {
if x != nil {
return x.Header
}
return nil
}
func (x *Response) GetBodyFieldsExpect() []*Pair {
if x != nil {
return x.BodyFieldsExpect
}
return nil
}
func (x *Response) GetVerify() []string {
if x != nil {
return x.Verify
}
return nil
}
func (x *Response) GetSchema() string {
if x != nil {
return x.Schema
}
return ""
}
type Pair struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
func (x *Pair) Reset() {
*x = Pair{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Pair) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Pair) ProtoMessage() {}
func (x *Pair) ProtoReflect() protoreflect.Message {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Pair.ProtoReflect.Descriptor instead.
func (*Pair) Descriptor() ([]byte, []int) {
return file_pkg_testing_remote_loader_proto_rawDescGZIP(), []int{7}
}
func (x *Pair) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *Pair) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
type Empty struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Empty) Reset() {
*x = Empty{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Empty) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Empty) ProtoMessage() {}
func (x *Empty) ProtoReflect() protoreflect.Message {
mi := &file_pkg_testing_remote_loader_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
func (*Empty) Descriptor() ([]byte, []int) {
return file_pkg_testing_remote_loader_proto_rawDescGZIP(), []int{8}
}
var File_pkg_testing_remote_loader_proto protoreflect.FileDescriptor var File_pkg_testing_remote_loader_proto protoreflect.FileDescriptor
var file_pkg_testing_remote_loader_proto_rawDesc = []byte{ var file_pkg_testing_remote_loader_proto_rawDesc = []byte{
0x0a, 0x1f, 0x70, 0x6b, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x0a, 0x1f, 0x70, 0x6b, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x72, 0x65,
0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x33, 0x0a, 0x0a, 0x54, 0x65, 0x73, 0x6f, 0x12, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x1a, 0x17, 0x70, 0x6b, 0x67, 0x2f, 0x73,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x74, 0x6f, 0x22, 0x33, 0x0a, 0x0a, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73,
0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xb6, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11,
0x01, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61,
0x70, 0x69, 0x12, 0x22, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52,
0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x23, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x41, 0x50,
0x49, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x26, 0x0a, 0x05, 0x69,
0x74, 0x65, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x65, 0x6d,
0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x52, 0x05, 0x69, 0x74,
0x65, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x75, 0x6c, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28,
0x08, 0x52, 0x04, 0x66, 0x75, 0x6c, 0x6c, 0x22, 0x2f, 0x0a, 0x07, 0x41, 0x50, 0x49, 0x53, 0x70,
0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x31, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74,
0x43, 0x61, 0x73, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73,
0x74, 0x43, 0x61, 0x73, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x95, 0x01, 0x0a, 0x08,
0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09,
0x73, 0x75, 0x69, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x73, 0x75, 0x69, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x72, 0x65,
0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65,
0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x10, 0x0a, 0x03, 0x61, 0x70, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x70,
0x69, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x24, 0x0a, 0x06, 0x68, 0x65, 0x61,
0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x65, 0x6d, 0x6f,
0x74, 0x65, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12,
0x22, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c,
0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x71, 0x75,
0x65, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52,
0x04, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x06, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xce, 0x01, 0x0a, 0x08, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74,
0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x24, 0x0a, 0x06, 0x68, 0x65,
0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x65, 0x6d,
0x6f, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
0x12, 0x38, 0x0a, 0x10, 0x62, 0x6f, 0x64, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x78,
0x70, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x65, 0x6d,
0x6f, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x10, 0x62, 0x6f, 0x64, 0x79, 0x46, 0x69,
0x65, 0x6c, 0x64, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65,
0x72, 0x69, 0x66, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x65, 0x72, 0x69,
0x66, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x2e, 0x0a, 0x04, 0x50, 0x61,
0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x32, 0xaf, 0x04, 0x0a, 0x06, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x34,
0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12,
0x0d, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12,
0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74,
0x65, 0x73, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xb6, 0x01, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74,
0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x0d, 0x2e, 0x72, 0x65, 0x6d, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 0x69,
0x6f, 0x74, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0c, 0x47, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x70, 0x69, 0x12, 0x22, 0x0a, 0x05, 0x70,
0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72,
0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x11, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x12,
0x23, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x41, 0x50, 0x49, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04,
0x73, 0x70, 0x65, 0x63, 0x12, 0x26, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x05, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73,
0x74, 0x43, 0x61, 0x73, 0x65, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04,
0x66, 0x75, 0x6c, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x66, 0x75, 0x6c, 0x6c,
0x32, 0xaf, 0x04, 0x0a, 0x06, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x0d, 0x4c,
0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x0d, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x72, 0x65,
0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22,
0x00, 0x12, 0x35, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53,
0x75, 0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65,
0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54,
0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74,
0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x11, 0x2e, 0x72, 0x65,
0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00,
0x12, 0x39, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75,
0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e,
0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0f, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x11,
0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74,
0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61,
0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x73, 0x65, 0x73, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73,
0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12, 0x35, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x73, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x0e, 0x43,
0x65, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x10, 0x2e,
0x75, 0x69, 0x74, 0x65, 0x1a, 0x0d, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x1a,
0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00,
0x74, 0x43, 0x61, 0x73, 0x65, 0x73, 0x12, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x12, 0x33, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12,
0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x11, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73,
0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x73, 0x22, 0x00, 0x12, 0x33, 0x65, 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43,
0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x61, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54,
0x12, 0x10, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x73, 0x65, 0x1a, 0x0d, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x79, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a,
0x73, 0x65, 0x12, 0x10, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12,
0x43, 0x61, 0x73, 0x65, 0x1a, 0x10, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73,
0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x10, 0x2e, 0x72, 0x65, 0x6d, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x1a, 0x10, 0x2e, 0x72, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x73, 0x75, 0x72, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2d,
0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x22, 0x00, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74,
0x12, 0x33, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x69, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x73, 0x65, 0x12, 0x10, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x6f, 0x33,
0x43, 0x61, 0x73, 0x65, 0x1a, 0x0d, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x73, 0x75, 0x72, 0x65, 0x6e, 0x2f, 0x61,
0x70, 0x69, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x74,
0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -712,56 +231,46 @@ func file_pkg_testing_remote_loader_proto_rawDescGZIP() []byte {
return file_pkg_testing_remote_loader_proto_rawDescData return file_pkg_testing_remote_loader_proto_rawDescData
} }
var file_pkg_testing_remote_loader_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_pkg_testing_remote_loader_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_pkg_testing_remote_loader_proto_goTypes = []interface{}{ var file_pkg_testing_remote_loader_proto_goTypes = []interface{}{
(*TestSuites)(nil), // 0: remote.TestSuites (*TestSuites)(nil), // 0: remote.TestSuites
(*TestSuite)(nil), // 1: remote.TestSuite (*TestSuite)(nil), // 1: remote.TestSuite
(*APISpec)(nil), // 2: remote.APISpec (*server.Pair)(nil), // 2: server.Pair
(*TestCases)(nil), // 3: remote.TestCases (*server.APISpec)(nil), // 3: server.APISpec
(*TestCase)(nil), // 4: remote.TestCase (*server.TestCase)(nil), // 4: server.TestCase
(*Request)(nil), // 5: remote.Request (*server.Empty)(nil), // 5: server.Empty
(*Response)(nil), // 6: remote.Response (*server.TestCases)(nil), // 6: server.TestCases
(*Pair)(nil), // 7: remote.Pair
(*Empty)(nil), // 8: remote.Empty
} }
var file_pkg_testing_remote_loader_proto_depIdxs = []int32{ var file_pkg_testing_remote_loader_proto_depIdxs = []int32{
1, // 0: remote.TestSuites.data:type_name -> remote.TestSuite 1, // 0: remote.TestSuites.data:type_name -> remote.TestSuite
7, // 1: remote.TestSuite.param:type_name -> remote.Pair 2, // 1: remote.TestSuite.param:type_name -> server.Pair
2, // 2: remote.TestSuite.spec:type_name -> remote.APISpec 3, // 2: remote.TestSuite.spec:type_name -> server.APISpec
4, // 3: remote.TestSuite.items:type_name -> remote.TestCase 4, // 3: remote.TestSuite.items:type_name -> server.TestCase
4, // 4: remote.TestCases.data:type_name -> remote.TestCase 5, // 4: remote.Loader.ListTestSuite:input_type -> server.Empty
5, // 5: remote.TestCase.request:type_name -> remote.Request 1, // 5: remote.Loader.CreateTestSuite:input_type -> remote.TestSuite
6, // 6: remote.TestCase.response:type_name -> remote.Response 1, // 6: remote.Loader.GetTestSuite:input_type -> remote.TestSuite
7, // 7: remote.Request.header:type_name -> remote.Pair 1, // 7: remote.Loader.UpdateTestSuite:input_type -> remote.TestSuite
7, // 8: remote.Request.query:type_name -> remote.Pair 1, // 8: remote.Loader.DeleteTestSuite:input_type -> remote.TestSuite
7, // 9: remote.Request.form:type_name -> remote.Pair 1, // 9: remote.Loader.ListTestCases:input_type -> remote.TestSuite
7, // 10: remote.Response.header:type_name -> remote.Pair 4, // 10: remote.Loader.CreateTestCase:input_type -> server.TestCase
7, // 11: remote.Response.bodyFieldsExpect:type_name -> remote.Pair 4, // 11: remote.Loader.GetTestCase:input_type -> server.TestCase
8, // 12: remote.Loader.ListTestSuite:input_type -> remote.Empty 4, // 12: remote.Loader.UpdateTestCase:input_type -> server.TestCase
1, // 13: remote.Loader.CreateTestSuite:input_type -> remote.TestSuite 4, // 13: remote.Loader.DeleteTestCase:input_type -> server.TestCase
1, // 14: remote.Loader.GetTestSuite:input_type -> remote.TestSuite 0, // 14: remote.Loader.ListTestSuite:output_type -> remote.TestSuites
1, // 15: remote.Loader.UpdateTestSuite:input_type -> remote.TestSuite 5, // 15: remote.Loader.CreateTestSuite:output_type -> server.Empty
1, // 16: remote.Loader.DeleteTestSuite:input_type -> remote.TestSuite 1, // 16: remote.Loader.GetTestSuite:output_type -> remote.TestSuite
1, // 17: remote.Loader.ListTestCases:input_type -> remote.TestSuite 1, // 17: remote.Loader.UpdateTestSuite:output_type -> remote.TestSuite
4, // 18: remote.Loader.CreateTestCase:input_type -> remote.TestCase 5, // 18: remote.Loader.DeleteTestSuite:output_type -> server.Empty
4, // 19: remote.Loader.GetTestCase:input_type -> remote.TestCase 6, // 19: remote.Loader.ListTestCases:output_type -> server.TestCases
4, // 20: remote.Loader.UpdateTestCase:input_type -> remote.TestCase 5, // 20: remote.Loader.CreateTestCase:output_type -> server.Empty
4, // 21: remote.Loader.DeleteTestCase:input_type -> remote.TestCase 4, // 21: remote.Loader.GetTestCase:output_type -> server.TestCase
0, // 22: remote.Loader.ListTestSuite:output_type -> remote.TestSuites 4, // 22: remote.Loader.UpdateTestCase:output_type -> server.TestCase
8, // 23: remote.Loader.CreateTestSuite:output_type -> remote.Empty 5, // 23: remote.Loader.DeleteTestCase:output_type -> server.Empty
1, // 24: remote.Loader.GetTestSuite:output_type -> remote.TestSuite 14, // [14:24] is the sub-list for method output_type
1, // 25: remote.Loader.UpdateTestSuite:output_type -> remote.TestSuite 4, // [4:14] is the sub-list for method input_type
8, // 26: remote.Loader.DeleteTestSuite:output_type -> remote.Empty 4, // [4:4] is the sub-list for extension type_name
3, // 27: remote.Loader.ListTestCases:output_type -> remote.TestCases 4, // [4:4] is the sub-list for extension extendee
8, // 28: remote.Loader.CreateTestCase:output_type -> remote.Empty 0, // [0:4] is the sub-list for field type_name
4, // 29: remote.Loader.GetTestCase:output_type -> remote.TestCase
4, // 30: remote.Loader.UpdateTestCase:output_type -> remote.TestCase
8, // 31: remote.Loader.DeleteTestCase:output_type -> remote.Empty
22, // [22:32] is the sub-list for method output_type
12, // [12:22] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
} }
func init() { file_pkg_testing_remote_loader_proto_init() } func init() { file_pkg_testing_remote_loader_proto_init() }
@ -794,90 +303,6 @@ func file_pkg_testing_remote_loader_proto_init() {
return nil return nil
} }
} }
file_pkg_testing_remote_loader_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*APISpec); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_testing_remote_loader_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TestCases); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_testing_remote_loader_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TestCase); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_testing_remote_loader_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Request); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_testing_remote_loader_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Response); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_testing_remote_loader_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Pair); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_testing_remote_loader_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Empty); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
@ -885,7 +310,7 @@ func file_pkg_testing_remote_loader_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pkg_testing_remote_loader_proto_rawDesc, RawDescriptor: file_pkg_testing_remote_loader_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 9, NumMessages: 2,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

View File

@ -4,18 +4,20 @@ option go_package = "github.com/linuxsuren/api-testing/pkg/testing/remote";
package remote; package remote;
import "pkg/server/server.proto";
service Loader { service Loader {
rpc ListTestSuite(Empty) returns (TestSuites) {} rpc ListTestSuite(server.Empty) returns (TestSuites) {}
rpc CreateTestSuite(TestSuite) returns (Empty) {} rpc CreateTestSuite(TestSuite) returns (server.Empty) {}
rpc GetTestSuite(TestSuite) returns (TestSuite) {} rpc GetTestSuite(TestSuite) returns (TestSuite) {}
rpc UpdateTestSuite(TestSuite) returns (TestSuite) {} rpc UpdateTestSuite(TestSuite) returns (TestSuite) {}
rpc DeleteTestSuite(TestSuite) returns (Empty) {} rpc DeleteTestSuite(TestSuite) returns (server.Empty) {}
rpc ListTestCases(TestSuite) returns (TestCases) {} rpc ListTestCases(TestSuite) returns (server.TestCases) {}
rpc CreateTestCase(TestCase) returns (Empty) {} rpc CreateTestCase(server.TestCase) returns (server.Empty) {}
rpc GetTestCase(TestCase) returns (TestCase) {} rpc GetTestCase(server.TestCase) returns (server.TestCase) {}
rpc UpdateTestCase(TestCase) returns (TestCase) {} rpc UpdateTestCase(server.TestCase) returns (server.TestCase) {}
rpc DeleteTestCase(TestCase) returns (Empty) {} rpc DeleteTestCase(server.TestCase) returns (server.Empty) {}
} }
message TestSuites { message TestSuites {
@ -25,50 +27,8 @@ message TestSuites {
message TestSuite { message TestSuite {
string name = 1; string name = 1;
string api = 2; string api = 2;
repeated Pair param = 3; repeated server.Pair param = 3;
APISpec spec = 4; server.APISpec spec = 4;
repeated TestCase items = 5; repeated server.TestCase items = 5;
bool full = 6; bool full = 6;
} }
message APISpec {
string kind = 1;
string url = 2;
}
message TestCases {
repeated TestCase data = 1;
}
message TestCase {
string name = 1;
string suiteName = 2;
Request request = 3;
Response response = 4;
}
message Request {
string api = 1;
string method = 2;
repeated Pair header = 3;
repeated Pair query = 4;
repeated Pair form = 5;
string body = 6;
}
message Response {
int32 statusCode = 1;
string body = 2;
repeated Pair header = 3;
repeated Pair bodyFieldsExpect = 4;
repeated string verify = 5;
string schema = 6;
}
message Pair {
string key = 1;
string value = 2;
}
message Empty {
}

View File

@ -8,6 +8,7 @@ package remote
import ( import (
context "context" context "context"
server "github.com/linuxsuren/api-testing/pkg/server"
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes" codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"
@ -22,16 +23,16 @@ const _ = grpc.SupportPackageIsVersion7
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type LoaderClient interface { type LoaderClient interface {
ListTestSuite(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TestSuites, error) ListTestSuite(ctx context.Context, in *server.Empty, opts ...grpc.CallOption) (*TestSuites, error)
CreateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*Empty, error) CreateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*server.Empty, error)
GetTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*TestSuite, error) GetTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*TestSuite, error)
UpdateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*TestSuite, error) UpdateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*TestSuite, error)
DeleteTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*Empty, error) DeleteTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*server.Empty, error)
ListTestCases(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*TestCases, error) ListTestCases(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*server.TestCases, error)
CreateTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*Empty, error) CreateTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.Empty, error)
GetTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*TestCase, error) GetTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.TestCase, error)
UpdateTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*TestCase, error) UpdateTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.TestCase, error)
DeleteTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*Empty, error) DeleteTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.Empty, error)
} }
type loaderClient struct { type loaderClient struct {
@ -42,7 +43,7 @@ func NewLoaderClient(cc grpc.ClientConnInterface) LoaderClient {
return &loaderClient{cc} return &loaderClient{cc}
} }
func (c *loaderClient) ListTestSuite(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TestSuites, error) { func (c *loaderClient) ListTestSuite(ctx context.Context, in *server.Empty, opts ...grpc.CallOption) (*TestSuites, error) {
out := new(TestSuites) out := new(TestSuites)
err := c.cc.Invoke(ctx, "/remote.Loader/ListTestSuite", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/ListTestSuite", in, out, opts...)
if err != nil { if err != nil {
@ -51,8 +52,8 @@ func (c *loaderClient) ListTestSuite(ctx context.Context, in *Empty, opts ...grp
return out, nil return out, nil
} }
func (c *loaderClient) CreateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*Empty, error) { func (c *loaderClient) CreateTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*server.Empty, error) {
out := new(Empty) out := new(server.Empty)
err := c.cc.Invoke(ctx, "/remote.Loader/CreateTestSuite", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/CreateTestSuite", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -78,8 +79,8 @@ func (c *loaderClient) UpdateTestSuite(ctx context.Context, in *TestSuite, opts
return out, nil return out, nil
} }
func (c *loaderClient) DeleteTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*Empty, error) { func (c *loaderClient) DeleteTestSuite(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*server.Empty, error) {
out := new(Empty) out := new(server.Empty)
err := c.cc.Invoke(ctx, "/remote.Loader/DeleteTestSuite", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/DeleteTestSuite", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -87,8 +88,8 @@ func (c *loaderClient) DeleteTestSuite(ctx context.Context, in *TestSuite, opts
return out, nil return out, nil
} }
func (c *loaderClient) ListTestCases(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*TestCases, error) { func (c *loaderClient) ListTestCases(ctx context.Context, in *TestSuite, opts ...grpc.CallOption) (*server.TestCases, error) {
out := new(TestCases) out := new(server.TestCases)
err := c.cc.Invoke(ctx, "/remote.Loader/ListTestCases", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/ListTestCases", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -96,8 +97,8 @@ func (c *loaderClient) ListTestCases(ctx context.Context, in *TestSuite, opts ..
return out, nil return out, nil
} }
func (c *loaderClient) CreateTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*Empty, error) { func (c *loaderClient) CreateTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.Empty, error) {
out := new(Empty) out := new(server.Empty)
err := c.cc.Invoke(ctx, "/remote.Loader/CreateTestCase", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/CreateTestCase", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -105,8 +106,8 @@ func (c *loaderClient) CreateTestCase(ctx context.Context, in *TestCase, opts ..
return out, nil return out, nil
} }
func (c *loaderClient) GetTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*TestCase, error) { func (c *loaderClient) GetTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.TestCase, error) {
out := new(TestCase) out := new(server.TestCase)
err := c.cc.Invoke(ctx, "/remote.Loader/GetTestCase", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/GetTestCase", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -114,8 +115,8 @@ func (c *loaderClient) GetTestCase(ctx context.Context, in *TestCase, opts ...gr
return out, nil return out, nil
} }
func (c *loaderClient) UpdateTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*TestCase, error) { func (c *loaderClient) UpdateTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.TestCase, error) {
out := new(TestCase) out := new(server.TestCase)
err := c.cc.Invoke(ctx, "/remote.Loader/UpdateTestCase", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/UpdateTestCase", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -123,8 +124,8 @@ func (c *loaderClient) UpdateTestCase(ctx context.Context, in *TestCase, opts ..
return out, nil return out, nil
} }
func (c *loaderClient) DeleteTestCase(ctx context.Context, in *TestCase, opts ...grpc.CallOption) (*Empty, error) { func (c *loaderClient) DeleteTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.Empty, error) {
out := new(Empty) out := new(server.Empty)
err := c.cc.Invoke(ctx, "/remote.Loader/DeleteTestCase", in, out, opts...) err := c.cc.Invoke(ctx, "/remote.Loader/DeleteTestCase", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -136,16 +137,16 @@ func (c *loaderClient) DeleteTestCase(ctx context.Context, in *TestCase, opts ..
// All implementations must embed UnimplementedLoaderServer // All implementations must embed UnimplementedLoaderServer
// for forward compatibility // for forward compatibility
type LoaderServer interface { type LoaderServer interface {
ListTestSuite(context.Context, *Empty) (*TestSuites, error) ListTestSuite(context.Context, *server.Empty) (*TestSuites, error)
CreateTestSuite(context.Context, *TestSuite) (*Empty, error) CreateTestSuite(context.Context, *TestSuite) (*server.Empty, error)
GetTestSuite(context.Context, *TestSuite) (*TestSuite, error) GetTestSuite(context.Context, *TestSuite) (*TestSuite, error)
UpdateTestSuite(context.Context, *TestSuite) (*TestSuite, error) UpdateTestSuite(context.Context, *TestSuite) (*TestSuite, error)
DeleteTestSuite(context.Context, *TestSuite) (*Empty, error) DeleteTestSuite(context.Context, *TestSuite) (*server.Empty, error)
ListTestCases(context.Context, *TestSuite) (*TestCases, error) ListTestCases(context.Context, *TestSuite) (*server.TestCases, error)
CreateTestCase(context.Context, *TestCase) (*Empty, error) CreateTestCase(context.Context, *server.TestCase) (*server.Empty, error)
GetTestCase(context.Context, *TestCase) (*TestCase, error) GetTestCase(context.Context, *server.TestCase) (*server.TestCase, error)
UpdateTestCase(context.Context, *TestCase) (*TestCase, error) UpdateTestCase(context.Context, *server.TestCase) (*server.TestCase, error)
DeleteTestCase(context.Context, *TestCase) (*Empty, error) DeleteTestCase(context.Context, *server.TestCase) (*server.Empty, error)
mustEmbedUnimplementedLoaderServer() mustEmbedUnimplementedLoaderServer()
} }
@ -153,10 +154,10 @@ type LoaderServer interface {
type UnimplementedLoaderServer struct { type UnimplementedLoaderServer struct {
} }
func (UnimplementedLoaderServer) ListTestSuite(context.Context, *Empty) (*TestSuites, error) { func (UnimplementedLoaderServer) ListTestSuite(context.Context, *server.Empty) (*TestSuites, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListTestSuite not implemented") return nil, status.Errorf(codes.Unimplemented, "method ListTestSuite not implemented")
} }
func (UnimplementedLoaderServer) CreateTestSuite(context.Context, *TestSuite) (*Empty, error) { func (UnimplementedLoaderServer) CreateTestSuite(context.Context, *TestSuite) (*server.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateTestSuite not implemented") return nil, status.Errorf(codes.Unimplemented, "method CreateTestSuite not implemented")
} }
func (UnimplementedLoaderServer) GetTestSuite(context.Context, *TestSuite) (*TestSuite, error) { func (UnimplementedLoaderServer) GetTestSuite(context.Context, *TestSuite) (*TestSuite, error) {
@ -165,22 +166,22 @@ func (UnimplementedLoaderServer) GetTestSuite(context.Context, *TestSuite) (*Tes
func (UnimplementedLoaderServer) UpdateTestSuite(context.Context, *TestSuite) (*TestSuite, error) { func (UnimplementedLoaderServer) UpdateTestSuite(context.Context, *TestSuite) (*TestSuite, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateTestSuite not implemented") return nil, status.Errorf(codes.Unimplemented, "method UpdateTestSuite not implemented")
} }
func (UnimplementedLoaderServer) DeleteTestSuite(context.Context, *TestSuite) (*Empty, error) { func (UnimplementedLoaderServer) DeleteTestSuite(context.Context, *TestSuite) (*server.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteTestSuite not implemented") return nil, status.Errorf(codes.Unimplemented, "method DeleteTestSuite not implemented")
} }
func (UnimplementedLoaderServer) ListTestCases(context.Context, *TestSuite) (*TestCases, error) { func (UnimplementedLoaderServer) ListTestCases(context.Context, *TestSuite) (*server.TestCases, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListTestCases not implemented") return nil, status.Errorf(codes.Unimplemented, "method ListTestCases not implemented")
} }
func (UnimplementedLoaderServer) CreateTestCase(context.Context, *TestCase) (*Empty, error) { func (UnimplementedLoaderServer) CreateTestCase(context.Context, *server.TestCase) (*server.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateTestCase not implemented") return nil, status.Errorf(codes.Unimplemented, "method CreateTestCase not implemented")
} }
func (UnimplementedLoaderServer) GetTestCase(context.Context, *TestCase) (*TestCase, error) { func (UnimplementedLoaderServer) GetTestCase(context.Context, *server.TestCase) (*server.TestCase, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetTestCase not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetTestCase not implemented")
} }
func (UnimplementedLoaderServer) UpdateTestCase(context.Context, *TestCase) (*TestCase, error) { func (UnimplementedLoaderServer) UpdateTestCase(context.Context, *server.TestCase) (*server.TestCase, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateTestCase not implemented") return nil, status.Errorf(codes.Unimplemented, "method UpdateTestCase not implemented")
} }
func (UnimplementedLoaderServer) DeleteTestCase(context.Context, *TestCase) (*Empty, error) { func (UnimplementedLoaderServer) DeleteTestCase(context.Context, *server.TestCase) (*server.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteTestCase not implemented") return nil, status.Errorf(codes.Unimplemented, "method DeleteTestCase not implemented")
} }
func (UnimplementedLoaderServer) mustEmbedUnimplementedLoaderServer() {} func (UnimplementedLoaderServer) mustEmbedUnimplementedLoaderServer() {}
@ -197,7 +198,7 @@ func RegisterLoaderServer(s grpc.ServiceRegistrar, srv LoaderServer) {
} }
func _Loader_ListTestSuite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Loader_ListTestSuite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty) in := new(server.Empty)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@ -209,7 +210,7 @@ func _Loader_ListTestSuite_Handler(srv interface{}, ctx context.Context, dec fun
FullMethod: "/remote.Loader/ListTestSuite", FullMethod: "/remote.Loader/ListTestSuite",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LoaderServer).ListTestSuite(ctx, req.(*Empty)) return srv.(LoaderServer).ListTestSuite(ctx, req.(*server.Empty))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
@ -305,7 +306,7 @@ func _Loader_ListTestCases_Handler(srv interface{}, ctx context.Context, dec fun
} }
func _Loader_CreateTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Loader_CreateTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestCase) in := new(server.TestCase)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@ -317,13 +318,13 @@ func _Loader_CreateTestCase_Handler(srv interface{}, ctx context.Context, dec fu
FullMethod: "/remote.Loader/CreateTestCase", FullMethod: "/remote.Loader/CreateTestCase",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LoaderServer).CreateTestCase(ctx, req.(*TestCase)) return srv.(LoaderServer).CreateTestCase(ctx, req.(*server.TestCase))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Loader_GetTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Loader_GetTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestCase) in := new(server.TestCase)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@ -335,13 +336,13 @@ func _Loader_GetTestCase_Handler(srv interface{}, ctx context.Context, dec func(
FullMethod: "/remote.Loader/GetTestCase", FullMethod: "/remote.Loader/GetTestCase",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LoaderServer).GetTestCase(ctx, req.(*TestCase)) return srv.(LoaderServer).GetTestCase(ctx, req.(*server.TestCase))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Loader_UpdateTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Loader_UpdateTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestCase) in := new(server.TestCase)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@ -353,13 +354,13 @@ func _Loader_UpdateTestCase_Handler(srv interface{}, ctx context.Context, dec fu
FullMethod: "/remote.Loader/UpdateTestCase", FullMethod: "/remote.Loader/UpdateTestCase",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LoaderServer).UpdateTestCase(ctx, req.(*TestCase)) return srv.(LoaderServer).UpdateTestCase(ctx, req.(*server.TestCase))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Loader_DeleteTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Loader_DeleteTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestCase) in := new(server.TestCase)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@ -371,7 +372,7 @@ func _Loader_DeleteTestCase_Handler(srv interface{}, ctx context.Context, dec fu
FullMethod: "/remote.Loader/DeleteTestCase", FullMethod: "/remote.Loader/DeleteTestCase",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LoaderServer).DeleteTestCase(ctx, req.(*TestCase)) return srv.(LoaderServer).DeleteTestCase(ctx, req.(*server.TestCase))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }

145
pkg/testing/store.go Normal file
View File

@ -0,0 +1,145 @@
/**
MIT License
Copyright (c) 2023 Rick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package testing
import (
"os"
"path"
"strings"
"gopkg.in/yaml.v3"
)
type Store struct {
Name string
Kind StoreKind
Description string
URL string
Username string
Password string
Properties map[string]string
}
func (s *Store) ToMap() (result map[string]string) {
result = map[string]string{
"name": s.Name,
"kind": s.Kind.Name,
"kind.url": s.Kind.URL,
"description": s.Description,
"url": s.URL,
"username": s.Username,
"password": s.Password,
}
for key, val := range s.Properties {
result["pro."+key] = val
}
return
}
func MapToStore(data map[string]string) (store Store) {
store = Store{
Name: data["name"],
Description: data["description"],
URL: data["url"],
Username: data["username"],
Password: data["password"],
Kind: StoreKind{
Name: data["kind"],
URL: data["kind.url"],
},
Properties: make(map[string]string),
}
for key, val := range data {
if strings.HasPrefix(key, "pro.") {
store.Properties[strings.TrimPrefix(key, "pro.")] = val
}
}
return
}
// StoreKind represents a gRPC-based store
type StoreKind struct {
Name string
URL string
}
type StoreGetterAndSetter interface {
GetStores() (stores []Store, err error)
GetStore(name string) (store *Store, err error)
DeleteStore(name string) (err error)
UpdateStore(store Store) (err error)
GetStoreKinds() (kinds []StoreKind, err error)
}
type StoreWriterFactory interface {
NewInstance(store Store) (writer Writer, err error)
}
type storeFactory struct {
configDir string
}
func NewStoreFactory(configDir string) StoreGetterAndSetter {
return &storeFactory{
configDir: configDir,
}
}
func (s *storeFactory) GetStores() (stores []Store, err error) {
var data []byte
if data, err = os.ReadFile(path.Join(s.configDir, "stores.yaml")); err == nil {
err = yaml.Unmarshal(data, &stores)
} else {
err = nil
}
stores = append(stores, Store{Name: "local"})
return
}
func (s *storeFactory) GetStore(name string) (store *Store, err error) {
var stores []Store
if stores, err = s.GetStores(); err == nil {
for i := range stores {
item := stores[i]
if item.Name == name {
store = &item
}
}
}
return
}
func (s *storeFactory) DeleteStore(name string) (err error) {
return
}
func (s *storeFactory) UpdateStore(store Store) (err error) {
return
}
func (s *storeFactory) GetStoreKinds() (kinds []StoreKind, err error) {
return
}

128
pkg/testing/store_test.go Normal file
View File

@ -0,0 +1,128 @@
/**
MIT License
Copyright (c) 2023 Rick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package testing
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestStoreConvert(t *testing.T) {
t.Run("ToMap", func(t *testing.T) {
store := sampleStore
assert.Equal(t, sampleStoreMap, store.ToMap())
})
t.Run("MapToStore", func(t *testing.T) {
store := MapToStore(sampleStoreMap)
assert.Equal(t, sampleStore, &store)
})
t.Run("NewStoreFactory", func(t *testing.T) {
assert.NotNil(t, NewStoreFactory(""))
})
}
func TestStoreFactory(t *testing.T) {
factory := NewStoreFactory("testdata")
assert.NotNil(t, factory)
t.Run("GetStoreKinds", func(t *testing.T) {
_, err := factory.GetStoreKinds()
assert.NoError(t, err)
})
t.Run("GetStore", func(t *testing.T) {
store, err := factory.GetStore("db")
assert.Nil(t, err)
assert.Equal(t, &Store{
Name: "db",
Kind: StoreKind{
Name: "database",
URL: "localhost:7071",
},
URL: "localhost:4000",
Username: "root",
Properties: map[string]string{
"database": "test",
},
}, store)
})
t.Run("GetAllStores", func(t *testing.T) {
stores, err := factory.GetStores()
assert.Nil(t, err)
assert.Equal(t, 2, len(stores))
assert.Equal(t, "local", stores[1].Name)
})
t.Run("DeleteStore", func(t *testing.T) {
err := factory.DeleteStore("")
assert.NoError(t, err)
})
t.Run("UpdateStore", func(t *testing.T) {
err := factory.UpdateStore(Store{})
assert.NoError(t, err)
})
t.Run("no stores.yaml found", func(t *testing.T) {
factory := NewStoreFactory("testdata-fake")
stores, err := factory.GetStores()
assert.NoError(t, err)
assert.Equal(t, []Store{{
Name: "local",
}}, stores)
})
}
var sampleStoreMap = map[string]string{
"name": "test",
"url": fooURL,
"kind.url": fooURL,
"kind": "test",
"description": "desc",
"username": "user",
"password": "pass",
"pro.key": "val",
}
var sampleStore = &Store{
Name: "test",
Kind: StoreKind{
Name: "test",
URL: fooURL,
},
URL: fooURL,
Description: "desc",
Username: "user",
Password: "pass",
Properties: map[string]string{
"key": "val",
},
}
const fooURL = "http://foo"

8
pkg/testing/testdata/stores.yaml vendored Normal file
View File

@ -0,0 +1,8 @@
- name: db
kind:
name: database
url: localhost:7071
url: localhost:4000
username: root
properties:
database: test