github.com/dougm/docker@v1.5.0/registry/v2/routes_test.go (about) 1 package v2 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "net/http/httptest" 7 "reflect" 8 "testing" 9 10 "github.com/gorilla/mux" 11 ) 12 13 type routeTestCase struct { 14 RequestURI string 15 Vars map[string]string 16 RouteName string 17 StatusCode int 18 } 19 20 // TestRouter registers a test handler with all the routes and ensures that 21 // each route returns the expected path variables. Not method verification is 22 // present. This not meant to be exhaustive but as check to ensure that the 23 // expected variables are extracted. 24 // 25 // This may go away as the application structure comes together. 26 func TestRouter(t *testing.T) { 27 28 router := Router() 29 30 testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 31 testCase := routeTestCase{ 32 RequestURI: r.RequestURI, 33 Vars: mux.Vars(r), 34 RouteName: mux.CurrentRoute(r).GetName(), 35 } 36 37 enc := json.NewEncoder(w) 38 39 if err := enc.Encode(testCase); err != nil { 40 http.Error(w, err.Error(), http.StatusInternalServerError) 41 return 42 } 43 }) 44 45 // Startup test server 46 server := httptest.NewServer(router) 47 48 for _, testcase := range []routeTestCase{ 49 { 50 RouteName: RouteNameBase, 51 RequestURI: "/v2/", 52 Vars: map[string]string{}, 53 }, 54 { 55 RouteName: RouteNameManifest, 56 RequestURI: "/v2/foo/bar/manifests/tag", 57 Vars: map[string]string{ 58 "name": "foo/bar", 59 "tag": "tag", 60 }, 61 }, 62 { 63 RouteName: RouteNameTags, 64 RequestURI: "/v2/foo/bar/tags/list", 65 Vars: map[string]string{ 66 "name": "foo/bar", 67 }, 68 }, 69 { 70 RouteName: RouteNameBlob, 71 RequestURI: "/v2/foo/bar/blobs/tarsum.dev+foo:abcdef0919234", 72 Vars: map[string]string{ 73 "name": "foo/bar", 74 "digest": "tarsum.dev+foo:abcdef0919234", 75 }, 76 }, 77 { 78 RouteName: RouteNameBlob, 79 RequestURI: "/v2/foo/bar/blobs/sha256:abcdef0919234", 80 Vars: map[string]string{ 81 "name": "foo/bar", 82 "digest": "sha256:abcdef0919234", 83 }, 84 }, 85 { 86 RouteName: RouteNameBlobUpload, 87 RequestURI: "/v2/foo/bar/blobs/uploads/", 88 Vars: map[string]string{ 89 "name": "foo/bar", 90 }, 91 }, 92 { 93 RouteName: RouteNameBlobUploadChunk, 94 RequestURI: "/v2/foo/bar/blobs/uploads/uuid", 95 Vars: map[string]string{ 96 "name": "foo/bar", 97 "uuid": "uuid", 98 }, 99 }, 100 { 101 RouteName: RouteNameBlobUploadChunk, 102 RequestURI: "/v2/foo/bar/blobs/uploads/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", 103 Vars: map[string]string{ 104 "name": "foo/bar", 105 "uuid": "D95306FA-FAD3-4E36-8D41-CF1C93EF8286", 106 }, 107 }, 108 { 109 RouteName: RouteNameBlobUploadChunk, 110 RequestURI: "/v2/foo/bar/blobs/uploads/RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==", 111 Vars: map[string]string{ 112 "name": "foo/bar", 113 "uuid": "RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==", 114 }, 115 }, 116 { 117 // Check ambiguity: ensure we can distinguish between tags for 118 // "foo/bar/image/image" and image for "foo/bar/image" with tag 119 // "tags" 120 RouteName: RouteNameManifest, 121 RequestURI: "/v2/foo/bar/manifests/manifests/tags", 122 Vars: map[string]string{ 123 "name": "foo/bar/manifests", 124 "tag": "tags", 125 }, 126 }, 127 { 128 // This case presents an ambiguity between foo/bar with tag="tags" 129 // and list tags for "foo/bar/manifest" 130 RouteName: RouteNameTags, 131 RequestURI: "/v2/foo/bar/manifests/tags/list", 132 Vars: map[string]string{ 133 "name": "foo/bar/manifests", 134 }, 135 }, 136 { 137 RouteName: RouteNameBlobUploadChunk, 138 RequestURI: "/v2/foo/../../blob/uploads/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", 139 StatusCode: http.StatusNotFound, 140 }, 141 } { 142 // Register the endpoint 143 router.GetRoute(testcase.RouteName).Handler(testHandler) 144 u := server.URL + testcase.RequestURI 145 146 resp, err := http.Get(u) 147 148 if err != nil { 149 t.Fatalf("error issuing get request: %v", err) 150 } 151 152 if testcase.StatusCode == 0 { 153 // Override default, zero-value 154 testcase.StatusCode = http.StatusOK 155 } 156 157 if resp.StatusCode != testcase.StatusCode { 158 t.Fatalf("unexpected status for %s: %v %v", u, resp.Status, resp.StatusCode) 159 } 160 161 if testcase.StatusCode != http.StatusOK { 162 // We don't care about json response. 163 continue 164 } 165 166 dec := json.NewDecoder(resp.Body) 167 168 var actualRouteInfo routeTestCase 169 if err := dec.Decode(&actualRouteInfo); err != nil { 170 t.Fatalf("error reading json response: %v", err) 171 } 172 // Needs to be set out of band 173 actualRouteInfo.StatusCode = resp.StatusCode 174 175 if actualRouteInfo.RouteName != testcase.RouteName { 176 t.Fatalf("incorrect route %q matched, expected %q", actualRouteInfo.RouteName, testcase.RouteName) 177 } 178 179 if !reflect.DeepEqual(actualRouteInfo, testcase) { 180 t.Fatalf("actual does not equal expected: %#v != %#v", actualRouteInfo, testcase) 181 } 182 } 183 184 }