tarsum_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. package tarsum
  2. import (
  3. "archive/tar"
  4. "bytes"
  5. "compress/gzip"
  6. "crypto/md5"
  7. "crypto/rand"
  8. "crypto/sha1"
  9. "crypto/sha256"
  10. "crypto/sha512"
  11. "encoding/hex"
  12. "fmt"
  13. "io"
  14. "io/ioutil"
  15. "os"
  16. "strings"
  17. "testing"
  18. )
  19. type testLayer struct {
  20. filename string
  21. options *sizedOptions
  22. jsonfile string
  23. gzip bool
  24. tarsum string
  25. version Version
  26. hash THash
  27. }
  28. var testLayers = []testLayer{
  29. {
  30. filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
  31. jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
  32. version: Version0,
  33. tarsum: "tarsum+sha256:4095cc12fa5fdb1ab2760377e1cd0c4ecdd3e61b4f9b82319d96fcea6c9a41c6"},
  34. {
  35. filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
  36. jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
  37. version: VersionDev,
  38. tarsum: "tarsum.dev+sha256:db56e35eec6ce65ba1588c20ba6b1ea23743b59e81fb6b7f358ccbde5580345c"},
  39. {
  40. filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
  41. jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
  42. gzip: true,
  43. tarsum: "tarsum+sha256:4095cc12fa5fdb1ab2760377e1cd0c4ecdd3e61b4f9b82319d96fcea6c9a41c6"},
  44. {
  45. // Tests existing version of TarSum when xattrs are present
  46. filename: "testdata/xattr/layer.tar",
  47. jsonfile: "testdata/xattr/json",
  48. version: Version0,
  49. tarsum: "tarsum+sha256:07e304a8dbcb215b37649fde1a699f8aeea47e60815707f1cdf4d55d25ff6ab4"},
  50. {
  51. // Tests next version of TarSum when xattrs are present
  52. filename: "testdata/xattr/layer.tar",
  53. jsonfile: "testdata/xattr/json",
  54. version: VersionDev,
  55. tarsum: "tarsum.dev+sha256:6c58917892d77b3b357b0f9ad1e28e1f4ae4de3a8006bd3beb8beda214d8fd16"},
  56. {
  57. filename: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar",
  58. jsonfile: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json",
  59. tarsum: "tarsum+sha256:c66bd5ec9f87b8f4c6135ca37684618f486a3dd1d113b138d0a177bfa39c2571"},
  60. {
  61. options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
  62. tarsum: "tarsum+sha256:8bf12d7e67c51ee2e8306cba569398b1b9f419969521a12ffb9d8875e8836738"},
  63. {
  64. // this tar has two files with the same path
  65. filename: "testdata/collision/collision-0.tar",
  66. tarsum: "tarsum+sha256:08653904a68d3ab5c59e65ef58c49c1581caa3c34744f8d354b3f575ea04424a"},
  67. {
  68. // this tar has the same two files (with the same path), but reversed order. ensuring is has different hash than above
  69. filename: "testdata/collision/collision-1.tar",
  70. tarsum: "tarsum+sha256:b51c13fbefe158b5ce420d2b930eef54c5cd55c50a2ee4abdddea8fa9f081e0d"},
  71. {
  72. // this tar has newer of collider-0.tar, ensuring is has different hash
  73. filename: "testdata/collision/collision-2.tar",
  74. tarsum: "tarsum+sha256:381547080919bb82691e995508ae20ed33ce0f6948d41cafbeb70ce20c73ee8e"},
  75. {
  76. // this tar has newer of collider-1.tar, ensuring is has different hash
  77. filename: "testdata/collision/collision-3.tar",
  78. tarsum: "tarsum+sha256:f886e431c08143164a676805205979cd8fa535dfcef714db5515650eea5a7c0f"},
  79. {
  80. options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
  81. tarsum: "tarsum+md5:0d7529ec7a8360155b48134b8e599f53",
  82. hash: md5THash,
  83. },
  84. {
  85. options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
  86. tarsum: "tarsum+sha1:f1fee39c5925807ff75ef1925e7a23be444ba4df",
  87. hash: sha1Hash,
  88. },
  89. {
  90. options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
  91. tarsum: "tarsum+sha224:6319390c0b061d639085d8748b14cd55f697cf9313805218b21cf61c",
  92. hash: sha224Hash,
  93. },
  94. {
  95. options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
  96. tarsum: "tarsum+sha384:a578ce3ce29a2ae03b8ed7c26f47d0f75b4fc849557c62454be4b5ffd66ba021e713b48ce71e947b43aab57afd5a7636",
  97. hash: sha384Hash,
  98. },
  99. {
  100. options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
  101. tarsum: "tarsum+sha512:e9bfb90ca5a4dfc93c46ee061a5cf9837de6d2fdf82544d6460d3147290aecfabf7b5e415b9b6e72db9b8941f149d5d69fb17a394cbfaf2eac523bd9eae21855",
  102. hash: sha512Hash,
  103. },
  104. }
  105. type sizedOptions struct {
  106. num int64
  107. size int64
  108. isRand bool
  109. realFile bool
  110. }
  111. // make a tar:
  112. // * num is the number of files the tar should have
  113. // * size is the bytes per file
  114. // * isRand is whether the contents of the files should be a random chunk (otherwise it's all zeros)
  115. // * realFile will write to a TempFile, instead of an in memory buffer
  116. func sizedTar(opts sizedOptions) io.Reader {
  117. var (
  118. fh io.ReadWriter
  119. err error
  120. )
  121. if opts.realFile {
  122. fh, err = ioutil.TempFile("", "tarsum")
  123. if err != nil {
  124. return nil
  125. }
  126. } else {
  127. fh = bytes.NewBuffer([]byte{})
  128. }
  129. tarW := tar.NewWriter(fh)
  130. defer tarW.Close()
  131. for i := int64(0); i < opts.num; i++ {
  132. err := tarW.WriteHeader(&tar.Header{
  133. Name: fmt.Sprintf("/testdata%d", i),
  134. Mode: 0755,
  135. Uid: 0,
  136. Gid: 0,
  137. Size: opts.size,
  138. })
  139. if err != nil {
  140. return nil
  141. }
  142. var rBuf []byte
  143. if opts.isRand {
  144. rBuf = make([]byte, 8)
  145. _, err = rand.Read(rBuf)
  146. if err != nil {
  147. return nil
  148. }
  149. } else {
  150. rBuf = []byte{0, 0, 0, 0, 0, 0, 0, 0}
  151. }
  152. for i := int64(0); i < opts.size/int64(8); i++ {
  153. tarW.Write(rBuf)
  154. }
  155. }
  156. return fh
  157. }
  158. func emptyTarSum(gzip bool) (TarSum, error) {
  159. reader, writer := io.Pipe()
  160. tarWriter := tar.NewWriter(writer)
  161. // Immediately close tarWriter and write-end of the
  162. // Pipe in a separate goroutine so we don't block.
  163. go func() {
  164. tarWriter.Close()
  165. writer.Close()
  166. }()
  167. return NewTarSum(reader, !gzip, Version0)
  168. }
  169. // Test errors on NewTarsumForLabel
  170. func TestNewTarSumForLabelInvalid(t *testing.T) {
  171. reader := strings.NewReader("")
  172. if _, err := NewTarSumForLabel(reader, true, "invalidlabel"); err == nil {
  173. t.Fatalf("Expected an error, got nothing.")
  174. }
  175. if _, err := NewTarSumForLabel(reader, true, "invalid+sha256"); err == nil {
  176. t.Fatalf("Expected an error, got nothing.")
  177. }
  178. if _, err := NewTarSumForLabel(reader, true, "tarsum.v1+invalid"); err == nil {
  179. t.Fatalf("Expected an error, got nothing.")
  180. }
  181. }
  182. func TestNewTarSumForLabel(t *testing.T) {
  183. layer := testLayers[0]
  184. reader, err := os.Open(layer.filename)
  185. if err != nil {
  186. t.Fatal(err)
  187. }
  188. defer reader.Close()
  189. label := strings.Split(layer.tarsum, ":")[0]
  190. ts, err := NewTarSumForLabel(reader, false, label)
  191. if err != nil {
  192. t.Fatal(err)
  193. }
  194. // Make sure it actually worked by reading a little bit of it
  195. nbByteToRead := 8 * 1024
  196. dBuf := make([]byte, nbByteToRead)
  197. _, err = ts.Read(dBuf)
  198. if err != nil {
  199. t.Errorf("failed to read %vKB from %s: %s", nbByteToRead, layer.filename, err)
  200. }
  201. }
  202. // TestEmptyTar tests that tarsum does not fail to read an empty tar
  203. // and correctly returns the hex digest of an empty hash.
  204. func TestEmptyTar(t *testing.T) {
  205. // Test without gzip.
  206. ts, err := emptyTarSum(false)
  207. if err != nil {
  208. t.Fatal(err)
  209. }
  210. zeroBlock := make([]byte, 1024)
  211. buf := new(bytes.Buffer)
  212. n, err := io.Copy(buf, ts)
  213. if err != nil {
  214. t.Fatal(err)
  215. }
  216. if n != int64(len(zeroBlock)) || !bytes.Equal(buf.Bytes(), zeroBlock) {
  217. t.Fatalf("tarSum did not write the correct number of zeroed bytes: %d", n)
  218. }
  219. expectedSum := ts.Version().String() + "+sha256:" + hex.EncodeToString(sha256.New().Sum(nil))
  220. resultSum := ts.Sum(nil)
  221. if resultSum != expectedSum {
  222. t.Fatalf("expected [%s] but got [%s]", expectedSum, resultSum)
  223. }
  224. // Test with gzip.
  225. ts, err = emptyTarSum(true)
  226. if err != nil {
  227. t.Fatal(err)
  228. }
  229. buf.Reset()
  230. n, err = io.Copy(buf, ts)
  231. if err != nil {
  232. t.Fatal(err)
  233. }
  234. bufgz := new(bytes.Buffer)
  235. gz := gzip.NewWriter(bufgz)
  236. n, err = io.Copy(gz, bytes.NewBuffer(zeroBlock))
  237. gz.Close()
  238. gzBytes := bufgz.Bytes()
  239. if n != int64(len(zeroBlock)) || !bytes.Equal(buf.Bytes(), gzBytes) {
  240. t.Fatalf("tarSum did not write the correct number of gzipped-zeroed bytes: %d", n)
  241. }
  242. resultSum = ts.Sum(nil)
  243. if resultSum != expectedSum {
  244. t.Fatalf("expected [%s] but got [%s]", expectedSum, resultSum)
  245. }
  246. // Test without ever actually writing anything.
  247. if ts, err = NewTarSum(bytes.NewReader([]byte{}), true, Version0); err != nil {
  248. t.Fatal(err)
  249. }
  250. resultSum = ts.Sum(nil)
  251. if resultSum != expectedSum {
  252. t.Fatalf("expected [%s] but got [%s]", expectedSum, resultSum)
  253. }
  254. }
  255. var (
  256. md5THash = NewTHash("md5", md5.New)
  257. sha1Hash = NewTHash("sha1", sha1.New)
  258. sha224Hash = NewTHash("sha224", sha256.New224)
  259. sha384Hash = NewTHash("sha384", sha512.New384)
  260. sha512Hash = NewTHash("sha512", sha512.New)
  261. )
  262. // Test all the build-in read size : buf8K, buf16K, buf32K and more
  263. func TestTarSumsReadSize(t *testing.T) {
  264. // Test always on the same layer (that is big enough)
  265. layer := testLayers[0]
  266. for i := 0; i < 5; i++ {
  267. reader, err := os.Open(layer.filename)
  268. if err != nil {
  269. t.Fatal(err)
  270. }
  271. defer reader.Close()
  272. ts, err := NewTarSum(reader, false, layer.version)
  273. if err != nil {
  274. t.Fatal(err)
  275. }
  276. // Read and discard bytes so that it populates sums
  277. nbByteToRead := (i + 1) * 8 * 1024
  278. dBuf := make([]byte, nbByteToRead)
  279. _, err = ts.Read(dBuf)
  280. if err != nil {
  281. t.Errorf("failed to read %vKB from %s: %s", nbByteToRead, layer.filename, err)
  282. continue
  283. }
  284. }
  285. }
  286. func TestTarSums(t *testing.T) {
  287. for _, layer := range testLayers {
  288. var (
  289. fh io.Reader
  290. err error
  291. )
  292. if len(layer.filename) > 0 {
  293. fh, err = os.Open(layer.filename)
  294. if err != nil {
  295. t.Errorf("failed to open %s: %s", layer.filename, err)
  296. continue
  297. }
  298. } else if layer.options != nil {
  299. fh = sizedTar(*layer.options)
  300. } else {
  301. // What else is there to test?
  302. t.Errorf("what to do with %#v", layer)
  303. continue
  304. }
  305. if file, ok := fh.(*os.File); ok {
  306. defer file.Close()
  307. }
  308. var ts TarSum
  309. if layer.hash == nil {
  310. // double negatives!
  311. ts, err = NewTarSum(fh, !layer.gzip, layer.version)
  312. } else {
  313. ts, err = NewTarSumHash(fh, !layer.gzip, layer.version, layer.hash)
  314. }
  315. if err != nil {
  316. t.Errorf("%q :: %q", err, layer.filename)
  317. continue
  318. }
  319. // Read variable number of bytes to test dynamic buffer
  320. dBuf := make([]byte, 1)
  321. _, err = ts.Read(dBuf)
  322. if err != nil {
  323. t.Errorf("failed to read 1B from %s: %s", layer.filename, err)
  324. continue
  325. }
  326. dBuf = make([]byte, 16*1024)
  327. _, err = ts.Read(dBuf)
  328. if err != nil {
  329. t.Errorf("failed to read 16KB from %s: %s", layer.filename, err)
  330. continue
  331. }
  332. // Read and discard remaining bytes
  333. _, err = io.Copy(ioutil.Discard, ts)
  334. if err != nil {
  335. t.Errorf("failed to copy from %s: %s", layer.filename, err)
  336. continue
  337. }
  338. var gotSum string
  339. if len(layer.jsonfile) > 0 {
  340. jfh, err := os.Open(layer.jsonfile)
  341. if err != nil {
  342. t.Errorf("failed to open %s: %s", layer.jsonfile, err)
  343. continue
  344. }
  345. defer jfh.Close()
  346. buf, err := ioutil.ReadAll(jfh)
  347. if err != nil {
  348. t.Errorf("failed to readAll %s: %s", layer.jsonfile, err)
  349. continue
  350. }
  351. gotSum = ts.Sum(buf)
  352. } else {
  353. gotSum = ts.Sum(nil)
  354. }
  355. if layer.tarsum != gotSum {
  356. t.Errorf("expecting [%s], but got [%s]", layer.tarsum, gotSum)
  357. }
  358. var expectedHashName string
  359. if layer.hash != nil {
  360. expectedHashName = layer.hash.Name()
  361. } else {
  362. expectedHashName = DefaultTHash.Name()
  363. }
  364. if expectedHashName != ts.Hash().Name() {
  365. t.Errorf("expecting hash [%v], but got [%s]", expectedHashName, ts.Hash().Name())
  366. }
  367. }
  368. }
  369. func TestIteration(t *testing.T) {
  370. headerTests := []struct {
  371. expectedSum string // TODO(vbatts) it would be nice to get individual sums of each
  372. version Version
  373. hdr *tar.Header
  374. data []byte
  375. }{
  376. {
  377. "tarsum+sha256:626c4a2e9a467d65c33ae81f7f3dedd4de8ccaee72af73223c4bc4718cbc7bbd",
  378. Version0,
  379. &tar.Header{
  380. Name: "file.txt",
  381. Size: 0,
  382. Typeflag: tar.TypeReg,
  383. Devminor: 0,
  384. Devmajor: 0,
  385. },
  386. []byte(""),
  387. },
  388. {
  389. "tarsum.dev+sha256:6ffd43a1573a9913325b4918e124ee982a99c0f3cba90fc032a65f5e20bdd465",
  390. VersionDev,
  391. &tar.Header{
  392. Name: "file.txt",
  393. Size: 0,
  394. Typeflag: tar.TypeReg,
  395. Devminor: 0,
  396. Devmajor: 0,
  397. },
  398. []byte(""),
  399. },
  400. {
  401. "tarsum.dev+sha256:b38166c059e11fb77bef30bf16fba7584446e80fcc156ff46d47e36c5305d8ef",
  402. VersionDev,
  403. &tar.Header{
  404. Name: "another.txt",
  405. Uid: 1000,
  406. Gid: 1000,
  407. Uname: "slartibartfast",
  408. Gname: "users",
  409. Size: 4,
  410. Typeflag: tar.TypeReg,
  411. Devminor: 0,
  412. Devmajor: 0,
  413. },
  414. []byte("test"),
  415. },
  416. {
  417. "tarsum.dev+sha256:4cc2e71ac5d31833ab2be9b4f7842a14ce595ec96a37af4ed08f87bc374228cd",
  418. VersionDev,
  419. &tar.Header{
  420. Name: "xattrs.txt",
  421. Uid: 1000,
  422. Gid: 1000,
  423. Uname: "slartibartfast",
  424. Gname: "users",
  425. Size: 4,
  426. Typeflag: tar.TypeReg,
  427. Xattrs: map[string]string{
  428. "user.key1": "value1",
  429. "user.key2": "value2",
  430. },
  431. },
  432. []byte("test"),
  433. },
  434. {
  435. "tarsum.dev+sha256:65f4284fa32c0d4112dd93c3637697805866415b570587e4fd266af241503760",
  436. VersionDev,
  437. &tar.Header{
  438. Name: "xattrs.txt",
  439. Uid: 1000,
  440. Gid: 1000,
  441. Uname: "slartibartfast",
  442. Gname: "users",
  443. Size: 4,
  444. Typeflag: tar.TypeReg,
  445. Xattrs: map[string]string{
  446. "user.KEY1": "value1", // adding different case to ensure different sum
  447. "user.key2": "value2",
  448. },
  449. },
  450. []byte("test"),
  451. },
  452. {
  453. "tarsum+sha256:c12bb6f1303a9ddbf4576c52da74973c00d14c109bcfa76b708d5da1154a07fa",
  454. Version0,
  455. &tar.Header{
  456. Name: "xattrs.txt",
  457. Uid: 1000,
  458. Gid: 1000,
  459. Uname: "slartibartfast",
  460. Gname: "users",
  461. Size: 4,
  462. Typeflag: tar.TypeReg,
  463. Xattrs: map[string]string{
  464. "user.NOT": "CALCULATED",
  465. },
  466. },
  467. []byte("test"),
  468. },
  469. }
  470. for _, htest := range headerTests {
  471. s, err := renderSumForHeader(htest.version, htest.hdr, htest.data)
  472. if err != nil {
  473. t.Fatal(err)
  474. }
  475. if s != htest.expectedSum {
  476. t.Errorf("expected sum: %q, got: %q", htest.expectedSum, s)
  477. }
  478. }
  479. }
  480. func renderSumForHeader(v Version, h *tar.Header, data []byte) (string, error) {
  481. buf := bytes.NewBuffer(nil)
  482. // first build our test tar
  483. tw := tar.NewWriter(buf)
  484. if err := tw.WriteHeader(h); err != nil {
  485. return "", err
  486. }
  487. if _, err := tw.Write(data); err != nil {
  488. return "", err
  489. }
  490. tw.Close()
  491. ts, err := NewTarSum(buf, true, v)
  492. if err != nil {
  493. return "", err
  494. }
  495. tr := tar.NewReader(ts)
  496. for {
  497. hdr, err := tr.Next()
  498. if hdr == nil || err == io.EOF {
  499. // Signals the end of the archive.
  500. break
  501. }
  502. if err != nil {
  503. return "", err
  504. }
  505. if _, err = io.Copy(ioutil.Discard, tr); err != nil {
  506. return "", err
  507. }
  508. }
  509. return ts.Sum(nil), nil
  510. }
  511. func Benchmark9kTar(b *testing.B) {
  512. buf := bytes.NewBuffer([]byte{})
  513. fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
  514. if err != nil {
  515. b.Error(err)
  516. return
  517. }
  518. defer fh.Close()
  519. n, err := io.Copy(buf, fh)
  520. if err != nil {
  521. b.Error(err)
  522. return
  523. }
  524. reader := bytes.NewReader(buf.Bytes())
  525. b.SetBytes(n)
  526. b.ResetTimer()
  527. for i := 0; i < b.N; i++ {
  528. reader.Seek(0, 0)
  529. ts, err := NewTarSum(reader, true, Version0)
  530. if err != nil {
  531. b.Error(err)
  532. return
  533. }
  534. io.Copy(ioutil.Discard, ts)
  535. ts.Sum(nil)
  536. }
  537. }
  538. func Benchmark9kTarGzip(b *testing.B) {
  539. buf := bytes.NewBuffer([]byte{})
  540. fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
  541. if err != nil {
  542. b.Error(err)
  543. return
  544. }
  545. defer fh.Close()
  546. n, err := io.Copy(buf, fh)
  547. if err != nil {
  548. b.Error(err)
  549. return
  550. }
  551. reader := bytes.NewReader(buf.Bytes())
  552. b.SetBytes(n)
  553. b.ResetTimer()
  554. for i := 0; i < b.N; i++ {
  555. reader.Seek(0, 0)
  556. ts, err := NewTarSum(reader, false, Version0)
  557. if err != nil {
  558. b.Error(err)
  559. return
  560. }
  561. io.Copy(ioutil.Discard, ts)
  562. ts.Sum(nil)
  563. }
  564. }
  565. // this is a single big file in the tar archive
  566. func Benchmark1mbSingleFileTar(b *testing.B) {
  567. benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, false)
  568. }
  569. // this is a single big file in the tar archive
  570. func Benchmark1mbSingleFileTarGzip(b *testing.B) {
  571. benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, true)
  572. }
  573. // this is 1024 1k files in the tar archive
  574. func Benchmark1kFilesTar(b *testing.B) {
  575. benchmarkTar(b, sizedOptions{1024, 1024, true, true}, false)
  576. }
  577. // this is 1024 1k files in the tar archive
  578. func Benchmark1kFilesTarGzip(b *testing.B) {
  579. benchmarkTar(b, sizedOptions{1024, 1024, true, true}, true)
  580. }
  581. func benchmarkTar(b *testing.B, opts sizedOptions, isGzip bool) {
  582. var fh *os.File
  583. tarReader := sizedTar(opts)
  584. if br, ok := tarReader.(*os.File); ok {
  585. fh = br
  586. }
  587. defer os.Remove(fh.Name())
  588. defer fh.Close()
  589. b.SetBytes(opts.size * opts.num)
  590. b.ResetTimer()
  591. for i := 0; i < b.N; i++ {
  592. ts, err := NewTarSum(fh, !isGzip, Version0)
  593. if err != nil {
  594. b.Error(err)
  595. return
  596. }
  597. io.Copy(ioutil.Discard, ts)
  598. ts.Sum(nil)
  599. fh.Seek(0, 0)
  600. }
  601. }