PageRenderTime 27ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/opts/opts_test.go

https://gitlab.com/liwh/docker
Go | 427 lines | 407 code | 19 blank | 1 comment | 64 complexity | ff8e9a18ae454c491efee80a69b33810 MD5 | raw file
  1. package opts
  2. import (
  3. "fmt"
  4. "os"
  5. "runtime"
  6. "strings"
  7. "testing"
  8. )
  9. func TestValidateIPAddress(t *testing.T) {
  10. if ret, err := ValidateIPAddress(`1.2.3.4`); err != nil || ret == "" {
  11. t.Fatalf("ValidateIPAddress(`1.2.3.4`) got %s %s", ret, err)
  12. }
  13. if ret, err := ValidateIPAddress(`127.0.0.1`); err != nil || ret == "" {
  14. t.Fatalf("ValidateIPAddress(`127.0.0.1`) got %s %s", ret, err)
  15. }
  16. if ret, err := ValidateIPAddress(`::1`); err != nil || ret == "" {
  17. t.Fatalf("ValidateIPAddress(`::1`) got %s %s", ret, err)
  18. }
  19. if ret, err := ValidateIPAddress(`127`); err == nil || ret != "" {
  20. t.Fatalf("ValidateIPAddress(`127`) got %s %s", ret, err)
  21. }
  22. if ret, err := ValidateIPAddress(`random invalid string`); err == nil || ret != "" {
  23. t.Fatalf("ValidateIPAddress(`random invalid string`) got %s %s", ret, err)
  24. }
  25. }
  26. func TestMapOpts(t *testing.T) {
  27. tmpMap := make(map[string]string)
  28. o := NewMapOpts(tmpMap, logOptsValidator)
  29. o.Set("max-size=1")
  30. if o.String() != "map[max-size:1]" {
  31. t.Errorf("%s != [map[max-size:1]", o.String())
  32. }
  33. o.Set("max-file=2")
  34. if len(tmpMap) != 2 {
  35. t.Errorf("map length %d != 2", len(tmpMap))
  36. }
  37. if tmpMap["max-file"] != "2" {
  38. t.Errorf("max-file = %s != 2", tmpMap["max-file"])
  39. }
  40. if tmpMap["max-size"] != "1" {
  41. t.Errorf("max-size = %s != 1", tmpMap["max-size"])
  42. }
  43. if o.Set("dummy-val=3") == nil {
  44. t.Errorf("validator is not being called")
  45. }
  46. }
  47. func TestValidateMACAddress(t *testing.T) {
  48. if _, err := ValidateMACAddress(`92:d0:c6:0a:29:33`); err != nil {
  49. t.Fatalf("ValidateMACAddress(`92:d0:c6:0a:29:33`) got %s", err)
  50. }
  51. if _, err := ValidateMACAddress(`92:d0:c6:0a:33`); err == nil {
  52. t.Fatalf("ValidateMACAddress(`92:d0:c6:0a:33`) succeeded; expected failure on invalid MAC")
  53. }
  54. if _, err := ValidateMACAddress(`random invalid string`); err == nil {
  55. t.Fatalf("ValidateMACAddress(`random invalid string`) succeeded; expected failure on invalid MAC")
  56. }
  57. }
  58. func TestListOptsWithoutValidator(t *testing.T) {
  59. o := NewListOpts(nil)
  60. o.Set("foo")
  61. if o.String() != "[foo]" {
  62. t.Errorf("%s != [foo]", o.String())
  63. }
  64. o.Set("bar")
  65. if o.Len() != 2 {
  66. t.Errorf("%d != 2", o.Len())
  67. }
  68. o.Set("bar")
  69. if o.Len() != 3 {
  70. t.Errorf("%d != 3", o.Len())
  71. }
  72. if !o.Get("bar") {
  73. t.Error("o.Get(\"bar\") == false")
  74. }
  75. if o.Get("baz") {
  76. t.Error("o.Get(\"baz\") == true")
  77. }
  78. o.Delete("foo")
  79. if o.String() != "[bar bar]" {
  80. t.Errorf("%s != [bar bar]", o.String())
  81. }
  82. listOpts := o.GetAll()
  83. if len(listOpts) != 2 || listOpts[0] != "bar" || listOpts[1] != "bar" {
  84. t.Errorf("Expected [[bar bar]], got [%v]", listOpts)
  85. }
  86. mapListOpts := o.GetMap()
  87. if len(mapListOpts) != 1 {
  88. t.Errorf("Expected [map[bar:{}]], got [%v]", mapListOpts)
  89. }
  90. }
  91. func TestListOptsWithValidator(t *testing.T) {
  92. // Re-using logOptsvalidator (used by MapOpts)
  93. o := NewListOpts(logOptsValidator)
  94. o.Set("foo")
  95. if o.String() != "[]" {
  96. t.Errorf("%s != []", o.String())
  97. }
  98. o.Set("foo=bar")
  99. if o.String() != "[]" {
  100. t.Errorf("%s != []", o.String())
  101. }
  102. o.Set("max-file=2")
  103. if o.Len() != 1 {
  104. t.Errorf("%d != 1", o.Len())
  105. }
  106. if !o.Get("max-file=2") {
  107. t.Error("o.Get(\"max-file=2\") == false")
  108. }
  109. if o.Get("baz") {
  110. t.Error("o.Get(\"baz\") == true")
  111. }
  112. o.Delete("max-file=2")
  113. if o.String() != "[]" {
  114. t.Errorf("%s != []", o.String())
  115. }
  116. }
  117. func TestValidateDNSSearch(t *testing.T) {
  118. valid := []string{
  119. `.`,
  120. `a`,
  121. `a.`,
  122. `1.foo`,
  123. `17.foo`,
  124. `foo.bar`,
  125. `foo.bar.baz`,
  126. `foo.bar.`,
  127. `foo.bar.baz`,
  128. `foo1.bar2`,
  129. `foo1.bar2.baz`,
  130. `1foo.2bar.`,
  131. `1foo.2bar.baz`,
  132. `foo-1.bar-2`,
  133. `foo-1.bar-2.baz`,
  134. `foo-1.bar-2.`,
  135. `foo-1.bar-2.baz`,
  136. `1-foo.2-bar`,
  137. `1-foo.2-bar.baz`,
  138. `1-foo.2-bar.`,
  139. `1-foo.2-bar.baz`,
  140. }
  141. invalid := []string{
  142. ``,
  143. ` `,
  144. ` `,
  145. `17`,
  146. `17.`,
  147. `.17`,
  148. `17-.`,
  149. `17-.foo`,
  150. `.foo`,
  151. `foo-.bar`,
  152. `-foo.bar`,
  153. `foo.bar-`,
  154. `foo.bar-.baz`,
  155. `foo.-bar`,
  156. `foo.-bar.baz`,
  157. `foo.bar.baz.this.should.fail.on.long.name.beause.it.is.longer.thanisshouldbethis.should.fail.on.long.name.beause.it.is.longer.thanisshouldbethis.should.fail.on.long.name.beause.it.is.longer.thanisshouldbethis.should.fail.on.long.name.beause.it.is.longer.thanisshouldbe`,
  158. }
  159. for _, domain := range valid {
  160. if ret, err := ValidateDNSSearch(domain); err != nil || ret == "" {
  161. t.Fatalf("ValidateDNSSearch(`"+domain+"`) got %s %s", ret, err)
  162. }
  163. }
  164. for _, domain := range invalid {
  165. if ret, err := ValidateDNSSearch(domain); err == nil || ret != "" {
  166. t.Fatalf("ValidateDNSSearch(`"+domain+"`) got %s %s", ret, err)
  167. }
  168. }
  169. }
  170. func TestValidateExtraHosts(t *testing.T) {
  171. valid := []string{
  172. `myhost:192.168.0.1`,
  173. `thathost:10.0.2.1`,
  174. `anipv6host:2003:ab34:e::1`,
  175. `ipv6local:::1`,
  176. }
  177. invalid := map[string]string{
  178. `myhost:192.notanipaddress.1`: `invalid IP`,
  179. `thathost-nosemicolon10.0.0.1`: `bad format`,
  180. `anipv6host:::::1`: `invalid IP`,
  181. `ipv6local:::0::`: `invalid IP`,
  182. }
  183. for _, extrahost := range valid {
  184. if _, err := ValidateExtraHost(extrahost); err != nil {
  185. t.Fatalf("ValidateExtraHost(`"+extrahost+"`) should succeed: error %v", err)
  186. }
  187. }
  188. for extraHost, expectedError := range invalid {
  189. if _, err := ValidateExtraHost(extraHost); err == nil {
  190. t.Fatalf("ValidateExtraHost(`%q`) should have failed validation", extraHost)
  191. } else {
  192. if !strings.Contains(err.Error(), expectedError) {
  193. t.Fatalf("ValidateExtraHost(`%q`) error should contain %q", extraHost, expectedError)
  194. }
  195. }
  196. }
  197. }
  198. func TestValidateAttach(t *testing.T) {
  199. valid := []string{
  200. "stdin",
  201. "stdout",
  202. "stderr",
  203. "STDIN",
  204. "STDOUT",
  205. "STDERR",
  206. }
  207. if _, err := ValidateAttach("invalid"); err == nil {
  208. t.Fatalf("Expected error with [valid streams are STDIN, STDOUT and STDERR], got nothing")
  209. }
  210. for _, attach := range valid {
  211. value, err := ValidateAttach(attach)
  212. if err != nil {
  213. t.Fatal(err)
  214. }
  215. if value != strings.ToLower(attach) {
  216. t.Fatalf("Expected [%v], got [%v]", attach, value)
  217. }
  218. }
  219. }
  220. func TestValidateLink(t *testing.T) {
  221. valid := []string{
  222. "name",
  223. "dcdfbe62ecd0:alias",
  224. "7a67485460b7642516a4ad82ecefe7f57d0c4916f530561b71a50a3f9c4e33da",
  225. "angry_torvalds:linus",
  226. }
  227. invalid := map[string]string{
  228. "": "empty string specified for links",
  229. "too:much:of:it": "bad format for links: too:much:of:it",
  230. }
  231. for _, link := range valid {
  232. if _, err := ValidateLink(link); err != nil {
  233. t.Fatalf("ValidateLink(`%q`) should succeed: error %q", link, err)
  234. }
  235. }
  236. for link, expectedError := range invalid {
  237. if _, err := ValidateLink(link); err == nil {
  238. t.Fatalf("ValidateLink(`%q`) should have failed validation", link)
  239. } else {
  240. if !strings.Contains(err.Error(), expectedError) {
  241. t.Fatalf("ValidateLink(`%q`) error should contain %q", link, expectedError)
  242. }
  243. }
  244. }
  245. }
  246. func TestValidateDevice(t *testing.T) {
  247. valid := []string{
  248. "/home",
  249. "/home:/home",
  250. "/home:/something/else",
  251. "/with space",
  252. "/home:/with space",
  253. "relative:/absolute-path",
  254. "hostPath:/containerPath:r",
  255. "/hostPath:/containerPath:rw",
  256. "/hostPath:/containerPath:mrw",
  257. }
  258. invalid := map[string]string{
  259. "": "bad format for path: ",
  260. "./": "./ is not an absolute path",
  261. "../": "../ is not an absolute path",
  262. "/:../": "../ is not an absolute path",
  263. "/:path": "path is not an absolute path",
  264. ":": "bad format for path: :",
  265. "/tmp:": " is not an absolute path",
  266. ":test": "bad format for path: :test",
  267. ":/test": "bad format for path: :/test",
  268. "tmp:": " is not an absolute path",
  269. ":test:": "bad format for path: :test:",
  270. "::": "bad format for path: ::",
  271. ":::": "bad format for path: :::",
  272. "/tmp:::": "bad format for path: /tmp:::",
  273. ":/tmp::": "bad format for path: :/tmp::",
  274. "path:ro": "ro is not an absolute path",
  275. "path:rr": "rr is not an absolute path",
  276. "a:/b:ro": "bad mode specified: ro",
  277. "a:/b:rr": "bad mode specified: rr",
  278. }
  279. for _, path := range valid {
  280. if _, err := ValidateDevice(path); err != nil {
  281. t.Fatalf("ValidateDevice(`%q`) should succeed: error %q", path, err)
  282. }
  283. }
  284. for path, expectedError := range invalid {
  285. if _, err := ValidateDevice(path); err == nil {
  286. t.Fatalf("ValidateDevice(`%q`) should have failed validation", path)
  287. } else {
  288. if err.Error() != expectedError {
  289. t.Fatalf("ValidateDevice(`%q`) error should contain %q, got %q", path, expectedError, err.Error())
  290. }
  291. }
  292. }
  293. }
  294. func TestValidateEnv(t *testing.T) {
  295. valids := map[string]string{
  296. "a": "a",
  297. "something": "something",
  298. "_=a": "_=a",
  299. "env1=value1": "env1=value1",
  300. "_env1=value1": "_env1=value1",
  301. "env2=value2=value3": "env2=value2=value3",
  302. "env3=abc!qwe": "env3=abc!qwe",
  303. "env_4=value 4": "env_4=value 4",
  304. "PATH": fmt.Sprintf("PATH=%v", os.Getenv("PATH")),
  305. "PATH=something": "PATH=something",
  306. "asd!qwe": "asd!qwe",
  307. "1asd": "1asd",
  308. "123": "123",
  309. "some space": "some space",
  310. " some space before": " some space before",
  311. "some space after ": "some space after ",
  312. }
  313. for value, expected := range valids {
  314. actual, err := ValidateEnv(value)
  315. if err != nil {
  316. t.Fatal(err)
  317. }
  318. if actual != expected {
  319. t.Fatalf("Expected [%v], got [%v]", expected, actual)
  320. }
  321. }
  322. }
  323. func TestValidateLabel(t *testing.T) {
  324. if _, err := ValidateLabel("label"); err == nil || err.Error() != "bad attribute format: label" {
  325. t.Fatalf("Expected an error [bad attribute format: label], go %v", err)
  326. }
  327. if actual, err := ValidateLabel("key1=value1"); err != nil || actual != "key1=value1" {
  328. t.Fatalf("Expected [key1=value1], got [%v,%v]", actual, err)
  329. }
  330. // Validate it's working with more than one =
  331. if actual, err := ValidateLabel("key1=value1=value2"); err != nil {
  332. t.Fatalf("Expected [key1=value1=value2], got [%v,%v]", actual, err)
  333. }
  334. // Validate it's working with one more
  335. if actual, err := ValidateLabel("key1=value1=value2=value3"); err != nil {
  336. t.Fatalf("Expected [key1=value1=value2=value2], got [%v,%v]", actual, err)
  337. }
  338. }
  339. func TestParseHost(t *testing.T) {
  340. invalid := map[string]string{
  341. "anything": "Invalid bind address format: anything",
  342. "something with spaces": "Invalid bind address format: something with spaces",
  343. "://": "Invalid bind address format: ://",
  344. "unknown://": "Invalid bind address format: unknown://",
  345. "tcp://:port": "Invalid bind address format: :port",
  346. "tcp://invalid": "Invalid bind address format: invalid",
  347. "tcp://invalid:port": "Invalid bind address format: invalid:port",
  348. }
  349. const defaultHTTPHost = "tcp://127.0.0.1:2375"
  350. var defaultHOST = "unix:///var/run/docker.sock"
  351. if runtime.GOOS == "windows" {
  352. defaultHOST = defaultHTTPHost
  353. }
  354. valid := map[string]string{
  355. "": defaultHOST,
  356. "fd://": "fd://",
  357. "fd://something": "fd://something",
  358. "tcp://host:": "tcp://host:2375",
  359. "tcp://": "tcp://localhost:2375",
  360. "tcp://:2375": "tcp://localhost:2375", // default ip address
  361. "tcp://:2376": "tcp://localhost:2376", // default ip address
  362. "tcp://0.0.0.0:8080": "tcp://0.0.0.0:8080",
  363. "tcp://192.168.0.0:12000": "tcp://192.168.0.0:12000",
  364. "tcp://192.168:8080": "tcp://192.168:8080",
  365. "tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890", // yeah it's valid :P
  366. "tcp://docker.com:2375": "tcp://docker.com:2375",
  367. "unix://": "unix:///var/run/docker.sock", // default unix:// value
  368. "unix://path/to/socket": "unix://path/to/socket",
  369. }
  370. for value, errorMessage := range invalid {
  371. if _, err := ParseHost(defaultHTTPHost, value); err == nil || err.Error() != errorMessage {
  372. t.Fatalf("Expected an error for %v with [%v], got [%v]", value, errorMessage, err)
  373. }
  374. }
  375. for value, expected := range valid {
  376. if actual, err := ParseHost(defaultHTTPHost, value); err != nil || actual != expected {
  377. t.Fatalf("Expected for %v [%v], got [%v, %v]", value, expected, actual, err)
  378. }
  379. }
  380. }
  381. func logOptsValidator(val string) (string, error) {
  382. allowedKeys := map[string]string{"max-size": "1", "max-file": "2"}
  383. vals := strings.Split(val, "=")
  384. if allowedKeys[vals[0]] != "" {
  385. return val, nil
  386. }
  387. return "", fmt.Errorf("invalid key %s", vals[0])
  388. }