From 816c743ad6e8b323e87a6de1bc0d2d5f01ab6e58 Mon Sep 17 00:00:00 2001 From: carlossanlop <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 11 Jul 2022 19:23:47 -0700 Subject: [PATCH] Add TAR tests that verify ExtractToFile works with special files. --- .../tests/System.Formats.Tar.Tests.csproj | 1 + .../TarEntry.ExtractToFile.Tests.Unix.cs | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index 4a58fe0a5c56c..49b2e6e22c89b 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -80,6 +80,7 @@ + diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs new file mode 100644 index 0000000000000..f86136bcc8021 --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + public class TarEntry_ExtractToFile_Tests_Unix : TarTestsBase + { + public static IEnumerable GetFormatsAndSpecialFiles() + { + foreach (TarEntryFormat format in new[] { TarEntryFormat.Ustar, TarEntryFormat.Pax, TarEntryFormat.Gnu }) // V7 does not support special files + { + foreach (TarEntryType entryType in new[] { TarEntryType.BlockDevice, TarEntryType.CharacterDevice, TarEntryType.Fifo }) + { + yield return new object[] { format, entryType }; + } + } + } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [MemberData(nameof(GetFormatsAndSpecialFiles))] + public void Extract_SpecialFiles(TarEntryFormat format, TarEntryType entryType) + { + using TempDirectory root = new TempDirectory(); + + (string entryName, string destination, PosixTarEntry entry) = Prepare_Extract_SpecialFiles(root, format, entryType); + + entry.ExtractToFile(destination, overwrite: true); + + Verify_Extract_SpecialFiles(destination, entry, entryType); + } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [MemberData(nameof(GetFormatsAndSpecialFiles))] + public async Task Extract_SpecialFiles_Async(TarEntryFormat format, TarEntryType entryType) + { + using TempDirectory root = new TempDirectory(); + + (string entryName, string destination, PosixTarEntry entry) = Prepare_Extract_SpecialFiles(root, format, entryType); + + await entry.ExtractToFileAsync(destination, overwrite: true); + + Verify_Extract_SpecialFiles(destination, entry, entryType); + } + + private (string, string, PosixTarEntry) Prepare_Extract_SpecialFiles(TempDirectory root, TarEntryFormat format, TarEntryType entryType) + { + string entryName = entryType.ToString(); + string destination = Path.Join(root.Path, entryName); + + PosixTarEntry entry = InvokeTarEntryCreationConstructor(format, entryType, entryName) as PosixTarEntry; + Assert.NotNull(entry); + + if (entryType is TarEntryType.BlockDevice) + { + entry.DeviceMajor = TestBlockDeviceMajor; + entry.DeviceMinor = TestBlockDeviceMinor; + } + else if (entryType is TarEntryType.CharacterDevice) + { + entry.DeviceMajor = TestCharacterDeviceMajor; + entry.DeviceMinor = TestCharacterDeviceMinor; + } + + return (entryName, destination, entry); + } + + private void Verify_Extract_SpecialFiles(string destination, PosixTarEntry entry, TarEntryType entryType) + { + Assert.True(File.Exists(destination)); + + Interop.Sys.FileStatus status = default; + status.Mode = default; + status.Dev = default; + Interop.CheckIo(Interop.Sys.LStat(destination, out status)); + int fileType = status.Mode & Interop.Sys.FileTypes.S_IFMT; + + if (entryType is TarEntryType.BlockDevice) + { + Assert.Equal(Interop.Sys.FileTypes.S_IFBLK, fileType); + } + else if (entryType is TarEntryType.CharacterDevice) + { + Assert.Equal(Interop.Sys.FileTypes.S_IFCHR, fileType); + } + else if (entryType is TarEntryType.Fifo) + { + Assert.Equal(Interop.Sys.FileTypes.S_IFIFO, fileType); + } + + if (entryType is TarEntryType.BlockDevice or TarEntryType.CharacterDevice) + { + uint major; + uint minor; + unsafe + { + Interop.Sys.GetDeviceIdentifiers((ulong)status.RDev, &major, &minor); + } + + Assert.Equal((int)major, entry.DeviceMajor); + Assert.Equal((int)minor, entry.DeviceMinor); + } + } + } +} \ No newline at end of file