volumetypes unit tests; 'Extract' method for consistency; rename blockStorage to blockstorage and volumeTypes to volumetypes
diff --git a/acceptance/openstack/blockStorage/v1/blockstorage_test.go.bak b/acceptance/openstack/blockstorage/v1/blockstorage_test.go.bak
similarity index 100%
rename from acceptance/openstack/blockStorage/v1/blockstorage_test.go.bak
rename to acceptance/openstack/blockstorage/v1/blockstorage_test.go.bak
diff --git a/acceptance/openstack/blockStorage/v1/snapshots_test.go b/acceptance/openstack/blockstorage/v1/snapshots_test.go
similarity index 100%
rename from acceptance/openstack/blockStorage/v1/snapshots_test.go
rename to acceptance/openstack/blockstorage/v1/snapshots_test.go
diff --git a/acceptance/openstack/blockStorage/v1/volumes_test.go b/acceptance/openstack/blockstorage/v1/volumes_test.go
similarity index 100%
rename from acceptance/openstack/blockStorage/v1/volumes_test.go
rename to acceptance/openstack/blockstorage/v1/volumes_test.go
diff --git a/acceptance/openstack/blockStorage/v1/volumeTypes_test.go b/acceptance/openstack/blockstorage/v1/volumetypes_test.go
similarity index 94%
rename from acceptance/openstack/blockStorage/v1/volumeTypes_test.go
rename to acceptance/openstack/blockstorage/v1/volumetypes_test.go
index 0317768..be0d2d8 100644
--- a/acceptance/openstack/blockStorage/v1/volumeTypes_test.go
+++ b/acceptance/openstack/blockstorage/v1/volumetypes_test.go
@@ -6,7 +6,7 @@
 	"testing"
 	"time"
 
