mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			237 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
   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 fstest
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"os"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
// TestApplier applies the test context
 | 
						|
type TestApplier interface {
 | 
						|
	TestContext(context.Context) (context.Context, func(), error)
 | 
						|
	Apply(context.Context, Applier) (string, func(), error)
 | 
						|
}
 | 
						|
 | 
						|
// FSSuite runs the path test suite
 | 
						|
func FSSuite(t *testing.T, a TestApplier) {
 | 
						|
	t.Run("Basic", makeTest(t, a, basicTest))
 | 
						|
	t.Run("Deletion", makeTest(t, a, deletionTest))
 | 
						|
	t.Run("Update", makeTest(t, a, updateTest))
 | 
						|
	t.Run("DirectoryPermission", makeTest(t, a, directoryPermissionsTest))
 | 
						|
	t.Run("ParentDirectoryPermission", makeTest(t, a, parentDirectoryPermissionsTest))
 | 
						|
	t.Run("HardlinkUnmodified", makeTest(t, a, hardlinkUnmodified))
 | 
						|
	t.Run("HardlinkBeforeUnmodified", makeTest(t, a, hardlinkBeforeUnmodified))
 | 
						|
	t.Run("HardlinkBeforeModified", makeTest(t, a, hardlinkBeforeModified))
 | 
						|
}
 | 
						|
 | 
						|
