Skip to content

Commit 77aa06b

Browse files
committed
add tests
1 parent 570a6a5 commit 77aa06b

File tree

6 files changed

+146
-65
lines changed

6 files changed

+146
-65
lines changed

internal/command/test_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"runtime"
1414
"strings"
1515
"testing"
16+
"time"
1617

1718
"github.com/google/go-cmp/cmp"
1819
"github.com/hashicorp/cli"
@@ -813,6 +814,91 @@ func TestTest_Parallel(t *testing.T) {
813814
}
814815
}
815816

817+
func TestTest_ParallelJSON(t *testing.T) {
818+
td := t.TempDir()
819+
testCopyDir(t, testFixturePath(path.Join("test", "parallel")), td)
820+
defer testChdir(t, td)()
821+
822+
provider := testing_command.NewProvider(&testing_command.ResourceStore{
823+
Data: make(map[string]cty.Value),
824+
Nolock: true,
825+
})
826+
providerSource, close := newMockProviderSource(t, map[string][]string{
827+
"test": {"1.0.0"},
828+
})
829+
defer close()
830+
831+
streams, done := terminal.StreamsForTesting(t)
832+
view := views.NewView(streams)
833+
ui := new(cli.MockUi)
834+
835+
meta := Meta{
836+
testingOverrides: metaOverridesForProvider(provider.Provider),
837+
Ui: ui,
838+
View: view,
839+
Streams: streams,
840+
ProviderSource: providerSource,
841+
}
842+
843+
init := &InitCommand{Meta: meta}
844+
if code := init.Run(nil); code != 0 {
845+
output := done(t)
846+
t.Fatalf("expected status code %d but got %d: %s", 9, code, output.All())
847+
}
848+
849+
c := &TestCommand{Meta: meta}
850+
c.Run([]string{"-json", "-no-color"})
851+
output := done(t).All()
852+
853+
if !strings.Contains(output, "40 passed, 0 failed") {
854+
t.Errorf("output didn't produce the right output:\n\n%s", output)
855+
}
856+
857+
// Split the log into lines
858+
lines := strings.Split(output, "\n")
859+
860+
// Find the start of the teardown and complete timestamps
861+
// The difference is the approximate duration of the test teardown operation.
862+
// This test is running in parallel, so we expect the teardown to also run in parallel.
863+
// We sleep for 3 seconds in the test teardown to simulate a long-running destroy.
864+
// There are 6 unique state keys in the parallel test, so we expect the teardown to take less than 3*6 (18) seconds.
865+
var startTimestamp, completeTimestamp string
866+
for _, line := range lines {
867+
if strings.Contains(line, `{"path":"parallel.tftest.hcl","progress":"teardown"`) {
868+
var obj map[string]interface{}
869+
if err := json.Unmarshal([]byte(line), &obj); err == nil {
870+
if ts, ok := obj["@timestamp"].(string); ok {
871+
startTimestamp = ts
872+
}
873+
}
874+
} else if strings.Contains(line, `{"path":"parallel.tftest.hcl","progress":"complete"`) {
875+
var obj map[string]interface{}
876+
if err := json.Unmarshal([]byte(line), &obj); err == nil {
877+
if ts, ok := obj["@timestamp"].(string); ok {
878+
completeTimestamp = ts
879+
}
880+
}
881+
}
882+
}
883+
884+
if startTimestamp == "" || completeTimestamp == "" {
885+
t.Fatalf("could not find start or complete timestamp in log output")
886+
}
887+
888+
startTime, err := time.Parse(time.RFC3339Nano, startTimestamp)
889+
if err != nil {
890+
t.Fatalf("failed to parse start timestamp: %v", err)
891+
}
892+
completeTime, err := time.Parse(time.RFC3339Nano, completeTimestamp)
893+
if err != nil {
894+
t.Fatalf("failed to parse complete timestamp: %v", err)
895+
}
896+
dur := completeTime.Sub(startTime)
897+
if dur > 10*time.Second {
898+
t.Fatalf("parallel.tftest.hcl duration took too long: %0.2f seconds", dur.Seconds())
899+
}
900+
}
901+
816902
func TestTest_InterruptSkipsRemaining(t *testing.T) {
817903
td := t.TempDir()
818904
testCopyDir(t, testFixturePath(path.Join("test", "with_interrupt_and_additional_file")), td)

internal/command/testdata/test/parallel/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ variable "input" {
55

66
resource "test_resource" "foo" {
77
value = var.input
8+
destroy_wait_seconds = 3
89
}
910

1011
output "value" {

internal/command/testdata/test/parallel/parallel.tftest.hcl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -515,10 +515,3 @@ run "test_30" {
515515
error_message = "error in test_30"
516516
}
517517
}
518-
519-
// Expected order:
520-
// - run [setup]
521-
// - run [test_a, test_d]
522-
// - run [test_b]
523-
// - run [test_c]
524-

internal/command/testing/test_provider.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ func NewProvider(store *ResourceStore) *TestProvider {
133133
provider.Provider.CallFunctionFn = provider.CallFunction
134134
provider.Provider.OpenEphemeralResourceFn = provider.OpenEphemeralResource
135135
provider.Provider.CloseEphemeralResourceFn = provider.CloseEphemeralResource
136+
provider.Provider.NoLock = store.Nolock
136137

137138
return provider
138139
}
@@ -192,8 +193,7 @@ func (provider *TestProvider) DataSourceCount() int {
192193
}
193194

194195
func (provider *TestProvider) count(prefix string) int {
195-
provider.Store.mutex.RLock()
196-
defer provider.Store.mutex.RUnlock()
196+
defer provider.Store.beginRead()()
197197

198198
if len(prefix) == 0 {
199199
return len(provider.Store.Data)
@@ -209,8 +209,7 @@ func (provider *TestProvider) count(prefix string) int {
209209
}
210210

211211
func (provider *TestProvider) string(prefix string) string {
212-
provider.Store.mutex.RLock()
213-
defer provider.Store.mutex.RUnlock()
212+
defer provider.Store.beginRead()()
214213

215214
var keys []string
216215
for key := range provider.Store.Data {
@@ -393,14 +392,14 @@ func (provider *TestProvider) CloseEphemeralResource(providers.CloseEphemeralRes
393392
// For example, when the test provider gets a ReadResource request it will search
394393
// the store for a resource with a matching ID. See (*TestProvider).ReadResource.
395394
type ResourceStore struct {
396-
mutex sync.RWMutex
395+
mutex sync.RWMutex
396+
Nolock bool // nolock is used to disable locking
397397

398398
Data map[string]cty.Value
399399
}
400400

401401
func (store *ResourceStore) Delete(key string) cty.Value {
402-
store.mutex.Lock()
403-
defer store.mutex.Unlock()
402+
defer store.beginWrite()()
404403

405404
if resource, ok := store.Data[key]; ok {
406405
delete(store.Data, key)
@@ -410,15 +409,13 @@ func (store *ResourceStore) Delete(key string) cty.Value {
410409
}
411410

412411
func (store *ResourceStore) Get(key string) cty.Value {
413-
store.mutex.RLock()
414-
defer store.mutex.RUnlock()
412+
defer store.beginRead()()
415413

416414
return store.get(key)
417415
}
418416

419417
func (store *ResourceStore) Put(key string, resource cty.Value) cty.Value {
420-
store.mutex.Lock()
421-
defer store.mutex.Unlock()
418+
defer store.beginWrite()()
422419

423420
old := store.get(key)
424421
store.Data[key] = resource
@@ -431,3 +428,18 @@ func (store *ResourceStore) get(key string) cty.Value {
431428
}
432429
return cty.NilVal
433430
}
431+
432+
func (store *ResourceStore) beginWrite() func() {
433+
if !store.Nolock {
434+
store.mutex.Lock()
435+
return store.mutex.Unlock
436+
}
437+
return func() {}
438+
}
439+
func (store *ResourceStore) beginRead() func() {
440+
if !store.Nolock {
441+
store.mutex.RLock()
442+
return store.mutex.RUnlock
443+
}
444+
return func() {}
445+
}

internal/moduletest/graph/node_state_cleanup.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,7 @@ func (n *NodeStateCleanup) destroy(ctx *EvalContext, runNode *NodeTestRun, waite
136136
Overrides: mocking.PackageOverrides(run.Config, file.Config, run.ModuleConfig),
137137
}
138138

139-
tfCtx, ctxDiags := terraform.NewContext(n.opts.ContextOpts)
140-
diags = diags.Append(ctxDiags)
141-
if ctxDiags.HasErrors() {
142-
return state, diags
143-
}
139+
tfCtx, _ := terraform.NewContext(n.opts.ContextOpts)
144140
ctx.Renderer().Run(run, file, moduletest.TearDown, 0)
145141

146142
waiter.update(tfCtx, moduletest.TearDown, nil)

0 commit comments

Comments
 (0)