forked from TrueCloudLab/frostfs-sdk-go
Evgenii Stratonikov
a02c0bfac8
Brackets can be semantically important and must not be omitted, otherwise the output is plain wrong. We do not take the responsibility to preserve every bracket, though, because parser does some optimizations related to grouping long chains of filters combined with the same operation. Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
129 lines
2.9 KiB
Go
129 lines
2.9 KiB
Go
package netmap_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
. "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
|
netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestPlacementPolicyEncoding(t *testing.T) {
|
|
v := netmaptest.PlacementPolicy()
|
|
|
|
t.Run("binary", func(t *testing.T) {
|
|
var v2 PlacementPolicy
|
|
require.NoError(t, v2.Unmarshal(v.Marshal()))
|
|
|
|
require.Equal(t, v, v2)
|
|
})
|
|
|
|
t.Run("json", func(t *testing.T) {
|
|
data, err := v.MarshalJSON()
|
|
require.NoError(t, err)
|
|
|
|
var v2 PlacementPolicy
|
|
require.NoError(t, v2.UnmarshalJSON(data))
|
|
|
|
require.Equal(t, v, v2)
|
|
})
|
|
}
|
|
|
|
func TestPlacementPolicyWriteString(t *testing.T) {
|
|
var testCases = []struct {
|
|
name string
|
|
input string
|
|
output string // If the output is empty, make it equal to input.
|
|
}{
|
|
{
|
|
name: "no compound operators",
|
|
input: `REP 1
|
|
CBF 1
|
|
SELECT 1 FROM Color
|
|
FILTER Color EQ Red AS Color`,
|
|
},
|
|
{
|
|
name: "no brackets in single level same-operator chain",
|
|
input: `REP 1
|
|
CBF 1
|
|
SELECT 1 FROM Color
|
|
FILTER Color EQ Red OR Color EQ Blue OR Color EQ Green AS Color`,
|
|
},
|
|
{
|
|
name: "no brackets aroung higher precedence op",
|
|
input: `REP 1
|
|
CBF 1
|
|
SELECT 1 FROM Color
|
|
FILTER Color EQ Red OR Color EQ Blue AND Color NE Green AS Color`,
|
|
},
|
|
{
|
|
name: "no brackets aroung higher precedence op, even if present in the input",
|
|
input: `REP 1
|
|
CBF 1
|
|
SELECT 1 FROM Color
|
|
FILTER Color EQ Red OR (Color EQ Blue AND Color NE Green) AS Color`,
|
|
output: `REP 1
|
|
CBF 1
|
|
SELECT 1 FROM Color
|
|
FILTER Color EQ Red OR Color EQ Blue AND Color NE Green AS Color`,
|
|
},
|
|
{
|
|
name: "brackets aroung lower precedence op",
|
|
input: `REP 1
|
|
CBF 1
|
|
SELECT 1 FROM Color
|
|
FILTER (Color EQ Red OR Color EQ Blue) AND Color NE Green AS Color`,
|
|
},
|
|
{
|
|
name: "no extra brackets for bracketed same-operator chain",
|
|
input: `REP 1
|
|
CBF 1
|
|
SELECT 1 FROM Color
|
|
FILTER (Color EQ Red OR Color EQ Blue OR Color EQ Yellow) AND Color NE Green AS Color`,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
var p PlacementPolicy
|
|
require.NoError(t, p.DecodeString(tc.input))
|
|
|
|
var sb strings.Builder
|
|
require.NoError(t, p.WriteStringTo(&sb))
|
|
|
|
if tc.output == "" {
|
|
require.Equal(t, tc.input, sb.String())
|
|
} else {
|
|
require.Equal(t, tc.output, sb.String())
|
|
|
|
var p1 PlacementPolicy
|
|
require.NoError(t, p1.DecodeString(tc.output))
|
|
require.Equal(t, p, p1)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDecodeSelectFilterExpr(t *testing.T) {
|
|
for _, s := range []string{
|
|
"SELECT 1 FROM *",
|
|
"FILTER Color EQ 'Red' AS RedNode",
|
|
`
|
|
FILTER Color EQ 'Red' AS RedNode
|
|
FILTER @RedNode AND Shape EQ 'Cirle' AS RedCircleNode
|
|
`,
|
|
`
|
|
SELECT 1 FROM RedCircleNode
|
|
FILTER Color EQ 'Red' AS RedNode
|
|
FILTER @RedNode AND Shape EQ 'Cirle' AS RedCircleNode
|
|
`,
|
|
`
|
|
CBF 1
|
|
SELECT 1 FROM RedCircleNode
|
|
FILTER Color EQ 'Red' AS RedNode
|
|
FILTER @RedNode AND Shape EQ 'Cirle' AS RedCircleNode
|
|
`,
|
|
} {
|
|
_, err := DecodeSelectFilterString(s)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|