Added Try tests
This commit is contained in:
parent
abef123f8a
commit
bc2f7aa911
@ -5,7 +5,7 @@ package gigaparsec_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.codemonkeysoftware.net/b/gigaparsec"
|
"git.codemonkeysoftware.net/b/gigaparsec"
|
||||||
@ -127,8 +127,32 @@ func TestSatisfy(t *testing.T) {
|
|||||||
Todo(t)
|
Todo(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Try(t *testing.T) {
|
func TestTry(t *testing.T) {
|
||||||
Todo(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) {
|
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) {
|
t.Run("consumes iff at least one application consumes", rapid.MakeCheck(func(t *rapid.T) {
|
||||||
type Token struct {
|
input := rapid.Map(rapid.SliceOfN(rapid.Just(ptest.ForcedResult{Succeed: true}), 0, 100),
|
||||||
Consume, Succeed bool
|
func(ts []ptest.ForcedResult) []ptest.ForcedResult { return append(ts, ptest.ForcedResult{}) }).Draw(t, "input")
|
||||||
}
|
|
||||||
// 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")
|
|
||||||
consumeAt := rapid.Ptr(rapid.IntRange(0, len(input)-1), true).Draw(t, "consumeAt")
|
consumeAt := rapid.Ptr(rapid.IntRange(0, len(input)-1), true).Draw(t, "consumeAt")
|
||||||
if consumeAt != nil {
|
if consumeAt != nil {
|
||||||
input[*consumeAt].Consume = true
|
input[*consumeAt].Consume = true
|
||||||
}
|
}
|
||||||
shouldConsume := consumeAt != nil
|
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)
|
must.NoError(t, err)
|
||||||
test.EqOp(t, shouldConsume, result.Consumed())
|
test.EqOp(t, shouldConsume, result.Consumed())
|
||||||
}))
|
}))
|
||||||
|
|
||||||
t.Run("does not consume on empty input", func(t *testing.T) {
|
t.Run("does not consume on empty input", func(t *testing.T) {
|
||||||
p := gigaparsec.Repeat(0, gigaparsec.Match(0))
|
p := gigaparsec.Repeat(0, gigaparsec.Match(0))
|
||||||
result, err := p(gigaparsec.MakeState(gigaparsec.SliceReaderAt[int](nil)))
|
result, err := p(gigaparsec.MakeState(gigaparsec.SliceReaderAt[int](nil)))
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.codemonkeysoftware.net/b/gigaparsec"
|
"git.codemonkeysoftware.net/b/gigaparsec"
|
||||||
@ -34,3 +35,22 @@ func SliceOfN[T any](value T, n int) []T {
|
|||||||
}
|
}
|
||||||
return s
|
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