Skip to content

Commit 6681021

Browse files
authored
Feat/bettertest (#195)
* Added new ErrorReporter to store all grule's GRL parsing errors * Updated README.md to removed featured product and added comment in the GrlParseErrorDetection_test.go so reader can easily understand how to use ErrorReporter * Added in function * Added lots of documentations of new features * Fixing linting issue for GruleEngineListener * Fix very minor logic bug * avoiding go mod tidy issue golang/go#44557 that CI pipeline to fail
1 parent b802e30 commit 6681021

18 files changed

+418
-95
lines changed

README.md

-15
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,3 @@ Yes. We need contributors to make Grule even better and useful to the Open Sourc
176176

177177
If you really want to help us, simply `Fork` the project and apply for Pull Request.
178178
Please read our [Contribution Manual](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCTS.md)
179-
180-
# Featured Projects Or Products
181-
182-
<a href="https://hyperjump.tech"><img width="200px" src="https://avatars.githubusercontent.com/u/47617049?s=400&u=7807a6dc27d2c6a8aa68b0496b1387e8954370e9&v=4"></a>
183-
184-
**HYPERJUMP tech** ( [https://hyperjump.tech](https://hyperjump.tech) )
185-
186-
<br>
187-
188-
<i>If your company or project is using Grule right now
189-
and don't mind tobe featured here, I would glad to add a name, logo (if you have one) and a link to your site.
190-
While it surely help us to know our users, your product might gain awareness by those who passing by.
191-
Please submit a ["Feature me" issue](https://github.com/hyperjumptech/grule-rule-engine/issues/new),
192-
stating the company/product name, a link to the page and/or logo in the issue's description. </i>
193-

antlr/GruleParserV3Listener.go

+20-20
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/hyperjumptech/grule-rule-engine/antlr/parser/grulev3"
2121
"github.com/hyperjumptech/grule-rule-engine/ast"
2222
"github.com/hyperjumptech/grule-rule-engine/logger"
23+
"github.com/hyperjumptech/grule-rule-engine/pkg"
2324
"github.com/sirupsen/logrus"
2425
"strconv"
2526
"strings"
@@ -34,7 +35,7 @@ var (
3435
)
3536

3637
// NewGruleV3ParserListener create new instance of GruleV3ParserListener
37-
func NewGruleV3ParserListener(KnowledgeBase *ast.KnowledgeBase, errorCallBack func(e error)) *GruleV3ParserListener {
38+
func NewGruleV3ParserListener(KnowledgeBase *ast.KnowledgeBase, errorCallBack *pkg.GruleErrorReporter) *GruleV3ParserListener {
3839
return &GruleV3ParserListener{
3940
PreviousNode: make([]string, 0),
4041
ErrorCallback: errorCallBack,
@@ -52,7 +53,7 @@ type GruleV3ParserListener struct {
5253
Grl *ast.Grl
5354
Stack *stack
5455
StopParse bool
55-
ErrorCallback func(e error)
56+
ErrorCallback *pkg.GruleErrorReporter
5657
KnowledgeBase *ast.KnowledgeBase
5758
}
5859

@@ -71,7 +72,6 @@ func (s *GruleV3ParserListener) VisitTerminal(node antlr.TerminalNode) {
7172
func (s *GruleV3ParserListener) VisitErrorNode(node antlr.ErrorNode) {
7273
LoggerV3.Errorf("GRL error, after '%v' and then unexpected '%s'", s.PreviousNode, node.GetText())
7374
s.StopParse = true
74-
s.ErrorCallback(fmt.Errorf("GRL error, after '%v' and then unexpected '%s'", s.PreviousNode, node.GetText()))
7575
}
7676

7777
// EnterEveryRule is called when any rule is entered.
@@ -95,7 +95,7 @@ func (s *GruleV3ParserListener) ExitGrl(ctx *grulev3.GrlContext) {
9595
for _, re := range s.Grl.RuleEntries {
9696
err := s.KnowledgeBase.AddRuleEntry(re)
9797
if err != nil {
98-
s.ErrorCallback(err)
98+
s.ErrorCallback.AddError(err)
9999
}
100100
}
101101
}
@@ -126,7 +126,7 @@ func (s *GruleV3ParserListener) ExitRuleEntry(ctx *grulev3.RuleEntryContext) {
126126
}
127127
err := entryReceiver.ReceiveRuleEntry(entry)
128128
if err != nil {
129-
s.ErrorCallback(err)
129+
s.ErrorCallback.AddError(err)
130130
} else {
131131
LoggerV3.Debugf("Added RuleEntry : %s", entry.RuleName)
132132
}
@@ -168,7 +168,7 @@ func (s *GruleV3ParserListener) ExitWhenScope(ctx *grulev3.WhenScopeContext) {
168168
err := receiver.AcceptWhenScope(when)
169169
if err != nil {
170170
s.StopParse = true
171-
s.ErrorCallback(err)
171+
s.ErrorCallback.AddError(err)
172172
}
173173
}
174174

@@ -192,7 +192,7 @@ func (s *GruleV3ParserListener) ExitThenScope(ctx *grulev3.ThenScopeContext) {
192192
err := receiver.AcceptThenScope(then)
193193
if err != nil {
194194
s.StopParse = true
195-
s.ErrorCallback(err)
195+
s.ErrorCallback.AddError(err)
196196
}
197197
}
198198

@@ -216,7 +216,7 @@ func (s *GruleV3ParserListener) ExitThenExpressionList(ctx *grulev3.ThenExpressi
216216
err := receiver.AcceptThenExpressionList(thenExpList)
217217
if err != nil {
218218
s.StopParse = true
219-
s.ErrorCallback(err)
219+
s.ErrorCallback.AddError(err)
220220
}
221221
}
222222

@@ -241,7 +241,7 @@ func (s *GruleV3ParserListener) ExitThenExpression(ctx *grulev3.ThenExpressionCo
241241
err := receiver.AcceptThenExpression(thenExpr)
242242
if err != nil {
243243
s.StopParse = true
244-
s.ErrorCallback(err)
244+
s.ErrorCallback.AddError(err)
245245
}
246246
}
247247

@@ -271,7 +271,7 @@ func (s *GruleV3ParserListener) ExitAssignment(ctx *grulev3.AssignmentContext) {
271271
err := receiver.AcceptAssignment(assign)
272272
if err != nil {
273273
s.StopParse = true
274-
s.ErrorCallback(err)
274+
s.ErrorCallback.AddError(err)
275275
}
276276
}
277277

@@ -300,7 +300,7 @@ func (s *GruleV3ParserListener) ExitExpression(ctx *grulev3.ExpressionContext) {
300300
err := exprRec.AcceptExpression(s.KnowledgeBase.WorkingMemory.AddExpression(expr))
301301
if err != nil {
302302
s.StopParse = true
303-
s.ErrorCallback(err)
303+
s.ErrorCallback.AddError(err)
304304
}
305305
}
306306

@@ -415,7 +415,7 @@ func (s *GruleV3ParserListener) ExitExpressionAtom(ctx *grulev3.ExpressionAtomCo
415415
err := expr.AcceptExpressionAtom(s.KnowledgeBase.WorkingMemory.AddExpressionAtom(atm))
416416
if err != nil {
417417
s.StopParse = true
418-
s.ErrorCallback(err)
418+
s.ErrorCallback.AddError(err)
419419
}
420420
}
421421

@@ -439,7 +439,7 @@ func (s *GruleV3ParserListener) ExitArrayMapSelector(ctx *grulev3.ArrayMapSelect
439439
err := receiver.AcceptArrayMapSelector(sel)
440440
if err != nil {
441441
s.StopParse = true
442-
s.ErrorCallback(err)
442+
s.ErrorCallback.AddError(err)
443443
}
444444
}
445445

@@ -463,7 +463,7 @@ func (s *GruleV3ParserListener) ExitFunctionCall(ctx *grulev3.FunctionCallContex
463463
err := metRec.AcceptFunctionCall(fun)
464464
if err != nil {
465465
s.StopParse = true
466-
s.ErrorCallback(err)
466+
s.ErrorCallback.AddError(err)
467467
}
468468
}
469469

@@ -488,7 +488,7 @@ func (s *GruleV3ParserListener) ExitArgumentList(ctx *grulev3.ArgumentListContex
488488
err := argListRec.AcceptArgumentList(argList)
489489
if err != nil {
490490
s.StopParse = true
491-
s.ErrorCallback(err)
491+
s.ErrorCallback.AddError(err)
492492
}
493493
}
494494

@@ -519,7 +519,7 @@ func (s *GruleV3ParserListener) ExitVariable(ctx *grulev3.VariableContext) {
519519
err := variRec.AcceptVariable(s.KnowledgeBase.WorkingMemory.AddVariable(vari))
520520
if err != nil {
521521
s.StopParse = true
522-
s.ErrorCallback(err)
522+
s.ErrorCallback.AddError(err)
523523
}
524524
}
525525

@@ -555,7 +555,7 @@ func (s *GruleV3ParserListener) ExitConstant(ctx *grulev3.ConstantContext) {
555555
err := conRec.AcceptConstant(cons)
556556
if err != nil {
557557
s.StopParse = true
558-
s.ErrorCallback(err)
558+
s.ErrorCallback.AddError(err)
559559
}
560560
}
561561

@@ -570,7 +570,7 @@ func (s *GruleV3ParserListener) ExitStringLiteral(ctx *grulev3.StringLiteralCont
570570
}
571571
dec, err := unquoteString(ctx.GetText())
572572
if err != nil {
573-
s.ErrorCallback(fmt.Errorf("error parsing quoted string (%s): %s", ctx.GetText(), err.Error()))
573+
s.ErrorCallback.AddError(fmt.Errorf("error parsing quoted string (%s): %s", ctx.GetText(), err.Error()))
574574
return
575575
}
576576
receiver := s.Stack.Peek().(ast.StringLiteralReceiver)
@@ -606,7 +606,7 @@ func (s *GruleV3ParserListener) ExitIntegerLiteral(ctx *grulev3.IntegerLiteralCo
606606
i, err := strconv.ParseInt(ctx.GetText(), 0, 64)
607607
if err != nil {
608608
s.StopParse = true
609-
s.ErrorCallback(err)
609+
s.ErrorCallback.AddError(err)
610610
} else {
611611
lit.Integer = i
612612
}
@@ -623,7 +623,7 @@ func (s *GruleV3ParserListener) ExitFloatLiteral(ctx *grulev3.FloatLiteralContex
623623
i, err := strconv.ParseFloat(ctx.GetText(), 64)
624624
if err != nil {
625625
s.StopParse = true
626-
s.ErrorCallback(err)
626+
s.ErrorCallback.AddError(err)
627627
} else {
628628
lit.Float = i
629629
}

antlr/GruleParserV3_test.go

+35-34
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/antlr/antlr4/runtime/Go/antlr"
2020
parser "github.com/hyperjumptech/grule-rule-engine/antlr/parser/grulev3"
2121
"github.com/hyperjumptech/grule-rule-engine/ast"
22+
"github.com/hyperjumptech/grule-rule-engine/pkg"
2223
"github.com/stretchr/testify/assert"
2324
"io/ioutil"
2425
"reflect"
@@ -137,19 +138,20 @@ func TestV3Parser(t *testing.T) {
137138
lexer := parser.Newgrulev3Lexer(is)
138139
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
139140

140-
var parseError error
141+
errReporter := &pkg.GruleErrorReporter{
142+
Errors: make([]error, 0),
143+
}
144+
141145
kb := ast.NewKnowledgeLibrary().GetKnowledgeBase("T", "1")
142146

143-
listener := NewGruleV3ParserListener(kb, func(e error) {
144-
parseError = e
145-
})
147+
listener := NewGruleV3ParserListener(kb, errReporter)
146148

147149
psr := parser.Newgrulev3Parser(stream)
148150
psr.BuildParseTrees = true
149151
antlr.ParseTreeWalkerDefault.Walk(listener, psr.Grl())
150152

151-
if parseError != nil {
152-
t.Log(parseError)
153+
if errReporter.HasError() {
154+
t.Log(errReporter.Error())
153155
t.FailNow()
154156
}
155157
}
@@ -164,20 +166,19 @@ func TestV3Parser2(t *testing.T) {
164166
lexer := parser.Newgrulev3Lexer(is)
165167
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
166168

167-
var parseError error
169+
errReporter := &pkg.GruleErrorReporter{
170+
Errors: make([]error, 0),
171+
}
168172
kb := ast.NewKnowledgeLibrary().GetKnowledgeBase("T", "1")
169173

170-
listener := NewGruleV3ParserListener(kb, func(e error) {
171-
parseError = e
172-
panic(e)
173-
})
174+
listener := NewGruleV3ParserListener(kb, errReporter)
174175

175176
psr := parser.Newgrulev3Parser(stream)
176177
psr.BuildParseTrees = true
177178
antlr.ParseTreeWalkerDefault.Walk(listener, psr.Grl())
178179

179-
if parseError != nil {
180-
t.Log(parseError)
180+
if errReporter.HasError() {
181+
t.Log(errReporter.Error())
181182
t.FailNow()
182183
}
183184
}
@@ -189,18 +190,18 @@ func TestV3ParserEscapedStringInvalid(t *testing.T) {
189190
lexer := parser.Newgrulev3Lexer(is)
190191
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
191192

192-
var parseError error
193+
errReporter := &pkg.GruleErrorReporter{
194+
Errors: make([]error, 0),
195+
}
193196
kb := ast.NewKnowledgeLibrary().GetKnowledgeBase("T", "1")
194197

195-
listener := NewGruleV3ParserListener(kb, func(e error) {
196-
parseError = e
197-
})
198+
listener := NewGruleV3ParserListener(kb, errReporter)
198199

199200
psr := parser.Newgrulev3Parser(stream)
200201
psr.BuildParseTrees = true
201202
antlr.ParseTreeWalkerDefault.Walk(listener, psr.Grl())
202203

203-
if parseError == nil {
204+
if errReporter.HasError() == false {
204205
t.Fatal("Successfully parsed invalid string literal, should have gotten an error")
205206
}
206207
}
@@ -212,18 +213,18 @@ func TestV3ParserEscapedStringValid(t *testing.T) {
212213
lexer := parser.Newgrulev3Lexer(is)
213214
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
214215

215-
var parseError error
216+
errReporter := &pkg.GruleErrorReporter{
217+
Errors: make([]error, 0),
218+
}
216219
kb := ast.NewKnowledgeLibrary().GetKnowledgeBase("T", "1")
217220

218-
listener := NewGruleV3ParserListener(kb, func(e error) {
219-
parseError = e
220-
})
221+
listener := NewGruleV3ParserListener(kb, errReporter)
221222

222223
psr := parser.Newgrulev3Parser(stream)
223224
psr.BuildParseTrees = true
224225
antlr.ParseTreeWalkerDefault.Walk(listener, psr.Grl())
225226

226-
if parseError != nil {
227+
if errReporter.HasError() {
227228
t.Fatal("Failed to parse rule with escaped string constant")
228229
}
229230
}
@@ -245,18 +246,18 @@ rule SpeedUp "When testcar is speeding up we keep increase the speed." salience
245246
lexer := parser.Newgrulev3Lexer(is)
246247
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
247248

248-
var parseError error
249+
errReporter := &pkg.GruleErrorReporter{
250+
Errors: make([]error, 0),
251+
}
249252
kb := ast.NewKnowledgeLibrary().GetKnowledgeBase("T", "1")
250253

251-
listener := NewGruleV3ParserListener(kb, func(e error) {
252-
parseError = e
253-
})
254+
listener := NewGruleV3ParserListener(kb, errReporter)
254255

255256
psr := parser.Newgrulev3Parser(stream)
256257
psr.BuildParseTrees = true
257258
antlr.ParseTreeWalkerDefault.Walk(listener, psr.Grl())
258-
if parseError != nil {
259-
t.Log(parseError)
259+
if errReporter.HasError() {
260+
t.Log(errReporter.Error())
260261
t.FailNow()
261262
}
262263

@@ -287,17 +288,17 @@ func prepareV3TestKnowledgeBase(t *testing.T, grl string) (*ast.KnowledgeBase, *
287288
lexer := parser.Newgrulev3Lexer(is)
288289
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
289290

290-
var parseError error
291+
errReporter := &pkg.GruleErrorReporter{
292+
Errors: make([]error, 0),
293+
}
291294
kb := ast.NewKnowledgeLibrary().GetKnowledgeBase("T", "1")
292295

293-
listener := NewGruleV3ParserListener(kb, func(e error) {
294-
parseError = e
295-
})
296+
listener := NewGruleV3ParserListener(kb, errReporter)
296297

297298
psr := parser.Newgrulev3Parser(stream)
298299
psr.BuildParseTrees = true
299300
antlr.ParseTreeWalkerDefault.Walk(listener, psr.Grl())
300-
assert.NoError(t, parseError)
301+
assert.False(t, errReporter.HasError())
301302
listener.KnowledgeBase.WorkingMemory.IndexVariables()
302303
return kb, kb.WorkingMemory
303304
}

0 commit comments

Comments
 (0)