You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.5 KiB

  1. // Copyright (c) 2014, Suryandaru Triandana <syndtr@gmail.com>
  2. // All rights reserved.
  3. //
  4. // Use of this source code is governed by a BSD-style license that can be
  5. // found in the LICENSE file.
  6. package table
  7. import (
  8. "bytes"
  9. . "github.com/onsi/ginkgo"
  10. . "github.com/onsi/gomega"
  11. "github.com/syndtr/goleveldb/leveldb/iterator"
  12. "github.com/syndtr/goleveldb/leveldb/opt"
  13. "github.com/syndtr/goleveldb/leveldb/storage"
  14. "github.com/syndtr/goleveldb/leveldb/testutil"
  15. "github.com/syndtr/goleveldb/leveldb/util"
  16. )
  17. type tableWrapper struct {
  18. *Reader
  19. }
  20. func (t tableWrapper) TestFind(key []byte) (rkey, rvalue []byte, err error) {
  21. return t.Reader.Find(key, false, nil)
  22. }
  23. func (t tableWrapper) TestGet(key []byte) (value []byte, err error) {
  24. return t.Reader.Get(key, nil)
  25. }
  26. func (t tableWrapper) TestNewIterator(slice *util.Range) iterator.Iterator {
  27. return t.Reader.NewIterator(slice, nil)
  28. }
  29. var _ = testutil.Defer(func() {
  30. Describe("Table", func() {
  31. Describe("approximate offset test", func() {
  32. var (
  33. buf = &bytes.Buffer{}
  34. o = &opt.Options{
  35. BlockSize: 1024,
  36. Compression: opt.NoCompression,
  37. }
  38. )
  39. // Building the table.
  40. tw := NewWriter(buf, o)
  41. tw.Append([]byte("k01"), []byte("hello"))
  42. tw.Append([]byte("k02"), []byte("hello2"))
  43. tw.Append([]byte("k03"), bytes.Repeat([]byte{'x'}, 10000))
  44. tw.Append([]byte("k04"), bytes.Repeat([]byte{'x'}, 200000))
  45. tw.Append([]byte("k05"), bytes.Repeat([]byte{'x'}, 300000))
  46. tw.Append([]byte("k06"), []byte("hello3"))
  47. tw.Append([]byte("k07"), bytes.Repeat([]byte{'x'}, 100000))
  48. err := tw.Close()
  49. It("Should be able to approximate offset of a key correctly", func() {
  50. Expect(err).ShouldNot(HaveOccurred())
  51. tr, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()), storage.FileDesc{}, nil, nil, o)
  52. Expect(err).ShouldNot(HaveOccurred())
  53. CheckOffset := func(key string, expect, threshold int) {
  54. offset, err := tr.OffsetOf([]byte(key))
  55. Expect(err).ShouldNot(HaveOccurred())
  56. Expect(offset).Should(BeNumerically("~", expect, threshold), "Offset of key %q", key)
  57. }
  58. CheckOffset("k0", 0, 0)
  59. CheckOffset("k01a", 0, 0)
  60. CheckOffset("k02", 0, 0)
  61. CheckOffset("k03", 0, 0)
  62. CheckOffset("k04", 10000, 1000)
  63. CheckOffset("k04a", 210000, 1000)
  64. CheckOffset("k05", 210000, 1000)
  65. CheckOffset("k06", 510000, 1000)
  66. CheckOffset("k07", 510000, 1000)
  67. CheckOffset("xyz", 610000, 2000)
  68. })
  69. })
  70. Describe("read test", func() {
  71. Build := func(kv testutil.KeyValue) testutil.DB {
  72. o := &opt.Options{
  73. BlockSize: 512,
  74. BlockRestartInterval: 3,
  75. }
  76. buf := &bytes.Buffer{}
  77. // Building the table.
  78. tw := NewWriter(buf, o)
  79. kv.Iterate(func(i int, key, value []byte) {
  80. tw.Append(key, value)
  81. })
  82. tw.Close()
  83. // Opening the table.
  84. tr, _ := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()), storage.FileDesc{}, nil, nil, o)
  85. return tableWrapper{tr}
  86. }
  87. Test := func(kv *testutil.KeyValue, body func(r *Reader)) func() {
  88. return func() {
  89. db := Build(*kv)
  90. if body != nil {
  91. body(db.(tableWrapper).Reader)
  92. }
  93. testutil.KeyValueTesting(nil, *kv, db, nil, nil)
  94. }
  95. }
  96. testutil.AllKeyValueTesting(nil, Build, nil, nil)
  97. Describe("with one key per block", Test(testutil.KeyValue_Generate(nil, 9, 1, 1, 10, 512, 512), func(r *Reader) {
  98. It("should have correct blocks number", func() {
  99. indexBlock, err := r.readBlock(r.indexBH, true)
  100. Expect(err).To(BeNil())
  101. Expect(indexBlock.restartsLen).Should(Equal(9))
  102. })
  103. }))
  104. })
  105. })
  106. })