Skip to content

Commit

Permalink
provider/test: a test provider
Browse files Browse the repository at this point in the history
Here we also introduce a `test` provider meant as an aid to exposing
via automated tests issues involving interactions between
`helper/schema` and Terraform core.

This has been helpful so far in diagnosing `ignore_changes` problems,
and I imagine it will be helpful in other contexts as well.

We'll have to be careful to prevent the `test` provider from becoming a
dumping ground for poorly specified tests that have a clear home
elsewhere. But for bug exposure I think it's useful to have.
  • Loading branch information
phinze committed Mar 21, 2016
1 parent 3bb9903 commit c3e27b3
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 1 deletion.
19 changes: 19 additions & 0 deletions builtin/providers/test/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package test

import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)

func Provider() terraform.ResourceProvider {
return &schema.Provider{
ResourcesMap: map[string]*schema.Resource{
"test_resource": testResource(),
},
ConfigureFunc: providerConfigure,
}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
return nil, nil
}
16 changes: 16 additions & 0 deletions builtin/providers/test/provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package test

import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)

var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider

func init() {
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"test": testAccProvider,
}
}
53 changes: 53 additions & 0 deletions builtin/providers/test/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package test

import (
"fmt"

"github.com/hashicorp/terraform/helper/schema"
)

func testResource() *schema.Resource {
return &schema.Resource{
Create: testResourceCreate,
Read: testResourceRead,
Update: testResourceUpdate,
Delete: testResourceDelete,
Schema: map[string]*schema.Schema{
"required": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"optional": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"optional_force_new": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
},
}
}

func testResourceCreate(d *schema.ResourceData, meta interface{}) error {
d.SetId("testId")

// Required must make it through to Create
if _, ok := d.GetOk("required"); !ok {
return fmt.Errorf("Missing attribute 'required', but it's required!")
}
return nil
}

func testResourceRead(d *schema.ResourceData, meta interface{}) error {
return nil
}

func testResourceUpdate(d *schema.ResourceData, meta interface{}) error {
return nil
}

func testResourceDelete(d *schema.ResourceData, meta interface{}) error {
return nil
}
32 changes: 32 additions & 0 deletions builtin/providers/test/resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package test

import (
"strings"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestResource_basic(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
Providers: testAccProviders,
CheckDestroy: testAccCheckResourceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: strings.TrimSpace(`
resource "test_resource" "foo" {
required = "yep"
}
`),
Check: func(s *terraform.State) error {
return nil
},
},
},
})
}

func testAccCheckResourceDestroy(s *terraform.State) error {
return nil
}
24 changes: 23 additions & 1 deletion helper/resource/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import (

const TestEnvVar = "TF_ACC"

// UnitTestOverride is a value that when set in TestEnvVar indicates that this
// is a unit test borrowing the acceptance testing framework.
const UnitTestOverride = "UnitTestOverride"

// TestCheckFunc is the callback type used with acceptance tests to check
// the state of a resource. The state passed in is the latest state known,
// or in the case of being after a destroy, it is the last known state when
Expand Down Expand Up @@ -108,14 +112,16 @@ func Test(t TestT, c TestCase) {
return
}

isUnitTest := (os.Getenv(TestEnvVar) == UnitTestOverride)

logWriter, err := logging.LogOutput()
if err != nil {
t.Error(fmt.Errorf("error setting up logging: %s", err))
}
log.SetOutput(logWriter)

// We require verbose mode so that the user knows what is going on.
if !testTesting && !testing.Verbose() {
if !testTesting && !testing.Verbose() && !isUnitTest {
t.Fatal("Acceptance tests must be run with the -v flag on tests")
return
}
Expand Down Expand Up @@ -173,6 +179,22 @@ func Test(t TestT, c TestCase) {
}
}

// UnitTest is a helper to force the acceptance testing harness to run in the
// normal unit test suite. This should only be used for resource that don't
// have any external dependencies.
func UnitTest(t TestT, c TestCase) {
oldEnv := os.Getenv(TestEnvVar)
if err := os.Setenv(TestEnvVar, UnitTestOverride); err != nil {
t.Fatal(err)
}
defer func() {
if err := os.Setenv(TestEnvVar, oldEnv); err != nil {
t.Fatal(err)
}
}()
Test(t, c)
}

func testStep(
opts terraform.ContextOpts,
state *terraform.State,
Expand Down

0 comments on commit c3e27b3

Please sign in to comment.