func makeTest(t *testing.T, ta TestApplier, as []Applier) func(t *testing.T) {
 | 
						|
	return func(t *testing.T) {
 | 
						|
		ctx, cleanup, err := ta.TestContext(context.Background())
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("Unable to get test context: %+v", err)
 | 
						|
		}
 | 
						|
		defer cleanup()
 | 
						|
 | 
						|
		applyDir, err := os.MkdirTemp("", "test-expected-")
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("Unable to make temp directory: %+v", err)
 | 
						|
		}
 | 
						|
		defer os.RemoveAll(applyDir)
 | 
						|
 | 
						|
		for i, a := range as {
 | 
						|
			testDir, c, err := ta.Apply(ctx, a)
 | 
						|
			if err != nil {
 | 
						|
				t.Fatalf("Apply failed at %d: %+v", i, err)
 | 
						|
			}
 | 
						|
			if err := a.Apply(applyDir); err != nil {
 | 
						|
				if c != nil {
 | 
						|
					c()
 | 
						|
				}
 | 
						|
				t.Fatalf("Error applying change to apply directory: %+v", err)
 | 
						|
			}
 | 
						|
 | 
						|
			err = CheckDirectoryEqual(applyDir, testDir)
 | 
						|
			if c != nil {
 | 
						|
				c()
 | 
						|
			}
 | 
						|
			if err != nil {
 | 
						|
				t.Fatalf("Directories not equal at %d (expected <> tested): %+v", i, err)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
var (
 | 
						|
	// baseApplier creates a basic filesystem layout
 | 
						|
	// with multiple types of files for basic tests.
 | 
						|
	baseApplier = Apply(
 | 
						|
		CreateDir("/etc/", 0o755),
 | 
						|
		CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0o644),
 | 
						|
		Link("/etc/hosts", "/etc/hosts.allow"),
 | 
						|
		CreateDir("/usr/local/lib", 0o755),
 | 
						|
		CreateFile("/usr/local/lib/libnothing.so", []byte{0x00, 0x00}, 0o755),
 | 
						|
		Symlink("libnothing.so", "/usr/local/lib/libnothing.so.2"),
 | 
						|
		CreateDir("/home", 0o755),
 | 
						|
		CreateDir("/home/derek", 0o700),
 | 
						|
		// TODO: CreateSocket: how should Sockets be handled in continuity?
 | 
						|
	)
 | 
						|
 | 
						|
	// basicTest covers basic operations
 | 
						|
	basicTest = []Applier{
 | 
						|
		baseApplier,
 | 
						|
		Apply(
 | 
						|
			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
 | 
						|
			CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0o600),
 | 
						|
			CreateFile("/etc/badfile", []byte(""), 0o666),
 | 
						|
			CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0o640),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			Remove("/etc/badfile"),
 | 
						|
			Rename("/home/derek", "/home/notderek"),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			RemoveAll("/usr"),
 | 
						|
			Remove("/etc/hosts.allow"),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			RemoveAll("/home"),
 | 
						|
			CreateDir("/home/derek", 0o700),
 | 
						|
			CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0o640),
 | 
						|
			Link("/etc/hosts", "/etc/hosts.allow"),
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	// deletionTest covers various deletion scenarios to ensure
 | 
						|
	// deletions are properly picked up and applied
 | 
						|
	deletionTest = []Applier{
 | 
						|
		Apply(
 | 
						|
			CreateDir("/test/somedir", 0o755),
 | 
						|
			CreateDir("/lib", 0o700),
 | 
						|
			CreateFile("/lib/hidden", []byte{}, 0o644),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			CreateFile("/test/a", []byte{}, 0o644),
 | 
						|
			CreateFile("/test/b", []byte{}, 0o644),
 | 
						|
			CreateDir("/test/otherdir", 0o755),
 | 
						|
			CreateFile("/test/otherdir/.empty", []byte{}, 0o644),
 | 
						|
			RemoveAll("/lib"),
 | 
						|
			CreateDir("/lib", 0o700),
 | 
						|
			CreateFile("/lib/not-hidden", []byte{}, 0o644),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			Remove("/test/a"),
 | 
						|
			Remove("/test/b"),
 | 
						|
			RemoveAll("/test/otherdir"),
 | 
						|
			CreateFile("/lib/newfile", []byte{}, 0o644),
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	// updateTest covers file updates for content and permission
 | 
						|
	updateTest = []Applier{
 | 
						|
		Apply(
 | 
						|
			CreateDir("/d1", 0o755),
 | 
						|
			CreateDir("/d2", 0o700),
 | 
						|
			CreateFile("/d1/f1", []byte("something..."), 0o644),
 | 
						|
			CreateFile("/d1/f2", []byte("else..."), 0o644),
 | 
						|
			CreateFile("/d1/f3", []byte("entirely..."), 0o644),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			CreateFile("/d1/f1", []byte("file content of a different length"), 0o664),
 | 
						|
			Remove("/d1/f3"),
 | 
						|
			CreateFile("/d1/f3", []byte("updated content"), 0o664),
 | 
						|
			Chmod("/d1/f2", 0o766),
 | 
						|
			Chmod("/d2", 0o777),
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	// directoryPermissionsTest covers directory permissions on update
 | 
						|
	directoryPermissionsTest = []Applier{
 | 
						|
		Apply(
 | 
						|
			CreateDir("/d1", 0o700),
 | 
						|
			CreateDir("/d2", 0o751),
 | 
						|
			CreateDir("/d3", 0o777),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			CreateFile("/d1/f", []byte("irrelevant"), 0o644),
 | 
						|
			CreateDir("/d1/d", 0o700),
 | 
						|
			CreateFile("/d1/d/f", []byte("irrelevant"), 0o644),
 | 
						|
			CreateFile("/d2/f", []byte("irrelevant"), 0o644),
 | 
						|
			CreateFile("/d3/f", []byte("irrelevant"), 0o644),
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	// parentDirectoryPermissionsTest covers directory permissions for updated
 | 
						|
	// files
 | 
						|
	parentDirectoryPermissionsTest = []Applier{
 | 
						|
		Apply(
 | 
						|
			CreateDir("/d1", 0o700),
 | 
						|
			CreateDir("/d1/a", 0o700),
 | 
						|
			CreateDir("/d1/a/b", 0o700),
 | 
						|
			CreateDir("/d1/a/b/c", 0o700),
 | 
						|
			CreateFile("/d1/a/b/f", []byte("content1"), 0o644),
 | 
						|
			CreateDir("/d2", 0o751),
 | 
						|
			CreateDir("/d2/a/b", 0o751),
 | 
						|
			CreateDir("/d2/a/b/c", 0o751),
 | 
						|
			CreateFile("/d2/a/b/f", []byte("content1"), 0o644),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			CreateFile("/d1/a/b/f", []byte("content1"), 0o644),
 | 
						|
			Chmod("/d1/a/b/c", 0o700),
 | 
						|
			CreateFile("/d2/a/b/f", []byte("content2"), 0o644),
 | 
						|
			Chmod("/d2/a/b/c", 0o751),
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	hardlinkUnmodified = []Applier{
 | 
						|
		baseApplier,
 | 
						|
		Apply(
 | 
						|
			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			Link("/etc/hosts", "/etc/hosts.deny"),
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	// Hardlink name before with modification
 | 
						|
	// Tests link is created for unmodified files when a new hard linked file is seen first
 | 
						|
	hardlinkBeforeUnmodified = []Applier{
 | 
						|
		baseApplier,
 | 
						|
		Apply(
 | 
						|
			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			Link("/etc/hosts", "/etc/before-hosts"),
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	// Hardlink name after without modification
 | 
						|
	// tests link is created for modified file with new hardlink
 | 
						|
	hardlinkBeforeModified = []Applier{
 | 
						|
		baseApplier,
 | 
						|
		Apply(
 | 
						|
			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
 | 
						|
		),
 | 
						|
		Apply(
 | 
						|
			Remove("/etc/hosts"),
 | 
						|
			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0o644),
 | 
						|
			Link("/etc/hosts", "/etc/before-hosts"),
 | 
						|
		),
 | 
						|
	}
 | 
						|
)
 |