pulumi/sdk/go/pulumix/context_test.go

532 lines
15 KiB
Go

// Copyright 2016-2023, Pulumi Corporation.
//
// 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 pulumix_test // to avoid import cycles
import (
"reflect"
"testing"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumix"
"github.com/stretchr/testify/require"
)
type testResourceInputs struct {
PuxString pulumix.Input[string]
PuString pulumi.StringInput
PuxStringPtr pulumix.Input[*string]
PuStringPtr pulumi.StringPtrInput
PuxIntArray pulumix.Input[[]int]
PuIntArray pulumi.IntArrayInput
PuxIntMap pulumix.Input[map[string]int]
PuIntMap pulumi.IntMapInput
}
func (*testResourceInputs) ElementType() reflect.Type {
return reflect.TypeOf((*testResourceArgs)(nil))
}
type testResourceArgs struct {
PuxString string `pulumi:"puxString"`
PuString string `pulumi:"puString"`
PuxStringPtr *string `pulumi:"puxStringPtr"`
PuStringPtr *string `pulumi:"puStringPtr"`
PuxIntArray []int `pulumi:"puxIntArray"`
PuIntArray []int `pulumi:"puIntArray"`
PuxIntMap map[string]int `pulumi:"puxIntMap"`
PuIntMap map[string]int `pulumi:"puIntMap"`
}
func TestRegisterResource_inputSerialization(t *testing.T) {
t.Parallel()
j := "j"
tests := []struct {
desc string
give pulumi.Input
want resource.PropertyMap
}{
// --- pulumix.Input[string] ---
{
desc: "pux.String/pu.String",
give: &testResourceInputs{PuxString: pulumi.String("a")},
want: resource.PropertyMap{"puxString": resource.NewStringProperty("a")},
},
{
desc: "pux.String/pu.StringOutput",
give: &testResourceInputs{PuxString: pulumi.String("b").ToStringOutput()},
want: resource.PropertyMap{"puxString": resource.NewStringProperty("b")},
},
{
desc: "pux.String/pux.Output[string]",
give: &testResourceInputs{PuxString: pulumix.Val("c")},
want: resource.PropertyMap{"puxString": resource.NewStringProperty("c")},
},
// --- pulumi.StringInput ---
{
desc: "pu.String/pu.String",
give: &testResourceInputs{PuString: pulumi.String("d")},
want: resource.PropertyMap{"puString": resource.NewStringProperty("d")},
},
{
desc: "pu.String/pu.StringOutput",
give: &testResourceInputs{PuString: pulumi.String("e").ToStringOutput()},
want: resource.PropertyMap{"puString": resource.NewStringProperty("e")},
},
{
desc: "pu.String/pux.Output[string] untyped",
give: &testResourceInputs{PuString: pulumix.Val("f").Untyped().(pulumi.StringOutput)},
want: resource.PropertyMap{"puString": resource.NewStringProperty("f")},
},
// --- pulumix.Input[*string] ---
{
desc: "pux.StringPtr/pu.String PtrOf",
give: &testResourceInputs{PuxStringPtr: pulumix.PtrOf[string](pulumi.String("g"))},
want: resource.PropertyMap{"puxStringPtr": resource.NewStringProperty("g")},
},
{
desc: "pux.StringPtr/pu.StringPtrOutput",
give: &testResourceInputs{PuxStringPtr: pulumi.String("h").ToStringPtrOutput()},
want: resource.PropertyMap{"puxStringPtr": resource.NewStringProperty("h")},
},
{
desc: "pux.StringPtr/pux.PtrOutput[string]",
give: &testResourceInputs{PuxStringPtr: pulumix.Ptr("i")},
want: resource.PropertyMap{"puxStringPtr": resource.NewStringProperty("i")},
},
{
desc: "pux.StringPtr/pux.Output[*string]",
give: &testResourceInputs{PuxStringPtr: pulumix.Val[*string](&j)},
want: resource.PropertyMap{"puxStringPtr": resource.NewStringProperty("j")},
},
// --- pulumi.StringPtrInput ---
{
desc: "pu.StringPtr/pu.StringPtr",
give: &testResourceInputs{PuStringPtr: pulumi.StringPtr("j")},
want: resource.PropertyMap{"puStringPtr": resource.NewStringProperty("j")},
},
{
desc: "pu.StringPtr/pu.String",
give: &testResourceInputs{PuStringPtr: pulumi.String("k")},
want: resource.PropertyMap{"puStringPtr": resource.NewStringProperty("k")},
},
{
desc: "pu.StringPtr/pu.StringPtrOutput",
give: &testResourceInputs{PuStringPtr: pulumi.String("l").ToStringPtrOutput()},
want: resource.PropertyMap{"puStringPtr": resource.NewStringProperty("l")},
},
{
desc: "pu.StringPtr/pux.PtrOutput[string] untyped",
give: &testResourceInputs{PuStringPtr: pulumix.Ptr("m").Untyped().(pulumi.StringPtrOutput)},
want: resource.PropertyMap{"puStringPtr": resource.NewStringProperty("m")},
},
{
desc: "pu.StringPtr/pux.GPtrOutput[string] untyped",
give: &testResourceInputs{
PuStringPtr: pulumix.Cast[pulumix.GPtrOutput[string, pulumi.StringOutput], *string](
pulumix.Ptr("n"),
).Untyped().(pulumi.StringPtrOutput),
},
want: resource.PropertyMap{"puStringPtr": resource.NewStringProperty("n")},
},
// --- pulumix.Input[[]int] ---
{
desc: "pux.IntArray/pu.IntArray",
give: &testResourceInputs{
PuxIntArray: pulumi.IntArray{
pulumi.Int(1),
pulumi.Int(2),
pulumi.Int(3),
},
},
want: resource.PropertyMap{
"puxIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(1),
resource.NewNumberProperty(2),
resource.NewNumberProperty(3),
},
),
},
},
{
desc: "pux.IntArray/pu.IntArrayOutput",
give: &testResourceInputs{
PuxIntArray: pulumi.IntArray{
pulumi.Int(4),
pulumi.Int(5),
pulumi.Int(6),
}.ToIntArrayOutput(),
},
want: resource.PropertyMap{
"puxIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(4),
resource.NewNumberProperty(5),
resource.NewNumberProperty(6),
},
),
},
},
{
desc: "pux.IntArray/pux.Output[[]int]",
give: &testResourceInputs{
PuxIntArray: pulumix.Val([]int{7, 8, 9}),
},
want: resource.PropertyMap{
"puxIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(7),
resource.NewNumberProperty(8),
resource.NewNumberProperty(9),
},
),
},
},
{
desc: "pux.IntArray/pux.ArrayOutput[int]",
give: &testResourceInputs{
PuxIntArray: pulumix.Cast[pulumix.ArrayOutput[int], []int](
pulumix.Val([]int{10, 11, 12}),
),
},
want: resource.PropertyMap{
"puxIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(10),
resource.NewNumberProperty(11),
resource.NewNumberProperty(12),
},
),
},
},
{
desc: "pux.IntArray/pux.GArrayOutput",
give: &testResourceInputs{
PuxIntArray: pulumix.Cast[pulumix.GArrayOutput[int, pulumi.IntOutput], []int](
pulumix.Val([]int{13, 14, 15}),
),
},
want: resource.PropertyMap{
"puxIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(13),
resource.NewNumberProperty(14),
resource.NewNumberProperty(15),
},
),
},
},
// --- pulumi.IntArrayInput ---
{
desc: "pu.IntArray/pux.Output[[]int] untyped",
give: &testResourceInputs{
PuIntArray: pulumix.Val([]int{1, 2, 3}).Untyped().(pulumi.IntArrayOutput),
},
want: resource.PropertyMap{
"puIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(1),
resource.NewNumberProperty(2),
resource.NewNumberProperty(3),
},
),
},
},
{
desc: "pu.IntArray/pux.ArrayOutput[int] untyped",
give: &testResourceInputs{
PuIntArray: pulumix.Cast[pulumix.ArrayOutput[int], []int](
pulumix.Val([]int{4, 5, 6}),
).Untyped().(pulumi.IntArrayOutput),
},
want: resource.PropertyMap{
"puIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(4),
resource.NewNumberProperty(5),
resource.NewNumberProperty(6),
},
),
},
},
{
desc: "pu.IntArray/pux.GArrayOutput untyped",
give: &testResourceInputs{
PuIntArray: pulumix.Cast[pulumix.GArrayOutput[int, pulumi.IntOutput], []int](
pulumix.Val([]int{7, 8, 9}),
).Untyped().(pulumi.IntArrayOutput),
},
want: resource.PropertyMap{
"puIntArray": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewNumberProperty(7),
resource.NewNumberProperty(8),
resource.NewNumberProperty(9),
},
),
},
},
// --- pulumix.Input[map[string]int] ---
{
desc: "pux.IntMap/pu.IntMap",
give: &testResourceInputs{
PuxIntMap: pulumi.IntMap{"a": pulumi.Int(1), "b": pulumi.Int(2)},
},
want: resource.PropertyMap{
"puxIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"a": resource.NewNumberProperty(1),
"b": resource.NewNumberProperty(2),
},
),
},
},
{
desc: "pux.IntMap/pu.IntMapOutput",
give: &testResourceInputs{
PuxIntMap: pulumi.IntMap{"c": pulumi.Int(3), "d": pulumi.Int(4)}.ToIntMapOutput(),
},
want: resource.PropertyMap{
"puxIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"c": resource.NewNumberProperty(3),
"d": resource.NewNumberProperty(4),
},
),
},
},
{
desc: "pux.IntMap/pux.Output[map[string]int]",
give: &testResourceInputs{
PuxIntMap: pulumix.Val(map[string]int{"e": 5, "f": 6}),
},
want: resource.PropertyMap{
"puxIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"e": resource.NewNumberProperty(5),
"f": resource.NewNumberProperty(6),
},
),
},
},
{
desc: "pux.IntMap/pux.MapOutput[int]",
give: &testResourceInputs{
PuxIntMap: pulumix.Cast[pulumix.MapOutput[int], map[string]int](
pulumix.Val(map[string]int{"g": 7, "h": 8}),
),
},
want: resource.PropertyMap{
"puxIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"g": resource.NewNumberProperty(7),
"h": resource.NewNumberProperty(8),
},
),
},
},
{
desc: "pux.IntMap/pux.GMapOutput",
give: &testResourceInputs{
PuxIntMap: pulumix.Cast[pulumix.GMapOutput[int, pulumi.IntOutput], map[string]int](
pulumix.Val(map[string]int{"i": 9, "j": 10}),
),
},
want: resource.PropertyMap{
"puxIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"i": resource.NewNumberProperty(9),
"j": resource.NewNumberProperty(10),
},
),
},
},
// --- pulumi.IntMapInput ---
{
desc: "pu.IntMap/pu.IntMap",
give: &testResourceInputs{
PuIntMap: pulumi.IntMap{"a": pulumi.Int(1), "b": pulumi.Int(2)},
},
want: resource.PropertyMap{
"puIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"a": resource.NewNumberProperty(1),
"b": resource.NewNumberProperty(2),
},
),
},
},
{
desc: "pu.IntMap/pux.Output[map[string]int] untyped",
give: &testResourceInputs{
PuIntMap: pulumix.Val(map[string]int{"c": 3, "d": 4}).Untyped().(pulumi.IntMapOutput),
},
want: resource.PropertyMap{
"puIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"c": resource.NewNumberProperty(3),
"d": resource.NewNumberProperty(4),
},
),
},
},
{
desc: "pu.IntMap/pux.MapOutput[int] untyped",
give: &testResourceInputs{
PuIntMap: pulumix.Cast[pulumix.MapOutput[int], map[string]int](
pulumix.Val(map[string]int{"e": 5, "f": 6}),
).Untyped().(pulumi.IntMapOutput),
},
want: resource.PropertyMap{
"puIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"e": resource.NewNumberProperty(5),
"f": resource.NewNumberProperty(6),
},
),
},
},
{
desc: "pu.IntMap/pux.GMapOutput untyped",
give: &testResourceInputs{
PuIntMap: pulumix.Cast[pulumix.GMapOutput[int, pulumi.IntOutput], map[string]int](
pulumix.Val(map[string]int{"g": 7, "h": 8}),
).Untyped().(pulumi.IntMapOutput),
},
want: resource.PropertyMap{
"puIntMap": resource.NewObjectProperty(
resource.PropertyMap{
"g": resource.NewNumberProperty(7),
"h": resource.NewNumberProperty(8),
},
),
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
var (
got resource.PropertyMap
ok bool
)
err := pulumi.RunErr(func(ctx *pulumi.Context) error {
var res pulumi.CustomResourceState
require.NoError(t,
ctx.RegisterResource("test:index:MyResource", "testResource", tt.give, &res))
return nil
}, pulumi.WithMocks("project", "stack", &mockResourceMonitor{
CallF: func(args pulumi.MockCallArgs) (resource.PropertyMap, error) {
t.Fatalf("unexpected Call(%#v)", args)
return nil, nil
},
NewResourceF: func(args pulumi.MockResourceArgs) (string, resource.PropertyMap, error) {
if args.TypeToken == "test:index:MyResource" {
got = args.Inputs
ok = true
} else {
t.Fatalf("unexpected NewResource(%#v)", args)
}
return args.Name + "_id", nil, nil
},
}))
require.NoError(t, err)
require.True(t, ok)
require.Equal(t, tt.want, got)
})
}
}
func TestRegisterResourceOutputs(t *testing.T) {
t.Parallel()
tests := []struct {
desc string
give pulumi.Input
// TODO: find a way to intercept RegisterResourceOutput calls.
}{
{"pu.String", pulumi.String("a")},
{"pu.StringOutput", pulumi.String("b").ToStringOutput()},
{"pux.Output[string]", pulumix.Val("c")},
{"pux.Output[string]/untyped", pulumix.Val("c").Untyped()},
{"pux.PtrOf", pulumix.PtrOf[string](pulumi.String("d"))},
{"pu.StringPtr", pulumi.StringPtr("e")},
{"pu.StringPtrOutput", pulumi.String("f").ToStringPtrOutput()},
{"pux.Output[*string]", pulumix.Ptr("g")},
{"pux.Output[*string]/untyped", pulumix.Ptr("h").Untyped()},
{"pux.Output[[]int]", pulumix.Val([]int{1, 2, 3})},
{
"pux.ArrayOutput[int]",
pulumix.Cast[pulumix.ArrayOutput[int], []int](
pulumix.Val([]int{4, 5, 6}),
),
},
{
"pux.GArrayOutput",
pulumix.Cast[pulumix.GArrayOutput[int, pulumi.IntOutput], []int](
pulumix.Val([]int{7, 8, 9}),
),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
err := pulumi.RunErr(func(ctx *pulumi.Context) error {
ctx.Export("x", tt.give)
return nil
}, pulumi.WithMocks("project", "stack", &mockResourceMonitor{}))
require.NoError(t, err)
})
}
}
type mockResourceMonitor struct {
CallF func(pulumi.MockCallArgs) (resource.PropertyMap, error)
NewResourceF func(pulumi.MockResourceArgs) (string, resource.PropertyMap, error)
}
var _ pulumi.MockResourceMonitor = (*mockResourceMonitor)(nil)
func (m *mockResourceMonitor) Call(args pulumi.MockCallArgs) (resource.PropertyMap, error) {
return m.CallF(args)
}
func (m *mockResourceMonitor) NewResource(args pulumi.MockResourceArgs) (string, resource.PropertyMap, error) {
return m.NewResourceF(args)
}