Beispiel #1
0
        public void Equals_returns_false_for_object([HasIdentity] TicketRelationship ticketRel,
                                                    [HasIdentity] DirectionalRelationship rel1)
        {
            var sut = new TraversibleRelationship(ticketRel.GetIdentity(), null, null, rel1.GetIdentity());

            Assert.That(() => sut.Equals(new Object()), Is.False);
        }
Beispiel #2
0
        public void Equals_returns_true_for_two_equal_identities([HasIdentity] TicketRelationship ticketRel,
                                                                 [HasIdentity] DirectionalRelationship rel1,
                                                                 [HasIdentity] DirectionalRelationship rel2)
        {
            var sut = new TraversibleRelationship(ticketRel.GetIdentity(), null, null, rel1.GetIdentity());
            var two = new TraversibleRelationship(ticketRel.GetIdentity(), null, null, rel2.GetIdentity());

            Assert.That(() => sut.Equals(two), Is.True);
        }
        public void A_user_can_add_a_hierarchical_ticket_relationship(Project project,
                                                                      Ticket childTicket,
                                                                      Ticket parentTicket,
                                                                      TicketType type,
                                                                      DirectionalRelationship parentChildRelationship,
                                                                      [FromDi] Lazy <IEntityData> data,
                                                                      [FromDi] Lazy <IGetsTransaction> tranFactory,
                                                                      [FromDi] Lazy <IHandlesEditTicketRequest> sut)
        {
            project.Code = "AddTicketRelationshipIntegrationTests.A_user_can_add_a_hierarchical_ticket_relationship";

            parentChildRelationship.Behaviour.ProhibitCircularRelationship           = true;
            parentChildRelationship.Behaviour.ProhibitMultipleSecondaryRelationships = false;

            childTicket.Project      = project;
            childTicket.TicketNumber = 1;
            childTicket.Type         = type;

            parentTicket.Project      = project;
            parentTicket.TicketNumber = 2;
            parentTicket.Type         = type;

            using (var tran = tranFactory.Value.GetTransaction())
            {
                data.Value.Add(project);
                data.Value.Add(parentChildRelationship);
                data.Value.Add(parentTicket);
                data.Value.Add(type);
                tran.Commit();
            }

            var editRequest = new EditTicketRequest {
                Identity = parentTicket.GetIdentity(),
                CommaSeparatedLabelNames = String.Empty,
                Description        = "This is a description",
                SprintIdentity     = null,
                Title              = "This is a title",
                TicketTypeIdentity = type.GetIdentity(),
                RelationshipsToAdd = new [] {
                    new AddRelationshipRequest {
                        ParticipationType      = RelationshipParticipant.Secondary,
                        RelatedTicketReference = childTicket.GetTicketReference(),
                        RelationshipId         = parentChildRelationship.GetIdentity(),
                    },
                },
            };

            var result = sut.Value.Edit(editRequest);

            if (result?.IsSuccess != true)
            {
                var unsuccessfulRules = result.ValidationResult.RuleResults.Where(x => x.RuleResult.Outcome != RuleOutcome.Success);
                logger.Error($"Failed results are: {String.Join(", ", unsuccessfulRules.Select(x => $"{x.ManifestIdentity}: {x.RuleResult.Outcome}"))}");
            }

            Assert.That(result?.IsSuccess, Is.True);
        }
            private void AddExistingRelationship(DirectionalRelationship relationship)
            {
                DirectionalRelationship existingRelationship;

                if (m_existingRelationships.TryGetValue(relationship, out existingRelationship))
                {
                    existingRelationship.AddToEquivalenceSet(relationship);
                }
                else
                {
                    m_existingRelationships.Add(relationship, relationship);
                }
            }
