using System.IO;
using System.Linq;
using System.Xml;
using NUnit.Framework;
using OpenTap.Package;
using OpenTap.Plugins.BasicSteps;
namespace OpenTap.UnitTests
{
[Display("Some test step")]
public class MyTestStep : TestStep
{
[FilePath(FilePathAttribute.BehaviorChoice.Open)]
public string StringPath { get; set; }
[FilePath(FilePathAttribute.BehaviorChoice.Open)]
public MacroString MacroPath { get; set; }
public string SomeString { get; set; }
public override void Run()
{
}
}
[TestFixture]
public class TestPlanDependencyTest
{
private string[] _files => new[] {ReferencedFile, ReferencedFile2, PictureReference};
private const string os = "Windows,Linux";
private const string version = "3.4.5";
private const string TestPackageName = "FakePackageReferencingFile";
private const string ReferencedFile = "TestPlanFromPackage.TapPlan";
public const string PictureReference = "SomePicture.png";
private const string NotReferencedFile = "OtherFile.txt";
private const string TestStepName = "Just a name for the step";
private string ReferencedFile2 => $"Packages/{TestPackageName}/{ReferencedFile}";
private string TestPackageXml => $@"
";
private string PackageXmlPath =>
Path.Combine(ExecutorClient.ExeDir, "Packages", TestPackageName, "package.xml");
public string PreviousDirectory { get; set; }
///
/// Engine unittests run in a temp directory it seems, and this test relies on the current installation
///
[SetUp]
public void SetDirectory()
{
PreviousDirectory = Directory.GetCurrentDirectory();
Directory.SetCurrentDirectory(ExecutorClient.ExeDir);
}
[SetUp]
public void Uninstall()
{
FileSystemHelper.EnsureDirectoryOf(PackageXmlPath);
if (File.Exists(PackageXmlPath))
File.Delete(PackageXmlPath);
foreach (var file in _files)
{
if (File.Exists(file))
File.Delete(file);
}
Installation.Current.Invalidate();
}
[TearDown]
public void TearDown()
{
Directory.SetCurrentDirectory(PreviousDirectory);
}
void VerifyDependency(string attr, string name, int count, XmlDocument document)
{
var nodes = document.SelectNodes(
$"/TestPlan/Package.Dependencies/Package[@Name='{TestPackageName}']/{attr}[@Name='{name}']");
Assert.AreEqual(count, nodes.Count);
}
[Test]
public void TestPictureDependency()
{
InstallPackage();
var plan = new TestPlan();
var pic = new MyPictureUsingTestStep();
pic.Picture.Source = PictureReference;
plan.ChildTestSteps.Add(pic);
var xml = plan.SerializeToString();
var document = new XmlDocument();
document.LoadXml(xml);
VerifyDependency("File", PictureReference, 1, document);
}
[Test]
public void TestFindInvalidPath()
{
var file = new string(Path.GetInvalidFileNameChars());
var a = Installation.Current.FindPackageContainingFile(file);
Assert.IsNull(a);
var file2 = "abc/def : ghi.txt";
var b = Installation.Current.FindPackageContainingFile(file2);
Assert.IsNull(b);
}
[Test]
public void TestPackageFileDependencies()
{
var plan = new TestPlan();
plan.ChildTestSteps.Add(new MyTestStep()
{
StringPath = ReferencedFile, MacroPath = new MacroString() {Text = ReferencedFile2},
SomeString = NotReferencedFile,
Name = TestStepName
});
var planXml = plan.SerializeToString();
var document = new XmlDocument();
document.LoadXml(planXml);
void VerifyDependency(string attr, string name, int count)
{
this.VerifyDependency(attr, name, count, document);
}
// Verify warnings when files used by test steps are missing
{
VerifyDependency("File", ReferencedFile, 0);
VerifyDependency("File", ReferencedFile2, 0);
VerifyDependency("Type", typeof(MyTestStep).FullName, 0);
VerifyDependency("File", NotReferencedFile, 0);
var ser = new TapSerializer();
ser.DeserializeFromString(planXml);
var errors = ser.Errors.ToArray();
Assert.AreEqual(0, errors.Length, "Expected no errors.");
}
// Verify no serializer errors when files are present
{
InstallPackage();
// OnSearch invalidates the cache of currently installed packages;
// otherwise the serializer will not detect that we have added a package
// And add the files the package is expected to contain
Installation.Current.Invalidate();
planXml = plan.SerializeToString();
document.LoadXml(planXml);
VerifyDependency("File", ReferencedFile, 1);
VerifyDependency("File", ReferencedFile2, 1);
// Uncomment when attributes are added to Package.Dependencies child elements
// VerifyDependency("Type", typeof(MyTestStep).FullName, 1);
VerifyDependency("File", NotReferencedFile, 0);
var ser = new TapSerializer();
ser.DeserializeFromString(planXml);
var errors = ser.Errors.ToArray();
Assert.AreEqual(0, errors.Length, "Expected 0 errors.");
}
Installation.Current.Invalidate();
// Verify serializer errors when required package and files are missing
{
// Remove the package again
Uninstall();
var ser = new TapSerializer();
ser.DeserializeFromString(planXml);
var errors = ser.Errors.ToArray();
// Expect a warning for the two [FilePath] properties on the test step
// Expect an error for the missing package and two errors for the missing files
Assert.AreEqual(3, errors.Length, "Expected 3 errors.");
Assert.IsTrue(errors.Any(e =>
e.Contains(
$"Package '{TestPackageName}' is required to load, but it is not installed.")));
Assert.IsTrue(errors.Any(e =>
e.Contains(
$"File '{ReferencedFile}' from package '{TestPackageName}' is required by the test plan, but it could not be found.")));
Assert.IsTrue(errors.Any(e =>
e.Contains(
$"File '{ReferencedFile2}' from package '{TestPackageName}' is required by the test plan, but it could not be found.")));
}
}
// Create fake install of the package
private void InstallPackage()
{
File.WriteAllText(PackageXmlPath, TestPackageXml);
foreach (var file in _files)
{
var fullPath = Path.Combine(ExecutorClient.ExeDir, file);
File.WriteAllText(fullPath, "test");
}
}
[Test]
[TestCase(".")]
[TestCase("../")]
[TestCase("../../")]
public void TestFindPackageOf(string workingDirectory)
{
var start = Directory.GetCurrentDirectory();
try
{
Directory.SetCurrentDirectory(workingDirectory);
// Test FindPackageContainingType(TypeData)
{
var td = TypeData.FromType(typeof(MyTestStep));
var p1 = Installation.Current.FindPackageContainingType(td);
Assert.IsNull(p1);
InstallPackage();
var p2 = Installation.Current.FindPackageContainingType(td);
// The package should be null because the cache is not invalidated
Assert.IsNull(p2);
Installation.Current.Invalidate();
var p3 = Installation.Current.FindPackageContainingType(td);
Assert.IsNotNull(p3);
StringAssert.AreEqualIgnoringCase(p3.Name, TestPackageName);
StringAssert.AreEqualIgnoringCase(p3.Version.ToString(), version);
}
Uninstall();
// Test FindPackageContainingFile("File/Path")
{
var filename = ReferencedFile2;
var p1 = Installation.Current.FindPackageContainingFile(filename);
Assert.IsNull(p1);
InstallPackage();
var p2 = Installation.Current.FindPackageContainingFile(filename);
// The package should be null because the cache is not invalidated
Assert.IsNull(p2);
Installation.Current.Invalidate();
var p3 = Installation.Current.FindPackageContainingFile(filename);
Assert.IsNotNull(p3);
StringAssert.AreEqualIgnoringCase(p3.Name, TestPackageName);
StringAssert.AreEqualIgnoringCase(p3.Version.ToString(), version);
}
}
finally
{
Directory.SetCurrentDirectory(start);
}
}
public class TestResultListener : ResultListener
{
public TestPlanRun LatestRun { get; private set; }
public bool WasRun { get; set; } = false;
public void Clear()
{
WasRun = false;
LatestRun = null;
}
public TestResultListener()
{
}
public override void OnTestPlanRunStart(TestPlanRun planRun)
{
LatestRun = planRun;
WasRun = true;
}
}
[Test]
public void EnsureParameterAttached()
{
var parameterName = "Test Plan Package";
using (Session.Create())
{
var listener = new TestResultListener();
ResultSettings.Current.Add(listener);
var plan = new TestPlan();
// Plan which is not from a package
{
Assert.IsFalse(listener.WasRun);
plan.ChildTestSteps.Add(new DelayStep());
plan.Execute();
var parameterValue = listener.LatestRun.Parameters[parameterName];
Assert.IsNull(parameterValue);
Assert.IsTrue(listener.WasRun);
}
listener.Clear();
Assert.IsFalse(listener.WasRun);
// Plan which is from a package
{
Assert.IsFalse(listener.WasRun);
InstallPackage();
Installation.Current.Invalidate();
var packageDef = Installation.Current.FindPackageContainingFile(ReferencedFile);
plan.Save(ReferencedFile);
plan.Execute();
Assert.IsTrue(listener.WasRun);
var parameterValue = listener.LatestRun.Parameters[parameterName];
Assert.AreEqual($"{TestPackageName}|{version}|{packageDef.ComputeHash()}", parameterValue);
Assert.IsTrue(listener.WasRun);
}
}
}
}
}