mirror of
https://github.com/restic/restic.git
synced 2025-03-15 14:40:53 +00:00
211 lines
7.6 KiB
Go
211 lines
7.6 KiB
Go
//go:build windows
|
|
// +build windows
|
|
|
|
package restic
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
"testing"
|
|
|
|
"github.com/restic/restic/internal/errors"
|
|
"github.com/restic/restic/internal/test"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
func TestRestoreCreationTime(t *testing.T) {
|
|
t.Parallel()
|
|
path := t.TempDir()
|
|
fi, err := os.Lstat(path)
|
|
test.OK(t, errors.Wrapf(err, "Could not Lstat for path: %s", path))
|
|
creationTimeAttribute := getCreationTime(fi, path)
|
|
test.OK(t, errors.Wrapf(err, "Could not get creation time for path: %s", path))
|
|
//Using the temp dir creation time as the test creation time for the test file and folder
|
|
runGenericAttributesTest(t, path, TypeCreationTime, WindowsAttributes{CreationTime: creationTimeAttribute}, false)
|
|
}
|
|
|
|
func TestRestoreFileAttributes(t *testing.T) {
|
|
t.Parallel()
|
|
genericAttributeName := TypeFileAttributes
|
|
tempDir := t.TempDir()
|
|
normal := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
|
|
hidden := uint32(syscall.FILE_ATTRIBUTE_HIDDEN)
|
|
system := uint32(syscall.FILE_ATTRIBUTE_SYSTEM)
|
|
archive := uint32(syscall.FILE_ATTRIBUTE_ARCHIVE)
|
|
encrypted := uint32(windows.FILE_ATTRIBUTE_ENCRYPTED)
|
|
fileAttributes := []WindowsAttributes{
|
|
//normal
|
|
{FileAttributes: &normal},
|
|
//hidden
|
|
{FileAttributes: &hidden},
|
|
//system
|
|
{FileAttributes: &system},
|
|
//archive
|
|
{FileAttributes: &archive},
|
|
//encrypted
|
|
{FileAttributes: &encrypted},
|
|
}
|
|
for i, fileAttr := range fileAttributes {
|
|
genericAttrs, err := WindowsAttrsToGenericAttributes(fileAttr)
|
|
test.OK(t, err)
|
|
expectedNodes := []Node{
|
|
{
|
|
Name: fmt.Sprintf("testfile%d", i),
|
|
Type: "file",
|
|
Mode: 0655,
|
|
ModTime: parseTime("2005-05-14 21:07:03.111"),
|
|
AccessTime: parseTime("2005-05-14 21:07:04.222"),
|
|
ChangeTime: parseTime("2005-05-14 21:07:05.333"),
|
|
GenericAttributes: genericAttrs,
|
|
},
|
|
}
|
|
runGenericAttributesTestForNodes(t, expectedNodes, tempDir, genericAttributeName, fileAttr, false)
|
|
}
|
|
normal = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY)
|
|
hidden = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | syscall.FILE_ATTRIBUTE_HIDDEN)
|
|
system = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_SYSTEM)
|
|
archive = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ARCHIVE)
|
|
encrypted = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ENCRYPTED)
|
|
folderAttributes := []WindowsAttributes{
|
|
//normal
|
|
{FileAttributes: &normal},
|
|
//hidden
|
|
{FileAttributes: &hidden},
|
|
//system
|
|
{FileAttributes: &system},
|
|
//archive
|
|
{FileAttributes: &archive},
|
|
//encrypted
|
|
{FileAttributes: &encrypted},
|
|
}
|
|
for i, folderAttr := range folderAttributes {
|
|
genericAttrs, err := WindowsAttrsToGenericAttributes(folderAttr)
|
|
test.OK(t, err)
|
|
expectedNodes := []Node{
|
|
{
|
|
Name: fmt.Sprintf("testdirectory%d", i),
|
|
Type: "dir",
|
|
Mode: 0755,
|
|
ModTime: parseTime("2005-05-14 21:07:03.111"),
|
|
AccessTime: parseTime("2005-05-14 21:07:04.222"),
|
|
ChangeTime: parseTime("2005-05-14 21:07:05.333"),
|
|
GenericAttributes: genericAttrs,
|
|
},
|
|
}
|
|
runGenericAttributesTestForNodes(t, expectedNodes, tempDir, genericAttributeName, folderAttr, false)
|
|
}
|
|
}
|
|
|
|
func runGenericAttributesTest(t *testing.T, tempDir string, genericAttributeName GenericAttributeType, genericAttributeExpected WindowsAttributes, warningExpected bool) {
|
|
genericAttributes, err := WindowsAttrsToGenericAttributes(genericAttributeExpected)
|
|
test.OK(t, err)
|
|
expectedNodes := []Node{
|
|
{
|
|
Name: "testfile",
|
|
Type: "file",
|
|
Mode: 0644,
|
|
ModTime: parseTime("2005-05-14 21:07:03.111"),
|
|
AccessTime: parseTime("2005-05-14 21:07:04.222"),
|
|
ChangeTime: parseTime("2005-05-14 21:07:05.333"),
|
|
GenericAttributes: genericAttributes,
|
|
},
|
|
{
|
|
Name: "testdirectory",
|
|
Type: "dir",
|
|
Mode: 0755,
|
|
ModTime: parseTime("2005-05-14 21:07:03.111"),
|
|
AccessTime: parseTime("2005-05-14 21:07:04.222"),
|
|
ChangeTime: parseTime("2005-05-14 21:07:05.333"),
|
|
GenericAttributes: genericAttributes,
|
|
},
|
|
}
|
|
runGenericAttributesTestForNodes(t, expectedNodes, tempDir, genericAttributeName, genericAttributeExpected, warningExpected)
|
|
}
|
|
func runGenericAttributesTestForNodes(t *testing.T, expectedNodes []Node, tempDir string, genericAttr GenericAttributeType, genericAttributeExpected WindowsAttributes, warningExpected bool) {
|
|
|
|
for _, testNode := range expectedNodes {
|
|
testPath, node := restoreAndGetNode(t, tempDir, testNode, warningExpected)
|
|
rawMessage := node.GenericAttributes[genericAttr]
|
|
genericAttrsExpected, err := WindowsAttrsToGenericAttributes(genericAttributeExpected)
|
|
test.OK(t, err)
|
|
rawMessageExpected := genericAttrsExpected[genericAttr]
|
|
test.Equals(t, rawMessageExpected, rawMessage, "Generic attribute: %s got from NodeFromFileInfo not equal for path: %s", string(genericAttr), testPath)
|
|
}
|
|
}
|
|
|
|
func restoreAndGetNode(t *testing.T, tempDir string, testNode Node, warningExpected bool) (string, *Node) {
|
|
testPath := filepath.Join(tempDir, "001", testNode.Name)
|
|
err := os.MkdirAll(filepath.Dir(testPath), testNode.Mode)
|
|
test.OK(t, errors.Wrapf(err, "Failed to create parent directories for: %s", testPath))
|
|
|
|
if testNode.Type == "file" {
|
|
|
|
testFile, err := os.Create(testPath)
|
|
test.OK(t, errors.Wrapf(err, "Failed to create test file: %s", testPath))
|
|
testFile.Close()
|
|
} else if testNode.Type == "dir" {
|
|
|
|
err := os.Mkdir(testPath, testNode.Mode)
|
|
test.OK(t, errors.Wrapf(err, "Failed to create test directory: %s", testPath))
|
|
}
|
|
|
|
err = testNode.RestoreMetadata(testPath, func(msg string) {
|
|
if warningExpected {
|
|
test.Assert(t, warningExpected, "Warning triggered as expected: %s", msg)
|
|
} else {
|
|
// If warning is not expected, this code should not get triggered.
|
|
test.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", testPath, msg))
|
|
}
|
|
})
|
|
test.OK(t, errors.Wrapf(err, "Failed to restore metadata for: %s", testPath))
|
|
|
|
fi, err := os.Lstat(testPath)
|
|
test.OK(t, errors.Wrapf(err, "Could not Lstat for path: %s", testPath))
|
|
|
|
nodeFromFileInfo, err := NodeFromFileInfo(testPath, fi)
|
|
test.OK(t, errors.Wrapf(err, "Could not get NodeFromFileInfo for path: %s", testPath))
|
|
|
|
return testPath, nodeFromFileInfo
|
|
}
|
|
|
|
const TypeSomeNewAttribute GenericAttributeType = "MockAttributes.SomeNewAttribute"
|
|
|
|
func TestNewGenericAttributeType(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
newGenericAttribute := map[GenericAttributeType]json.RawMessage{}
|
|
newGenericAttribute[TypeSomeNewAttribute] = []byte("any value")
|
|
|
|
tempDir := t.TempDir()
|
|
expectedNodes := []Node{
|
|
{
|
|
Name: "testfile",
|
|
Type: "file",
|
|
Mode: 0644,
|
|
ModTime: parseTime("2005-05-14 21:07:03.111"),
|
|
AccessTime: parseTime("2005-05-14 21:07:04.222"),
|
|
ChangeTime: parseTime("2005-05-14 21:07:05.333"),
|
|
GenericAttributes: newGenericAttribute,
|
|
},
|
|
{
|
|
Name: "testdirectory",
|
|
Type: "dir",
|
|
Mode: 0755,
|
|
ModTime: parseTime("2005-05-14 21:07:03.111"),
|
|
AccessTime: parseTime("2005-05-14 21:07:04.222"),
|
|
ChangeTime: parseTime("2005-05-14 21:07:05.333"),
|
|
GenericAttributes: newGenericAttribute,
|
|
},
|
|
}
|
|
for _, testNode := range expectedNodes {
|
|
testPath, node := restoreAndGetNode(t, tempDir, testNode, true)
|
|
_, ua, err := genericAttributesToWindowsAttrs(node.GenericAttributes)
|
|
test.OK(t, err)
|
|
// Since this GenericAttribute is unknown to this version of the software, it will not get set on the file.
|
|
test.Assert(t, len(ua) == 0, "Unkown attributes: %s found for path: %s", ua, testPath)
|
|
}
|
|
}
|