Example #1
0
func openTestCache(test *testing.T) (common.BlockDevice, *LRUCache) {
	dev := testutils.NewTestDevice(test, 64, 100)
	cache := NewLRUCache(4, 10, 16)

	err := cache.MountDevice(0, dev, getDevInfo(64))
	if err != nil {
		testutils.ErrorHere(test, "Failed when mounting ramdisk device into cache: %s", err)
	}
	return dev, cache.(*LRUCache)
}
Example #2
0
func TestGetConcurrency(test *testing.T) {
	dev, cache := openTestCache(test)
	bdev := testutils.NewBlockingDevice(testutils.NewTestDevice(test, 64, 100))
	cache.MountDevice(1, bdev, getDevInfo(64))

	// Test that reads from a normal device are not blocked by reads from a
	// broken device.
	wg := new(sync.WaitGroup)
	wg.Add(2)
	go func() {
		// Do the read on the broken device
		cb := cache.GetBlock(1, 0, common.FULL_DATA_BLOCK, common.NORMAL)
		cache.PutBlock(cb, common.FULL_DATA_BLOCK)
		wg.Done()
	}()

	go func() {
		// Wait for the device to be blocked
		<-bdev.HasBlocked
		cb := cache.GetBlock(0, 0, common.FULL_DATA_BLOCK, common.NORMAL)
		// Now unblock that device so we can shut down
		bdev.Unblock <- true
		cache.PutBlock(cb, common.FULL_DATA_BLOCK)

		wg.Done()
	}()

	wg.Wait()
	if err := cache.UnmountDevice(1); err != nil {
		testutils.ErrorHere(test, "Failed when unmounting device: %s", err)
	}
	if err := bdev.Close(); err != nil {
		testutils.ErrorHere(test, "Failed when closing device: %s", err)
	}
	closeTestCache(test, dev, cache)
}
Example #3
0
// Test that blocks are cached. This test will deadlock if more than one block
// read is attempted from the underlying device.
func TestDoesCache(test *testing.T) {
	// Open an always-broken device
	dev := testutils.NewBlockingDevice(testutils.NewTestDevice(test, 64, 100))
	cache := NewLRUCache(4, 10, 16)
	err := cache.MountDevice(0, dev, getDevInfo(64))
	if err != nil {
		testutils.ErrorHere(test, "Failed when mounting ramdisk device into cache: %s", err)
	}

	wg := new(sync.WaitGroup)
	wg.Add(2)

	go func() {
		// Allow a single block to be read
		<-dev.HasBlocked
		dev.Unblock <- true
		wg.Done()
	}()

	go func() {
		cb1 := cache.GetBlock(0, 5, common.FULL_DATA_BLOCK, common.NORMAL)
		data, ok := cb1.Block.(common.FullDataBlock)
		if !ok {
			testutils.ErrorHere(test, "Did not get a FullDataBlock")
		}
		if data[0] != 5 {
			testutils.ErrorHere(test, "Data in block did not match, expected %x, got %x", 5, data[0])
		}

		// this should be pulled from the cache, not from the device
		cb2 := cache.GetBlock(0, 5, common.FULL_DATA_BLOCK, common.NORMAL)
		if cb1 != cb2 {
			testutils.ErrorHere(test, "Cache block mismatch, expected %p, got %p", cb1, cb2)
		}
		data, ok = cb2.Block.(common.FullDataBlock)
		if !ok {
			testutils.ErrorHere(test, "Did not get a FullDataBlock")
		}
		if data[0] != 5 {
			testutils.ErrorHere(test, "Data in block did not match, expected %x, got %x", 5, data[0])
		}

		cache.PutBlock(cb1, common.FULL_DATA_BLOCK)
		cache.PutBlock(cb2, common.FULL_DATA_BLOCK)

		wg.Done()
	}()

	wg.Wait()

	err = cache.UnmountDevice(0)
	if err != nil {
		testutils.ErrorHere(test, "Failed when unmounting ramdisk device: %s", err)
	}

	// if err = cache.Close(); err != nil {
	// 	ErrorHere(test, "Failed when closing cache: %s", err)
	// }

	// if err = dev.Close(); err != nil {
	// 	ErrorHere(test, "Failed when closing device: %s", err)
	// }
}