blob: bc0ea4c498b42b87e71962da76917c04d4196d90 [file] [log] [blame]
// Copyright 2023 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package starlark_import
import (
"reflect"
"testing"
"go.starlark.net/starlark"
)
func createStarlarkValue(t *testing.T, code string) starlark.Value {
t.Helper()
result, err := starlark.ExecFile(&starlark.Thread{}, "main.bzl", "x = "+code, builtins)
if err != nil {
panic(err)
}
return result["x"]
}
func TestUnmarshalConcreteType(t *testing.T) {
x, err := Unmarshal[string](createStarlarkValue(t, `"foo"`))
if err != nil {
t.Error(err)
return
}
if x != "foo" {
t.Errorf(`Expected "foo", got %q`, x)
}
}
func TestUnmarshalConcreteTypeWithInterfaces(t *testing.T) {
x, err := Unmarshal[map[string]map[string]interface{}](createStarlarkValue(t,
`{"foo": {"foo2": "foo3"}, "bar": {"bar2": ["bar3"]}}`))
if err != nil {
t.Error(err)
return
}
expected := map[string]map[string]interface{}{
"foo": {"foo2": "foo3"},
"bar": {"bar2": []string{"bar3"}},
}
if !reflect.DeepEqual(x, expected) {
t.Errorf(`Expected %v, got %v`, expected, x)
}
}
func TestUnmarshalToStarlarkValue(t *testing.T) {
x, err := Unmarshal[map[string]starlark.Value](createStarlarkValue(t,
`{"foo": "Hi", "bar": None}`))
if err != nil {
t.Error(err)
return
}
if x["foo"].(starlark.String).GoString() != "Hi" {
t.Errorf("Expected \"Hi\", got: %q", x["foo"].(starlark.String).GoString())
}
if x["bar"].Type() != "NoneType" {
t.Errorf("Expected \"NoneType\", got: %q", x["bar"].Type())
}
}
func TestUnmarshal(t *testing.T) {
testCases := []struct {
input string
expected interface{}
}{
{
input: `"foo"`,
expected: "foo",
},
{
input: `5`,
expected: 5,
},
{
input: `["foo", "bar"]`,
expected: []string{"foo", "bar"},
},
{
input: `("foo", "bar")`,
expected: []string{"foo", "bar"},
},
{
input: `("foo",5)`,
expected: []interface{}{"foo", 5},
},
{
input: `{"foo": 5, "bar": 10}`,
expected: map[string]int{"foo": 5, "bar": 10},
},
{
input: `{"foo": ["qux"], "bar": []}`,
expected: map[string][]string{"foo": {"qux"}, "bar": nil},
},
{
input: `struct(Foo="foo", Bar=5)`,
expected: struct {
Foo string
Bar int
}{Foo: "foo", Bar: 5},
},
{
// Unexported fields version of the above
input: `struct(foo="foo", bar=5)`,
expected: struct {
foo string
bar int
}{foo: "foo", bar: 5},
},
{
input: `{"foo": "foo2", "bar": ["bar2"], "baz": 5, "qux": {"qux2": "qux3"}, "quux": {"quux2": "quux3", "quux4": 5}}`,
expected: map[string]interface{}{
"foo": "foo2",
"bar": []string{"bar2"},
"baz": 5,
"qux": map[string]string{"qux2": "qux3"},
"quux": map[string]interface{}{
"quux2": "quux3",
"quux4": 5,
},
},
},
}
for _, tc := range testCases {
x, err := UnmarshalReflect(createStarlarkValue(t, tc.input), reflect.TypeOf(tc.expected))
if err != nil {
t.Error(err)
continue
}
if !reflect.DeepEqual(x.Interface(), tc.expected) {
t.Errorf(`Expected %#v, got %#v`, tc.expected, x.Interface())
}
}
}