Repository: opentofu/opentofu
File: internal/builtin/provisioners/local-exec/resource_provisioner_test.go (Go)

Code before:
	case <-doneCh:
		t.Logf(maxTempl, finishWithin, time.Since(stopTime))
	case <-time.After(finishWithin):
		t.Fatalf(maxTempl, finishWithin, time.Since(stopTime))
	}
}

func TestResourceProvider_ApplyCustomInterpreter(t *testing.T) {
	output := cli.NewMockUi()
	p := New()

	schema := p.GetSchema().Provisioner

	c, err := schema.CoerceValue(cty.ObjectVal(map[string]cty.Value{
		"interpreter": cty.ListVal([]cty.Value{cty.StringVal("echo"), cty.StringVal("is")}),
		"command":     cty.StringVal("not really an interpreter"),
	}))
	if err != nil {
		t.Fatal(err)
	}

	resp := p.ProvisionResource(provisioners.ProvisionResourceRequest{
		Config:   c,
		UIOutput: output,
	})

	if resp.Diagnostics.HasErrors() {
		t.Fatal(resp.Diagnostics.Err())
	}

	got := strings.TrimSpace(output.OutputWriter.String())
	want := `Executing: ["echo" "is" "not really an interpreter"]
is not really an interpreter`
	if got != want {
		t.Errorf("wrong output\ngot:  %s\nwant: %s", got, want)
	}
}

func TestResourceProvider_ApplyCustomWorkingDirectory(t *testing.T) {
	testdir := "working_dir_test"
	if err := os.Mkdir(testdir, 0755); err != nil {
		t.Fatal(err)
	}
	defer os.Remove(testdir)

	output := cli.NewMockUi()
	p := New()
	schema := p.GetSchema().Provisioner

	command := "echo `pwd`"
	if runtime.GOOS == "windows" {

Review comment (suggestion):
```suggestion
	<-doneCh
	resp := provisionerResp.Load()
	provisionerErr := resp.Diagnostics.Err()
	if provisionerErr == nil {
		t.Fatalf("expected error but got nothing")
	}
	if !strings.Contains(provisionerErr.Error(), "signal: killed") {
		t.Fatalf(`expected the reason of the error found to be "signal: killed" but the error didn't contain it: %s`, provisionerErr)
	}
```
Wouldn't this make the test more robust? Once the channel is closed, there should be also an error in the atomic object, and that error should contain a diagnostic with a clear reason since we stopped it.

Code after:
		// pass the minimum time check above.
		if resp.Diagnostics.HasErrors() {
			t.Fatalf("provisioner failed: %s", resp.Diagnostics.Err())
		}
		t.Fatalf("provisioner responded with success before we asked it to stop")
	}

	// Stop it
	stopTime := time.Now()
	if err := p.Stop(); err != nil {
		t.Fatal(err)
	}

	maxTempl := "expected to finish under %s, finished in %s"
	finishWithin := (2 * time.Second)
	select {
	case <-doneCh:
		t.Logf(maxTempl, finishWithin, time.Since(stopTime))
	case <-time.After(finishWithin):
		t.Fatalf(maxTempl, finishWithin, time.Since(stopTime))
	}

	// Our background goroutine _must_ eventually exit before we consider
	// the test to be done.
	for range doneCh {
	}
}

func TestResourceProvider_ApplyCustomInterpreter(t *testing.T) {
	output := cli.NewMockUi()
	p := New()

	schema := p.GetSchema().Provisioner

	c, err := schema.CoerceValue(cty.ObjectVal(map[string]cty.Value{
		"interpreter": cty.ListVal([]cty.Value{cty.StringVal("echo"), cty.StringVal("is")}),
		"command":     cty.StringVal("not really an interpreter"),
	}))
	if err != nil {
		t.Fatal(err)
	}

	resp := p.ProvisionResource(provisioners.ProvisionResourceRequest{
		Config:   c,
		UIOutput: output,
	})

	if resp.Diagnostics.HasErrors() {
		t.Fatal(resp.Diagnostics.Err())
	}