reference_test.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package reference
  2. import (
  3. "testing"
  4. "github.com/docker/distribution/digest"
  5. )
  6. func TestValidateReferenceName(t *testing.T) {
  7. validRepoNames := []string{
  8. "docker/docker",
  9. "library/debian",
  10. "debian",
  11. "docker.io/docker/docker",
  12. "docker.io/library/debian",
  13. "docker.io/debian",
  14. "index.docker.io/docker/docker",
  15. "index.docker.io/library/debian",
  16. "index.docker.io/debian",
  17. "127.0.0.1:5000/docker/docker",
  18. "127.0.0.1:5000/library/debian",
  19. "127.0.0.1:5000/debian",
  20. "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
  21. }
  22. invalidRepoNames := []string{
  23. "https://github.com/docker/docker",
  24. "docker/Docker",
  25. "-docker",
  26. "-docker/docker",
  27. "-docker.io/docker/docker",
  28. "docker///docker",
  29. "docker.io/docker/Docker",
  30. "docker.io/docker///docker",
  31. "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
  32. "docker.io/1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
  33. }
  34. for _, name := range invalidRepoNames {
  35. _, err := ParseNamed(name)
  36. if err == nil {
  37. t.Fatalf("Expected invalid repo name for %q", name)
  38. }
  39. }
  40. for _, name := range validRepoNames {
  41. _, err := ParseNamed(name)
  42. if err != nil {
  43. t.Fatalf("Error parsing repo name %s, got: %q", name, err)
  44. }
  45. }
  46. }
  47. func TestValidateRemoteName(t *testing.T) {
  48. validRepositoryNames := []string{
  49. // Sanity check.
  50. "docker/docker",
  51. // Allow 64-character non-hexadecimal names (hexadecimal names are forbidden).
  52. "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
  53. // Allow embedded hyphens.
  54. "docker-rules/docker",
  55. // Allow multiple hyphens as well.
  56. "docker---rules/docker",
  57. //Username doc and image name docker being tested.
  58. "doc/docker",
  59. // single character names are now allowed.
  60. "d/docker",
  61. "jess/t",
  62. // Consecutive underscores.
  63. "dock__er/docker",
  64. }
  65. for _, repositoryName := range validRepositoryNames {
  66. _, err := ParseNamed(repositoryName)
  67. if err != nil {
  68. t.Errorf("Repository name should be valid: %v. Error: %v", repositoryName, err)
  69. }
  70. }
  71. invalidRepositoryNames := []string{
  72. // Disallow capital letters.
  73. "docker/Docker",
  74. // Only allow one slash.
  75. "docker///docker",
  76. // Disallow 64-character hexadecimal.
  77. "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
  78. // Disallow leading and trailing hyphens in namespace.
  79. "-docker/docker",
  80. "docker-/docker",
  81. "-docker-/docker",
  82. // Don't allow underscores everywhere (as opposed to hyphens).
  83. "____/____",
  84. "_docker/_docker",
  85. // Disallow consecutive periods.
  86. "dock..er/docker",
  87. "dock_.er/docker",
  88. "dock-.er/docker",
  89. // No repository.
  90. "docker/",
  91. //namespace too long
  92. "this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255/docker",
  93. }
  94. for _, repositoryName := range invalidRepositoryNames {
  95. if _, err := ParseNamed(repositoryName); err == nil {
  96. t.Errorf("Repository name should be invalid: %v", repositoryName)
  97. }
  98. }
  99. }
  100. func TestParseRepositoryInfo(t *testing.T) {
  101. type tcase struct {
  102. RemoteName, NormalizedName, FullName, AmbiguousName, Hostname string
  103. }
  104. tcases := []tcase{
  105. {
  106. RemoteName: "fooo/bar",
  107. NormalizedName: "fooo/bar",
  108. FullName: "docker.io/fooo/bar",
  109. AmbiguousName: "index.docker.io/fooo/bar",
  110. Hostname: "docker.io",
  111. },
  112. {
  113. RemoteName: "library/ubuntu",
  114. NormalizedName: "ubuntu",
  115. FullName: "docker.io/library/ubuntu",
  116. AmbiguousName: "library/ubuntu",
  117. Hostname: "docker.io",
  118. },
  119. {
  120. RemoteName: "nonlibrary/ubuntu",
  121. NormalizedName: "nonlibrary/ubuntu",
  122. FullName: "docker.io/nonlibrary/ubuntu",
  123. AmbiguousName: "",
  124. Hostname: "docker.io",
  125. },
  126. {
  127. RemoteName: "other/library",
  128. NormalizedName: "other/library",
  129. FullName: "docker.io/other/library",
  130. AmbiguousName: "",
  131. Hostname: "docker.io",
  132. },
  133. {
  134. RemoteName: "private/moonbase",
  135. NormalizedName: "127.0.0.1:8000/private/moonbase",
  136. FullName: "127.0.0.1:8000/private/moonbase",
  137. AmbiguousName: "",
  138. Hostname: "127.0.0.1:8000",
  139. },
  140. {
  141. RemoteName: "privatebase",
  142. NormalizedName: "127.0.0.1:8000/privatebase",
  143. FullName: "127.0.0.1:8000/privatebase",
  144. AmbiguousName: "",
  145. Hostname: "127.0.0.1:8000",
  146. },
  147. {
  148. RemoteName: "private/moonbase",
  149. NormalizedName: "example.com/private/moonbase",
  150. FullName: "example.com/private/moonbase",
  151. AmbiguousName: "",
  152. Hostname: "example.com",
  153. },
  154. {
  155. RemoteName: "privatebase",
  156. NormalizedName: "example.com/privatebase",
  157. FullName: "example.com/privatebase",
  158. AmbiguousName: "",
  159. Hostname: "example.com",
  160. },
  161. {
  162. RemoteName: "private/moonbase",
  163. NormalizedName: "example.com:8000/private/moonbase",
  164. FullName: "example.com:8000/private/moonbase",
  165. AmbiguousName: "",
  166. Hostname: "example.com:8000",
  167. },
  168. {
  169. RemoteName: "privatebasee",
  170. NormalizedName: "example.com:8000/privatebasee",
  171. FullName: "example.com:8000/privatebasee",
  172. AmbiguousName: "",
  173. Hostname: "example.com:8000",
  174. },
  175. {
  176. RemoteName: "library/ubuntu-12.04-base",
  177. NormalizedName: "ubuntu-12.04-base",
  178. FullName: "docker.io/library/ubuntu-12.04-base",
  179. AmbiguousName: "index.docker.io/library/ubuntu-12.04-base",
  180. Hostname: "docker.io",
  181. },
  182. }
  183. for _, tcase := range tcases {
  184. refStrings := []string{tcase.NormalizedName, tcase.FullName}
  185. if tcase.AmbiguousName != "" {
  186. refStrings = append(refStrings, tcase.AmbiguousName)
  187. }
  188. var refs []Named
  189. for _, r := range refStrings {
  190. named, err := ParseNamed(r)
  191. if err != nil {
  192. t.Fatal(err)
  193. }
  194. refs = append(refs, named)
  195. named, err = WithName(r)
  196. if err != nil {
  197. t.Fatal(err)
  198. }
  199. refs = append(refs, named)
  200. }
  201. for _, r := range refs {
  202. if expected, actual := tcase.NormalizedName, r.Name(); expected != actual {
  203. t.Fatalf("Invalid normalized reference for %q. Expected %q, got %q", r, expected, actual)
  204. }
  205. if expected, actual := tcase.FullName, r.FullName(); expected != actual {
  206. t.Fatalf("Invalid normalized reference for %q. Expected %q, got %q", r, expected, actual)
  207. }
  208. if expected, actual := tcase.Hostname, r.Hostname(); expected != actual {
  209. t.Fatalf("Invalid hostname for %q. Expected %q, got %q", r, expected, actual)
  210. }
  211. if expected, actual := tcase.RemoteName, r.RemoteName(); expected != actual {
  212. t.Fatalf("Invalid remoteName for %q. Expected %q, got %q", r, expected, actual)
  213. }
  214. }
  215. }
  216. }
  217. func TestParseReferenceWithTagAndDigest(t *testing.T) {
  218. ref, err := ParseNamed("busybox:latest@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")
  219. if err != nil {
  220. t.Fatal(err)
  221. }
  222. if _, isTagged := ref.(NamedTagged); isTagged {
  223. t.Fatalf("Reference from %q should not support tag", ref)
  224. }
  225. if _, isCanonical := ref.(Canonical); !isCanonical {
  226. t.Fatalf("Reference from %q should not support digest", ref)
  227. }
  228. if expected, actual := "busybox@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa", ref.String(); actual != expected {
  229. t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual)
  230. }
  231. }
  232. func TestInvalidReferenceComponents(t *testing.T) {
  233. if _, err := WithName("-foo"); err == nil {
  234. t.Fatal("Expected WithName to detect invalid name")
  235. }
  236. ref, err := WithName("busybox")
  237. if err != nil {
  238. t.Fatal(err)
  239. }
  240. if _, err := WithTag(ref, "-foo"); err == nil {
  241. t.Fatal("Expected WithName to detect invalid tag")
  242. }
  243. if _, err := WithDigest(ref, digest.Digest("foo")); err == nil {
  244. t.Fatal("Expected WithName to detect invalid digest")
  245. }
  246. }