diff --git a/parsehandler_test.go b/parsehandler_test.go index b5c7ec5..cf654aa 100644 --- a/parsehandler_test.go +++ b/parsehandler_test.go @@ -1,6 +1,7 @@ package parsekit_test import ( + "fmt" "testing" "git.makaay.nl/mauricem/go-parsekit" @@ -106,3 +107,31 @@ func TestGivenLoopingParserDefinition_ParserPanics(t *testing.T) { "(*parserWithLoop).second at /home/ubuntu/Projects/Parsekit/go-parsekit" + "/parsehandler_test.go, line 87"}) } + +// This test incorporates an actual loop bug that I dropped on myself and +// that I could not easily spot in my code. It sounded so logical: +// I want to get chunks of 5 chars from the input, so I simply loop on: +// +// p.On(c.Max(5, a.AnyRune)) +// +// The problem here is that Max(5, ...) will also match when there is +// no more input, since Max(5, ---) is actually MinMax(0, 5, ...). +// Therefore the loop will never stop. Solving the loop was simple: +// +// p.On(c.MinMax(1, 5, a.AnyRune)) +// +// Now the loop stops when the parser finds no more matching input data. +func TestGivenLoopingParserDefinition2_ParserPanics(t *testing.T) { + parser := parsekit.NewParser(func(p *parsekit.ParseAPI) { + for p.On(c.Max(5, a.AnyRune)).Accept() { + fmt.Printf("Cycle: %s\n", p.BufLiteral()) + p.BufClear() + } + p.Stop() + }) + RunPanicTest(t, PanicTest{ + func() { parser.Execute("This will end soon") }, + "Loop detected in parser in git.makaay.nl/mauricem/go-parsekit_test." + + "TestGivenLoopingParserDefinition2_ParserPanics.func1 at " + + "/home/ubuntu/Projects/Parsekit/go-parsekit/parsehandler_test.go, line 126"}) +}