Beispiel #5
0
        public void Entity_should_persist_successfully(Ticket ticket,
                                                       Comment comment1,
                                                       Comment comment2,
                                                       Label label1,
                                                       Label label2,
                                                       DirectionalRelationship rel1,
                                                       DirectionalRelationship rel2,
                                                       NonDirectionalRelationship rel3,
                                                       Ticket otherTicket,
                                                       TicketWorkLog log1,
                                                       TicketWorkLog log2,
                                                       [FromDi] Lazy <ISessionFactory> sessionFactory,
                                                       [FromDi] Lazy <IResetsDatabase> dbResetter)
        {
            ticket.Comments.Add(comment1);
            ticket.Comments.Add(comment2);
            ticket.Labels.Add(label1);
            ticket.Labels.Add(label2);
            ticket.PrimaryRelationships.Add(new TicketRelationship {
                Relationship = rel1, SecondaryTicket = otherTicket
            });
            ticket.PrimaryRelationships.Add(new TicketRelationship {
                Relationship = rel3, SecondaryTicket = otherTicket
            });
            ticket.SecondaryRelationships.Add(new TicketRelationship {
                Relationship = rel2, PrimaryTicket = otherTicket
            });
            ticket.WorkLogs.Add(log1);
            ticket.WorkLogs.Add(log2);

            using (var provider = new CachingDataConnectionFactoryAdapter(new CSF.ORM.NHibernate.SessionFactoryAdapter(sessionFactory.Value)))
            {
                var result = TestPersistence.UsingConnectionProvider(provider)
                             .WithSetup(s => dbResetter.Value.ResetDatabase(), false)
                             .WithEntity(ticket)
                             .WithEqualityRule(builder => {
                    return(builder
                           .ForProperty(x => x.CreationTimestamp, c => c.UsingComparer(ComparerFactory.GetDateTimeAccurateToSecondsComparer()))

                           .ForProperty(x => x.Comments, c => c.UsingComparer(new SetEqualityComparer <Comment>(new EntityIdentityEqualityComparer())))
                           .ForProperty(x => x.Labels, c => c.UsingComparer(new SetEqualityComparer <Label>(new EntityIdentityEqualityComparer())))
                           .ForProperty(x => x.PrimaryRelationships, c => c.UsingComparer(new SetEqualityComparer <TicketRelationship>(new EntityIdentityEqualityComparer())))
                           .ForProperty(x => x.SecondaryRelationships, c => c.UsingComparer(new SetEqualityComparer <TicketRelationship>(new EntityIdentityEqualityComparer())))
                           .ForProperty(x => x.WorkLogs, c => c.UsingComparer(new SetEqualityComparer <TicketWorkLog>(new EntityIdentityEqualityComparer())))
                           .ForAllOtherProperties());
                });
                Assert.That(result, Persisted.Successfully());
            }
        }
 public void Entity_should_persist_successfully(DirectionalRelationship relationship,
                                                [FromDi] Lazy <ISessionFactory> sessionFactory,
                                                [FromDi] Lazy <IResetsDatabase> dbResetter)
 {
     using (var provider = new CachingDataConnectionFactoryAdapter(new CSF.ORM.NHibernate.SessionFactoryAdapter(sessionFactory.Value)))
     {
         var result = TestPersistence.UsingConnectionProvider(provider)
                      .WithSetup(s => dbResetter.Value.ResetDatabase(), false)
                      .WithEntity(relationship)
                      .WithEqualityRule(builder => {
             return(builder
                    .ForAllOtherProperties());
         });
         Assert.That(result, Persisted.Successfully());
     }
 }
            /// <summary>
            /// Determines the net change in relationship count.
            /// For instance, if the directional relationship is added 2 times and deleted 3, the return value is -1.
            /// </summary>
            private int GetDirectionalRelationshipCountDelta(DirectionalRelationship expectedRelationship)
            {
                // lookup up existing relationship from expected relationship
                DirectionalRelationship existingRelationship;

                if (m_existingRelationships.TryGetValue(expectedRelationship, out existingRelationship))
                {
                    int addedCount;
                    int deletedCount;
                    existingRelationship.GetCountsInEquivalenceSet(out addedCount, out deletedCount);
                    return(addedCount - deletedCount);
                }
                else
                {
                    // no modifications to the relationship... return 0 (no net change)
                    return(0);
                }
            }
        TicketRelationship GetTicketRelationship(RelationshipType t, long relationshipId)
        {
            Relationship relationship = null;

            switch (t)
            {
            case RelationshipType.Directional:
                relationship = new DirectionalRelationship();
                break;

            case RelationshipType.NonDirectional:
                relationship = new NonDirectionalRelationship();
                break;
            }

            ((IEntity)relationship).IdentityValue = relationshipId;

            return(new TicketRelationship {
                Relationship = relationship
            });
        }
        public void IsRelationshipCircular_returns_true_when_complex_circle_exists([HasIdentity] DirectionalRelationship rel,
                                                                                   [HasIdentity] Ticket ticket1,
                                                                                   [HasIdentity] Ticket ticket2,
                                                                                   [HasIdentity] Ticket ticket3,
                                                                                   [HasIdentity] Ticket ticket4,
                                                                                   [HasIdentity] Ticket ticket5,
                                                                                   [HasIdentity] TicketRelationship tr1,
                                                                                   [HasIdentity] TicketRelationship tr2,
                                                                                   [HasIdentity] TicketRelationship tr3,
                                                                                   [HasIdentity] TicketRelationship tr4,
                                                                                   [HasIdentity] TicketRelationship tr5,
                                                                                   CircularRelationshipDetector sut)
        {
            var traversibleRelationships = new[] {
                new TraversibleRelationship(tr1.GetIdentity(),
                                            ticket1.GetIdentity(),
                                            ticket2.GetIdentity(),
                                            rel.GetIdentity()),
                new TraversibleRelationship(tr2.GetIdentity(),
                                            ticket2.GetIdentity(),
                                            ticket3.GetIdentity(),
                                            rel.GetIdentity()),
                new TraversibleRelationship(tr3.GetIdentity(),
                                            ticket2.GetIdentity(),
                                            ticket4.GetIdentity(),
                                            rel.GetIdentity()),
                new TraversibleRelationship(tr4.GetIdentity(),
                                            ticket5.GetIdentity(),
                                            ticket4.GetIdentity(),
                                            rel.GetIdentity()),
                new TraversibleRelationship(tr5.GetIdentity(),
                                            ticket4.GetIdentity(),
                                            ticket1.GetIdentity(),
                                            rel.GetIdentity()),
            };

            var result = sut.IsRelationshipCircular(rel.GetIdentity(), traversibleRelationships);

            Assert.That(result, Is.True);
        }
            /// <summary>
            /// Add a relationship to be tracked by the validator.
            /// </summary>
            /// <param name="associationSet">Relationship set to which the given record belongs.</param>
            /// <param name="record">Relationship record. Must conform to the type of the relationship set.</param>
            /// <param name="stateEntry">State entry for the relationship being tracked</param>
            internal void RegisterAssociation(AssociationSet associationSet, IExtendedDataRecord record, IEntityStateEntry stateEntry)
            {
                EntityUtil.CheckArgumentNull(associationSet, "relationshipSet");
                EntityUtil.CheckArgumentNull(record, "record");
                EntityUtil.CheckArgumentNull(stateEntry, "stateEntry");

                Debug.Assert(associationSet.ElementType.Equals(record.DataRecordInfo.RecordType.EdmType));

                // retrieve the ends of the relationship
                Dictionary <string, EntityKey> endNameToKeyMap = new Dictionary <string, EntityKey>(
                    StringComparer.Ordinal);

                foreach (FieldMetadata field in record.DataRecordInfo.FieldMetadata)
                {
                    string    endName   = field.FieldType.Name;
                    EntityKey entityKey = (EntityKey)record.GetValue(field.Ordinal);
                    endNameToKeyMap.Add(endName, entityKey);
                }

                // register each unidirectional relationship subpart in the relationship instance
                var ends = associationSet.AssociationSetEnds;

                foreach (var fromEnd in ends)
                {
                    foreach (var toEnd in ends)
                    {
                        // end to itself does not describe an interesting relationship subpart
                        if (object.ReferenceEquals(toEnd.CorrespondingAssociationEndMember, fromEnd.CorrespondingAssociationEndMember))
                        {
                            continue;
                        }

                        EntityKey toEntityKey = endNameToKeyMap[toEnd.CorrespondingAssociationEndMember.Name];
                        DirectionalRelationship relationship = new DirectionalRelationship(toEntityKey, fromEnd.CorrespondingAssociationEndMember,
                                                                                           toEnd.CorrespondingAssociationEndMember, associationSet, stateEntry);
                        AddExistingRelationship(relationship);
                    }
                }
            }
        public void GetRelationships_can_get_a_grandchild_relationship(Ticket ticket1,
                                                                       Ticket ticket2,
                                                                       Ticket ticket3,
                                                                       DirectionalRelationship relationship)
        {
            var rel1 = new TicketRelationship {
                PrimaryTicket   = ticket1,
                SecondaryTicket = ticket2,
                Relationship    = relationship
            };
            var rel2 = new TicketRelationship {
                PrimaryTicket   = ticket2,
                SecondaryTicket = ticket3,
                Relationship    = relationship
            };

            var result = ExerciseSut(ticket1, rel1, rel2);

            Assert.That(result?.Count, Is.EqualTo(2), "Count of results");
            Assert.That(result?.Select(x => x?.Ticket)?.ToList(), Is.EquivalentTo(new[] { ticket1, ticket1 }), "Correct source tickets");
            Assert.That(result?.Select(x => x?.RelatedTicket)?.ToList(), Is.EquivalentTo(new[] { ticket2, ticket3 }), "Correct related tickets");
            Assert.That(result?.Select(x => x?.Direction)?.ToList(), Is.EquivalentTo(new[] { HierarchicalRelationshipDirection.Descendent, HierarchicalRelationshipDirection.Descendent }), "Correct relationship direction");
            Assert.That(result?.Select(x => x?.TicketRelationship)?.ToList(), Is.EquivalentTo(new[] { rel1, rel2 }), "Correct ticket relationships");
        }
            /// <summary>
            /// Add an entity to be tracked by the validator. Requires that the input describes an entity.
            /// </summary>
            /// <param name="stateEntry">State entry for the entity being tracked.</param>
            internal void RegisterEntity(IEntityStateEntry stateEntry)
            {
                EntityUtil.CheckArgumentNull(stateEntry, "stateEntry");

                if (EntityState.Added == stateEntry.State || EntityState.Deleted == stateEntry.State)
                {
                    // We only track added and deleted entities because modifications to entities do not affect
                    // cardinality constraints. Relationships are based on end keys, and it is not
                    // possible to modify key values.
                    Debug.Assert(null != (object)stateEntry.EntityKey, "entity state entry must have an entity key");
                    EntityKey  entityKey  = EntityUtil.CheckArgumentNull(stateEntry.EntityKey, "stateEntry.EntityKey");
                    EntitySet  entitySet  = (EntitySet)stateEntry.EntitySet;
                    EntityType entityType = EntityState.Added == stateEntry.State ?
                                            GetEntityType(stateEntry.CurrentValues) :
                                            GetEntityType(stateEntry.OriginalValues);

                    // figure out relationship set ends that are associated with this entity set
                    foreach (AssociationSet associationSet in GetReferencingAssocationSets(entitySet))
                    {
                        // describe unidirectional relationships in which the added entity is the "destination"
                        var ends = associationSet.AssociationSetEnds;
                        foreach (var fromEnd in ends)
                        {
                            foreach (var toEnd in ends)
                            {
                                // end to itself does not describe an interesting relationship subpart
                                if (object.ReferenceEquals(toEnd.CorrespondingAssociationEndMember,
                                                           fromEnd.CorrespondingAssociationEndMember))
                                {
                                    continue;
                                }

                                // skip ends that don't target the current entity set
                                if (!toEnd.EntitySet.EdmEquals(entitySet))
                                {
                                    continue;
                                }

                                // skip ends that aren't required
                                if (0 == MetadataHelper.GetLowerBoundOfMultiplicity(
                                        fromEnd.CorrespondingAssociationEndMember.RelationshipMultiplicity))
                                {
                                    continue;
                                }

                                // skip ends that don't target the current entity type
                                if (!MetadataHelper.GetEntityTypeForEnd(toEnd.CorrespondingAssociationEndMember)
                                    .IsAssignableFrom(entityType))
                                {
                                    continue;
                                }

                                // register the relationship so that we know it's required
                                DirectionalRelationship relationship = new DirectionalRelationship(entityKey, fromEnd.CorrespondingAssociationEndMember,
                                                                                                   toEnd.CorrespondingAssociationEndMember, associationSet, stateEntry);
                                m_impliedRelationships.Add(relationship, stateEntry);
                            }
                        }
                    }
                }
            }
