PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/V4/PrismLibrary/Desktop/Prism.Tests/Modularity/ModuleManagerFixture.cs

#
C# | 542 lines | 434 code | 91 blank | 17 comment | 14 complexity | 6a6d819394ea7cf282c609bfa313e2b0 MD5 | raw file
  1. //===================================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4. //===================================================================================
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===================================================================================
  11. // The example companies, organizations, products, domain names,
  12. // e-mail addresses, logos, people, places, and events depicted
  13. // herein are fictitious. No association with any real company,
  14. // organization, product, domain name, email address, logo, person,
  15. // places, or events is intended or should be inferred.
  16. //===================================================================================
  17. using System;
  18. using System.Collections.Generic;
  19. using Microsoft.Practices.Prism.Tests.Mocks;
  20. using Microsoft.Practices.Prism;
  21. using Microsoft.Practices.Prism.Logging;
  22. using Microsoft.Practices.Prism.Modularity;
  23. using Microsoft.VisualStudio.TestTools.UnitTesting;
  24. using Moq;
  25. namespace Microsoft.Practices.Prism.Tests.Modularity
  26. {
  27. [TestClass]
  28. public class ModuleManagerFixture
  29. {
  30. [TestMethod]
  31. [ExpectedException(typeof(ArgumentNullException))]
  32. public void NullLoaderThrows()
  33. {
  34. new ModuleManager(null, new MockModuleCatalog(), new MockLogger());
  35. }
  36. [TestMethod]
  37. [ExpectedException(typeof(ArgumentNullException))]
  38. public void NullCatalogThrows()
  39. {
  40. new ModuleManager(new MockModuleInitializer(), null, new MockLogger());
  41. }
  42. [TestMethod]
  43. [ExpectedException(typeof(ArgumentNullException))]
  44. public void NullLoggerThrows()
  45. {
  46. new ModuleManager(new MockModuleInitializer(), new MockModuleCatalog(), null);
  47. }
  48. [TestMethod]
  49. public void ShouldInvokeRetrieverForModules()
  50. {
  51. var loader = new MockModuleInitializer();
  52. var moduleInfo = CreateModuleInfo("needsRetrieval", InitializationMode.WhenAvailable);
  53. var catalog = new MockModuleCatalog { Modules = { moduleInfo } };
  54. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  55. var moduleTypeLoader = new MockModuleTypeLoader();
  56. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  57. manager.Run();
  58. Assert.IsTrue(moduleTypeLoader.LoadedModules.Contains(moduleInfo));
  59. }
  60. [TestMethod]
  61. public void ShouldInitializeModulesOnRetrievalCompleted()
  62. {
  63. var loader = new MockModuleInitializer();
  64. var backgroungModuleInfo = CreateModuleInfo("NeedsRetrieval", InitializationMode.WhenAvailable);
  65. var catalog = new MockModuleCatalog { Modules = { backgroungModuleInfo } };
  66. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  67. var moduleTypeLoader = new MockModuleTypeLoader();
  68. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  69. Assert.IsFalse(loader.InitializeCalled);
  70. manager.Run();
  71. Assert.IsTrue(loader.InitializeCalled);
  72. Assert.AreEqual(1, loader.InitializedModules.Count);
  73. Assert.AreEqual(backgroungModuleInfo, loader.InitializedModules[0]);
  74. }
  75. [TestMethod]
  76. public void ShouldInitializeModuleOnDemand()
  77. {
  78. var loader = new MockModuleInitializer();
  79. var onDemandModule = CreateModuleInfo("NeedsRetrieval", InitializationMode.OnDemand);
  80. var catalog = new MockModuleCatalog { Modules = { onDemandModule } };
  81. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  82. var moduleRetriever = new MockModuleTypeLoader();
  83. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleRetriever };
  84. manager.Run();
  85. Assert.IsFalse(loader.InitializeCalled);
  86. Assert.AreEqual(0, moduleRetriever.LoadedModules.Count);
  87. manager.LoadModule("NeedsRetrieval");
  88. Assert.AreEqual(1, moduleRetriever.LoadedModules.Count);
  89. Assert.IsTrue(loader.InitializeCalled);
  90. Assert.AreEqual(1, loader.InitializedModules.Count);
  91. Assert.AreEqual(onDemandModule, loader.InitializedModules[0]);
  92. }
  93. [TestMethod]
  94. [ExpectedException(typeof(ModuleNotFoundException))]
  95. public void InvalidOnDemandModuleNameThrows()
  96. {
  97. var loader = new MockModuleInitializer();
  98. var catalog = new MockModuleCatalog { Modules = new List<ModuleInfo> { CreateModuleInfo("Missing", InitializationMode.OnDemand) } };
  99. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  100. var moduleTypeLoader = new MockModuleTypeLoader();
  101. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  102. manager.Run();
  103. manager.LoadModule("NonExistent");
  104. }
  105. [TestMethod]
  106. [ExpectedException(typeof(ModuleNotFoundException))]
  107. public void EmptyOnDemandModuleReturnedThrows()
  108. {
  109. var loader = new MockModuleInitializer();
  110. var catalog = new MockModuleCatalog { CompleteListWithDependencies = modules => new List<ModuleInfo>() };
  111. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  112. var moduleRetriever = new MockModuleTypeLoader();
  113. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleRetriever };
  114. manager.Run();
  115. manager.LoadModule("NullModule");
  116. }
  117. [TestMethod]
  118. public void ShouldNotLoadTypeIfModuleInitialized()
  119. {
  120. var loader = new MockModuleInitializer();
  121. var alreadyPresentModule = CreateModuleInfo(typeof(MockModule), InitializationMode.WhenAvailable);
  122. alreadyPresentModule.State = ModuleState.ReadyForInitialization;
  123. var catalog = new MockModuleCatalog { Modules = { alreadyPresentModule } };
  124. var manager = new ModuleManager(loader, catalog, new MockLogger());
  125. var moduleTypeLoader = new MockModuleTypeLoader();
  126. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  127. manager.Run();
  128. Assert.IsFalse(moduleTypeLoader.LoadedModules.Contains(alreadyPresentModule));
  129. Assert.IsTrue(loader.InitializeCalled);
  130. Assert.AreEqual(1, loader.InitializedModules.Count);
  131. Assert.AreEqual(alreadyPresentModule, loader.InitializedModules[0]);
  132. }
  133. [TestMethod]
  134. public void ShouldNotLoadSameModuleTwice()
  135. {
  136. var loader = new MockModuleInitializer();
  137. var onDemandModule = CreateModuleInfo(typeof(MockModule), InitializationMode.OnDemand);
  138. var catalog = new MockModuleCatalog { Modules = { onDemandModule } };
  139. var manager = new ModuleManager(loader, catalog, new MockLogger());
  140. manager.Run();
  141. manager.LoadModule("MockModule");
  142. loader.InitializeCalled = false;
  143. manager.LoadModule("MockModule");
  144. Assert.IsFalse(loader.InitializeCalled);
  145. }
  146. [TestMethod]
  147. public void ShouldNotLoadModuleThatNeedsRetrievalTwice()
  148. {
  149. var loader = new MockModuleInitializer();
  150. var onDemandModule = CreateModuleInfo("ModuleThatNeedsRetrieval", InitializationMode.OnDemand);
  151. var catalog = new MockModuleCatalog { Modules = { onDemandModule } };
  152. var manager = new ModuleManager(loader, catalog, new MockLogger());
  153. var moduleTypeLoader = new MockModuleTypeLoader();
  154. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  155. manager.Run();
  156. manager.LoadModule("ModuleThatNeedsRetrieval");
  157. moduleTypeLoader.RaiseLoadModuleCompleted(new LoadModuleCompletedEventArgs(onDemandModule, null));
  158. loader.InitializeCalled = false;
  159. manager.LoadModule("ModuleThatNeedsRetrieval");
  160. Assert.IsFalse(loader.InitializeCalled);
  161. }
  162. [TestMethod]
  163. public void ShouldCallValidateCatalogBeforeGettingGroupsFromCatalog()
  164. {
  165. var loader = new MockModuleInitializer();
  166. var catalog = new MockModuleCatalog();
  167. var manager = new ModuleManager(loader, catalog, new MockLogger());
  168. bool validateCatalogCalled = false;
  169. bool getModulesCalledBeforeValidate = false;
  170. catalog.ValidateCatalog = () => validateCatalogCalled = true;
  171. catalog.CompleteListWithDependencies = f =>
  172. {
  173. if (!validateCatalogCalled)
  174. {
  175. getModulesCalledBeforeValidate = true;
  176. }
  177. return null;
  178. };
  179. manager.Run();
  180. Assert.IsTrue(validateCatalogCalled);
  181. Assert.IsFalse(getModulesCalledBeforeValidate);
  182. }
  183. [TestMethod]
  184. public void ShouldNotInitializeIfDependenciesAreNotMet()
  185. {
  186. var loader = new MockModuleInitializer();
  187. var requiredModule = CreateModuleInfo("ModuleThatNeedsRetrieval1", InitializationMode.WhenAvailable);
  188. requiredModule.ModuleName = "RequiredModule";
  189. var dependantModuleInfo = CreateModuleInfo("ModuleThatNeedsRetrieval2", InitializationMode.WhenAvailable, "RequiredModule");
  190. var catalog = new MockModuleCatalog { Modules = { requiredModule, dependantModuleInfo } };
  191. catalog.GetDependentModules = m => new[] { requiredModule };
  192. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  193. var moduleTypeLoader = new MockModuleTypeLoader();
  194. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  195. manager.Run();
  196. moduleTypeLoader.RaiseLoadModuleCompleted(new LoadModuleCompletedEventArgs(dependantModuleInfo, null));
  197. Assert.IsFalse(loader.InitializeCalled);
  198. Assert.AreEqual(0, loader.InitializedModules.Count);
  199. }
  200. [TestMethod]
  201. public void ShouldInitializeIfDependenciesAreMet()
  202. {
  203. var initializer = new MockModuleInitializer();
  204. var requiredModule = CreateModuleInfo("ModuleThatNeedsRetrieval1", InitializationMode.WhenAvailable);
  205. requiredModule.ModuleName = "RequiredModule";
  206. var dependantModuleInfo = CreateModuleInfo("ModuleThatNeedsRetrieval2", InitializationMode.WhenAvailable, "RequiredModule");
  207. var catalog = new MockModuleCatalog { Modules = { requiredModule, dependantModuleInfo } };
  208. catalog.GetDependentModules = delegate(ModuleInfo module)
  209. {
  210. if (module == dependantModuleInfo)
  211. return new[] { requiredModule };
  212. else
  213. return null;
  214. };
  215. ModuleManager manager = new ModuleManager(initializer, catalog, new MockLogger());
  216. var moduleTypeLoader = new MockModuleTypeLoader();
  217. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  218. manager.Run();
  219. Assert.IsTrue(initializer.InitializeCalled);
  220. Assert.AreEqual(2, initializer.InitializedModules.Count);
  221. }
  222. [TestMethod]
  223. public void ShouldThrowOnRetrieverErrorAndWrapException()
  224. {
  225. var loader = new MockModuleInitializer();
  226. var moduleInfo = CreateModuleInfo("NeedsRetrieval", InitializationMode.WhenAvailable);
  227. var catalog = new MockModuleCatalog { Modules = { moduleInfo } };
  228. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  229. var moduleTypeLoader = new MockModuleTypeLoader();
  230. Exception retrieverException = new Exception();
  231. moduleTypeLoader.LoadCompletedError = retrieverException;
  232. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  233. Assert.IsFalse(loader.InitializeCalled);
  234. try
  235. {
  236. manager.Run();
  237. }
  238. catch (Exception ex)
  239. {
  240. Assert.IsInstanceOfType(ex, typeof(ModuleTypeLoadingException));
  241. Assert.AreEqual(moduleInfo.ModuleName, ((ModularityException)ex).ModuleName);
  242. StringAssert.Contains(ex.Message, moduleInfo.ModuleName);
  243. Assert.AreSame(retrieverException, ex.InnerException);
  244. return;
  245. }
  246. Assert.Fail("Exception not thrown.");
  247. }
  248. [TestMethod]
  249. [ExpectedException(typeof(ModuleTypeLoaderNotFoundException))]
  250. public void ShouldThrowIfNoRetrieverCanRetrieveModule()
  251. {
  252. var loader = new MockModuleInitializer();
  253. var catalog = new MockModuleCatalog { Modules = { CreateModuleInfo("ModuleThatNeedsRetrieval", InitializationMode.WhenAvailable) } };
  254. ModuleManager manager = new ModuleManager(loader, catalog, new MockLogger());
  255. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { new MockModuleTypeLoader() { canLoadModuleTypeReturnValue = false } };
  256. manager.Run();
  257. }
  258. [TestMethod]
  259. public void ShouldLogMessageOnModuleRetrievalError()
  260. {
  261. var loader = new MockModuleInitializer();
  262. var moduleInfo = CreateModuleInfo("ModuleThatNeedsRetrieval", InitializationMode.WhenAvailable);
  263. var catalog = new MockModuleCatalog { Modules = { moduleInfo } };
  264. var logger = new MockLogger();
  265. ModuleManager manager = new ModuleManager(loader, catalog, logger);
  266. var moduleTypeLoader = new MockModuleTypeLoader();
  267. moduleTypeLoader.LoadCompletedError = new Exception();
  268. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { moduleTypeLoader };
  269. try
  270. {
  271. manager.Run();
  272. }
  273. catch
  274. {
  275. // Ignore all errors to make sure logger is called even if errors thrown.
  276. }
  277. Assert.IsNotNull(logger.LastMessage);
  278. StringAssert.Contains(logger.LastMessage, "ModuleThatNeedsRetrieval");
  279. Assert.AreEqual<Category>(Category.Exception, logger.LastMessageCategory);
  280. }
  281. [TestMethod]
  282. public void ShouldWorkIfModuleLoadsAnotherOnDemandModuleWhenInitializing()
  283. {
  284. var initializer = new StubModuleInitializer();
  285. var onDemandModule = CreateModuleInfo(typeof(MockModule), InitializationMode.OnDemand);
  286. onDemandModule.ModuleName = "OnDemandModule";
  287. var moduleThatLoadsOtherModule = CreateModuleInfo(typeof(MockModule), InitializationMode.WhenAvailable);
  288. var catalog = new MockModuleCatalog { Modules = { moduleThatLoadsOtherModule, onDemandModule } };
  289. ModuleManager manager = new ModuleManager(initializer, catalog, new MockLogger());
  290. bool onDemandModuleWasInitialized = false;
  291. initializer.Initialize = m =>
  292. {
  293. if (m == moduleThatLoadsOtherModule)
  294. {
  295. manager.LoadModule("OnDemandModule");
  296. }
  297. else if (m == onDemandModule)
  298. {
  299. onDemandModuleWasInitialized = true;
  300. }
  301. };
  302. manager.Run();
  303. Assert.IsTrue(onDemandModuleWasInitialized);
  304. }
  305. [TestMethod]
  306. public void ModuleManagerIsDisposable()
  307. {
  308. Mock<IModuleInitializer> mockInit = new Mock<IModuleInitializer>();
  309. var moduleInfo = CreateModuleInfo("needsRetrieval", InitializationMode.WhenAvailable);
  310. var catalog = new Mock<IModuleCatalog>();
  311. ModuleManager manager = new ModuleManager(mockInit.Object, catalog.Object, new MockLogger());
  312. IDisposable disposableManager = manager as IDisposable;
  313. Assert.IsNotNull(disposableManager);
  314. }
  315. [TestMethod]
  316. public void DisposeDoesNotThrowWithNonDisposableTypeLoaders()
  317. {
  318. Mock<IModuleInitializer> mockInit = new Mock<IModuleInitializer>();
  319. var moduleInfo = CreateModuleInfo("needsRetrieval", InitializationMode.WhenAvailable);
  320. var catalog = new Mock<IModuleCatalog>();
  321. ModuleManager manager = new ModuleManager(mockInit.Object, catalog.Object, new MockLogger());
  322. var mockTypeLoader = new Mock<IModuleTypeLoader>();
  323. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> {mockTypeLoader.Object};
  324. try
  325. {
  326. manager.Dispose();
  327. }
  328. catch(Exception)
  329. {
  330. Assert.Fail();
  331. }
  332. }
  333. [TestMethod]
  334. public void DisposeCleansUpDisposableTypeLoaders()
  335. {
  336. Mock<IModuleInitializer> mockInit = new Mock<IModuleInitializer>();
  337. var moduleInfo = CreateModuleInfo("needsRetrieval", InitializationMode.WhenAvailable);
  338. var catalog = new Mock<IModuleCatalog>();
  339. ModuleManager manager = new ModuleManager(mockInit.Object, catalog.Object, new MockLogger());
  340. var mockTypeLoader = new Mock<IModuleTypeLoader>();
  341. var disposableMockTypeLoader = mockTypeLoader.As<IDisposable>();
  342. disposableMockTypeLoader.Setup(loader => loader.Dispose());
  343. manager.ModuleTypeLoaders = new List<IModuleTypeLoader> { mockTypeLoader.Object };
  344. manager.Dispose();
  345. disposableMockTypeLoader.Verify(loader => loader.Dispose(), Times.Once());
  346. }
  347. [TestMethod]
  348. public void DisposeDoesNotThrowWithMixedTypeLoaders()
  349. {
  350. Mock<IModuleInitializer> mockInit = new Mock<IModuleInitializer>();
  351. var moduleInfo = CreateModuleInfo("needsRetrieval", InitializationMode.WhenAvailable);
  352. var catalog = new Mock<IModuleCatalog>();
  353. ModuleManager manager = new ModuleManager(mockInit.Object, catalog.Object, new MockLogger());
  354. var mockTypeLoader1 = new Mock<IModuleTypeLoader>();
  355. var mockTypeLoader = new Mock<IModuleTypeLoader>();
  356. var disposableMockTypeLoader = mockTypeLoader.As<IDisposable>();
  357. disposableMockTypeLoader.Setup(loader => loader.Dispose());
  358. manager.ModuleTypeLoaders = new List<IModuleTypeLoader>() { mockTypeLoader1.Object, mockTypeLoader.Object };
  359. try
  360. {
  361. manager.Dispose();
  362. }
  363. catch (Exception)
  364. {
  365. Assert.Fail();
  366. }
  367. disposableMockTypeLoader.Verify(loader => loader.Dispose(), Times.Once());
  368. }
  369. private static ModuleInfo CreateModuleInfo(string name, InitializationMode initializationMode, params string[] dependsOn)
  370. {
  371. ModuleInfo moduleInfo = new ModuleInfo(name, name);
  372. moduleInfo.InitializationMode = initializationMode;
  373. moduleInfo.DependsOn.AddRange(dependsOn);
  374. return moduleInfo;
  375. }
  376. private static ModuleInfo CreateModuleInfo(Type type, InitializationMode initializationMode, params string[] dependsOn)
  377. {
  378. ModuleInfo moduleInfo = new ModuleInfo(type.Name, type.AssemblyQualifiedName);
  379. moduleInfo.InitializationMode = initializationMode;
  380. moduleInfo.DependsOn.AddRange(dependsOn);
  381. return moduleInfo;
  382. }
  383. }
  384. internal class MockModule : IModule
  385. {
  386. public void Initialize()
  387. {
  388. throw new System.NotImplementedException();
  389. }
  390. }
  391. internal class MockModuleCatalog : IModuleCatalog
  392. {
  393. public List<ModuleInfo> Modules = new List<ModuleInfo>();
  394. public Func<ModuleInfo, IEnumerable<ModuleInfo>> GetDependentModules;
  395. public Func<IEnumerable<ModuleInfo>, IEnumerable<ModuleInfo>> CompleteListWithDependencies;
  396. public Action ValidateCatalog;
  397. public void Initialize()
  398. {
  399. if (this.ValidateCatalog != null)
  400. {
  401. this.ValidateCatalog();
  402. }
  403. }
  404. IEnumerable<ModuleInfo> IModuleCatalog.Modules
  405. {
  406. get { return this.Modules; }
  407. }
  408. IEnumerable<ModuleInfo> IModuleCatalog.GetDependentModules(ModuleInfo moduleInfo)
  409. {
  410. if (GetDependentModules == null)
  411. return new List<ModuleInfo>();
  412. return GetDependentModules(moduleInfo);
  413. }
  414. IEnumerable<ModuleInfo> IModuleCatalog.CompleteListWithDependencies(IEnumerable<ModuleInfo> modules)
  415. {
  416. if (CompleteListWithDependencies != null)
  417. return CompleteListWithDependencies(modules);
  418. return modules;
  419. }
  420. public void AddModule(ModuleInfo moduleInfo)
  421. {
  422. this.Modules.Add(moduleInfo);
  423. }
  424. }
  425. internal class MockModuleInitializer : IModuleInitializer
  426. {
  427. public bool InitializeCalled;
  428. public List<ModuleInfo> InitializedModules = new List<ModuleInfo>();
  429. public void Initialize(ModuleInfo moduleInfo)
  430. {
  431. InitializeCalled = true;
  432. this.InitializedModules.Add(moduleInfo);
  433. }
  434. }
  435. internal class StubModuleInitializer : IModuleInitializer
  436. {
  437. public Action<ModuleInfo> Initialize;
  438. void IModuleInitializer.Initialize(ModuleInfo moduleInfo)
  439. {
  440. this.Initialize(moduleInfo);
  441. }
  442. }
  443. internal class MockDelegateModuleInitializer : IModuleInitializer
  444. {
  445. public Action<ModuleInfo> LoadBody;
  446. public void Initialize(ModuleInfo moduleInfo)
  447. {
  448. LoadBody(moduleInfo);
  449. }
  450. }
  451. }