blob: 77974ecf6db4e4099fba81341d6065378a813267 [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package promising_test
import (
"context"
"sync/atomic"
"testing"
"github.com/hashicorp/terraform/internal/promising"
)
func TestOnce(t *testing.T) {
type FakeResult struct {
msg string
}
var o promising.Once[*FakeResult]
ctx := context.Background()
results := make([]*FakeResult, 5)
var callCount atomic.Int64
for i := range results {
// The "Once" mechanism expects to be run inside a task so that
// it can create promises and detect self-dependency problems.
result, err := promising.MainTask(ctx, func(ctx context.Context) (*FakeResult, error) {
return o.Do(ctx, "test", func(ctx context.Context) (*FakeResult, error) {
callCount.Add(1)
return &FakeResult{
msg: "hello",
}, nil
})
})
if err != nil {
t.Fatal(err)
}
results[i] = result
}
if got, want := callCount.Load(), int64(1); got != want {
t.Errorf("incorrect call count %d; want %d", got, want)
}
gotPtr := results[0]
if gotPtr == nil {
t.Fatal("first result is nil; want non-nil pointer")
}
if got, want := gotPtr.msg, "hello"; got != want {
t.Fatalf("wrong message %q; want %q", got, want)
}
// Because of the coalescing effect of Once, all of the results should
// point to the same FakeResult object.
for i, result := range results {
if result != gotPtr {
t.Errorf("result %d does not match result 0; all results should be identical", i)
}
}
}