Add test for the weird remapping/cache interaction.

This test is really a test of a very specific bit of the internals
of containers_btree/containers_slice, but we can't easily test it from
there because they don't have all the logic for remapping files.

The underlying issue is that they maintain a single-item "most recent
container" cache, and this wasn't getting updated during the remap
operations, happening through containers.UpdateEvery. The fix is
probably just to make sure that UpdateEvery invalidates the cache.
This commit is contained in:
Seebs 2020-03-31 11:36:24 -05:00
parent d26e221a91
commit 1ac00291f3

View file

@ -25,6 +25,8 @@ import (
"math/rand"
"os"
"reflect"
"runtime"
"runtime/debug"
"sort"
"sync/atomic"
"testing"
@ -3583,6 +3585,60 @@ func TestFragmentConcurrentReadWrite(t *testing.T) {
t.Logf("%d", acc)
}
func TestRemapCache(t *testing.T) {
f := mustOpenFragment("i", "f", viewStandard, 0, "")
// request a panic that doesn't kill the program on fault
wouldFault := debug.SetPanicOnFault(true)
defer func() {
debug.SetPanicOnFault(wouldFault)
if r := recover(); r != nil {
if err, ok := r.(error); ok {
// special case: if we caught a page fault, we diagnose that directly. sadly,
// we can't see the actual values that were used to generate this, probably.
if err.Error() == "runtime error: invalid memory address or nil pointer dereference" {
t.Fatalf("segfault trapped during remap test (expected failure mode)")
}
}
t.Fatalf("unexpected panic: %v", r)
}
}()
// create a container
_, err := f.storage.Add(65537)
if err != nil {
t.Fatalf("storage add: %v", err)
}
// cause the container to be mapped
err = f.Snapshot()
if err != nil {
t.Fatalf("storage snapshot: %v", err)
}
// freeze the row
_ = f.row(0)
// add a bit that isn't in that container, so that container doesn't
// change
_, err = f.storage.Add(2)
if err != nil {
t.Fatalf("storage add: %v", err)
}
// make the original container be the most recent, thus cached, container
_, err = f.bit(0, 65537)
if err != nil {
t.Fatalf("storage bit check: %v", err)
}
// force snapshot, remapping the containers
err = f.Snapshot()
if err != nil {
t.Fatalf("storage snapshot: %v", err)
}
// get rid of the old mapping
runtime.GC()
// try to read that container again
_, err = f.bit(0, 65537)
if err != nil {
t.Fatalf("storage bit check: %v", err)
}
}
func TestFragment_Bug_Q2DoubleDelete(t *testing.T) {
f := mustOpenFragment("i", "f", viewStandard, 0, "")
b := []byte{60, 48, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 24, 0, 0, 0, 1, 0}