mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
61b8c1463d
This helper accepts JSON or YAML, and used to do this: 1. For YAML input, yaml.YAMLToJSON would parse it as yaml, marshal it to JSON, and pass that back out to be passed to UnmarshalJSON 2. For JSON input, yaml.YAMLToJSON would also parse it as yaml, marshal it to JSON, and pass that back out to UnmarshalJSON Issue #4673 has shown that the theoretical "superset" propery of YAML doesn't seem to hold in all cases. So now, we'll do this: 1. For YAML input, yaml.YAMLToJSON would parse it as yaml, marshal it to JSON, and pass that back out to be passed to UnmarshalJSON 2. For JSON input, json.Valid will determine that it's JSON, and we'll feed it into UnmarshalJSON as-is. The YAML path (1.) still seems suboptimal, but I also suspect that JSON is more common. Also, this change shouldn't make the YAML path much worse: determining that yaml string isn't valid JSON should be quick. Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
125 lines
2.8 KiB
Go
125 lines
2.8 KiB
Go
// Copyright 2018 The OPA Authors. All rights reserved.
|
|
// Use of this source code is governed by an Apache2
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package util_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/open-policy-agent/opa/util"
|
|
)
|
|
|
|
func TestInvalidJSONInput(t *testing.T) {
|
|
cases := [][]byte{
|
|
[]byte("{ \"k\": 1 }\n{}}"),
|
|
[]byte("{ \"k\": 1 }\n!!!}"),
|
|
}
|
|
for _, tc := range cases {
|
|
var x interface{}
|
|
err := util.UnmarshalJSON(tc, &x)
|
|
if err == nil {
|
|
t.Errorf("should be an error")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRoundTrip(t *testing.T) {
|
|
cases := []interface{}{
|
|
nil,
|
|
1,
|
|
1.1,
|
|
false,
|
|
[]int{1},
|
|
[]bool{true},
|
|
[]string{"foo"},
|
|
map[string]string{"foo": "bar"},
|
|
struct {
|
|
F string `json:"foo"`
|
|
B int `json:"bar"`
|
|
}{"x", 32},
|
|
map[string][]int{
|
|
"ones": {1, 1, 1},
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(fmt.Sprintf("input %v", tc), func(t *testing.T) {
|
|
err := util.RoundTrip(&tc)
|
|
if err != nil {
|
|
t.Errorf("expected error=nil, got %s", err.Error())
|
|
}
|
|
switch x := tc.(type) {
|
|
// These are the output types we want, nothing else
|
|
case nil, bool, json.Number, int64, float64, int, string, []interface{},
|
|
[]string, map[string]interface{}, map[string]string:
|
|
default:
|
|
t.Errorf("unexpected type %T", x)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestReference(t *testing.T) {
|
|
cases := []interface{}{
|
|
nil,
|
|
func() interface{} { f := interface{}(nil); return &f }(),
|
|
1,
|
|
func() interface{} { f := 1; return &f }(),
|
|
1.1,
|
|
func() interface{} { f := 1.1; return &f }(),
|
|
false,
|
|
func() interface{} { f := false; return &f }(),
|
|
[]int{1},
|
|
&[]int{1},
|
|
func() interface{} { f := &[]int{1}; return &f }(),
|
|
[]bool{true},
|
|
&[]bool{true},
|
|
func() interface{} { f := &[]bool{true}; return &f }(),
|
|
[]string{"foo"},
|
|
&[]string{"foo"},
|
|
func() interface{} { f := &[]string{"foo"}; return &f }(),
|
|
map[string]string{"foo": "bar"},
|
|
&map[string]string{"foo": "bar"},
|
|
func() interface{} { f := &map[string]string{"foo": "bar"}; return &f }(),
|
|
struct {
|
|
F string `json:"foo"`
|
|
B int `json:"bar"`
|
|
}{"x", 32},
|
|
&struct {
|
|
F string `json:"foo"`
|
|
B int `json:"bar"`
|
|
}{"x", 32},
|
|
map[string][]int{
|
|
"ones": {1, 1, 1},
|
|
},
|
|
&map[string][]int{
|
|
"ones": {1, 1, 1},
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(fmt.Sprintf("input %v", tc), func(t *testing.T) {
|
|
ref := util.Reference(tc)
|
|
rv := reflect.ValueOf(ref)
|
|
if rv.Kind() != reflect.Ptr {
|
|
t.Fatalf("expected pointer, got %v", rv.Kind())
|
|
}
|
|
if rv.Elem().Kind() == reflect.Ptr {
|
|
t.Error("expected non-pointer element")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// There's valid JSON that doesn't pass through yaml.YAMLToJSON.
|
|
// See https://github.com/open-policy-agent/opa/issues/4673
|
|
func TestInvalidYAMLValidJSON(t *testing.T) {
|
|
x := []byte{0x22, 0x3a, 0xc2, 0x9a, 0x22}
|
|
y := ""
|
|
if err := util.Unmarshal(x, &y); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|