using HeuristicLab.Services.Deployment.DataAccess; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; using System.Linq; using System; using System.Diagnostics; namespace HeuristicLab.Services.Deployment.Test { /// ///This is a test class for PluginStoreTest and is intended ///to contain all PluginStoreTest Unit Tests /// [TestClass()] public class PluginStoreTest { private System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); private TestContext testContextInstance; /// ///Gets or sets the test context which provides ///information about and functionality for the current test run. /// public TestContext TestContext { get { return testContextInstance; } set { testContextInstance = value; } } #region Additional test attributes // //You can use the following additional attributes as you write your tests: // //Use ClassInitialize to run code before running the first test in the class //[ClassInitialize()] //public static void MyClassInitialize(TestContext testContext) //{ //} // //Use ClassCleanup to run code after all tests in a class have run //[ClassCleanup()] //public static void MyClassCleanup() //{ //} // //Use TestInitialize to run code before running each test //[TestInitialize()] //public void MyTestInitialize() //{ //} // //Use TestCleanup to run code after each test has run //[TestCleanup()] //public void MyTestCleanup() //{ //} // #endregion /// ///A test for PluginFile /// [TestMethod()] public void PluginFileTest() { PluginStore target = new PluginStore(); #region insert and retrieve a plugin file int oldCount = target.Plugins.Count(); // store a new entry in the db string name = Guid.NewGuid().ToString(); target.Persist(new PluginDescription(name, new Version(0, 1)), enc.GetBytes("Zipped " + name)); int newCount = target.Plugins.Count(); // make sure the new entry was added to the db Assert.AreEqual(oldCount + 1, newCount); // get matching description from db and try to retrieve the stored file PluginDescription pluginDescription = target.Plugins.Where(p => p.Name == name).Single(); byte[] expected = enc.GetBytes("Zipped " + name); byte[] actual = target.PluginFile(pluginDescription); // check retrieved file Assert.AreEqual(expected.Length, actual.Length); for (int i = 0; i < expected.Length; i++) { Assert.AreEqual(expected[i], actual[i]); } #endregion } /// ///A test for Persist /// [TestMethod()] public void PersistPluginTest() { var vers01 = new Version(0, 1); PluginStore target = new PluginStore(); #region persist single plugin without dependencies { string name = Guid.NewGuid().ToString(); int oldCount = target.Plugins.Count(); PluginDescription pluginDescription = new PluginDescription(name, vers01); byte[] pluginPackage = enc.GetBytes("Zipped " + name); target.Persist(pluginDescription, pluginPackage); int newCount = target.Plugins.Count(); Assert.AreEqual(oldCount + 1, newCount); } #endregion #region persist a product with same name and version as an existent product { string name = Guid.NewGuid().ToString(); int oldCount = target.Plugins.Count(); PluginDescription pluginDescription = new PluginDescription(name, vers01); byte[] pluginPackage = enc.GetBytes("Zipped " + name); target.Persist(pluginDescription, pluginPackage); int newCount = target.Plugins.Count(); Assert.AreEqual(oldCount + 1, newCount); // insert same name and version oldCount = target.Plugins.Count(); pluginDescription = new PluginDescription(name, vers01); pluginPackage = enc.GetBytes("Zipped " + name); target.Persist(pluginDescription, pluginPackage); newCount = target.Plugins.Count(); // make sure old entry was updated Assert.AreEqual(oldCount, newCount); // insert new with different version oldCount = target.Plugins.Count(); pluginDescription = new PluginDescription(name, new Version(0, 2)); pluginPackage = enc.GetBytes("Zipped " + name); target.Persist(pluginDescription, pluginPackage); newCount = target.Plugins.Count(); // make sure a new entry was created Assert.AreEqual(oldCount + 1, newCount); } #endregion #region persist a plugin with an already persisted dependency { string name = Guid.NewGuid().ToString(); PluginDescription dependency = new PluginDescription(name, vers01); // insert dependency first target.Persist(dependency, enc.GetBytes("Zipped " + name)); // persist another plugin that has a dependency on the first plugin string name2 = Guid.NewGuid().ToString(); int oldCount = target.Plugins.Count(); PluginDescription newEntity = new PluginDescription(name2, vers01, Enumerable.Repeat(dependency, 1)); byte[] newEntityPackage = enc.GetBytes("Zipped " + name2); target.Persist(newEntity, newEntityPackage); int newCount = target.Plugins.Count(); Assert.AreEqual(oldCount + 1, newCount); // only one new plugin should be added // retrieve second plugin and check dependencies newEntity = target.Plugins.Where(p => p.Name == name2).Single(); Assert.AreEqual(newEntity.Dependencies.Count(), 1); Assert.AreEqual(newEntity.Dependencies.First().Name, name); } #endregion #region try to persist a new plugin with a non-existant dependency and check the expected exception { // try to persist a new plugin with a non-existant dependency try { string pluginName = Guid.NewGuid().ToString(); string dependencyName = Guid.NewGuid().ToString(); var dependency = new PluginDescription(dependencyName, vers01); var newEntity = new PluginDescription(pluginName, vers01, Enumerable.Repeat(dependency, 1)); target.Persist(newEntity, enc.GetBytes("Zipped " + pluginName)); Assert.Fail("persist should fail with ArgumentException"); } catch (ArgumentException e) { // this is expected Assert.IsTrue(true, "expected exception"); } } #endregion #region update the plugin file of an existing plugin { // insert new plugin string pluginName = Guid.NewGuid().ToString(); var newPlugin = new PluginDescription(pluginName, vers01); target.Persist(newPlugin, enc.GetBytes("Zipped " + pluginName)); // update the plugin file byte[] expected = enc.GetBytes("Zipped2 " + pluginName); target.Persist(newPlugin, expected); // check if the updated file is returned byte[] actual = target.PluginFile(newPlugin); // check retrieved file Assert.AreEqual(expected.Length, actual.Length); for (int i = 0; i < expected.Length; i++) { Assert.AreEqual(expected[i], actual[i]); } } #endregion #region update the dependencies of an existing plugin { string dependency1Name = Guid.NewGuid().ToString(); var newDependency1 = new PluginDescription(dependency1Name, vers01); target.Persist(newDependency1, enc.GetBytes("Zipped " + dependency1Name)); string pluginName = Guid.NewGuid().ToString(); var newPlugin = new PluginDescription(pluginName, vers01, Enumerable.Repeat(newDependency1, 1)); target.Persist(newPlugin, enc.GetBytes("Zipped " + pluginName)); // retrieve plugin var dbPlugin = target.Plugins.Where(p => p.Name == pluginName).Single(); Assert.AreEqual(dbPlugin.Dependencies.Count(), 1); Assert.AreEqual(dbPlugin.Dependencies.First().Name, dependency1Name); // change dependencies string dependency2Name = Guid.NewGuid().ToString(); var newDependency2 = new PluginDescription(dependency2Name, vers01); target.Persist(newDependency2, enc.GetBytes("Zipped " + pluginName)); newPlugin = new PluginDescription(pluginName, vers01, new PluginDescription[] { newDependency1, newDependency2 }); target.Persist(newPlugin, enc.GetBytes("Zipped " + pluginName)); // retrieve plugin dbPlugin = target.Plugins.Where(p => p.Name == pluginName).Single(); Assert.AreEqual(dbPlugin.Dependencies.Count(), 2); } #endregion #region try to insert a plugin that references the same dependency twice and check if the correct exception is thrown { string depName = Guid.NewGuid().ToString(); var depPlugin = new PluginDescription(depName, vers01); target.Persist(depPlugin, enc.GetBytes("Zipped " + depName)); // insert new plugin string pluginName = Guid.NewGuid().ToString(); var plugin = new PluginDescription(pluginName, vers01, new PluginDescription[] { depPlugin, depPlugin }); try { target.Persist(plugin, enc.GetBytes("Zipped " + depName)); Assert.Fail("Expected ArgumentException"); } catch (ArgumentException) { Assert.IsTrue(true, "Exception thrown as expected"); } } #endregion } /// ///A test for Persist /// [TestMethod()] public void PersistProductTest() { Version vers01 = new Version(0, 1); PluginStore target = new PluginStore(); #region persist a product without plugins to the db { string prodName = Guid.NewGuid().ToString(); int oldCount = target.Products.Count(); ProductDescription product = new ProductDescription(prodName, vers01); target.Persist(product); int newCount = target.Products.Count(); Assert.AreEqual(oldCount + 1, newCount); } #endregion #region persist a product with the same name and version as an existant product { string prodName = Guid.NewGuid().ToString(); int oldCount = target.Products.Count(); ProductDescription product = new ProductDescription(prodName, vers01); target.Persist(product); int newCount = target.Products.Count(); Assert.AreEqual(oldCount + 1, newCount); // write a product with same name and version oldCount = target.Products.Count(); product = new ProductDescription(prodName, vers01); target.Persist(product); newCount = target.Products.Count(); // make sure that the old entry was updated Assert.AreEqual(oldCount, newCount); // write a product with same name and different version oldCount = target.Products.Count(); product = new ProductDescription(prodName, new Version(0, 2)); target.Persist(product); newCount = target.Products.Count(); // make sure that a new entry was created Assert.AreEqual(oldCount + 1, newCount); } #endregion #region try to persist a product referencing an non-existant plugin and check the expected exception { // try to persist a product referencing an non-existant plugin string prodName = Guid.NewGuid().ToString(); string pluginName = Guid.NewGuid().ToString(); var plugin = new PluginDescription(pluginName, vers01); var product = new ProductDescription(prodName, vers01, Enumerable.Repeat(plugin, 1)); try { target.Persist(product); Assert.Fail("persist should fail with ArgumentException"); } catch (ArgumentException e) { // this is expected Assert.IsTrue(true, "expected exception"); } } #endregion #region persist a product with a single plugin reference { string prodName = Guid.NewGuid().ToString(); string pluginName = Guid.NewGuid().ToString(); var plugin = new PluginDescription(pluginName, vers01); var product = new ProductDescription(prodName, vers01, Enumerable.Repeat(plugin, 1)); // persist the plugin first int oldCount = target.Products.Count(); target.Persist(plugin, enc.GetBytes("Zipped " + plugin.Name)); target.Persist(product); int newCount = target.Products.Count(); // make sure the store went through Assert.AreEqual(oldCount + 1, newCount); // retrieve the product and check if the plugin list was stored/retrieved correctly var dbProd = target.Products.Where(p => p.Name == prodName).Single(); Assert.AreEqual(dbProd.Plugins.Count(), 1); Assert.AreEqual(dbProd.Plugins.First().Name, pluginName); } #endregion #region update the plugin list of an existing product { string prodName = Guid.NewGuid().ToString(); string plugin1Name = Guid.NewGuid().ToString(); var plugin1 = new PluginDescription(plugin1Name, vers01); var product = new ProductDescription(prodName, vers01, Enumerable.Repeat(plugin1, 1)); // persist the plugin first int oldCount = target.Products.Count(); target.Persist(plugin1, enc.GetBytes("Zipped " + plugin1.Name)); target.Persist(product); int newCount = target.Products.Count(); // make sure the store went through Assert.AreEqual(oldCount + 1, newCount); var plugin2Name = Guid.NewGuid().ToString(); var plugin2 = new PluginDescription(plugin2Name, vers01); target.Persist(plugin2, enc.GetBytes("Zipped " + plugin2.Name)); product = new ProductDescription(prodName, vers01, new PluginDescription[] { plugin1, plugin2 }); oldCount = target.Products.Count(); target.Persist(product); newCount = target.Products.Count(); // make sure that a new entry was not created Assert.AreEqual(oldCount, newCount); // check the plugin list of the product var dbProduct = target.Products.Where(p => p.Name == prodName).Single(); Assert.AreEqual(dbProduct.Plugins.Count(), 2); } #endregion #region insert a product which references the same plugin twice and check if the correct exception is thrown { string prodName = Guid.NewGuid().ToString(); string plugin1Name = Guid.NewGuid().ToString(); var plugin1 = new PluginDescription(plugin1Name, vers01); var product = new ProductDescription(prodName, vers01, Enumerable.Repeat(plugin1, 2)); // persist the plugin first target.Persist(plugin1, enc.GetBytes("Zipped " + plugin1.Name)); try { target.Persist(product); Assert.Fail("Expected ArgumentException"); } catch (ArgumentException) { Assert.IsTrue(true, "Expected exception was thrown."); } } #endregion } [TestMethod] public void InsertPluginPerformanceTest() { int nPlugins = 100; int maxDependencies = 10; int avgZipFileLength = 32000; var store = new PluginStore(); Version vers01 = new Version(0, 1); // create a random byte array to represent file length byte[] zippedConstant = new byte[avgZipFileLength]; Random r = new Random(); r.NextBytes(zippedConstant); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // create plugins List plugins = new List(); for (int i = 0; i < nPlugins; i++) { string name = Guid.NewGuid().ToString(); var dependencies = store.Plugins; if (dependencies.Count() > maxDependencies) dependencies = dependencies.Take(maxDependencies); var plugin = new PluginDescription(name, vers01, dependencies); store.Persist(plugin, zippedConstant); plugins.Add(plugin); } stopWatch.Stop(); Assert.Inconclusive("Created " + nPlugins + " plugins in " + stopWatch.ElapsedMilliseconds + " ms (" + (double)stopWatch.ElapsedMilliseconds / nPlugins + " ms / plugin )"); } [TestMethod] public void InsertProductPerformanceTest() { int nProducts = 50; int avgProductPlugins = 30; var store = new PluginStore(); Version vers01 = new Version(0, 1); Stopwatch stopWatch = new Stopwatch(); Random r = new Random(); var plugins = store.Plugins.ToList(); stopWatch.Start(); // create products for (int i = 0; i < nProducts; i++) { string name = Guid.NewGuid().ToString(); List prodPlugins = new List(); for (int j = 0; j < avgProductPlugins; j++) { prodPlugins.Add(plugins[r.Next(0, plugins.Count)]); } var prod = new ProductDescription(name, vers01, prodPlugins); store.Persist(prod); } stopWatch.Stop(); Assert.Inconclusive("Created " + nProducts + " products in " + stopWatch.ElapsedMilliseconds + " ms (" + (double)stopWatch.ElapsedMilliseconds / nProducts + " ms / product )"); } } }