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) }
func TestIoMeterDeltas(t *testing.T) { prev := &IoMeter{ Ios: 1000, Blocks: 5000, } prev.Latency.Add(time.Millisecond) prev.Latency.Add(time.Millisecond) prev.Latency.Add(time.Millisecond) prev.Latency.Add(time.Millisecond) meter := &IoMeter{} *meter = *prev meter.Ios += 500 meter.Blocks += 500 meter.Latency.Add(time.Millisecond * 2) meter.Latency.Add(time.Millisecond * 2) meter.Latency.Add(time.Millisecond * 2) meter.Latency.Add(time.Millisecond * 2) // Test Accessors tests.Assert(t, meter.MeanLatencyDeltaUsecs(prev) == 2000.0) tests.Assert(t, meter.IosDelta(prev) == 500) tests.Assert(t, meter.MeanLatencyUsecs() == 1500.0) }
func TestNullPipeline(t *testing.T) { destination := make(chan *Message) pipe := make(chan *Message) np := NewNullPipeline(pipe) defer np.Close() np.Start() m := &Message{ Type: MsgPut, RetChan: destination, } // Send message np.In <- m // Pipe should be the first to see it returnedmsg := <-pipe tests.Assert(t, returnedmsg == m) // Now we finish the message m.Done() // It should arrive at destination returnedmsg = <-destination tests.Assert(t, returnedmsg == m) }
func TestInvalidateMultipleBlocks(t *testing.T) { nc := message.NewNullTerminator() nc.Start() defer nc.Close() c := NewCacheMap(8, 4096, nc.In) tests.Assert(t, c != nil) defer c.Close() // Insert some values in the addressmap for i := uint32(0); i < 4; i++ { // The key is block number c.addressmap[uint64(i)] = i } // This value should still be on the addressmap c.addressmap[8] = 8 iopkt := &message.IoPkt{ Address: 0, Blocks: 8, } c.Invalidate(iopkt) tests.Assert(t, c.stats.invalidations == uint64(iopkt.Blocks)) tests.Assert(t, c.stats.invalidatehits == 4) tests.Assert(t, c.addressmap[8] == 8) }
func TestNewSpcStats(t *testing.T) { s := NewSpcStats() tests.Assert(t, len(s.Asustats) == 3) tests.Assert(t, s.Asustats[ASU1] != nil) tests.Assert(t, s.Asustats[ASU2] != nil) tests.Assert(t, s.Asustats[ASU3] != nil) }
func TestNullNewTerminator(t *testing.T) { np := NewNullTerminator() defer np.Close() tests.Assert(t, np.In != nil) tests.Assert(t, len(np.In) == 0) tests.Assert(t, np.Out == nil) }
func TestNullNewPipeline(t *testing.T) { out := make(chan *Message) np := NewNullPipeline(out) defer np.Close() tests.Assert(t, np.In != nil) tests.Assert(t, len(np.In) == 0) tests.Assert(t, np.Out == out) }
func TestRamHitRate(t *testing.T) { s := &logstats{} ls := s.Stats() tests.Assert(t, ls.RamHitRate() == 0.0) s.ramhits = 100 s.totalhits = 200 ls = s.Stats() tests.Assert(t, ls.RamHitRate() == 0.5) }
func TestCacheStatsRates(t *testing.T) { s := &cachestats{} stats1 := s.stats() stats2 := s.stats() tests.Assert(t, stats1.ReadHitRate() == 0.0) tests.Assert(t, stats1.InvalidateHitRate() == 0.0) tests.Assert(t, stats1.ReadHitRateDelta(stats2) == 0.0) tests.Assert(t, stats1.InvalidateHitRateDelta(stats2) == 0.0) }
func TestIoPktString(t *testing.T) { m := NewMsgGet() iopkt := m.IoPkt() s := iopkt.String() tests.Assert(t, strings.Contains(s, "Address")) tests.Assert(t, strings.Contains(s, "LogBlock")) tests.Assert(t, strings.Contains(s, "Blocks")) }
func TestBufferHitRate(t *testing.T) { s := &logstats{} ls := s.Stats() tests.Assert(t, ls.BufferHitRate() == 0.0) s.bufferhits = 100 s.totalhits = 200 ls = s.Stats() tests.Assert(t, ls.BufferHitRate() == 0.5) }
func TestCacheStatsJson(t *testing.T) { s := &cachestats{ readhits: 1, invalidatehits: 12, reads: 123, evictions: 1234, invalidations: 12345, insertions: 123456, } // Encode exportedstats := s.stats() jsonstats, err := json.Marshal(exportedstats) tests.Assert(t, err == nil) // Decode and check with original decstats := &CacheStats{} err = json.Unmarshal(jsonstats, &decstats) tests.Assert(t, err == nil) tests.Assert(t, reflect.DeepEqual(decstats, exportedstats)) tests.Assert(t, s.readhits == decstats.Readhits) tests.Assert(t, s.invalidatehits == decstats.Invalidatehits) tests.Assert(t, s.reads == decstats.Reads) tests.Assert(t, s.evictions == decstats.Evictions) tests.Assert(t, s.invalidations == decstats.Invalidations) tests.Assert(t, s.insertions == decstats.Insertions) }
func TestCacheStatsCsvDelta(t *testing.T) { s1 := &cachestats{ readhits: 1, invalidatehits: 12, reads: 123, evictions: 1234, invalidations: 12345, insertions: 123456, } s2 := &cachestats{ readhits: 12, invalidatehits: 123, reads: 1234, evictions: 12345, invalidations: 123456, insertions: 1234567, } stats1 := s1.stats() stats2 := s2.stats() slice := strings.Split(stats2.CsvDelta(stats1), ",") // 8 elements per csv line + the empty tests.Assert(t, len(slice) == 9) tests.Assert(t, slice[0] == fmt.Sprintf("%v", stats2.ReadHitRateDelta(stats1))) tests.Assert(t, slice[1] == fmt.Sprintf("%v", stats2.InvalidateHitRateDelta(stats1))) tests.Assert(t, slice[2] == strconv.FormatUint(s2.readhits-s1.readhits, 10)) tests.Assert(t, slice[3] == strconv.FormatUint(s2.invalidatehits-s1.invalidatehits, 10)) tests.Assert(t, slice[4] == strconv.FormatUint(s2.reads-s1.reads, 10)) tests.Assert(t, slice[5] == strconv.FormatUint(s2.insertions-s1.insertions, 10)) tests.Assert(t, slice[6] == strconv.FormatUint(s2.evictions-s1.evictions, 10)) tests.Assert(t, slice[7] == strconv.FormatUint(s2.invalidations-s1.invalidations, 10)) }
func TestInvalidateIoPkt(t *testing.T) { c := make(chan *Message) m := NewMsgGet() m.RetChan = c iopkt := m.IoPkt() tests.Assert(t, iopkt.LogBlock == 0) tests.Assert(t, iopkt.Buffer == nil) tests.Assert(t, iopkt.Address == 0) tests.Assert(t, m.RetChan == c) tests.Assert(t, m.Type == MsgGet) }
func TestAddressUtils(t *testing.T) { a := Address{ Devid: 9876, Block: 123456789, } merged := Address64(a) converted := AddressValue(merged) tests.Assert(t, a.Devid == converted.Devid) tests.Assert(t, a.Block == converted.Block) }
func TestMsgIoDone(t *testing.T) { // Channel to send worker := make(chan *Message) // Return channel backhere := make(chan *Message) // Message m := NewMsgPut() m.Priv = &Data{i: 1} m.RetChan = backhere // Start 'work' service go func() { // Wait for work msg := <-worker d := msg.Priv.(*Data) io := msg.IoPkt() io.Buffer = []byte("TESTSTRING") tests.Assert(t, msg.Type == MsgPut) tests.Assert(t, d.i == 1) // Increment the offset here to test d.i += 1 // Return to channel msg.Done() }() // Send to 'work' worker <- m // Wait until it is done rm := <-backhere // Get the data newD := rm.Priv.(*Data) io := rm.IoPkt() // Check results tests.Assert(t, newD.i == 2) tests.Assert(t, string(io.Buffer) == "TESTSTRING") }
func TestIoMeterCsvDelta(t *testing.T) { spc1info := &spc1.Spc1Io{ Asu: 1, Blocks: 1, Stream: 2, Offset: 123456, When: time.Second * 2, } stat := &IoStats{ Io: spc1info, Start: time.Now(), Latency: time.Millisecond * 3, } // Inster first data point meter := &IoMeter{} meter.Collect(stat) tests.Assert(t, meter.Blocks == 1) tests.Assert(t, meter.Ios == 1) tests.Assert(t, meter.Latency.MeanTimeUsecs() == 3000.0) prev := &IoMeter{} s := meter.CsvDelta(prev, time.Millisecond) split := strings.Split(s, ",") tests.Assert(t, split[0] == "1") tests.Assert(t, split[1] == "4096") tests.Assert(t, strings.Contains(split[2], "3.9")) tests.Assert(t, strings.Contains(split[3], "3000")) }
func TestAsuSize(t *testing.T) { usedirectio := false asu := NewAsu(usedirectio) // set fake length asu.len = 1234 * GB / (4 * KB) tests.Assert(t, float64(1234) == asu.Size()) }
func TestNewCacheMap(t *testing.T) { nc := message.NewNullTerminator() nc.Start() defer nc.Close() c := NewCacheMap(8, 4096, nc.In) tests.Assert(t, c != nil) c.Close() }
func TestLogStatsSegmentReadTimeRecord(t *testing.T) { s := &logstats{} s.SegmentReadTimeRecord(50 * 1000) s.SegmentReadTimeRecord(50 * 1000) tests.Assert(t, s.readtime.MeanTimeUsecs() == 0.0) tests.Assert(t, s.segmentreadtime.MeanTimeUsecs() == 50.0) tests.Assert(t, s.writetime.MeanTimeUsecs() == 0.0) tests.Assert(t, s.ramhits == 0) tests.Assert(t, s.storagehits == 0) tests.Assert(t, s.wraps == 0) tests.Assert(t, s.seg_skipped == 0) tests.Assert(t, s.bufferhits == 0) tests.Assert(t, s.totalhits == 0) }
func TestUsing(t *testing.T) { bda := NewBlockDescriptorArray(2) id := uint64(123) index, evictkey, evict := bda.Insert(id) tests.Assert(t, bda.bds[0].key == id) tests.Assert(t, bda.bds[0].clock_set == false) tests.Assert(t, bda.bds[0].used == true) tests.Assert(t, index == 0) tests.Assert(t, evictkey == INVALID_KEY) tests.Assert(t, evict == false) bda.Using(index) tests.Assert(t, bda.bds[0].key == id) tests.Assert(t, bda.bds[0].clock_set == true) tests.Assert(t, bda.bds[0].used == true) }
// Should wrap four times func TestWrapPut(t *testing.T) { // Simple log blocks := uint32(16) testcachefile := tests.Tempfile() err := tests.CreateFile(testcachefile, 16*4096) tests.Assert(t, nil == err) defer os.Remove(testcachefile) l, logblocks, err := NewLog(testcachefile, 4096, 2, 4096*2, false) tests.Assert(t, err == nil) tests.Assert(t, l != nil) tests.Assert(t, blocks == logblocks) l.Start() here := make(chan *message.Message) wraps := uint32(4) // Write enough blocks to wrap around the log // as many times as determined by the value in 'wraps' for io := uint32(0); io < (blocks * wraps); io++ { buf := make([]byte, 4096) buf[0] = byte(io) msg := message.NewMsgPut() msg.RetChan = here iopkt := msg.IoPkt() iopkt.Buffer = buf iopkt.LogBlock = io % blocks l.Msgchan <- msg <-here } // Close will also empty all the channels l.Close() // Check that we have wrapped the correct number of times tests.Assert(t, l.Stats().Wraps == uint64(wraps)) }
func TestIoMeterCollect(t *testing.T) { spc1info := &spc1.Spc1Io{ Asu: 1, Blocks: 1, Stream: 2, Offset: 123456, When: time.Second * 2, } stat := &IoStats{ Io: spc1info, Start: time.Now(), Latency: time.Millisecond * 3, } // Inster first data point meter := &IoMeter{} meter.Collect(stat) tests.Assert(t, meter.Blocks == 1) tests.Assert(t, meter.Ios == 1) tests.Assert(t, meter.Latency.MeanTimeUsecs() == 3000.0) // Inster second data point spc1info.Blocks = 4 stat.Latency = time.Millisecond meter.Collect(stat) tests.Assert(t, meter.Blocks == 5) tests.Assert(t, meter.Ios == 2) tests.Assert(t, meter.Latency.MeanTimeUsecs() == 2000.0) }
func TestAsuStatCollect(t *testing.T) { spc1info := &spc1.Spc1Io{ Asu: 1, Blocks: 1, Isread: true, Stream: 2, Offset: 123456, When: time.Second * 2, } stat := &IoStats{ Io: spc1info, Start: time.Now(), Latency: time.Millisecond * 3, } asumeter := &AsuStats{} asumeter.Collect(stat) tests.Assert(t, asumeter.Read.Blocks == 1) tests.Assert(t, asumeter.Write.Blocks == 0) tests.Assert(t, asumeter.Total.Blocks == 1) // Inster second data point spc1info.Blocks = 4 spc1info.Isread = false stat.Latency = time.Millisecond asumeter.Collect(stat) tests.Assert(t, asumeter.Read.Blocks == 1) tests.Assert(t, asumeter.Write.Blocks == 4) tests.Assert(t, asumeter.Total.Blocks == 5) }
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() }
func TestNewSpcInfo(t *testing.T) { var cache *cache.CacheMap usedirectio := false blocksize := 4 * KB s := NewSpcInfo(cache, usedirectio, blocksize) tests.Assert(t, s.pblcache == cache) tests.Assert(t, s.blocksize == blocksize) tests.Assert(t, len(s.asus) == 3) tests.Assert(t, nil != s.asus[ASU1]) tests.Assert(t, nil != s.asus[ASU2]) tests.Assert(t, nil != s.asus[ASU3]) tests.Assert(t, usedirectio == s.asus[ASU1].usedirectio) tests.Assert(t, usedirectio == s.asus[ASU2].usedirectio) tests.Assert(t, usedirectio == s.asus[ASU3].usedirectio) }
func TestSpcStatsCopy(t *testing.T) { s := NewSpcStats() c := s.Copy() tests.Assert(t, len(c.Asustats) == 3) tests.Assert(t, c.Asustats[ASU1] != nil) tests.Assert(t, c.Asustats[ASU2] != nil) tests.Assert(t, c.Asustats[ASU3] != nil) tests.Assert(t, c.Asustats[ASU1] != s.Asustats[ASU1]) tests.Assert(t, c.Asustats[ASU2] != s.Asustats[ASU2]) tests.Assert(t, c.Asustats[ASU3] != s.Asustats[ASU3]) }
func TestSpcOpen(t *testing.T) { // initialize var cache *cache.CacheMap usedirectio := false blocksize := 4 * KB s := NewSpcInfo(cache, usedirectio, blocksize) // Get a test file tmpfile := tests.Tempfile() // No file exists err := s.Open(1, tmpfile) tests.Assert(t, err != nil) // Create the file and open it err = tests.CreateFile(tmpfile, 16*4*KB) tests.Assert(t, err == nil) defer os.Remove(tmpfile) // Now open, and it should work err = s.Open(1, tmpfile) tests.Assert(t, err == nil) }
func TestCacheStatsInsertions(t *testing.T) { s := cachestats{} s.insertion() tests.Assert(t, s.readhits == 0) tests.Assert(t, s.invalidatehits == 0) tests.Assert(t, s.reads == 0) tests.Assert(t, s.evictions == 0) tests.Assert(t, s.invalidations == 0) tests.Assert(t, s.insertions == 1) }
func TestLogStatsWrapped(t *testing.T) { s := &logstats{} s.Wrapped() tests.Assert(t, s.ramhits == 0) tests.Assert(t, s.storagehits == 0) tests.Assert(t, s.wraps == 1) tests.Assert(t, s.seg_skipped == 0) tests.Assert(t, s.bufferhits == 0) tests.Assert(t, s.totalhits == 0) }