1+ // Copyright (c) Microsoft. All rights reserved.
2+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
14using System ;
5+ using System . Collections . Generic ;
26using System . IO ;
3- using System . Reflection ;
47using System . Runtime . Versioning ;
58using Microsoft . Build . Shared ;
69using Microsoft . Build . Tasks ;
@@ -12,10 +15,6 @@ namespace Microsoft.Build.UnitTests.ResolveAssemblyReference_Tests
1215{
1316 public class ResolveAssemblyReferenceCacheSerialization : IDisposable
1417 {
15- // Maintain this two in sync with the constant in SystemState
16- private static readonly byte [ ] TranslateContractSignature = { ( byte ) 'M' , ( byte ) 'B' , ( byte ) 'R' , ( byte ) 'S' , ( byte ) 'C' } ; // Microsoft Build RAR State Cache
17- private static readonly byte TranslateContractVersion = 0x01 ;
18-
1918 private readonly string _rarCacheFile ;
2019 private readonly TaskLoggingHelper _taskLoggingHelper ;
2120
@@ -42,178 +41,81 @@ public void RoundTripEmptyState()
4241 {
4342 SystemState systemState = new ( ) ;
4443
45- systemState . SerializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
44+ systemState . SerializeCache ( _rarCacheFile , _taskLoggingHelper ) ;
4645
47- var deserialized = SystemState . DeserializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
46+ var deserialized = SystemState . DeserializeCache ( _rarCacheFile , _taskLoggingHelper , typeof ( SystemState ) ) ;
4847
4948 deserialized . ShouldNotBeNull ( ) ;
5049 }
5150
5251 [ Fact ]
53- public void WrongFileSignature ( )
54- {
55- SystemState systemState = new ( ) ;
56-
57- for ( int i = 0 ; i < TranslateContractSignature . Length ; i ++ )
58- {
59- systemState . SerializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
60- using ( var cacheStream = new FileStream ( _rarCacheFile , FileMode . Open , FileAccess . ReadWrite ) )
61- {
62- cacheStream . Seek ( i , SeekOrigin . Begin ) ;
63- cacheStream . WriteByte ( 0 ) ;
64- cacheStream . Close ( ) ;
65- }
66-
67- var deserialized = SystemState . DeserializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
68-
69- deserialized . ShouldBeNull ( ) ;
70- }
71- }
72-
73- [ Fact ]
74- public void WrongFileVersion ( )
52+ public void CorrectFileVersion ( )
7553 {
7654 SystemState systemState = new ( ) ;
7755
78- systemState . SerializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
56+ systemState . SerializeCache ( _rarCacheFile , _taskLoggingHelper ) ;
7957 using ( var cacheStream = new FileStream ( _rarCacheFile , FileMode . Open , FileAccess . ReadWrite ) )
8058 {
81- cacheStream . Seek ( TranslateContractSignature . Length , SeekOrigin . Begin ) ;
82- cacheStream . WriteByte ( ( byte ) ( TranslateContractVersion + 1 ) ) ;
59+ cacheStream . Seek ( 0 , SeekOrigin . Begin ) ;
60+ cacheStream . WriteByte ( StateFileBase . CurrentSerializationVersion ) ;
8361 cacheStream . Close ( ) ;
8462 }
8563
86- var deserialized = SystemState . DeserializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
87-
88- deserialized . ShouldBeNull ( ) ;
89- }
90-
91- [ Fact ]
92- public void CorrectFileSignature ( )
93- {
94- SystemState systemState = new ( ) ;
95-
96- for ( int i = 0 ; i < TranslateContractSignature . Length ; i ++ )
97- {
98- systemState . SerializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
99- using ( var cacheStream = new FileStream ( _rarCacheFile , FileMode . Open , FileAccess . ReadWrite ) )
100- {
101- cacheStream . Seek ( i , SeekOrigin . Begin ) ;
102- cacheStream . WriteByte ( TranslateContractSignature [ i ] ) ;
103- cacheStream . Close ( ) ;
104- }
105-
106- var deserialized = SystemState . DeserializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
64+ var deserialized = SystemState . DeserializeCache ( _rarCacheFile , _taskLoggingHelper , typeof ( SystemState ) ) ;
10765
108- deserialized . ShouldNotBeNull ( ) ;
109- }
66+ deserialized . ShouldNotBeNull ( ) ;
11067 }
11168
11269 [ Fact ]
113- public void CorrectFileVersion ( )
70+ public void WrongFileVersion ( )
11471 {
11572 SystemState systemState = new ( ) ;
11673
117- systemState . SerializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
74+ systemState . SerializeCache ( _rarCacheFile , _taskLoggingHelper ) ;
11875 using ( var cacheStream = new FileStream ( _rarCacheFile , FileMode . Open , FileAccess . ReadWrite ) )
11976 {
120- cacheStream . Seek ( TranslateContractSignature . Length , SeekOrigin . Begin ) ;
121- cacheStream . WriteByte ( TranslateContractVersion ) ;
77+ cacheStream . Seek ( 0 , SeekOrigin . Begin ) ;
78+ cacheStream . WriteByte ( StateFileBase . CurrentSerializationVersion - 1 ) ;
12279 cacheStream . Close ( ) ;
12380 }
12481
125- var deserialized = SystemState . DeserializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
82+ var deserialized = SystemState . DeserializeCache ( _rarCacheFile , _taskLoggingHelper , typeof ( SystemState ) ) ;
12683
127- deserialized . ShouldNotBeNull ( ) ;
84+ deserialized . ShouldBeNull ( ) ;
12885 }
12986
13087 [ Fact ]
131- public void VerifySampleStateDeserialization ( )
88+ public void ValidateSerializationAndDeserialization ( )
13289 {
133- // This test might also fail when binary format is modified.
134- // Any change in SystemState and child class ITranslatable implementation will most probably make this fail.
135- // To fix it, file referred by 'sampleName' needs to be recaptured and constant bellow modified to reflect
136- // the content of that cache.
137- // This sample was captured by compiling https://github.com/dotnet/roslyn/commit/f8107de2a94a01e96ac3d7c1f225acbb61e18830
138- const string sampleName = "Microsoft.VisualStudio.LanguageServices.Implementation.csprojAssemblyReference.cache" ;
139- const string expectedAssemblyPath = @"C:\Users\rokon\.nuget\packages\microsoft.visualstudio.codeanalysis.sdk.ui\15.8.27812-alpha\lib\net46\Microsoft.VisualStudio.CodeAnalysis.Sdk.UI.dll" ;
140- const long expectedAssemblyLastWriteTimeTicks = 636644382480000000 ;
141- const string expectedAssemblyName = "Microsoft.VisualStudio.CodeAnalysis.Sdk.UI, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ;
142- const string expectedFrameworkName = ".NETFramework,Version=v4.5" ;
143- var expectedDependencies = new [ ]
90+ Dictionary < string , SystemState . FileState > cache = new ( ) {
91+ { "path1" , new SystemState . FileState ( DateTime . Now ) } ,
92+ { "path2" , new SystemState . FileState ( DateTime . Now ) { Assembly = new AssemblyNameExtension ( "hi" ) } } ,
93+ { "dllName" , new SystemState . FileState ( DateTime . Now . AddSeconds ( - 10 ) ) {
94+ Assembly = null ,
95+ RuntimeVersion = "v4.0.30319" ,
96+ FrameworkNameAttribute = new FrameworkName ( ".NETFramework" , Version . Parse ( "4.7.2" ) , "Profile" ) ,
97+ scatterFiles = new string [ ] { "first" , "second" } } } } ;
98+ SystemState sysState = new ( ) ;
99+ sysState . instanceLocalFileStateCache = cache ;
100+ SystemState sysState2 = null ;
101+ using ( TestEnvironment env = TestEnvironment . Create ( ) )
144102 {
145- "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" ,
146- "System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" ,
147- "System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
148- "Microsoft.VisualStudio.CodeAnalysis, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
149- "Microsoft.VisualStudio.DeveloperTools, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
150- "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" ,
151- "Microsoft.VisualStudio.Shell.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
152- "EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
153- "Microsoft.VisualStudio.CodeAnalysis.Sdk, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
154- "Microsoft.Build.Framework, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
155- "Microsoft.VisualStudio.Text.Logic, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
156- "Microsoft.VisualStudio.Text.UI, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
157- "Microsoft.VisualStudio.Text.Data, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
158- "Microsoft.VisualStudio.Text.UI.Wpf, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
159- "Microsoft.VisualStudio.ComponentModelHost, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
160- "Microsoft.VisualStudio.VSHelp, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
161- "Microsoft.VisualStudio.Shell.Interop.11.0, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
162- "Microsoft.VisualStudio.VCProjectEngine, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
163- "Microsoft.VisualStudio.Shell.15.0, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
164- "Microsoft.VisualStudio.OLE.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
165- "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" ,
166- "Microsoft.VisualStudio.TextManager.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
167- "EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
168- "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" ,
169- "Microsoft.VisualStudio.VirtualTreeGrid, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
170- "Microsoft.VisualStudio.Shell.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
171- "Microsoft.VisualStudio.Editor, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
172- } ;
173-
174-
175- CopyResourceSampleFileIntoRarCacheFile ( $@ "AssemblyDependency\CacheFileSamples\{ sampleName } ") ;
176-
177- var deserializedByTranslator = SystemState . DeserializeCacheByTranslator ( _rarCacheFile , _taskLoggingHelper ) ;
178- deserializedByTranslator . ShouldNotBeNull ( ) ;
179-
180- deserializedByTranslator . SetGetLastWriteTime ( path =>
181- {
182- if ( path != expectedAssemblyPath )
183- throw new InvalidOperationException ( "Unexpected file name for this test case" ) ;
184-
185- return new DateTime ( expectedAssemblyLastWriteTimeTicks , DateTimeKind . Utc ) ;
186- } ) ;
187-
188- GetAssemblyName getAssemblyName = deserializedByTranslator . CacheDelegate ( ( GetAssemblyName ) null ) ;
189- GetAssemblyMetadata getAssemblyMetadata = deserializedByTranslator . CacheDelegate ( ( GetAssemblyMetadata ) null ) ;
190-
191- var assemblyName = getAssemblyName ( expectedAssemblyPath ) ;
192- getAssemblyMetadata ( expectedAssemblyPath , null ,
193- out AssemblyNameExtension [ ] dependencies ,
194- out string [ ] scatterFiles ,
195- out FrameworkName frameworkNameAttribute ) ;
196-
197-
198- assemblyName . ShouldNotBeNull ( ) ;
199- assemblyName . ShouldBe ( new AssemblyNameExtension ( expectedAssemblyName , false ) ) ;
200- scatterFiles . ShouldBeEmpty ( ) ;
201- frameworkNameAttribute . ShouldBe ( new FrameworkName ( expectedFrameworkName ) ) ;
202- dependencies . ShouldNotBeNull ( ) ;
203- expectedDependencies . ShouldBe ( expectedDependencies , ignoreOrder : true ) ;
204- }
205-
206- private void CopyResourceSampleFileIntoRarCacheFile ( string name )
207- {
208- Assembly asm = this . GetType ( ) . Assembly ;
209- var resource = string . Format ( $ "{ asm . GetName ( ) . Name } .{ name . Replace ( "\\ " , "." ) } ") ;
210- using Stream resourceStream = asm . GetManifestResourceStream ( resource ) ;
211- if ( resourceStream == null )
212- throw new InvalidOperationException ( $ "Resource '{ resource } ' has not been found.") ;
213-
214- using FileStream rarCacheFile = new FileStream ( _rarCacheFile , FileMode . CreateNew ) ;
103+ TransientTestFile file = env . CreateFile ( ) ;
104+ sysState . SerializeCache ( file . Path , null ) ;
105+ sysState2 = SystemState . DeserializeCache ( file . Path , null , typeof ( SystemState ) ) as SystemState ;
106+ }
215107
216- resourceStream . CopyTo ( rarCacheFile ) ;
108+ Dictionary < string , SystemState . FileState > cache2 = sysState2 . instanceLocalFileStateCache ;
109+ cache2 . Count . ShouldBe ( cache . Count ) ;
110+ cache2 [ "path2" ] . Assembly . Name . ShouldBe ( cache [ "path2" ] . Assembly . Name ) ;
111+ SystemState . FileState dll = cache [ "dllName" ] ;
112+ SystemState . FileState dll2 = cache2 [ "dllName" ] ;
113+ dll2 . Assembly . ShouldBe ( dll . Assembly ) ;
114+ dll2 . FrameworkNameAttribute . FullName . ShouldBe ( dll . FrameworkNameAttribute . FullName ) ;
115+ dll2 . LastModified . ShouldBe ( dll . LastModified ) ;
116+ dll2 . RuntimeVersion . ShouldBe ( dll . RuntimeVersion ) ;
117+ dll2 . scatterFiles . Length . ShouldBe ( dll . scatterFiles . Length ) ;
118+ dll2 . scatterFiles [ 1 ] . ShouldBe ( dll . scatterFiles [ 1 ] ) ;
217119 }
218120 }
219121}
0 commit comments