Skip to content

Commit

Permalink
Fix test failure in Apple OSs due to paths too long and using Ustar w…
Browse files Browse the repository at this point in the history
…hich does not support long paths. (#71115)

Co-authored-by: carlossanlop <carlossanlop@users.noreply.github.com>
  • Loading branch information
carlossanlop and carlossanlop authored Jun 22, 2022
1 parent fc813dd commit 7e46936
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,6 @@ private void GetExpectedTimestampsFromOriginalPaxOrGnu(TarEntry originalEntry, o

}

protected TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targetFormat, TarEntryType entryType, string entryName)
=> targetFormat switch
{
TarEntryFormat.V7 => new V7TarEntry(entryType, entryName),
TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName),
TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName),
TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName),
_ => throw new FormatException($"Unexpected format: {targetFormat}")
};

protected TarEntry InvokeTarEntryConversionConstructor(TarEntryFormat targetFormat, TarEntry other)
=> targetFormat switch
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,35 +94,56 @@ public void Extract_LinkEntry_TargetOutsideDirectory(TarEntryType entryType)
Assert.Equal(0, Directory.GetFileSystemEntries(root.Path).Count());
}

[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
public void Extract_SymbolicLinkEntry_TargetInsideDirectory() => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink);

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))]
public void Extract_HardLinkEntry_TargetInsideDirectory() => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink);

private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entryType)
[ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_SymbolicLinkEntry_TargetInsideDirectory(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink, format, null);

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_HardLinkEntry_TargetInsideDirectory(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink, format, null);

[ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_SymbolicLinkEntry_TargetInsideDirectory_LongBaseDir(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink, format, new string('a', 99));

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_HardLinkEntry_TargetInsideDirectory_LongBaseDir(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink, format, new string('a', 99));

// This test would not pass for the V7 and Ustar formats in some OSs like MacCatalyst, tvOSSimulator and OSX, because the TempDirectory gets created in
// a folder with a path longer than 100 bytes, and those tar formats have no way of handling pathnames and linknames longer than that length.
// The rest of the OSs create the TempDirectory in a path that does not surpass the 100 bytes, so the 'subfolder' parameter gives a chance to extend
// the base directory past that length, to ensure this scenario is tested everywhere.
private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entryType, TarEntryFormat format, string subfolder)
{
using TempDirectory root = new TempDirectory();

string baseDir = string.IsNullOrEmpty(subfolder) ? root.Path : Path.Join(root.Path, subfolder);
Directory.CreateDirectory(baseDir);

string linkName = "link";
string targetName = "target";
string targetPath = Path.Join(root.Path, targetName);
string targetPath = Path.Join(baseDir, targetName);

File.Create(targetPath).Dispose();

using MemoryStream archive = new MemoryStream();
using (TarWriter writer = new TarWriter(archive, TarEntryFormat.Ustar, leaveOpen: true))
using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true))
{
UstarTarEntry entry = new UstarTarEntry(entryType, linkName);
TarEntry entry= InvokeTarEntryCreationConstructor(format, entryType, linkName);
entry.LinkName = targetPath;
writer.WriteEntry(entry);
}

archive.Seek(0, SeekOrigin.Begin);

TarFile.ExtractToDirectory(archive, root.Path, overwriteFiles: false);
TarFile.ExtractToDirectory(archive, baseDir, overwriteFiles: false);

Assert.Equal(2, Directory.GetFileSystemEntries(root.Path).Count());
Assert.Equal(2, Directory.GetFileSystemEntries(baseDir).Count());
}
}
}
11 changes: 11 additions & 0 deletions src/libraries/System.Formats.Tar/tests/TarTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,5 +323,16 @@ protected Type GetTypeForFormat(TarEntryFormat expectedFormat)
_ => throw new FormatException($"Unrecognized format: {expectedFormat}"),
};
}

protected TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targetFormat, TarEntryType entryType, string entryName)
=> targetFormat switch
{
TarEntryFormat.V7 => new V7TarEntry(entryType, entryName),
TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName),
TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName),
TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName),
_ => throw new FormatException($"Unexpected format: {targetFormat}")
};

}
}

0 comments on commit 7e46936

Please sign in to comment.