Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(go): runtime type check type unions #3712

Merged
merged 23 commits into from
Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c65ad77
chore: simplify go tooling usage
RomainMuller Aug 12, 2022
f5cf060
feat(go): weave runtime null-checks for parameters
RomainMuller Aug 16, 2022
3097ccf
feat(go): runtime type-check unions
RomainMuller Aug 16, 2022
0348ccd
Merge remote-tracking branch 'origin/main' into rmuller/go-type-checking
RomainMuller Aug 18, 2022
7bd1f5e
Merge remote-tracking branch 'origin/main' into rmuller/go-type-checking
RomainMuller Aug 18, 2022
c0811d8
apply opt-out
RomainMuller Aug 18, 2022
24ccbe2
Merge branch 'main' into rmuller/go-type-checking
RomainMuller Aug 19, 2022
9a1b28b
linter fix
RomainMuller Aug 19, 2022
495a3d5
make go1.16-compatible
RomainMuller Aug 22, 2022
c8e7a7a
Merge remote-tracking branch 'origin/main' into rmuller/go-type-checking
RomainMuller Aug 22, 2022
441fe5b
Merge branch 'main' into rmuller/go-type-checking
RomainMuller Aug 22, 2022
4856f45
add missing +build comment
RomainMuller Aug 22, 2022
348f326
Merge branch 'main' into rmuller/go-type-checking
RomainMuller Aug 22, 2022
41f5a18
reverse type checking diff check
RomainMuller Aug 23, 2022
a744849
add nested union test
RomainMuller Aug 23, 2022
a675905
fix typo
RomainMuller Aug 23, 2022
f6351d9
fixup snapshot
RomainMuller Aug 23, 2022
1d57f2c
Fixup format of map access in error message
RomainMuller Aug 24, 2022
b791b0d
Standardize on using %v for fmt.Printf
RomainMuller Aug 24, 2022
c0473a5
Merge remote-tracking branch 'origin/main' into rmuller/go-type-checking
RomainMuller Aug 24, 2022
51af006
fix(.net): bad error message syntax in .NET
RomainMuller Aug 24, 2022
8b8d7cb
use no_runtime_type_checking tag
RomainMuller Aug 24, 2022
165170a
fix snapshots
RomainMuller Aug 24, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@ updates:
ignore:
- dependency-name: "setuptools"

- package-ecosystem: gomod
directory: '/packages/@jsii/go-runtime'
schedule:
interval: daily
labels:
- dependencies
- language/go

- package-ecosystem: gomod
directory: '/packages/@jsii/go-runtime/jsii-runtime-go'
schedule:
Expand Down
31 changes: 0 additions & 31 deletions packages/@jsii/go-runtime-test/build-tools/go-run.ts

This file was deleted.

7 changes: 3 additions & 4 deletions packages/@jsii/go-runtime-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
"description": "",
"scripts": {
"build": "tsc --build && yarn gen:calc",
"fmt": "yarn --silent go:run goimports -w .",
"lint": "cd project && go vet ./... && yarn --silent go:run golint ./...",
"fmt": "cd project && go run golang.org/x/tools/cmd/goimports -w .",
"lint": "cd project && go vet ./... && go run golang.org/x/lint/golint ./...",
"test": "cd project && go test ./...",
"lint:fix": "yarn lint && yarn fmt",
"gen:calc": "node build-tools/gen-calc.js",
"go:run": "cd project && go mod download && node ../build-tools/go-run.js"
"gen:calc": "node build-tools/gen-calc.js"
},
"keywords": [],
"author": "",
Expand Down
10 changes: 5 additions & 5 deletions packages/@jsii/go-runtime-test/project/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ require (
github.com/aws/jsii-runtime-go v0.0.0
github.com/aws/jsii/jsii-calc/go/jcb v0.0.0
github.com/aws/jsii/jsii-calc/go/jsiicalc/v3 v3.20.120
github.com/aws/jsii/jsii-calc/go/scopejsiicalclib v0.0.0
github.com/aws/jsii/jsii-calc/go/scopejsiicalclib v0.0.0-devpreview
github.com/stretchr/testify v1.8.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
golang.org/x/tools v0.1.12
)

replace (
github.com/aws/jsii-runtime-go => ../../go-runtime/jsii-runtime-go
github.com/aws/jsii/jsii-calc/go/jcb => ../jsii-calc/go/jcb
github.com/aws/jsii/jsii-calc/go/jsiicalc/v3 => ../jsii-calc/go/jsiicalc
github.com/aws/jsii-runtime-go v0.0.0 => ../../go-runtime/jsii-runtime-go
github.com/aws/jsii/jsii-calc/go/jcb v0.0.0 => ../jsii-calc/go/jcb
github.com/aws/jsii/jsii-calc/go/jsiicalc/v3 v3.20.120 => ../jsii-calc/go/jsiicalc
github.com/aws/jsii/jsii-calc/go/scopejsiicalcbaseofbase/v2 => ../jsii-calc/go/scopejsiicalcbaseofbase
github.com/aws/jsii/jsii-calc/go/scopejsiicalclib => ../jsii-calc/go/scopejsiicalclib
github.com/aws/jsii/jsii-calc/go/scopejsiicalclib v0.0.0-devpreview => ../jsii-calc/go/scopejsiicalclib
)
2 changes: 2 additions & 0 deletions packages/@jsii/go-runtime-test/project/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
Expand All @@ -24,6 +25,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package tests

import (
"fmt"
"testing"

"github.com/aws/jsii-runtime-go"
"github.com/aws/jsii/jsii-calc/go/jsiicalc/v3"
"github.com/aws/jsii/jsii-calc/go/jsiicalc/v3/anonymous"
)

