Files
biztalk-application-catalog/src/BizTalkApplicationCatalog/Infrastructure/SelfTestRunner.cs
T

216 lines
8.5 KiB
C#

using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using BizTalkApplicationCatalog.Models;
using BizTalkApplicationCatalog.Persistence;
using BizTalkApplicationCatalog.Reporting;
namespace BizTalkApplicationCatalog.Infrastructure
{
/// <summary>
/// Prüft Snapshot, Merge und Excel-Ausgabe ohne BizTalk-Zugriff.
/// </summary>
internal static class SelfTestRunner
{
public static void Run(string outputPath = null)
{
var keepOutput = !string.IsNullOrWhiteSpace(outputPath);
var directory = keepOutput
? Path.GetDirectoryName(Path.GetFullPath(outputPath))
: Path.Combine(
Path.GetTempPath(),
"BizTalkApplicationCatalogTests-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(directory);
var path = keepOutput
? Path.GetFullPath(outputPath)
: Path.Combine(directory, "phase1-test.xlsx");
var jsonPath = Path.Combine(
directory,
"phase1-test-" + Guid.NewGuid().ToString("N") + ".json");
try
{
var acc = AccSnapshot();
SnapshotStore.Save(acc, jsonPath);
var loadedAcc = SnapshotStore.Load(jsonPath);
SnapshotStore.ValidateForMerge(loadedAcc, "ACC");
Assert(
loadedAcc.Applications.Count == 2,
"JSON-Roundtrip hat Anwendungen verloren.");
var prod = ProdSnapshot();
SnapshotStore.ValidateForMerge(prod, "PROD");
new XlsxReportWriter().Write(new[] { loadedAcc, prod }, path);
Assert(File.Exists(path), "XLSX-Datei wurde nicht erzeugt.");
using (var archive = ZipFile.OpenRead(path))
{
var required = new[]
{
"[Content_Types].xml",
"_rels/.rels",
"docProps/core.xml",
"docProps/app.xml",
"xl/workbook.xml",
"xl/_rels/workbook.xml.rels",
"xl/styles.xml",
"xl/worksheets/sheet1.xml"
};
foreach (var name in required)
{
Assert(
archive.GetEntry(name) != null,
"XLSX-Part fehlt: " + name);
}
Assert(
archive.GetEntry("xl/worksheets/sheet2.xml") == null,
"Die Arbeitsmappe enthält mehr als ein Datenblatt.");
foreach (var entry in archive.Entries.Where(item =>
item.FullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)
|| item.FullName.EndsWith(".rels", StringComparison.OrdinalIgnoreCase)))
{
using (var stream = entry.Open())
{
XDocument.Load(stream);
}
}
var workbook = LoadXml(archive, "xl/workbook.xml");
XNamespace spreadsheet =
"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
var names = workbook.Descendants(spreadsheet + "sheet")
.Select(item => (string)item.Attribute("name"))
.ToList();
Assert(
names.SequenceEqual(new[] { "Phase 1" }),
"Es wird nicht exakt das Blatt 'Phase 1' erzeugt.");
var contentTypes = LoadXml(archive, "[Content_Types].xml");
XNamespace contentTypeNamespace =
"http://schemas.openxmlformats.org/package/2006/content-types";
Assert(
contentTypes.Root
.Elements(contentTypeNamespace + "Override")
.Count() == 5,
"Content-Type-Overrides sind unvollständig.");
var worksheet = LoadXml(
archive,
"xl/worksheets/sheet1.xml");
Assert(
worksheet.Descendants(spreadsheet + "mergeCell")
.Select(item => (string)item.Attribute("ref"))
.Contains("A1:G1"),
"Titelzeile ist nicht zusammengeführt.");
Assert(
(string)worksheet
.Descendants(spreadsheet + "autoFilter")
.Single()
.Attribute("ref") == "A2:G5",
"Filterbereich ist falsch.");
string text;
using (var reader = new StreamReader(
archive.GetEntry("xl/worksheets/sheet1.xml").Open(),
Encoding.UTF8))
{
text = reader.ReadToEnd();
}
Assert(text.Contains("BizTalk-Anwendung in ACC"), "ACC-Spalte fehlt.");
Assert(text.Contains("BizTalk-Anwendung in PRD"), "PRD-Spalte fehlt.");
Assert(text.Contains("FILE (1x) / SFTP (1x)"), "Adapteraggregation ist falsch.");
Assert(text.Contains("Nur in ACC vorhanden"), "ACC-Hinweis fehlt.");
Assert(text.Contains("Nur in PRD vorhanden"), "PRD-Hinweis fehlt.");
Assert(text.Contains("Gesamt: 3 BizTalk-Anwendungen"), "Summenzeile ist falsch.");
}
}
finally
{
try
{
if (File.Exists(jsonPath)) File.Delete(jsonPath);
if (!keepOutput && Directory.Exists(directory))
{
Directory.Delete(directory, true);
}
}
catch (IOException)
{
}
catch (UnauthorizedAccessException)
{
}
}
}
private static CatalogSnapshot AccSnapshot()
{
var snapshot = Snapshot("ACC", "BIZTALK-ACC");
snapshot.Applications.Add(Application(
"OrderProcessing",
new AdapterCount { AdapterType = "FILE", Count = 1 },
new AdapterCount { AdapterType = "SFTP", Count = 1 }));
snapshot.Applications.Add(Application(
"AccOnly",
new AdapterCount { AdapterType = "FILE", Count = 1 }));
return snapshot;
}
private static CatalogSnapshot ProdSnapshot()
{
var snapshot = Snapshot("PROD", "BIZTALK-PROD");
snapshot.Applications.Add(Application(
"OrderProcessing",
new AdapterCount { AdapterType = "FILE", Count = 1 },
new AdapterCount { AdapterType = "SFTP", Count = 1 }));
snapshot.Applications.Add(Application(
"ProdOnly",
new AdapterCount { AdapterType = "SFTP", Count = 1 }));
return snapshot;
}
private static CatalogSnapshot Snapshot(
string environment,
string computer)
{
return new CatalogSnapshot
{
EnvironmentName = environment,
ComputerName = computer,
CreatedUtc = DateTime.UtcNow.ToString("o"),
IsComplete = true
};
}
private static CatalogApplication Application(
string name,
params AdapterCount[] adapters)
{
var result = new CatalogApplication
{
Name = name,
EndpointCount = adapters.Sum(item => item.Count)
};
result.AdapterCounts.AddRange(adapters);
return result;
}
private static XDocument LoadXml(ZipArchive archive, string name)
{
using (var stream = archive.GetEntry(name).Open())
{
return XDocument.Load(stream);
}
}
private static void Assert(bool condition, string message)
{
if (!condition) throw new InvalidOperationException(message);
}
}
}