pulumi/cmd/pulumi-test-language/testing.go

255 lines
6.4 KiB
Go
Raw Permalink Normal View History

Add matrix testing (#13705) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Adds the first pass of matrix testing. Matrix testing allows us to define tests once in pulumi/pulumi via PCL and then run those tests against each language plugin to verify code generation and runtime correctness. Rather than packing matrix tests and all the associated data and machinery into the CLI itself we define a new Go package at cmd/pulumi-test-lanaguage. This depends on pkg and runs the deployment engine in a unique way for matrix tests but it is running the proper deployment engine with a proper backend (always filestate, using $TEMP). Currently only NodeJS is hooked up to run these tests, and all the code for that currently lives in sdk/nodejs/cmd/pulumi-language-nodejs/language_test.go. I expect we'll move that helper code to sdk/go/common and use it in each language plugin to run the tests in the same way. This first pass includes 3 simple tests: * l1-empty that runs an empty PCL file and checks just a stack is created * l1-output-bool that runs a PCL program that returns two stack outputs of `true` and `false * l2-resource-simple that runs a PCL program creating a simple resource with a single bool property These tests are themselves tested with a mock language runtime. This verifies the behavior of the matrix test framework for both correct and incorrect language hosts (that is some the mock language runtimes purposefully cause errors or compute the wrong result). There are a number of things missing from from the core framework still, but I feel don't block getting this first pass merged and starting to be used. 1. The tests can not currently run in parallel. That is calling RunLanguageTest in parallel will break things. This is due to two separate problems. Firstly is that the SDK snapshot's are not safe to write in parallel (when PULUMI_ACCEPT is true), this should be fairly easy to fix by doing a write to dst-{random} and them atomic move to dst. Secondly is that the deployment engine itself has mutable global state, short term we should probably just lock around that part RunLanguageTest, long term it would be good to clean that up. 2. We need a way to verify "preview" behavior, I think this is probably just a variation of the tests that would call `stack.Preview` and not pass a snapshot to `assert`. 3. stdout, stderr and log messages are returned in bulk at the end of the test. Plus there are a couple of calls to the language runtime that don't correctly thread stdout/stderr to use and so default to the process `os.Stdout/Stderr`. stdout/stderr streaming shows up in a load of other places as well so I'm thinking of a clean way to handle all of them together. Log message streaming we can probably do by just turning RunLanguageTest to a streaming grpc call. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Abhinav Gupta <abhinav@pulumi.com>
2023-09-13 15:17:46 +00:00
// 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 main
import (
"fmt"
"path/filepath"
"runtime"
"runtime/debug"
"sync"
mapset "github.com/deckarep/golang-set/v2"
"github.com/pulumi/pulumi/pkg/v3/display"
Add matrix testing (#13705) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Adds the first pass of matrix testing. Matrix testing allows us to define tests once in pulumi/pulumi via PCL and then run those tests against each language plugin to verify code generation and runtime correctness. Rather than packing matrix tests and all the associated data and machinery into the CLI itself we define a new Go package at cmd/pulumi-test-lanaguage. This depends on pkg and runs the deployment engine in a unique way for matrix tests but it is running the proper deployment engine with a proper backend (always filestate, using $TEMP). Currently only NodeJS is hooked up to run these tests, and all the code for that currently lives in sdk/nodejs/cmd/pulumi-language-nodejs/language_test.go. I expect we'll move that helper code to sdk/go/common and use it in each language plugin to run the tests in the same way. This first pass includes 3 simple tests: * l1-empty that runs an empty PCL file and checks just a stack is created * l1-output-bool that runs a PCL program that returns two stack outputs of `true` and `false * l2-resource-simple that runs a PCL program creating a simple resource with a single bool property These tests are themselves tested with a mock language runtime. This verifies the behavior of the matrix test framework for both correct and incorrect language hosts (that is some the mock language runtimes purposefully cause errors or compute the wrong result). There are a number of things missing from from the core framework still, but I feel don't block getting this first pass merged and starting to be used. 1. The tests can not currently run in parallel. That is calling RunLanguageTest in parallel will break things. This is due to two separate problems. Firstly is that the SDK snapshot's are not safe to write in parallel (when PULUMI_ACCEPT is true), this should be fairly easy to fix by doing a write to dst-{random} and them atomic move to dst. Secondly is that the deployment engine itself has mutable global state, short term we should probably just lock around that part RunLanguageTest, long term it would be good to clean that up. 2. We need a way to verify "preview" behavior, I think this is probably just a variation of the tests that would call `stack.Preview` and not pass a snapshot to `assert`. 3. stdout, stderr and log messages are returned in bulk at the end of the test. Plus there are a couple of calls to the language runtime that don't correctly thread stdout/stderr to use and so default to the process `os.Stdout/Stderr`. stdout/stderr streaming shows up in a load of other places as well so I'm thinking of a clean way to handle all of them together. Log message streaming we can probably do by just turning RunLanguageTest to a streaming grpc call. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Abhinav Gupta <abhinav@pulumi.com>
2023-09-13 15:17:46 +00:00
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/result"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// L holds the state for the current language test.
//
// It provides an interface similar to testing.T,
// allowing its use with testing libraries like Testify.
type L struct {
mu sync.RWMutex // guards the fields below
// Whether this test has already failed.
failed bool
// Messages logged to l.Errorf or l.Logf.
logs []string
// Functions marked helpers with L.Helper().
// These names are from the runtime.Frame.Function field.
// They're fully qualified with package names.
helpers mapset.Set[string]
Add matrix testing (#13705) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Adds the first pass of matrix testing. Matrix testing allows us to define tests once in pulumi/pulumi via PCL and then run those tests against each language plugin to verify code generation and runtime correctness. Rather than packing matrix tests and all the associated data and machinery into the CLI itself we define a new Go package at cmd/pulumi-test-lanaguage. This depends on pkg and runs the deployment engine in a unique way for matrix tests but it is running the proper deployment engine with a proper backend (always filestate, using $TEMP). Currently only NodeJS is hooked up to run these tests, and all the code for that currently lives in sdk/nodejs/cmd/pulumi-language-nodejs/language_test.go. I expect we'll move that helper code to sdk/go/common and use it in each language plugin to run the tests in the same way. This first pass includes 3 simple tests: * l1-empty that runs an empty PCL file and checks just a stack is created * l1-output-bool that runs a PCL program that returns two stack outputs of `true` and `false * l2-resource-simple that runs a PCL program creating a simple resource with a single bool property These tests are themselves tested with a mock language runtime. This verifies the behavior of the matrix test framework for both correct and incorrect language hosts (that is some the mock language runtimes purposefully cause errors or compute the wrong result). There are a number of things missing from from the core framework still, but I feel don't block getting this first pass merged and starting to be used. 1. The tests can not currently run in parallel. That is calling RunLanguageTest in parallel will break things. This is due to two separate problems. Firstly is that the SDK snapshot's are not safe to write in parallel (when PULUMI_ACCEPT is true), this should be fairly easy to fix by doing a write to dst-{random} and them atomic move to dst. Secondly is that the deployment engine itself has mutable global state, short term we should probably just lock around that part RunLanguageTest, long term it would be good to clean that up. 2. We need a way to verify "preview" behavior, I think this is probably just a variation of the tests that would call `stack.Preview` and not pass a snapshot to `assert`. 3. stdout, stderr and log messages are returned in bulk at the end of the test. Plus there are a couple of calls to the language runtime that don't correctly thread stdout/stderr to use and so default to the process `os.Stdout/Stderr`. stdout/stderr streaming shows up in a load of other places as well so I'm thinking of a clean way to handle all of them together. Log message streaming we can probably do by just turning RunLanguageTest to a streaming grpc call. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Abhinav Gupta <abhinav@pulumi.com>
2023-09-13 15:17:46 +00:00
}
// Helper marks the calling function as a test helper function.
// When printing file and line information, that function will be skipped.
func (l *L) Helper() {
pc, _, _, ok := runtime.Caller(1) // skip this function
if !ok {
return // unlikely but not worth panicking over
}
frame, _ := runtime.CallersFrames([]uintptr{pc}).Next()
if frame.Function == "" {
return
}
l.mu.Lock()
defer l.mu.Unlock()
if l.helpers == nil {
l.helpers = mapset.NewSet[string]()
Add matrix testing (#13705) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Adds the first pass of matrix testing. Matrix testing allows us to define tests once in pulumi/pulumi via PCL and then run those tests against each language plugin to verify code generation and runtime correctness. Rather than packing matrix tests and all the associated data and machinery into the CLI itself we define a new Go package at cmd/pulumi-test-lanaguage. This depends on pkg and runs the deployment engine in a unique way for matrix tests but it is running the proper deployment engine with a proper backend (always filestate, using $TEMP). Currently only NodeJS is hooked up to run these tests, and all the code for that currently lives in sdk/nodejs/cmd/pulumi-language-nodejs/language_test.go. I expect we'll move that helper code to sdk/go/common and use it in each language plugin to run the tests in the same way. This first pass includes 3 simple tests: * l1-empty that runs an empty PCL file and checks just a stack is created * l1-output-bool that runs a PCL program that returns two stack outputs of `true` and `false * l2-resource-simple that runs a PCL program creating a simple resource with a single bool property These tests are themselves tested with a mock language runtime. This verifies the behavior of the matrix test framework for both correct and incorrect language hosts (that is some the mock language runtimes purposefully cause errors or compute the wrong result). There are a number of things missing from from the core framework still, but I feel don't block getting this first pass merged and starting to be used. 1. The tests can not currently run in parallel. That is calling RunLanguageTest in parallel will break things. This is due to two separate problems. Firstly is that the SDK snapshot's are not safe to write in parallel (when PULUMI_ACCEPT is true), this should be fairly easy to fix by doing a write to dst-{random} and them atomic move to dst. Secondly is that the deployment engine itself has mutable global state, short term we should probably just lock around that part RunLanguageTest, long term it would be good to clean that up. 2. We need a way to verify "preview" behavior, I think this is probably just a variation of the tests that would call `stack.Preview` and not pass a snapshot to `assert`. 3. stdout, stderr and log messages are returned in bulk at the end of the test. Plus there are a couple of calls to the language runtime that don't correctly thread stdout/stderr to use and so default to the process `os.Stdout/Stderr`. stdout/stderr streaming shows up in a load of other places as well so I'm thinking of a clean way to handle all of them together. Log message streaming we can probably do by just turning RunLanguageTest to a streaming grpc call. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Abhinav Gupta <abhinav@pulumi.com>
2023-09-13 15:17:46 +00:00
}
l.helpers.Add(frame.Function)
Add matrix testing (#13705) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Adds the first pass of matrix testing. Matrix testing allows us to define tests once in pulumi/pulumi via PCL and then run those tests against each language plugin to verify code generation and runtime correctness. Rather than packing matrix tests and all the associated data and machinery into the CLI itself we define a new Go package at cmd/pulumi-test-lanaguage. This depends on pkg and runs the deployment engine in a unique way for matrix tests but it is running the proper deployment engine with a proper backend (always filestate, using $TEMP). Currently only NodeJS is hooked up to run these tests, and all the code for that currently lives in sdk/nodejs/cmd/pulumi-language-nodejs/language_test.go. I expect we'll move that helper code to sdk/go/common and use it in each language plugin to run the tests in the same way. This first pass includes 3 simple tests: * l1-empty that runs an empty PCL file and checks just a stack is created * l1-output-bool that runs a PCL program that returns two stack outputs of `true` and `false * l2-resource-simple that runs a PCL program creating a simple resource with a single bool property These tests are themselves tested with a mock language runtime. This verifies the behavior of the matrix test framework for both correct and incorrect language hosts (that is some the mock language runtimes purposefully cause errors or compute the wrong result). There are a number of things missing from from the core framework still, but I feel don't block getting this first pass merged and starting to be used. 1. The tests can not currently run in parallel. That is calling RunLanguageTest in parallel will break things. This is due to two separate problems. Firstly is that the SDK snapshot's are not safe to write in parallel (when PULUMI_ACCEPT is true), this should be fairly easy to fix by doing a write to dst-{random} and them atomic move to dst. Secondly is that the deployment engine itself has mutable global state, short term we should probably just lock around that part RunLanguageTest, long term it would be good to clean that up. 2. We need a way to verify "preview" behavior, I think this is probably just a variation of the tests that would call `stack.Preview` and not pass a snapshot to `assert`. 3. stdout, stderr and log messages are returned in bulk at the end of the test. Plus there are a couple of calls to the language runtime that don't correctly thread stdout/stderr to use and so default to the process `os.Stdout/Stderr`. stdout/stderr streaming shows up in a load of other places as well so I'm thinking of a clean way to handle all of them together. Log message streaming we can probably do by just turning RunLanguageTest to a streaming grpc call. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Abhinav Gupta <abhinav@pulumi.com>
2023-09-13 15:17:46 +00:00
}
// FailNow marks this test as having failed and halts execution.
func (l *L) FailNow() {
l.Fail()
runtime.Goexit()
}
// Fail marks this test as failed but keeps executing.
func (l *L) Fail() {
l.mu.Lock()
defer l.mu.Unlock()
l.failed = true
}
// Failed returns whether this test has failed.
func (l *L) Failed() bool {
l.mu.RLock()
defer l.mu.RUnlock()
return l.failed
}
// Errorf records the given error message and marks this test as failed.
func (l *L) Errorf(format string, args ...interface{}) {
l.log(1, fmt.Sprintf(format, args...))
l.Fail()
}
// Logf records the given message in the L's logs.
func (l *L) Logf(format string, args ...interface{}) {
l.log(1, fmt.Sprintf(format, args...))
}
// log records the given message in the L's logs.
//
// Skip specifies the number of stack frames to skip
// when recording the caller's location.
// 0 refers to the immediate caller of log.
//
// Typically, when used from an exported method on L,
// most callers will want to pass skip=1 to skip themselves
// and record the location of their caller.
func (l *L) log(skip int, msg string) {
file, line := "???", 1
if frame, ok := l.callerFrame(skip + 1); ok {
file, line = frame.File, frame.Line
}
msg = fmt.Sprintf("%s:%d: %s", filepath.Base(file), line, msg)
l.mu.Lock()
l.logs = append(l.logs, msg)
l.mu.Unlock()
}
// Maximal stack depth to search for the caller's frame.
const _maxStackDepth = 50
// callerFrame searches the call stack for the first frame
// that isn't a helper function.
//
// skip specifies the initial number of frames to skip
// with 0 referring to the immediate caller of callerFrame.
func (l *L) callerFrame(skip int) (frame runtime.Frame, ok bool) {
var pc [_maxStackDepth]uintptr
n := runtime.Callers(skip+2, pc[:]) // skip runtime.Callers and callerFrame
if n == 0 {
return frame, false
}
l.mu.RLock()
defer l.mu.RUnlock()
frames := runtime.CallersFrames(pc[:n])
for {
frame, more := frames.Next()
if !l.helpers.Contains(frame.Function) {
Add matrix testing (#13705) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Adds the first pass of matrix testing. Matrix testing allows us to define tests once in pulumi/pulumi via PCL and then run those tests against each language plugin to verify code generation and runtime correctness. Rather than packing matrix tests and all the associated data and machinery into the CLI itself we define a new Go package at cmd/pulumi-test-lanaguage. This depends on pkg and runs the deployment engine in a unique way for matrix tests but it is running the proper deployment engine with a proper backend (always filestate, using $TEMP). Currently only NodeJS is hooked up to run these tests, and all the code for that currently lives in sdk/nodejs/cmd/pulumi-language-nodejs/language_test.go. I expect we'll move that helper code to sdk/go/common and use it in each language plugin to run the tests in the same way. This first pass includes 3 simple tests: * l1-empty that runs an empty PCL file and checks just a stack is created * l1-output-bool that runs a PCL program that returns two stack outputs of `true` and `false * l2-resource-simple that runs a PCL program creating a simple resource with a single bool property These tests are themselves tested with a mock language runtime. This verifies the behavior of the matrix test framework for both correct and incorrect language hosts (that is some the mock language runtimes purposefully cause errors or compute the wrong result). There are a number of things missing from from the core framework still, but I feel don't block getting this first pass merged and starting to be used. 1. The tests can not currently run in parallel. That is calling RunLanguageTest in parallel will break things. This is due to two separate problems. Firstly is that the SDK snapshot's are not safe to write in parallel (when PULUMI_ACCEPT is true), this should be fairly easy to fix by doing a write to dst-{random} and them atomic move to dst. Secondly is that the deployment engine itself has mutable global state, short term we should probably just lock around that part RunLanguageTest, long term it would be good to clean that up. 2. We need a way to verify "preview" behavior, I think this is probably just a variation of the tests that would call `stack.Preview` and not pass a snapshot to `assert`. 3. stdout, stderr and log messages are returned in bulk at the end of the test. Plus there are a couple of calls to the language runtime that don't correctly thread stdout/stderr to use and so default to the process `os.Stdout/Stderr`. stdout/stderr streaming shows up in a load of other places as well so I'm thinking of a clean way to handle all of them together. Log message streaming we can probably do by just turning RunLanguageTest to a streaming grpc call. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Abhinav Gupta <abhinav@pulumi.com>
2023-09-13 15:17:46 +00:00
// Not a helper. Use this frame.
return frame, true
}
if !more {
break
}
}
return frame, false // no non-helper frames found
}
// WithL runs the given function with a new L,
// blocking until the function returns.
//
// It returns the information recorded by the L.
func WithL(f func(*L)) LResult {
// To be able to implement FailNow in the L,
// we need to run it in a separate goroutine
// so that we can call runtime.Goexit.
done := make(chan struct{})
var l L
go func() {
defer func() {
if r := recover(); r != nil {
l.failed = true
l.logs = append(l.logs,
fmt.Sprintf("panic: %v\n\n%s", r, debug.Stack()))
}
close(done)
}()
f(&l)
}()
<-done
return LResult{
Failed: l.failed,
Messages: l.logs,
}
}
// LResult is the result of running a language test.
type LResult struct {
// Failed is true if the test failed.
Failed bool
// Messages contains the messages logged by the test.
//
// This doesn't necessarily mean that the test failed.
// For example, a test may log debugging information
// that is only useful when the test fails.
Messages []string
}
// TestingT is a subset of the testing.T interface.
// [L] implements this interface.
type TestingT interface {
Helper()
FailNow()
Fail()
Failed() bool
Errorf(string, ...interface{})
Logf(string, ...interface{})
}
var (
_ TestingT = (*L)(nil)
_ require.TestingT = (TestingT)(nil) // ensure testify compatibility
)
func assertStackResource(t TestingT, res result.Result, changes display.ResourceChanges) (ok bool) {
t.Helper()
ok = true
ok = ok && assert.Nil(t, res, "expected no error, got %v", res)
ok = ok && assert.NotEmpty(t, changes, "expected at least 1 StepOp")
ok = ok && assert.NotZero(t, changes[deploy.OpCreate], "expected at least 1 Create")
return ok
}
func requireStackResource(t TestingT, res result.Result, changes display.ResourceChanges) {
t.Helper()
if !assertStackResource(t, res, changes) {
t.FailNow()
}
}
// assertPropertyMapMember asserts that the given property map has a member with the given key and value.
func assertPropertyMapMember(
t TestingT,
props resource.PropertyMap,
key string,
want resource.PropertyValue,
) (ok bool) {
t.Helper()
got, ok := props[resource.PropertyKey(key)]
if !assert.True(t, ok, "expected property %q", key) {
return false
}
return assert.Equal(t, want, got, "expected property %q to be %v", key, want)
}