SQLiteIndexUnitTests.cs (13890B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="SQLiteIndexUnitTests.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace WinGetUtilInterop.UnitTests.APIUnitTests 8 { 9 using System; 10 using System.IO; 11 using System.Reflection; 12 using Microsoft.WinGetUtil.Api; 13 using Microsoft.WinGetUtil.Exceptions; 14 using Microsoft.WinGetUtil.Interfaces; 15 using Microsoft.WinGetUtil.UnitTests.Common.Logging; 16 using Xunit; 17 using Xunit.Abstractions; 18 19 /// <summary> 20 /// SQLite Index tests. 21 /// </summary> 22 public class SQLiteIndexUnitTests 23 { 24 private const string Index = "Index"; 25 private const string IndexLogFile = "index_log.txt"; 26 private const string IndexFileName = "index.db"; 27 28 private const string PackageTest = "PackageTest.yaml"; 29 private const string PackageTestNewName = "PackageTestNewName.yaml"; 30 private const string PackageTestNewVersion = "PackageTestNewVersion.yaml"; 31 private const string PackageTestRelativePath = @"manifests\t\Test\Test\1.0\Test.Test.yaml"; 32 33 private readonly string indexTestFilePath; 34 private readonly string indexTestLogFile; 35 private readonly string indexTestOutputPath; 36 private readonly string indexTestDataPath; 37 38 private ITestOutputHelper log; 39 40 /// <summary> 41 /// Initializes a new instance of the <see cref="SQLiteIndexUnitTests"/> class. 42 /// </summary> 43 /// <param name="log">Output Helper.</param> 44 public SQLiteIndexUnitTests(ITestOutputHelper log) 45 { 46 this.log = log; 47 48 var assemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 49 this.indexTestDataPath = Path.Combine( 50 Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 51 "TestCollateral"); 52 53 this.indexTestOutputPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), "WinGetUtilIndexTests"); 54 Directory.CreateDirectory(this.indexTestOutputPath); 55 56 this.indexTestFilePath = Path.Combine(this.indexTestOutputPath, IndexFileName); 57 this.indexTestLogFile = Path.Combine(this.indexTestOutputPath, IndexLogFile); 58 59 if (File.Exists(this.indexTestFilePath)) 60 { 61 File.Delete(this.indexTestFilePath); 62 } 63 64 if (File.Exists(this.indexTestLogFile)) 65 { 66 File.Delete(this.indexTestLogFile); 67 } 68 } 69 70 /// <summary> 71 /// Verify opening a existing index file succeeds. 72 /// </summary> 73 [Fact] 74 [DisplayTestMethodName] 75 public void OpenIndex() 76 { 77 this.CreateIndexHelperForIndexTest((wrapper) => true); 78 this.OpenIndexHelper((wrapper) => true); 79 } 80 81 /// <summary> 82 /// Verify opening a fake file fails. 83 /// </summary> 84 [Fact] 85 [DisplayTestMethodName] 86 public void OpenIndexFileDontExist() 87 { 88 // Verify fails with nonexistent file. 89 var exception = Assert.Throws<WinGetSQLiteIndexException>( 90 () => 91 { 92 var factory = new WinGetFactory(); 93 using var log = factory.LoggingInit(this.indexTestLogFile); 94 using var wrapper = factory.SQLiteIndexOpen("fakeFile.db"); 95 }); 96 Assert.NotNull(exception.InnerException); 97 Assert.True(exception.InnerException is System.Runtime.InteropServices.COMException); 98 Assert.Equal(-2018574322, exception.InnerException.HResult); 99 File.Delete(this.indexTestLogFile); 100 101 // Verify fails with not an index file. 102 string textFile = Path.Combine(this.indexTestOutputPath, "text.txt"); 103 File.WriteAllText(textFile, "This is a text file."); 104 Assert.True(File.Exists(textFile), "File created correctly."); 105 var exception2 = Assert.Throws<WinGetSQLiteIndexException>( 106 () => 107 { 108 var factory = new WinGetFactory(); 109 using var log = factory.LoggingInit(this.indexTestLogFile); 110 using var wrapper = factory.SQLiteIndexOpen(textFile); 111 }); 112 Assert.NotNull(exception2.InnerException); 113 Assert.True(exception2.InnerException is System.Runtime.InteropServices.COMException); 114 Assert.Equal("File opened that is not a database file (0x87AF001A)", exception2.InnerException.Message); 115 File.Delete(textFile); 116 } 117 118 /// <summary> 119 /// Verifies adding a manifest to the index succeeds. 120 /// </summary> 121 [Fact] 122 [DisplayTestMethodName] 123 public void AddManifest() 124 { 125 this.CreateIndexHelperForIndexTest((wrapper) => 126 { 127 // Add manifest. 128 string testManifest = Path.Combine(this.indexTestDataPath, PackageTest); 129 wrapper.AddManifest(testManifest, PackageTestRelativePath); 130 return true; 131 }); 132 } 133 134 /// <summary> 135 /// Verify that adding an already existing manifest fails. 136 /// </summary> 137 [Fact] 138 [DisplayTestMethodName] 139 public void AddManifestAlreadyExists() 140 { 141 this.CreateIndexHelperForIndexTest((wrapper) => 142 { 143 // Add manifest. 144 string testManifest = Path.Combine(this.indexTestDataPath, PackageTest); 145 wrapper.AddManifest(testManifest, PackageTestRelativePath); 146 147 // Add manifest again. 148 var exception = Assert.Throws<WinGetSQLiteIndexException>( 149 () => 150 { 151 wrapper.AddManifest(testManifest, PackageTestRelativePath); 152 }); 153 Assert.NotNull(exception.InnerException); 154 Assert.True(exception.InnerException is System.Runtime.InteropServices.COMException); 155 Assert.Equal(-2147024713, exception.InnerException.HResult); 156 157 return true; 158 }); 159 } 160 161 /// <summary> 162 /// Verify that updating a manifest with different name. 163 /// </summary> 164 [Fact] 165 [DisplayTestMethodName] 166 public void UpdateManifest() 167 { 168 this.CreateIndexHelperForIndexTest((wrapper) => 169 { 170 // Add manifest. 171 string addManifest = Path.Combine(this.indexTestDataPath, PackageTest); 172 wrapper.AddManifest(addManifest, PackageTestRelativePath); 173 174 // Update manifest. name is different, should return true. 175 string updateManifest = Path.Combine(this.indexTestDataPath, PackageTestNewName); 176 Assert.True(wrapper.UpdateManifest(updateManifest, PackageTestRelativePath)); 177 178 return true; 179 }); 180 } 181 182 /// <summary> 183 /// Verify that add or update works both times. 184 /// </summary> 185 [Fact] 186 [DisplayTestMethodName] 187 public void AddOrUpdateManifest() 188 { 189 this.CreateIndexHelperForIndexTest((wrapper) => 190 { 191 // Add manifest; should return true. 192 string addManifest = Path.Combine(this.indexTestDataPath, PackageTest); 193 Assert.True(wrapper.AddOrUpdateManifest(addManifest, PackageTestRelativePath)); 194 195 // Update manifest. name is different, should return false. 196 string updateManifest = Path.Combine(this.indexTestDataPath, PackageTestNewName); 197 Assert.False(wrapper.AddOrUpdateManifest(updateManifest, PackageTestRelativePath)); 198 199 return true; 200 }); 201 } 202 203 /// <summary> 204 /// Verify that updating a manifest in the index with the exact same information succeeds. 205 /// </summary> 206 [Fact] 207 [DisplayTestMethodName] 208 public void UpdateManifestNoChanges() 209 { 210 this.CreateIndexHelperForIndexTest((wrapper) => 211 { 212 // Add manifest. 213 string addManifest = Path.Combine(this.indexTestDataPath, PackageTest); 214 wrapper.AddManifest(addManifest, PackageTestRelativePath); 215 216 // Update manifest. Same file, should succeed but return false. 217 Assert.False(wrapper.UpdateManifest(addManifest, PackageTestRelativePath)); 218 219 return true; 220 }); 221 } 222 223 /// <summary> 224 /// Verify that updating a manifest that doesn't exists fails. 225 /// </summary> 226 [Fact] 227 [DisplayTestMethodName] 228 public void UpdateManifestNonExistant() 229 { 230 this.CreateIndexHelperForIndexTest((wrapper) => 231 { 232 // Update manifest that doesn't exists 233 string updateManifest = Path.Combine(this.indexTestDataPath, PackageTest); 234 var exception = Assert.Throws<WinGetSQLiteIndexException>( 235 () => 236 { 237 wrapper.UpdateManifest(updateManifest, PackageTestRelativePath); 238 }); 239 Assert.NotNull(exception.InnerException); 240 Assert.True(exception.InnerException is System.Runtime.InteropServices.COMException); 241 Assert.Equal(-2147023728, exception.InnerException.HResult); 242 243 return true; 244 }); 245 } 246 247 /// <summary> 248 /// Verify that updating an existing manifest in the index, but another version. 249 /// </summary> 250 [Fact] 251 [DisplayTestMethodName] 252 public void UpdateManifestDifferentVersion() 253 { 254 this.CreateIndexHelperForIndexTest((wrapper) => 255 { 256 // Add manifest. 257 string addManifest = Path.Combine(this.indexTestDataPath, PackageTest); 258 wrapper.AddManifest(addManifest, PackageTestRelativePath); 259 260 // Update manifest. Version is different. 261 string updateManifest = Path.Combine(this.indexTestDataPath, PackageTestNewVersion); 262 var exception = Assert.Throws<WinGetSQLiteIndexException>( 263 () => 264 { 265 wrapper.UpdateManifest(updateManifest, PackageTestRelativePath); 266 }); 267 Assert.NotNull(exception.InnerException); 268 Assert.True(exception.InnerException is System.Runtime.InteropServices.COMException); 269 Assert.Equal(-2147023728, exception.InnerException.HResult); 270 271 return true; 272 }); 273 } 274 275 /// <summary> 276 /// Verify that removing a manifest in the index succeeds. 277 /// </summary> 278 [Fact] 279 [DisplayTestMethodName] 280 public void RemoveManifest() 281 { 282 this.CreateIndexHelperForIndexTest((wrapper) => 283 { 284 // Add manifest. 285 string addManifest = Path.Combine(this.indexTestDataPath, PackageTest); 286 wrapper.AddManifest(addManifest, PackageTestRelativePath); 287 288 // Remove manifest. 289 wrapper.RemoveManifest(addManifest, PackageTestRelativePath); 290 291 return true; 292 }); 293 } 294 295 /// <summary> 296 /// Verify that trying to delete a manifest that doesn't exists fails. 297 /// </summary> 298 [Fact] 299 [DisplayTestMethodName] 300 public void RemoveManifestNonExistant() 301 { 302 // create index, add manifest, delete. 303 this.CreateIndexHelperForIndexTest((wrapper) => 304 { 305 // Add manifest. 306 string addManifest = Path.Combine(this.indexTestDataPath, PackageTest); 307 308 // Remove manifest. 309 Assert.Throws<WinGetSQLiteIndexException>( 310 () => 311 { 312 wrapper.RemoveManifest(addManifest, PackageTestRelativePath); 313 }); 314 315 return true; 316 }); 317 } 318 319 private void CreateIndexHelperForIndexTest(Func<IWinGetSQLiteIndex, bool> lambda) 320 { 321 if (File.Exists(this.indexTestLogFile)) 322 { 323 File.Delete(this.indexTestLogFile); 324 } 325 326 if (File.Exists(this.indexTestFilePath)) 327 { 328 File.Delete(this.indexTestFilePath); 329 } 330 331 // Create index. 332 var factory = new WinGetFactory(); 333 using var log = factory.LoggingInit(this.indexTestLogFile); 334 using var wrapper = factory.SQLiteIndexCreateLatestVersion(this.indexTestFilePath); 335 Assert.True(lambda(wrapper), "Expression passed"); 336 337 Assert.True(File.Exists(this.indexTestLogFile)); 338 Assert.True(File.Exists(this.indexTestFilePath)); 339 } 340 341 private void OpenIndexHelper(Func<IWinGetSQLiteIndex, bool> lambda) 342 { 343 Assert.True(File.Exists(this.indexTestFilePath)); 344 if (File.Exists(this.indexTestLogFile)) 345 { 346 File.Delete(this.indexTestLogFile); 347 } 348 349 // Open index. 350 var factory = new WinGetFactory(); 351 using var log = factory.LoggingInit(this.indexTestLogFile); 352 using var wrapper = factory.SQLiteIndexOpen(this.indexTestFilePath); 353 Assert.True(lambda(wrapper), "Expression passed"); 354 355 Assert.True(File.Exists(this.indexTestLogFile)); 356 } 357 } 358 }