From ae12b2237d7dd5f91ae3636af9bf3af3200e876d Mon Sep 17 00:00:00 2001 From: Allen Date: Sat, 25 Feb 2023 22:42:52 +0600 Subject: [PATCH 1/5] feat: create files split_from_start.go and split_from_start_test.go --- internal/primitive/transform/action/strings/split_from_start.go | 1 + .../primitive/transform/action/strings/split_from_start_test.go | 1 + 2 files changed, 2 insertions(+) create mode 100644 internal/primitive/transform/action/strings/split_from_start.go create mode 100644 internal/primitive/transform/action/strings/split_from_start_test.go diff --git a/internal/primitive/transform/action/strings/split_from_start.go b/internal/primitive/transform/action/strings/split_from_start.go new file mode 100644 index 000000000..e152b4b83 --- /dev/null +++ b/internal/primitive/transform/action/strings/split_from_start.go @@ -0,0 +1 @@ +package strings diff --git a/internal/primitive/transform/action/strings/split_from_start_test.go b/internal/primitive/transform/action/strings/split_from_start_test.go new file mode 100644 index 000000000..9c53d25e9 --- /dev/null +++ b/internal/primitive/transform/action/strings/split_from_start_test.go @@ -0,0 +1 @@ +package strings_test From 54df2426ac3ac898b89cea0fa866610c3b7ffc8c Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 27 Feb 2023 20:36:42 +0600 Subject: [PATCH 2/5] feat: add constructor NewSplitFromStartAction, register it in runtime.Init --- .../action/strings/split_from_start.go | 31 +++++++++++++++++++ internal/primitive/transform/runtime/init.go | 1 + 2 files changed, 32 insertions(+) diff --git a/internal/primitive/transform/action/strings/split_from_start.go b/internal/primitive/transform/action/strings/split_from_start.go index e152b4b83..70e7909a0 100644 --- a/internal/primitive/transform/action/strings/split_from_start.go +++ b/internal/primitive/transform/action/strings/split_from_start.go @@ -1 +1,32 @@ +// Copyright 2023 Linkall Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package strings + +import ( + "github.com/linkall-labs/vanus/internal/primitive/transform/action" + "github.com/linkall-labs/vanus/internal/primitive/transform/arg" + "github.com/linkall-labs/vanus/internal/primitive/transform/function" +) + +// NewSplitFromStartAction ["split_from_start", "key"]. +func NewSplitFromStartAction() action.Action { + a := &action.SourceTargetSameAction{} + a.CommonAction = action.CommonAction{ + ActionName: "SPLIT_FROM_START", + FixedArgs: []arg.TypeList{arg.EventList, arg.All}, + Fn: function.SplitFromStart, + } + return a +} diff --git a/internal/primitive/transform/runtime/init.go b/internal/primitive/transform/runtime/init.go index 390cd8511..42e41360f 100644 --- a/internal/primitive/transform/runtime/init.go +++ b/internal/primitive/transform/runtime/init.go @@ -55,6 +55,7 @@ func init() { strings.NewCheckCustomValuesAction, strings.NewCapitalizeWordAction, strings.NewSplitWithDelimiterAction, + strings.NewSplitFromStartAction, // condition condition.NewConditionIfAction, // array From 29e6a9121a9bddd7edd946773197a170aa66046f Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 27 Feb 2023 21:34:04 +0600 Subject: [PATCH 3/5] feat: add SplitFromStart, initial code --- .../transform/function/strings_functions.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/internal/primitive/transform/function/strings_functions.go b/internal/primitive/transform/function/strings_functions.go index 2846d2760..f69942b6b 100644 --- a/internal/primitive/transform/function/strings_functions.go +++ b/internal/primitive/transform/function/strings_functions.go @@ -140,3 +140,22 @@ var CapitalizeWord = function{ return string(rs), nil }, } + +var SplitFromStart = function{ + name: "SPLIT_FROM_START", + fixedArgs: []common.Type{common.String, common.Int}, + fn: func(args []interface{}) (interface{}, error) { + value, _ := args[0].(string) + splitPosition, _ := args[1].(int) + if len(value) < 2 { + return []string{value}, nil + } + if splitPosition < 1 { + return nil, fmt.Errorf("split position must be more than zero") + } + if splitPosition >= len(value) { + return nil, fmt.Errorf("split position must be less than the length of the string") + } + return []string{value[:splitPosition], value[splitPosition:]}, nil + }, +} From 9948fe4488ba14f87e65b6c989e8a65d2e705353 Mon Sep 17 00:00:00 2001 From: Allen Date: Fri, 3 Mar 2023 20:48:05 +0600 Subject: [PATCH 4/5] feat: SplitFromStart with constructor redefining Execute, add main tests --- .../action/strings/split_from_start.go | 18 +++- .../action/strings/split_from_start_test.go | 92 +++++++++++++++++++ .../transform/function/strings_functions.go | 3 +- 3 files changed, 109 insertions(+), 4 deletions(-) diff --git a/internal/primitive/transform/action/strings/split_from_start.go b/internal/primitive/transform/action/strings/split_from_start.go index 70e7909a0..99c345828 100644 --- a/internal/primitive/transform/action/strings/split_from_start.go +++ b/internal/primitive/transform/action/strings/split_from_start.go @@ -17,16 +17,28 @@ package strings import ( "github.com/linkall-labs/vanus/internal/primitive/transform/action" "github.com/linkall-labs/vanus/internal/primitive/transform/arg" + "github.com/linkall-labs/vanus/internal/primitive/transform/common" "github.com/linkall-labs/vanus/internal/primitive/transform/function" ) -// NewSplitFromStartAction ["split_from_start", "key"]. +type splitFromStartAction struct { + action.FunctionAction +} + +// NewSplitFromStartAction ["split_from_start", "sourceJsonPath", "position", "targetJsonPath"]. func NewSplitFromStartAction() action.Action { - a := &action.SourceTargetSameAction{} + a := &splitFromStartAction{} a.CommonAction = action.CommonAction{ ActionName: "SPLIT_FROM_START", - FixedArgs: []arg.TypeList{arg.EventList, arg.All}, + FixedArgs: []arg.TypeList{arg.EventList, []arg.Type{arg.Constant}, []arg.Type{arg.EventData}}, Fn: function.SplitFromStart, } return a } + +func (a *splitFromStartAction) Init(args []arg.Arg) error { + a.TargetArg = args[2] + a.Args = args[:2] + a.ArgTypes = []common.Type{common.String, common.Int} + return nil +} diff --git a/internal/primitive/transform/action/strings/split_from_start_test.go b/internal/primitive/transform/action/strings/split_from_start_test.go index 9c53d25e9..30b1da6cb 100644 --- a/internal/primitive/transform/action/strings/split_from_start_test.go +++ b/internal/primitive/transform/action/strings/split_from_start_test.go @@ -1 +1,93 @@ +// Copyright 2023 Linkall Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package strings_test + +import ( + "testing" + + cetest "github.com/cloudevents/sdk-go/v2/test" + "github.com/linkall-labs/vanus/internal/primitive/transform/action/strings" + "github.com/linkall-labs/vanus/internal/primitive/transform/context" + "github.com/linkall-labs/vanus/internal/primitive/transform/runtime" + . "github.com/smartystreets/goconvey/convey" +) + +func TestSplitFromStartAction(t *testing.T) { + funcName := strings.NewSplitFromStartAction().Name() + + Convey("test split from start: Positive testcase", t, func() { + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 5, "$.data.target"}) + So(err, ShouldBeNil) + e := cetest.MinEvent() + data := map[string]interface{}{} + e.SetExtension("test", "Hello, World!") + ceCtx := &context.EventContext{ + Event: &e, + Data: data, + } + err = a.Execute(ceCtx) + So(err, ShouldBeNil) + res, ok := data["target"] + So(ok, ShouldBeTrue) + So(res, ShouldResemble, []string{"Hello", ", World!"}) + }) + + Convey("test split from start: Positive testcase, length 1", t, func() { + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 0, "$.data.target"}) + So(err, ShouldBeNil) + e := cetest.MinEvent() + data := map[string]interface{}{} + e.SetExtension("test", "H") + ceCtx := &context.EventContext{ + Event: &e, + Data: data, + } + err = a.Execute(ceCtx) + So(err, ShouldBeNil) + res, ok := data["target"] + So(ok, ShouldBeTrue) + So(res, ShouldResemble, []string{"H"}) + }) + + Convey("test split from start: Negative testcase, split position less than one", t, func() { + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 0, "$.data.target"}) + So(err, ShouldBeNil) + e := cetest.MinEvent() + data := map[string]interface{}{} + e.SetExtension("test", "split position must be more than zero") + ceCtx := &context.EventContext{ + Event: &e, + Data: data, + } + err = a.Execute(ceCtx) + So(err, ShouldNotBeNil) + So(e.Extensions()["test"], ShouldEqual, "split position must be more than zero") + }) + + Convey("test split from start: Negative testcase, split position greater than string length", t, func() { + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 100, "$.data.target"}) + So(err, ShouldBeNil) + e := cetest.MinEvent() + data := map[string]interface{}{} + e.SetExtension("test", "split position must be less than the length of the string") + ceCtx := &context.EventContext{ + Event: &e, + Data: data, + } + err = a.Execute(ceCtx) + So(err, ShouldNotBeNil) + So(e.Extensions()["test"], ShouldEqual, "split position must be less than the length of the string") + }) +} diff --git a/internal/primitive/transform/function/strings_functions.go b/internal/primitive/transform/function/strings_functions.go index f69942b6b..de3010f2b 100644 --- a/internal/primitive/transform/function/strings_functions.go +++ b/internal/primitive/transform/function/strings_functions.go @@ -156,6 +156,7 @@ var SplitFromStart = function{ if splitPosition >= len(value) { return nil, fmt.Errorf("split position must be less than the length of the string") } - return []string{value[:splitPosition], value[splitPosition:]}, nil + result := []string{value[:splitPosition], value[splitPosition:]} + return result, nil }, } From 7d6f616e36ca5a485edea9beade6bca05b4e27e6 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 6 Mar 2023 17:22:49 +0600 Subject: [PATCH 5/5] fix: update how split_from_start handles special cases, update unit tests --- .../action/strings/split_from_start_test.go | 43 +++++++++++++------ .../transform/function/strings_functions.go | 10 ++--- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/internal/primitive/transform/action/strings/split_from_start_test.go b/internal/primitive/transform/action/strings/split_from_start_test.go index 30b1da6cb..20479254b 100644 --- a/internal/primitive/transform/action/strings/split_from_start_test.go +++ b/internal/primitive/transform/action/strings/split_from_start_test.go @@ -27,7 +27,7 @@ import ( func TestSplitFromStartAction(t *testing.T) { funcName := strings.NewSplitFromStartAction().Name() - Convey("test split from start: Positive testcase", t, func() { + Convey("test split from start: Positive testcase, common", t, func() { a, err := runtime.NewAction([]interface{}{funcName, "$.test", 5, "$.data.target"}) So(err, ShouldBeNil) e := cetest.MinEvent() @@ -45,7 +45,7 @@ func TestSplitFromStartAction(t *testing.T) { }) Convey("test split from start: Positive testcase, length 1", t, func() { - a, err := runtime.NewAction([]interface{}{funcName, "$.test", 0, "$.data.target"}) + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 1, "$.data.target"}) So(err, ShouldBeNil) e := cetest.MinEvent() data := map[string]interface{}{} @@ -58,36 +58,55 @@ func TestSplitFromStartAction(t *testing.T) { So(err, ShouldBeNil) res, ok := data["target"] So(ok, ShouldBeTrue) - So(res, ShouldResemble, []string{"H"}) + So(res, ShouldResemble, []string{"H", ""}) }) - Convey("test split from start: Negative testcase, split position less than one", t, func() { - a, err := runtime.NewAction([]interface{}{funcName, "$.test", 0, "$.data.target"}) + Convey("test split from start: Positive testcase, length 0", t, func() { + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 1, "$.data.target"}) So(err, ShouldBeNil) e := cetest.MinEvent() data := map[string]interface{}{} - e.SetExtension("test", "split position must be more than zero") + e.SetExtension("test", "") ceCtx := &context.EventContext{ Event: &e, Data: data, } err = a.Execute(ceCtx) - So(err, ShouldNotBeNil) - So(e.Extensions()["test"], ShouldEqual, "split position must be more than zero") + So(err, ShouldBeNil) + res, ok := data["target"] + So(ok, ShouldBeTrue) + So(res, ShouldResemble, []string{"", ""}) + }) + + Convey("test split from start: Positive testcase, split position above value length", t, func() { + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 10, "$.data.target"}) + So(err, ShouldBeNil) + e := cetest.MinEvent() + data := map[string]interface{}{} + e.SetExtension("test", "hello") + ceCtx := &context.EventContext{ + Event: &e, + Data: data, + } + err = a.Execute(ceCtx) + So(err, ShouldBeNil) + res, ok := data["target"] + So(ok, ShouldBeTrue) + So(res, ShouldResemble, []string{"hello", ""}) }) - Convey("test split from start: Negative testcase, split position greater than string length", t, func() { - a, err := runtime.NewAction([]interface{}{funcName, "$.test", 100, "$.data.target"}) + Convey("test split from start: Negative testcase, split position less than one", t, func() { + a, err := runtime.NewAction([]interface{}{funcName, "$.test", 0, "$.data.target"}) So(err, ShouldBeNil) e := cetest.MinEvent() data := map[string]interface{}{} - e.SetExtension("test", "split position must be less than the length of the string") + e.SetExtension("test", "split position must be more than zero") ceCtx := &context.EventContext{ Event: &e, Data: data, } err = a.Execute(ceCtx) So(err, ShouldNotBeNil) - So(e.Extensions()["test"], ShouldEqual, "split position must be less than the length of the string") + So(e.Extensions()["test"], ShouldEqual, "split position must be more than zero") }) } diff --git a/internal/primitive/transform/function/strings_functions.go b/internal/primitive/transform/function/strings_functions.go index de3010f2b..0016b4fe4 100644 --- a/internal/primitive/transform/function/strings_functions.go +++ b/internal/primitive/transform/function/strings_functions.go @@ -147,15 +147,15 @@ var SplitFromStart = function{ fn: func(args []interface{}) (interface{}, error) { value, _ := args[0].(string) splitPosition, _ := args[1].(int) - if len(value) < 2 { - return []string{value}, nil - } - if splitPosition < 1 { + + if splitPosition <= 0 { return nil, fmt.Errorf("split position must be more than zero") } + if splitPosition >= len(value) { - return nil, fmt.Errorf("split position must be less than the length of the string") + return []string{value, ""}, nil } + result := []string{value[:splitPosition], value[splitPosition:]} return result, nil },