libgocryptfs/internal/inomap/inomap_test.go
Jakob Unterwurzacher c9b825c58a inomap: deterministically set root device
We used to have "first Translate() wins". This is not deterministic,
as the LOOKUP for the root directory does not seem to reach us, so
the first user LOOKUP would win, which may be on a mountpoint.
2021-09-10 17:17:16 +02:00

156 lines
2.9 KiB
Go

package inomap
import (
"sync"
"testing"
)
func TestTranslate(t *testing.T) {
m := New(0)
q := QIno{Ino: 1}
out := m.Translate(q)
if out != 1 {
t.Errorf("expected 1, got %d", out)
}
q.Ino = maxPassthruIno
out = m.Translate(q)
if out < maxPassthruIno {
t.Errorf("got %d", out)
}
out2 := m.Translate(q)
if out2 != out {
t.Errorf("unstable mapping: %d %d", out2, out)
}
}
func TestTranslateStress(t *testing.T) {
const baseDev = 12345
m := New(baseDev)
var wg sync.WaitGroup
wg.Add(4)
go func() {
// Some normal inode numbers on baseDev
var q QIno
q.Dev = baseDev
for i := uint64(1); i <= 10000; i++ {
q.Ino = i
out := m.Translate(q)
if out != i {
t.Errorf("i=%d out=%d", i, out)
break
}
}
wg.Done()
}()
go func() {
// Very high (>maxPassthruIno) inode numbers on baseDev
var q QIno
q.Dev = baseDev
for i := uint64(1); i <= 10000; i++ {
q.Ino = maxPassthruIno + i
out := m.Translate(q)
if out < maxPassthruIno {
t.Errorf("out=%d", out)
break
}
}
wg.Done()
}()
go func() {
// Device 9999999
var q QIno
q.Dev = 9999999
for i := uint64(1); i <= 10000; i++ {
q.Ino = i
out := m.Translate(q)
if out < maxPassthruIno {
t.Errorf("out=%d", out)
break
}
}
wg.Done()
}()
go func() {
// Device 4444444
var q QIno
q.Dev = 4444444
for i := uint64(1); i <= 10000; i++ {
q.Ino = i
out := m.Translate(q)
if out < maxPassthruIno {
t.Errorf("out=%d", out)
break
}
}
wg.Done()
}()
wg.Wait()
if len(m.spillMap) != 10000 {
t.Errorf("len=%d", len(m.spillMap))
}
if len(m.namespaceMap) != 3 {
t.Errorf("len=%d", len(m.namespaceMap))
}
}
func TestSpill(t *testing.T) {
m := New(0)
var q QIno
q.Ino = maxPassthruIno + 1
out1 := m.Translate(q)
if out1&spillBit == 0 {
t.Error("spill bit not set")
}
out2 := m.Translate(q)
if out2&spillBit == 0 {
t.Error("spill bit not set")
}
if out1 != out2 {
t.Errorf("unstable mapping: %d vs %d", out1, out2)
}
}
// TestUniqueness checks that unique (Dev, Flags, Ino) tuples get unique inode
// numbers
func TestUniqueness(t *testing.T) {
m := New(0)
var q QIno
outMap := make(map[uint64]struct{})
for q.Dev = 0; q.Dev < 10; q.Dev++ {
for q.Tag = 0; q.Tag < 10; q.Tag++ {
// some go into spill
for q.Ino = maxPassthruIno - 100; q.Ino < maxPassthruIno+100; q.Ino++ {
out := m.Translate(q)
_, found := outMap[out]
if found {
t.Fatalf("inode number %d already used", out)
}
outMap[out] = struct{}{}
}
}
}
if len(outMap) != 10*10*200 {
t.Errorf("%d", len(outMap))
}
}
func BenchmarkTranslateSingleDev(b *testing.B) {
m := New(0)
var q QIno
for n := 0; n < b.N; n++ {
q.Ino = uint64(n % 1000)
m.Translate(q)
}
}
func BenchmarkTranslateManyDevs(b *testing.B) {
m := New(0)
var q QIno
for n := 0; n < b.N; n++ {
q.Dev = uint64(n % 10)
q.Ino = uint64(n % 1000)
m.Translate(q)
}
}