feat: support verify the store (#157)

This commit is contained in:
Rick 2023-08-03 17:06:38 +08:00 committed by GitHub
parent 96f9e7d5ec
commit 46552d1c15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 889 additions and 425 deletions

View File

@ -13,7 +13,7 @@ items:
api: /GetTestSuite
method: POST
body: |
{"name": "texst"}
{"name": "test"}
expect:
bodyFieldsExpect:
name: ""
@ -23,7 +23,7 @@ items:
api: /GetTestCase
method: POST
body: |
{"name": "texst"}
{"name": "test"}
expect:
statusCode: 500
bodyFieldsExpect:
@ -33,7 +33,7 @@ items:
api: /GetTestCase
method: POST
body: |
{"name": "texst"}
{"name": "test"}
expect:
statusCode: 500
bodyFieldsExpect:
@ -42,3 +42,28 @@ items:
request:
api: /PopularHeaders
method: POST
- name: list-code-generators
request:
api: /ListCodeGenerator
method: POST
expect:
verify:
- len(data) == 1
- name: list-stores
request:
api: /GetStores
method: POST
expect:
verify:
- len(data) >= 1
- name: query-funcs
request:
api: /FunctionsQuery
method: POST
expect:
verify:
- len(data) == 1
- name: version
request:
api: /GetVersion
method: POST

View File

@ -30,6 +30,7 @@ jobs:
make build copy
sudo atest service install
sudo atest service restart
sudo atest service status
atest run -p .github/testing/core.yaml
Build:

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Rick
Copyright (c) 2023 API Testing Authors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -126,7 +126,9 @@ function loadStores() {
data.value = [] as Tree[]
d.data.forEach((item: any) => {
loadTestSuites(item.name)
if (item.ready) {
loadTestSuites(item.name)
}
})
})
}

View File

