public static List <SnapshotTableDifferences> SortDifferences(SnapshotCollection collection, List <SnapshotTableDifferences> tableDiffs) { return(tableDiffs.Select(t => t.TableDefinition.SortColumns.Any() ? SortTable(t) : t) .ToList()); }
public static bool Match(SnapshotCollection collection, Snapshot before, Snapshot after) { foreach (var tableDefinition in collection.TablesInDefinitionOrder.Where(t => !t.ExcludeFromComparison)) { //find all keys var beforeRows = SnapshotKeyExtractor.GetKeys(before, tableDefinition) ?? new Dictionary <SnapshotRowKey, SnapshotRow>(); var afterRows = SnapshotKeyExtractor.GetKeys(after, tableDefinition) ?? new Dictionary <SnapshotRowKey, SnapshotRow>(); if (!beforeRows.Keys.SequenceEqual(afterRows.Keys)) { return(false); //snapshots have row difference } foreach (var snapshotRowKey in beforeRows.Keys) { var beforeRow = beforeRows[snapshotRowKey]; var afterRow = afterRows[snapshotRowKey]; var match = RowDataComparer.Compare(tableDefinition, snapshotRowKey, beforeRow, afterRow); if (!match.Matched) { return(false); } } } return(true); }
public void SetUp() { _collection = new SnapshotCollection(); _collection.DefineTable(TableName).PrimaryKey(IdCol).PrimaryKey(NameCol); _tableDef = _collection.GetTableDefinition(TableName); _snapshotBuilder = _collection.NewSnapshot("Test"); }
public void SnapshotRowsInMissingTablesAreNull() { //Arrange var snapshots = new SnapshotCollection(GetType(), t => t != typeof(Snapshots.TestDefinitions.TableDef)); snapshots.DefineTable("Customer") .PrimaryKey("Id") .CompareKey("Surname") .IsUnpredictable("Id"); var builder = snapshots.NewSnapshot("Before"); var rowBuilder = builder.AddNewRow("Customer"); rowBuilder["Id"] = 1; rowBuilder["Surname"] = "surname"; var snapshot = snapshots.GetSnapshot("Before"); //Act var row = snapshot.Rows("Customer").First(); var result = snapshot.GetRow(new SnapshotRowKey(row, snapshots.GetTableDefinition("Customer")), "Wrong"); //Assert result.Should().BeNull(); }
public void SetUp() { _collection = new SnapshotCollection(); _collection.DefineTable("Test").CompareKey("Key"); _snapshot = _collection.NewSnapshot("TestSnapshot"); _row = _snapshot.AddNewRow("Test"); }
public void ReportChangesThrowsWhenAfterSnapshotNotPresent() { //Arrange/Act var snapshots = new SnapshotCollection(GetType(), t => t != typeof(Snapshots.TestDefinitions.TableDef)); snapshots.DefineTable("Customer") .PrimaryKey("Id") .CompareKey("Surname") .IsUnpredictable("Id"); var customers = new[] { new { Id = 1, Surname = "S1", FirstName = "F1", Age = 40 }, }; var builder = snapshots.NewSnapshot("Before"); customers.ToSnapshotTable(builder, "Customer"); var output = new Output(); //Assert Action action = () => snapshots.ReportChanges("Before", "After", output); action.Should().Throw <SnapshotNotFoundException>().Where(x => x.SnapshotName == "After"); }
public static void Define(SnapshotCollection collection, SchemaStructure schema) { foreach (var table in schema.Tables) { var tableDef = collection.DefineTable(table.Name); foreach (var column in table.Columns.Where(c => c.InPrimaryKey)) { tableDef.PrimaryKey(column.Name); if (column.IsUnpredictable) { tableDef.IsUnpredictable(column.Name); } if (column.IsUtcDateTime) { tableDef.Utc(column.Name); } if (column.IsLocalDateTime) { tableDef.Local(column.Name); } } foreach (var reference in table.References) { tableDef.IsReference(reference.ReferencingColumnNames.First(), $"[{reference.ReferencedSchema}].[{reference.ReferencedTable}]", reference.ReferencedColumnNames.First()); } } }
/// <summary> /// Scan the differences in a set of table <see cref="SnapshotTableDifferences"/> for columns flagged as referencing rows in the snapshot. If the /// referenced row is present, but does not contain any differences, it will be returned as an additional reference. This method reads the differences, /// but will not make any changes. /// </summary> /// <param name="collection">The snapshot collection. Needed for table definitions.</param> /// <param name="tableDiffs">The difference set that will be analysed</param> /// <returns>An <see cref="AdditionalReferencedRows"/> instance containing the referenced row details. Only rows not currently in the difference set /// will be included.</returns> public static AdditionalReferencedRows GetMissingRows(SnapshotCollection collection, IReadOnlyCollection <SnapshotTableDifferences> tableDiffs) { var allKeysByReferencedTable = GeyKeysByReferencedTable(collection, tableDiffs) .Where(rk => rk.KeyValue != null) .GroupBy(rk => new { rk.ReferencedTableDefinition.TableName, rk.ColumnName }) .ToList(); var requiredTableNotPresent = allKeysByReferencedTable .Where(g => !tableDiffs.Any(td => td.TableDefinition.TableName == g.Key.TableName)) .ToList(); var missingKeys = allKeysByReferencedTable.Join(tableDiffs, kg => kg.Key.TableName, td => td.TableDefinition.TableName, (kg, td) => new { TableDefinition = kg.Key.TableName, KeyField = kg.Key.ColumnName, MissingRows = kg.Where(k => !td.RowDifferences.Any(row => IsMatchByKeyValue(row, k))) .Select(k => k.KeyValue).ToList() }) .Concat(requiredTableNotPresent.Select(r => new { TableDefinition = r.Key.TableName, KeyField = r.Key.ColumnName, MissingRows = allKeysByReferencedTable.Where(g => g.Key.TableName == r.Key.TableName) .SelectMany(g => g.Select(k => k.KeyValue)) .ToList() })) .GroupBy(req => req.TableDefinition) .Select(g => new AdditionalReferencedRows.RequiredTableRows(collection.GetTableDefinition(g.Key), g.SelectMany(r => r.MissingRows.Select(mr => new AdditionalReferencedRows.RowRequest(r.KeyField, mr))).ToList())) .ToList(); return(new AdditionalReferencedRows(missingKeys)); }
internal TestData() { _collection = new SnapshotCollection(); Definer = _collection.DefineTable(TableName); Builder = _collection.NewSnapshot("Test"); Snapshot = _collection.GetSnapshot("Test"); NewRow(); }
internal static SnapshotDifferences ExtractDifferences(SnapshotCollection collection, Snapshot before, Snapshot after, ChangeReportOptions changeReportOptions = ChangeReportOptions.Default) { var tableDiffs = SnapshotDifferenceCalculator.GetDifferences(collection, before, after); tableDiffs = SnapshotDifferenceSorter.SortDifferences(collection, tableDiffs); tableDiffs = DifferenceRegulator.CleanDifferences(collection, tableDiffs, before, (changeReportOptions & ChangeReportOptions.NoSubs) == 0); return(new SnapshotDifferences(tableDiffs)); }
public static List <SnapshotTableDifferences> GetDifferences(SnapshotCollection collection, Snapshot before, Snapshot after) { return(collection .TablesInDefinitionOrder .Select(t => GetTableDifferences(t, before, after)) .Where(t => t != null) .ToList()); }
public void InitTimeIsSet() { //Arrange/Act var start = DateTime.UtcNow; var snapshots = new SnapshotCollection(); //Assert snapshots.InitialisationTime.Ticks.Should().BeGreaterOrEqualTo(start.Ticks); }
public static List <ISubstitutableValueTracker> Make(ColumnValueSet columnValueSet, SnapshotCollection snapshotCollection) { return(new List <ISubstitutableValueTracker> { new DateTimeValueTracker(columnValueSet.Column, TimeRangeExtractor.Extract(snapshotCollection)), new DefaultValueTracker(columnValueSet.Column.Name) }); }
public void DateDiagnosticsAreReported() { //Arrange var collection = new SnapshotCollection(); var beforeDates = new[] { DateTime.Parse("2020-10-11 10:35"), DateTime.Parse("2020-10-11 10:36"), DateTime.Parse("2020-10-11 10:37"), DateTime.Parse("2020-10-11 10:38"), }; var afterDates = new[] { DateTime.Parse("2020-10-11 10:35"), DateTime.Parse("2020-10-11 10:36"), DateTime.Parse("2020-10-11 10:39"), DateTime.Parse("2020-10-11 10:40"), DateTime.Parse("2020-10-11 10:41"), }; var beforeBuilder = collection.NewSnapshot("before"); collection.DefineTable("Dates").PrimaryKey("Key").IsUnpredictable("Date"); beforeDates.Select((bd, ix) => new { Key = ix, Date = bd, Other = "o", OtherDate = DateTime.MinValue }).ToSnapshotTable(beforeBuilder, "Dates"); var deleteRow = beforeBuilder.AddNewRow("Dates"); deleteRow["Key"] = 100; deleteRow["Date"] = DateTime.Parse("2020-10-18 11:19"); deleteRow["Other"] = "o"; deleteRow["OtherDate"] = DateTime.MinValue; var afterBuilder = collection.NewSnapshot("after"); afterDates.Select((bd, ix) => new { Key = ix, Date = bd, Other = "a", OtherDate = DateTime.MaxValue }).ToSnapshotTable(afterBuilder, "Dates"); var before = collection.GetSnapshot("before"); var after = collection.GetSnapshot("after"); var differences = SnapshotDifferenceAnalyser.ExtractDifferences(collection, before, after); var output = new Output(); //Act var ranges = new List <NamedTimeRange> { new NamedTimeRange(beforeDates[0], beforeDates[3], "before"), new NamedTimeRange(afterDates[2], afterDates[3], "after"), }; DateDiagnosticReporter.Report(output, ranges, before, after, differences); //Assert output.Report.Verify(); }
public void TableDefinitionsAreFilteredLoadedFromAssembly() { //Arrange/Act var snapshots = new SnapshotCollection(GetType().Assembly, t => t != typeof(Snapshots.TestDefinitions.TableDef)); //Assert var output = new Output(); snapshots.GetSchemaReport(output); output.Report.Verify(); }
public void TableDefinitionsAreLoadedFromType() { //Arrange/Act var snapshots = new SnapshotCollection(GetType()); //Assert var output = new Output(); snapshots.GetSchemaReport(output); output.Report.Verify(); }
public async Task <(object Snapshot, long Index)> GetSnapshotAsync(string actorName) { var sort = Builders <Snapshot> .Sort.Descending("snapshotIndex"); var snapshot = await SnapshotCollection .Find(s => s.ActorName == actorName) .Sort(sort) .FirstOrDefaultAsync(); return(snapshot != null ? (snapshot.Data, snapshot.SnapshotIndex) : (null, 0)); }
public void InitTimeIsSetUsingTimeSource() { //Arrange var time = DateTime.Parse("2020-09-19 19:53:01"); var snapshots = new SnapshotCollection(); //Act snapshots.SetTimeSource(new FakeTimeSource(time)); //Assert snapshots.InitialisationTime.Should().Be(time); }
public IEnumerable <SnapshotCollection> GetSnapshots(SourceUrl sourceUrl) { var result = new List <SnapshotCollection>(); if (!_isConfigured) { return(result); } foreach (var item in (IEnumerable)JsonConvert.DeserializeObject(new WebClient().DownloadString(String.Format("{0}{1}{2}", sourceUrl.Url, "contents.php", !String.IsNullOrEmpty(sourceUrl.GroupId) ? String.Format("?gid={0}", sourceUrl.GroupId) : String.Empty)))) { var i = 0; JProperty tmp = null; foreach (var m in (IEnumerable)item) { switch (i) { case 0: tmp = (m as JProperty); i++; break; case 1: var snapshotName = tmp != null ? (String)tmp.Value : String.Empty; var s = new SnapshotCollection(snapshotName); if (m != null) { foreach (var property in ((IEnumerable)m).OfType <JArray>()) { foreach (var ss in property.Select(prop => (String)prop).Where(ss => !String.IsNullOrEmpty(ss))) { s.Screenshots.Add(new SnapshotItem(ss.Replace(s.Name, String.Empty), String.Format("{0}{1}/{2}/", sourceUrl.Url, s.Name, ss))); } break; } } if (s.Screenshots.Any()) { result.Add(s); } break; } if (i > 1) { break; // Next } } } return(result); }
public static List <SnapshotTableDifferences> Refine(SnapshotCollection collection, List <SnapshotTableDifferences> tableDiffs, bool performSubstitution) { var unpredictableValues = UnpredictableColumnLocator.Locate(tableDiffs.Select(td => td.TableDefinition).ToList()) .SelectMany(u => UnpredictableValueScanner.Scan(u, tableDiffs)) .ToList(); if (performSubstitution) { return(ValueSubstituter.Substitute(unpredictableValues, tableDiffs, collection)); } return(tableDiffs); }
public void BasicTableStructureIsLoaded() { //Arrange var collection = new SnapshotCollection(); //Act SnapshotTableDefiner.Define(collection, _schema); //Assert var output = new Output(); collection.GetSchemaReport(output, true); output.Report.Verify(); }
internal static List <NamedTimeRange> Extract(SnapshotCollection collection) { var start = collection.InitialisationTime; return(collection .GetSnapshots() .Select(s => { var snapshotEnd = s.SnapshotTimestamp; var range = new NamedTimeRange(start, snapshotEnd, s.Name); start = snapshotEnd; return range; }).ToList()); }
public void SubstitutionsCanBeDisabledInDiffReports() { //Arrange var snapshots = new SnapshotCollection(); snapshots.DefineTable("Customer") .PrimaryKey("Id") .CompareKey("Surname") .IsUnpredictable("Id"); snapshots.DefineTable("Address") .PrimaryKey("AddressId") .IsUnpredictable("AddressId") .IsReference("CustomerId", "Customer", "Id"); var customers = new[] { new { Id = 1, Surname = "S1", FirstName = "F1", Age = 40 }, new { Id = 2, Surname = "S2", FirstName = "F2", Age = 45 }, new { Id = 3, Surname = "S3", FirstName = "F3", Age = 50 }, }; var addresses = new[] { new { AddressId = 102, CustomerId = 1, House = 15, Street = "Line 1", PostCode = "code1" }, new { AddressId = 193, CustomerId = 2, House = 99, Street = "Line 2", PostCode = "code2" }, new { AddressId = 6985, CustomerId = 3, House = 8000, Street = "Line 3", PostCode = "code3" } }; { var builder = snapshots.NewSnapshot("Before"); customers.ToSnapshotTable(builder, "Customer"); addresses.ToSnapshotTable(builder, "Address"); } customers[1] = new { Id = 2, Surname = "S2", FirstName = "F2Edited", Age = 32 }; addresses[2] = new { AddressId = 6985, CustomerId = 2, House = 8001, Street = "Line 3", PostCode = "code3" }; { var builder2 = snapshots.NewSnapshot("After"); customers.ToSnapshotTable(builder2, "Customer"); addresses.ToSnapshotTable(builder2, "Address"); } //Act/Assert var output = new Output(); snapshots.ReportChanges("Before", "After", output, ChangeReportOptions.NoSubs); output.Report.Verify(); }
internal static List <SnapshotTableDifferences> ExpandDifferences(SnapshotCollection collection, List <SnapshotTableDifferences> tableDiffs, Snapshot before) { var rows = ReferencedRowLocator.GetMissingRows(collection, tableDiffs); tableDiffs = DifferenceEnhancer.RequireRows(collection, tableDiffs, rows, before); var mandatoryFields = MandatoryColumnFinder.Find(collection, tableDiffs); foreach (var tableColumnRequest in mandatoryFields) { tableDiffs = DifferenceColumnAdder.RequireColumns(collection, tableDiffs, tableColumnRequest.TableDefinition, tableColumnRequest.Columns, before); } return(tableDiffs); }
public void SetUp() { _collection = new SnapshotCollection(); _collection.DefineTable(TestTableName).CompareKey("Id"); _table = _collection.GetTableDefinition(TestTableName); _snapshot = _collection.NewSnapshot("Test"); //Borrow a column config so that we can test with it. void ExtractColumnDefForTest(ColumnConfig config) { _cc = config; } var report = new[] { "T" }.AsReport(rep => rep.AddColumn(t => t, ExtractColumnDefForTest)); }
public void TableDefinitionsCanBeApplied() { //Arrange var definitionSet = SnapshotDefinitionLoader.Load(GetType()); var snapshots = new SnapshotCollection(); //Act snapshots.ApplyDefinitions(definitionSet); //Assert var output = new Output(); snapshots.GetSchemaReport(output, true); output.Report.Verify(); }
public void GetSnapshotReturnsTheRequestedSnapshot() { //Arrange/Act var snapshots = new SnapshotCollection(GetType(), t => t != typeof(Snapshots.TestDefinitions.TableDef)); snapshots.DefineTable("Customer") .PrimaryKey("Id") .CompareKey("Surname") .IsUnpredictable("Id"); var builder = snapshots.NewSnapshot("Before"); //Assert snapshots.GetSnapshot("Before").Name.Should().Be("Before"); }
public void TablesAreDefined() { //Arrange var snapshots = new SnapshotCollection(); //Act snapshots.DefineTable("Customer").PrimaryKey("Id").CompareKey("Surname"); snapshots.DefineTable("Address").PrimaryKey("AddressId"); //Assert var output = new Output(); snapshots.GetSchemaReport(output); output.Report.Verify(); }
public void SubstitutionsCanBeSuppressed() { //Arrange var collection = new SnapshotCollection(); collection.DefineTable("TheTable") .PrimaryKey("Id") .IsUnpredictable("Id"); void AddRow(SnapshotBuilder snapshot, int id, string name) { var add = snapshot.AddNewRow("TheTable"); add["Id"] = id; add["Name"] = name; } void AddData(SnapshotBuilder snapshot, string names) { var id = 1; foreach (var name in names.Split(',')) { AddRow(snapshot, id++, name); } } var beforeBuilder = collection.NewSnapshot("Before"); AddData(beforeBuilder, "A,B,C"); var afterBuilder = collection.NewSnapshot("After"); AddData(afterBuilder, "D,E,F"); var before = collection.GetSnapshot("Before"); var after = collection.GetSnapshot("After"); var diffs = SnapshotDifferenceAnalyser.ExtractDifferences(collection, before, after, ChangeReportOptions.NoSubs); //Act var result = SnapshotDifferenceSorter.SortDifferences(collection, diffs.TableDifferences.ToList()); //Assert var output = new Output(); result.Report(output); output.Report.Verify(); }
public void SnapshotThrowsWhenUndefinedTableUsed() { //Arrange/Act var snapshots = new SnapshotCollection(GetType(), t => t != typeof(Snapshots.TestDefinitions.TableDef)); snapshots.DefineTable("Customer") .PrimaryKey("Id") .CompareKey("Surname") .IsUnpredictable("Id"); var builder = snapshots.NewSnapshot("Before"); //Assert Action action = () => builder.AddNewRow("Wrong"); action.Should().Throw <UndefinedTableInSnapshotException>().Where(x => x.TableName == "Wrong"); }