Beispiel #1
0
// Ensure that a C cursor can seek over branches and leafs.
func TestCursor_Seek_Deep(t *testing.T) {
	withDB(func(db *bolt.DB) {
		pgsz := db.Info().PageSize / 10
		assert.True(t, pgsz > 100)
		db.Update(func(tx *bolt.Tx) error {
			b, _ := tx.CreateBucket([]byte("widgets"))
			for i := 1; i < 1000; i++ {
				kv := []byte(fmt.Sprintf("%0*d", pgsz, i*10))
				b.Put(kv, kv)
			}
			return nil
		})
		db.View(func(tx *bolt.Tx) error {
			b := tx.Bucket([]byte("widgets"))
			s := b.Stats()
			assert.True(t, s.Depth > 3)

			c := NewCursor(b)

			// Exact match should go to the key.
			seek := fmt.Sprintf("%0*d", pgsz, 5000)
			k, v, _ := c.Seek([]byte(seek))
			assert.Equal(t, seek, string(k))
			assert.Equal(t, seek, string(v))

			// Inexact match should go to the next key.
			seek = fmt.Sprintf("%0*d", pgsz, 7495)
			found := fmt.Sprintf("%0*d", pgsz, 7500)
			k, v, _ = c.Seek([]byte(seek))
			assert.Equal(t, found, string(k))
			assert.Equal(t, found, string(v))

			// Low key should go to the first key.
			seek = fmt.Sprintf("%0*d", pgsz, 0)
			found = fmt.Sprintf("%0*d", pgsz, 10)
			k, v, _ = c.Seek([]byte(seek))
			assert.Equal(t, found, string(k))
			assert.Equal(t, found, string(v))

			// High key should return no key.
			seek = fmt.Sprintf("%0*d", pgsz, 40000)
			k, v, _ = c.Seek([]byte(seek))
			assert.Equal(t, "", string(k))
			assert.Equal(t, "", string(v))

			// Exact match in the middle of a branch page.
			seek = fmt.Sprintf("%0*d", pgsz, 4170)
			k, v, _ = c.Seek([]byte(seek))
			assert.Equal(t, seek, string(k))
			assert.Equal(t, seek, string(v))

			return nil
		})
	})
}
Beispiel #2
0
// Ensure that a C cursor can seek over branches and leafs.
func TestCursor_Seek_Large(t *testing.T) {
	withDB(func(db *bolt.DB) {
		db.Update(func(tx *bolt.Tx) error {
			b, _ := tx.CreateBucket([]byte("widgets"))
			for i := 1; i < 1000; i++ {
				b.Put([]byte(fmt.Sprintf("%05d\000", i*10)), []byte(fmt.Sprintf("%020d", i*10)))
			}
			return nil
		})
		db.View(func(tx *bolt.Tx) error {
			c := NewCursor(tx.Bucket([]byte("widgets")))

			// Exact match should go to the key.
			k, v, _ := c.Seek([]byte("05000\000"))
			assert.Equal(t, "05000\000", string(k))
			assert.Equal(t, fmt.Sprintf("%020d", 5000), string(v))

			// Inexact match should go to the next key.
			k, v, _ = c.Seek([]byte("07495\000"))
			assert.Equal(t, "07500\000", string(k))
			assert.Equal(t, fmt.Sprintf("%020d", 7500), string(v))

			// Low key should go to the first key.
			k, v, _ = c.Seek([]byte("00000\000"))
			assert.Equal(t, "00010\000", string(k))
			assert.Equal(t, fmt.Sprintf("%020d", 10), string(v))

			// High key should return no key.
			k, v, _ = c.Seek([]byte("40000\000"))
			assert.Equal(t, "", string(k))
			assert.Equal(t, "", string(v))

			return nil
		})
	})
}
Beispiel #3
0
// Ensure that a C cursor handles empty bucket properly
func TestCursor_Empty(t *testing.T) {
	withDB(func(db *bolt.DB) {
		db.Update(func(tx *bolt.Tx) error {
			tx.CreateBucket([]byte("widgets"))
			return nil
		})
		db.View(func(tx *bolt.Tx) error {
			c := NewCursor(tx.Bucket([]byte("widgets")))
			key, value := c.First()
			assert.Nil(t, key)
			assert.Nil(t, value)
			key, value = c.Next()
			assert.Nil(t, key)
			assert.Nil(t, value)
			key, value, flags := c.Seek([]byte("bar"))
			assert.Nil(t, key)
			assert.Nil(t, value)
			assert.Equal(t, 0, flags)
			return nil
		})
	})
}
Beispiel #4
0
// Ensure that a C cursor can seek to the appropriate keys.
func TestCursor_Seek(t *testing.T) {
	withDB(func(db *bolt.DB) {
		db.Update(func(tx *bolt.Tx) error {
			b, err := tx.CreateBucket([]byte("widgets"))
			assert.NoError(t, err)
			assert.NoError(t, b.Put([]byte("foo"), []byte("0001")))
			assert.NoError(t, b.Put([]byte("bar"), []byte("0002")))
			assert.NoError(t, b.Put([]byte("baz"), []byte("0003")))
			_, err = b.CreateBucket([]byte("bkt"))
			assert.NoError(t, err)
			return nil
		})
		db.View(func(tx *bolt.Tx) error {
			c := NewCursor(tx.Bucket([]byte("widgets")))

			// Exact match should go to the key.
			k, v, flags := c.Seek([]byte("bar"))
			assert.Equal(t, "bar", string(k))
			assert.Equal(t, "0002", string(v))
			assert.Equal(t, 0, flags)

			// Inexact match should go to the next key.
			k, v, flags = c.Seek([]byte("bas"))
			assert.Equal(t, "baz", string(k))
			assert.Equal(t, "0003", string(v))
			assert.Equal(t, 0, flags)

			// Inexact match with smaller db key should go to the next key.
			k, v, flags = c.Seek([]byte("barrrr"))
			assert.Equal(t, "baz", string(k))
			assert.Equal(t, "0003", string(v))
			assert.Equal(t, 0, flags)

			// Inexact match with smaller seek key should go to the next key.
			k, v, flags = c.Seek([]byte("ba"))
			assert.Equal(t, "bar", string(k))
			assert.Equal(t, "0002", string(v))
			assert.Equal(t, 0, flags)

			// Low key should go to the first key.
			k, v, flags = c.Seek([]byte(""))
			assert.Equal(t, "bar", string(k))
			assert.Equal(t, "0002", string(v))
			assert.Equal(t, 0, flags)

			// High key should return no key.
			k, v, flags = c.Seek([]byte("zzz"))
			assert.Equal(t, "", string(k))
			assert.Equal(t, "", string(v))
			assert.Equal(t, 0, flags)

			// Buckets should return their key but no value.
			k, v, flags = c.Seek([]byte("bkt"))
			assert.Equal(t, []byte("bkt"), k)
			assert.True(t, len(v) > 0)
			assert.Equal(t, 1, flags) // bucketLeafFlag

			return nil
		})
	})
}