From 206f2da83b183b758cb254f55c5565f901663f3f Mon Sep 17 00:00:00 2001 From: Ferdinand Neman Date: Wed, 1 Dec 2021 10:02:20 +0700 Subject: [PATCH] Feat/resiliency Fixing #270 (#271) * Better make file * Fixes issue #270, where in JSON DOM, evaluating non-existent field in map interface yield a zero value, thus caling val.elem() causes a panic. Now the zero is evaluated and returned a normal error --- Makefile | 6 ++- examples/EvaluateMissingDataContext_test.go | 51 +++++++++++++++++++++ model/JsonDataAccessLayer.go | 3 ++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100755 examples/EvaluateMissingDataContext_test.go diff --git a/Makefile b/Makefile index af16d6ef..5e195e24 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,11 @@ build: fix-antlr4-bug go build ./... lint: build - ${GOBIN}/golint -set_exit_status builder/... engine/... examples/... ast/... pkg/... antlr/. model/... +ifndef GOBIN + "${GOPATH}/bin/golint" -set_exit_status builder/... engine/... examples/... ast/... pkg/... antlr/. model/... +else + "${GOBIN}/golint" -set_exit_status builder/... engine/... examples/... ast/... pkg/... antlr/. model/... +endif test-short: build go test ./... -v -covermode=count -coverprofile=coverage.out -short diff --git a/examples/EvaluateMissingDataContext_test.go b/examples/EvaluateMissingDataContext_test.go new file mode 100755 index 00000000..b9efe93e --- /dev/null +++ b/examples/EvaluateMissingDataContext_test.go @@ -0,0 +1,51 @@ +package examples + +import ( + "fmt" + "github.com/hyperjumptech/grule-rule-engine/ast" + "github.com/hyperjumptech/grule-rule-engine/builder" + "github.com/hyperjumptech/grule-rule-engine/engine" + "github.com/hyperjumptech/grule-rule-engine/pkg" + "testing" +) + +const ( + input_rule = ` + rule TestRule "" { + when + R.Result == 'NoResult' && + inputs.i_am_missing == 'abc' && + inputs.name.first == 'john' + then + R.Result = "ok"; + } + ` +) + + +func TestDataContextMissingFact(t *testing.T) { + + oresult := &ObjectResult{ + Result: "NoResult", + } + + // build rules + lib := ast.NewKnowledgeLibrary() + rb := builder.NewRuleBuilder(lib) + err := rb.BuildRuleFromResource("Test", "0.0.1", pkg.NewBytesResource([]byte(input_rule))) + + // add JSON fact + json := []byte(`{"blabla":"bla","name":{"first":"john","last":"doe"}}`) + kb := lib.NewKnowledgeBaseInstance("Test", "0.0.1") + dcx := ast.NewDataContext() + + err = dcx.Add("R", oresult) + err = dcx.AddJSON("inputs", json) + if err != nil { + fmt.Println(err.Error()) + } + + // results in panic + engine.NewGruleEngine().Execute(dcx, kb) + +} \ No newline at end of file diff --git a/model/JsonDataAccessLayer.go b/model/JsonDataAccessLayer.go index 6b87799e..406543e5 100755 --- a/model/JsonDataAccessLayer.go +++ b/model/JsonDataAccessLayer.go @@ -191,6 +191,9 @@ func (vn *JSONValueNode) GetObjectValueByField(field string) (reflect.Value, err return reflect.ValueOf(nil), fmt.Errorf("not an object or map") } tmap := vn.data.MapIndex(reflect.ValueOf(field)) + if tmap == reflect.ValueOf(nil) { + return reflect.ValueOf(nil), fmt.Errorf("json field '%s' is undefined", field) + } return tmap.Elem(), nil }