frostfs-sdk-go/netmap/policy_test.go
Evgenii Stratonikov a02c0bfac8 [#186] netmap: Marshal policy with brackets
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>
2023-10-27 10:54:45 +03:00

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)
}
}