func TestListImageDetails(t *testing.T) {
	anon := func(imageService *image.Service) {
		images, err := imageService.ImagesDetail()
		if err != nil {
			t.Error(err)
		}

		if len(images) != 2 {
			t.Error(errors.New("Incorrect number of images found"))
		}
		createdAt, _ := misc.NewDateTimeFromString(`"2014-09-29T14:44:31"`)
		updatedAt, _ := misc.NewDateTimeFromString(`"2014-09-29T15:33:37"`)
		owner := "10014302369510"
		virtualSize := int64(2525125)
		expectedImageDetail := image.DetailResponse{
			Status:          "active",
			Name:            "Ubuntu Server 12.04.5 LTS (amd64 20140927) - Partner Image",
			Deleted:         false,
			ContainerFormat: "bare",
			CreatedAt:       createdAt,
			DiskFormat:      "qcow2",
			UpdatedAt:       updatedAt,
			MinDisk:         8,
			Protected:       false,
			ID:              "8ca068c5-6fde-4701-bab8-322b3e7c8d81",
			MinRAM:          0,
			CheckSum:        "de1831ea85702599a27e7e63a9a444c3",
			Owner:           &owner,
			IsPublic:        true,
			DeletedAt:       nil,
			Properties: map[string]string{
				"com.ubuntu.cloud__1__milestone":    "release",
				"com.hp__1__os_distro":              "com.ubuntu",
				"description":                       "Ubuntu Server 12.04.5 LTS (amd64 20140927) for HP Public Cloud. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.5 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. More information regarding Ubuntu Cloud is available from http://www.ubuntu.com/cloud and instructions for using Juju to deploy workloads are available from http://juju.ubuntu.com EULA: http://www.ubuntu.com/about/about-ubuntu/licensing Privacy Policy: http://www.ubuntu.com/privacy-policy",
				"com.ubuntu.cloud__1__suite":        "precise",
				"com.ubuntu.cloud__1__serial":       "20140927",
				"com.hp__1__bootable_volume":        "True",
				"com.hp__1__vendor":                 "Canonical",
				"com.hp__1__image_lifecycle":        "active",
				"com.hp__1__image_type":             "disk",
				"os_version":                        "12.04",
				"architecture":                      "x86_64",
				"os_type":                           "linux-ext4",
				"com.ubuntu.cloud__1__stream":       "server",
				"com.ubuntu.cloud__1__official":     "True",
				"com.ubuntu.cloud__1__published_at": "2014-09-29T15:33:36"},
			Size:        261423616,
			VirtualSize: &virtualSize}
		testUtil.Equals(t, expectedImageDetail, images[0])
	}

	testImageServiceAction(t, "images/detail?limit=21", sampleImageDetailsData, anon)
}
				t.Error(errors.New("Incorrect URL created, expected '" + urlEndsWith + "' at the end, actual URL:" + reqURL))
			}
			if r.Method == expectedMethod {
				data, _ := json.Marshal(responseOutput)
				w.Write(data)
				w.WriteHeader(200)
				return
			}

			t.Error(errors.New("Failed: r.Method == " + expectedMethod))
		}))
}

// Tests for the special case where image is "" instead of an image structure

var staticCreatedRFC8601, _ = misc.NewDateTimeFromString("2015-04-03T22:47:44")
var staticCreatedTime = staticCreatedRFC8601.Time()