-	"github.com/rackspace/gophercloud/openstack/blockStorage/v1/volumeTypes"
+	"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
diff --git a/openstack/blockStorage/v1/volumeTypes/requests.go b/openstack/blockStorage/v1/volumeTypes/requests.go
deleted file mode 100644
index 42c4a8b..0000000
--- a/openstack/blockStorage/v1/volumeTypes/requests.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package volumeTypes
-
-import (
-	"github.com/racker/perigee"
-	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
-	"github.com/rackspace/gophercloud/pagination"
-)
-
-type CreateOpts struct {
-	ExtraSpecs map[string]interface{}
-	Name       string
-}
-
-func Create(client *gophercloud.ServiceClient, opts CreateOpts) (*VolumeType, error) {
-	type volumeType struct {
-		ExtraSpecs map[string]interface{} `json:"extra_specs,omitempty"`
-		Name       *string                `json:"name,omitempty"`
-	}
-
-	type request struct {
-		VolumeType volumeType `json:"volume_type"`
-	}
-
-	reqBody := request{
-		VolumeType: volumeType{},
-	}
-
-	reqBody.VolumeType.Name = utils.MaybeString(opts.Name)
-	reqBody.VolumeType.ExtraSpecs = opts.ExtraSpecs
-
-	type response struct {
-		VolumeType VolumeType `json:"volume_type"`
-	}
-
-	var respBody response
-
-	_, err := perigee.Request("POST", volumeTypesURL(client), perigee.Options{
-		MoreHeaders: client.Provider.AuthenticatedHeaders(),
-		OkCodes:     []int{200},
-		ReqBody:     &reqBody,
-		Results:     &respBody,
-	})
-	if err != nil {
-		return nil, err
-	}
-
-	return &respBody.VolumeType, nil
-
-}
-
-func Delete(client *gophercloud.ServiceClient, id string) error {
-	_, err := perigee.Request("DELETE", volumeTypeURL(client, id), perigee.Options{
-		MoreHeaders: client.Provider.AuthenticatedHeaders(),
-		OkCodes:     []int{202},
-	})
-	return err
-}
-
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
-	var gr GetResult
-	_, gr.Err = perigee.Request("GET", volumeTypeURL(client, id), perigee.Options{
-		Results:     &gr.Resp,
-		MoreHeaders: client.Provider.AuthenticatedHeaders(),
-	})
-	return gr
-}
-
-// ListOpts holds options for listing volumes. It is passed to the volumes.List function.
-type ListOpts struct {
-}
-
-func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
-	createPage := func(r pagination.LastHTTPResponse) pagination.Page {
-		return ListResult{pagination.SinglePageBase(r)}
-	}
-
-	return pagination.NewPager(client, volumeTypesURL(client), createPage)
-}
diff --git a/openstack/blockStorage/v1/volumeTypes/requests_test.go b/openstack/blockStorage/v1/volumeTypes/requests_test.go
deleted file mode 100644
index 3051821..0000000
--- a/openstack/blockStorage/v1/volumeTypes/requests_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package volumeTypes
diff --git a/openstack/blockStorage/v1/volumeTypes/urls.go b/openstack/blockStorage/v1/volumeTypes/urls.go
deleted file mode 100644
index 8df75cd..0000000
--- a/openstack/blockStorage/v1/volumeTypes/urls.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package volumeTypes
-
-import "github.com/rackspace/gophercloud"
-
-func volumeTypesURL(c *gophercloud.ServiceClient) string {
-	return c.ServiceURL("types")
-}
-
-func volumeTypeURL(c *gophercloud.ServiceClient, id string) string {
-	return c.ServiceURL("types", id)
-}
diff --git a/openstack/blockStorage/v1/volumeTypes/urls_test.go b/openstack/blockStorage/v1/volumeTypes/urls_test.go
deleted file mode 100644
index 492f6e7..0000000
--- a/openstack/blockStorage/v1/volumeTypes/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package volumeTypes
-
-import (
-	"testing"
-
-	"github.com/rackspace/gophercloud"
-	th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909"
-
-func endpointClient() *gophercloud.ServiceClient {
-	return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestVolumeTypesURL(t *testing.T) {
-	actual := volumeTypesURL(endpointClient())
-	expected := endpoint + "types"
-	th.AssertEquals(t, expected, actual)
-}
-
-func TestVolumeTypeURL(t *testing.T) {
-	actual := volumeTypeURL(endpointClient(), "foo")
-	expected := endpoint + "types/foo"
-	th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/blockStorage/v1/snapshots/requests.go b/openstack/blockstorage/v1/snapshots/requests.go
similarity index 100%
rename from openstack/blockStorage/v1/snapshots/requests.go
rename to openstack/blockstorage/v1/snapshots/requests.go
diff --git a/openstack/blockStorage/v1/snapshots/requests_test.go b/openstack/blockstorage/v1/snapshots/requests_test.go
similarity index 100%
rename from openstack/blockStorage/v1/snapshots/requests_test.go
rename to openstack/blockstorage/v1/snapshots/requests_test.go
diff --git a/openstack/blockStorage/v1/snapshots/results.go b/openstack/blockstorage/v1/snapshots/results.go
similarity index 100%
rename from openstack/blockStorage/v1/snapshots/results.go
rename to openstack/blockstorage/v1/snapshots/results.go
diff --git a/openstack/blockStorage/v1/snapshots/urls.go b/openstack/blockstorage/v1/snapshots/urls.go
similarity index 100%
rename from openstack/blockStorage/v1/snapshots/urls.go
rename to openstack/blockstorage/v1/snapshots/urls.go
diff --git a/openstack/blockStorage/v1/snapshots/urls_test.go b/openstack/blockstorage/v1/snapshots/urls_test.go
similarity index 100%
rename from openstack/blockStorage/v1/snapshots/urls_test.go
rename to openstack/blockstorage/v1/snapshots/urls_test.go
diff --git a/openstack/blockStorage/v1/volumes/requests.go b/openstack/blockstorage/v1/volumes/requests.go
similarity index 100%
rename from openstack/blockStorage/v1/volumes/requests.go
rename to openstack/blockstorage/v1/volumes/requests.go
diff --git a/openstack/blockStorage/v1/volumes/requests_test.go b/openstack/blockstorage/v1/volumes/requests_test.go
similarity index 100%
rename from openstack/blockStorage/v1/volumes/requests_test.go
rename to openstack/blockstorage/v1/volumes/requests_test.go
diff --git a/openstack/blockStorage/v1/volumes/results.go b/openstack/blockstorage/v1/volumes/results.go
similarity index 100%
rename from openstack/blockStorage/v1/volumes/results.go
rename to openstack/blockstorage/v1/volumes/results.go
diff --git a/openstack/blockStorage/v1/volumes/urls.go b/openstack/blockstorage/v1/volumes/urls.go
similarity index 100%
rename from openstack/blockStorage/v1/volumes/urls.go
rename to openstack/blockstorage/v1/volumes/urls.go
diff --git a/openstack/blockStorage/v1/volumes/urls_test.go b/openstack/blockstorage/v1/volumes/urls_test.go
similarity index 100%
rename from openstack/blockStorage/v1/volumes/urls_test.go
rename to openstack/blockstorage/v1/volumes/urls_test.go
diff --git a/openstack/blockstorage/v1/volumetypes/requests.go b/openstack/blockstorage/v1/volumetypes/requests.go
new file mode 100644
index 0000000..be6bf09
--- /dev/null
+++ b/openstack/blockstorage/v1/volumetypes/requests.go
@@ -0,0 +1,71 @@
+package volumetypes
+
+import (
+	"fmt"
+	"github.com/racker/perigee"
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/openstack/utils"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+type CreateOpts struct {
+	ExtraSpecs map[string]interface{}
+	Name       string
+}
+
+func Create(client *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
+	type volumeType struct {
+		ExtraSpecs map[string]interface{} `json:"extra_specs,omitempty"`
+		Name       *string                `json:"name,omitempty"`
+	}
+
+	type request struct {
+		VolumeType volumeType `json:"volume_type"`
+	}
+
+	reqBody := request{
+		VolumeType: volumeType{},
+	}
+
+	reqBody.VolumeType.Name = utils.MaybeString(opts.Name)
+	reqBody.VolumeType.ExtraSpecs = opts.ExtraSpecs
+
+	var res CreateResult
+	_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
+		MoreHeaders: client.Provider.AuthenticatedHeaders(),
+		OkCodes:     []int{200},
+		ReqBody:     &reqBody,
+		Results:     &res.Resp,
+	})
+	return res
+}
+
+func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
+	var res DeleteResult
+	_, err := perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
+		MoreHeaders: client.Provider.AuthenticatedHeaders(),
+		OkCodes:     []int{202},
+	})
+	res.Err = err
+	return res
+}
+
+func Get(client *gophercloud.ServiceClient, id string) GetResult {
+	var res GetResult
+	resp, err := perigee.Request("GET", getURL(client, id), perigee.Options{
+		MoreHeaders: client.Provider.AuthenticatedHeaders(),
+		OkCodes:     []int{200},
+		Results:     &res.Resp,
+	})
+	res.Err = err
+	fmt.Printf("resp: %+v\n", resp)
+	return res
+}
+
+func List(client *gophercloud.ServiceClient) pagination.Pager {
+	createPage := func(r pagination.LastHTTPResponse) pagination.Page {
+		return ListResult{pagination.SinglePageBase(r)}
+	}
+
+	return pagination.NewPager(client, listURL(client), createPage)
+}
diff --git a/openstack/blockstorage/v1/volumetypes/requests_test.go b/openstack/blockstorage/v1/volumetypes/requests_test.go
new file mode 100644
index 0000000..5f83e04
--- /dev/null
+++ b/openstack/blockstorage/v1/volumetypes/requests_test.go
@@ -0,0 +1,174 @@
+package volumetypes
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
+	th "github.com/rackspace/gophercloud/testhelper"
+)
+
+const TokenID = "123"
+
+func ServiceClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{
+		Provider: &gophercloud.ProviderClient{
+			TokenID: TokenID,
+		},
+		Endpoint: th.Endpoint(),
+	}
+}
+
+func TestList(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/types", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+		{
+			"volume_types": [
+				{
+					"id": "289da7f8-6440-407c-9fb4-7db01ec49164",
+					"name": "vol-type-001",
+					"extra_specs": {
+						"capabilities": "gpu"
+						}
+				},
+				{
+					"id": "96c3bda7-c82a-4f50-be73-ca7621794835",
+					"name": "vol-type-002",
+					"extra_specs": {}
+				}
+			]
+		}
+		`)
+	})
+
+	client := ServiceClient()
+	count := 0
+
+	List(client).EachPage(func(page pagination.Page) (bool, error) {
+		count++
+		actual, err := ExtractVolumeTypes(page)
+		if err != nil {
+			t.Errorf("Failed to extract volume types: %v", err)
+			return false, err
+		}
+
+		expected := []VolumeType{
+			VolumeType{
+				ID:   "289da7f8-6440-407c-9fb4-7db01ec49164",
+				Name: "vol-type-001",
+				ExtraSpecs: map[string]interface{}{
+					"capabilities": "gpu",
+				},
+			},
+			VolumeType{
+				ID:         "96c3bda7-c82a-4f50-be73-ca7621794835",
+				Name:       "vol-type-002",
+				ExtraSpecs: map[string]interface{}{},
+			},
+		}
+
+		th.CheckDeepEquals(t, expected, actual)
+
+		return true, nil
+	})
+
+	if count != 1 {
+		t.Errorf("Expected 1 page, got %d", count)
+	}
+}
+
+func TestGet(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/types/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+		fmt.Fprintf(w, `
+{
+    "volume_type": {
+        "name": "vol-type-001",
+        "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
+		"extra_specs": {
+			"serverNumber": 2
+		}
+    }
+}
+			`)
+	})
+
+	vt, err := Get(ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
+	th.AssertNoErr(t, err)
+
+	t.Logf("vt: %+v\n", vt)
+	th.AssertDeepEquals(t, vt.ExtraSpecs, map[string]interface{}{"serverNumber": 2})
+	th.AssertEquals(t, vt.Name, "vol-type-001")
+	th.AssertEquals(t, vt.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
+}
+
+func TestCreate(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/types", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", TokenID)
+		th.TestHeader(t, r, "Content-Type", "application/json")
+		th.TestHeader(t, r, "Accept", "application/json")
+		th.TestJSONRequest(t, r, `
+{
+    "volume_type": {
+        "name": "vol-type-001",
+		"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
+    }
+}
+			`)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusCreated)
+
+		fmt.Fprintf(w, `
+{
+    "volume_type": {
+        "name": "vol-type-001",
+        "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
+    }
+}
+		`)
+	})
+
+	options := CreateOpts{Name: "vol-type-001"}
+	n, err := Create(ServiceClient(), options).Extract()
+	th.AssertNoErr(t, err)
+
+	th.AssertEquals(t, n.Name, "vol-type-001")
+	th.AssertEquals(t, n.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
+}
+
+func TestDelete(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/types/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "DELETE")
+		th.TestHeader(t, r, "X-Auth-Token", TokenID)
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	res := Delete(ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22")
+	th.AssertNoErr(t, res.Err)
+}
diff --git a/openstack/blockStorage/v1/volumeTypes/results.go b/openstack/blockstorage/v1/volumetypes/results.go
similarity index 63%
rename from openstack/blockStorage/v1/volumeTypes/results.go
rename to openstack/blockstorage/v1/volumetypes/results.go
index 83583b8..54847be 100644
--- a/openstack/blockStorage/v1/volumeTypes/results.go
+++ b/openstack/blockstorage/v1/volumetypes/results.go
@@ -1,4 +1,4 @@
-package volumeTypes
+package volumetypes
 
 import (
 	"fmt"
@@ -10,8 +10,8 @@
 
 type VolumeType struct {
 	ExtraSpecs map[string]interface{} `json:"extra_specs" mapstructure:"extra_specs"`
-	ID         string                 `json:"id"		  mapstructure:"id"`
-	Name       string                 `json:"name"		  mapstructure:"name"`
+	ID         string                 `json:"id" mapstructure:"id"`
+	Name       string                 `json:"name" mapstructure:"name"`
 }
 
 // ListResult is a *http.Response that is returned from a call to the List function.
@@ -38,20 +38,33 @@
 	return response.VolumeTypes, err
 }
 
-type GetResult struct {
+type commonResult struct {
 	gophercloud.CommonResult
 }
 
-func (gr GetResult) ExtractVolumeType() (*VolumeType, error) {
-	if gr.Err != nil {
-		return nil, gr.Err
+func (r commonResult) Extract() (*VolumeType, error) {
+	if r.Err != nil {
+		return nil, r.Err
 	}
-	var response struct {
-		VolumeType *VolumeType `mapstructure:"volume_type"`
+
+	var res struct {
+		VolumeType *VolumeType `json:"volume_type" mapstructure:"volume_type"`
 	}
-	err := mapstructure.Decode(gr, &response)
+
+	err := mapstructure.Decode(r.Resp, &res)
 	if err != nil {
-		return nil, fmt.Errorf("volumeTypes: Error decoding volumeTypes.GetResult: %v", err)
+		return nil, fmt.Errorf("Error decoding Volume Type: %v", err)
 	}
-	return response.VolumeType, nil
+
+	return res.VolumeType, nil
 }
+
+type GetResult struct {
+	commonResult
+}
+
+type CreateResult struct {
+	commonResult
+}
+
+type DeleteResult commonResult
diff --git a/openstack/blockstorage/v1/volumetypes/urls.go b/openstack/blockstorage/v1/volumetypes/urls.go
new file mode 100644
index 0000000..cf8367b
--- /dev/null
+++ b/openstack/blockstorage/v1/volumetypes/urls.go
@@ -0,0 +1,19 @@
+package volumetypes
+
+import "github.com/rackspace/gophercloud"
+
+func listURL(c *gophercloud.ServiceClient) string {
+	return c.ServiceURL("types")
+}
+
+func createURL(c *gophercloud.ServiceClient) string {
+	return listURL(c)
+}
+
+func getURL(c *gophercloud.ServiceClient, id string) string {
+	return c.ServiceURL("types", id)
+}
+
+func deleteURL(c *gophercloud.ServiceClient, id string) string {
+	return getURL(c, id)
+}
diff --git a/openstack/blockstorage/v1/volumetypes/urls_test.go b/openstack/blockstorage/v1/volumetypes/urls_test.go
new file mode 100644
index 0000000..44016e2
--- /dev/null
+++ b/openstack/blockstorage/v1/volumetypes/urls_test.go
@@ -0,0 +1,38 @@
+package volumetypes
+
+import (
+	"testing"
+
+	"github.com/rackspace/gophercloud"
+	th "github.com/rackspace/gophercloud/testhelper"
+)
+
+const endpoint = "http://localhost:57909"
+
+func endpointClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{Endpoint: endpoint}
+}
+
+func TestListURL(t *testing.T) {
+	actual := listURL(endpointClient())
+	expected := endpoint + "types"
+	th.AssertEquals(t, expected, actual)
+}
+
+func TestCreateURL(t *testing.T) {
+	actual := createURL(endpointClient())
+	expected := endpoint + "types"
+	th.AssertEquals(t, expected, actual)
+}
+
+func TestGetURL(t *testing.T) {
+	actual := getURL(endpointClient(), "foo")
+	expected := endpoint + "types/foo"
+	th.AssertEquals(t, expected, actual)
+}
+
+func TestDeleteURL(t *testing.T) {
+	actual := deleteURL(endpointClient(), "foo")
+	expected := endpoint + "types/foo"
+	th.AssertEquals(t, expected, actual)
+}