2024-10-22 12:42:15 +02:00
|
|
|
package selector
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"math"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestParse(t *testing.T) {
|
|
|
|
|
t.Run("identity", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 1, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("dotted field name", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".foo")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 1, len(sel))
|
|
|
|
|
require.False(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Equal(t, sel[0].Field(), "foo")
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
2024-11-20 12:37:29 -05:00
|
|
|
|
|
|
|
|
sel, err = Parse(".foo_bar")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 1, len(sel))
|
|
|
|
|
require.False(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Equal(t, sel[0].Field(), "foo_bar")
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".foo-bar")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 1, len(sel))
|
|
|
|
|
require.False(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Equal(t, sel[0].Field(), "foo-bar")
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".foo*bar")
|
|
|
|
|
require.ErrorContains(t, err, "invalid segment")
|
2024-10-22 12:42:15 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("explicit field", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(`.["foo"]`)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Equal(t, sel[1].Field(), "foo")
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("iterator, collection value", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.True(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("index", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[138]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Equal(t, sel[1].Index(), 138)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("negative index", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[-138]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Equal(t, sel[1].Index(), -138)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("List slice", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[7:11]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{7, 11})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".[2:]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{2, math.MaxInt})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".[:42]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{math.MinInt, 42})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".[0:-2]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{0, -2})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("optional identity", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 1, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.True(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("optional dotted field name", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".foo?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 1, len(sel))
|
|
|
|
|
require.False(t, sel[0].Identity())
|
|
|
|
|
require.True(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Equal(t, sel[0].Field(), "foo")
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("optional explicit field", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(`.["foo"]?`)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Equal(t, sel[1].Field(), "foo")
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("optional iterator", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[]?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.True(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("optional index", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[138]?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Equal(t, sel[1].Index(), 138)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("optional negative index", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[-138]?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Equal(t, sel[1].Index(), -138)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("optional list slice", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[7:11]?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{7, 11})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".[2:]?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{2, math.MaxInt})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".[:42]?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{math.MinInt, 42})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
|
|
|
|
|
sel, err = Parse(".[0:-2]?")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.True(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{0, -2})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("idempotent optional", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".foo???")
|
|
|
|
|
require.NoError(t, err)
|
2024-10-22 17:33:28 +02:00
|
|
|
require.Equal(t, 1, len(sel))
|
|
|
|
|
require.False(t, sel[0].Identity())
|
|
|
|
|
require.True(t, sel[0].Optional())
|
2024-10-22 12:42:15 +02:00
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
2024-10-22 17:33:28 +02:00
|
|
|
require.Equal(t, sel[0].Field(), "foo")
|
2024-10-22 12:42:15 +02:00
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("deny multi dot", func(t *testing.T) {
|
|
|
|
|
_, err := Parse("..")
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("nesting", func(t *testing.T) {
|
|
|
|
|
str := `.foo.["bar"].[138]?.baz[1:]`
|
|
|
|
|
sel, err := Parse(str)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, str, sel.String())
|
|
|
|
|
require.Equal(t, 7, len(sel))
|
|
|
|
|
require.False(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Equal(t, sel[0].Field(), "foo")
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.True(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
require.False(t, sel[2].Identity())
|
|
|
|
|
require.False(t, sel[2].Optional())
|
|
|
|
|
require.False(t, sel[2].Iterator())
|
|
|
|
|
require.Empty(t, sel[2].Slice())
|
|
|
|
|
require.Equal(t, sel[2].Field(), "bar")
|
|
|
|
|
require.Empty(t, sel[2].Index())
|
|
|
|
|
require.True(t, sel[3].Identity())
|
|
|
|
|
require.False(t, sel[3].Optional())
|
|
|
|
|
require.False(t, sel[3].Iterator())
|
|
|
|
|
require.Empty(t, sel[3].Slice())
|
|
|
|
|
require.Empty(t, sel[3].Field())
|
|
|
|
|
require.Empty(t, sel[3].Index())
|
|
|
|
|
require.False(t, sel[4].Identity())
|
|
|
|
|
require.True(t, sel[4].Optional())
|
|
|
|
|
require.False(t, sel[4].Iterator())
|
|
|
|
|
require.Empty(t, sel[4].Slice())
|
|
|
|
|
require.Empty(t, sel[4].Field())
|
|
|
|
|
require.Equal(t, sel[4].Index(), 138)
|
|
|
|
|
require.False(t, sel[5].Identity())
|
|
|
|
|
require.False(t, sel[5].Optional())
|
|
|
|
|
require.False(t, sel[5].Iterator())
|
|
|
|
|
require.Empty(t, sel[5].Slice())
|
|
|
|
|
require.Equal(t, sel[5].Field(), "baz")
|
|
|
|
|
require.Empty(t, sel[5].Index())
|
|
|
|
|
require.False(t, sel[6].Identity())
|
|
|
|
|
require.False(t, sel[6].Optional())
|
|
|
|
|
require.False(t, sel[6].Iterator())
|
|
|
|
|
require.Equal(t, sel[6].Slice(), []int64{1, math.MaxInt})
|
|
|
|
|
require.Empty(t, sel[6].Field())
|
|
|
|
|
require.Empty(t, sel[6].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("non dotted", func(t *testing.T) {
|
|
|
|
|
_, err := Parse("foo")
|
|
|
|
|
require.NotNil(t, err)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("non quoted", func(t *testing.T) {
|
|
|
|
|
_, err := Parse(".[foo]")
|
|
|
|
|
require.NotNil(t, err)
|
|
|
|
|
})
|
2024-10-23 16:37:35 +02:00
|
|
|
|
|
|
|
|
t.Run("slice with negative start and positive end", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[0:-2]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{0, -2})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice with start greater than end", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(".[5:2]")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{5, 2})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice on string", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(`.["foo"].[1:3]`)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 4, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Equal(t, sel[1].Field(), "foo")
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
require.True(t, sel[2].Identity())
|
|
|
|
|
require.False(t, sel[2].Optional())
|
|
|
|
|
require.False(t, sel[2].Iterator())
|
|
|
|
|
require.Empty(t, sel[2].Slice())
|
|
|
|
|
require.Empty(t, sel[2].Field())
|
|
|
|
|
require.Empty(t, sel[2].Index())
|
|
|
|
|
require.False(t, sel[3].Identity())
|
|
|
|
|
require.False(t, sel[3].Optional())
|
|
|
|
|
require.False(t, sel[3].Iterator())
|
|
|
|
|
require.Equal(t, sel[3].Slice(), []int64{1, 3})
|
|
|
|
|
require.Empty(t, sel[3].Field())
|
|
|
|
|
require.Empty(t, sel[3].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice on array", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(`.[1:3]`)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Equal(t, sel[1].Slice(), []int64{1, 3})
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("index on array", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(`.[1]`)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Empty(t, sel[1].Field())
|
|
|
|
|
require.Equal(t, sel[1].Index(), 1)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("invalid slice on object", func(t *testing.T) {
|
|
|
|
|
_, err := Parse(`.["foo":"bar"]`)
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
require.Contains(t, err.Error(), "invalid segment")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("index on object", func(t *testing.T) {
|
|
|
|
|
sel, err := Parse(`.["foo"]`)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, 2, len(sel))
|
|
|
|
|
require.True(t, sel[0].Identity())
|
|
|
|
|
require.False(t, sel[0].Optional())
|
|
|
|
|
require.False(t, sel[0].Iterator())
|
|
|
|
|
require.Empty(t, sel[0].Slice())
|
|
|
|
|
require.Empty(t, sel[0].Field())
|
|
|
|
|
require.Empty(t, sel[0].Index())
|
|
|
|
|
require.False(t, sel[1].Identity())
|
|
|
|
|
require.False(t, sel[1].Optional())
|
|
|
|
|
require.False(t, sel[1].Iterator())
|
|
|
|
|
require.Empty(t, sel[1].Slice())
|
|
|
|
|
require.Equal(t, sel[1].Field(), "foo")
|
|
|
|
|
require.Empty(t, sel[1].Index())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice with non-integer start", func(t *testing.T) {
|
|
|
|
|
_, err := Parse(".[foo:3]")
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice with non-integer end", func(t *testing.T) {
|
|
|
|
|
_, err := Parse(".[1:bar]")
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("index with non-integer", func(t *testing.T) {
|
|
|
|
|
_, err := Parse(".[foo]")
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
})
|
2024-11-29 19:32:31 +01:00
|
|
|
|
|
|
|
|
t.Run("extended field names", func(t *testing.T) {
|
|
|
|
|
validFields := []string{
|
|
|
|
|
".basic",
|
|
|
|
|
".user_name",
|
|
|
|
|
".user-name",
|
|
|
|
|
".userName$special",
|
|
|
|
|
".αβγ", // Greek letters
|
|
|
|
|
".użytkownik", // Polish characters
|
|
|
|
|
".用户", // Chinese characters
|
|
|
|
|
".사용자", // Korean characters
|
|
|
|
|
"._private",
|
|
|
|
|
".number123",
|
|
|
|
|
".camelCase",
|
|
|
|
|
".snake_case",
|
|
|
|
|
".kebab-case",
|
|
|
|
|
".mixed_kebab-case",
|
|
|
|
|
".with$dollar",
|
|
|
|
|
".MIXED_Case_123",
|
2024-12-02 18:30:41 +01:00
|
|
|
".unicodeø",
|
2024-11-29 19:32:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, field := range validFields {
|
|
|
|
|
sel, err := Parse(field)
|
|
|
|
|
require.NoError(t, err, "field: %s", field)
|
|
|
|
|
require.NotNil(t, sel)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
invalidFields := []string{
|
|
|
|
|
".123number", // Can't start with digit
|
|
|
|
|
".@special", // @ not allowed
|
|
|
|
|
".space name", // No spaces
|
|
|
|
|
".#hashtag", // No #
|
|
|
|
|
".name!", // No !
|
|
|
|
|
".{brackets}", // No brackets
|
|
|
|
|
".name/with/slashes", // No slashes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, field := range invalidFields {
|
|
|
|
|
sel, err := Parse(field)
|
|
|
|
|
require.Error(t, err, "field: %s", field)
|
|
|
|
|
require.Nil(t, sel)
|
|
|
|
|
}
|
|
|
|
|
})
|
2024-10-22 12:42:15 +02:00
|
|
|
}
|