Beispiel #13
0
        public void GetRelevantHierarchicalRelationships_can_get_a_relationship_with_a_secondary_ticket_identity(DirectionalRelationship relationship,
                                                                                                                 Identity <long, Ticket> ticketId,
                                                                                                                 [Frozen] IGetsHierarchicalTicketRelationships relationshipProvider,
                                                                                                                 PossiblyCircularHierarchicalTicketRelationshipProviderAdapter sut)
        {
            var theoreticalRelationship = new TheoreticalRelationship {
                Relationship    = relationship,
                SecondaryTicket = ticketId
            };

            relationship.Behaviour.ProhibitCircularRelationship = true;

            sut.GetRelevantHierarchicalRelationships(new[] { theoreticalRelationship });

            Mock.Get(relationshipProvider)
            .Verify(x => x.GetRelationships(ticketId), Times.Once);
        }
            /// <summary>
            /// Validates cardinality constraints for all added entities/relationships.
            /// </summary>
            internal void ValidateConstraints()
            {
                // ensure all expected relationships exist
                foreach (KeyValuePair <DirectionalRelationship, IEntityStateEntry> expected in m_impliedRelationships)
                {
                    DirectionalRelationship expectedRelationship = expected.Key;
                    IEntityStateEntry       stateEntry           = expected.Value;

                    // determine actual end cardinality
                    int count = GetDirectionalRelationshipCountDelta(expectedRelationship);

                    if (EntityState.Deleted == stateEntry.State)
                    {
                        // our cardinality expectations are reversed for delete (cardinality of 1 indicates
                        // we want -1 operation total)
                        count = -count;
                    }

                    // determine expected cardinality
                    int minimumCount         = MetadataHelper.GetLowerBoundOfMultiplicity(expectedRelationship.FromEnd.RelationshipMultiplicity);
                    int?maximumCountDeclared = MetadataHelper.GetUpperBoundOfMultiplicity(expectedRelationship.FromEnd.RelationshipMultiplicity);
                    int maximumCount         = maximumCountDeclared.HasValue ? maximumCountDeclared.Value : count; // negative value
                    // indicates unlimited cardinality

                    if (count < minimumCount || count > maximumCount)
                    {
                        // We could in theory "fix" the cardinality constraint violation by introducing surrogates,
                        // but we risk doing work on behalf of the user they don't want performed (e.g., deleting an
                        // entity or relationship the user has intentionally left untouched).
                        throw EntityUtil.UpdateRelationshipCardinalityConstraintViolation(
                                  expectedRelationship.AssociationSet.Name, minimumCount, maximumCountDeclared,
                                  TypeHelpers.GetFullName(expectedRelationship.ToEntityKey.EntityContainerName, expectedRelationship.ToEntityKey.EntitySetName),
                                  count, expectedRelationship.FromEnd.Name,
                                  stateEntry);
                    }
                }

                // ensure actual relationships have required ends
                foreach (DirectionalRelationship actualRelationship in m_existingRelationships.Keys)
                {
                    int addedCount;
                    int deletedCount;
                    actualRelationship.GetCountsInEquivalenceSet(out addedCount, out deletedCount);
                    int absoluteCount = Math.Abs(addedCount - deletedCount);
                    int minimumCount  = MetadataHelper.GetLowerBoundOfMultiplicity(actualRelationship.FromEnd.RelationshipMultiplicity);
                    int?maximumCount  = MetadataHelper.GetUpperBoundOfMultiplicity(actualRelationship.FromEnd.RelationshipMultiplicity);

                    // Check that we haven't inserted or deleted too many relationships
                    if (maximumCount.HasValue)
                    {
                        EntityState?violationType  = default(EntityState?);
                        int?        violationCount = default(int?);
                        if (addedCount > maximumCount.Value)
                        {
                            violationType  = EntityState.Added;
                            violationCount = addedCount;
                        }
                        else if (deletedCount > maximumCount.Value)
                        {
                            violationType  = EntityState.Deleted;
                            violationCount = deletedCount;
                        }
                        if (violationType.HasValue)
                        {
                            throw EntityUtil.Update(Strings.Update_RelationshipCardinalityViolation(maximumCount.Value,
                                                                                                    violationType.Value, actualRelationship.AssociationSet.ElementType.FullName,
                                                                                                    actualRelationship.FromEnd.Name, actualRelationship.ToEnd.Name, violationCount.Value),
                                                    null, actualRelationship.GetEquivalenceSet().Select(reln => reln.StateEntry));
                        }
                    }

                    // We care about the case where there is a relationship but no entity when
                    // the relationship and entity map to the same table. If there is a relationship
                    // with 1..1 cardinality to the entity and the relationship is being added or deleted,
                    // it is required that the entity is also added or deleted.
                    if (1 == absoluteCount && 1 == minimumCount && 1 == maximumCount) // 1..1 relationship being added/deleted
                    {
                        bool isAdd = addedCount > deletedCount;

                        // Ensure the entity is also being added or deleted
                        IEntityStateEntry entityEntry;

                        // Identify the following error conditions:
                        // - the entity is not being modified at all
                        // - the entity is being modified, but not in the way we expect (it's not being added or deleted)
                        if (!m_impliedRelationships.TryGetValue(actualRelationship, out entityEntry) ||
                            (isAdd && EntityState.Added != entityEntry.State) ||
                            (!isAdd && EntityState.Deleted != entityEntry.State))
                        {
                            throw EntityUtil.UpdateEntityMissingConstraintViolation(actualRelationship.AssociationSet.Name,
                                                                                    actualRelationship.ToEnd.Name, actualRelationship.StateEntry);
                        }
                    }
                }
            }
        public void IsRelationshipCircular_returns_true_when_a_ticket_in_the_circle_has_no_identity([HasIdentity] DirectionalRelationship rel,
                                                                                                    [HasIdentity] Ticket ticket2,
                                                                                                    [HasIdentity] Ticket ticket3,
                                                                                                    [HasIdentity] TicketRelationship tr1,
                                                                                                    [HasIdentity] TicketRelationship tr2,
                                                                                                    [HasIdentity] TicketRelationship tr3,
                                                                                                    CircularRelationshipDetector sut)
        {
            var traversibleRelationships = new[] {
                new TraversibleRelationship(tr1.GetIdentity(),
                                            null,
                                            ticket2.GetIdentity(),
                                            rel.GetIdentity()),
                new TraversibleRelationship(tr2.GetIdentity(),
                                            ticket2.GetIdentity(),
                                            ticket3.GetIdentity(),
                                            rel.GetIdentity()),
                new TraversibleRelationship(tr3.GetIdentity(),
                                            ticket3.GetIdentity(),
                                            null,
                                            rel.GetIdentity()),
            };

            var result = sut.IsRelationshipCircular(rel.GetIdentity(), traversibleRelationships);

            Assert.That(result, Is.True);
        }
        public void IsRelationshipCircular_returns_false_when_a_complex_non_circular_relationship_hierarchy_exists([HasIdentity] DirectionalRelationship rel1,
                                                                                                                   [HasIdentity] Ticket ticket1,
                                                                                                                   [HasIdentity] Ticket ticket2,
                                                                                                                   [HasIdentity] Ticket ticket3,
                                                                                                                   [HasIdentity] Ticket ticket4,
                                                                                                                   [HasIdentity] Ticket ticket5,
                                                                                                                   [HasIdentity] TicketRelationship tr1,
                                                                                                                   [HasIdentity] TicketRelationship tr2,
                                                                                                                   [HasIdentity] TicketRelationship tr3,
                                                                                                                   [HasIdentity] TicketRelationship tr4,
                                                                                                                   [HasIdentity] TicketRelationship tr5,
                                                                                                                   [HasIdentity] TicketRelationship tr6,
                                                                                                                   [HasIdentity] TicketRelationship tr7,
                                                                                                                   [Frozen, LoggerFor(typeof(CircularRelationshipDetector))] ILog logger,
                                                                                                                   CircularRelationshipDetector sut)
        {
            var traversibleRelationships = new[] {
                new TraversibleRelationship(tr1.GetIdentity(),
                                            ticket1.GetIdentity(),
                                            ticket2.GetIdentity(),
                                            rel1.GetIdentity()),
                new TraversibleRelationship(tr2.GetIdentity(),
                                            ticket1.GetIdentity(),
                                            ticket3.GetIdentity(),
                                            rel1.GetIdentity()),
                new TraversibleRelationship(tr3.GetIdentity(),
                                            ticket1.GetIdentity(),
                                            ticket4.GetIdentity(),
                                            rel1.GetIdentity()),
                new TraversibleRelationship(tr4.GetIdentity(),
                                            ticket2.GetIdentity(),
                                            ticket3.GetIdentity(),
                                            rel1.GetIdentity()),
                new TraversibleRelationship(tr5.GetIdentity(),
                                            ticket2.GetIdentity(),
                                            ticket4.GetIdentity(),
                                            rel1.GetIdentity()),
                new TraversibleRelationship(tr6.GetIdentity(),
                                            ticket3.GetIdentity(),
                                            ticket4.GetIdentity(),
                                            rel1.GetIdentity()),
                new TraversibleRelationship(tr7.GetIdentity(),
                                            ticket4.GetIdentity(),
                                            ticket5.GetIdentity(),
                                            rel1.GetIdentity()),
            };

            Assert.That(() => sut.IsRelationshipCircular(rel1.GetIdentity(), traversibleRelationships), Is.False);
        }
        public void A_user_may_add_a_relatinship_to_a_complex_multipath_directional_relationship_structure(Project project,
                                                                                                           Ticket editedTicket,
                                                                                                           Ticket blockedTicket1,
                                                                                                           Ticket blockedTicket2,
                                                                                                           Ticket blockedTicket3,
                                                                                                           Ticket blockedTicket4,
                                                                                                           Ticket parentTicket,
                                                                                                           TicketType type,
                                                                                                           DirectionalRelationship blocks,
                                                                                                           DirectionalRelationship childOf,
                                                                                                           [FromDi] Lazy <IEntityData> data,
                                                                                                           [FromDi] Lazy <IGetsTransaction> tranFactory,
                                                                                                           [FromDi] Lazy <IHandlesEditTicketRequest> sut)
        {
            /* The summary of the test data is that there are two directional relationships (block & child-of)
             * which prohibit circular relationships.  The edited ticket blocks other tickets 1, 2 & 3.
             * Other ticket 1 blocks other tickets 2 & 3.  Other ticket 2 blocks other ticket 3. Other ticket 3
             * blocks other ticket 4.  This is valid because the blocks flow in only one direction and cannot get
             * back to a parent ticket.
             *
             * In the test, we are adding a new child-of relationship to the edited ticket, making it a child of
             * the parent ticket.
             */

            #region Setup test data

            project.Code = "AddTicketRelationshipIntegrationTests.A_user_may_add_a_relatinship_to_a_complex_multipath_directional_relationship_structure";

            blocks.Behaviour.ProhibitCircularRelationship           = true;
            blocks.Behaviour.ProhibitMultipleSecondaryRelationships = false;

            childOf.Behaviour.ProhibitCircularRelationship           = true;
            childOf.Behaviour.ProhibitMultipleSecondaryRelationships = false;

            editedTicket.Project      = project;
            editedTicket.TicketNumber = 1;
            editedTicket.Type         = type;

            blockedTicket1.Project      = project;
            blockedTicket1.TicketNumber = 2;
            blockedTicket1.Type         = type;

            blockedTicket1.Project      = project;
            blockedTicket1.TicketNumber = 3;
            blockedTicket1.Type         = type;

            blockedTicket1.Project      = project;
            blockedTicket1.TicketNumber = 4;
            blockedTicket1.Type         = type;

            blockedTicket1.Project      = project;
            blockedTicket1.TicketNumber = 5;
            blockedTicket1.Type         = type;

            parentTicket.Project      = project;
            parentTicket.TicketNumber = 6;
            parentTicket.Type         = type;

            editedTicket.PrimaryRelationships.Add(new TicketRelationship {
                SecondaryTicket = blockedTicket1, Relationship = blocks
            });
            editedTicket.PrimaryRelationships.Add(new TicketRelationship {
                SecondaryTicket = blockedTicket2, Relationship = blocks
            });
            editedTicket.PrimaryRelationships.Add(new TicketRelationship {
                SecondaryTicket = blockedTicket3, Relationship = blocks
            });
            blockedTicket1.PrimaryRelationships.Add(new TicketRelationship {
                SecondaryTicket = blockedTicket2, Relationship = blocks
            });
            blockedTicket1.PrimaryRelationships.Add(new TicketRelationship {
                SecondaryTicket = blockedTicket3, Relationship = blocks
            });
            blockedTicket2.PrimaryRelationships.Add(new TicketRelationship {
                SecondaryTicket = blockedTicket3, Relationship = blocks
            });
            blockedTicket3.PrimaryRelationships.Add(new TicketRelationship {
                SecondaryTicket = blockedTicket4, Relationship = blocks
            });

            using (var tran = tranFactory.Value.GetTransaction())
            {
                data.Value.Add(project);
                data.Value.Add(blocks);
                data.Value.Add(childOf);
                data.Value.Add(editedTicket);
                data.Value.Add(parentTicket);
                data.Value.Add(type);
                tran.Commit();
            }

            #endregion

            var editRequest = new EditTicketRequest {
                Identity           = editedTicket.GetIdentity(),
                Title              = "This is a title",
                TicketTypeIdentity = type.GetIdentity(),
                RelationshipsToAdd = new[] {
                    new AddRelationshipRequest {
                        ParticipationType      = RelationshipParticipant.Secondary,
                        RelatedTicketReference = parentTicket.GetTicketReference(),
                        RelationshipId         = childOf.GetIdentity(),
                    },
                },
            };

            var result = sut.Value.Edit(editRequest);

            if (result?.IsSuccess != true)
            {
                var unsuccessfulRules = result.ValidationResult.RuleResults.Where(x => x.RuleResult.Outcome != RuleOutcome.Success);
                logger.Error($"Failed results are: {String.Join(", ", unsuccessfulRules.Select(x => $"{x.ManifestIdentity}: {x.RuleResult.Outcome}"))}");
            }

            Assert.That(result?.IsSuccess, Is.True);
        }
