Added Try tests
This commit is contained in:
parent
abef123f8a
commit
bc2f7aa911
@ -5,7 +5,7 @@ package gigaparsec_test
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.codemonkeysoftware.net/b/gigaparsec"
|
||||
@ -127,8 +127,32 @@ func TestSatisfy(t *testing.T) {
|
||||
Todo(t)
|
||||
}
|
||||
|
||||
func Try(t *testing.T) {
|
||||
Todo(t)
|
||||
func TestTry(t *testing.T) {
|
||||
type R = ptest.ForcedResult
|
||||
var cases = []struct{ P, TryP R }{
|
||||
{P: R{Succeed: false, Consume: false}, TryP: R{Succeed: false, Consume: false}},
|
||||
{P: R{Succeed: false, Consume: true}, TryP: R{Succeed: false, Consume: false}},
|
||||
{P: R{Succeed: true, Consume: false}, TryP: R{Succeed: true, Consume: false}},
|
||||
{P: R{Succeed: true, Consume: true}, TryP: R{Succeed: true, Consume: true}},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(fmt.Sprintf("%+v", c.P), func(t *testing.T) {
|
||||
start := gigaparsec.MakeState(gigaparsec.SliceReaderAt[R]{c.P})
|
||||
result, err := gigaparsec.Try(ptest.ForceResult)(start)
|
||||
succeeded, _, _ := result.Status()
|
||||
must.NoError(t, err)
|
||||
test.EqOp(t, c.TryP.Succeed, succeeded)
|
||||
test.EqOp(t, c.TryP.Consume, result.Consumed())
|
||||
})
|
||||
}
|
||||
t.Run("fails on error", func(t *testing.T) {
|
||||
expectedErr := errors.New("it broke")
|
||||
p := gigaparsec.Try(gigaparsec.Match(byte(0)))
|
||||
result, err := p(gigaparsec.MakeState(ptest.ErrReaderAt(expectedErr)))
|
||||
succeeded, _, _ := result.Status()
|
||||
test.ErrorIs(t, err, expectedErr)
|
||||
test.False(t, succeeded)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabel(t *testing.T) {
|
||||
@ -158,39 +182,19 @@ func TestRepeat(t *testing.T) {
|
||||
}
|
||||
}))
|
||||
t.Run("consumes iff at least one application consumes", rapid.MakeCheck(func(t *rapid.T) {
|
||||
type Token struct {
|
||||
Consume, Succeed bool
|
||||
}
|
||||
// p will succeed and consume based on the values in the parsed token.
|
||||
var p gigaparsec.Parser[Token, Token] = func(s gigaparsec.State[Token]) (gigaparsec.Result[Token, Token], error) {
|
||||
buf := make([]Token, 1)
|
||||
_, next, err := s.Read(buf)
|
||||
if errors.Is(err, io.EOF) {
|
||||
return gigaparsec.Fail[Token, Token](false, gigaparsec.MessageEnd(s.Pos())), nil
|
||||
}
|
||||
if err != nil {
|
||||
return gigaparsec.Result[Token, Token]{}, err
|
||||
}
|
||||
tok := buf[0]
|
||||
if tok.Succeed {
|
||||
return gigaparsec.Succeed(tok.Consume, tok, next, gigaparsec.MessageOK(s.Pos())), nil
|
||||
} else {
|
||||
return gigaparsec.Fail[Token, Token](tok.Consume, gigaparsec.MakeMessage(s.Pos(), "false", "true")), nil
|
||||
}
|
||||
}
|
||||
|
||||
input := rapid.Map(rapid.SliceOfN(rapid.Just(Token{Succeed: true}), 0, 100),
|
||||
func(ts []Token) []Token { return append(ts, Token{}) }).Draw(t, "input")
|
||||
input := rapid.Map(rapid.SliceOfN(rapid.Just(ptest.ForcedResult{Succeed: true}), 0, 100),
|
||||
func(ts []ptest.ForcedResult) []ptest.ForcedResult { return append(ts, ptest.ForcedResult{}) }).Draw(t, "input")
|
||||
consumeAt := rapid.Ptr(rapid.IntRange(0, len(input)-1), true).Draw(t, "consumeAt")
|
||||
if consumeAt != nil {
|
||||
input[*consumeAt].Consume = true
|
||||
}
|
||||
shouldConsume := consumeAt != nil
|
||||
|
||||
result, err := gigaparsec.Repeat(0, p)(gigaparsec.MakeState(gigaparsec.SliceReaderAt[Token](input)))
|
||||
result, err := gigaparsec.Repeat(0, ptest.ForceResult)(gigaparsec.MakeState(gigaparsec.SliceReaderAt[ptest.ForcedResult](input)))
|
||||
must.NoError(t, err)
|
||||
test.EqOp(t, shouldConsume, result.Consumed())
|
||||
}))
|
||||
|
||||
t.Run("does not consume on empty input", func(t *testing.T) {
|
||||
p := gigaparsec.Repeat(0, gigaparsec.Match(0))
|
||||
result, err := p(gigaparsec.MakeState(gigaparsec.SliceReaderAt[int](nil)))
|
||||
|
@ -4,6 +4,7 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"git.codemonkeysoftware.net/b/gigaparsec"
|
||||
@ -34,3 +35,22 @@ func SliceOfN[T any](value T, n int) []T {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type ForcedResult struct{ Succeed, Consume bool }
|
||||
|
||||
func ForceResult(state gigaparsec.State[ForcedResult]) (gigaparsec.Result[ForcedResult, struct{}], error) {
|
||||
buf := make([]ForcedResult, 1)
|
||||
_, next, err := state.Read(buf)
|
||||
if errors.Is(err, io.EOF) {
|
||||
return gigaparsec.Fail[ForcedResult, struct{}](false, gigaparsec.MessageEnd(state.Pos())), nil
|
||||
}
|
||||
if err != nil {
|
||||
return gigaparsec.Result[ForcedResult, struct{}]{}, err
|
||||
}
|
||||
tok := buf[0]
|
||||
if tok.Succeed {
|
||||
return gigaparsec.Succeed(tok.Consume, struct{}{}, next, gigaparsec.MessageOK(state.Pos())), nil
|
||||
} else {
|
||||
return gigaparsec.Fail[ForcedResult, struct{}](tok.Consume, gigaparsec.MakeMessage(state.Pos(), "Succeed=false", "Succeed=true")), nil
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user