public void ConnectedSharedResources_GivenTheSharedResourcesAreConnectedInACycle_ResolvesTheCycleCorrectly()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();
            var sharedResource3 = new SharedResource();
            var sharedResource4 = new SharedResource();
            sharedResource1.DirectlyConnect(sharedResource2);
            sharedResource2.DirectlyConnect(sharedResource3);
            sharedResource3.DirectlyConnect(sharedResource4);

            // Act
            sharedResource3.DirectlyConnect(sharedResource1);

            // Assert
            sharedResource1.ConnectedSharedResources.Should().Contain(new[] { sharedResource1, sharedResource2, sharedResource3, sharedResource4 });
            sharedResource2.ConnectedSharedResources.Should().Contain(new[] { sharedResource1, sharedResource2, sharedResource3, sharedResource4 });
            sharedResource3.ConnectedSharedResources.Should().Contain(new[] { sharedResource1, sharedResource2, sharedResource3, sharedResource4 });
            sharedResource4.ConnectedSharedResources.Should().Contain(new[] { sharedResource1, sharedResource2, sharedResource3, sharedResource4 });
        }
        public void ConnectSharedResources(SharedResource resource1, SharedResource resource2)
        {
            CheckSharedResourcesAcquired();
            CheckSharedResourcesAreInGroup(resource1, resource2);
            if (resource1.Equals(resource2) || resource1.DirectlyConnectedSharedResources.Contains(resource2)) return;

            resource1.DirectlyConnect(resource2);

            var resource1Identifier = resource1.GetCurrentRootSharedResourceIdentifier();
            var resource2Identifier = resource2.GetCurrentRootSharedResourceIdentifier();
            if (resource1Identifier.Equals(resource2Identifier)) return;

            var parentResourceIdentifier = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(resource1Identifier, resource2Identifier);
            parentResourceIdentifier.Acquire(this);

            resource1Identifier.SetParentSharedResourceIdentifier(parentResourceIdentifier);
            resource2Identifier.SetParentSharedResourceIdentifier(parentResourceIdentifier);

            // We must free these SharedResource identifiers to ensure that we do not hold onto them after the group is freed.
            resource1Identifier.Free(this);
            resource2Identifier.Free(this);
        }
        public void RemoveDirectConnectionTo_WhenDisconnectingAChainOfSharedResources_BreaksThatChain()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();
            var sharedResource3 = new SharedResource();
            var sharedResource4 = new SharedResource();
            sharedResource1.DirectlyConnect(sharedResource2);
            sharedResource2.DirectlyConnect(sharedResource3);
            sharedResource3.DirectlyConnect(sharedResource4);

            // Act
            sharedResource2.RemoveDirectConnectionTo(sharedResource3);

            // Assert
            sharedResource2.DirectlyConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource1, sharedResource2 }.Contains(r));
            sharedResource3.DirectlyConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource3, sharedResource4 }.Contains(r));

            sharedResource1.ConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource1, sharedResource2 }.Contains(r));
            sharedResource2.ConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource1, sharedResource2 }.Contains(r));
            sharedResource3.ConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource3, sharedResource4 }.Contains(r));
            sharedResource4.ConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource3, sharedResource4 }.Contains(r));
        }
        public void RemoveDirectConnectionTo_GivenAPairOfConnectedSharedResources_DisconnectsThemBoth()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();
            sharedResource1.DirectlyConnect(sharedResource2);

            // Act
            sharedResource2.RemoveDirectConnectionTo(sharedResource1);

            // Assert
            sharedResource1.DirectlyConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource1 }.Contains(r));
            sharedResource1.ConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource1 }.Contains(r));
            sharedResource2.DirectlyConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource2 }.Contains(r));
            sharedResource2.ConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource2 }.Contains(r));
        }
        public void DirectlyConnect_WhenAppliedToResourcesInAChain_ConnectsThemAllTogether()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();
            var sharedResource3 = new SharedResource();
            var sharedResource4 = new SharedResource();

            // Act
            sharedResource1.DirectlyConnect(sharedResource2);
            sharedResource2.DirectlyConnect(sharedResource3);
            sharedResource2.DirectlyConnect(sharedResource4);

            // Assert
            sharedResource1.DirectlyConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource1, sharedResource2 }.Contains(r));
            sharedResource2.DirectlyConnectedSharedResources.Should().Contain(new [] { sharedResource1, sharedResource2, sharedResource3, sharedResource4 });
            sharedResource3.DirectlyConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource3, sharedResource2 }.Contains(r));
            sharedResource4.DirectlyConnectedSharedResources.Should().OnlyContain(r => new[] { sharedResource4, sharedResource2 }.Contains(r));

            sharedResource2.ConnectedSharedResources.ShouldAllBeEquivalentTo(sharedResource1.ConnectedSharedResources);
            sharedResource3.ConnectedSharedResources.ShouldAllBeEquivalentTo(sharedResource1.ConnectedSharedResources);
            sharedResource4.ConnectedSharedResources.ShouldAllBeEquivalentTo(sharedResource1.ConnectedSharedResources);
            sharedResource1.ConnectedSharedResources.ShouldAllBeEquivalentTo(new[] { sharedResource1, sharedResource2, sharedResource3, sharedResource4 });
        }
        public void DirectlyConnect_GivenASharedResource_ConnectsTheCurrentSharedResourceToThatSharedResource()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();

            // Act
            sharedResource1.DirectlyConnect(sharedResource2);

            // Assert
            sharedResource1.DirectlyConnectedSharedResources.Should().Contain(sharedResource2);
            sharedResource1.ConnectedSharedResources.Should().Contain(sharedResource2);
            sharedResource2.DirectlyConnectedSharedResources.Should().Contain(sharedResource1);
            sharedResource2.ConnectedSharedResources.Should().Contain(sharedResource1);
        }
        public void DirectlyConnect_CalledTwiceForTheSameResource_OnlyConnectsThatResourceOnce()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();

            // Act
            sharedResource1.DirectlyConnect(sharedResource2);
            sharedResource1.DirectlyConnect(sharedResource2);

            // Assert
            sharedResource1.ConnectedSharedResources.Should().HaveCount(2);
            sharedResource2.ConnectedSharedResources.Should().HaveCount(2);
            sharedResource2.ConnectedSharedResources.ShouldAllBeEquivalentTo(sharedResource1.ConnectedSharedResources);
            sharedResource1.ConnectedSharedResources.Should().Contain(new[] { sharedResource1, sharedResource2 });

            sharedResource1.DirectlyConnectedSharedResources.Should().HaveCount(2);
            sharedResource2.DirectlyConnectedSharedResources.Should().HaveCount(2);
            sharedResource2.DirectlyConnectedSharedResources.ShouldAllBeEquivalentTo(sharedResource1.ConnectedSharedResources);
            sharedResource1.DirectlyConnectedSharedResources.Should().Contain(new[] { sharedResource1, sharedResource2 });
        }