1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 using System
.Collections
;
16 using System
.Collections
.Generic
;
17 using Castle
.DynamicProxy
.Generators
;
18 using Castle
.DynamicProxy
.Tests
.InterClasses
;
20 namespace Castle
.DynamicProxy
.Tests
23 using NUnit
.Framework
;
24 using System
.Reflection
.Emit
;
26 using System
.Reflection
;
29 public class ModuleScopeTestCase
32 public void ModuleScopeStoresModuleBuilder ()
34 ModuleScope scope
= new ModuleScope ();
35 ModuleBuilder one
= scope
.ObtainDynamicModuleWithStrongName ();
36 ModuleBuilder two
= scope
.ObtainDynamicModuleWithStrongName ();
38 Assert
.AreSame (one
, two
);
39 Assert
.AreSame (one
.Assembly
, two
.Assembly
);
43 public void ModuleScopeCanHandleSignedAndUnsignedInParallel ()
45 ModuleScope scope
= new ModuleScope ();
46 Assert
.IsNull (scope
.StrongNamedModule
);
47 Assert
.IsNull (scope
.WeakNamedModule
);
49 ModuleBuilder one
= scope
.ObtainDynamicModuleWithStrongName ();
50 Assert
.IsNotNull (scope
.StrongNamedModule
);
51 Assert
.IsNull (scope
.WeakNamedModule
);
52 Assert
.AreSame (one
, scope
.StrongNamedModule
);
54 ModuleBuilder two
= scope
.ObtainDynamicModuleWithWeakName ();
55 Assert
.IsNotNull (scope
.StrongNamedModule
);
56 Assert
.IsNotNull (scope
.WeakNamedModule
);
57 Assert
.AreSame (two
, scope
.WeakNamedModule
);
59 Assert
.AreNotSame (one
, two
);
60 Assert
.AreNotSame (one
.Assembly
, two
.Assembly
);
62 ModuleBuilder three
= scope
.ObtainDynamicModuleWithStrongName ();
63 ModuleBuilder four
= scope
.ObtainDynamicModuleWithWeakName ();
65 Assert
.AreSame (one
, three
);
66 Assert
.AreSame (two
, four
);
72 public void ImplicitModulePaths ()
74 ModuleScope scope
= new ModuleScope (true);
75 Assert
.AreEqual (ModuleScope
.DEFAULT_FILE_NAME
, scope
.StrongNamedModuleName
);
76 Assert
.AreEqual (Path
.Combine (Environment
.CurrentDirectory
, ModuleScope
.DEFAULT_FILE_NAME
),
77 scope
.ObtainDynamicModuleWithStrongName ().FullyQualifiedName
);
78 Assert
.IsNull (scope
.StrongNamedModuleDirectory
);
80 Assert
.AreEqual (ModuleScope
.DEFAULT_FILE_NAME
, scope
.WeakNamedModuleName
);
81 Assert
.AreEqual (Path
.Combine (Environment
.CurrentDirectory
, ModuleScope
.DEFAULT_FILE_NAME
),
82 scope
.ObtainDynamicModuleWithWeakName ().FullyQualifiedName
);
83 Assert
.IsNull (scope
.WeakNamedModuleDirectory
);
87 public void ExplicitModulePaths ()
89 ModuleScope scope
= new ModuleScope (true, "Strong", "StrongModule.dll", "Weak", "WeakModule.dll");
90 Assert
.AreEqual ("StrongModule.dll", scope
.StrongNamedModuleName
);
91 Assert
.AreEqual (Path
.Combine (Environment
.CurrentDirectory
, "StrongModule.dll"), scope
.ObtainDynamicModuleWithStrongName ().FullyQualifiedName
);
92 Assert
.IsNull (scope
.StrongNamedModuleDirectory
);
94 Assert
.AreEqual ("WeakModule.dll", scope
.WeakNamedModuleName
);
95 Assert
.AreEqual (Path
.Combine (Environment
.CurrentDirectory
, "WeakModule.dll"), scope
.ObtainDynamicModuleWithWeakName ().FullyQualifiedName
);
96 Assert
.IsNull (scope
.WeakNamedModuleDirectory
);
98 scope
= new ModuleScope (true, "Strong", @"c:\Foo\StrongModule.dll", "Weak", @"d:\Bar\WeakModule.dll");
99 Assert
.AreEqual ("StrongModule.dll", scope
.StrongNamedModuleName
);
100 Assert
.AreEqual (@"c:\Foo\StrongModule.dll", scope
.ObtainDynamicModuleWithStrongName ().FullyQualifiedName
);
101 Assert
.AreEqual (@"c:\Foo", scope
.StrongNamedModuleDirectory
);
103 Assert
.AreEqual ("WeakModule.dll", scope
.WeakNamedModuleName
);
104 Assert
.AreEqual (@"d:\Bar\WeakModule.dll", scope
.ObtainDynamicModuleWithWeakName ().FullyQualifiedName
);
105 Assert
.AreEqual (@"d:\Bar", scope
.WeakNamedModuleDirectory
);
110 private static void CheckSignedSavedAssembly (string path
)
112 Assert
.IsTrue (File
.Exists (path
));
114 AssemblyName assemblyName
= AssemblyName
.GetAssemblyName (path
);
115 Assert
.AreEqual (ModuleScope
.DEFAULT_ASSEMBLY_NAME
, assemblyName
.Name
);
117 byte[] keyPairBytes
= ModuleScope
.GetKeyPair ();
118 StrongNameKeyPair keyPair
= new StrongNameKeyPair (keyPairBytes
);
119 byte[] loadedPublicKey
= assemblyName
.GetPublicKey ();
121 Assert
.AreEqual (keyPair
.PublicKey
.Length
, loadedPublicKey
.Length
);
122 for (int i
= 0; i
< keyPair
.PublicKey
.Length
; ++i
)
123 Assert
.AreEqual (keyPair
.PublicKey
[i
], loadedPublicKey
[i
]);
127 public void SaveSigned ()
129 ModuleScope scope
= new ModuleScope (true);
130 scope
.ObtainDynamicModuleWithStrongName ();
132 string path
= ModuleScope
.DEFAULT_FILE_NAME
;
133 if (File
.Exists (path
))
136 Assert
.IsFalse (File
.Exists (path
));
137 string savedPath
= scope
.SaveAssembly ();
139 Assert
.AreEqual (savedPath
, Path
.GetFullPath (path
));
141 CheckSignedSavedAssembly(path
);
146 public void SaveUnsigned ()
148 ModuleScope scope
= new ModuleScope (true);
149 scope
.ObtainDynamicModuleWithWeakName ();
151 string path
= ModuleScope
.DEFAULT_FILE_NAME
;
152 if (File
.Exists (path
))
155 Assert
.IsFalse (File
.Exists (path
));
156 string savedPath
= scope
.SaveAssembly ();
158 Assert
.AreEqual (savedPath
, Path
.GetFullPath (path
));
160 CheckUnsignedSavedAssembly(path
);
165 public void SaveWithPath ()
167 string strongModulePath
= Path
.GetTempFileName ();
168 string weakModulePath
= Path
.GetTempFileName ();
170 File
.Delete (strongModulePath
);
171 File
.Delete (weakModulePath
);
173 Assert
.IsFalse (File
.Exists (strongModulePath
));
174 Assert
.IsFalse (File
.Exists (weakModulePath
));
176 ModuleScope scope
= new ModuleScope (true, "Strong", strongModulePath
, "Weak", weakModulePath
);
177 scope
.ObtainDynamicModuleWithStrongName ();
178 scope
.ObtainDynamicModuleWithWeakName ();
180 scope
.SaveAssembly (true);
181 scope
.SaveAssembly (false);
183 Assert
.IsTrue (File
.Exists (strongModulePath
));
184 Assert
.IsTrue (File
.Exists (weakModulePath
));
186 File
.Delete (strongModulePath
);
187 File
.Delete (weakModulePath
);
190 private static void CheckUnsignedSavedAssembly (string path
)
192 Assert
.IsTrue (File
.Exists (path
));
194 AssemblyName assemblyName
= AssemblyName
.GetAssemblyName (path
);
195 Assert
.AreEqual (ModuleScope
.DEFAULT_ASSEMBLY_NAME
, assemblyName
.Name
);
197 byte[] loadedPublicKey
= assemblyName
.GetPublicKey ();
198 Assert
.IsNull (loadedPublicKey
);
202 public void SaveReturnsNullWhenNoModuleObtained ()
204 ModuleScope scope
= new ModuleScope (true);
205 Assert
.IsNull (scope
.SaveAssembly ());
209 [ExpectedException (typeof (InvalidOperationException
))]
210 public void SaveThrowsWhenMultipleAssembliesGenerated ()
212 ModuleScope scope
= new ModuleScope (true);
213 scope
.ObtainDynamicModuleWithStrongName ();
214 scope
.ObtainDynamicModuleWithWeakName ();
216 scope
.SaveAssembly ();
220 public void SaveWithFlagFalseDoesntThrowsWhenMultipleAssembliesGenerated ()
222 ModuleScope scope
= new ModuleScope (false);
223 scope
.ObtainDynamicModuleWithStrongName ();
224 scope
.ObtainDynamicModuleWithWeakName ();
226 scope
.SaveAssembly ();
230 public void ExplicitSaveWorksEvenWhenMultipleAssembliesGenerated ()
232 ModuleScope scope
= new ModuleScope (true);
233 scope
.ObtainDynamicModuleWithStrongName ();
234 scope
.ObtainDynamicModuleWithWeakName ();
236 scope
.SaveAssembly (true);
237 CheckSignedSavedAssembly (ModuleScope
.DEFAULT_FILE_NAME
);
239 scope
.SaveAssembly (false);
240 CheckUnsignedSavedAssembly (ModuleScope
.DEFAULT_FILE_NAME
);
242 File
.Delete (ModuleScope
.DEFAULT_FILE_NAME
);
246 [ExpectedException (typeof (InvalidOperationException
))]
247 public void ExplicitSaveThrowsWhenSpecifiedAssemblyNotGeneratedWeakName ()
249 ModuleScope scope
= new ModuleScope (true);
250 scope
.ObtainDynamicModuleWithStrongName ();
252 scope
.SaveAssembly (false);
256 [ExpectedException (typeof (InvalidOperationException
))]
257 public void ExplicitSaveThrowsWhenSpecifiedAssemblyNotGeneratedStrongName ()
259 ModuleScope scope
= new ModuleScope (true);
260 scope
.ObtainDynamicModuleWithWeakName ();
262 scope
.SaveAssembly (true);
266 public void SavedAssemblyHasCacheMappings ()
268 ModuleScope scope
= new ModuleScope (true);
269 scope
.ObtainDynamicModuleWithWeakName ();
271 string savedPath
= scope
.SaveAssembly ();
273 CrossAppDomainCaller
.RunInOtherAppDomain (delegate (object[] args
)
275 Assembly assembly
= Assembly
.LoadFrom ((string)args
[0]);
276 Assert
.IsTrue (assembly
.IsDefined (typeof (CacheMappingsAttribute
), false));
280 File
.Delete (savedPath
);
284 public void CacheMappingsHoldTypes ()
286 ModuleScope scope
= new ModuleScope (true);
287 DefaultProxyBuilder builder
= new DefaultProxyBuilder (scope
);
288 Type cp
= builder
.CreateClassProxy (typeof (object), ProxyGenerationOptions
.Default
);
290 string savedPath
= scope
.SaveAssembly ();
292 CrossAppDomainCaller
.RunInOtherAppDomain (delegate (object[] args
)
294 Assembly assembly
= Assembly
.LoadFrom ((string) args
[0]);
295 CacheMappingsAttribute attribute
= (CacheMappingsAttribute
) assembly
.GetCustomAttributes (typeof (CacheMappingsAttribute
), false)[0];
296 Dictionary
<CacheKey
, string> entries
= attribute
.GetDeserializedMappings();
297 Assert
.AreEqual (1, entries
.Count
);
299 CacheKey key
= new CacheKey (typeof (object), new Type
[0], ProxyGenerationOptions
.Default
);
300 Assert
.IsTrue (entries
.ContainsKey (key
));
301 Assert
.AreEqual (args
[1], entries
[key
]);
303 savedPath
, cp
.FullName
);
305 File
.Delete (savedPath
);
309 public void GeneratedAssembliesDefaultName ()
311 ModuleScope scope
= new ModuleScope ();
312 ModuleBuilder strong
= scope
.ObtainDynamicModuleWithStrongName ();
313 ModuleBuilder weak
= scope
.ObtainDynamicModuleWithWeakName ();
315 Assert
.AreEqual (ModuleScope
.DEFAULT_ASSEMBLY_NAME
, strong
.Assembly
.GetName ().Name
);
316 Assert
.AreEqual (ModuleScope
.DEFAULT_ASSEMBLY_NAME
, weak
.Assembly
.GetName ().Name
);
320 public void GeneratedAssembliesWithCustomName ()
322 ModuleScope scope
= new ModuleScope (false, "Strong", "Module1.dll", "Weak", "Module2,dll");
323 ModuleBuilder strong
= scope
.ObtainDynamicModuleWithStrongName ();
324 ModuleBuilder weak
= scope
.ObtainDynamicModuleWithWeakName ();
326 Assert
.AreEqual ("Strong", strong
.Assembly
.GetName ().Name
);
327 Assert
.AreEqual ("Weak", weak
.Assembly
.GetName ().Name
);
331 public void ModuleScopeDoesntTryToDeleteFromCurrentDirectory ()
333 string moduleDirectory
= Path
.Combine (Environment
.CurrentDirectory
, "GeneratedDlls");
334 if (Directory
.Exists (moduleDirectory
))
335 Directory
.Delete (moduleDirectory
, true);
337 string strongModulePath
= Path
.Combine (moduleDirectory
, "Strong.dll");
338 string weakModulePath
= Path
.Combine (moduleDirectory
, "Weak.dll");
340 Directory
.CreateDirectory(moduleDirectory
);
341 ModuleScope scope
= new ModuleScope (true, "Strong", strongModulePath
, "Weak", weakModulePath
);
343 using (File
.Create (Path
.Combine (Environment
.CurrentDirectory
, "Strong.dll")))
345 scope
.ObtainDynamicModuleWithStrongName ();
346 scope
.SaveAssembly (true); // this will throw if SaveAssembly tries to delete from the current directory
349 using (File
.Create (Path
.Combine (Environment
.CurrentDirectory
, "Weak.dll")))
351 scope
.ObtainDynamicModuleWithWeakName ();
352 scope
.SaveAssembly (false); // this will throw if SaveAssembly tries to delete from the current directory
357 public void DefaultProxyBuilderWithSpecificScope ()
359 ModuleScope scope
= new ModuleScope (false);
360 DefaultProxyBuilder builder
= new DefaultProxyBuilder (scope
);
361 Assert
.AreSame (scope
, builder
.ModuleScope
);
365 [ExpectedException (typeof (ArgumentException
))]
366 public void LoadAssemblyIntoCache_InvalidAssembly ()
368 ModuleScope newScope
= new ModuleScope (false);
369 newScope
.LoadAssemblyIntoCache (Assembly
.GetExecutingAssembly());
373 public void LoadAssemblyIntoCache_CreateClassProxy ()
375 CheckLoadAssemblyIntoCache (delegate (IProxyBuilder builder
)
377 return builder
.CreateClassProxy (typeof (object), ProxyGenerationOptions
.Default
);
382 public void LoadAssemblyIntoCache_CreateInterfaceProxyTypeWithoutTarget ()
384 CheckLoadAssemblyIntoCache (delegate (IProxyBuilder builder
)
386 return builder
.CreateInterfaceProxyTypeWithoutTarget (typeof (IServiceProvider
), new Type
[0], ProxyGenerationOptions
.Default
);
391 public void LoadAssemblyIntoCache_CreateInterfaceProxyTypeWithTarget ()
393 CheckLoadAssemblyIntoCache (delegate (IProxyBuilder builder
)
395 return builder
.CreateInterfaceProxyTypeWithTarget (typeof (IMyInterface2
), new Type
[0], typeof (MyInterfaceImpl
), ProxyGenerationOptions
.Default
);
400 public void LoadAssemblyIntoCache_CreateInterfaceProxyTypeWithTargetInterface ()
402 CheckLoadAssemblyIntoCache (delegate (IProxyBuilder builder
)
404 return builder
.CreateInterfaceProxyTypeWithTargetInterface (typeof (IMyInterface2
), ProxyGenerationOptions
.Default
);
409 public void LoadAssemblyIntoCache_DifferentGenerationOptions ()
411 ModuleScope savedScope
= new ModuleScope (true);
412 DefaultProxyBuilder builder
= new DefaultProxyBuilder (savedScope
);
414 ProxyGenerationOptions options1
= new ProxyGenerationOptions();
415 options1
.AddMixinInstance (new DateTime ());
416 ProxyGenerationOptions options2
= ProxyGenerationOptions
.Default
;
418 Type cp1
= builder
.CreateClassProxy (typeof (object), options1
);
419 Type cp2
= builder
.CreateClassProxy (typeof (object), options2
);
420 Assert
.AreNotSame (cp1
, cp2
);
421 Assert
.AreSame (cp1
, builder
.CreateClassProxy (typeof (object), options1
));
422 Assert
.AreSame (cp2
, builder
.CreateClassProxy (typeof (object), options2
));
424 string path
= savedScope
.SaveAssembly ();
426 CrossAppDomainCaller
.RunInOtherAppDomain (delegate (object[] args
)
428 ModuleScope newScope
= new ModuleScope (false);
429 DefaultProxyBuilder newBuilder
= new DefaultProxyBuilder (newScope
);
431 Assembly assembly
= Assembly
.LoadFrom ((string) args
[0]);
432 newScope
.LoadAssemblyIntoCache (assembly
);
434 ProxyGenerationOptions newOptions1
= new ProxyGenerationOptions ();
435 newOptions1
.AddMixinInstance (new DateTime ());
436 ProxyGenerationOptions newOptions2
= ProxyGenerationOptions
.Default
;
438 Type loadedCP1
= newBuilder
.CreateClassProxy (typeof (object), newOptions1
);
439 Type loadedCP2
= newBuilder
.CreateClassProxy (typeof (object), newOptions2
);
440 Assert
.AreNotSame (loadedCP1
, loadedCP2
);
441 Assert
.AreEqual (assembly
, loadedCP1
.Assembly
);
442 Assert
.AreEqual (assembly
, loadedCP2
.Assembly
);
448 private delegate Type
ProxyCreator (IProxyBuilder proxyBuilder
);
450 private void CheckLoadAssemblyIntoCache (ProxyCreator creator
)
452 ModuleScope savedScope
= new ModuleScope (true);
453 DefaultProxyBuilder builder
= new DefaultProxyBuilder (savedScope
);
455 Type cp
= creator (builder
);
456 Assert
.AreSame (cp
, creator (builder
));
458 string path
= savedScope
.SaveAssembly ();
460 CrossAppDomainCaller
.RunInOtherAppDomain (delegate (object[] args
)
462 ModuleScope newScope
= new ModuleScope (false);
463 DefaultProxyBuilder newBuilder
= new DefaultProxyBuilder (newScope
);
465 Assembly assembly
= Assembly
.LoadFrom ((string) args
[0]);
466 newScope
.LoadAssemblyIntoCache (assembly
);
468 Type loadedCP
= assembly
.GetType ((string) args
[1]);
469 Assert
.AreSame (loadedCP
, ((ProxyCreator
) args
[2])(newBuilder
));
470 Assert
.AreEqual (assembly
, ((ProxyCreator
) args
[2]) (newBuilder
).Assembly
);
471 }, path
, cp
.FullName
, creator
);