107 lines
3.3 KiB
Go
107 lines
3.3 KiB
Go
package parsekit_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.makaay.nl/mauricem/go-parsekit"
|
|
)
|
|
|
|
func TestGivenNilTokenHandler_WhenCallingOn_ParsekitPanics(t *testing.T) {
|
|
p := parsekit.NewParser(func(p *parsekit.ParseAPI) {
|
|
p.On(nil)
|
|
})
|
|
RunPanicTest(t, PanicTest{
|
|
func() { p.Execute("") },
|
|
`ParseHandler bug: tokenHandler argument for On\(\) is nil`})
|
|
}
|
|
|
|
func TestGivenStoppedParser_WhenCallingHandle_ParsekitPanics(t *testing.T) {
|
|
otherHandler := func(p *parsekit.ParseAPI) {
|
|
panic("This is not the handler you're looking for")
|
|
}
|
|
p := parsekit.NewParser(func(p *parsekit.ParseAPI) {
|
|
p.Stop()
|
|
p.Handle(otherHandler)
|
|
})
|
|
RunPanicTest(t, PanicTest{
|
|
func() { p.Execute("") },
|
|
`Illegal call to ParseAPI.Handle\(\) from .*ParsekitPanics.func.* at ` +
|
|
`.*/parsehandler_test.go:\d+: no calls allowed after ParseAPI.Stop\(\)`})
|
|
}
|
|
|
|
func TestGivenParserWithError_WhenCallingHandle_ParsekitPanics(t *testing.T) {
|
|
otherHandler := func(p *parsekit.ParseAPI) {
|
|
panic("This is not the handler you're looking for")
|
|
}
|
|
p := parsekit.NewParser(func(p *parsekit.ParseAPI) {
|
|
p.Error("It ends here")
|
|
p.Handle(otherHandler)
|
|
})
|
|
RunPanicTest(t, PanicTest{
|
|
func() { p.Execute("") },
|
|
`Illegal call to ParseAPI\.Handle\(\) from .*ParsekitPanics\.func2 at ` +
|
|
`.*/parsehandler_test\.go:\d+: no calls allowed after ParseAPI\.Error\(\)`})
|
|
}
|
|
|
|
type parserWithLoop struct {
|
|
loopCounter int
|
|
}
|
|
|
|
func (l *parserWithLoop) first(p *parsekit.ParseAPI) {
|
|
p.On(parsekit.A.ASCII).Accept()
|
|
p.Handle(l.second)
|
|
}
|
|
|
|
func (l *parserWithLoop) second(p *parsekit.ParseAPI) {
|
|
p.On(parsekit.A.ASCII).Accept()
|
|
p.Handle(l.third)
|
|
}
|
|
|
|
func (l *parserWithLoop) third(p *parsekit.ParseAPI) {
|
|
if l.loopCounter++; l.loopCounter > 100 {
|
|
p.Error("Loop not detected by parsekit")
|
|
return
|
|
}
|
|
p.On(parsekit.A.ASCII).Accept()
|
|
p.Handle(l.first)
|
|
}
|
|
|
|
func TestGivenLoopingParserDefinition_ParserPanics(t *testing.T) {
|
|
looper := &parserWithLoop{}
|
|
parser := parsekit.NewParser(looper.first)
|
|
RunPanicTest(t, PanicTest{
|
|
func() { parser.Execute("Het houdt niet op, niet vanzelf") },
|
|
`Loop detected in parser in .*\(\*parserWithLoop\).second at .*/parsehandler_test\.go:\d+`})
|
|
}
|
|
|
|
// 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() {
|
|
}
|
|
p.Stop()
|
|
})
|
|
RunPanicTest(t, PanicTest{
|
|
func() { parser.Execute("This will end soon") },
|
|
`Loop detected in parser in .*ParserPanics.* at .*/parsehandler_test.go:\d+`})
|
|
}
|
|
|
|
func TestGivenNullHandler_HandlePanics(t *testing.T) {
|
|
parser := parsekit.NewParser(nil)
|
|
RunPanicTest(t, PanicTest{
|
|
func() { parser.Execute("") },
|
|
`ParseAPI.Handle\(\) called with nil input from .*\(\*Parser\).Execute at .*/parsekit\.go:\d+`})
|
|
}
|