From 33725611c102019af144d02a1661534bba7709d6 Mon Sep 17 00:00:00 2001 From: Novan <25704935+nofun97@users.noreply.github.com> Date: Tue, 27 Apr 2021 11:36:33 +1000 Subject: [PATCH 1/2] allow offset empty set (#165) --- rel/expr_offset.go | 2 ++ rel/expr_offset_test.go | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/rel/expr_offset.go b/rel/expr_offset.go index 828e9f05..e946d11a 100644 --- a/rel/expr_offset.go +++ b/rel/expr_offset.go @@ -41,6 +41,8 @@ func (o *OffsetExpr) Eval(ctx context.Context, local Scope) (_ Value, err error) return NewOffsetBytes(a.Bytes(), a.offset+int(offset.(Number))), nil case String: return NewOffsetString(a.s, a.offset+int(offset.(Number))), nil + case EmptySet: + return None, nil } return nil, WrapContextErr(errors.Errorf("offset not applicable to %s", ValueTypeAsString(array)), o, local) } diff --git a/rel/expr_offset_test.go b/rel/expr_offset_test.go index 7b9971cd..e57bc30e 100644 --- a/rel/expr_offset_test.go +++ b/rel/expr_offset_test.go @@ -136,6 +136,15 @@ func TestOffsetExprString(t *testing.T) { ) } +func TestOffsetExprEmptySet(t *testing.T) { + t.Parallel() + + AssertExprsEvalToSameValue(t, + None, + NewOffsetExpr(*parser.NewScanner(""), NewNumber(float64(-10)), None), + ) +} + func TestOffsetExprEvalFail(t *testing.T) { t.Parallel() From c0ad211cd78fba7475170466bcfbc1fc81384803 Mon Sep 17 00:00:00 2001 From: Novan <25704935+nofun97@users.noreply.github.com> Date: Tue, 27 Apr 2021 16:21:21 +1000 Subject: [PATCH 2/2] fix #148, deprecation warnings are logged once (#166) * fix #148, deprecation warnings are logged once initially the deprecator logs deprecated expressions everytime they are evaluated. This slows down scripts significantly. This commit ensures that they are logged once by storing expression location. * better name --- pkg/deprecate/deprecate.go | 30 ++++++++++++++++++++++++++++++ pkg/deprecate/deprecate_test.go | 18 +++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/pkg/deprecate/deprecate.go b/pkg/deprecate/deprecate.go index 21f73c77..9547a5f5 100644 --- a/pkg/deprecate/deprecate.go +++ b/pkg/deprecate/deprecate.go @@ -11,8 +11,33 @@ import ( "github.com/sirupsen/logrus" ) +type sourceContextCache struct { + sync.RWMutex + m map[string]struct{} +} + +func (d *sourceContextCache) encountered(scanner parser.Scanner) bool { + s := scanner.String() + d.RLock() + if _, has := d.m[s]; has { + defer d.RUnlock() + return true + } + d.RUnlock() + + d.Lock() + defer d.Unlock() + d.m[s] = struct{}{} + return false +} + +func newDeprecatorMap() *sourceContextCache { + return &sourceContextCache{m: make(map[string]struct{})} +} + // Deprecator contains information required to do deprecation checks and deprecation event trigger type Deprecator struct { + cache *sourceContextCache featureDesc string weakWarning, strongWarning, crash time.Time } @@ -77,12 +102,17 @@ func NewDeprecator(featureDesc, weakWarningDate, strongWarningDate, crashDate st weakWarning: weak, strongWarning: strong, crash: crash, + cache: newDeprecatorMap(), }, nil } // Deprecate does extracts build information from context once and does deprecation checks and trigger deprecation // events. func (d *Deprecator) Deprecate(ctx context.Context, scanner parser.Scanner) error { + if d.cache.encountered(scanner) { + return nil + } + buildDate, err := buildinfo.BuildDateFrom(ctx) if err != nil { return err diff --git a/pkg/deprecate/deprecate_test.go b/pkg/deprecate/deprecate_test.go index 99ccf8f6..39dcd661 100644 --- a/pkg/deprecate/deprecate_test.go +++ b/pkg/deprecate/deprecate_test.go @@ -22,7 +22,6 @@ func TestNewDeprecator(t *testing.T) { func TestDeprecate(t *testing.T) { // FIXME: use hook attached to a local logger instead of the global one hook := test.NewGlobal() - deprecator := MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") scanner := parser.NewScanner("expression") scannerStr := scanner.Context(parser.DefaultLimit) @@ -30,30 +29,36 @@ func TestDeprecate(t *testing.T) { return fmt.Sprintf("%s\n%s", msg, scannerStr) } + deprecator := MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") assert.NoError(t, deprecator.Deprecate(context.Background(), *scanner)) assert.Equal(t, errMsg("feature is being deprecated"), hook.LastEntry().Message) hook.Reset() + deprecator = MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") ctx := buildinfo.WithBuildData(context.Background(), buildinfo.BuildData{Date: "unspecified"}) assert.NoError(t, deprecator.Deprecate(ctx, *scanner)) assert.Equal(t, errMsg("feature is being deprecated"), hook.LastEntry().Message) hook.Reset() + deprecator = MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") ctx = buildinfo.WithBuildData(context.Background(), buildinfo.BuildData{Date: ""}) assert.NoError(t, deprecator.Deprecate(ctx, *scanner)) assert.Equal(t, errMsg("feature is being deprecated"), hook.LastEntry().Message) hook.Reset() + deprecator = MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") ctx = buildinfo.WithBuildData(context.Background(), buildinfo.BuildData{Date: "2000-01-01T00:00:00Z"}) assert.NoError(t, deprecator.Deprecate(ctx, *scanner)) assert.Equal(t, 0, len(hook.Entries)) hook.Reset() + deprecator = MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") ctx = buildinfo.WithBuildData(context.Background(), buildinfo.BuildData{Date: "2000-01-03T00:00:00Z"}) assert.NoError(t, deprecator.Deprecate(ctx, *scanner)) assert.Equal(t, errMsg("feature is being deprecated"), hook.LastEntry().Message) hook.Reset() + deprecator = MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") ctx = buildinfo.WithBuildData(context.Background(), buildinfo.BuildData{Date: "2000-01-05T00:00:00Z"}) assert.NoError(t, deprecator.Deprecate(ctx, *scanner)) assert.Equal(t, @@ -62,8 +67,19 @@ func TestDeprecate(t *testing.T) { ) hook.Reset() + deprecator = MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") ctx = buildinfo.WithBuildData(context.Background(), buildinfo.BuildData{Date: "2000-01-07T00:00:00Z"}) assert.EqualError(t, deprecator.Deprecate(ctx, *scanner), "feature is deprecated") assert.Equal(t, 0, len(hook.Entries)) hook.Reset() + + // test scanner storing + deprecator = MustNewDeprecator("feature", "2000-01-02", "2000-01-04", "2000-01-06") + assert.NoError(t, deprecator.Deprecate(context.Background(), *scanner)) + assert.Equal(t, errMsg("feature is being deprecated"), hook.LastEntry().Message) + assert.True(t, deprecator.cache.encountered(*scanner)) + hook.Reset() + assert.NoError(t, deprecator.Deprecate(context.Background(), *scanner)) + assert.Equal(t, 0, len(hook.Entries)) + hook.Reset() }