mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-26 20:29:51 +01:00
336 lines
13 KiB
C#
336 lines
13 KiB
C#
|
/* Copyright (c) Citrix Systems Inc.
|
|||
|
* All rights reserved.
|
|||
|
*
|
|||
|
* Redistribution and use in source and binary forms,
|
|||
|
* with or without modification, are permitted provided
|
|||
|
* that the following conditions are met:
|
|||
|
*
|
|||
|
* * Redistributions of source code must retain the above
|
|||
|
* copyright notice, this list of conditions and the
|
|||
|
* following disclaimer.
|
|||
|
* * Redistributions in binary form must reproduce the above
|
|||
|
* copyright notice, this list of conditions and the
|
|||
|
* following disclaimer in the documentation and/or other
|
|||
|
* materials provided with the distribution.
|
|||
|
*
|
|||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|||
|
* SUCH DAMAGE.
|
|||
|
*/
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using NUnit.Framework;
|
|||
|
using XenAdmin.Actions;
|
|||
|
using Moq;
|
|||
|
using XenAdmin.Core;
|
|||
|
using XenAPI;
|
|||
|
using System.Linq;
|
|||
|
|
|||
|
namespace XenAdminTests.UnitTests
|
|||
|
{
|
|||
|
[TestFixture, Category(TestCategories.Unit)]
|
|||
|
public class BatchUpdatesTests
|
|||
|
{
|
|||
|
|
|||
|
private static Mock<Host> GetAMockHost(string productVersion, string buildNumber)
|
|||
|
{
|
|||
|
var id = System.Guid.NewGuid().ToString();
|
|||
|
|
|||
|
MockObjectManager mom = new MockObjectManager();
|
|||
|
|
|||
|
mom.CreateNewConnection(id);
|
|||
|
|
|||
|
Mock<Host> master = mom.NewXenObject<Host>(id);
|
|||
|
Mock<Pool> pool = mom.NewXenObject<Pool>(id);
|
|||
|
XenRef<Host> masterRef = new XenRef<Host>("master-ref");
|
|||
|
pool.Setup(p => p.master).Returns(masterRef);
|
|||
|
|
|||
|
mom.MockCacheFor(id).Setup(c => c.Resolve(It.IsAny<XenRef<Pool>>())).Returns(pool.Object);
|
|||
|
|
|||
|
mom.MockConnectionFor(id).Setup(c => c.Resolve(masterRef)).Returns(master.Object);
|
|||
|
mom.MockConnectionFor(id).Setup(c => c.Cache.Hosts).Returns(new Host[] { master.Object });
|
|||
|
mom.MockConnectionFor(id).Setup(c => c.Cache.Pools).Returns(new Pool[] { pool.Object });
|
|||
|
|
|||
|
master.Setup(h => h.software_version).Returns(new Dictionary<string, string>());
|
|||
|
master.Setup(h => h.ProductVersion).Returns(productVersion);
|
|||
|
master.Setup(h => h.AppliedPatches()).Returns(new List<Pool_patch>());
|
|||
|
master.Setup(h => h.BuildNumberRaw).Returns(buildNumber);
|
|||
|
master.Setup(h => h.uuid).Returns(id);
|
|||
|
return master;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private static List<XenServerVersion> GetAVersionWithGivenNumberOfPatches(int numberOfPatches)
|
|||
|
{
|
|||
|
var serverVersions = new List<XenServerVersion>();
|
|||
|
|
|||
|
var version = new XenServerVersion("7.0.0", "XenServer Test 7", true, "", new List<XenServerPatch>(), new List<XenServerPatch>(), DateTime.MinValue.ToString(), "buildNo");
|
|||
|
for (int ii = 0; ii < numberOfPatches; ii++)
|
|||
|
{
|
|||
|
var patch = new XenServerPatch("patch_uuid_" + ii, "patch name " + ii, "patch description" + ii, "", "", "1.0", "", "", "1970-01-01T00:00:00Z", "", "1000");
|
|||
|
version.Patches.Add(patch);
|
|||
|
version.MinimalPatches.Add(patch);
|
|||
|
}
|
|||
|
serverVersions.Add(version);
|
|||
|
|
|||
|
return serverVersions;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private static void RemoveANumberOfPatchesPseudoRandomly(List<XenServerPatch> patches, int numberOfPatchesToRemove)
|
|||
|
{
|
|||
|
int expectedCount = patches.Count - numberOfPatchesToRemove;
|
|||
|
var rnd = new Random(777); //pseudo random to be able to repeat this test...
|
|||
|
|
|||
|
while (patches.Count > expectedCount)
|
|||
|
{
|
|||
|
patches.RemoveAt(rnd.Next(patches.Count));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
[Test]
|
|||
|
public void GetUpgradeSequenceForNullConnection()
|
|||
|
{
|
|||
|
Assert.AreEqual(XenAdmin.Core.Updates.GetUpgradeSequence(null), null);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Version exist
|
|||
|
/// No patches in updates
|
|||
|
/// Nothing installed on host
|
|||
|
/// Result: update sequence has the host, but empty sequence
|
|||
|
/// </summary>
|
|||
|
[Test]
|
|||
|
public void NoPatchesForCurrentVersion()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
|
|||
|
var serverVersions = GetAVersionWithGivenNumberOfPatches(0);
|
|||
|
var master = GetAMockHost(serverVersions.First().Oem, serverVersions.First().BuildNumber);
|
|||
|
SetXenServerVersionsInUpdates(serverVersions);
|
|||
|
|
|||
|
// Act
|
|||
|
|
|||
|
var upgradeSequence = XenAdmin.Core.Updates.GetUpgradeSequence(master.Object.Connection);
|
|||
|
|
|||
|
// Assert
|
|||
|
|
|||
|
Assert.NotNull(upgradeSequence);
|
|||
|
Assert.AreEqual(1, upgradeSequence.Count);
|
|||
|
Assert.NotNull(upgradeSequence.First().Key);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Key.uuid, master.Object.uuid);
|
|||
|
Assert.NotNull(upgradeSequence.First().Value);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value.Count, 0);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Version exist
|
|||
|
/// 1 patch in updates. 1 in minimal list.
|
|||
|
/// 1 has to be installed on host
|
|||
|
/// Result: update sequence has the host, with the one single patch in it
|
|||
|
/// </summary>
|
|||
|
[Test]
|
|||
|
public void OnePatchToBeInstalledForCurrentVersion()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
|
|||
|
var serverVersions = GetAVersionWithGivenNumberOfPatches(1);
|
|||
|
var patch = serverVersions.First().Patches[0];
|
|||
|
var master = GetAMockHost(serverVersions.First().Oem, serverVersions.First().BuildNumber);
|
|||
|
SetXenServerVersionsInUpdates(serverVersions);
|
|||
|
|
|||
|
// Act
|
|||
|
|
|||
|
var upgradeSequence = XenAdmin.Core.Updates.GetUpgradeSequence(master.Object.Connection);
|
|||
|
|
|||
|
// Assert
|
|||
|
|
|||
|
Assert.NotNull(upgradeSequence);
|
|||
|
Assert.AreEqual(1, upgradeSequence.Count);
|
|||
|
Assert.NotNull(upgradeSequence.First().Key);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Key.uuid, master.Object.uuid);
|
|||
|
Assert.NotNull(upgradeSequence.First().Value);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value.Count, 1);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value[0], patch);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Version exist
|
|||
|
/// 100 patch in updates. 100 in minimal list.
|
|||
|
/// 100 has to be installed on host
|
|||
|
/// Result: update sequence has all the 100 patches in it
|
|||
|
/// </summary>
|
|||
|
[Test]
|
|||
|
public void HundredPatchToBeInstalledForCurrentVersion()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
var serverVersions = GetAVersionWithGivenNumberOfPatches(100);
|
|||
|
var master = GetAMockHost(serverVersions.First().Oem, serverVersions.First().BuildNumber);
|
|||
|
SetXenServerVersionsInUpdates(serverVersions);
|
|||
|
|
|||
|
// Act
|
|||
|
|
|||
|
var upgradeSequence = XenAdmin.Core.Updates.GetUpgradeSequence(master.Object.Connection);
|
|||
|
|
|||
|
// Assert
|
|||
|
|
|||
|
Assert.NotNull(upgradeSequence);
|
|||
|
Assert.AreEqual(1, upgradeSequence.Count);
|
|||
|
var seqToCheck = upgradeSequence.First();
|
|||
|
Assert.NotNull(seqToCheck.Key);
|
|||
|
Assert.AreEqual(seqToCheck.Key.uuid, master.Object.uuid);
|
|||
|
Assert.NotNull(seqToCheck.Value);
|
|||
|
Assert.AreEqual(seqToCheck.Value.Count, 100);
|
|||
|
|
|||
|
for (int ii = 100; ii < 0; --ii)
|
|||
|
Assert.AreEqual(seqToCheck.Value[ii], serverVersions.First().Patches[ii]);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Version exist
|
|||
|
/// 100 patch in updates. 51 in minimal list.
|
|||
|
/// 51 has to be installed on host
|
|||
|
/// Result: update sequence has all the 100 patches in it
|
|||
|
/// </summary>
|
|||
|
[Test]
|
|||
|
public void FiftyOnePatchToBeInstalledForCurrentVersion()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
var serverVersions = GetAVersionWithGivenNumberOfPatches(100);
|
|||
|
var master = GetAMockHost(serverVersions.First().Oem, serverVersions.First().BuildNumber);
|
|||
|
RemoveANumberOfPatchesPseudoRandomly(serverVersions.First().MinimalPatches, 49);
|
|||
|
SetXenServerVersionsInUpdates(serverVersions);
|
|||
|
|
|||
|
// Act
|
|||
|
|
|||
|
var upgradeSequence = XenAdmin.Core.Updates.GetUpgradeSequence(master.Object.Connection);
|
|||
|
|
|||
|
// Assert
|
|||
|
|
|||
|
Assert.NotNull(upgradeSequence);
|
|||
|
Assert.AreEqual(1, upgradeSequence.Count);
|
|||
|
var seqToCheck = upgradeSequence.First();
|
|||
|
Assert.NotNull(seqToCheck.Key);
|
|||
|
Assert.AreEqual(seqToCheck.Key.uuid, master.Object.uuid);
|
|||
|
Assert.NotNull(seqToCheck.Value);
|
|||
|
Assert.AreEqual(seqToCheck.Value.Count, 51);
|
|||
|
|
|||
|
foreach (var patch in seqToCheck.Value)
|
|||
|
Assert.IsTrue(serverVersions.First().MinimalPatches.Contains(patch));
|
|||
|
|
|||
|
Assert.False(seqToCheck.Value.Exists(seqpatch => !serverVersions.First().MinimalPatches.Contains(seqpatch)));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Version exist
|
|||
|
/// 2 patch in updates. 1 in minimal list.
|
|||
|
/// 1 has to be installed on host
|
|||
|
/// Result: update sequence has the host, with the one single patch in it
|
|||
|
/// </summary>
|
|||
|
[Test]
|
|||
|
public void OnePatchOutOfTwoToBeInstalledForCurrentVersion()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
|
|||
|
var serverVersions = GetAVersionWithGivenNumberOfPatches(2);
|
|||
|
var master = GetAMockHost(serverVersions.First().Oem, serverVersions.First().BuildNumber);
|
|||
|
RemoveANumberOfPatchesPseudoRandomly(serverVersions.First().MinimalPatches, 1);
|
|||
|
SetXenServerVersionsInUpdates(serverVersions);
|
|||
|
|
|||
|
// Act
|
|||
|
|
|||
|
var upgradeSequence = XenAdmin.Core.Updates.GetUpgradeSequence(master.Object.Connection);
|
|||
|
|
|||
|
// Assert
|
|||
|
|
|||
|
Assert.NotNull(upgradeSequence);
|
|||
|
Assert.AreEqual(1, upgradeSequence.Count);
|
|||
|
Assert.NotNull(upgradeSequence.First().Key);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Key.uuid, master.Object.uuid);
|
|||
|
Assert.NotNull(upgradeSequence.First().Value);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value.Count, 1);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value[0], serverVersions.First().MinimalPatches[0]);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Version exist
|
|||
|
/// 2 patch in updates. 2 in minimal list.
|
|||
|
/// 2 has to be installed on host
|
|||
|
/// Result: update sequence has the host, with the one single patch in it
|
|||
|
/// </summary>
|
|||
|
[Test]
|
|||
|
public void TwoPatchToBeInstalleOutOfTwodForCurrentVersion()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
|
|||
|
var serverVersions = GetAVersionWithGivenNumberOfPatches(2);
|
|||
|
var master = GetAMockHost(serverVersions.First().Oem, serverVersions.First().BuildNumber);
|
|||
|
SetXenServerVersionsInUpdates(serverVersions);
|
|||
|
|
|||
|
// Act
|
|||
|
|
|||
|
var upgradeSequence = XenAdmin.Core.Updates.GetUpgradeSequence(master.Object.Connection);
|
|||
|
|
|||
|
// Assert
|
|||
|
|
|||
|
Assert.NotNull(upgradeSequence);
|
|||
|
Assert.AreEqual(1, upgradeSequence.Count);
|
|||
|
Assert.NotNull(upgradeSequence.First().Key);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Key.uuid, master.Object.uuid);
|
|||
|
Assert.NotNull(upgradeSequence.First().Value);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value.Count, 2);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value[0], serverVersions.First().MinimalPatches[0]);
|
|||
|
Assert.AreEqual(upgradeSequence.First().Value[1], serverVersions.First().MinimalPatches[1]);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Version does not exist
|
|||
|
/// Result: update sequence does not have the host
|
|||
|
/// </summary>
|
|||
|
[Test]
|
|||
|
public void NoInfoForCurrentVersion()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
|
|||
|
var serverVersions = GetAVersionWithGivenNumberOfPatches(200);
|
|||
|
var master = GetAMockHost(serverVersions.First().Oem, serverVersions.First().BuildNumber + "to_make_it_not_match");
|
|||
|
SetXenServerVersionsInUpdates(serverVersions);
|
|||
|
|
|||
|
// Act
|
|||
|
|
|||
|
var upgradeSequence = XenAdmin.Core.Updates.GetUpgradeSequence(master.Object.Connection);
|
|||
|
|
|||
|
// Assert
|
|||
|
|
|||
|
Assert.NotNull(upgradeSequence);
|
|||
|
Assert.AreEqual(0, upgradeSequence.Count);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Updates is static class, can't be mocked without refactoring - using this method instead
|
|||
|
/// </summary>
|
|||
|
/// <param name="serverVersions"></param>
|
|||
|
private void SetXenServerVersionsInUpdates(List<XenServerVersion> serverVersions)
|
|||
|
{
|
|||
|
Updates.XenServerVersions = serverVersions;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|