123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package slotting
- import (
- "testing"
- "devt.de/krotik/eliasdb/storage/file"
- "devt.de/krotik/eliasdb/storage/paging"
- "devt.de/krotik/eliasdb/storage/slotting/pageview"
- "devt.de/krotik/eliasdb/storage/util"
- )
- func TestLogicalSlotManager(t *testing.T) {
- sf, err := file.NewDefaultStorageFile(DBDIR+"/test8_data", false)
- if err != nil {
- t.Error(err.Error())
- return
- }
- psf, err := paging.NewPagedStorageFile(sf)
- if err != nil {
- t.Error(err)
- return
- }
- fsf, err := file.NewDefaultStorageFile(DBDIR+"/test8_free", false)
- if err != nil {
- t.Error(err.Error())
- return
- }
- fpsf, err := paging.NewPagedStorageFile(fsf)
- if err != nil {
- t.Error(err)
- return
- }
- lsm := NewLogicalSlotManager(psf, fpsf)
- if lsm.ElementsPerPage() != 509 {
- t.Error("Unexpected elements per page:", lsm.ElementsPerPage())
- return
- }
- // Check return value when fetching from a logical slot which doesn't yet exist
- slotinfo, err := lsm.Fetch(util.PackLocation(1, pageview.OffsetTransData))
- if slotinfo != 0 || err != nil {
- t.Error("Unexpected fetch result:", slotinfo, err)
- }
- // Test insertion error
- record, err := sf.Get(1)
- if err != nil {
- t.Error(err)
- return
- }
- _, err = lsm.Insert(util.PackLocation(10, 11))
- if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
- t.Error(err)
- return
- }
- sf.ReleaseInUse(record)
- // Test insertion error when allocating free slots
- record, err = fsf.Get(1)
- if err != nil {
- t.Error(err)
- return
- }
- _, err = lsm.Insert(util.PackLocation(10, 11))
- if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
- t.Error(err)
- return
- }
- fsf.ReleaseInUse(record)
- // Insert a locations
- loc, err := lsm.Insert(util.PackLocation(10, 11))
- if err != nil {
- t.Error(err)
- return
- }
- checkLocation(t, loc, 1, pageview.OffsetTransData)
- // Test error checking when force inserting a location (page does not exist)
- record, err = sf.Get(2)
- if err != nil {
- t.Error(err)
- return
- }
- err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13))
- if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
- t.Error(err)
- return
- }
- sf.ReleaseInUse(record)
- // Force insert a location
- if err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13)); err != nil {
- t.Error(err)
- return
- }
- // Test error checking when force inserting a location (this time the page exists)
- record, err = sf.Get(2)
- if err != nil {
- t.Error(err)
- return
- }
- err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13))
- if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
- t.Error(err)
- return
- }
- sf.ReleaseInUse(record)
- testForceInsertPanic(t, lsm)
- // Check that the physical slot infos have been stored in the logical slots
- _testLogicalSlot(t, sf, 1, pageview.OffsetTransData, 10, 11)
- _testLogicalSlot(t, sf, 2, 2, 12, 13)
- // Free a slot
- record, err = sf.Get(2)
- if err != nil {
- t.Error(err)
- return
- }
- err = lsm.Free(util.PackLocation(2, 2))
- if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
- t.Error("Unexpected free result:", err)
- return
- }
- sf.ReleaseInUse(record)
- if err = lsm.Free(util.PackLocation(2, 2)); err != nil {
- t.Error(err)
- return
- }
- // Check error when fetching from the free manager (the free manager has
- // nothing stored but should fail since it can't look on page 1)
- record, err = fsf.Get(1)
- if err != nil {
- t.Error(err)
- return
- }
- _, err = lsm.Insert(util.PackLocation(12, 13))
- if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
- t.Error("Unexpected free result:", err)
- return
- }
- fsf.ReleaseInUse(record)
- // Check error when updating a logical slot
- record, err = sf.Get(1)
- if err != nil {
- t.Error(err)
- return
- }
- err = lsm.Update(util.PackLocation(1, 3), util.PackLocation(12, 13))
- if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
- t.Error("Unexpected update result:", err)
- return
- }
- sf.ReleaseInUse(record)
- if err := psf.Close(); err != nil {
- t.Error(err)
- return
- }
- if err := fpsf.Close(); err != nil {
- t.Error(err)
- return
- }
- }
- func testForceInsertPanic(t *testing.T, lsm *LogicalSlotManager) {
- defer func() {
- if r := recover(); r == nil {
- t.Error("Force inserting to an existing location did not cause a panic.")
- }
- }()
- lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13))
- }
- func _testLogicalSlot(t *testing.T, sf *file.StorageFile,
- logicalRecord uint64, logicalOffset uint16,
- physicalRecord uint64, physicalOffset uint16) {
- record, err := sf.Get(logicalRecord)
- if err != nil {
- t.Error(err)
- return
- }
- slotinfo := record.ReadUInt64(int(logicalOffset))
- if slotinfo != util.PackLocation(physicalRecord, physicalOffset) {
- t.Error("Unexpected physical location was stored in logical slot:",
- logicalRecord, logicalOffset, " expected:", physicalRecord, physicalOffset,
- "got:", util.LocationRecord(slotinfo), util.LocationOffset(slotinfo))
- }
- sf.ReleaseInUse(record)
- }
|