var serverDetailNoImage = ServerDetail{
	ID:               "my_server_id_1",
	Name:             "my_server_name_1",
	Status:           "my_server_status_1",
	Created:          staticCreatedTime,
	Updated:          &staticCreatedTime,
	HostID:           "my_server_hostId_1",
	Addresses:        make(map[string][]Address),
	Links:            []Link{{"href_1", "rel_1"}, {"href_2", "rel_2"}},
	Image:            ImageWrapper{},
	Flavor:           Flavor{ID: "image_id1", Links: []Link{{"href_1", "rel_1"}, {"href_2", "rel_2"}}},
	TaskState:        "my_OS-EXT-STS_task_state_1",
	VMState:          "my_OS-EXT-STS_vm_state_1",
//    under the License.

package blockstorage_test

import (
	"encoding/json"
	"fmt"
	"testing"

	blockstorage "git.openstack.org/stackforge/golang-client.git/blockstorage/v1"
	"git.openstack.org/stackforge/golang-client.git/identity/common"
	"git.openstack.org/stackforge/golang-client.git/misc"
	"git.openstack.org/stackforge/golang-client.git/testUtil"
)

var createdAt, _ = misc.NewDateTimeFromString(`"2014-09-29T15:33:37"`)
var volumeSample = blockstorage.Volume{
	Status:      "ACTIVE",
	DisplayName: "Display",
	Attachments: []blockstorage.VolumeAttachment{
		blockstorage.VolumeAttachment{
			AttachmentID: "attachment-id-1234",
			Device:       "/dev/vdc",
			ServerID:     "server-id-1234",
			VolumeID:     "ID",
		},
	},
	Az:          "az1",
	Bootable:    true,
	CreatedAt:   createdAt,
	Desciption:  "Description",
func TestImageDetail(t *testing.T) {
	testHeaders := http.Header{
		"X-Image-Meta-property-purpose": []string{"test"},
		"X-Image-Meta-status":           []string{"active"},
		"X-Image-Meta-owner":            []string{"54026737306152"},
		"X-Image-Meta-name":             []string{"Ubuntu Minimal"},
		"X-Image-Meta-container_format": []string{"bare"},
		"X-Image-Meta-created_at":       []string{"2015-04-03T18:19:40"},
		"X-Image-Meta-min_ram":          []string{"4096"},
		"X-Image-Meta-updated_at":       []string{"2015-04-03T18:19:42"},
		"X-Image-Meta-property-os":      []string{"ubuntu"},
		"X-Image-Meta-id":               []string{"84cf82c0-41e7-4f5f-8722-40b03878b4a9"},
		"X-Image-Meta-deleted":          []string{"False"},
		"X-Image-Meta-checksum":         []string{"4f783f3917ed4c663c9a983f4ee046fc"},
		"X-Image-Meta-protected":        []string{"False"},
		"X-Image-Meta-min_disk":         []string{"10"},
		"X-Image-Meta-size":             []string{"40894464"},
		"X-Image-Meta-is_public":        []string{"False"},
		"X-Image-Meta-disk_format":      []string{"iso"},
	}

	testBody := []byte("")

	anon := func(imageService *image.Service) {
		detail, err := imageService.ImageDetail("84cf82c0-41e7-4f5f-8722-40b03878b4a9")
		if err != nil {
			t.Error(err)
		}

		createdAt, err := misc.NewDateTimeFromString("2015-04-03T18:19:40")
		if err != nil {
			t.Error(err)
		}

		updatedAt, err := misc.NewDateTimeFromString("2015-04-03T18:19:42")
		if err != nil {
			t.Error(err)
		}

		owner := "54026737306152"

		expectedDetails := image.DetailResponse{
			CheckSum:        "4f783f3917ed4c663c9a983f4ee046fc",
			ContainerFormat: "bare",
			CreatedAt:       createdAt,
			Deleted:         false,
			DeletedAt:       nil,
			DiskFormat:      "iso",
			ID:              "84cf82c0-41e7-4f5f-8722-40b03878b4a9",
			IsPublic:        false,
			MinDisk:         10,
			MinRAM:          4096,
			Name:            "Ubuntu Minimal",
			Owner:           &owner,
			UpdatedAt:       updatedAt,
			Properties: map[string]string{
				"purpose": "test",
				"os":      "ubuntu",
			},
			Protected:   false,
			Status:      "active",
			Size:        40894464,
			VirtualSize: nil,
		}

		testUtil.Equals(t, expectedDetails, detail)
	}

	testImageServiceHeadAction(t, "images/84cf82c0-41e7-4f5f-8722-40b03878b4a9", testHeaders, testBody, anon)
}
func (service Service) headersToDetailResponse(headers http.Header) DetailResponse {
	result := DetailResponse{}

	int64Value := func(header string, value string) int64 {
		if value != "" {
			r, err := strconv.ParseInt(value, 10, 64)
			if err != nil {
				log.Printf("Unable to coerce header %s to int64, value was %s", header, value)
				return 0
			}

			return r
		}

		return 0
	}

	boolValue := func(value string) bool {
		if strings.ToLower(value) == "true" {
			return true
		}

		return false
	}

	timeValue := func(header string, value string) *misc.RFC8601DateTime {
		if value == "" {
			return nil
		}

		t, err := misc.NewDateTimeFromString(value)

		if err != nil {
			log.Printf("Unable to coerce header %s to RFC8601DateTime, value was %s, err: %v", header, value, err)
		}

		return &t
	}

	// properties are different.
	for k, v := range headers {
		lowerK := strings.ToLower(k)
		val := v[0]

		switch lowerK {
		case "x-image-meta-checksum":
			result.CheckSum = val
		case "x-image-meta-container_format":
			result.ContainerFormat = val
		case "x-image-meta-created_at":
			result.CreatedAt = *timeValue(k, val)
		case "x-image-meta-deleted":
			result.Deleted = boolValue(val)
		case "x-image-meta-deleted_at":
			result.DeletedAt = timeValue(k, val)
		case "x-image-meta-disk_format":
			result.DiskFormat = val
		case "x-image-meta-id":
			result.ID = val
		case "x-image-meta-is_public":
			result.IsPublic = boolValue(val)
		case "x-image-meta-min_disk":
			result.MinDisk = int64Value(k, val)
		case "x-image-meta-min_ram":
			result.MinRAM = int64Value(k, val)
		case "x-image-meta-name":
			result.Name = val
		case "x-image-meta-owner":
			result.Owner = &val
		case "x-image-meta-protected":
			result.Protected = boolValue(val)
		case "x-image-meta-size":
			result.Size = int64Value(k, val)
		case "x-image-meta-status":
			result.Status = val
		case "x-image-meta-updated_at":
			result.UpdatedAt = *timeValue(k, val)
		case "x-image-meta-virtual_size":
			vSize := int64Value(k, val)
			result.VirtualSize = &vSize
		default:
			if strings.HasPrefix(lowerK, "x-image-meta-property-") {
				if result.Properties == nil {
					result.Properties = map[string]string{}
				}

				propertyName := strings.TrimPrefix(lowerK, "x-image-meta-property-")
				result.Properties[propertyName] = val
			}
		}
	}

	return result
}