influxdb/cmd/influxd/inspect/verify_tombstone/verify_tombstone_test.go

173 lines
4.2 KiB
Go

package verify_tombstone
import (
"bytes"
"encoding/binary"
"io"
"os"
"testing"
"github.com/influxdata/influxdb/v2/tsdb/engine/tsm1"
"github.com/stretchr/testify/require"
)
// Tombstone file headers for different versions.
// Treated as v1 without a header.
const (
v2header = 0x1502
v3header = 0x1503
v4header = 0x1504
)
// Run tests on a directory with no Tombstone files
func TestVerifies_InvalidFileType(t *testing.T) {
path, err := os.MkdirTemp("", "verify-tombstone")
require.NoError(t, err)
_, err = os.CreateTemp(path, "verifytombstonetest*"+".txt")
require.NoError(t, err)
defer os.RemoveAll(path)
verify := NewVerifyTombstoneCommand()
verify.SetArgs([]string{"--engine-path", path})
b := bytes.NewBufferString("")
verify.SetOut(b)
require.NoError(t, verify.Execute())
out, err := io.ReadAll(b)
require.NoError(t, err)
require.Contains(t, string(out), "No tombstone files found")
}
// Run tests on an empty Tombstone file (treated as v1)
func TestVerifies_InvalidEmptyFile(t *testing.T) {
path, _ := NewTempTombstone(t)
defer os.RemoveAll(path)
verify := NewVerifyTombstoneCommand()
verify.SetArgs([]string{"--engine-path", path})
b := bytes.NewBufferString("")
verify.SetOut(b)
require.NoError(t, verify.Execute())
out, err := io.ReadAll(b)
require.NoError(t, err)
require.Contains(t, string(out), "has no tombstone entries")
}
// Runs tests on an invalid V2 Tombstone File
func TestVerifies_InvalidV2(t *testing.T) {
path, file := NewTempTombstone(t)
defer os.RemoveAll(path)
WriteTombstoneHeader(t, file, v2header)
WriteBadData(t, file)
verify := NewVerifyTombstoneCommand()
verify.SetArgs([]string{"--engine-path", path})
verify.SetOut(bytes.NewBufferString(""))
require.Error(t, verify.Execute())
}
func TestVerifies_ValidTS(t *testing.T) {
path, file := NewTempTombstone(t)
defer os.RemoveAll(path)
ts := tsm1.NewTombstoner(file.Name(), nil)
require.NoError(t, ts.Add([][]byte{[]byte("foobar")}))
require.NoError(t, ts.Flush())
verify := NewVerifyTombstoneCommand()
verify.SetArgs([]string{"--engine-path", path, "--vv"})
verify.SetOut(bytes.NewBufferString(""))
require.NoError(t, verify.Execute())
}
// Runs tests on an invalid V3 Tombstone File
func TestVerifies_InvalidV3(t *testing.T) {
path, file := NewTempTombstone(t)
defer os.RemoveAll(path)
WriteTombstoneHeader(t, file, v3header)
WriteBadData(t, file)
verify := NewVerifyTombstoneCommand()
verify.SetArgs([]string{"--engine-path", path})
verify.SetOut(bytes.NewBufferString(""))
require.Error(t, verify.Execute())
}
// Runs tests on an invalid V4 Tombstone File
func TestVerifies_InvalidV4(t *testing.T) {
path, file := NewTempTombstone(t)
defer os.RemoveAll(path)
WriteTombstoneHeader(t, file, v4header)
WriteBadData(t, file)
verify := NewVerifyTombstoneCommand()
verify.SetArgs([]string{"--engine-path", path})
verify.SetOut(bytes.NewBufferString(""))
require.Error(t, verify.Execute())
}
// Ensures "--vvv" flag will not error as it
// is not needed, but was part of old command.
func TestTombstone_VeryVeryVerbose(t *testing.T) {
path, file := NewTempTombstone(t)
defer os.RemoveAll(path)
WriteTombstoneHeader(t, file, v4header)
WriteBadData(t, file)
verify := NewVerifyTombstoneCommand()
verify.SetArgs([]string{"--engine-path", path, "--vvv"})
verify.SetOut(bytes.NewBufferString(""))
require.Error(t, verify.Execute())
}
func NewTempTombstone(t *testing.T) (string, *os.File) {
t.Helper()
dir, err := os.MkdirTemp("", "verify-tombstone")
require.NoError(t, err)
file, err := os.CreateTemp(dir, "verifytombstonetest*"+"."+tsm1.TombstoneFileExtension)
require.NoError(t, err)
defer file.Close()
return dir, file
}
func WriteTombstoneHeader(t *testing.T, file *os.File, header uint32) {
t.Helper()
writer, err := os.OpenFile(file.Name(), os.O_RDWR, 0)
require.NoError(t, err)
defer writer.Close()
var b [4]byte
binary.BigEndian.PutUint32(b[:], header)
_, err = writer.Write(b[:])
require.NoError(t, err)
}
func WriteBadData(t *testing.T, file *os.File) {
t.Helper()
writer, err := os.OpenFile(file.Name(), os.O_APPEND|os.O_WRONLY, 0644)
require.NoError(t, err)
defer writer.Close()
written, err := writer.Write([]byte("foobar"))
require.NoError(t, err)
require.Equal(t, 6, written)
}