예제 #1
0
func TestNewLog(t *testing.T) {

	mockfile := tests.NewMockFile()
	seeklen := int64(16 * 4096)
	mockfile.MockSeek = func(offset int64, whence int) (int64, error) {
		return seeklen, nil
	}

	// Mock openFile
	defer tests.Patch(&openFile,
		func(name string, flag int, perm os.FileMode) (Filer, error) {
			return mockfile, nil
		}).Restore()

	// Simple log
	l, blocks, err := NewLog("file", 4096, 4, 4096*2, false)
	tests.Assert(t, err == nil)
	tests.Assert(t, l != nil)
	tests.Assert(t, blocks == 16)
	l.Close()

	// Check the log correctly return maximum number of
	// blocks that are aligned to the segments.
	// 17 blocks are not aligned to a segment with 4 blocks
	// per segment
	seeklen = 17 * 4096
	l, blocks, err = NewLog("file", 4096, 4, 4096*2, false)
	tests.Assert(t, err == nil)
	tests.Assert(t, l != nil)
	tests.Assert(t, blocks == 16)
	l.Close()
}
예제 #2
0
func TestAsuOpenFile(t *testing.T) {
	usedirectio := true
	asu := NewAsu(usedirectio)
	mockfile := tests.NewMockFile()
	mockerror := errors.New("Test Error")

	directio_set := false

	// Mock openFile
	defer tests.Patch(&openFile,
		func(name string, flag int, perm os.FileMode) (Filer, error) {
			directio_set = false
			if (flag & cache.OSSYNC) == cache.OSSYNC {
				directio_set = true
			}

			return mockfile, mockerror
		}).Restore()

	// Call
	err := asu.Open("filename")

	// Check results
	tests.Assert(t, directio_set == true)
	tests.Assert(t, err == mockerror)

	// Now try without directio set
	usedirectio = false
	asu = NewAsu(usedirectio)

	// Check results
	err = asu.Open("filename")
	tests.Assert(t, directio_set == false)
	tests.Assert(t, err == mockerror)
}
예제 #3
0
func TestAsuOpenSeek(t *testing.T) {
	usedirectio := true
	asu := NewAsu(usedirectio)
	mockfile := tests.NewMockFile()

	seeklen := int64(0)
	mockerror := errors.New("Test Error")
	seekerror := error(nil)
	mockfile.MockSeek = func(offset int64, whence int) (int64, error) {
		return seeklen, seekerror
	}

	// Mock openFile
	defer tests.Patch(&openFile,
		func(name string, flag int, perm os.FileMode) (Filer, error) {
			return mockfile, nil
		}).Restore()

	// Seek will return len of 0
	err := asu.Open("filename")
	tests.Assert(t, err != nil)
	tests.Assert(t, len(asu.fps) == 0)

	// Seek will return error
	seekerror = mockerror
	err = asu.Open("filename")
	tests.Assert(t, err != nil)
	tests.Assert(t, err == mockerror)
	tests.Assert(t, len(asu.fps) == 0)

	// Seek will return correct data
	seeklen = int64(4 * KB * 100)
	asublocks := uint32(seeklen / (4 * KB))
	seekerror = nil
	err = asu.Open("filename")
	tests.Assert(t, err == nil)
	tests.Assert(t, len(asu.fps) == 1)
	tests.Assert(t, asu.len == asublocks)

	// Now add a larger file, but it should
	// only add the min() size of the files opened
	seeklen = int64(4 * KB * 110)
	asublocks += asublocks
	err = asu.Open("filename")
	tests.Assert(t, err == nil)
	tests.Assert(t, len(asu.fps) == 2)
	tests.Assert(t, asu.len == asublocks)

	// Now add a smaller file, but it should
	// only add the min() size of the files opened
	seeklen = int64(4 * KB * 50)
	asublocks = 50 * 3
	err = asu.Open("filename")
	tests.Assert(t, err == nil)
	tests.Assert(t, len(asu.fps) == 3)
	tests.Assert(t, asu.len == asublocks)

}
예제 #4
0
func TestLogMultiBlock(t *testing.T) {

	// 256 blocks available in the log
	seeklen := int64(256 * 4096)

	// Setup Mockfile
	mockfile := tests.NewMockFile()
	mockfile.MockSeek = func(offset int64, whence int) (int64, error) {
		return seeklen, nil
	}

	mock_byteswritten := 0
	mock_written := 0
	mock_off_written := int64(0)
	continue_test := make(chan bool, 1)
	mockfile.MockWriteAt = func(p []byte, off int64) (n int, err error) {
		mock_written++
		mock_off_written = off
		mock_byteswritten += len(p)
		continue_test <- true
		return len(p), nil
	}

	mock_bytesread := 0
	mock_read := 0
	mock_off_read := int64(0)
	mockfile.MockReadAt = func(p []byte, off int64) (n int, err error) {
		mock_read++
		mock_off_read = off
		mock_bytesread += len(p)
		continue_test <- true
		return len(p), nil
	}

	// Mock openFile
	defer tests.Patch(&openFile,
		func(name string, flag int, perm os.FileMode) (Filer, error) {
			return mockfile, nil
		}).Restore()

	// Simple log
	l, blocks, err := NewLog("file", 4096, 4, 0, false)
	tests.Assert(t, err == nil)
	tests.Assert(t, l != nil)
	tests.Assert(t, blocks == 256)
	l.Start()

	// Send 8 blocks
	here := make(chan *message.Message)
	m := message.NewMsgPut()
	iopkt := m.IoPkt()
	m.RetChan = here
	iopkt.Buffer = make([]byte, 8*4096)
	iopkt.Blocks = 8

	for block := uint32(0); block < iopkt.Blocks; block++ {
		child := message.NewMsgPut()
		m.Add(child)

		child_io := child.IoPkt()
		child_io.Address = iopkt.Address + uint64(block)
		child_io.Buffer = SubBlockBuffer(iopkt.Buffer, 4096, block, 1)
		child_io.LogBlock = block
		child_io.Blocks = 1

		l.Msgchan <- child
	}

	m.Done()
	<-here
	<-continue_test

	tests.Assert(t, mock_byteswritten == 4*4096)
	tests.Assert(t, mock_written == 1)
	tests.Assert(t, mock_off_written == 0)
	tests.Assert(t, mock_read == 0)
	tests.Assert(t, len(continue_test) == 0)

	// At this point we have 4 blocks written to the log storage
	// and 4 blocks in the current segment.

	// Read log blocks 0-3
	m = message.NewMsgGet()
	iopkt = m.IoPkt()
	m.RetChan = here
	iopkt.Blocks = 4
	iopkt.Buffer = make([]byte, 4*4096)
	iopkt.LogBlock = 0

	mock_written = 0
	mock_byteswritten = 0
	l.Msgchan <- m
	<-here
	<-continue_test

	tests.Assert(t, mock_byteswritten == 0)
	tests.Assert(t, mock_written == 0)
	tests.Assert(t, mock_read == 1)
	tests.Assert(t, mock_bytesread == 4*4096)
	tests.Assert(t, mock_off_read == 0)
	tests.Assert(t, len(continue_test) == 0)

	// Now read log blocks 1,2,3,4,5.  Blocks 1,2,3 will be on the storage
	// device, and blocks 4,5 will be in ram
	m = message.NewMsgGet()
	iopkt = m.IoPkt()
	m.RetChan = here
	iopkt.Blocks = 5
	iopkt.Buffer = make([]byte, 5*4096)
	iopkt.LogBlock = 1

	mock_written = 0
	mock_byteswritten = 0
	mock_bytesread = 0
	mock_read = 0
	l.Msgchan <- m
	<-here
	<-continue_test

	tests.Assert(t, mock_byteswritten == 0)
	tests.Assert(t, mock_written == 0)
	tests.Assert(t, mock_read == 1)
	tests.Assert(t, mock_bytesread == 3*4096)
	tests.Assert(t, mock_off_read == 1*4096)
	tests.Assert(t, len(continue_test) == 0)

	// Cleanup
	l.Close()
}
예제 #5
0
func TestAsuIoAt(t *testing.T) {

	usedirectio := true
	asu := NewAsu(usedirectio)

	// Setup Head - 10 4k blocks
	head := tests.NewMockFile()
	head.MockSeek = func(offset int64, whence int) (int64, error) {
		return 10 * 4 * KB, nil
	}

	var (
		head_check_p_len  int
		head_check_offset int64
		head_called       bool
	)
	head.MockReadAt = func(p []byte, off int64) (n int, err error) {
		tests.Assert(t, len(p) == head_check_p_len)
		tests.Assert(t, head_check_offset == off)
		head_called = true

		return len(p), nil
	}
	head.MockWriteAt = func(p []byte, off int64) (n int, err error) {
		tests.Assert(t, len(p) == head_check_p_len)
		tests.Assert(t, head_check_offset == off)
		head_called = true

		return len(p), nil
	}

	// Setup Tail - 12 4K blocks
	tail := tests.NewMockFile()
	tail.MockSeek = func(offset int64, whence int) (int64, error) {
		return 12 * 4 * KB, nil
	}

	var (
		tail_check_p_len  int
		tail_check_offset int64
		tail_called       bool
	)
	tail.MockReadAt = func(p []byte, off int64) (n int, err error) {
		tests.Assert(t, len(p) == tail_check_p_len)
		tests.Assert(t, tail_check_offset == off)
		tail_called = true

		return len(p), nil
	}
	tail.MockWriteAt = func(p []byte, off int64) (n int, err error) {
		tests.Assert(t, len(p) == tail_check_p_len)
		tests.Assert(t, tail_check_offset == off)
		tail_called = true

		return len(p), nil
	}

	// Mock openFile
	defer tests.Patch(&openFile,
		func(name string, flag int, perm os.FileMode) (Filer, error) {
			if name == "head" {
				return head, nil
			} else {
				return tail, nil
			}
		}).Restore()

	// Open files
	err := asu.Open("head")
	tests.Assert(t, err == nil)
	err = asu.Open("tail")
	tests.Assert(t, err == nil)

	// Write small, it should not over flow into file2
	small := make([]byte, 4*KB)
	head_check_offset = 4 * KB
	head_check_p_len = len(small)
	tail_called = false
	head_called = false
	n, err := asu.WriteAt(small, 4*KB)
	tests.Assert(t, n == len(small))
	tests.Assert(t, err == nil)
	tests.Assert(t, head_called == true)
	tests.Assert(t, tail_called == false)

	// Write large buffer.  It should only write
	// to the first file since it the buffer is exactly
	// the same size as the size of the file.
	large := make([]byte, 10*4*KB)
	head_check_offset = 0
	head_check_p_len = 10 * 4 * KB
	tail_check_offset = 0
	tail_check_p_len = 0
	tail_called = false
	head_called = true
	n, err = asu.WriteAt(large, 0)
	tests.Assert(t, n == len(large))
	tests.Assert(t, err == nil)
	tests.Assert(t, head_called == true)
	tests.Assert(t, tail_called == false)

	// Write large, should go across files
	head_check_offset = 1 * 4 * KB
	head_check_p_len = 9 * 4 * KB
	tail_check_offset = 0
	tail_check_p_len = 1 * 4 * KB
	tail_called = false
	head_called = false
	n, err = asu.WriteAt(large, 4*KB)
	tests.Assert(t, n == len(large))
	tests.Assert(t, err == nil)
	tests.Assert(t, head_called == true)
	tests.Assert(t, tail_called == true)

	// Repeat with ReadAt
	// Read small, it should not over flow into file2
	head_check_offset = 4 * KB
	head_check_p_len = len(small)
	tail_called = false
	head_called = false
	n, err = asu.ReadAt(small, 4*KB)
	tests.Assert(t, n == len(small))
	tests.Assert(t, err == nil)
	tests.Assert(t, head_called == true)
	tests.Assert(t, tail_called == false)

	// Write large, should go across files
	head_check_offset = 9 * 4 * KB
	head_check_p_len = 1 * 4 * KB
	tail_check_offset = 0
	tail_check_p_len = 9 * 4 * KB
	tail_called = false
	head_called = false
	n, err = asu.ReadAt(large, 9*4*KB)
	tests.Assert(t, n == len(large))
	tests.Assert(t, err == nil)
	tests.Assert(t, head_called == true)
	tests.Assert(t, tail_called == true)
}
예제 #6
0
func TestSpcContextQuit(t *testing.T) {

	// initialize
	var cache *cache.CacheMap
	usedirectio := false
	blocksize := 4 * KB
	s := NewSpcInfo(cache, usedirectio, blocksize)

	// Setup Mockfile
	mockfile := tests.NewMockFile()
	seeklen := int64(4 * 1024 * 1024 * 1024)
	mockfile.MockSeek = func(offset int64, whence int) (int64, error) {
		return seeklen, nil
	}

	// Mock openfile
	defer tests.Patch(&openFile,
		func(name string, flag int, perm os.FileMode) (Filer, error) {
			return mockfile, nil
		}).Restore()

	// Open files
	err := s.Open(1, "asu1file")
	tests.Assert(t, err == nil)
	err = s.Open(2, "asu2file")
	tests.Assert(t, err == nil)
	err = s.Open(3, "asu3file")
	tests.Assert(t, err == nil)

	// Initialize
	bsu := 50
	contexts := 1
	err = s.Spc1Init(bsu, contexts)
	tests.Assert(t, err == nil)

	// Setup channel for Context() subroutines
	// to send stats back
	iotime := make(chan *IoStats)

	// 60 secs, but we will send a quit signal
	runlen := 60

	teststart := time.Now()

	// Create context goroutine
	var wg sync.WaitGroup
	wg.Add(1)
	quit := make(chan struct{})
	go s.Context(&wg, iotime, quit, runlen, contexts)

	// Create a go routine to get stats
	// from channel
	var iostatwg sync.WaitGroup
	iostatwg.Add(1)
	go func() {
		defer iostatwg.Done()

		for iostat := range iotime {
			if iostat == nil {
				t.Error("iostat is nil")
			}
			if iostat.Io == nil {
				t.Errorf("iostat return nil Io")
			}
			if iostat.Start.Before(teststart) {
				t.Errorf("iostat returned a time in the past")
			}
		}
	}()

	// Wait a bit
	time.Sleep(time.Second)

	// Send the quit signal
	close(quit)

	// Wait here for Context() to finish
	wg.Wait()
	end := time.Now()

	// Shutdown iotime channel reader
	close(iotime)
	iostatwg.Wait()

	// These are quite big, but just in case a test framework
	// is very busy
	tests.Assert(t, end.Sub(teststart).Seconds() < 5)
	tests.Assert(t, end.Sub(teststart).Seconds() > 1)

	// Cleanup
	s.Close()

}