@ -23,6 +23,8 @@ const suite = ref({
}
} as Suite)
function load() {
if (!props.name || props.store === "") return
const requestOptions = {
method: 'POST',
headers: {

View File

@ -0,0 +1,71 @@
/**
MIT License
Copyright (c) 2023 API Testing Authors.
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 cmd
import (
"fmt"
"net"
"github.com/linuxsuren/api-testing/extensions/store-orm/pkg"
"github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/spf13/cobra"
"google.golang.org/grpc"
)
func NewRootCommand() (c *cobra.Command) {
opt := &option{}
c = &cobra.Command{
Use: "store-orm",
Short: "Storage extension of api-testing",
RunE: opt.runE,
}
flags := c.Flags()
flags.IntVarP(&opt.port, "port", "p", 7071, "The port of gRPC server")
return
}
func (o *option) runE(cmd *cobra.Command, args []string) (err error) {
removeServer := pkg.NewRemoteServer()
var lis net.Listener
lis, err = net.Listen("tcp", fmt.Sprintf(":%d", o.port))
if err != nil {
return
}
gRPCServer := grpc.NewServer()
remote.RegisterLoaderServer(gRPCServer, removeServer)
go func() {
<-cmd.Context().Done()
gRPCServer.Stop()
}()
cmd.Println("ORM storage extension is running at port", o.port)
err = gRPCServer.Serve(lis)
return
}
type option struct {
port int
}

View File

@ -0,0 +1,55 @@
/**
MIT License
Copyright (c) 2023 API Testing Authors.
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 cmd
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestRootCommand(t *testing.T) {
t.Run("invalid port", func(t *testing.T) {
c := NewRootCommand()
assert.Equal(t, "store-orm", c.Use)
c.SetArgs([]string{"--port", "abc"})
err := c.Execute()
assert.Error(t, err)
})
t.Run("a random port", func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
c := NewRootCommand()
c.SetContext(ctx)
c.SetArgs([]string{"--port", "0"})
err := c.Execute()
assert.NoError(t, err)
})
}

View File

@ -1,258 +1,13 @@
package main
import (
"context"
"errors"
"fmt"
"net"
"os"
"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/spf13/cobra"
"google.golang.org/grpc"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/linuxsuren/api-testing/extensions/store-orm/cmd"
)
func main() {
opt := &option{}
cmd := &cobra.Command{
Use: "store-orm",
Short: "Storage extension of api-testing",
RunE: opt.runE,
}
flags := cmd.Flags()
flags.IntVarP(&opt.port, "port", "p", 7071, "The port of gRPC server")
if err := cmd.Execute(); err != nil {
if err := cmd.NewRootCommand().Execute(); err != nil {
os.Exit(1)
}
}
func (o *option) runE(cmd *cobra.Command, args []string) (err error) {
var removeServer remote.LoaderServer
if removeServer, err = NewRemoteServer(); err != nil {
return
}
var lis net.Listener
lis, err = net.Listen("tcp", fmt.Sprintf(":%d", o.port))
if err != nil {
return
}
gRPCServer := grpc.NewServer()
remote.RegisterLoaderServer(gRPCServer, removeServer)
err = gRPCServer.Serve(lis)
return
}
type option struct {
port int
}
type dbserver struct {
remote.UnimplementedLoaderServer
}
// NewRemoteServer creates a remote server instance
func NewRemoteServer() (s remote.LoaderServer, err error) {
s = &dbserver{}
return
}
func createDB(user, address, database string) (db *gorm.DB, err error) {
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{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
err = fmt.Errorf("failed to connect to %s, %v", dsn, err)
return
}
db.AutoMigrate(&pkg.TestCase{})
db.AutoMigrate(&pkg.TestSuite{})
return
}
var dbCache map[string]*gorm.DB = make(map[string]*gorm.DB)
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{}
for i := range items {
suites.Data = append(suites.Data, pkg.ConvertToGRPCTestSuite(items[i]))
}
return
}
func (s *dbserver) CreateTestSuite(ctx context.Context, testSuite *remote.TestSuite) (reply *server.Empty, err error) {
reply = &server.Empty{}
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Create(pkg.ConvertToDBTestSuite(testSuite))
return
}
const nameQuery = `name = ?`
func (s *dbserver) GetTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) {
query := &pkg.TestSuite{}
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&query, nameQuery, suite.Name)
reply = pkg.ConvertToGRPCTestSuite(query)
if suite.Full {
var testcases *server.TestCases
if testcases, err = s.ListTestCases(ctx, &remote.TestSuite{
Name: suite.Name,
}); err == nil && testcases != nil {
reply.Items = testcases.Data
}
}
return
}
func (s *dbserver) UpdateTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) {
reply = &remote.TestSuite{}
input := pkg.ConvertToDBTestSuite(suite)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testSuiteIdentity(db, input).Updates(input)
return
}
func testSuiteIdentity(db *gorm.DB, suite *pkg.TestSuite) *gorm.DB {
return db.Model(suite).Where(nameQuery, suite.Name)
}
func (s *dbserver) DeleteTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *server.Empty, err error) {
reply = &server.Empty{}
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Delete(suite, nameQuery, suite.Name)
return
}
func (s *dbserver) ListTestCases(ctx context.Context, suite *remote.TestSuite) (result *server.TestCases, err error) {
items := make([]*pkg.TestCase, 0)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&items, "suite_name = ?", suite.Name)
result = &server.TestCases{}
for i := range items {
result.Data = append(result.Data, pkg.ConvertToRemoteTestCase(items[i]))
}
return
}
func (s *dbserver) CreateTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.Empty, err error) {
payload := pkg.ConverToDBTestCase(testcase)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
reply = &server.Empty{}
db.Create(&payload)
return
}
func (s *dbserver) GetTestCase(ctx context.Context, testcase *server.TestCase) (result *server.TestCase, err error) {
item := &pkg.TestCase{}
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)
return
}
func (s *dbserver) UpdateTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.TestCase, err error) {
reply = &server.TestCase{}
input := pkg.ConverToDBTestCase(testcase)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testCaseIdentiy(db, input).Updates(input)
data := make(map[string]interface{})
if input.ExpectBody == "" {
data["expect_body"] = ""
}
if input.ExpectSchema == "" {
data["expect_schema"] = ""
}
if len(data) > 0 {
testCaseIdentiy(db, input).Updates(data)
}
return
}
func (s *dbserver) DeleteTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.Empty, err error) {
reply = &server.Empty{}
input := pkg.ConverToDBTestCase(testcase)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testCaseIdentiy(db, input).Delete(input)
return
}
func testCaseIdentiy(db *gorm.DB, testcase *pkg.TestCase) *gorm.DB {
return db.Model(testcase).Where(fmt.Sprintf("suite_name = '%s' AND name = '%s'", testcase.SuiteName, testcase.Name))
}

View File

@ -0,0 +1,251 @@
/**
MIT License
Copyright (c) 2023 API Testing Authors.
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 pkg
import (
"context"
"errors"
"fmt"
"github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/linuxsuren/api-testing/pkg/util"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type dbserver struct {
remote.UnimplementedLoaderServer
}
// NewRemoteServer creates a remote server instance
func NewRemoteServer() (s remote.LoaderServer) {
s = &dbserver{}
return
}
func createDB(user, address, database string) (db *gorm.DB, err error) {
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{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
err = fmt.Errorf("failed to connect to %s, %v", dsn, err)
return
}
db.AutoMigrate(&TestCase{})
db.AutoMigrate(&TestSuite{})
return
}
var dbCache map[string]*gorm.DB = make(map[string]*gorm.DB)
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
}
}
if db, err = createDB(store.Username, store.URL, database); err == nil {
dbCache[store.Name] = db
}
}
return
}
func (s *dbserver) ListTestSuite(ctx context.Context, _ *server.Empty) (suites *remote.TestSuites, err error) {
items := make([]*TestSuite, 0)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&items)
suites = &remote.TestSuites{}
for i := range items {
suites.Data = append(suites.Data, ConvertToGRPCTestSuite(items[i]))
}
return
}
func (s *dbserver) CreateTestSuite(ctx context.Context, testSuite *remote.TestSuite) (reply *server.Empty, err error) {
reply = &server.Empty{}
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Create(ConvertToDBTestSuite(testSuite))
return
}
const nameQuery = `name = ?`
func (s *dbserver) GetTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) {
query := &TestSuite{}
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&query, nameQuery, suite.Name)
reply = ConvertToGRPCTestSuite(query)
if suite.Full {
var testcases *server.TestCases
if testcases, err = s.ListTestCases(ctx, &remote.TestSuite{
Name: suite.Name,
}); err == nil && testcases != nil {
reply.Items = testcases.Data
}
}
return
}
func (s *dbserver) UpdateTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *remote.TestSuite, err error) {
reply = &remote.TestSuite{}
input := ConvertToDBTestSuite(suite)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testSuiteIdentity(db, input).Updates(input)
return
}
func testSuiteIdentity(db *gorm.DB, suite *TestSuite) *gorm.DB {
return db.Model(suite).Where(nameQuery, suite.Name)
}
func (s *dbserver) DeleteTestSuite(ctx context.Context, suite *remote.TestSuite) (reply *server.Empty, err error) {
reply = &server.Empty{}
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Delete(suite, nameQuery, suite.Name)
return
}
func (s *dbserver) ListTestCases(ctx context.Context, suite *remote.TestSuite) (result *server.TestCases, err error) {
items := make([]*TestCase, 0)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
db.Find(&items, "suite_name = ?", suite.Name)
result = &server.TestCases{}
for i := range items {
result.Data = append(result.Data, ConvertToRemoteTestCase(items[i]))
}
return
}
func (s *dbserver) CreateTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.Empty, err error) {
payload := ConverToDBTestCase(testcase)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
reply = &server.Empty{}
db.Create(&payload)
return
}
func (s *dbserver) GetTestCase(ctx context.Context, testcase *server.TestCase) (result *server.TestCase, err error) {
item := &TestCase{}
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 = ConvertToRemoteTestCase(item)
return
}
func (s *dbserver) UpdateTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.TestCase, err error) {
reply = &server.TestCase{}
input := ConverToDBTestCase(testcase)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testCaseIdentiy(db, input).Updates(input)
data := make(map[string]interface{})
if input.ExpectBody == "" {
data["expect_body"] = ""
}
if input.ExpectSchema == "" {
data["expect_schema"] = ""
}
if len(data) > 0 {
testCaseIdentiy(db, input).Updates(data)
}
return
}
func (s *dbserver) DeleteTestCase(ctx context.Context, testcase *server.TestCase) (reply *server.Empty, err error) {
reply = &server.Empty{}
input := ConverToDBTestCase(testcase)
var db *gorm.DB
if db, err = s.getClient(ctx); err != nil {
return
}
testCaseIdentiy(db, input).Delete(input)
return
}
func (s *dbserver) Verify(ctx context.Context, in *server.Empty) (reply *server.CommonResult, err error) {
db, clientErr := s.getClient(ctx)
reply = &server.CommonResult{
Success: err == nil && db != nil,
Message: util.OKOrErrorMessage(clientErr),
}
return
}
func testCaseIdentiy(db *gorm.DB, testcase *TestCase) *gorm.DB {
return db.Model(testcase).Where(fmt.Sprintf("suite_name = '%s' AND name = '%s'", testcase.SuiteName, testcase.Name))
}

View File

@ -0,0 +1,95 @@
/**
MIT License
Copyright (c) 2023 API Testing Authors.
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 pkg
import (
"context"
"testing"
"github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/stretchr/testify/assert"
)
func TestNewRemoteServer(t *testing.T) {
remoteServer := NewRemoteServer()
assert.NotNil(t, remoteServer)
defaultCtx := context.Background()
t.Run("ListTestSuite", func(t *testing.T) {
_, err := remoteServer.ListTestSuite(defaultCtx, nil)
assert.Error(t, err)
})
t.Run("CreateTestSuite", func(t *testing.T) {
_, err := remoteServer.CreateTestSuite(defaultCtx, nil)
assert.Error(t, err)
})
t.Run("GetTestSuite", func(t *testing.T) {
_, err := remoteServer.GetTestSuite(defaultCtx, nil)
assert.Error(t, err)
})
t.Run("UpdateTestSuite", func(t *testing.T) {
_, err := remoteServer.UpdateTestSuite(defaultCtx, &remote.TestSuite{})
assert.Error(t, err)
})
t.Run("DeleteTestSuite", func(t *testing.T) {
_, err := remoteServer.DeleteTestSuite(defaultCtx, nil)
assert.Error(t, err)
})
t.Run("ListTestCases", func(t *testing.T) {
_, err := remoteServer.ListTestCases(defaultCtx, nil)
assert.Error(t, err)
})
t.Run("CreateTestCase", func(t *testing.T) {
_, err := remoteServer.CreateTestCase(defaultCtx, &server.TestCase{})
assert.Error(t, err)
})
t.Run("GetTestCase", func(t *testing.T) {
_, err := remoteServer.GetTestCase(defaultCtx, nil)
assert.Error(t, err)
})
t.Run("UpdateTestCase", func(t *testing.T) {
_, err := remoteServer.UpdateTestCase(defaultCtx, &server.TestCase{})
assert.Error(t, err)
})
t.Run("DeleteTestCase", func(t *testing.T) {
_, err := remoteServer.DeleteTestCase(defaultCtx, &server.TestCase{})
assert.Error(t, err)
})
t.Run("Verify", func(t *testing.T) {
reply, err := remoteServer.Verify(defaultCtx, nil)
assert.NoError(t, err)
assert.False(t, reply.Success)
})
}

View File

@ -12,7 +12,7 @@ import (
func NewRootCmd(s3Creator pkg.S3Creator) (cmd *cobra.Command) {
opt := &option{
S3Creator: s3Creator,
s3Creator: s3Creator,
}
cmd = &cobra.Command{
Use: "store-s3",
@ -25,7 +25,7 @@ func NewRootCmd(s3Creator pkg.S3Creator) (cmd *cobra.Command) {
}
func (o *option) runE(cmd *cobra.Command, args []string) (err error) {
removeServer := pkg.NewRemoteServer(o.S3Creator)
removeServer := pkg.NewRemoteServer(o.s3Creator)
var lis net.Listener
lis, err = net.Listen("tcp", fmt.Sprintf(":%d", o.port))
@ -50,5 +50,5 @@ type option struct {
port int
// inner fields
S3Creator pkg.S3Creator
s3Creator pkg.S3Creator
}

View File

@ -13,6 +13,7 @@ import (
"github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing"
"github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/linuxsuren/api-testing/pkg/util"
"gopkg.in/yaml.v3"
)
@ -21,8 +22,8 @@ type s3Client struct {
remote.UnimplementedLoaderServer
}
func NewRemoteServer(S3Creator S3Creator) remote.LoaderServer {
return &s3Client{S3Creator: S3Creator}
func NewRemoteServer(s3Creator S3Creator) remote.LoaderServer {
return &s3Client{S3Creator: s3Creator}
}
func (s *s3Client) ListTestSuite(ctx context.Context, _ *server.Empty) (suites *remote.TestSuites, err error) {
@ -169,6 +170,14 @@ func (s *s3Client) DeleteTestCase(ctx context.Context, testcase *server.TestCase
}
return
}
func (s *s3Client) Verify(ctx context.Context, in *server.Empty) (reply *server.CommonResult, err error) {
_, clientErr := s.ListTestSuite(ctx, in)
reply = &server.CommonResult{
Success: err == nil,
Message: util.OKOrErrorMessage(clientErr),
}
return
}
func (s *s3Client) getClient(ctx context.Context) (db *s3WithBucket, err error) {
store := remote.GetStoreFromContext(ctx)
if store == nil {
@ -180,18 +189,9 @@ func (s *s3Client) getClient(ctx context.Context) (db *s3WithBucket, err error)
}
options := mapToS3Options(store.Properties)
cred := credentials.NewStaticCredentials(options.AccessKeyID, options.SecretAccessKey, options.SessionToken)
config := aws.Config{
Region: aws.String(options.Region),
Endpoint: aws.String(store.URL),
DisableSSL: aws.Bool(options.DisableSSL),
S3ForcePathStyle: aws.Bool(options.ForcePathStyle),
Credentials: cred,
}
var sess *session.Session
sess, err = session.NewSession(&config)
sess, err = createClientFromSs3Options(options, store.URL)
if err == nil {
svc := s.S3Creator.New(sess) // s3.New(sess)
db = &s3WithBucket{S3API: svc, bucket: options.Bucket}
@ -200,6 +200,20 @@ func (s *s3Client) getClient(ctx context.Context) (db *s3WithBucket, err error)
}
return
}
func createClientFromSs3Options(options s3Options, storeURL string) (sess *session.Session, err error) {
cred := credentials.NewStaticCredentials(options.AccessKeyID, options.SecretAccessKey, options.SessionToken)
config := aws.Config{
Region: aws.String(options.Region),
Endpoint: aws.String(storeURL),
DisableSSL: aws.Bool(options.DisableSSL),
S3ForcePathStyle: aws.Bool(options.ForcePathStyle),
Credentials: cred,
}
sess, err = session.NewSession(&config)
return
}
func mapToS3Options(data map[string]string) (opt s3Options) {
opt.AccessKeyID = data["accesskeyid"]

View File

@ -31,6 +31,11 @@ func TestNewRemoteServer(t *testing.T) {
t.Run("ListTestSuite", func(t *testing.T) {
_, err := newRemoteServer(t).ListTestSuite(defaultCtx, nil)
assert.NoError(t, err)
var result *server.CommonResult
result, err = newRemoteServer(t).Verify(defaultCtx, &server.Empty{})
assert.NoError(t, err)
assert.True(t, result.Success)
})
t.Run("CreateTestSuite", func(t *testing.T) {

View File

@ -19,6 +19,7 @@ import (
"github.com/linuxsuren/api-testing/pkg/render"
"github.com/linuxsuren/api-testing/pkg/runner"
"github.com/linuxsuren/api-testing/pkg/testing"
"github.com/linuxsuren/api-testing/pkg/util"
"github.com/linuxsuren/api-testing/pkg/version"
"github.com/linuxsuren/api-testing/sample"
"google.golang.org/grpc/metadata"
@ -110,19 +111,11 @@ func (s *server) getLoader(ctx context.Context) (loader testing.Writer) {
storeNameMeta := mdd.Get(HeaderKeyStoreName)
if len(storeNameMeta) > 0 {
storeName := storeNameMeta[0]
if storeName == "local" {
if storeName == "local" || storeName == "" {
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)
}
loader, _ = s.getLoaderByStoreName(storeName)
}
}
return
@ -530,7 +523,7 @@ func (s *server) GetSuggestedAPIs(ctx context.Context, in *TestSuiteIdentity) (r
return
}
fmt.Println(in.Name, suite)
fmt.Println("Finding APIs from", in.Name, "with loader", reflect.TypeOf(loader))
var swaggerAPI *apispec.Swagger
if swaggerAPI, err = apispec.ParseURLToSwagger(suite.Spec.URL); err == nil && swaggerAPI != nil {
for api, item := range swaggerAPI.Paths {
@ -607,7 +600,16 @@ func (s *server) GetStores(ctx context.Context, in *Empty) (reply *Stores, err e
Data: make([]*Store, 0),
}
for _, item := range stores {
reply.Data = append(reply.Data, ToGRPCStore(item))
grpcStore := ToGRPCStore(item)
if !item.IsLocal() {
storeStatus, sErr := s.VerifyStore(ctx, &SimpleQuery{Name: item.Name})
grpcStore.Ready = sErr == nil && storeStatus.Success
} else {
grpcStore.Ready = true
}
reply.Data = append(reply.Data, grpcStore)
}
}
return
@ -622,6 +624,27 @@ func (s *server) DeleteStore(ctx context.Context, in *Store) (reply *Store, err
}
func (s *server) VerifyStore(ctx context.Context, in *SimpleQuery) (reply *CommonResult, err error) {
// TODO need to implement
reply = &CommonResult{}
var loader testing.Writer
if loader, err = s.getLoaderByStoreName(in.Name); err == nil && loader != nil {
verifyErr := loader.Verify()
reply.Success = verifyErr == nil
reply.Message = util.OKOrErrorMessage(verifyErr)
}
return
}
func (s *server) getLoaderByStoreName(storeName string) (loader testing.Writer, err error) {
var store *testing.Store
store, err = testing.NewStoreFactory(s.configDir).GetStore(storeName)
if err == nil && store != nil {
loader, err = s.storeWriterFactory.NewInstance(*store)
if err != nil {
err = fmt.Errorf("failed to new grpc loader from store %s, err: %v", store.Name, err)
}
} else {
err = fmt.Errorf("failed to get store %s, err: %v", storeName, err)
}
return
}

View File

@ -663,8 +663,8 @@ func TestStoreManager(t *testing.T) {
defer clean()
reply, err := server.VerifyStore(ctx, &SimpleQuery{})
assert.NoError(t, err)
assert.Nil(t, reply)
assert.Error(t, err)
assert.NotNil(t, reply)
})
}
@ -673,7 +673,19 @@ func getRemoteServerInTempDir() (server RunnerServer, call func()) {
call = func() { os.RemoveAll(dir) }
writer := atesting.NewFileWriter(dir)
server = NewRemoteServer(writer, nil, "")
server = NewRemoteServer(writer, newLocalloaderFromStore(), "")
return
}
type fakeLocalLoaderFactory struct {
}
func newLocalloaderFromStore() atesting.StoreWriterFactory {
return &fakeLocalLoaderFactory{}
}
func (l *fakeLocalLoaderFactory) NewInstance(store atesting.Store) (writer atesting.Writer, err error) {
writer = atesting.NewFileWriter("")
return
}

View File

@ -1252,6 +1252,7 @@ type Store struct {
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"`
Ready bool `protobuf:"varint,8,opt,name=ready,proto3" json:"ready,omitempty"`
}
func (x *Store) Reset() {
@ -1335,6 +1336,13 @@ func (x *Store) GetKind() *StoreKind {
return nil
}
func (x *Store) GetReady() bool {
if x != nil {
return x.Ready
}
return false
}
type StoreKinds struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -1814,7 +1822,7 @@ var file_pkg_server_server_proto_rawDesc = []byte{
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22,
0x2b, 0x0a, 0x06, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x04, 0x64, 0x61, 0x74,
0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xdc, 0x01, 0x0a,
0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf2, 0x01, 0x0a,
0x05, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
@ -1828,126 +1836,127 @@ var file_pkg_server_server_proto_rawDesc = []byte{
0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72,
0x74, 0x69, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x07, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72,
0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x33, 0x0a, 0x0a, 0x53,
0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x61, 0x74,
0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
0x22, 0x31, 0x0a, 0x09, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x75, 0x72, 0x6c, 0x22, 0x42, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01,
0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a,
0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2e, 0x0a, 0x0a, 0x53, 0x69, 0x6d, 0x70, 0x6c,
0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x69,
0x72, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x20, 0x0a, 0x0a, 0x53, 0x69, 0x6d, 0x70, 0x6c,
0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x6d, 0x0a, 0x13, 0x43, 0x6f, 0x64,
0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x1c, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x1a,
0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x47, 0x65,
0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x47,
0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x32, 0xbc, 0x0b, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x03,
0x52, 0x75, 0x6e, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73,
0x74, 0x54, 0x61, 0x73, 0x6b, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54,
0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x2c, 0x0a, 0x09, 0x47,
0x65, 0x74, 0x53, 0x75, 0x69, 0x74, 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, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0f, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 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, 0x3e, 0x0a,
0x0c, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65,
0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a,
0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65,
0x12, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75,
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, 0x42, 0x0a, 0x0f, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 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, 0x3a, 0x0a,
0x0c, 0x4c, 0x69, 0x73, 0x74, 0x54, 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,
0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x2e, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x10, 0x47, 0x65, 0x74,
0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x50, 0x49, 0x73, 0x12, 0x19, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74, 0x65,
0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x73, 0x22, 0x00, 0x12, 0x41, 0x0a,
0x0b, 0x52, 0x75, 0x6e, 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, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00,
0x12, 0x3b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 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, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a,
0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12,
0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73,
0x65, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75, 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, 0x41, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61,
0x73, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74,
0x43, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75, 0x69, 0x74, 0x65, 0x1a, 0x12, 0x2e,
0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x72,
0x65, 0x61, 0x64, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64,
0x79, 0x22, 0x33, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x73, 0x12,
0x25, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b, 0x69, 0x6e, 0x64,
0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x31, 0x0a, 0x09, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x4b,
0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x42, 0x0a, 0x0c, 0x43, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63,
0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63,
0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2e, 0x0a,
0x0a, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x04, 0x64,
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x20, 0x0a,
0x0a, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22,
0x6d, 0x0a, 0x13, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75,
0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x65, 0x73, 0x74, 0x53,
0x75, 0x69, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65,
0x12, 0x1c, 0x0a, 0x09, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x07,
0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xbc, 0x0b, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e,
0x65, 0x72, 0x12, 0x2d, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x1a, 0x12, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22,
0x00, 0x12, 0x2c, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x75, 0x69, 0x74, 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, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x00, 0x12,
0x42, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69,
0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74,
0x53, 0x75, 0x69, 0x74, 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, 0x40, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73,
0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75,
0x69, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x11,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69, 0x74,
0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 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,
0x42, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x69,
0x74, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74,
0x53, 0x75, 0x69, 0x74, 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, 0x3a, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x54, 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, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x0d,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x75, 0x69, 0x74, 0x65, 0x22, 0x00, 0x12,
0x42, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41,
0x50, 0x49, 0x73, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73,
0x74, 0x53, 0x75, 0x69, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x11,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65,
0x73, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 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, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x52, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 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, 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, 0x38, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x64,
0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 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, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12,
0x43, 0x0a, 0x0c, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12,
0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e,
0x65, 0x72, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75,
0x6c, 0x74, 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, 0x40,
0x0a, 0x14, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x51, 0x75, 0x65, 0x72, 0x79,
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 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, 0x28, 0x01, 0x30, 0x01,
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,
0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73,
0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x73,
0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54,
0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75, 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, 0x41, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x53, 0x75,
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,
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, 0x38, 0x0a, 0x11, 0x4c,
0x69, 0x73, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72,
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, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4c,
0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0c, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x43,
0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 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, 0x40, 0x0a, 0x14, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 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, 0x28, 0x01, 0x30, 0x01, 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 (

View File

@ -165,6 +165,7 @@ message Store {
string password = 5;
repeated Pair properties = 6;
StoreKind kind = 7;
bool ready = 8;
}
message StoreKinds {

View File

@ -25,4 +25,6 @@ type Writer interface {
GetSuite(name string) (*TestSuite, string, error)
UpdateSuite(TestSuite) (err error)
DeleteSuite(name string) (err error)
Verify() (err error)
}

View File

@ -304,3 +304,8 @@ func (l *fileLoader) DeleteTestCase(suiteName, testcase string) (err error) {
}
return
}
func (l *fileLoader) Verify() (err error) {
// always be okay
return
}

View File

@ -2,6 +2,7 @@ package remote
import (
context "context"
"errors"
server "github.com/linuxsuren/api-testing/pkg/server"
"github.com/linuxsuren/api-testing/pkg/testing"
@ -170,3 +171,13 @@ func (g *gRPCLoader) DeleteSuite(name string) (err error) {
})
return
}
func (g *gRPCLoader) Verify() (err error) {
var result *server.CommonResult
if result, err = g.client.Verify(g.ctx, &server.Empty{}); err == nil {
if !result.Success {
err = errors.New(result.Message)
}
}
return
}

View File

@ -177,7 +177,7 @@ var file_pkg_testing_remote_loader_proto_rawDesc = []byte{
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,
0x32, 0xe0, 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,
@ -212,11 +212,14 @@ var file_pkg_testing_remote_loader_proto_rawDesc = []byte{
0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12,
0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73,
0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 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,
0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x0d, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 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, 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 (
@ -233,13 +236,14 @@ func file_pkg_testing_remote_loader_proto_rawDescGZIP() []byte {
var file_pkg_testing_remote_loader_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_pkg_testing_remote_loader_proto_goTypes = []interface{}{
(*TestSuites)(nil), // 0: remote.TestSuites
(*TestSuite)(nil), // 1: remote.TestSuite
(*server.Pair)(nil), // 2: server.Pair
(*server.APISpec)(nil), // 3: server.APISpec
(*server.TestCase)(nil), // 4: server.TestCase
(*server.Empty)(nil), // 5: server.Empty
(*server.TestCases)(nil), // 6: server.TestCases
(*TestSuites)(nil), // 0: remote.TestSuites
(*TestSuite)(nil), // 1: remote.TestSuite
(*server.Pair)(nil), // 2: server.Pair
(*server.APISpec)(nil), // 3: server.APISpec
(*server.TestCase)(nil), // 4: server.TestCase
(*server.Empty)(nil), // 5: server.Empty
(*server.TestCases)(nil), // 6: server.TestCases
(*server.CommonResult)(nil), // 7: server.CommonResult
}
var file_pkg_testing_remote_loader_proto_depIdxs = []int32{
1, // 0: remote.TestSuites.data:type_name -> remote.TestSuite
@ -256,18 +260,20 @@ var file_pkg_testing_remote_loader_proto_depIdxs = []int32{
4, // 11: remote.Loader.GetTestCase:input_type -> server.TestCase
4, // 12: remote.Loader.UpdateTestCase:input_type -> server.TestCase
4, // 13: remote.Loader.DeleteTestCase:input_type -> server.TestCase
0, // 14: remote.Loader.ListTestSuite:output_type -> remote.TestSuites
5, // 15: remote.Loader.CreateTestSuite:output_type -> server.Empty
1, // 16: remote.Loader.GetTestSuite:output_type -> remote.TestSuite
1, // 17: remote.Loader.UpdateTestSuite:output_type -> remote.TestSuite
5, // 18: remote.Loader.DeleteTestSuite:output_type -> server.Empty
6, // 19: remote.Loader.ListTestCases:output_type -> server.TestCases
5, // 20: remote.Loader.CreateTestCase:output_type -> server.Empty
4, // 21: remote.Loader.GetTestCase:output_type -> server.TestCase
4, // 22: remote.Loader.UpdateTestCase:output_type -> server.TestCase
5, // 23: remote.Loader.DeleteTestCase:output_type -> server.Empty
14, // [14:24] is the sub-list for method output_type
4, // [4:14] is the sub-list for method input_type
5, // 14: remote.Loader.Verify:input_type -> server.Empty
0, // 15: remote.Loader.ListTestSuite:output_type -> remote.TestSuites
5, // 16: remote.Loader.CreateTestSuite:output_type -> server.Empty
1, // 17: remote.Loader.GetTestSuite:output_type -> remote.TestSuite
1, // 18: remote.Loader.UpdateTestSuite:output_type -> remote.TestSuite
5, // 19: remote.Loader.DeleteTestSuite:output_type -> server.Empty
6, // 20: remote.Loader.ListTestCases:output_type -> server.TestCases
5, // 21: remote.Loader.CreateTestCase:output_type -> server.Empty
4, // 22: remote.Loader.GetTestCase:output_type -> server.TestCase
4, // 23: remote.Loader.UpdateTestCase:output_type -> server.TestCase
5, // 24: remote.Loader.DeleteTestCase:output_type -> server.Empty
7, // 25: remote.Loader.Verify:output_type -> server.CommonResult
15, // [15:26] is the sub-list for method output_type
4, // [4:15] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name

View File

@ -18,6 +18,8 @@ service Loader {
rpc GetTestCase(server.TestCase) returns (server.TestCase) {}
rpc UpdateTestCase(server.TestCase) returns (server.TestCase) {}
rpc DeleteTestCase(server.TestCase) returns (server.Empty) {}
rpc Verify(server.Empty) returns (server.CommonResult) {}
}
message TestSuites {

View File

@ -33,6 +33,7 @@ type LoaderClient interface {
GetTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.TestCase, error)
UpdateTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.TestCase, error)
DeleteTestCase(ctx context.Context, in *server.TestCase, opts ...grpc.CallOption) (*server.Empty, error)
Verify(ctx context.Context, in *server.Empty, opts ...grpc.CallOption) (*server.CommonResult, error)
}
type loaderClient struct {
@ -133,6 +134,15 @@ func (c *loaderClient) DeleteTestCase(ctx context.Context, in *server.TestCase,
return out, nil
}
func (c *loaderClient) Verify(ctx context.Context, in *server.Empty, opts ...grpc.CallOption) (*server.CommonResult, error) {
out := new(server.CommonResult)
err := c.cc.Invoke(ctx, "/remote.Loader/Verify", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// LoaderServer is the server API for Loader service.
// All implementations must embed UnimplementedLoaderServer
// for forward compatibility
@ -147,6 +157,7 @@ type LoaderServer interface {
GetTestCase(context.Context, *server.TestCase) (*server.TestCase, error)
UpdateTestCase(context.Context, *server.TestCase) (*server.TestCase, error)
DeleteTestCase(context.Context, *server.TestCase) (*server.Empty, error)
Verify(context.Context, *server.Empty) (*server.CommonResult, error)
mustEmbedUnimplementedLoaderServer()
}
@ -184,6 +195,9 @@ func (UnimplementedLoaderServer) UpdateTestCase(context.Context, *server.TestCas
func (UnimplementedLoaderServer) DeleteTestCase(context.Context, *server.TestCase) (*server.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteTestCase not implemented")
}
func (UnimplementedLoaderServer) Verify(context.Context, *server.Empty) (*server.CommonResult, error) {
return nil, status.Errorf(codes.Unimplemented, "method Verify not implemented")
}
func (UnimplementedLoaderServer) mustEmbedUnimplementedLoaderServer() {}
// UnsafeLoaderServer may be embedded to opt out of forward compatibility for this service.
@ -377,6 +391,24 @@ func _Loader_DeleteTestCase_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
func _Loader_Verify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(server.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(LoaderServer).Verify(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/remote.Loader/Verify",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LoaderServer).Verify(ctx, req.(*server.Empty))
}
return interceptor(ctx, in, info, handler)
}
// Loader_ServiceDesc is the grpc.ServiceDesc for Loader service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -424,6 +456,10 @@ var Loader_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteTestCase",
Handler: _Loader_DeleteTestCase_Handler,
},
{
MethodName: "Verify",
Handler: _Loader_Verify_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "pkg/testing/remote/loader.proto",

View File

@ -58,6 +58,10 @@ func (s *Store) ToMap() (result map[string]string) {
return
}
func (s *Store) IsLocal() bool {
return s.Name == "local"
}
func MapToStore(data map[string]string) (store Store) {
store = Store{
Name: data["name"],

View File

@ -70,6 +70,7 @@ func TestStoreFactory(t *testing.T) {
"database": "test",
},
}, store)
assert.False(t, store.IsLocal())
})
t.Run("GetAllStores", func(t *testing.T) {
@ -97,6 +98,11 @@ func TestStoreFactory(t *testing.T) {
Name: "local",
}}, stores)
})
t.Run("local store", func(t *testing.T) {
store := Store{Name: "local"}
assert.True(t, store.IsLocal())
})
}
var sampleStoreMap = map[string]string{

33
pkg/util/error.go Normal file
View File

@ -0,0 +1,33 @@
/**
MIT License
Copyright (c) 2023 API Testing Authors.
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 util
// OKOrErrorMessage returns OK or error message
func OKOrErrorMessage(err error) string {
if err != nil {
return err.Error()
}
return "OK"
}

38
pkg/util/error_test.go Normal file
View File

@ -0,0 +1,38 @@
/**
MIT License
Copyright (c) 2023 API Testing Authors.
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 util_test
import (
"errors"
"testing"
"github.com/linuxsuren/api-testing/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestOkOrErrorMessage(t *testing.T) {
assert.Equal(t, "OK", util.OKOrErrorMessage(nil))
assert.Equal(t, "test", util.OKOrErrorMessage(errors.New("test")))
}