PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go

https://gitlab.com/4144/gcc
Go | 635 lines | 587 code | 36 blank | 12 comment | 101 complexity | 6f5422dbb89fa7a601064ffec0fde2db MD5 | raw file
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package codehost
  5. import (
  6. "archive/zip"
  7. "bytes"
  8. "flag"
  9. "fmt"
  10. "internal/testenv"
  11. "io/ioutil"
  12. "log"
  13. "os"
  14. "os/exec"
  15. "path"
  16. "path/filepath"
  17. "reflect"
  18. "strings"
  19. "testing"
  20. "time"
  21. )
  22. func TestMain(m *testing.M) {
  23. // needed for initializing the test environment variables as testing.Short
  24. // and HasExternalNetwork
  25. flag.Parse()
  26. os.Exit(testMain(m))
  27. }
  28. const (
  29. gitrepo1 = "https://vcs-test.golang.org/git/gitrepo1"
  30. hgrepo1 = "https://vcs-test.golang.org/hg/hgrepo1"
  31. )
  32. var altRepos = []string{
  33. "localGitRepo",
  34. hgrepo1,
  35. }
  36. // TODO: Convert gitrepo1 to svn, bzr, fossil and add tests.
  37. // For now, at least the hgrepo1 tests check the general vcs.go logic.
  38. // localGitRepo is like gitrepo1 but allows archive access.
  39. var localGitRepo string
  40. func testMain(m *testing.M) int {
  41. if _, err := exec.LookPath("git"); err != nil {
  42. fmt.Fprintln(os.Stderr, "skipping because git binary not found")
  43. fmt.Println("PASS")
  44. return 0
  45. }
  46. dir, err := ioutil.TempDir("", "gitrepo-test-")
  47. if err != nil {
  48. log.Fatal(err)
  49. }
  50. defer os.RemoveAll(dir)
  51. WorkRoot = dir
  52. if testenv.HasExternalNetwork() && testenv.HasExec() {
  53. // Clone gitrepo1 into a local directory.
  54. // If we use a file:// URL to access the local directory,
  55. // then git starts up all the usual protocol machinery,
  56. // which will let us test remote git archive invocations.
  57. localGitRepo = filepath.Join(dir, "gitrepo2")
  58. if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
  59. log.Fatal(err)
  60. }
  61. if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
  62. log.Fatal(err)
  63. }
  64. }
  65. return m.Run()
  66. }
  67. func testRepo(remote string) (Repo, error) {
  68. if remote == "localGitRepo" {
  69. return LocalGitRepo(filepath.ToSlash(localGitRepo))
  70. }
  71. kind := "git"
  72. for _, k := range []string{"hg"} {
  73. if strings.Contains(remote, "/"+k+"/") {
  74. kind = k
  75. }
  76. }
  77. return NewRepo(kind, remote)
  78. }
  79. var tagsTests = []struct {
  80. repo string
  81. prefix string
  82. tags []string
  83. }{
  84. {gitrepo1, "xxx", []string{}},
  85. {gitrepo1, "", []string{"v1.2.3", "v1.2.4-annotated", "v2.0.1", "v2.0.2", "v2.3"}},
  86. {gitrepo1, "v", []string{"v1.2.3", "v1.2.4-annotated", "v2.0.1", "v2.0.2", "v2.3"}},
  87. {gitrepo1, "v1", []string{"v1.2.3", "v1.2.4-annotated"}},
  88. {gitrepo1, "2", []string{}},
  89. }
  90. func TestTags(t *testing.T) {
  91. testenv.MustHaveExternalNetwork(t)
  92. testenv.MustHaveExec(t)
  93. for _, tt := range tagsTests {
  94. f := func(t *testing.T) {
  95. r, err := testRepo(tt.repo)
  96. if err != nil {
  97. t.Fatal(err)
  98. }
  99. tags, err := r.Tags(tt.prefix)
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. if !reflect.DeepEqual(tags, tt.tags) {
  104. t.Errorf("Tags: incorrect tags\nhave %v\nwant %v", tags, tt.tags)
  105. }
  106. }
  107. t.Run(path.Base(tt.repo)+"/"+tt.prefix, f)
  108. if tt.repo == gitrepo1 {
  109. for _, tt.repo = range altRepos {
  110. t.Run(path.Base(tt.repo)+"/"+tt.prefix, f)
  111. }
  112. }
  113. }
  114. }
  115. var latestTests = []struct {
  116. repo string
  117. info *RevInfo
  118. }{
  119. {
  120. gitrepo1,
  121. &RevInfo{
  122. Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
  123. Short: "ede458df7cd0",
  124. Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
  125. Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
  126. Tags: []string{"v1.2.3", "v1.2.4-annotated"},
  127. },
  128. },
  129. {
  130. hgrepo1,
  131. &RevInfo{
  132. Name: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
  133. Short: "18518c07eb8e",
  134. Version: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
  135. Time: time.Date(2018, 6, 27, 16, 16, 30, 0, time.UTC),
  136. },
  137. },
  138. }
  139. func TestLatest(t *testing.T) {
  140. testenv.MustHaveExternalNetwork(t)
  141. testenv.MustHaveExec(t)
  142. for _, tt := range latestTests {
  143. f := func(t *testing.T) {
  144. r, err := testRepo(tt.repo)
  145. if err != nil {
  146. t.Fatal(err)
  147. }
  148. info, err := r.Latest()
  149. if err != nil {
  150. t.Fatal(err)
  151. }
  152. if !reflect.DeepEqual(info, tt.info) {
  153. t.Errorf("Latest: incorrect info\nhave %+v\nwant %+v", *info, *tt.info)
  154. }
  155. }
  156. t.Run(path.Base(tt.repo), f)
  157. if tt.repo == gitrepo1 {
  158. tt.repo = "localGitRepo"
  159. t.Run(path.Base(tt.repo), f)
  160. }
  161. }
  162. }
  163. var readFileTests = []struct {
  164. repo string
  165. rev string
  166. file string
  167. err string
  168. data string
  169. }{
  170. {
  171. repo: gitrepo1,
  172. rev: "latest",
  173. file: "README",
  174. data: "",
  175. },
  176. {
  177. repo: gitrepo1,
  178. rev: "v2",
  179. file: "another.txt",
  180. data: "another\n",
  181. },
  182. {
  183. repo: gitrepo1,
  184. rev: "v2.3.4",
  185. file: "another.txt",
  186. err: os.ErrNotExist.Error(),
  187. },
  188. }
  189. func TestReadFile(t *testing.T) {
  190. testenv.MustHaveExternalNetwork(t)
  191. testenv.MustHaveExec(t)
  192. for _, tt := range readFileTests {
  193. f := func(t *testing.T) {
  194. r, err := testRepo(tt.repo)
  195. if err != nil {
  196. t.Fatal(err)
  197. }
  198. data, err := r.ReadFile(tt.rev, tt.file, 100)
  199. if err != nil {
  200. if tt.err == "" {
  201. t.Fatalf("ReadFile: unexpected error %v", err)
  202. }
  203. if !strings.Contains(err.Error(), tt.err) {
  204. t.Fatalf("ReadFile: wrong error %q, want %q", err, tt.err)
  205. }
  206. if len(data) != 0 {
  207. t.Errorf("ReadFile: non-empty data %q with error %v", data, err)
  208. }
  209. return
  210. }
  211. if tt.err != "" {
  212. t.Fatalf("ReadFile: no error, wanted %v", tt.err)
  213. }
  214. if string(data) != tt.data {
  215. t.Errorf("ReadFile: incorrect data\nhave %q\nwant %q", data, tt.data)
  216. }
  217. }
  218. t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, f)
  219. if tt.repo == gitrepo1 {
  220. for _, tt.repo = range altRepos {
  221. t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, f)
  222. }
  223. }
  224. }
  225. }
  226. var readZipTests = []struct {
  227. repo string
  228. rev string
  229. subdir string
  230. actualSubdir string
  231. err string
  232. files map[string]uint64
  233. }{
  234. {
  235. repo: gitrepo1,
  236. rev: "v2.3.4",
  237. subdir: "",
  238. files: map[string]uint64{
  239. "prefix/": 0,
  240. "prefix/README": 0,
  241. "prefix/v2": 3,
  242. },
  243. },
  244. {
  245. repo: hgrepo1,
  246. rev: "v2.3.4",
  247. subdir: "",
  248. files: map[string]uint64{
  249. "prefix/.hg_archival.txt": ^uint64(0),
  250. "prefix/README": 0,
  251. "prefix/v2": 3,
  252. },
  253. },
  254. {
  255. repo: gitrepo1,
  256. rev: "v2",
  257. subdir: "",
  258. files: map[string]uint64{
  259. "prefix/": 0,
  260. "prefix/README": 0,
  261. "prefix/v2": 3,
  262. "prefix/another.txt": 8,
  263. "prefix/foo.txt": 13,
  264. },
  265. },
  266. {
  267. repo: hgrepo1,
  268. rev: "v2",
  269. subdir: "",
  270. files: map[string]uint64{
  271. "prefix/.hg_archival.txt": ^uint64(0),
  272. "prefix/README": 0,
  273. "prefix/v2": 3,
  274. "prefix/another.txt": 8,
  275. "prefix/foo.txt": 13,
  276. },
  277. },
  278. {
  279. repo: gitrepo1,
  280. rev: "v3",
  281. subdir: "",
  282. files: map[string]uint64{
  283. "prefix/": 0,
  284. "prefix/v3/": 0,
  285. "prefix/v3/sub/": 0,
  286. "prefix/v3/sub/dir/": 0,
  287. "prefix/v3/sub/dir/file.txt": 16,
  288. "prefix/README": 0,
  289. },
  290. },
  291. {
  292. repo: hgrepo1,
  293. rev: "v3",
  294. subdir: "",
  295. files: map[string]uint64{
  296. "prefix/.hg_archival.txt": ^uint64(0),
  297. "prefix/.hgtags": 405,
  298. "prefix/v3/sub/dir/file.txt": 16,
  299. "prefix/README": 0,
  300. },
  301. },
  302. {
  303. repo: gitrepo1,
  304. rev: "v3",
  305. subdir: "v3/sub/dir",
  306. files: map[string]uint64{
  307. "prefix/": 0,
  308. "prefix/v3/": 0,
  309. "prefix/v3/sub/": 0,
  310. "prefix/v3/sub/dir/": 0,
  311. "prefix/v3/sub/dir/file.txt": 16,
  312. },
  313. },
  314. {
  315. repo: hgrepo1,
  316. rev: "v3",
  317. subdir: "v3/sub/dir",
  318. files: map[string]uint64{
  319. "prefix/v3/sub/dir/file.txt": 16,
  320. },
  321. },
  322. {
  323. repo: gitrepo1,
  324. rev: "v3",
  325. subdir: "v3/sub",
  326. files: map[string]uint64{
  327. "prefix/": 0,
  328. "prefix/v3/": 0,
  329. "prefix/v3/sub/": 0,
  330. "prefix/v3/sub/dir/": 0,
  331. "prefix/v3/sub/dir/file.txt": 16,
  332. },
  333. },
  334. {
  335. repo: hgrepo1,
  336. rev: "v3",
  337. subdir: "v3/sub",
  338. files: map[string]uint64{
  339. "prefix/v3/sub/dir/file.txt": 16,
  340. },
  341. },
  342. {
  343. repo: gitrepo1,
  344. rev: "aaaaaaaaab",
  345. subdir: "",
  346. err: "unknown revision",
  347. },
  348. {
  349. repo: hgrepo1,
  350. rev: "aaaaaaaaab",
  351. subdir: "",
  352. err: "unknown revision",
  353. },
  354. {
  355. repo: "https://github.com/rsc/vgotest1",
  356. rev: "submod/v1.0.4",
  357. subdir: "submod",
  358. files: map[string]uint64{
  359. "prefix/": 0,
  360. "prefix/submod/": 0,
  361. "prefix/submod/go.mod": 53,
  362. "prefix/submod/pkg/": 0,
  363. "prefix/submod/pkg/p.go": 31,
  364. },
  365. },
  366. }
  367. type zipFile struct {
  368. name string
  369. size int64
  370. }
  371. func TestReadZip(t *testing.T) {
  372. testenv.MustHaveExternalNetwork(t)
  373. testenv.MustHaveExec(t)
  374. for _, tt := range readZipTests {
  375. f := func(t *testing.T) {
  376. r, err := testRepo(tt.repo)
  377. if err != nil {
  378. t.Fatal(err)
  379. }
  380. rc, actualSubdir, err := r.ReadZip(tt.rev, tt.subdir, 100000)
  381. if err != nil {
  382. if tt.err == "" {
  383. t.Fatalf("ReadZip: unexpected error %v", err)
  384. }
  385. if !strings.Contains(err.Error(), tt.err) {
  386. t.Fatalf("ReadZip: wrong error %q, want %q", err, tt.err)
  387. }
  388. if rc != nil {
  389. t.Errorf("ReadZip: non-nil io.ReadCloser with error %v", err)
  390. }
  391. return
  392. }
  393. defer rc.Close()
  394. if tt.err != "" {
  395. t.Fatalf("ReadZip: no error, wanted %v", tt.err)
  396. }
  397. if actualSubdir != tt.actualSubdir {
  398. t.Fatalf("ReadZip: actualSubdir = %q, want %q", actualSubdir, tt.actualSubdir)
  399. }
  400. zipdata, err := ioutil.ReadAll(rc)
  401. if err != nil {
  402. t.Fatal(err)
  403. }
  404. z, err := zip.NewReader(bytes.NewReader(zipdata), int64(len(zipdata)))
  405. if err != nil {
  406. t.Fatalf("ReadZip: cannot read zip file: %v", err)
  407. }
  408. have := make(map[string]bool)
  409. for _, f := range z.File {
  410. size, ok := tt.files[f.Name]
  411. if !ok {
  412. t.Errorf("ReadZip: unexpected file %s", f.Name)
  413. continue
  414. }
  415. have[f.Name] = true
  416. if size != ^uint64(0) && f.UncompressedSize64 != size {
  417. t.Errorf("ReadZip: file %s has unexpected size %d != %d", f.Name, f.UncompressedSize64, size)
  418. }
  419. }
  420. for name := range tt.files {
  421. if !have[name] {
  422. t.Errorf("ReadZip: missing file %s", name)
  423. }
  424. }
  425. }
  426. t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, f)
  427. if tt.repo == gitrepo1 {
  428. tt.repo = "localGitRepo"
  429. t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, f)
  430. }
  431. }
  432. }
  433. var hgmap = map[string]string{
  434. "HEAD": "41964ddce1180313bdc01d0a39a2813344d6261d", // not tip due to bad hgrepo1 conversion
  435. "9d02800338b8a55be062c838d1f02e0c5780b9eb": "8f49ee7a6ddcdec6f0112d9dca48d4a2e4c3c09e",
  436. "76a00fb249b7f93091bc2c89a789dab1fc1bc26f": "88fde824ec8b41a76baa16b7e84212cee9f3edd0",
  437. "ede458df7cd0fdca520df19a33158086a8a68e81": "41964ddce1180313bdc01d0a39a2813344d6261d",
  438. "97f6aa59c81c623494825b43d39e445566e429a4": "c0cbbfb24c7c3c50c35c7b88e7db777da4ff625d",
  439. }
  440. var statTests = []struct {
  441. repo string
  442. rev string
  443. err string
  444. info *RevInfo
  445. }{
  446. {
  447. repo: gitrepo1,
  448. rev: "HEAD",
  449. info: &RevInfo{
  450. Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
  451. Short: "ede458df7cd0",
  452. Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
  453. Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
  454. Tags: []string{"v1.2.3", "v1.2.4-annotated"},
  455. },
  456. },
  457. {
  458. repo: gitrepo1,
  459. rev: "v2", // branch
  460. info: &RevInfo{
  461. Name: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
  462. Short: "9d02800338b8",
  463. Version: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
  464. Time: time.Date(2018, 4, 17, 20, 00, 32, 0, time.UTC),
  465. Tags: []string{"v2.0.2"},
  466. },
  467. },
  468. {
  469. repo: gitrepo1,
  470. rev: "v2.3.4", // badly-named branch (semver should be a tag)
  471. info: &RevInfo{
  472. Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
  473. Short: "76a00fb249b7",
  474. Version: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
  475. Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
  476. Tags: []string{"v2.0.1", "v2.3"},
  477. },
  478. },
  479. {
  480. repo: gitrepo1,
  481. rev: "v2.3", // badly-named tag (we only respect full semver v2.3.0)
  482. info: &RevInfo{
  483. Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
  484. Short: "76a00fb249b7",
  485. Version: "v2.3",
  486. Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
  487. Tags: []string{"v2.0.1", "v2.3"},
  488. },
  489. },
  490. {
  491. repo: gitrepo1,
  492. rev: "v1.2.3", // tag
  493. info: &RevInfo{
  494. Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
  495. Short: "ede458df7cd0",
  496. Version: "v1.2.3",
  497. Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
  498. Tags: []string{"v1.2.3", "v1.2.4-annotated"},
  499. },
  500. },
  501. {
  502. repo: gitrepo1,
  503. rev: "ede458df", // hash prefix in refs
  504. info: &RevInfo{
  505. Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
  506. Short: "ede458df7cd0",
  507. Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
  508. Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
  509. Tags: []string{"v1.2.3", "v1.2.4-annotated"},
  510. },
  511. },
  512. {
  513. repo: gitrepo1,
  514. rev: "97f6aa59", // hash prefix not in refs
  515. info: &RevInfo{
  516. Name: "97f6aa59c81c623494825b43d39e445566e429a4",
  517. Short: "97f6aa59c81c",
  518. Version: "97f6aa59c81c623494825b43d39e445566e429a4",
  519. Time: time.Date(2018, 4, 17, 20, 0, 19, 0, time.UTC),
  520. },
  521. },
  522. {
  523. repo: gitrepo1,
  524. rev: "v1.2.4-annotated", // annotated tag uses unwrapped commit hash
  525. info: &RevInfo{
  526. Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
  527. Short: "ede458df7cd0",
  528. Version: "v1.2.4-annotated",
  529. Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
  530. Tags: []string{"v1.2.3", "v1.2.4-annotated"},
  531. },
  532. },
  533. {
  534. repo: gitrepo1,
  535. rev: "aaaaaaaaab",
  536. err: "unknown revision",
  537. },
  538. }
  539. func TestStat(t *testing.T) {
  540. testenv.MustHaveExternalNetwork(t)
  541. testenv.MustHaveExec(t)
  542. for _, tt := range statTests {
  543. f := func(t *testing.T) {
  544. r, err := testRepo(tt.repo)
  545. if err != nil {
  546. t.Fatal(err)
  547. }
  548. info, err := r.Stat(tt.rev)
  549. if err != nil {
  550. if tt.err == "" {
  551. t.Fatalf("Stat: unexpected error %v", err)
  552. }
  553. if !strings.Contains(err.Error(), tt.err) {
  554. t.Fatalf("Stat: wrong error %q, want %q", err, tt.err)
  555. }
  556. if info != nil {
  557. t.Errorf("Stat: non-nil info with error %q", err)
  558. }
  559. return
  560. }
  561. if !reflect.DeepEqual(info, tt.info) {
  562. t.Errorf("Stat: incorrect info\nhave %+v\nwant %+v", *info, *tt.info)
  563. }
  564. }
  565. t.Run(path.Base(tt.repo)+"/"+tt.rev, f)
  566. if tt.repo == gitrepo1 {
  567. for _, tt.repo = range altRepos {
  568. old := tt
  569. var m map[string]string
  570. if tt.repo == hgrepo1 {
  571. m = hgmap
  572. }
  573. if tt.info != nil {
  574. info := *tt.info
  575. tt.info = &info
  576. tt.info.Name = remap(tt.info.Name, m)
  577. tt.info.Version = remap(tt.info.Version, m)
  578. tt.info.Short = remap(tt.info.Short, m)
  579. }
  580. tt.rev = remap(tt.rev, m)
  581. t.Run(path.Base(tt.repo)+"/"+tt.rev, f)
  582. tt = old
  583. }
  584. }
  585. }
  586. }
  587. func remap(name string, m map[string]string) string {
  588. if m[name] != "" {
  589. return m[name]
  590. }
  591. if AllHex(name) {
  592. for k, v := range m {
  593. if strings.HasPrefix(k, name) {
  594. return v[:len(name)]
  595. }
  596. }
  597. }
  598. return name
  599. }