From 6d8b91396169d4ef6afb525d8d21b989e500a425 Mon Sep 17 00:00:00 2001 From: wurui Date: Mon, 27 Nov 2023 15:52:16 +0800 Subject: [PATCH] feat(cli): yomo init with test file (#680) # Description `yomo init` command now generates `app_test.go` template for testing `app.go`. --- cli/cli.go | 5 +- cli/init.go | 7 +++ cli/serverless/golang/template.go | 3 + .../golang/templates/init_test.tmpl | 36 +++++++++++ serverless/mock/mock_context.go | 62 +++++++++++++++++++ 5 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 cli/serverless/golang/templates/init_test.tmpl create mode 100644 serverless/mock/mock_context.go diff --git a/cli/cli.go b/cli/cli.go index ec09d0b84..3664927ac 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -18,8 +18,9 @@ import ( // defaultSFNFile is the default serverless file name const ( - defaultSFNSourceFile = "app.go" - defaultSFNCompliedFile = "sfn.wasm" + defaultSFNSourceFile = "app.go" + defaultSFNTestSourceFile = "app_test.go" + defaultSFNCompliedFile = "sfn.wasm" ) // GetRootPath get root path diff --git a/cli/init.go b/cli/init.go index f4d10451a..37a28422d 100644 --- a/cli/init.go +++ b/cli/init.go @@ -60,6 +60,13 @@ var initCmd = &cobra.Command{ return } + // create app_test.go + testName := filepath.Join(name, defaultSFNTestSourceFile) + if err := file.PutContents(testName, golang.InitTestTmpl); err != nil { + log.FailureStatusEvent(os.Stdout, "Write unittest tmpl into app_test.go file failure with the error: %v", err) + return + } + // create .env fname = filepath.Join(name, ".env") if err := file.PutContents(fname, []byte(fmt.Sprintf("YOMO_SFN_NAME=%s\n", name))); err != nil { diff --git a/cli/serverless/golang/template.go b/cli/serverless/golang/template.go index 83fc4cb20..d8c104d67 100644 --- a/cli/serverless/golang/template.go +++ b/cli/serverless/golang/template.go @@ -24,6 +24,9 @@ var PartialsTmpl []byte //go:embed templates/init.tmpl var InitTmpl []byte +//go:embed templates/init_test.tmpl +var InitTestTmpl []byte + //go:embed templates/init_rx.tmpl var InitRxTmpl []byte diff --git a/cli/serverless/golang/templates/init_test.tmpl b/cli/serverless/golang/templates/init_test.tmpl new file mode 100644 index 000000000..de97e3f72 --- /dev/null +++ b/cli/serverless/golang/templates/init_test.tmpl @@ -0,0 +1,36 @@ +package main + +import ( + "reflect" + "testing" + + "github.com/yomorun/yomo/serverless/mock" +) + +func TestHandler(t *testing.T) { + tests := []struct { + name string + ctx *mock.MockContext + // want is the expected data and tag that be written by ctx.Write + want []mock.DataAndTag + }{ + { + name: "upper", + ctx: mock.NewMockContext([]byte("hello"), 0x33), + want: []mock.DataAndTag{ + {Data: []byte("HELLO"), Tag: 0x34}, + }, + }, + // TODO: add more test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + Handler(tt.ctx) + got := tt.ctx.RecordWritten() + + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("TestHandler got: %v, want: %v", got, tt.want) + } + }) + } +} diff --git a/serverless/mock/mock_context.go b/serverless/mock/mock_context.go new file mode 100644 index 000000000..502648259 --- /dev/null +++ b/serverless/mock/mock_context.go @@ -0,0 +1,62 @@ +package mock + +import ( + "sync" + + "github.com/yomorun/yomo/serverless" + "github.com/yomorun/yomo/serverless/guest" +) + +// DataAndTag is a pair of data and tag. +type DataAndTag struct { + Data []byte + Tag uint32 +} + +// MockContext mock context. +type MockContext struct { + data []byte + tag uint32 + + mu sync.Mutex + wrSlice []DataAndTag +} + +// NewMockContext returns the mock context. +// the data is that returned by ctx.Data(), the tag is that returned by ctx.Tag(). +func NewMockContext(data []byte, tag uint32) *MockContext { + return &MockContext{ + data: data, + tag: tag, + } +} + +func (c *MockContext) Data() []byte { + return c.data +} +func (c *MockContext) Tag() uint32 { + return c.tag +} +func (m *MockContext) HTTP() serverless.HTTP { + return &guest.GuestHTTP{} +} + +func (c *MockContext) Write(tag uint32, data []byte) error { + c.mu.Lock() + defer c.mu.Unlock() + + c.wrSlice = append(c.wrSlice, DataAndTag{ + Data: data, + Tag: tag, + }) + + return nil +} + +// RecordWritten returns the data records be written with `ctx.Write`. +func (c *MockContext) RecordWritten() []DataAndTag { + c.mu.Lock() + defer c.mu.Unlock() + + return c.wrSlice +}