PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ServiceManagement/Services/Commands.Test.Utilities/Common/FileSystemHelper.cs

https://gitlab.com/jslee1/azure-powershell
C# | 321 lines | 177 code | 35 blank | 109 comment | 19 complexity | c811efbeb7fff1d19d4f181d47955ba4 MD5 | raw file
  1. // ----------------------------------------------------------------------------------
  2. //
  3. // Copyright Microsoft Corporation
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. // ----------------------------------------------------------------------------------
  14. using System;
  15. using System.Diagnostics;
  16. using System.IO;
  17. using Microsoft.WindowsAzure.Commands.Common;
  18. using Microsoft.WindowsAzure.Commands.Utilities.CloudService;
  19. using Microsoft.WindowsAzure.Commands.Utilities.Common;
  20. using Microsoft.Azure.Commands.Common.Authentication;
  21. using Microsoft.Azure.Commands.Common.Authentication.Models;
  22. using Microsoft.Azure.ServiceManagemenet.Common;
  23. namespace Microsoft.WindowsAzure.Commands.Test.Utilities.Common
  24. {
  25. /// <summary>
  26. /// Utility used to create files and directories and clean them up when
  27. /// complete.
  28. /// </summary>
  29. public class FileSystemHelper : IDisposable
  30. {
  31. /// <summary>
  32. /// Gets the path to the rootPath of the file system utilized by the test.
  33. /// </summary>
  34. public string RootPath { get; private set; }
  35. /// <summary>
  36. /// Gets or sets the path to a temporary Azure SDK which we use to
  37. /// store and cleanup after global files.
  38. /// </summary>
  39. public string AzureSdkPath { get; private set; }
  40. /// <summary>
  41. /// Gets a reference to the test class using the FileSystemHelper to
  42. /// provide access to its logging.
  43. /// </summary>
  44. public SMTestBase TestInstance { get; private set; }
  45. /// <summary>
  46. /// Monitors changes to the file system.
  47. /// </summary>
  48. private FileSystemWatcher _watcher = null;
  49. /// <summary>
  50. /// Gets or sets a value indicating whether to enable monitoring on
  51. /// the portion of the file system being managed by FileSystemHelper.
  52. /// </summary>
  53. public bool EnableMonitoring
  54. {
  55. get { return _watcher != null; }
  56. set
  57. {
  58. if (!value && _watcher != null)
  59. {
  60. // Dispose of the watcher if we're turning it off
  61. DisposeWatcher();
  62. }
  63. else if (value && _watcher == null)
  64. {
  65. // Create a file system watcher
  66. _watcher = new FileSystemWatcher();
  67. _watcher.Path = RootPath;
  68. _watcher.IncludeSubdirectories = true;
  69. _watcher.Changed += (s, e) => Log("<Watcher> Changed {0}", GetRelativePath(e.FullPath));
  70. _watcher.Created += (s, e) => Log("<Watcher> Created at {0}", GetRelativePath(e.FullPath));
  71. _watcher.Deleted += (s, e) => Log("<Watcher> Deleted at {0}", GetRelativePath(e.FullPath));
  72. _watcher.Renamed += (s, e) => Log("<Watcher> Renamed {0} to {1}", GetRelativePath(e.OldFullPath), GetRelativePath(e.FullPath));
  73. _watcher.EnableRaisingEvents = true;
  74. }
  75. }
  76. }
  77. /// <summary>
  78. /// Initializes a new FileSystemHelper to a random temp directory.
  79. /// </summary>
  80. /// <param name="testInstance">
  81. /// Reference to the test class (to access its logging).
  82. /// </param>
  83. public FileSystemHelper(SMTestBase testInstance)
  84. : this(testInstance, GetTemporaryDirectoryName())
  85. {
  86. }
  87. /// <summary>
  88. /// Initialize a new FileSystemHelper to a specific directory.
  89. /// </summary>
  90. /// <param name="testInstance">
  91. /// Reference to the test class (to access its logging).
  92. /// </param>
  93. /// <param name="rootPath">The rootPath directory.</param>
  94. public FileSystemHelper(SMTestBase testInstance, string rootPath)
  95. {
  96. Debug.Assert(testInstance != null);
  97. Debug.Assert(!string.IsNullOrEmpty(rootPath));
  98. TestInstance = testInstance;
  99. // Set the directory and create it if necessary.
  100. RootPath = rootPath;
  101. if (!FileUtilities.DataStore.DirectoryExists(rootPath))
  102. {
  103. Log("Creating directory {0}", rootPath);
  104. FileUtilities.DataStore.CreateDirectory(rootPath);
  105. }
  106. }
  107. /// <summary>
  108. /// Destroy the files and directories created during the test.
  109. /// </summary>
  110. public void Dispose()
  111. {
  112. Dispose(true);
  113. GC.SuppressFinalize(this);
  114. }
  115. protected virtual void Dispose(bool disposing)
  116. {
  117. if (disposing)
  118. {
  119. if (RootPath != null)
  120. {
  121. // Cleanup any certificates added during the test
  122. if (!string.IsNullOrEmpty(AzureSdkPath))
  123. {
  124. try { new RemoveAzurePublishSettingsCommand().RemovePublishSettingsProcess(AzureSdkPath); }
  125. catch { /* Cleanup failed, ignore*/ }
  126. AzureSdkPath = null;
  127. }
  128. Log("Deleting directory {0}", RootPath);
  129. try
  130. {
  131. FileUtilities.DataStore.DeleteDirectory(RootPath);
  132. }
  133. catch { }
  134. DisposeWatcher();
  135. // Note: We can't clear the RootPath until we've disposed the
  136. // watcher because its handlers will attempt to get relative
  137. // paths which will fail if there is no RootPath
  138. RootPath = null;
  139. }
  140. }
  141. }
  142. /// <summary>
  143. /// Dispose of the FileSystemWatcher we're using to monitor changes to
  144. /// the FileSystem.
  145. /// </summary>
  146. private void DisposeWatcher()
  147. {
  148. if (_watcher != null)
  149. {
  150. _watcher.EnableRaisingEvents = false;
  151. _watcher.Dispose();
  152. _watcher = null;
  153. }
  154. }
  155. /// <summary>
  156. /// Log a message from the FileSytemHelper.
  157. /// </summary>
  158. /// <param name="format">Message format.</param>
  159. /// <param name="args">Message argument.</param>
  160. private void Log(string format, params object[] args)
  161. {
  162. TestInstance.Log("[FileSystemHelper] " + format, args);
  163. }
  164. /// <summary>
  165. /// Get the path of a file relative to the FileSystemHelper's rootPath.
  166. /// </summary>
  167. /// <param name="fullPath">The full path to the file.</param>
  168. /// <returns>The path relative to the FileSystemHelper's rootPath.</returns>
  169. public string GetRelativePath(string fullPath)
  170. {
  171. Debug.Assert(!string.IsNullOrEmpty(fullPath));
  172. Debug.Assert(fullPath.StartsWith(RootPath, StringComparison.OrdinalIgnoreCase));
  173. return fullPath.Substring(RootPath.Length, fullPath.Length - RootPath.Length);
  174. }
  175. /// <summary>
  176. /// Get the full path to a file given a path relative to the
  177. /// FileSystemHelper's rootPath.
  178. /// </summary>
  179. /// <param name="relativePath">Relative path.</param>
  180. /// <returns>Corresponding full path.</returns>
  181. public string GetFullPath(string relativePath)
  182. {
  183. Debug.Assert(!string.IsNullOrEmpty(relativePath));
  184. return Path.Combine(RootPath, relativePath);
  185. }
  186. /// <summary>
  187. /// Create a random directory name that doesn't yet exist on disk.
  188. /// </summary>
  189. /// <returns>A random, non-existent directory name.</returns>
  190. public static string GetTemporaryDirectoryName()
  191. {
  192. string path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
  193. while (Directory.Exists(path))
  194. {
  195. path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
  196. }
  197. return path;
  198. }
  199. /// <summary>
  200. /// Create a new directory relative to the rootPath.
  201. /// </summary>
  202. /// <param name="relativePath">Relative path to the directory.</param>
  203. /// <returns>The full path to the directory.</returns>
  204. public string CreateDirectory(string relativePath)
  205. {
  206. Debug.Assert(!string.IsNullOrEmpty(relativePath));
  207. string path = Path.Combine(RootPath, relativePath);
  208. if (!FileUtilities.DataStore.DirectoryExists(path))
  209. {
  210. Log("Creating directory {0}", path);
  211. FileUtilities.DataStore.CreateDirectory(path);
  212. }
  213. return path;
  214. }
  215. /// <summary>
  216. /// Create an empty file relative to the rootPath.
  217. /// </summary>
  218. /// <param name="relativePath">Relative path to the file.</param>
  219. /// <returns>The full path to the file.</returns>
  220. public string CreateEmptyFile(string relativePath)
  221. {
  222. Debug.Assert(!string.IsNullOrEmpty(relativePath));
  223. string path = Path.Combine(RootPath, relativePath);
  224. if (!FileUtilities.DataStore.FileExists(path))
  225. {
  226. Log("Creating empty file {0}", path);
  227. FileUtilities.DataStore.WriteFile(path, "");
  228. }
  229. return path;
  230. }
  231. /// <summary>
  232. /// Create a temporary Azure SDK directory to simulate global files.
  233. /// </summary>
  234. /// <returns>The path to the temporary Azure SDK directory.</returns>
  235. public string CreateAzureSdkDirectoryAndImportPublishSettings()
  236. {
  237. return CreateAzureSdkDirectoryAndImportPublishSettings(Data.ValidPublishSettings[0]);
  238. }
  239. /// <summary>
  240. /// Create a temporary Azure SDK directory to simulate global files.
  241. /// </summary>
  242. /// <param name="publishSettingsPath">
  243. /// Path to the publish settings.
  244. /// </param>
  245. /// <returns>The path to the temporary Azure SDK directory.</returns>
  246. public string CreateAzureSdkDirectoryAndImportPublishSettings(string publishSettingsPath)
  247. {
  248. Debug.Assert(!string.IsNullOrEmpty(publishSettingsPath));
  249. Debug.Assert(File.Exists(publishSettingsPath));
  250. Debug.Assert(string.IsNullOrEmpty(AzureSdkPath));
  251. AzureSdkPath = CreateDirectory("AzureSdk");
  252. ProfileClient client = new ProfileClient(new AzureSMProfile(Path.Combine(AzureSession.ProfileDirectory, AzureSession.ProfileFile)));
  253. AzureSession.DataStore.WriteFile(publishSettingsPath, File.ReadAllText(publishSettingsPath));
  254. client.ImportPublishSettings(publishSettingsPath, null);
  255. client.Profile.Save();
  256. return AzureSdkPath;
  257. }
  258. /// <summary>
  259. /// Create a new service with a given name and make that the current
  260. /// directory used by cmdlets.
  261. /// </summary>
  262. /// <param name="serviceName">Name of the service.</param>
  263. /// <returns>Directory created for the service.</returns>
  264. public string CreateNewService(string serviceName)
  265. {
  266. CloudServiceProject newService = new CloudServiceProject(RootPath, serviceName, FileUtilities.GetContentFilePath(@"..\..\..\..\..\Package\Debug\ServiceManagement\Azure\Services"));
  267. string path = Path.Combine(RootPath, serviceName);
  268. TestMockSupport.TestExecutionFolder = path;
  269. return path;
  270. }
  271. public void CreateDirectoryWithPrebuiltPackage(string packageName, out string package, out string configuration)
  272. {
  273. string serviceName = packageName;
  274. package = Path.Combine(RootPath, packageName + ".cspkg");
  275. FileUtilities.DataStore.WriteFile(package, "does not matter");
  276. configuration = Path.Combine(RootPath, "ServiceConfiguration.Cloud.cscfg");
  277. string template = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
  278. + Environment.NewLine
  279. + "<ServiceConfiguration serviceName=\"" + serviceName + "\" "
  280. + "xmlns=\"http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration\" "
  281. + "osFamily=\"2\" osVersion=\"*\" />";
  282. FileUtilities.DataStore.WriteFile(configuration, template);
  283. TestMockSupport.TestExecutionFolder = RootPath;
  284. }
  285. }
  286. }