mirror of
https://github.com/containerd/containerd.git
synced 2026-08-08 09:01:21 +00:00
Merge pull request #12310 from aadhar-agarwal/aadagarwal/add_tar_index_tests
Add a test for the erofs differ using tar index mode
This commit is contained in:
@@ -18,17 +18,31 @@ package erofs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/v2/core/content"
|
||||
"github.com/containerd/containerd/v2/core/mount"
|
||||
"github.com/containerd/containerd/v2/core/snapshots"
|
||||
"github.com/containerd/containerd/v2/core/snapshots/storage"
|
||||
"github.com/containerd/containerd/v2/core/snapshots/testsuite"
|
||||
"github.com/containerd/containerd/v2/internal/erofsutils"
|
||||
"github.com/containerd/containerd/v2/internal/fsverity"
|
||||
"github.com/containerd/containerd/v2/pkg/archive/tartest"
|
||||
"github.com/containerd/containerd/v2/pkg/testutil"
|
||||
"github.com/containerd/containerd/v2/plugins/content/local"
|
||||
erofsdiffer "github.com/containerd/containerd/v2/plugins/diff/erofs"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
testFileContent = "Hello, this is content for testing the EROFS Snapshotter!"
|
||||
testNestedFileContent = "Nested file content"
|
||||
)
|
||||
|
||||
func newSnapshotter(t *testing.T) func(ctx context.Context, root string) (snapshots.Snapshotter, func() error, error) {
|
||||
@@ -131,3 +145,177 @@ func TestErofsFsverity(t *testing.T) {
|
||||
t.Fatal("Expected direct write to fsverity-enabled layer to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErofsDifferWithTarIndexMode(t *testing.T) {
|
||||
testutil.RequiresRoot(t)
|
||||
ctx := context.Background()
|
||||
|
||||
if !findErofs() {
|
||||
t.Skip("check for erofs kernel support failed, skipping test")
|
||||
}
|
||||
|
||||
// Check if mkfs.erofs supports tar index mode
|
||||
supported, err := erofsutils.SupportGenerateFromTar()
|
||||
if err != nil || !supported {
|
||||
t.Skip("mkfs.erofs does not support tar mode, skipping tar index test")
|
||||
}
|
||||
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Create content store for the differ
|
||||
contentStore, err := local.NewStore(filepath.Join(tempDir, "content"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create EROFS differ with tar index mode enabled
|
||||
differ := erofsdiffer.NewErofsDiffer(contentStore, erofsdiffer.WithTarIndexMode())
|
||||
|
||||
// Create EROFS snapshotter
|
||||
snapshotRoot := filepath.Join(tempDir, "snapshots")
|
||||
s, err := NewSnapshotter(snapshotRoot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
// Create test tar content
|
||||
tarReader := createTestTarContent()
|
||||
defer tarReader.Close()
|
||||
|
||||
// Read the tar content into a buffer for digest calculation and writing
|
||||
tarContent, err := io.ReadAll(tarReader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Write tar content to content store
|
||||
desc := ocispec.Descriptor{
|
||||
MediaType: ocispec.MediaTypeImageLayerGzip,
|
||||
Digest: digest.FromBytes(tarContent),
|
||||
Size: int64(len(tarContent)),
|
||||
}
|
||||
|
||||
writer, err := contentStore.Writer(ctx,
|
||||
content.WithRef("test-layer"),
|
||||
content.WithDescriptor(desc))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := writer.Write(tarContent); err != nil {
|
||||
writer.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := writer.Commit(ctx, desc.Size, desc.Digest); err != nil {
|
||||
writer.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
writer.Close()
|
||||
|
||||
// Prepare a snapshot using the snapshotter
|
||||
snapshotKey := "test-snapshot"
|
||||
mounts, err := s.Prepare(ctx, snapshotKey, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Apply the tar content using the EROFS differ with tar index mode
|
||||
appliedDesc, err := differ.Apply(ctx, desc, mounts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Logf("Applied layer using EROFS differ with tar index mode:")
|
||||
t.Logf(" Original: %s (%d bytes)", desc.Digest, desc.Size)
|
||||
t.Logf(" Applied: %s (%d bytes)", appliedDesc.Digest, appliedDesc.Size)
|
||||
t.Logf(" MediaType: %s", appliedDesc.MediaType)
|
||||
|
||||
// Commit the snapshot to finalize the EROFS layer creation
|
||||
commitKey := "test-commit"
|
||||
if err := s.Commit(ctx, commitKey, snapshotKey); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Get the internal snapshot ID to check the EROFS layer file
|
||||
snap := s.(*snapshotter)
|
||||
var id string
|
||||
if err := snap.ms.WithTransaction(ctx, false, func(ctx context.Context) error {
|
||||
id, _, _, err = storage.GetInfo(ctx, commitKey)
|
||||
return err
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify the EROFS layer file was created
|
||||
layerPath := snap.layerBlobPath(id)
|
||||
if _, err := os.Stat(layerPath); err != nil {
|
||||
t.Fatalf("EROFS layer file should exist: %v", err)
|
||||
}
|
||||
|
||||
// Verify the layer file is not empty
|
||||
stat, err := os.Stat(layerPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if stat.Size() == 0 {
|
||||
t.Fatal("EROFS layer file should not be empty")
|
||||
}
|
||||
|
||||
t.Logf("EROFS layer file created with tar index mode: %s (%d bytes)", layerPath, stat.Size())
|
||||
|
||||
// Create a view to verify the content
|
||||
viewKey := "test-view"
|
||||
viewMounts, err := s.View(ctx, viewKey, commitKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
viewTarget := filepath.Join(tempDir, viewKey)
|
||||
if err := os.MkdirAll(viewTarget, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := mount.All(viewMounts, viewTarget); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer testutil.Unmount(t, viewTarget)
|
||||
|
||||
// Verify we can read the original test data
|
||||
testData, err := os.ReadFile(filepath.Join(viewTarget, "test-file.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := testFileContent
|
||||
if string(testData) != expected {
|
||||
t.Fatalf("Expected %q, got %q", expected, string(testData))
|
||||
}
|
||||
|
||||
// Verify nested file
|
||||
nestedData, err := os.ReadFile(filepath.Join(viewTarget, "testdir", "nested.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expectedNested := testNestedFileContent
|
||||
if string(nestedData) != expectedNested {
|
||||
t.Fatalf("Expected %q, got %q", expectedNested, string(nestedData))
|
||||
}
|
||||
|
||||
t.Logf("Successfully verified EROFS Snapshotter using the differ with tar index mode")
|
||||
}
|
||||
|
||||
// Helper function to create test tar content using tartest
|
||||
func createTestTarContent() io.ReadCloser {
|
||||
// Create a tar context with current time for consistency
|
||||
tc := tartest.TarContext{}.WithModTime(time.Now())
|
||||
|
||||
// Create the tar with our test files and directories
|
||||
tarWriter := tartest.TarAll(
|
||||
tc.File("test-file.txt", []byte(testFileContent), 0644),
|
||||
tc.Dir("testdir", 0755),
|
||||
tc.File("testdir/nested.txt", []byte(testNestedFileContent), 0644),
|
||||
)
|
||||
|
||||
// Return the tar as a ReadCloser
|
||||
return tartest.TarFromWriterTo(tarWriter)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user