mirror of https://github.com/pulumi/pulumi.git
629 lines
17 KiB
Go
629 lines
17 KiB
Go
// Copyright 2020-2024, 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 gen
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/testing/test"
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/testing/utils"
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/slice"
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/executable"
|
|
)
|
|
|
|
func TestInputUsage(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pkg := &pkgContext{}
|
|
arrayUsage := pkg.getInputUsage("FooArray")
|
|
assert.Equal(
|
|
t,
|
|
"FooArrayInput is an input type that accepts FooArray and FooArrayOutput values.\nYou can construct a "+
|
|
"concrete instance of `FooArrayInput` via:\n\n\t\t FooArray{ FooArgs{...} }\n ",
|
|
arrayUsage)
|
|
|
|
mapUsage := pkg.getInputUsage("FooMap")
|
|
assert.Equal(
|
|
t,
|
|
"FooMapInput is an input type that accepts FooMap and FooMapOutput values.\nYou can construct a concrete"+
|
|
" instance of `FooMapInput` via:\n\n\t\t FooMap{ \"key\": FooArgs{...} }\n ",
|
|
mapUsage)
|
|
|
|
ptrUsage := pkg.getInputUsage("FooPtr")
|
|
assert.Equal(
|
|
t,
|
|
"FooPtrInput is an input type that accepts FooArgs, FooPtr and FooPtrOutput values.\nYou can construct a "+
|
|
"concrete instance of `FooPtrInput` via:\n\n\t\t FooArgs{...}\n\n or:\n\n\t\t nil\n ",
|
|
ptrUsage)
|
|
|
|
usage := pkg.getInputUsage("Foo")
|
|
assert.Equal(
|
|
t,
|
|
"FooInput is an input type that accepts FooArgs and FooOutput values.\nYou can construct a concrete instance"+
|
|
" of `FooInput` via:\n\n\t\t FooArgs{...}\n ",
|
|
usage)
|
|
}
|
|
|
|
func TestGoPackageName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
assert.Equal(t, "aws", goPackage("aws"))
|
|
assert.Equal(t, "azurenextgen", goPackage("azure-nextgen"))
|
|
assert.Equal(t, "plantprovider", goPackage("plant-provider"))
|
|
assert.Equal(t, "", goPackage(""))
|
|
}
|
|
|
|
func TestGeneratePackage(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
generatePackage := func(tool string, pkg *schema.Package, files map[string][]byte) (map[string][]byte, error) {
|
|
for f := range files {
|
|
t.Logf("Ignoring extraFile %s", f)
|
|
}
|
|
|
|
return GeneratePackage(tool, pkg, nil)
|
|
}
|
|
|
|
test.TestSDKCodegen(t, &test.SDKCodegenOptions{
|
|
Language: "go",
|
|
GenPackage: generatePackage,
|
|
Checks: map[string]test.CodegenCheck{
|
|
"go/compile": typeCheckGeneratedPackage,
|
|
"go/test": testGeneratedPackage,
|
|
},
|
|
TestCases: test.PulumiPulumiSDKTests,
|
|
})
|
|
}
|
|
|
|
func readGoPackageInfo(schemaPath string) (*GoPackageInfo, error) {
|
|
f, err := os.Open(schemaPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
type language struct {
|
|
Go GoPackageInfo `json:"go"`
|
|
}
|
|
type model struct {
|
|
Language language `json:"language"`
|
|
}
|
|
var m model
|
|
if err := json.NewDecoder(f).Decode(&m); err != nil {
|
|
return nil, err
|
|
}
|
|
return &m.Language.Go, nil
|
|
}
|
|
|
|
// Decide the name of the Go module for a generated test.
|
|
//
|
|
// For example for this path:
|
|
//
|
|
// codeDir = "../testing/test/testdata/external-resource-schema/go/"
|
|
//
|
|
// We will generate "$codeDir/go.mod" using `external-resource-schema` as the module name so that it can compile
|
|
// independently.
|
|
//
|
|
// This can be overwritten by setting ModulePath in GoPackageInfo in
|
|
//
|
|
// jq .language.go.modulePath ${codeDir}../schema.json
|
|
func inferModuleName(codeDir string) string {
|
|
schemaPath := filepath.Join(filepath.Dir(codeDir), "schema.json")
|
|
if gotSchema, err := test.PathExists(schemaPath); err == nil && gotSchema {
|
|
if info, err := readGoPackageInfo(schemaPath); err == nil {
|
|
if info.ModulePath != "" {
|
|
return info.ModulePath
|
|
}
|
|
}
|
|
}
|
|
|
|
return filepath.Base(filepath.Dir(codeDir))
|
|
}
|
|
|
|
func typeCheckGeneratedPackage(t *testing.T, codeDir string) {
|
|
sdk, err := filepath.Abs(filepath.Join("..", "..", "..", "sdk"))
|
|
require.NoError(t, err)
|
|
|
|
goExe, err := executable.FindExecutable("go")
|
|
require.NoError(t, err)
|
|
|
|
goMod := filepath.Join(codeDir, "go.mod")
|
|
alreadyHaveGoMod, err := test.PathExists(goMod)
|
|
require.NoError(t, err)
|
|
|
|
if alreadyHaveGoMod {
|
|
t.Logf("Found an existing go.mod, leaving as is")
|
|
} else {
|
|
test.RunCommand(t, "go_mod_init", codeDir, goExe, "mod", "init", inferModuleName(codeDir))
|
|
replacement := "github.com/pulumi/pulumi/sdk/v3=" + sdk
|
|
test.RunCommand(t, "go_mod_edit", codeDir, goExe, "mod", "edit", "-replace", replacement)
|
|
}
|
|
|
|
test.RunCommand(t, "go_mod_tidy", codeDir, goExe, "mod", "tidy")
|
|
test.RunCommand(t, "go_build", codeDir, goExe, "build", "-v", "all")
|
|
}
|
|
|
|
func testGeneratedPackage(t *testing.T, codeDir string) {
|
|
goExe, err := executable.FindExecutable("go")
|
|
require.NoError(t, err)
|
|
|
|
test.RunCommand(t, "go-test", codeDir, goExe, "test", inferModuleName(codeDir)+"/...")
|
|
}
|
|
|
|
func TestGenerateTypeNames(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
test.TestTypeNameCodegen(t, "go", func(pkg *schema.Package) test.TypeNameGeneratorFunc {
|
|
err := pkg.ImportLanguages(map[string]schema.Language{"go": Importer})
|
|
require.NoError(t, err)
|
|
|
|
var goPkgInfo GoPackageInfo
|
|
if goInfo, ok := pkg.Language["go"].(GoPackageInfo); ok {
|
|
goPkgInfo = goInfo
|
|
}
|
|
packages, err := generatePackageContextMap("test", pkg.Reference(), goPkgInfo, nil)
|
|
require.NoError(t, err)
|
|
|
|
root, ok := packages[""]
|
|
require.True(t, ok)
|
|
|
|
return func(t schema.Type) string {
|
|
return root.typeString(t)
|
|
}
|
|
})
|
|
}
|
|
|
|
func readSchemaFile(file string) *schema.Package {
|
|
// Read in, decode, and import the schema.
|
|
schemaBytes, err := os.ReadFile(filepath.Join("..", "testing", "test", "testdata", file))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
var pkgSpec schema.PackageSpec
|
|
if err = json.Unmarshal(schemaBytes, &pkgSpec); err != nil {
|
|
panic(err)
|
|
}
|
|
loader := schema.NewPluginLoader(utils.NewHost(testdataPath))
|
|
pkg, diags, err := schema.BindSpec(pkgSpec, loader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if diags.HasErrors() {
|
|
panic(diags.Error())
|
|
}
|
|
|
|
return pkg
|
|
}
|
|
|
|
func readYamlSchemaFile(file string) *schema.Package {
|
|
// Read in, decode, and import the schema.
|
|
schemaBytes, err := os.ReadFile(filepath.Join("..", "testing", "test", "testdata", file))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
var pkgSpec schema.PackageSpec
|
|
if err = yaml.Unmarshal(schemaBytes, &pkgSpec); err != nil {
|
|
panic(err)
|
|
}
|
|
loader := schema.NewPluginLoader(utils.NewHost(testdataPath))
|
|
pkg, diags, err := schema.BindSpec(pkgSpec, loader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if diags.HasErrors() {
|
|
panic(diags.Error())
|
|
}
|
|
|
|
return pkg
|
|
}
|
|
|
|
func TestLanguageResources(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, test := range test.PulumiPulumiSDKTests {
|
|
test := test
|
|
t.Run(test.Directory, func(t *testing.T) {
|
|
t.Parallel()
|
|
var pkg *schema.Package
|
|
if test.Directory == "simple-yaml-schema" || test.Directory == "cyclic-types" {
|
|
pkg = readYamlSchemaFile(filepath.Join(test.Directory, "schema.yaml"))
|
|
} else {
|
|
pkg = readSchemaFile(filepath.Join(test.Directory, "schema.json"))
|
|
}
|
|
|
|
resources, err := LanguageResources("test", pkg)
|
|
for token, resource := range resources {
|
|
assert.Equal(t, tokenToName(token), resource.Name)
|
|
}
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
// We test the naming/module structure of generated packages.
|
|
func TestPackageNaming(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := []struct {
|
|
importBasePath string
|
|
rootPackageName string
|
|
name string
|
|
expectedRoot string
|
|
}{
|
|
{
|
|
importBasePath: "github.com/pulumi/pulumi-azure-quickstart-acr-geo-replication/sdk/go/acr",
|
|
expectedRoot: "acr",
|
|
},
|
|
{
|
|
importBasePath: "github.com/ihave/animport",
|
|
rootPackageName: "root",
|
|
expectedRoot: "",
|
|
},
|
|
{
|
|
name: "named-package",
|
|
expectedRoot: "namedpackage",
|
|
},
|
|
}
|
|
for _, tt := range testCases {
|
|
tt := tt
|
|
t.Run(tt.expectedRoot, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// This schema is arbitrary. We just needed a filled out schema. All
|
|
// path decisions should be made based off of the Name and
|
|
// Language[go] fields (which we set after import).
|
|
schema := readSchemaFile(filepath.Join("schema", "good-enum-1.json"))
|
|
if tt.name != "" {
|
|
// We want there to be a name, so if one isn't provided we
|
|
// default to the schema.
|
|
schema.Name = tt.name
|
|
}
|
|
schema.Language = map[string]interface{}{
|
|
"go": GoPackageInfo{
|
|
ImportBasePath: tt.importBasePath,
|
|
RootPackageName: tt.rootPackageName,
|
|
},
|
|
}
|
|
files, err := GeneratePackage("test", schema, nil)
|
|
require.NoError(t, err)
|
|
ordering := slice.Prealloc[string](len(files))
|
|
for k := range files {
|
|
ordering = append(ordering, k)
|
|
}
|
|
sort.Strings(ordering)
|
|
require.NotEmpty(t, files, "This test only works when files are generated")
|
|
for _, k := range ordering {
|
|
root := strings.Split(k, "/")[0]
|
|
if tt.expectedRoot != "" {
|
|
require.Equal(t, tt.expectedRoot, root, "Root should precede all cases. Got file %s", k)
|
|
}
|
|
// We should work on a way to assert this is one level higher then it otherwise would be.
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTokenToType(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const awsImportBasePath = "github.com/pulumi/pulumi-aws/sdk/v4/go/aws"
|
|
awsSpec := schema.PackageSpec{
|
|
Name: "aws",
|
|
Meta: &schema.MetadataSpec{
|
|
ModuleFormat: "(.*)(?:/[^/]*)",
|
|
},
|
|
}
|
|
|
|
const googleNativeImportBasePath = "github.com/pulumi/pulumi-google-native/sdk/go/google"
|
|
googleNativeSpec := schema.PackageSpec{
|
|
Name: "google-native",
|
|
}
|
|
|
|
tests := []struct {
|
|
pkg *pkgContext
|
|
token string
|
|
expected string
|
|
}{
|
|
{
|
|
pkg: &pkgContext{
|
|
pkg: importSpec(t, awsSpec).Reference(),
|
|
importBasePath: awsImportBasePath,
|
|
},
|
|
token: "aws:s3/BucketWebsite:BucketWebsite",
|
|
expected: "s3.BucketWebsite",
|
|
},
|
|
{
|
|
pkg: &pkgContext{
|
|
pkg: importSpec(t, awsSpec).Reference(),
|
|
importBasePath: awsImportBasePath,
|
|
pkgImportAliases: map[string]string{
|
|
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/s3": "awss3",
|
|
},
|
|
},
|
|
token: "aws:s3/BucketWebsite:BucketWebsite",
|
|
expected: "awss3.BucketWebsite",
|
|
},
|
|
{
|
|
pkg: &pkgContext{
|
|
pkg: importSpec(t, googleNativeSpec).Reference(),
|
|
importBasePath: googleNativeImportBasePath,
|
|
pkgImportAliases: map[string]string{
|
|
"github.com/pulumi/pulumi-google-native/sdk/go/google/dns/v1": "dns",
|
|
},
|
|
},
|
|
token: "google-native:dns/v1:DnsKeySpec",
|
|
expected: "dns.DnsKeySpec",
|
|
},
|
|
}
|
|
//nolint:paralleltest // false positive because range var isn't used directly in t.Run(name) arg
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.token+"=>"+tt.expected, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
actual := tt.pkg.tokenToType(tt.token)
|
|
assert.Equal(t, tt.expected, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTokenToResource(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const awsImportBasePath = "github.com/pulumi/pulumi-aws/sdk/v4/go/aws"
|
|
awsSpec := schema.PackageSpec{
|
|
Name: "aws",
|
|
Meta: &schema.MetadataSpec{
|
|
ModuleFormat: "(.*)(?:/[^/]*)",
|
|
},
|
|
}
|
|
|
|
const googleNativeImportBasePath = "github.com/pulumi/pulumi-google-native/sdk/go/google"
|
|
googleNativeSpec := schema.PackageSpec{
|
|
Name: "google-native",
|
|
}
|
|
|
|
tests := []struct {
|
|
pkg *pkgContext
|
|
token string
|
|
expected string
|
|
}{
|
|
{
|
|
pkg: &pkgContext{
|
|
pkg: importSpec(t, awsSpec).Reference(),
|
|
importBasePath: awsImportBasePath,
|
|
},
|
|
token: "aws:s3/Bucket:Bucket",
|
|
expected: "s3.Bucket",
|
|
},
|
|
{
|
|
pkg: &pkgContext{
|
|
pkg: importSpec(t, awsSpec).Reference(),
|
|
importBasePath: awsImportBasePath,
|
|
pkgImportAliases: map[string]string{
|
|
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/s3": "awss3",
|
|
},
|
|
},
|
|
token: "aws:s3/Bucket:Bucket",
|
|
expected: "awss3.Bucket",
|
|
},
|
|
{
|
|
pkg: &pkgContext{
|
|
pkg: importSpec(t, googleNativeSpec).Reference(),
|
|
importBasePath: googleNativeImportBasePath,
|
|
pkgImportAliases: map[string]string{
|
|
"github.com/pulumi/pulumi-google-native/sdk/go/google/dns/v1": "dns",
|
|
},
|
|
},
|
|
token: "google-native:dns/v1:Policy",
|
|
expected: "dns.Policy",
|
|
},
|
|
}
|
|
//nolint:paralleltest // false positive because range var isn't used directly in t.Run(name) arg
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.token+"=>"+tt.expected, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
actual := tt.pkg.tokenToResource(tt.token)
|
|
assert.Equal(t, tt.expected, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
func importSpec(t *testing.T, spec schema.PackageSpec) *schema.Package {
|
|
importedPkg, err := schema.ImportSpec(spec, map[string]schema.Language{})
|
|
assert.NoError(t, err)
|
|
return importedPkg
|
|
}
|
|
|
|
func TestGenHeader(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pkg := &pkgContext{
|
|
tool: "a tool",
|
|
pkg: (&schema.Package{Name: "test-pkg"}).Reference(),
|
|
}
|
|
|
|
s := func() string {
|
|
b := &bytes.Buffer{}
|
|
pkg.genHeader(b, []string{"pkg1", "example.com/foo/123-foo"}, nil, false /* isUtil */)
|
|
return b.String()
|
|
}()
|
|
assert.Equal(t, `// Code generated by a tool DO NOT EDIT.
|
|
// *** WARNING: Do not edit by hand unless you're certain you know what you are doing! ***
|
|
|
|
package testpkg
|
|
|
|
import (
|
|
"pkg1"
|
|
"example.com/foo/123-foo"
|
|
)
|
|
|
|
`, s)
|
|
|
|
// Compliance is defined by https://pkg.go.dev/cmd/go#hdr-Generate_Go_files_by_processing_source
|
|
autogenerated := regexp.MustCompile(`^// Code generated .* DO NOT EDIT\.$`)
|
|
found := false
|
|
loop:
|
|
for _, l := range strings.Split(s, "\n") {
|
|
switch {
|
|
case autogenerated.Match([]byte(l)):
|
|
found = true
|
|
break loop
|
|
case l == "" || strings.HasPrefix(l, "//"):
|
|
default:
|
|
break loop
|
|
}
|
|
}
|
|
assert.Truef(t, found, `Didn't find a line that complies with "%v"`, autogenerated)
|
|
}
|
|
|
|
func TestTitle(t *testing.T) {
|
|
t.Parallel()
|
|
assert := assert.New(t)
|
|
|
|
assert.Equal("", Title(""))
|
|
assert.Equal("Plugh", Title("plugh"))
|
|
assert.Equal("WaldoThudFred", Title("WaldoThudFred"))
|
|
assert.Equal("WaldoThudFred", Title("waldoThudFred"))
|
|
assert.Equal("WaldoThudFred", Title("waldo-Thud-Fred"))
|
|
assert.Equal("WaldoThudFred", Title("waldo-ThudFred"))
|
|
assert.Equal("WaldoThud_Fred", Title("waldo-Thud_Fred"))
|
|
assert.Equal("WaldoThud_Fred", Title("waldo-thud_Fred"))
|
|
assert.Equal("WaldoThud_Fred", Title("$waldo-thud_Fred"))
|
|
}
|
|
|
|
func TestRegressTypeDuplicatesInChunking(t *testing.T) {
|
|
t.Parallel()
|
|
pkgSpec := schema.PackageSpec{
|
|
Name: "test",
|
|
Version: "0.0.1",
|
|
Resources: make(map[string]schema.ResourceSpec),
|
|
Types: map[string]schema.ComplexTypeSpec{
|
|
"test:index:PolicyStatusAutogenRules": {
|
|
ObjectTypeSpec: schema.ObjectTypeSpec{
|
|
Type: "object",
|
|
Properties: map[string]schema.PropertySpec{
|
|
"imageExtractors": {
|
|
TypeSpec: schema.TypeSpec{
|
|
Type: "object",
|
|
AdditionalProperties: &schema.TypeSpec{
|
|
Type: "array",
|
|
Items: &schema.TypeSpec{
|
|
Type: "object",
|
|
Ref: "#/types/test:index:Im",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"test:index:Im": {
|
|
ObjectTypeSpec: schema.ObjectTypeSpec{
|
|
Type: "object",
|
|
Properties: map[string]schema.PropertySpec{
|
|
"name": {TypeSpec: schema.TypeSpec{Type: "string"}},
|
|
"path": {TypeSpec: schema.TypeSpec{Type: "string"}},
|
|
},
|
|
Required: []string{"path"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
// Need to ref PolicyStatusAutogenRules in input position to trigger the code path.
|
|
pkgSpec.Resources["test:index:Res"] = schema.ResourceSpec{
|
|
InputProperties: map[string]schema.PropertySpec{
|
|
"a": {
|
|
TypeSpec: schema.TypeSpec{
|
|
Ref: "#/types/test:index:PolicyStatusAutogenRules",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
// Need to have N>500 but N<1000 to obtain 2 chunks.
|
|
for i := 0; i < 750; i++ {
|
|
ttok := fmt.Sprintf("test:index:Typ%d", i)
|
|
pkgSpec.Types[ttok] = schema.ComplexTypeSpec{
|
|
ObjectTypeSpec: schema.ObjectTypeSpec{
|
|
Type: "object",
|
|
Required: []string{"x"},
|
|
Properties: map[string]schema.PropertySpec{
|
|
"x": {TypeSpec: schema.TypeSpec{Type: "string"}},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
loader := schema.NewPluginLoader(utils.NewHost(testdataPath))
|
|
pkg, diags, err := schema.BindSpec(pkgSpec, loader)
|
|
require.NoError(t, err)
|
|
t.Logf("%v", diags)
|
|
require.False(t, diags.HasErrors())
|
|
|
|
fs, err := GeneratePackage("tests", pkg, nil)
|
|
require.NoError(t, err)
|
|
|
|
for f := range fs {
|
|
t.Logf("Generated %v", f)
|
|
}
|
|
|
|
// Expect to see two chunked files (chunking at n=500).
|
|
assert.Contains(t, fs, "test/pulumiTypes.go")
|
|
assert.Contains(t, fs, "test/pulumiTypes1.go")
|
|
assert.NotContains(t, fs, "test/pulumiTypes2.go")
|
|
|
|
// The types defined in the chunks should be mutually exclusive.
|
|
typedefs := func(s string) []string {
|
|
var types []string
|
|
for _, line := range strings.Split(s, "\n") {
|
|
line = strings.TrimSpace(line)
|
|
if strings.HasPrefix(line, "type") {
|
|
types = append(types, line)
|
|
}
|
|
}
|
|
sort.Strings(types)
|
|
return types
|
|
}
|
|
|
|
typedefs1 := typedefs(string(fs["test/pulumiTypes.go"]))
|
|
typedefs2 := typedefs(string(fs["test/pulumiTypes1.go"]))
|
|
|
|
for _, typ := range typedefs1 {
|
|
assert.NotContains(t, typedefs2, typ)
|
|
}
|
|
|
|
for _, typ := range typedefs2 {
|
|
assert.NotContains(t, typedefs1, typ)
|
|
}
|
|
}
|