github.com/nalind/docker@v1.5.0/registry/registry_test.go (about)

     1  package registry
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/docker/docker/utils"
    11  )
    12  
    13  var (
    14  	token = []string{"fake-token"}
    15  )
    16  
    17  const (
    18  	imageID = "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d"
    19  	REPO    = "foo42/bar"
    20  )
    21  
    22  func spawnTestRegistrySession(t *testing.T) *Session {
    23  	authConfig := &AuthConfig{}
    24  	endpoint, err := NewEndpoint(makeIndex("/v1/"))
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	r, err := NewSession(authConfig, utils.NewHTTPRequestFactory(), endpoint, true)
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  	return r
    33  }
    34  
    35  func TestPublicSession(t *testing.T) {
    36  	authConfig := &AuthConfig{}
    37  
    38  	getSessionDecorators := func(index *IndexInfo) int {
    39  		endpoint, err := NewEndpoint(index)
    40  		if err != nil {
    41  			t.Fatal(err)
    42  		}
    43  		r, err := NewSession(authConfig, utils.NewHTTPRequestFactory(), endpoint, true)
    44  		if err != nil {
    45  			t.Fatal(err)
    46  		}
    47  		return len(r.reqFactory.GetDecorators())
    48  	}
    49  
    50  	decorators := getSessionDecorators(makeIndex("/v1/"))
    51  	assertEqual(t, decorators, 0, "Expected no decorator on http session")
    52  
    53  	decorators = getSessionDecorators(makeHttpsIndex("/v1/"))
    54  	assertNotEqual(t, decorators, 0, "Expected decorator on https session")
    55  
    56  	decorators = getSessionDecorators(makePublicIndex())
    57  	assertEqual(t, decorators, 0, "Expected no decorator on public session")
    58  }
    59  
    60  func TestPingRegistryEndpoint(t *testing.T) {
    61  	testPing := func(index *IndexInfo, expectedStandalone bool, assertMessage string) {
    62  		ep, err := NewEndpoint(index)
    63  		if err != nil {
    64  			t.Fatal(err)
    65  		}
    66  		regInfo, err := ep.Ping()
    67  		if err != nil {
    68  			t.Fatal(err)
    69  		}
    70  
    71  		assertEqual(t, regInfo.Standalone, expectedStandalone, assertMessage)
    72  	}
    73  
    74  	testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)")
    75  	testPing(makeHttpsIndex("/v1/"), true, "Expected standalone to be true (default)")
    76  	testPing(makePublicIndex(), false, "Expected standalone to be false for public index")
    77  }
    78  
    79  func TestEndpoint(t *testing.T) {
    80  	// Simple wrapper to fail test if err != nil
    81  	expandEndpoint := func(index *IndexInfo) *Endpoint {
    82  		endpoint, err := NewEndpoint(index)
    83  		if err != nil {
    84  			t.Fatal(err)
    85  		}
    86  		return endpoint
    87  	}
    88  
    89  	assertInsecureIndex := func(index *IndexInfo) {
    90  		index.Secure = true
    91  		_, err := NewEndpoint(index)
    92  		assertNotEqual(t, err, nil, index.Name+": Expected error for insecure index")
    93  		assertEqual(t, strings.Contains(err.Error(), "insecure-registry"), true, index.Name+": Expected insecure-registry  error for insecure index")
    94  		index.Secure = false
    95  	}
    96  
    97  	assertSecureIndex := func(index *IndexInfo) {
    98  		index.Secure = true
    99  		_, err := NewEndpoint(index)
   100  		assertNotEqual(t, err, nil, index.Name+": Expected cert error for secure index")
   101  		assertEqual(t, strings.Contains(err.Error(), "certificate signed by unknown authority"), true, index.Name+": Expected cert error for secure index")
   102  		index.Secure = false
   103  	}
   104  
   105  	index := &IndexInfo{}
   106  	index.Name = makeURL("/v1/")
   107  	endpoint := expandEndpoint(index)
   108  	assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name)
   109  	if endpoint.Version != APIVersion1 {
   110  		t.Fatal("Expected endpoint to be v1")
   111  	}
   112  	assertInsecureIndex(index)
   113  
   114  	index.Name = makeURL("")
   115  	endpoint = expandEndpoint(index)
   116  	assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/")
   117  	if endpoint.Version != APIVersion1 {
   118  		t.Fatal("Expected endpoint to be v1")
   119  	}
   120  	assertInsecureIndex(index)
   121  
   122  	httpURL := makeURL("")
   123  	index.Name = strings.SplitN(httpURL, "://", 2)[1]
   124  	endpoint = expandEndpoint(index)
   125  	assertEqual(t, endpoint.String(), httpURL+"/v1/", index.Name+": Expected endpoint to be "+httpURL+"/v1/")
   126  	if endpoint.Version != APIVersion1 {
   127  		t.Fatal("Expected endpoint to be v1")
   128  	}
   129  	assertInsecureIndex(index)
   130  
   131  	index.Name = makeHttpsURL("/v1/")
   132  	endpoint = expandEndpoint(index)
   133  	assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name)
   134  	if endpoint.Version != APIVersion1 {
   135  		t.Fatal("Expected endpoint to be v1")
   136  	}
   137  	assertSecureIndex(index)
   138  
   139  	index.Name = makeHttpsURL("")
   140  	endpoint = expandEndpoint(index)
   141  	assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/")
   142  	if endpoint.Version != APIVersion1 {
   143  		t.Fatal("Expected endpoint to be v1")
   144  	}
   145  	assertSecureIndex(index)
   146  
   147  	httpsURL := makeHttpsURL("")
   148  	index.Name = strings.SplitN(httpsURL, "://", 2)[1]
   149  	endpoint = expandEndpoint(index)
   150  	assertEqual(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/")
   151  	if endpoint.Version != APIVersion1 {
   152  		t.Fatal("Expected endpoint to be v1")
   153  	}
   154  	assertSecureIndex(index)
   155  
   156  	badEndpoints := []string{
   157  		"http://127.0.0.1/v1/",
   158  		"https://127.0.0.1/v1/",
   159  		"http://127.0.0.1",
   160  		"https://127.0.0.1",
   161  		"127.0.0.1",
   162  	}
   163  	for _, address := range badEndpoints {
   164  		index.Name = address
   165  		_, err := NewEndpoint(index)
   166  		checkNotEqual(t, err, nil, "Expected error while expanding bad endpoint")
   167  	}
   168  }
   169  
   170  func TestGetRemoteHistory(t *testing.T) {
   171  	r := spawnTestRegistrySession(t)
   172  	hist, err := r.GetRemoteHistory(imageID, makeURL("/v1/"), token)
   173  	if err != nil {
   174  		t.Fatal(err)
   175  	}
   176  	assertEqual(t, len(hist), 2, "Expected 2 images in history")
   177  	assertEqual(t, hist[0], imageID, "Expected "+imageID+"as first ancestry")
   178  	assertEqual(t, hist[1], "77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20",
   179  		"Unexpected second ancestry")
   180  }
   181  
   182  func TestLookupRemoteImage(t *testing.T) {
   183  	r := spawnTestRegistrySession(t)
   184  	err := r.LookupRemoteImage(imageID, makeURL("/v1/"), token)
   185  	assertEqual(t, err, nil, "Expected error of remote lookup to nil")
   186  	if err := r.LookupRemoteImage("abcdef", makeURL("/v1/"), token); err == nil {
   187  		t.Fatal("Expected error of remote lookup to not nil")
   188  	}
   189  }
   190  
   191  func TestGetRemoteImageJSON(t *testing.T) {
   192  	r := spawnTestRegistrySession(t)
   193  	json, size, err := r.GetRemoteImageJSON(imageID, makeURL("/v1/"), token)
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  	assertEqual(t, size, 154, "Expected size 154")
   198  	if len(json) <= 0 {
   199  		t.Fatal("Expected non-empty json")
   200  	}
   201  
   202  	_, _, err = r.GetRemoteImageJSON("abcdef", makeURL("/v1/"), token)
   203  	if err == nil {
   204  		t.Fatal("Expected image not found error")
   205  	}
   206  }
   207  
   208  func TestGetRemoteImageLayer(t *testing.T) {
   209  	r := spawnTestRegistrySession(t)
   210  	data, err := r.GetRemoteImageLayer(imageID, makeURL("/v1/"), token, 0)
   211  	if err != nil {
   212  		t.Fatal(err)
   213  	}
   214  	if data == nil {
   215  		t.Fatal("Expected non-nil data result")
   216  	}
   217  
   218  	_, err = r.GetRemoteImageLayer("abcdef", makeURL("/v1/"), token, 0)
   219  	if err == nil {
   220  		t.Fatal("Expected image not found error")
   221  	}
   222  }
   223  
   224  func TestGetRemoteTags(t *testing.T) {
   225  	r := spawnTestRegistrySession(t)
   226  	tags, err := r.GetRemoteTags([]string{makeURL("/v1/")}, REPO, token)
   227  	if err != nil {
   228  		t.Fatal(err)
   229  	}
   230  	assertEqual(t, len(tags), 1, "Expected one tag")
   231  	assertEqual(t, tags["latest"], imageID, "Expected tag latest to map to "+imageID)
   232  
   233  	_, err = r.GetRemoteTags([]string{makeURL("/v1/")}, "foo42/baz", token)
   234  	if err == nil {
   235  		t.Fatal("Expected error when fetching tags for bogus repo")
   236  	}
   237  }
   238  
   239  func TestGetRepositoryData(t *testing.T) {
   240  	r := spawnTestRegistrySession(t)
   241  	parsedURL, err := url.Parse(makeURL("/v1/"))
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	host := "http://" + parsedURL.Host + "/v1/"
   246  	data, err := r.GetRepositoryData("foo42/bar")
   247  	if err != nil {
   248  		t.Fatal(err)
   249  	}
   250  	assertEqual(t, len(data.ImgList), 2, "Expected 2 images in ImgList")
   251  	assertEqual(t, len(data.Endpoints), 2,
   252  		fmt.Sprintf("Expected 2 endpoints in Endpoints, found %d instead", len(data.Endpoints)))
   253  	assertEqual(t, data.Endpoints[0], host,
   254  		fmt.Sprintf("Expected first endpoint to be %s but found %s instead", host, data.Endpoints[0]))
   255  	assertEqual(t, data.Endpoints[1], "http://test.example.com/v1/",
   256  		fmt.Sprintf("Expected first endpoint to be http://test.example.com/v1/ but found %s instead", data.Endpoints[1]))
   257  
   258  }
   259  
   260  func TestPushImageJSONRegistry(t *testing.T) {
   261  	r := spawnTestRegistrySession(t)
   262  	imgData := &ImgData{
   263  		ID:       "77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20",
   264  		Checksum: "sha256:1ac330d56e05eef6d438586545ceff7550d3bdcb6b19961f12c5ba714ee1bb37",
   265  	}
   266  
   267  	err := r.PushImageJSONRegistry(imgData, []byte{0x42, 0xdf, 0x0}, makeURL("/v1/"), token)
   268  	if err != nil {
   269  		t.Fatal(err)
   270  	}
   271  }
   272  
   273  func TestPushImageLayerRegistry(t *testing.T) {
   274  	r := spawnTestRegistrySession(t)
   275  	layer := strings.NewReader("")
   276  	_, _, err := r.PushImageLayerRegistry(imageID, layer, makeURL("/v1/"), token, []byte{})
   277  	if err != nil {
   278  		t.Fatal(err)
   279  	}
   280  }
   281  
   282  func TestValidateRepositoryName(t *testing.T) {
   283  	validRepoNames := []string{
   284  		"docker/docker",
   285  		"library/debian",
   286  		"debian",
   287  		"docker.io/docker/docker",
   288  		"docker.io/library/debian",
   289  		"docker.io/debian",
   290  		"index.docker.io/docker/docker",
   291  		"index.docker.io/library/debian",
   292  		"index.docker.io/debian",
   293  		"127.0.0.1:5000/docker/docker",
   294  		"127.0.0.1:5000/library/debian",
   295  		"127.0.0.1:5000/debian",
   296  		"thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
   297  	}
   298  	invalidRepoNames := []string{
   299  		"https://github.com/docker/docker",
   300  		"docker/Docker",
   301  		"docker///docker",
   302  		"docker.io/docker/Docker",
   303  		"docker.io/docker///docker",
   304  		"1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
   305  		"docker.io/1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
   306  	}
   307  
   308  	for _, name := range invalidRepoNames {
   309  		err := ValidateRepositoryName(name)
   310  		assertNotEqual(t, err, nil, "Expected invalid repo name: "+name)
   311  	}
   312  
   313  	for _, name := range validRepoNames {
   314  		err := ValidateRepositoryName(name)
   315  		assertEqual(t, err, nil, "Expected valid repo name: "+name)
   316  	}
   317  
   318  	err := ValidateRepositoryName(invalidRepoNames[0])
   319  	assertEqual(t, err, ErrInvalidRepositoryName, "Expected ErrInvalidRepositoryName: "+invalidRepoNames[0])
   320  }
   321  
   322  func TestParseRepositoryInfo(t *testing.T) {
   323  	expectedRepoInfos := map[string]RepositoryInfo{
   324  		"fooo/bar": {
   325  			Index: &IndexInfo{
   326  				Name:     IndexServerName(),
   327  				Official: true,
   328  			},
   329  			RemoteName:    "fooo/bar",
   330  			LocalName:     "fooo/bar",
   331  			CanonicalName: "fooo/bar",
   332  			Official:      false,
   333  		},
   334  		"library/ubuntu": {
   335  			Index: &IndexInfo{
   336  				Name:     IndexServerName(),
   337  				Official: true,
   338  			},
   339  			RemoteName:    "library/ubuntu",
   340  			LocalName:     "ubuntu",
   341  			CanonicalName: "ubuntu",
   342  			Official:      true,
   343  		},
   344  		"nonlibrary/ubuntu": {
   345  			Index: &IndexInfo{
   346  				Name:     IndexServerName(),
   347  				Official: true,
   348  			},
   349  			RemoteName:    "nonlibrary/ubuntu",
   350  			LocalName:     "nonlibrary/ubuntu",
   351  			CanonicalName: "nonlibrary/ubuntu",
   352  			Official:      false,
   353  		},
   354  		"ubuntu": {
   355  			Index: &IndexInfo{
   356  				Name:     IndexServerName(),
   357  				Official: true,
   358  			},
   359  			RemoteName:    "library/ubuntu",
   360  			LocalName:     "ubuntu",
   361  			CanonicalName: "ubuntu",
   362  			Official:      true,
   363  		},
   364  		"other/library": {
   365  			Index: &IndexInfo{
   366  				Name:     IndexServerName(),
   367  				Official: true,
   368  			},
   369  			RemoteName:    "other/library",
   370  			LocalName:     "other/library",
   371  			CanonicalName: "other/library",
   372  			Official:      false,
   373  		},
   374  		"127.0.0.1:8000/private/moonbase": {
   375  			Index: &IndexInfo{
   376  				Name:     "127.0.0.1:8000",
   377  				Official: false,
   378  			},
   379  			RemoteName:    "private/moonbase",
   380  			LocalName:     "127.0.0.1:8000/private/moonbase",
   381  			CanonicalName: "127.0.0.1:8000/private/moonbase",
   382  			Official:      false,
   383  		},
   384  		"127.0.0.1:8000/privatebase": {
   385  			Index: &IndexInfo{
   386  				Name:     "127.0.0.1:8000",
   387  				Official: false,
   388  			},
   389  			RemoteName:    "privatebase",
   390  			LocalName:     "127.0.0.1:8000/privatebase",
   391  			CanonicalName: "127.0.0.1:8000/privatebase",
   392  			Official:      false,
   393  		},
   394  		"localhost:8000/private/moonbase": {
   395  			Index: &IndexInfo{
   396  				Name:     "localhost:8000",
   397  				Official: false,
   398  			},
   399  			RemoteName:    "private/moonbase",
   400  			LocalName:     "localhost:8000/private/moonbase",
   401  			CanonicalName: "localhost:8000/private/moonbase",
   402  			Official:      false,
   403  		},
   404  		"localhost:8000/privatebase": {
   405  			Index: &IndexInfo{
   406  				Name:     "localhost:8000",
   407  				Official: false,
   408  			},
   409  			RemoteName:    "privatebase",
   410  			LocalName:     "localhost:8000/privatebase",
   411  			CanonicalName: "localhost:8000/privatebase",
   412  			Official:      false,
   413  		},
   414  		"example.com/private/moonbase": {
   415  			Index: &IndexInfo{
   416  				Name:     "example.com",
   417  				Official: false,
   418  			},
   419  			RemoteName:    "private/moonbase",
   420  			LocalName:     "example.com/private/moonbase",
   421  			CanonicalName: "example.com/private/moonbase",
   422  			Official:      false,
   423  		},
   424  		"example.com/privatebase": {
   425  			Index: &IndexInfo{
   426  				Name:     "example.com",
   427  				Official: false,
   428  			},
   429  			RemoteName:    "privatebase",
   430  			LocalName:     "example.com/privatebase",
   431  			CanonicalName: "example.com/privatebase",
   432  			Official:      false,
   433  		},
   434  		"example.com:8000/private/moonbase": {
   435  			Index: &IndexInfo{
   436  				Name:     "example.com:8000",
   437  				Official: false,
   438  			},
   439  			RemoteName:    "private/moonbase",
   440  			LocalName:     "example.com:8000/private/moonbase",
   441  			CanonicalName: "example.com:8000/private/moonbase",
   442  			Official:      false,
   443  		},
   444  		"example.com:8000/privatebase": {
   445  			Index: &IndexInfo{
   446  				Name:     "example.com:8000",
   447  				Official: false,
   448  			},
   449  			RemoteName:    "privatebase",
   450  			LocalName:     "example.com:8000/privatebase",
   451  			CanonicalName: "example.com:8000/privatebase",
   452  			Official:      false,
   453  		},
   454  		"localhost/private/moonbase": {
   455  			Index: &IndexInfo{
   456  				Name:     "localhost",
   457  				Official: false,
   458  			},
   459  			RemoteName:    "private/moonbase",
   460  			LocalName:     "localhost/private/moonbase",
   461  			CanonicalName: "localhost/private/moonbase",
   462  			Official:      false,
   463  		},
   464  		"localhost/privatebase": {
   465  			Index: &IndexInfo{
   466  				Name:     "localhost",
   467  				Official: false,
   468  			},
   469  			RemoteName:    "privatebase",
   470  			LocalName:     "localhost/privatebase",
   471  			CanonicalName: "localhost/privatebase",
   472  			Official:      false,
   473  		},
   474  		IndexServerName() + "/public/moonbase": {
   475  			Index: &IndexInfo{
   476  				Name:     IndexServerName(),
   477  				Official: true,
   478  			},
   479  			RemoteName:    "public/moonbase",
   480  			LocalName:     "public/moonbase",
   481  			CanonicalName: "public/moonbase",
   482  			Official:      false,
   483  		},
   484  		"index." + IndexServerName() + "/public/moonbase": {
   485  			Index: &IndexInfo{
   486  				Name:     IndexServerName(),
   487  				Official: true,
   488  			},
   489  			RemoteName:    "public/moonbase",
   490  			LocalName:     "public/moonbase",
   491  			CanonicalName: "public/moonbase",
   492  			Official:      false,
   493  		},
   494  		IndexServerName() + "/public/moonbase": {
   495  			Index: &IndexInfo{
   496  				Name:     IndexServerName(),
   497  				Official: true,
   498  			},
   499  			RemoteName:    "public/moonbase",
   500  			LocalName:     "public/moonbase",
   501  			CanonicalName: "public/moonbase",
   502  			Official:      false,
   503  		},
   504  		"ubuntu-12.04-base": {
   505  			Index: &IndexInfo{
   506  				Name:     IndexServerName(),
   507  				Official: true,
   508  			},
   509  			RemoteName:    "library/ubuntu-12.04-base",
   510  			LocalName:     "ubuntu-12.04-base",
   511  			CanonicalName: "ubuntu-12.04-base",
   512  			Official:      true,
   513  		},
   514  		IndexServerName() + "/ubuntu-12.04-base": {
   515  			Index: &IndexInfo{
   516  				Name:     IndexServerName(),
   517  				Official: true,
   518  			},
   519  			RemoteName:    "library/ubuntu-12.04-base",
   520  			LocalName:     "ubuntu-12.04-base",
   521  			CanonicalName: "ubuntu-12.04-base",
   522  			Official:      true,
   523  		},
   524  		IndexServerName() + "/ubuntu-12.04-base": {
   525  			Index: &IndexInfo{
   526  				Name:     IndexServerName(),
   527  				Official: true,
   528  			},
   529  			RemoteName:    "library/ubuntu-12.04-base",
   530  			LocalName:     "ubuntu-12.04-base",
   531  			CanonicalName: "ubuntu-12.04-base",
   532  			Official:      true,
   533  		},
   534  		"index." + IndexServerName() + "/ubuntu-12.04-base": {
   535  			Index: &IndexInfo{
   536  				Name:     IndexServerName(),
   537  				Official: true,
   538  			},
   539  			RemoteName:    "library/ubuntu-12.04-base",
   540  			LocalName:     "ubuntu-12.04-base",
   541  			CanonicalName: "ubuntu-12.04-base",
   542  			Official:      true,
   543  		},
   544  	}
   545  
   546  	for reposName, expectedRepoInfo := range expectedRepoInfos {
   547  		repoInfo, err := ParseRepositoryInfo(reposName)
   548  		if err != nil {
   549  			t.Error(err)
   550  		} else {
   551  			checkEqual(t, repoInfo.Index.Name, expectedRepoInfo.Index.Name, reposName)
   552  			checkEqual(t, repoInfo.RemoteName, expectedRepoInfo.RemoteName, reposName)
   553  			checkEqual(t, repoInfo.LocalName, expectedRepoInfo.LocalName, reposName)
   554  			checkEqual(t, repoInfo.CanonicalName, expectedRepoInfo.CanonicalName, reposName)
   555  			checkEqual(t, repoInfo.Index.Official, expectedRepoInfo.Index.Official, reposName)
   556  			checkEqual(t, repoInfo.Official, expectedRepoInfo.Official, reposName)
   557  		}
   558  	}
   559  }
   560  
   561  func TestNewIndexInfo(t *testing.T) {
   562  	testIndexInfo := func(config *ServiceConfig, expectedIndexInfos map[string]*IndexInfo) {
   563  		for indexName, expectedIndexInfo := range expectedIndexInfos {
   564  			index, err := config.NewIndexInfo(indexName)
   565  			if err != nil {
   566  				t.Fatal(err)
   567  			} else {
   568  				checkEqual(t, index.Name, expectedIndexInfo.Name, indexName+" name")
   569  				checkEqual(t, index.Official, expectedIndexInfo.Official, indexName+" is official")
   570  				checkEqual(t, index.Secure, expectedIndexInfo.Secure, indexName+" is secure")
   571  				checkEqual(t, len(index.Mirrors), len(expectedIndexInfo.Mirrors), indexName+" mirrors")
   572  			}
   573  		}
   574  	}
   575  
   576  	config := NewServiceConfig(nil)
   577  	noMirrors := make([]string, 0)
   578  	expectedIndexInfos := map[string]*IndexInfo{
   579  		IndexServerName(): {
   580  			Name:     IndexServerName(),
   581  			Official: true,
   582  			Secure:   true,
   583  			Mirrors:  noMirrors,
   584  		},
   585  		"index." + IndexServerName(): {
   586  			Name:     IndexServerName(),
   587  			Official: true,
   588  			Secure:   true,
   589  			Mirrors:  noMirrors,
   590  		},
   591  		"example.com": {
   592  			Name:     "example.com",
   593  			Official: false,
   594  			Secure:   true,
   595  			Mirrors:  noMirrors,
   596  		},
   597  		"127.0.0.1:5000": {
   598  			Name:     "127.0.0.1:5000",
   599  			Official: false,
   600  			Secure:   false,
   601  			Mirrors:  noMirrors,
   602  		},
   603  	}
   604  	testIndexInfo(config, expectedIndexInfos)
   605  
   606  	publicMirrors := []string{"http://mirror1.local", "http://mirror2.local"}
   607  	config = makeServiceConfig(publicMirrors, []string{"example.com"})
   608  
   609  	expectedIndexInfos = map[string]*IndexInfo{
   610  		IndexServerName(): {
   611  			Name:     IndexServerName(),
   612  			Official: true,
   613  			Secure:   true,
   614  			Mirrors:  publicMirrors,
   615  		},
   616  		"index." + IndexServerName(): {
   617  			Name:     IndexServerName(),
   618  			Official: true,
   619  			Secure:   true,
   620  			Mirrors:  publicMirrors,
   621  		},
   622  		"example.com": {
   623  			Name:     "example.com",
   624  			Official: false,
   625  			Secure:   false,
   626  			Mirrors:  noMirrors,
   627  		},
   628  		"example.com:5000": {
   629  			Name:     "example.com:5000",
   630  			Official: false,
   631  			Secure:   true,
   632  			Mirrors:  noMirrors,
   633  		},
   634  		"127.0.0.1": {
   635  			Name:     "127.0.0.1",
   636  			Official: false,
   637  			Secure:   false,
   638  			Mirrors:  noMirrors,
   639  		},
   640  		"127.0.0.1:5000": {
   641  			Name:     "127.0.0.1:5000",
   642  			Official: false,
   643  			Secure:   false,
   644  			Mirrors:  noMirrors,
   645  		},
   646  		"other.com": {
   647  			Name:     "other.com",
   648  			Official: false,
   649  			Secure:   true,
   650  			Mirrors:  noMirrors,
   651  		},
   652  	}
   653  	testIndexInfo(config, expectedIndexInfos)
   654  
   655  	config = makeServiceConfig(nil, []string{"42.42.0.0/16"})
   656  	expectedIndexInfos = map[string]*IndexInfo{
   657  		"example.com": {
   658  			Name:     "example.com",
   659  			Official: false,
   660  			Secure:   false,
   661  			Mirrors:  noMirrors,
   662  		},
   663  		"example.com:5000": {
   664  			Name:     "example.com:5000",
   665  			Official: false,
   666  			Secure:   false,
   667  			Mirrors:  noMirrors,
   668  		},
   669  		"127.0.0.1": {
   670  			Name:     "127.0.0.1",
   671  			Official: false,
   672  			Secure:   false,
   673  			Mirrors:  noMirrors,
   674  		},
   675  		"127.0.0.1:5000": {
   676  			Name:     "127.0.0.1:5000",
   677  			Official: false,
   678  			Secure:   false,
   679  			Mirrors:  noMirrors,
   680  		},
   681  		"other.com": {
   682  			Name:     "other.com",
   683  			Official: false,
   684  			Secure:   true,
   685  			Mirrors:  noMirrors,
   686  		},
   687  	}
   688  	testIndexInfo(config, expectedIndexInfos)
   689  }
   690  
   691  func TestPushRegistryTag(t *testing.T) {
   692  	r := spawnTestRegistrySession(t)
   693  	err := r.PushRegistryTag("foo42/bar", imageID, "stable", makeURL("/v1/"), token)
   694  	if err != nil {
   695  		t.Fatal(err)
   696  	}
   697  }
   698  
   699  func TestPushImageJSONIndex(t *testing.T) {
   700  	r := spawnTestRegistrySession(t)
   701  	imgData := []*ImgData{
   702  		{
   703  			ID:       "77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20",
   704  			Checksum: "sha256:1ac330d56e05eef6d438586545ceff7550d3bdcb6b19961f12c5ba714ee1bb37",
   705  		},
   706  		{
   707  			ID:       "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d",
   708  			Checksum: "sha256:bea7bf2e4bacd479344b737328db47b18880d09096e6674165533aa994f5e9f2",
   709  		},
   710  	}
   711  	repoData, err := r.PushImageJSONIndex("foo42/bar", imgData, false, nil)
   712  	if err != nil {
   713  		t.Fatal(err)
   714  	}
   715  	if repoData == nil {
   716  		t.Fatal("Expected RepositoryData object")
   717  	}
   718  	repoData, err = r.PushImageJSONIndex("foo42/bar", imgData, true, []string{r.indexEndpoint.String()})
   719  	if err != nil {
   720  		t.Fatal(err)
   721  	}
   722  	if repoData == nil {
   723  		t.Fatal("Expected RepositoryData object")
   724  	}
   725  }
   726  
   727  func TestSearchRepositories(t *testing.T) {
   728  	r := spawnTestRegistrySession(t)
   729  	results, err := r.SearchRepositories("fakequery")
   730  	if err != nil {
   731  		t.Fatal(err)
   732  	}
   733  	if results == nil {
   734  		t.Fatal("Expected non-nil SearchResults object")
   735  	}
   736  	assertEqual(t, results.NumResults, 1, "Expected 1 search results")
   737  	assertEqual(t, results.Query, "fakequery", "Expected 'fakequery' as query")
   738  	assertEqual(t, results.Results[0].StarCount, 42, "Expected 'fakeimage' a ot hae 42 stars")
   739  }
   740  
   741  func TestValidRemoteName(t *testing.T) {
   742  	validRepositoryNames := []string{
   743  		// Sanity check.
   744  		"docker/docker",
   745  
   746  		// Allow 64-character non-hexadecimal names (hexadecimal names are forbidden).
   747  		"thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
   748  
   749  		// Allow embedded hyphens.
   750  		"docker-rules/docker",
   751  
   752  		// Allow underscores everywhere (as opposed to hyphens).
   753  		"____/____",
   754  	}
   755  	for _, repositoryName := range validRepositoryNames {
   756  		if err := validateRemoteName(repositoryName); err != nil {
   757  			t.Errorf("Repository name should be valid: %v. Error: %v", repositoryName, err)
   758  		}
   759  	}
   760  
   761  	invalidRepositoryNames := []string{
   762  		// Disallow capital letters.
   763  		"docker/Docker",
   764  
   765  		// Only allow one slash.
   766  		"docker///docker",
   767  
   768  		// Disallow 64-character hexadecimal.
   769  		"1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
   770  
   771  		// Disallow leading and trailing hyphens in namespace.
   772  		"-docker/docker",
   773  		"docker-/docker",
   774  		"-docker-/docker",
   775  
   776  		// Disallow consecutive hyphens.
   777  		"dock--er/docker",
   778  
   779  		// Namespace too short.
   780  		"doc/docker",
   781  
   782  		// No repository.
   783  		"docker/",
   784  	}
   785  	for _, repositoryName := range invalidRepositoryNames {
   786  		if err := validateRemoteName(repositoryName); err == nil {
   787  			t.Errorf("Repository name should be invalid: %v", repositoryName)
   788  		}
   789  	}
   790  }
   791  
   792  func TestTrustedLocation(t *testing.T) {
   793  	for _, url := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} {
   794  		req, _ := http.NewRequest("GET", url, nil)
   795  		if trustedLocation(req) == true {
   796  			t.Fatalf("'%s' shouldn't be detected as a trusted location", url)
   797  		}
   798  	}
   799  
   800  	for _, url := range []string{"https://docker.io", "https://test.docker.com:80"} {
   801  		req, _ := http.NewRequest("GET", url, nil)
   802  		if trustedLocation(req) == false {
   803  			t.Fatalf("'%s' should be detected as a trusted location", url)
   804  		}
   805  	}
   806  }
   807  
   808  func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) {
   809  	for _, urls := range [][]string{
   810  		{"http://docker.io", "https://docker.com"},
   811  		{"https://foo.docker.io:7777", "http://bar.docker.com"},
   812  		{"https://foo.docker.io", "https://example.com"},
   813  	} {
   814  		reqFrom, _ := http.NewRequest("GET", urls[0], nil)
   815  		reqFrom.Header.Add("Content-Type", "application/json")
   816  		reqFrom.Header.Add("Authorization", "super_secret")
   817  		reqTo, _ := http.NewRequest("GET", urls[1], nil)
   818  
   819  		AddRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
   820  
   821  		if len(reqTo.Header) != 1 {
   822  			t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header))
   823  		}
   824  
   825  		if reqTo.Header.Get("Content-Type") != "application/json" {
   826  			t.Fatal("'Content-Type' should be 'application/json'")
   827  		}
   828  
   829  		if reqTo.Header.Get("Authorization") != "" {
   830  			t.Fatal("'Authorization' should be empty")
   831  		}
   832  	}
   833  
   834  	for _, urls := range [][]string{
   835  		{"https://docker.io", "https://docker.com"},
   836  		{"https://foo.docker.io:7777", "https://bar.docker.com"},
   837  	} {
   838  		reqFrom, _ := http.NewRequest("GET", urls[0], nil)
   839  		reqFrom.Header.Add("Content-Type", "application/json")
   840  		reqFrom.Header.Add("Authorization", "super_secret")
   841  		reqTo, _ := http.NewRequest("GET", urls[1], nil)
   842  
   843  		AddRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
   844  
   845  		if len(reqTo.Header) != 2 {
   846  			t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header))
   847  		}
   848  
   849  		if reqTo.Header.Get("Content-Type") != "application/json" {
   850  			t.Fatal("'Content-Type' should be 'application/json'")
   851  		}
   852  
   853  		if reqTo.Header.Get("Authorization") != "super_secret" {
   854  			t.Fatal("'Authorization' should be 'super_secret'")
   855  		}
   856  	}
   857  }
   858  
   859  func TestIsSecureIndex(t *testing.T) {
   860  	tests := []struct {
   861  		addr               string
   862  		insecureRegistries []string
   863  		expected           bool
   864  	}{
   865  		{IndexServerName(), nil, true},
   866  		{"example.com", []string{}, true},
   867  		{"example.com", []string{"example.com"}, false},
   868  		{"localhost", []string{"localhost:5000"}, false},
   869  		{"localhost:5000", []string{"localhost:5000"}, false},
   870  		{"localhost", []string{"example.com"}, false},
   871  		{"127.0.0.1:5000", []string{"127.0.0.1:5000"}, false},
   872  		{"localhost", nil, false},
   873  		{"localhost:5000", nil, false},
   874  		{"127.0.0.1", nil, false},
   875  		{"localhost", []string{"example.com"}, false},
   876  		{"127.0.0.1", []string{"example.com"}, false},
   877  		{"example.com", nil, true},
   878  		{"example.com", []string{"example.com"}, false},
   879  		{"127.0.0.1", []string{"example.com"}, false},
   880  		{"127.0.0.1:5000", []string{"example.com"}, false},
   881  		{"example.com:5000", []string{"42.42.0.0/16"}, false},
   882  		{"example.com", []string{"42.42.0.0/16"}, false},
   883  		{"example.com:5000", []string{"42.42.42.42/8"}, false},
   884  		{"127.0.0.1:5000", []string{"127.0.0.0/8"}, false},
   885  		{"42.42.42.42:5000", []string{"42.1.1.1/8"}, false},
   886  		{"invalid.domain.com", []string{"42.42.0.0/16"}, true},
   887  		{"invalid.domain.com", []string{"invalid.domain.com"}, false},
   888  		{"invalid.domain.com:5000", []string{"invalid.domain.com"}, true},
   889  		{"invalid.domain.com:5000", []string{"invalid.domain.com:5000"}, false},
   890  	}
   891  	for _, tt := range tests {
   892  		config := makeServiceConfig(nil, tt.insecureRegistries)
   893  		if sec := config.isSecureIndex(tt.addr); sec != tt.expected {
   894  			t.Errorf("isSecureIndex failed for %q %v, expected %v got %v", tt.addr, tt.insecureRegistries, tt.expected, sec)
   895  		}
   896  	}
   897  }