Beispiel #18
0
        public void GetRelevantHierarchicalRelationships_does_not_include_a_relationship_which_permits_circles(DirectionalRelationship relationship,
                                                                                                               Identity <long, Ticket> ticketId,
                                                                                                               [Frozen] IGetsHierarchicalTicketRelationships relationshipProvider,
                                                                                                               PossiblyCircularHierarchicalTicketRelationshipProviderAdapter sut)
        {
            var theoreticalRelationship = new TheoreticalRelationship {
                Relationship  = relationship,
                PrimaryTicket = ticketId
            };

            relationship.Behaviour.ProhibitCircularRelationship = false;

            sut.GetRelevantHierarchicalRelationships(new[] { theoreticalRelationship });

            Mock.Get(relationshipProvider)
            .Verify(x => x.GetRelationships(It.Is <IIdentity <Ticket>[]>(p => p.Length == 0)), Times.Once);
        }
        public void AreRelationshipsValid_does_not_consider_relationships_of_different_types_for_validation([HasIdentity] Ticket ticket,
                                                                                                            [HasIdentity] DirectionalRelationship rel1,
                                                                                                            [HasIdentity] DirectionalRelationship rel2,
                                                                                                            [Frozen] IValidatesTheoreticalTicketRelationships wrapped,
                                                                                                            MultipleSecondaryRelationshipPreventingValidationDecorator sut)
        {
            var identity = ticket.GetIdentity();

            rel1.Behaviour.ProhibitMultipleSecondaryRelationships = true;
            rel2.Behaviour.ProhibitMultipleSecondaryRelationships = true;

            var relationships = new[] {
                new TheoreticalRelationship {
                    SecondaryTicket = identity,
                    Relationship    = rel1,
                    Type            = TheoreticalRelationshipType.Existing,
                },
                new TheoreticalRelationship {
                    SecondaryTicket = identity,
                    Relationship    = rel2,
                    Type            = TheoreticalRelationshipType.Added,
                },
            };

            Mock.Get(wrapped)
            .Setup(x => x.AreRelationshipsValid(It.IsAny <IIdentity <Ticket> >(), It.IsAny <IEnumerable <TheoreticalRelationship> >()))
            .Returns(true);

            var result = sut.AreRelationshipsValid(identity, relationships);

            Assert.That(result, Is.True);
        }
        public void AreRelationshipsValid_returns_false_when_there_are_disallowed_relationships([HasIdentity] Ticket ticket,
                                                                                                [HasIdentity] DirectionalRelationship rel,
                                                                                                [Frozen] IValidatesTheoreticalTicketRelationships wrapped,
                                                                                                MultipleSecondaryRelationshipPreventingValidationDecorator sut)
        {
            var identity = ticket.GetIdentity();

            rel.Behaviour.ProhibitMultipleSecondaryRelationships = true;

            var relationships = new[] {
                new TheoreticalRelationship {
                    SecondaryTicket = identity,
                    Relationship    = rel,
                    Type            = TheoreticalRelationshipType.Existing,
                },
                new TheoreticalRelationship {
                    SecondaryTicket = identity,
                    Relationship    = rel,
                    Type            = TheoreticalRelationshipType.Added,
                },
            };

            Mock.Get(wrapped)
            .Setup(x => x.AreRelationshipsValid(It.IsAny <IIdentity <Ticket> >(), It.IsAny <IEnumerable <TheoreticalRelationship> >()))
            .Returns(true);

            var result = sut.AreRelationshipsValid(identity, relationships);

            Assert.That(result, Is.False);
        }