e2e_test.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // Unit tests for hack/e2e.go shim
  14. package main
  15. import (
  16. "errors"
  17. "flag"
  18. "fmt"
  19. "os"
  20. "path/filepath"
  21. "reflect"
  22. "testing"
  23. "time"
  24. )
  25. type FileInfo struct {
  26. when time.Time
  27. }
  28. func (f FileInfo) Name() string {
  29. return "fake-file"
  30. }
  31. func (f FileInfo) Size() int64 {
  32. return 0
  33. }
  34. func (f FileInfo) Mode() os.FileMode {
  35. return 0
  36. }
  37. func (f FileInfo) ModTime() time.Time {
  38. return f.when
  39. }
  40. func (f FileInfo) IsDir() bool {
  41. return false
  42. }
  43. func (f FileInfo) Sys() interface{} {
  44. return f
  45. }
  46. func TestParse(t *testing.T) {
  47. cases := []struct {
  48. args []string
  49. expected flags
  50. err error
  51. }{
  52. {
  53. []string{"foo", "-v=false"},
  54. flags{getDefault, oldDefault, []string{"--verbose-commands=false"}},
  55. nil,
  56. },
  57. {
  58. []string{"foo", "-v"},
  59. flags{getDefault, oldDefault, []string{"--verbose-commands=true"}},
  60. nil,
  61. },
  62. {
  63. []string{"hello", "world"},
  64. flags{getDefault, oldDefault, []string{"--verbose-commands=true", "world"}},
  65. nil,
  66. },
  67. {
  68. []string{"hello", "--", "--venus", "--karaoke"},
  69. flags{getDefault, oldDefault, []string{"--verbose-commands=true", "--venus", "--karaoke"}},
  70. nil,
  71. },
  72. {
  73. []string{"hello", "--alpha", "--beta"},
  74. flags{getDefault, oldDefault, []string{"--alpha", "--beta"}},
  75. nil,
  76. },
  77. {
  78. []string{"so", "--get", "--boo"},
  79. flags{true, oldDefault, []string{"--boo"}},
  80. nil,
  81. },
  82. {
  83. []string{"omg", "--get=false", "--", "ugh"},
  84. flags{false, oldDefault, []string{"--verbose-commands=true", "ugh"}},
  85. nil,
  86. },
  87. {
  88. []string{"wee", "--old=5m", "--get"},
  89. flags{true, 5 * time.Minute, []string{"--verbose-commands=true"}},
  90. nil,
  91. },
  92. {
  93. []string{"fun", "--times", "--old=666s"},
  94. flags{getDefault, oldDefault, []string{"--times", "--old=666s"}},
  95. nil,
  96. },
  97. {
  98. []string{"wut", "-h"},
  99. flags{},
  100. flag.ErrHelp,
  101. },
  102. {
  103. []string{"wut", "--", "-h"},
  104. flags{getDefault, oldDefault, []string{"--verbose-commands=true", "-h"}},
  105. nil,
  106. },
  107. }
  108. for i, c := range cases {
  109. a, err := parse(c.args)
  110. if err != c.err {
  111. t.Errorf("%d: a=%v != e%v", i, err, c.err)
  112. }
  113. e := c.expected
  114. if a.get != e.get {
  115. t.Errorf("%d: a=%v != e=%v", i, a.get, e.get)
  116. }
  117. if a.old != e.old {
  118. t.Errorf("%d: a=%v != e=%v", i, a.old, e.old)
  119. }
  120. if !reflect.DeepEqual(a.args, e.args) {
  121. t.Errorf("%d: a=%v != e=%v", i, a.args, e.args)
  122. }
  123. }
  124. }
  125. func TestLook(t *testing.T) {
  126. lpf := errors.New("LookPath failed")
  127. sf := errors.New("Stat failed")
  128. lpnc := errors.New("LookPath should not be called")
  129. snc := errors.New("Stat should not be called")
  130. cases := []struct {
  131. stat error
  132. lookPath error
  133. goPath string
  134. expected error
  135. }{
  136. { // GOPATH set, stat succeeds returns gopath
  137. stat: nil,
  138. lookPath: lpnc,
  139. goPath: "fake-gopath/",
  140. expected: nil,
  141. },
  142. { // GOPATH set, stat fails, terms on lookpath
  143. stat: sf,
  144. lookPath: lpf,
  145. goPath: "fake-gopath/",
  146. expected: lpf,
  147. },
  148. { // GOPATH unset, stat not called, terms on lookpath
  149. stat: snc,
  150. lookPath: lpf,
  151. goPath: "",
  152. expected: lpf,
  153. },
  154. { // GOPATH unset, stat not called, lookpath matches
  155. stat: snc,
  156. lookPath: nil,
  157. goPath: "",
  158. expected: nil,
  159. },
  160. }
  161. for _, c := range cases {
  162. l := tester{
  163. func(string) (os.FileInfo, error) {
  164. return FileInfo{}, c.stat
  165. },
  166. func(string) (string, error) {
  167. if c.lookPath != nil {
  168. return "FAILED", c.lookPath
  169. }
  170. return "$PATH-FOUND", nil
  171. },
  172. c.goPath,
  173. nil, // wait
  174. }
  175. if _, err := l.lookKubetest(); err != c.expected {
  176. t.Errorf("err: %s != %s", err, c.expected)
  177. }
  178. }
  179. }
  180. func TestGetKubetest(t *testing.T) {
  181. gp := "fake-gopath"
  182. gpk := filepath.Join(gp, "bin", "kubetest")
  183. p := "PATH"
  184. pk := filepath.Join(p, "kubetest")
  185. eu := errors.New("upgrade failed")
  186. euVerbose := fmt.Errorf("go get -u k8s.io/test-infra/kubetest: %v", eu)
  187. et := errors.New("touch failed")
  188. cases := []struct {
  189. name string
  190. get bool
  191. old time.Duration
  192. stat string // stat succeeds on this file
  193. path bool // file exists on path
  194. age time.Duration // age of mod time on file
  195. upgraded bool // go get -u succeeds
  196. touched bool // touch succeeds
  197. goPath string // GOPATH var
  198. returnPath string
  199. returnError error
  200. }{
  201. {name: "0: Pass when on GOPATH/bin",
  202. get: false,
  203. old: 0,
  204. stat: gpk,
  205. path: false,
  206. age: 100,
  207. upgraded: false,
  208. touched: false,
  209. goPath: gp,
  210. returnPath: gpk,
  211. returnError: nil,
  212. },
  213. {name: "1: Pass when on PATH",
  214. get: false,
  215. old: 0,
  216. stat: pk,
  217. path: true,
  218. age: 100,
  219. upgraded: false,
  220. touched: false,
  221. goPath: gp,
  222. returnPath: pk,
  223. returnError: nil,
  224. },
  225. {name: "2: Don't upgrade if on PATH and GOPATH is ''",
  226. get: true,
  227. old: 0,
  228. stat: pk,
  229. path: true,
  230. age: 100,
  231. upgraded: false,
  232. touched: false,
  233. goPath: "",
  234. returnPath: pk,
  235. returnError: nil,
  236. },
  237. {name: "3: Don't upgrade on PATH when young.",
  238. get: true,
  239. old: time.Hour,
  240. stat: pk,
  241. path: true,
  242. age: time.Second,
  243. upgraded: false,
  244. touched: false,
  245. goPath: gp,
  246. returnPath: pk,
  247. returnError: nil,
  248. },
  249. {name: "4: Upgrade if old but GOPATH is set.",
  250. get: true,
  251. old: 0,
  252. stat: pk,
  253. path: true,
  254. age: time.Second,
  255. upgraded: true,
  256. touched: true,
  257. goPath: gp,
  258. returnPath: pk,
  259. returnError: nil,
  260. },
  261. {name: "5: Fail if upgrade fails",
  262. get: true,
  263. old: 0,
  264. stat: pk,
  265. path: true,
  266. age: time.Second,
  267. upgraded: false,
  268. touched: false,
  269. goPath: gpk,
  270. returnPath: "",
  271. returnError: euVerbose,
  272. },
  273. {name: "6: Fail if touch fails",
  274. get: true,
  275. old: 0,
  276. stat: pk,
  277. path: true,
  278. age: time.Second,
  279. upgraded: true,
  280. touched: false,
  281. goPath: gpk,
  282. returnPath: "",
  283. returnError: et,
  284. },
  285. }
  286. for i, c := range cases {
  287. didUp := false
  288. didTouch := false
  289. l := tester{
  290. stat: func(p string) (os.FileInfo, error) {
  291. // stat
  292. if p != c.stat {
  293. return nil, fmt.Errorf("Failed to find %s", p)
  294. }
  295. return FileInfo{time.Now().Add(c.age * -1)}, nil
  296. },
  297. lookPath: func(name string) (string, error) {
  298. if c.path {
  299. return filepath.Join(p, name), nil
  300. }
  301. return "", fmt.Errorf("Not on path: %s", name)
  302. },
  303. goPath: c.goPath,
  304. wait: func(cmd string, args ...string) error {
  305. if cmd == "go" {
  306. if c.upgraded {
  307. didUp = true
  308. return nil
  309. }
  310. return eu
  311. }
  312. if c.touched {
  313. didTouch = true
  314. return nil
  315. }
  316. return et
  317. },
  318. }
  319. p, e := l.getKubetest(c.get, c.old)
  320. if p != c.returnPath {
  321. t.Errorf("%d: test=%q returnPath %q != %q", i, c.name, p, c.returnPath)
  322. }
  323. if e == nil || c.returnError == nil {
  324. if e != c.returnError {
  325. t.Errorf("%d: test=%q returnError %q != %q", i, c.name, e, c.returnError)
  326. }
  327. } else {
  328. if e.Error() != c.returnError.Error() {
  329. t.Errorf("%d: test=%q returnError %q != %q", i, c.name, e, c.returnError)
  330. }
  331. }
  332. if didUp != c.upgraded {
  333. t.Errorf("%d: test=%q bad upgrade state of %v", i, c.name, didUp)
  334. }
  335. if didTouch != c.touched {
  336. t.Errorf("%d: test=%q bad touch state of %v", i, c.name, didTouch)
  337. }
  338. }
  339. }