Files
containerd/plugins/diff/erofs/dmverity_linux_test.go
2026-03-31 20:21:39 +00:00

129 lines
4.5 KiB
Go

//go:build linux
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package erofs
import (
"context"
"os"
"path/filepath"
"testing"
"github.com/containerd/log/logtest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/containerd/containerd/v2/internal/dmverity"
)
// TestGetDmverityOptions tests the block size configuration
func TestGetDmverityOptions(t *testing.T) {
// tar-index mode uses 512-byte blocks
opts := (&erofsDiff{enableTarIndex: true, enableDmverity: true}).getDmverityOptions()
assert.Equal(t, uint32(512), opts.DataBlockSize)
assert.Equal(t, uint32(512), opts.HashBlockSize)
// regular mode uses 4096-byte blocks
opts = (&erofsDiff{enableTarIndex: false, enableDmverity: true}).getDmverityOptions()
assert.Equal(t, uint32(4096), opts.DataBlockSize)
assert.Equal(t, uint32(4096), opts.HashBlockSize)
}
// TestFormatDmverityLayer tests the layer formatting logic
func TestFormatDmverityLayer(t *testing.T) {
supported, err := dmverity.IsSupported()
if err != nil || !supported {
t.Skip("dm-verity is not supported on this system")
}
ctx := logtest.WithT(context.Background(), t)
tmpDir := t.TempDir()
t.Run("formats layer and creates metadata", func(t *testing.T) {
d := &erofsDiff{enableDmverity: true, enableTarIndex: false}
layerPath := filepath.Join(tmpDir, "layer.erofs")
require.NoError(t, os.WriteFile(layerPath, make([]byte, 8192), 0644))
require.NoError(t, d.formatDmverityLayer(ctx, layerPath))
metadata, err := dmverity.ReadMetadata(layerPath)
require.NoError(t, err)
assert.NotEmpty(t, metadata.RootHash)
assert.Greater(t, metadata.HashOffset, uint64(0))
assert.Equal(t, uint64(8192), metadata.HashOffset)
})
t.Run("skips formatting if metadata already exists", func(t *testing.T) {
d := &erofsDiff{enableDmverity: true, enableTarIndex: false}
layerPath := filepath.Join(tmpDir, "layer-idempotent.erofs")
require.NoError(t, os.WriteFile(layerPath, make([]byte, 8192), 0644))
// First format
require.NoError(t, d.formatDmverityLayer(ctx, layerPath))
metadata1, _ := dmverity.ReadMetadata(layerPath)
origHash := metadata1.RootHash
require.NoError(t, d.formatDmverityLayer(ctx, layerPath))
metadata2, _ := dmverity.ReadMetadata(layerPath)
assert.Equal(t, origHash, metadata2.RootHash)
})
t.Run("uses 4096-byte blocks in regular mode", func(t *testing.T) {
d := &erofsDiff{enableDmverity: true, enableTarIndex: false}
layerPath := filepath.Join(tmpDir, "layer-4k.erofs")
require.NoError(t, os.WriteFile(layerPath, make([]byte, 8192), 0644))
require.NoError(t, d.formatDmverityLayer(ctx, layerPath))
metadata, _ := dmverity.ReadMetadata(layerPath)
assert.Equal(t, uint64(8192), metadata.HashOffset)
})
t.Run("uses 512-byte blocks in tar-index mode", func(t *testing.T) {
d := &erofsDiff{enableDmverity: true, enableTarIndex: true}
layerPath := filepath.Join(tmpDir, "layer-512.erofs")
require.NoError(t, os.WriteFile(layerPath, make([]byte, 1024), 0644))
require.NoError(t, d.formatDmverityLayer(ctx, layerPath))
metadata, _ := dmverity.ReadMetadata(layerPath)
assert.Equal(t, uint64(1024), metadata.HashOffset)
})
t.Run("returns error for non-existent file", func(t *testing.T) {
d := &erofsDiff{enableDmverity: true, enableTarIndex: false}
err := d.formatDmverityLayer(ctx, filepath.Join(tmpDir, "missing.erofs"))
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to stat layer blob")
})
t.Run("rounds up non-aligned file size to block boundary", func(t *testing.T) {
d := &erofsDiff{enableDmverity: true, enableTarIndex: false}
layerPath := filepath.Join(tmpDir, "layer-unaligned.erofs")
// Write 5000 bytes (not aligned to 4096), should round up to 8192
require.NoError(t, os.WriteFile(layerPath, make([]byte, 5000), 0644))
require.NoError(t, d.formatDmverityLayer(ctx, layerPath))
metadata, err := dmverity.ReadMetadata(layerPath)
require.NoError(t, err)
// Hash offset should be rounded up to next 4096-byte boundary
assert.Equal(t, uint64(8192), metadata.HashOffset)
})
}