protected override IEnumerable <MigrationOperation> Add(IColumn target, DiffContext diffContext, bool inline = false) { if (!inline) { foreach (var propertyMapping in target.PropertyMappings) { if (propertyMapping.Property.FindTypeMapping() is RelationalTypeMapping storeType) { var valueGenerationStrategy = MySqlValueGenerationStrategyCompatibility.GetValueGenerationStrategy( target.GetAnnotations() .ToArray()); // Ensure that null will be set for the columns default value, if CURRENT_TIMESTAMP has been required, // or when the store type of the column does not support default values at all. inline = inline || (storeType.StoreTypeNameBase == "datetime" || storeType.StoreTypeNameBase == "timestamp") && (valueGenerationStrategy == MySqlValueGenerationStrategy.IdentityColumn || valueGenerationStrategy == MySqlValueGenerationStrategy.ComputedColumn) || storeType.StoreTypeNameBase.Contains("text") || storeType.StoreTypeNameBase.Contains("blob") || storeType.StoreTypeNameBase == "geometry" || storeType.StoreTypeNameBase == "json"; if (inline) { break; } } } } return(PostFilterOperations(base.Add(target, diffContext, inline))); }
protected override IReadOnlyList <MigrationOperation> Sort( [NotNull] IEnumerable <MigrationOperation> operations, [NotNull] DiffContext diffContext) { var ops = base.Sort(operations, diffContext); // base.Sort will leave operations it doesn't recognize (Npgsql-specific) at the end. // If there's no Npgsql-specific operation, we have nothing to do and just return the list. if (ops.Count > 0 && !(ops[ops.Count - 1] is NpgsqlEnsurePostgresExtensionOperation)) { return(ops); } if (ops.Any(op => op is EnsureSchemaOperation)) { // We have at least one ensure schema operation. This must be ordered before extension // creation operations, since the latter may depend on the former. return(ops.TakeWhile(op => !(op is EnsureSchemaOperation)) .Concat(ops.Where(op => op is EnsureSchemaOperation)) .Concat(ops.Where(op => op is NpgsqlEnsurePostgresExtensionOperation)) .Concat(ops .SkipWhile(op => !(op is EnsureSchemaOperation)) .SkipWhile(op => op is EnsureSchemaOperation) .TakeWhile(op => !(op is NpgsqlEnsurePostgresExtensionOperation)) ) .ToArray()); } // No schema creation, just put the ensure extension operations at the beginning return(ops.Where(op => op is NpgsqlEnsurePostgresExtensionOperation) .Concat(ops.Where(op => !(op is NpgsqlEnsurePostgresExtensionOperation))) .ToArray()); }
private string getContext(IContextMaker contextMaker, DiffPosition position, ContextDepth depth, double fontSizePx, out string stylesheet) { stylesheet = String.Empty; if (contextMaker == null) { return("<html><body>Cannot access file storage and render diff context</body></html>"); } try { DiffContext context = contextMaker.GetContext(position, depth); DiffContextFormatter formatter = new DiffContextFormatter(fontSizePx, 2); stylesheet = formatter.GetStylesheet(); return(formatter.GetBody(context)); } catch (Exception ex) { if (ex is ArgumentException || ex is ContextMakingException) { string errorMessage = "Cannot render HTML context."; ExceptionHandlers.Handle(errorMessage, ex); return(String.Format("<html><body>{0} See logs for details</body></html>", errorMessage)); } throw; } }
private DiffLineViewModel TranslateLineContext(DiffViewLine item, int lineIndex) { DiffContext lineContext = DiffContext.Blank; switch (item.EditType) { case AehnlichLib.Enums.EditType.Delete: lineContext = DiffContext.Deleted; break; case AehnlichLib.Enums.EditType.Insert: lineContext = DiffContext.Added; break; case AehnlichLib.Enums.EditType.Change: lineContext = DiffContext.Context; break; case AehnlichLib.Enums.EditType.None: default: break; } return(new DiffLineViewModel(lineContext, item, lineIndex)); }
protected override IEnumerable <MigrationOperation> Add(IProperty target, DiffContext diffContext, bool inline = false) { var schema = _cassandraOptionsExtension.DefaultKeyspace; var targetEntityType = target.DeclaringEntityType.GetRootType(); var et = targetEntityType.Model.FindEntityType(target.ClrType); Type clrType; IEntityType userDefinedType = null; if (et == null || !et.IsUserDefinedType()) { var typeMapping = TypeMappingSource.GetMapping(target); clrType = typeMapping.Converter?.ProviderClrType ?? (typeMapping.ClrType).UnwrapNullableType(); } else { clrType = target.ClrType; userDefinedType = et; } var operation = new AddColumnOperation { Schema = schema, Table = targetEntityType.GetTableName(), Name = target.GetColumnName() }; Initialize( operation, target, clrType, target.IsColumnNullable(), MigrationsAnnotations.For(target), inline, userDefinedType); yield return(operation); }
/// <summary> /// Class constructor /// </summary> /// <param name="lineContext"></param> /// <param name="item"></param> /// <param name="lineIndex"></param> internal DiffLineViewModel(DiffContext lineContext, DiffViewLine item, int lineIndex) : this() { _Context = lineContext; _Model = item; this.IndexLineNumber = lineIndex; }
protected virtual IEnumerable <MigrationOperation> Diff( [NotNull] IEntityType source, [NotNull] IEntityType target, [NotNull] DiffContext diffContext) { var sourceAnnotations = Annotations.For(source); var targetAnnotations = Annotations.For(target); var schemaChanged = sourceAnnotations.Schema != targetAnnotations.Schema; var renamed = sourceAnnotations.TableName != targetAnnotations.TableName; if (schemaChanged || renamed) { yield return(new RenameTableOperation { Schema = sourceAnnotations.Schema, Name = sourceAnnotations.TableName, NewSchema = schemaChanged ? targetAnnotations.Schema : null, NewName = renamed ? targetAnnotations.TableName : null }); } diffContext.AddMapping(source, target); var operations = Diff(GetPropertiesInHierarchy(source), GetPropertiesInHierarchy(target), diffContext) .Concat(Diff(source.GetKeys(), target.GetKeys(), diffContext)) .Concat(Diff(GetIndexesInHierarchy(source), GetIndexesInHierarchy(target), diffContext)); foreach (var operation in operations) { yield return(operation); } }
public static IDiffResult <T> Diff <T, TKey, TData>( this IEnumerable <T> previous, IEnumerable <T> current, Func <T, TKey> keySelector, Func <T, TData> dataSelector ) { if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (dataSelector == null) { throw new ArgumentNullException(nameof(dataSelector)); } var diffContext = new DiffContext <T, TKey>(previous, current, keySelector); var modifiedKeys = diffContext.SelectModifiedKeys(dataSelector).ToArray(); var unmodifiedKeys = diffContext.SelectIntersectingKeys().Except(modifiedKeys).ToArray(); return(new DiffResult <T> { Removed = SelectValues(diffContext.Previous, diffContext.SelectRemovedKeys()), Added = SelectValues(diffContext.Current, diffContext.SelectAddedKeys()), Modified = SelectValues(diffContext.Current, modifiedKeys), Unmodified = SelectValues(diffContext.Current, unmodifiedKeys) }); }
protected virtual IEnumerable <MigrationOperation> Add(IForeignKey target, DiffContext diffContext) { var declaringRootEntityType = target.DeclaringEntityType.RootType(); var targetEntityTypeAnnotations = Annotations.For(declaringRootEntityType); var targetPrincipalEntityTypeAnnotations = Annotations.For(target.PrincipalEntityType.RootType()); // TODO: Set OnDelete (See #1084) var operation = new AddForeignKeyOperation { Schema = targetEntityTypeAnnotations.Schema, Table = targetEntityTypeAnnotations.TableName, Name = Annotations.For(target).Name, Columns = GetColumns(target.Properties), PrincipalSchema = targetPrincipalEntityTypeAnnotations.Schema, PrincipalTable = targetPrincipalEntityTypeAnnotations.TableName, PrincipalColumns = GetColumns(target.PrincipalKey.Properties) }; CopyAnnotations(MigrationsAnnotations.For(target), operation); var createTableOperation = diffContext.FindCreate(declaringRootEntityType); if (createTableOperation != null) { createTableOperation.ForeignKeys.Add(operation); } else { yield return(operation); } }
protected virtual IEnumerable <MigrationOperation> Add(IEntityType target, DiffContext diffContext) { var targetAnnotations = Annotations.For(target); var createTableOperation = new CreateTableOperation { Schema = targetAnnotations.Schema, Name = targetAnnotations.TableName }; CopyAnnotations(MigrationsAnnotations.For(target), createTableOperation); createTableOperation.Columns.AddRange(target.GetPropertiesInHierarchy().SelectMany(p => Add(p, inline: true)).Cast <AddColumnOperation>()); var primaryKey = target.GetPrimaryKey(); createTableOperation.PrimaryKey = Add(primaryKey).Cast <AddPrimaryKeyOperation>().Single(); createTableOperation.UniqueConstraints.AddRange( target.GetKeys().Where(k => k != primaryKey).SelectMany(Add).Cast <AddUniqueConstraintOperation>()); diffContext.AddCreate(target, createTableOperation); yield return(createTableOperation); foreach (var operation in target.GetIndexesInHierarchy().SelectMany(Add)) { yield return(operation); } }
protected override IEnumerable <MigrationOperation> Add(TableMapping target, DiffContext diffContext) { var schema = _cassandraOptionsExtension.DefaultKeyspace; var result = new List <MigrationOperation>(); var type = target.GetRootType(); if (!type.IsUserDefinedType()) { var entityType = target.EntityTypes[0]; var createTableOperation = new CreateTableOperation { Schema = schema, Name = target.Name, Comment = target.GetComment() }; createTableOperation.AddAnnotations(MigrationsAnnotations.For(entityType)); createTableOperation.Columns.AddRange(GetSortedProperties(target).SelectMany(p => Add(p, diffContext, inline: true)).Cast <AddColumnOperation>()); var primaryKey = target.EntityTypes[0].FindPrimaryKey(); if (primaryKey != null) { createTableOperation.PrimaryKey = Add(primaryKey, diffContext).Cast <AddPrimaryKeyOperation>().Single(); } createTableOperation.UniqueConstraints.AddRange( target.GetKeys().Where(k => !k.IsPrimaryKey()).SelectMany(k => Add(k, diffContext)) .Cast <AddUniqueConstraintOperation>()); createTableOperation.CheckConstraints.AddRange( target.GetCheckConstraints().SelectMany(c => Add(c, diffContext)) .Cast <CreateCheckConstraintOperation>()); foreach (var targetEntityType in target.EntityTypes) { diffContext.AddCreate(targetEntityType, createTableOperation); } result.Add(createTableOperation); foreach (var operation in target.GetIndexes().SelectMany(i => Add(i, diffContext))) { result.Add(operation); } return(result.ToArray()); } var createUserDefinedOperation = new CreateUserDefinedTypeOperation { Schema = schema, Name = target.Name, }; createUserDefinedOperation.Columns.AddRange(type.GetProperties().SelectMany(p => Add(p, diffContext, inline: true)).Cast <AddColumnOperation>()); result.Add(createUserDefinedOperation); foreach (var operation in target.GetIndexes().SelectMany(i => Add(i, diffContext))) { result.Add(operation); } return(result.ToArray()); }
public override IReadOnlyList <MigrationOperation> GetDifferences(IModel source, IModel target) { source = CleanModel(source); target = CleanModel(target); var diffContext = new DiffContext(source, target); return(Sort(Diff(source, target, diffContext), diffContext)); }
private static void UpdateRetainedChildComponent( ref DiffContext diffContext, int oldComponentIndex, int newComponentIndex) { var oldTree = diffContext.OldTree; var newTree = diffContext.NewTree; ref var oldComponentFrame = ref oldTree[oldComponentIndex];
public void Test003() { var controls = ToSourceCollection(@"<p diff:match=""p""></p>", ComparisonSourceType.Control); var tests = ToSourceCollection("<p></p><p></p>", ComparisonSourceType.Test); var context = new DiffContext(controls[0].Node.GetRoot() as IElement, tests[0].Node.GetRoot() as IElement); Should.Throw <DiffMatchSelectorReturnedTooManyResultsException>(() => CssSelectorElementMatcher.Match(context, controls, tests).ToList()); }
// Collect discussions started for lines within DiffContextDepth range near `position` private IEnumerable <ReportedDiscussionNote> getRelatedDiscussions( MergeRequestKey mrk, ReportedDiscussionNoteKey?keyOpt, DiffPosition position) { // Obtain a context for a passed position. DiffContext ctx = getDiffContext <CombinedContextMaker>(position, UnchangedLinePolicy.TakeFromRight); if (!ctx.IsValid()) { return(Array.Empty <ReportedDiscussionNote>()); } string leftFileName = position.LeftPath; string rightFileName = position.RightPath; Core.Matching.DiffRefs refs = position.Refs; List <DiffPosition> neighborPositions = new List <DiffPosition>(); // CombinedContextMaker provides a context where line numbers are matched so no need to // match them manually here. foreach (DiffContext.Line line in ctx.Lines) { Debug.Assert(line.Left.HasValue || line.Right.HasValue); string leftLineNumber = null; string rightLineNumber = null; if (line.Left.HasValue) { leftLineNumber = line.Left.Value.Number.ToString(); } if (line.Right.HasValue) { rightLineNumber = line.Right.Value.Number.ToString(); } neighborPositions.Add(new DiffPosition(leftFileName, rightFileName, leftLineNumber, rightLineNumber, refs)); } // Find discussions that reported on each line from the diff context. List <ReportedDiscussionNote> relatedNotes = new List <ReportedDiscussionNote>(); foreach (Discussion discussion in _getDiscussions(mrk)) { DiscussionNote firstNote = discussion.Notes.First(); DiffPosition firstNotePosition = PositionConverter.Convert(firstNote.Position); if (firstNotePosition != null) { foreach (DiffPosition neighbor in neighborPositions) { if (doPositionsReferenceTheSameLine(neighbor, firstNotePosition) && (!keyOpt.HasValue || keyOpt.Value.Id != firstNote.Id)) { ReportedDiscussionNote note = new ReportedDiscussionNote(firstNote.Id, discussion.Id, firstNotePosition, firstNote.Body, firstNote.Author.Name, firstNote.Created_At); relatedNotes.Add(note); } } } } return(relatedNotes.GroupBy(note => note.Key.Id).Select(c => c.First())); }
/// <inheritdoc/> protected override IEnumerable <MigrationOperation> Diff( IEnumerable <IForeignKey> source, IEnumerable <IForeignKey> target, DiffContext diffContext) { return(DiffCollection ( source, target, diffContext, Diff, Add, Remove, (s, t, c) => { if (s.Relational().Name != t.Relational().Name) { return false; } if (!s.Properties.Select(p => p.Relational().ColumnName).SequenceEqual( t.Properties.Select(p => c.FindSource(p)?.Relational().ColumnName))) { return false; } var schemaToInclude = ((SchemaAwareDiffContext)diffContext).Source.Relational().DefaultSchema; if (c.FindSourceTable(s.PrincipalEntityType).Schema == schemaToInclude && c.FindSourceTable(s.PrincipalEntityType) != c.FindSource(c.FindTargetTable(t.PrincipalEntityType))) { return false; } if (t.PrincipalKey.Properties.Select(p => c.FindSource(p)?.Relational().ColumnName) .First() != null && !s.PrincipalKey.Properties .Select(p => p.Relational().ColumnName).SequenceEqual( t.PrincipalKey.Properties.Select(p => c.FindSource(p)?.Relational().ColumnName))) { return false; } if (ToReferentialAction(s.DeleteBehavior) != ToReferentialAction(t.DeleteBehavior)) { return false; } return !HasDifferences ( this.MigrationsAnnotations.For(s), this.MigrationsAnnotations.For(t) ); } )); }
protected virtual IEnumerable <MigrationOperation> Diff( [NotNull] IEnumerable <IKey> source, [NotNull] IEnumerable <IKey> target, [NotNull] DiffContext diffContext) => DiffCollection( source, target, Diff, Add, Remove, (s, t) => (Annotations.For(s).Name == Annotations.For(t).Name) && s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties) && (s.IsPrimaryKey() == t.IsPrimaryKey()));
public void Test004() { var controls = ToSourceCollection(@"<p diff:match=""div""></p>", ComparisonSourceType.Control); var tests = ToSourceCollection("<p></p>", ComparisonSourceType.Test); var context = new DiffContext(controls[0].Node.GetRoot() as IElement, tests[0].Node.GetRoot() as IElement); var actual = CssSelectorElementMatcher.Match(context, controls, tests).ToList(); actual.ShouldBeEmpty(); }
protected override IEnumerable <MigrationOperation> Diff( [CanBeNull] IModel source, [CanBeNull] IModel target, [NotNull] DiffContext diffContext) => ( source != null && target != null ? Diff(source.Npgsql().PostgresExtensions, target.Npgsql().PostgresExtensions) : source == null ? target.Npgsql().PostgresExtensions.SelectMany(Add) : source.Npgsql().PostgresExtensions.SelectMany(Remove) ).Concat(base.Diff(source, target, diffContext));
private static void AppendDiffEntriesForRange( ref DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl) { // This is deliberately a very large method. Parts of it could be factored out // into other private methods, but doing so comes at a consequential perf cost, // because it involves so much parameter passing. You can think of the code here // as being several private methods (delimited by #region) pre-inlined. // // A naive "extract methods"-type refactoring will worsen perf by about 10%. So, // if you plan to refactor this, be sure to benchmark the old and new versions // on Mono WebAssembly. var origOldStartIndex = oldStartIndex; var origNewStartIndex = newStartIndex; var hasMoreOld = oldEndIndexExcl > oldStartIndex; var hasMoreNew = newEndIndexExcl > newStartIndex; var prevOldSeq = -1; var prevNewSeq = -1; var oldTree = diffContext.OldTree; var newTree = diffContext.NewTree; var matchWithNewTreeIndex = -1; // Only used when action == DiffAction.Match Dictionary <object, KeyedItemInfo> keyedItemInfos = null; try { while (hasMoreOld || hasMoreNew) { DiffAction action; #region "Read keys and sequence numbers" int oldSeq, newSeq; object oldKey, newKey; if (hasMoreOld) { ref var oldFrame = ref oldTree[oldStartIndex]; oldSeq = oldFrame.SequenceField; oldKey = KeyValue(ref oldFrame); } else { oldSeq = int.MaxValue; oldKey = null; } if (hasMoreNew) { ref var newFrame = ref newTree[newStartIndex]; newSeq = newFrame.SequenceField; newKey = KeyValue(ref newFrame); }
/// <summary> /// Throws ArgumentException. /// Throws GitOperationException and GitObjectException in case of problems with git. /// </summary> private void showDiscussionContext(HtmlPanel htmlPanel, TextBox tbFileName) { ContextDepth depth = new ContextDepth(0, 3); IContextMaker textContextMaker = new EnhancedContextMaker(_gitRepository); DiffContext context = textContextMaker.GetContext(_position, depth); DiffContextFormatter formatter = new DiffContextFormatter(); htmlPanel.Text = formatter.FormatAsHTML(context); tbFileName.Text = "Left: " + (_difftoolInfo.Left?.FileName ?? "N/A") + " Right: " + (_difftoolInfo.Right?.FileName ?? "N/A"); }
private static void UpdateRetainedChildComponent( ref DiffContext diffContext, int oldComponentIndex, int newComponentIndex) { // The algorithm here is the same as in AppendDiffEntriesForRange, except that // here we don't optimise for loops - we assume that both sequences are forward-only. // That's because this is true for all currently supported scenarios, and it means // fewer steps here. var oldTree = diffContext.OldTree; var newTree = diffContext.NewTree; ref var oldComponentFrame = ref oldTree[oldComponentIndex];
protected virtual IEnumerable <MigrationOperation> Diff( [NotNull] IEnumerable <IIndex> source, [NotNull] IEnumerable <IIndex> target, [NotNull] DiffContext diffContext) => DiffCollection( source, target, Diff, Add, Remove, (s, t) => string.Equals( Annotations.For(s).Name, Annotations.For(t).Name, StringComparison.OrdinalIgnoreCase) && s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties), (s, t) => s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties));
private Brush GetLineBackgroundDiffBrush(DiffContext context, bool lineIsImaginary) { var brush = default(SolidColorBrush); if (lineIsImaginary == false) { switch (context) { case DiffContext.Added: brush = _DiffView.ColorBackgroundAdded; break; case DiffContext.Deleted: brush = _DiffView.ColorBackgroundDeleted; break; case DiffContext.Context: brush = _DiffView.ColorBackgroundContext; break; case DiffContext.Blank: brush = _DiffView.ColorBackgroundBlank; break; default: throw new System.ArgumentException(context.ToString()); } } else { // These lines have no line number and where inserted or deleted to // re-sync view sequences when compared to each other switch (context) { case DiffContext.Added: brush = _DiffView.ColorBackgroundImaginaryLineAdded; break; case DiffContext.Deleted: brush = _DiffView.ColorBackgroundImaginaryLineDeleted; break; default: case DiffContext.Blank: case DiffContext.Context: throw new System.NotSupportedException(string.Format("Context '{0}' not supported. An imaginary line can only be inserted or deleted.", context)); } } return(brush); }
public void Test002() { var controls = ToSourceCollection(@"<p diff:match=""main > p:first-child""></p>", ComparisonSourceType.Control); var tests = ToSourceCollection("<p></p><main><p></p></main>", ComparisonSourceType.Test); var context = new DiffContext(controls[0].Node.GetRoot() as IElement, tests[0].Node.GetRoot() as IElement); var actual = CssSelectorElementMatcher.Match(context, controls, tests).ToList(); actual.Count.ShouldBe(1); actual[0].ShouldSatisfyAllConditions( c => c.Control.Node.ShouldBe(controls[0].Node), c => c.Test.Node.ShouldBe(tests[1].Node.FirstChild) ); }
public DiffData GetDiffDataById(int id) { using (var diffContext = new DiffContext()) { try { return(diffContext.Diffs.Where(b => b.Id == id).FirstOrDefault()); } catch (Exception ex) { throw ex; } } }
public void UpdateDiff(DiffData newDiff) { using (var diffContext = new DiffContext()) { try { diffContext.Update(newDiff); diffContext.SaveChanges(); } catch (Exception ex) { throw ex; } } }
protected virtual IEnumerable <MigrationOperation> Remove( [NotNull] IEntityType source, [NotNull] DiffContext diffContext) { var sourceAnnotations = Annotations.For(source); var operation = new DropTableOperation { Schema = sourceAnnotations.Schema, Name = sourceAnnotations.TableName }; diffContext.AddDrop(source, operation); yield return(operation); }
protected virtual IEnumerable <MigrationOperation> Diff( [NotNull] IEnumerable <IForeignKey> source, [NotNull] IEnumerable <IForeignKey> target, [NotNull] DiffContext diffContext) => DiffCollection( source, target, (s, t) => Diff(s, t, diffContext), t => Add(t, diffContext), s => Remove(s, diffContext), (s, t) => (Annotations.For(s).Name == Annotations.For(t).Name) && s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties) && (diffContext.FindTarget(s.PrincipalEntityType.RootType()) == t.PrincipalEntityType.RootType()) && s.PrincipalKey.Properties.Select(diffContext.FindTarget).SequenceEqual(t.PrincipalKey.Properties) && (s.DeleteBehavior == t.DeleteBehavior));
public static IEnumerable <T> SelectRemoved <T, TKey>( this IEnumerable <T> previous, IEnumerable <T> current, Func <T, TKey> keySelector ) { if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } var diffContext = new DiffContext <T, TKey>(previous, current, keySelector); return(SelectValues(diffContext.Previous, diffContext.SelectRemovedKeys())); }
public override DiffResult Diff(DiffContext ctx) { var diffResult = new DiffResult(); var files = Directory.GetFiles(ctx.BddFolder, "*.feature", SearchOption.TopDirectoryOnly); foreach (var file in files) { FeatureParser.Models.Feature f = null; var feature = new FeatureViewModel(); try { f = GetFeatureFromFile(file); feature.Name = f.Title.CodeLabel(); feature.Status = ItemStatus.XNotFound; foreach (var svm in f.Scenarios.Select(scenario => new ScenarioViewModel { Name = scenario.Title.CodeLabel(), Status = ItemStatus.XNotFound, Diff = { Left = scenario.ToString() } })) { feature.Scenarios.Add(svm); } } catch (InvalidInputException) { feature.Name = Path.GetFileNameWithoutExtension(file); feature.Status = ItemStatus.ParsingFailed; } diffResult.Features.Add(feature); } using (var filestream = File.OpenRead(ctx.TestOutputFile)) { var xml = XElement.Load(filestream); foreach (var suite in xml.Descendants("test-suite").Where(x=> x.Attribute("type").Value == "TestFixture")) { var featureCodeLabel = suite.Attribute("name").Value.Replace("FeatureTests", ""); var feature = diffResult.Features.FirstOrDefault(x => x.Name.Equals(featureCodeLabel)); if (feature == null) { feature = new FeatureViewModel() { Name = featureCodeLabel, Status = ItemStatus.XDeleted }; diffResult.Features.Add(feature); } else { feature.Status = ItemStatus.XOkay; } foreach (var testCase in xml.Descendants("test-case")) { var sections = testCase.Attribute("name") .Value.Split(new[] { suite.Attribute("name").Value + "." }, StringSplitOptions.RemoveEmptyEntries); var scenarioCodeLabel = sections[1]; var scenario = feature.Scenarios.FirstOrDefault(x => x.Name.Equals(scenarioCodeLabel)); if (scenario == null) { scenario = new ScenarioViewModel() { Name = scenarioCodeLabel, Status = ItemStatus.XDeleted }; feature.Scenarios.Add(scenario); } else { feature.Status = ItemStatus.XOkay; } scenario.DidPass = testCase.Attribute("result").Value.Equals("success", StringComparison.InvariantCultureIgnoreCase); var message = testCase.Descendants("message").Single(); var final = Regex.Replace(message.Value, @"TearDown\s:\s", ""); final = Regex.Replace(final, @"^\s", "", RegexOptions.Multiline); if (scenario.DidPass) { scenario.Diff.Right = GetFeatureFromString(final).Scenarios.Single().ToString(); } if (scenario.Status == ItemStatus.XNotFound) { scenario.Status = ItemStatus.XOkay; } if (!scenario.Diff.IsEqual() && scenario.Status != ItemStatus.XDeleted) { scenario.Status = ItemStatus.XModified; } if (scenario.DidPass) { scenario.TestStatus = TestStatus.XPassed; } else { scenario.TestStatus = TestStatus.XFailed; scenario.ErrorText = final; } } } } return diffResult; }
public abstract DiffResult Diff(DiffContext ctx);