public void Ctor() { Assert.Throws<ArgumentNullException>(() => new PEReader(null, PEStreamOptions.Default)); var invalid = new MemoryStream(new byte[] { 1, 2, 3, 4 }); // the stream should not be disposed if the arguments are bad Assert.Throws<ArgumentOutOfRangeException>(() => new PEReader(invalid, (PEStreamOptions)int.MaxValue)); Assert.True(invalid.CanRead); // no BadImageFormatException if we're prefetching the entire image: var peReader0 = new PEReader(invalid, PEStreamOptions.PrefetchEntireImage | PEStreamOptions.LeaveOpen); Assert.True(invalid.CanRead); Assert.Throws<BadImageFormatException>(() => peReader0.PEHeaders); invalid.Position = 0; // BadImageFormatException if we're prefetching the entire image and metadata: Assert.Throws<BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchEntireImage | PEStreamOptions.PrefetchMetadata | PEStreamOptions.LeaveOpen)); Assert.True(invalid.CanRead); invalid.Position = 0; // the stream should be disposed if the content is bad: Assert.Throws<BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchMetadata)); Assert.False(invalid.CanRead); // the stream should not be disposed if we specified LeaveOpen flag: invalid = new MemoryStream(new byte[] { 1, 2, 3, 4 }); Assert.Throws<BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchMetadata | PEStreamOptions.LeaveOpen)); Assert.True(invalid.CanRead); // valid metadata: var valid = new MemoryStream(TestResources.Misc.Members); var peReader = new PEReader(valid, PEStreamOptions.Default); Assert.True(valid.CanRead); peReader.Dispose(); Assert.False(valid.CanRead); }
public void FileShareDeleteCompatibility_Xplat() { var bytes = TestResources.MetadataTests.InterfaceAndClass.CSClasses01; var mvid = ReadMvid(new MemoryStream(bytes)); var dir = Temp.CreateDirectory(); var libSrc = dir.CreateFile("Lib.cs").WriteAllText("class C { }"); var libDll = dir.CreateFile("Lib.dll").WriteAllBytes(bytes); var libPdb = dir.CreateFile("Lib.pdb").WriteAllBytes(bytes); var fsDll = new FileStream(libDll.Path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete); var fsPdb = new FileStream(libPdb.Path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete); var peDll = new PEReader(fsDll); var pePdb = new PEReader(fsPdb); // creates memory map view: var imageDll = peDll.GetEntireImage(); var imagePdb = pePdb.GetEntireImage(); var output = ProcessUtilities.RunAndGetOutput(s_CSharpCompilerExecutable, $"/target:library /debug:portable {libSrc.Path}", startFolder: dir.ToString()); AssertEx.AssertEqualToleratingWhitespaceDifferences($@" Microsoft (R) Visual C# Compiler version {s_compilerVersion} Copyright (C) Microsoft Corporation. All rights reserved.", output); // reading original content from the memory map: Assert.Equal(mvid, ReadMvid(new MemoryStream(imageDll.GetContent().ToArray()))); Assert.Equal(mvid, ReadMvid(new MemoryStream(imagePdb.GetContent().ToArray()))); // reading original content directly from the streams: fsDll.Position = 0; fsPdb.Position = 0; Assert.Equal(mvid, ReadMvid(fsDll)); Assert.Equal(mvid, ReadMvid(fsPdb)); // reading new content from the file: using (var fsNewDll = File.OpenRead(libDll.Path)) { Assert.NotEqual(mvid, ReadMvid(fsNewDll)); } // Portable PDB metadata signature: AssertEx.Equal(new[] { (byte)'B', (byte)'S', (byte)'J', (byte)'B' }, ReadBytes(libPdb.Path, 4)); // dispose PEReaders (they dispose the underlying file streams) peDll.Dispose(); pePdb.Dispose(); AssertEx.Equal(new[] { "Lib.cs", "Lib.dll", "Lib.pdb" }, Directory.GetFiles(dir.Path).Select(p => Path.GetFileName(p)).Order()); // files can be deleted now: File.Delete(libSrc.Path); File.Delete(libDll.Path); File.Delete(libPdb.Path); // directory can be deleted (should be empty): Directory.Delete(dir.Path, recursive: false); }