func handlerPutImage(w http.ResponseWriter, r *http.Request) {
	if !requiresAuth(w, r) {
		return
	}
	vars := mux.Vars(r)
	imageID := vars["image_id"]
	action := vars["action"]
	layer, exists := testLayers[imageID]
	if !exists {
		if action != "json" {
			http.NotFound(w, r)
			return
		}
		layer = make(map[string]string)
		testLayers[imageID] = layer
	}
	if checksum := r.Header.Get("X-Docker-Checksum"); checksum != "" {
		if checksum != layer["checksum_simple"] && checksum != layer["checksum_tarsum"] {
			apiError(w, "Wrong checksum", 400)
			return
		}
	}
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		apiError(w, fmt.Sprintf("Error: %s", err), 500)
		return
	}
	layer[action] = string(body)
	writeResponse(w, true, 200)
}
func handlerGetImage(w http.ResponseWriter, r *http.Request) {
	if !requiresAuth(w, r) {
		return
	}
	vars := mux.Vars(r)
	layer, exists := testLayers[vars["image_id"]]
	if !exists {
		http.NotFound(w, r)
		return
	}
	writeHeaders(w)
	layerSize := len(layer["layer"])
	w.Header().Add("X-Docker-Size", strconv.Itoa(layerSize))
	io.WriteString(w, layer[vars["action"]])
}
func handlerPutTag(w http.ResponseWriter, r *http.Request) {
	if !requiresAuth(w, r) {
		return
	}
	vars := mux.Vars(r)
	repositoryName := vars["repository"]
	repositoryName = NormalizeLocalName(repositoryName)
	tagName := vars["tag"]
	tags, exists := testRepositories[repositoryName]
	if !exists {
		tags := make(map[string]string)
		testRepositories[repositoryName] = tags
	}
	tagValue := ""
	readJSON(r, tagValue)
	tags[tagName] = tagValue
	writeResponse(w, true, 200)
}
func handlerGetDeleteTags(w http.ResponseWriter, r *http.Request) {
	if !requiresAuth(w, r) {
		return
	}
	repositoryName := mux.Vars(r)["repository"]
	repositoryName = NormalizeLocalName(repositoryName)
	tags, exists := testRepositories[repositoryName]
	if !exists {
		apiError(w, "Repository not found", 404)
		return
	}
	if r.Method == "DELETE" {
		delete(testRepositories, repositoryName)
		writeResponse(w, true, 200)
		return
	}
	writeResponse(w, tags, 200)
}
func handlerGetTag(w http.ResponseWriter, r *http.Request) {
	if !requiresAuth(w, r) {
		return
	}
	vars := mux.Vars(r)
	repositoryName := vars["repository"]
	repositoryName = NormalizeLocalName(repositoryName)
	tagName := vars["tag"]
	tags, exists := testRepositories[repositoryName]
	if !exists {
		apiError(w, "Repository not found", 404)
		return
	}
	tag, exists := tags[tagName]
	if !exists {
		apiError(w, "Tag not found", 404)
		return
	}
	writeResponse(w, tag, 200)
}
func checkTestRouter(t *testing.T, testCases []routeTestCase, prefix string, deeplyEqual bool) {
	router := RouterWithPrefix(prefix)

	testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		testCase := routeTestCase{
			RequestURI: r.RequestURI,
			Vars:       mux.Vars(r),
			RouteName:  mux.CurrentRoute(r).GetName(),
		}

		enc := json.NewEncoder(w)

		if err := enc.Encode(testCase); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})

	// Startup test server
	server := httptest.NewServer(router)

	for _, testcase := range testCases {
		testcase.RequestURI = strings.TrimSuffix(prefix, "/") + testcase.RequestURI
		// Register the endpoint
		route := router.GetRoute(testcase.RouteName)
		if route == nil {
			t.Fatalf("route for name %q not found", testcase.RouteName)
		}

		route.Handler(testHandler)

		u := server.URL + testcase.RequestURI

		resp, err := http.Get(u)

		if err != nil {
			t.Fatalf("error issuing get request: %v", err)
		}

		if testcase.StatusCode == 0 {
			// Override default, zero-value
			testcase.StatusCode = http.StatusOK
		}
		if testcase.ExpectedURI == "" {
			// Override default, zero-value
			testcase.ExpectedURI = testcase.RequestURI
		}

		if resp.StatusCode != testcase.StatusCode {
			t.Fatalf("unexpected status for %s: %v %v", u, resp.Status, resp.StatusCode)
		}

		if testcase.StatusCode != http.StatusOK {
			resp.Body.Close()
			// We don't care about json response.
			continue
		}

		dec := json.NewDecoder(resp.Body)

		var actualRouteInfo routeTestCase
		if err := dec.Decode(&actualRouteInfo); err != nil {
			t.Fatalf("error reading json response: %v", err)
		}
		// Needs to be set out of band
		actualRouteInfo.StatusCode = resp.StatusCode

		if actualRouteInfo.RequestURI != testcase.ExpectedURI {
			t.Fatalf("URI %v incorrectly parsed, expected %v", actualRouteInfo.RequestURI, testcase.ExpectedURI)
		}

		if actualRouteInfo.RouteName != testcase.RouteName {
			t.Fatalf("incorrect route %q matched, expected %q", actualRouteInfo.RouteName, testcase.RouteName)
		}

		// when testing deep equality, the actualRouteInfo has an empty ExpectedURI, we don't want
		// that to make the comparison fail. We're otherwise done with the testcase so empty the
		// testcase.ExpectedURI
		testcase.ExpectedURI = ""
		if deeplyEqual && !reflect.DeepEqual(actualRouteInfo, testcase) {
			t.Fatalf("actual does not equal expected: %#v != %#v", actualRouteInfo, testcase)
		}

		resp.Body.Close()
	}

}