diff --git a/pkg/appendable/index_file.go b/pkg/appendable/index_file.go index 20bffca3..56c29b06 100644 --- a/pkg/appendable/index_file.go +++ b/pkg/appendable/index_file.go @@ -54,6 +54,21 @@ func NewIndexFile(f io.ReadWriteSeeker, dataHandler DataHandler) (*IndexFile, er } else if i > 1 { panic("expected to only reset the first page once") } else { + // validate the metadata + buf, err := tree.Metadata() + if err != nil { + return nil, fmt.Errorf("failed to read metadata: %w", err) + } + metadata := &FileMeta{} + if err := metadata.UnmarshalBinary(buf); err != nil { + return nil, fmt.Errorf("failed to unmarshal metadata: %w", err) + } + if metadata.Version != CurrentVersion { + return nil, fmt.Errorf("unsupported version: %d", metadata.Version) + } + if metadata.Format != dataHandler.Format() { + return nil, fmt.Errorf("unsupported format: %x", metadata.Format) + } return &IndexFile{tree: tree, dataHandler: dataHandler}, nil } } diff --git a/pkg/appendable/index_file_test.go b/pkg/appendable/index_file_test.go new file mode 100644 index 00000000..38c2b0f1 --- /dev/null +++ b/pkg/appendable/index_file_test.go @@ -0,0 +1,36 @@ +package appendable + +import ( + "testing" + + "github.com/kevmo314/appendable/pkg/buftest" +) + +type FormatHandler struct{ ReturnsFormat Format } + +func (f FormatHandler) Format() Format { + return f.ReturnsFormat +} + +func (f FormatHandler) Synchronize(f1 *IndexFile, df []byte) error { + return nil +} + +func (f FormatHandler) Parse(data []byte) []byte { + return nil +} + +func TestIndexFile(t *testing.T) { + t.Run("validate metadata throws error if format doesn't match on second read", func(t *testing.T) { + f := buftest.NewSeekableBuffer() + + if _, err := NewIndexFile(f, &FormatHandler{ReturnsFormat: Format(1)}); err != nil { + t.Fatal(err) + } + + // try creating a new index file with a different format + if _, err := NewIndexFile(f, &FormatHandler{ReturnsFormat: Format(2)}); err == nil { + t.Fatal("expected error") + } + }) +}