func TestConstructor(t *testing.T) {
RomainMuller marked this conversation as resolved.
Show resolved Hide resolved
defer expectPanic(t, "parameter unionProperty[0][bad] must be one of the allowed types: *StructA, *StructB; received \"Not a StructA or StructB\" (a string)")
jsiicalc.NewClassWithCollectionOfUnions(&[]*map[string]interface{}{
{
"good": jsiicalc.StructA{
RequiredString: jsii.String("present"),
},
"bad": "Not a StructA or StructB",
},
})
}

func TestSetter(t *testing.T) {
subject := jsiicalc.NewClassWithCollectionOfUnions(&[]*map[string]interface{}{})

defer expectPanic(t, "parameter val[0][bad] must be one of the allowed types: *StructA, *StructB; received \"Not a StructA or StructB\" (a string)")
subject.SetUnionProperty(&[]*map[string]interface{}{
{
"good": jsiicalc.StructA{
RequiredString: jsii.String("present"),
},
"bad": "Not a StructA or StructB",
},
})
}

func TestStaticMethod(t *testing.T) {
defer expectPanic(t, "parameter struct_ must be one of the allowed types: *StructA, *StructB; received \"Not a StructA\" (a string)")
jsiicalc.StructUnionConsumer_IsStructA("Not a StructA")
}

func TestAnonymousObjectIsValid(t *testing.T) {
strct := jsiicalc.StructUnionConsumer_ProvideStruct(jsii.String("A"))
if !*jsiicalc.StructUnionConsumer_IsStructA(strct) {
t.Error("Expected strct to be a StructA")
}

iface := anonymous.UseOptions_Provide(jsii.String("A"))
if *anonymous.UseOptions_Consume(iface) != "A" {
t.Error("Expected iface to produce A")
}
}

func TestNestedUnion(t *testing.T) {
func() {
defer expectPanic(t, "parameter unionProperty[0] must be one of the allowed types: *map[string]interface{}, *[]interface{}; received 1337.42 (a float64)")
jsiicalc.NewClassWithNestedUnion(&[]interface{}{1337.42})
}()

func() {
defer expectPanic(t, "parameter unionProperty[0][1] must be one of the allowed types: *StructA, *StructB; received 1337.42 (a float64)")
jsiicalc.NewClassWithNestedUnion(&[]interface{}{
[]interface{}{
jsiicalc.StructA{RequiredString: jsii.String("present")},
1337.42,
},
})
}()

func() {
defer expectPanic(t, "parameter unionProperty[0][bad] must be one of the allowed types: *StructA, *StructB; received \"Not a StructA or StructB\" (a string)")
RomainMuller marked this conversation as resolved.
Show resolved Hide resolved
jsiicalc.NewClassWithNestedUnion(&[]interface{}{
map[string]interface{}{
"good": jsiicalc.StructA{RequiredString: jsii.String("present")},
"bad": "Not a StructA or StructB",
},
})
}()
}

func expectPanic(t *testing.T, expected string) {
if err := recover(); err != nil {
actual := fmt.Sprintf("%v", err)
if actual != expected {
t.Errorf("Failed with error:\n%#v\nexpected to receive:\n%#v", actual, expected)
}
} else {
t.Errorf("Expected test to fail with error:\n%#v", expected)
}
}
32 changes: 0 additions & 32 deletions packages/@jsii/go-runtime/build-tools/go-run.ts

This file was deleted.

8 changes: 0 additions & 8 deletions packages/@jsii/go-runtime/go.mod

This file was deleted.

36 changes: 0 additions & 36 deletions packages/@jsii/go-runtime/go.sum

This file was deleted.

3 changes: 2 additions & 1 deletion packages/@jsii/go-runtime/jsii-runtime-go/deprecated.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package jsii

import (
"reflect"

"github.com/aws/jsii-runtime-go/internal/api"
"github.com/aws/jsii-runtime-go/runtime"
"reflect"
)

// Deprecated: FQN represents a fully-qualified type name in the jsii type system.
Expand Down
2 changes: 2 additions & 0 deletions packages/@jsii/go-runtime/jsii-runtime-go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/mattn/go-isatty v0.0.16
github.com/stretchr/testify v1.8.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
golang.org/x/tools v0.1.12
)

retract v1.27.0
35 changes: 35 additions & 0 deletions packages/@jsii/go-runtime/jsii-runtime-go/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,43 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ type registeredType struct {
}

type registeredStruct struct {
FQN api.FQN
Fields []reflect.StructField
FQN api.FQN
Fields []reflect.StructField
Validator func(interface{}, string) error
}

// RegisterClass maps the given FQN to the provided class interface, list of
Expand Down Expand Up @@ -150,3 +151,20 @@ func (t *TypeRegistry) RegisterStruct(fqn api.FQN, strct reflect.Type) error {

return nil
}

// RegisterStructValidator adds a validator function to an already registered struct type. This is separate call largely
// to maintain backwards compatibility with existing code.
comcalvi marked this conversation as resolved.
Show resolved Hide resolved
func (t *TypeRegistry) RegisterStructValidator(strct reflect.Type, validator func(interface{}, string) error) error {
if strct.Kind() != reflect.Struct {
return fmt.Errorf("the provided struct is not a struct: %v", strct)
}

info, ok := t.structInfo[strct]
if !ok {
return fmt.Errorf("the provided struct %s is not registered (call RegisterStruct first)", strct)
}
info.Validator = validator
t.structInfo[strct] = info

return nil
}
Loading