 8889d459af
			
		
	
	8889d459af
	
	
	
		
			
			Adds tests for verifying parent directory permissions. Currently an issue exists in extracting into some Docker graph drivers. Supporting these graph drivers may require changes to the diff logic, these tests clarify the existing behavior and that extraction within containerd works. Signed-off-by: Derek McGowan <derek@mcgstyle.net>
		
			
				
	
	
		
			198 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package fstest
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"io/ioutil"
 | |
| 	"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("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 := ioutil.TempDir("", "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/", 0755),
 | |
| 		CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
 | |
| 		Link("/etc/hosts", "/etc/hosts.allow"),
 | |
| 		CreateDir("/usr/local/lib", 0755),
 | |
| 		CreateFile("/usr/local/lib/libnothing.so", []byte{0x00, 0x00}, 0755),
 | |
| 		Symlink("libnothing.so", "/usr/local/lib/libnothing.so.2"),
 | |
| 		CreateDir("/home", 0755),
 | |
| 		CreateDir("/home/derek", 0700),
 | |
| 	)
 | |
| 
 | |
| 	// basicTest covers basic operations
 | |
| 	basicTest = []Applier{
 | |
| 		baseApplier,
 | |
| 		Apply(
 | |
| 			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
 | |
| 			CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0600),
 | |
| 			CreateFile("/etc/badfile", []byte(""), 0666),
 | |
| 			CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0640),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			Remove("/etc/badfile"),
 | |
| 			Rename("/home/derek", "/home/notderek"),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			RemoveAll("/usr"),
 | |
| 			Remove("/etc/hosts.allow"),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			RemoveAll("/home"),
 | |
| 			CreateDir("/home/derek", 0700),
 | |
| 			CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0640),
 | |
| 			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", 0755),
 | |
| 			CreateDir("/lib", 0700),
 | |
| 			CreateFile("/lib/hidden", []byte{}, 0644),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			CreateFile("/test/a", []byte{}, 0644),
 | |
| 			CreateFile("/test/b", []byte{}, 0644),
 | |
| 			CreateDir("/test/otherdir", 0755),
 | |
| 			CreateFile("/test/otherdir/.empty", []byte{}, 0644),
 | |
| 			RemoveAll("/lib"),
 | |
| 			CreateDir("/lib", 0700),
 | |
| 			CreateFile("/lib/not-hidden", []byte{}, 0644),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			Remove("/test/a"),
 | |
| 			Remove("/test/b"),
 | |
| 			RemoveAll("/test/otherdir"),
 | |
| 			CreateFile("/lib/newfile", []byte{}, 0644),
 | |
| 		),
 | |
| 	}
 | |
| 
 | |
| 	// updateTest covers file updates for content and permission
 | |
| 	updateTest = []Applier{
 | |
| 		Apply(
 | |
| 			CreateDir("/d1", 0755),
 | |
| 			CreateDir("/d2", 0700),
 | |
| 			CreateFile("/d1/f1", []byte("something..."), 0644),
 | |
| 			CreateFile("/d1/f2", []byte("else..."), 0644),
 | |
| 			CreateFile("/d1/f3", []byte("entirely..."), 0644),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			CreateFile("/d1/f1", []byte("file content of a different length"), 0664),
 | |
| 			Remove("/d1/f3"),
 | |
| 			CreateFile("/d1/f3", []byte("updated content"), 0664),
 | |
| 			Chmod("/d1/f2", 0766),
 | |
| 			Chmod("/d2", 0777),
 | |
| 		),
 | |
| 	}
 | |
| 
 | |
| 	// directoryPermissionsTest covers directory permissions on update
 | |
| 	directoryPermissionsTest = []Applier{
 | |
| 		Apply(
 | |
| 			CreateDir("/d1", 0700),
 | |
| 			CreateDir("/d2", 0751),
 | |
| 			CreateDir("/d3", 0777),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			CreateFile("/d1/f", []byte("irrelevant"), 0644),
 | |
| 			CreateDir("/d1/d", 0700),
 | |
| 			CreateFile("/d1/d/f", []byte("irrelevant"), 0644),
 | |
| 			CreateFile("/d2/f", []byte("irrelevant"), 0644),
 | |
| 			CreateFile("/d3/f", []byte("irrelevant"), 0644),
 | |
| 		),
 | |
| 	}
 | |
| 
 | |
| 	hardlinkUnmodified = []Applier{
 | |
| 		baseApplier,
 | |
| 		Apply(
 | |
| 			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			Link("/etc/hosts", "/etc/hosts.deny"),
 | |
| 		),
 | |
| 	}
 | |
| 
 | |
| 	// Hardlink name before with modification
 | |
| 	// Tests link is created for unmodified files when new hardlinked file is seen first
 | |
| 	hardlinkBeforeUnmodified = []Applier{
 | |
| 		baseApplier,
 | |
| 		Apply(
 | |
| 			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
 | |
| 		),
 | |
| 		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"), 0644),
 | |
| 		),
 | |
| 		Apply(
 | |
| 			Remove("/etc/hosts"),
 | |
| 			CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
 | |
| 			Link("/etc/hosts", "/etc/before-hosts"),
 | |
| 		),
 | |
| 	}
 | |
| )
 |