public void DisconnectSharedResources(SharedResource resource1, SharedResource resource2)
        {
            CheckSharedResourcesAcquired();
            CheckSharedResourcesAreInGroup(resource1, resource2);
            if (resource1 == resource2) throw new ArgumentException("You cannot disconnect a shared resource form itself");
            if (!resource1.DirectlyConnectedSharedResources.Contains(resource2)) return;

            resource1.RemoveDirectConnectionTo(resource2);
            if (resource1.ConnectedSharedResources.Contains(resource2)) return;

            // All resources connected to resource 1 or 2 should have been acquired and have the same root shared resource identifier
            var originalResourceIdentifier = resource1.GetCurrentRootSharedResourceIdentifier();
            var newResourceIdentifierForResource1 = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(originalResourceIdentifier);
            newResourceIdentifierForResource1.Acquire(this);
            foreach (var resource in resource1.ConnectedSharedResources)
            {
                resource.ResetRootSharedResourceIdentifier(newResourceIdentifierForResource1);
            }
            var newResourceIdentifierForResource2 = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(newResourceIdentifierForResource1);
            newResourceIdentifierForResource2.Acquire(this);
            foreach (var resource in resource2.ConnectedSharedResources)
            {
                resource.ResetRootSharedResourceIdentifier(newResourceIdentifierForResource2);
            }
            originalResourceIdentifier.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_GivenAResourceThisIsNotConnectedTo_DoesNothing()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();

            // Act
            sharedResource1.RemoveDirectConnectionTo(sharedResource2);

            // Assert
            sharedResource1.ConnectedSharedResources.Should().HaveCount(1);
            sharedResource1.ConnectedSharedResources.Should().Contain(sharedResource1);
            sharedResource2.ConnectedSharedResources.Should().HaveCount(1);
            sharedResource2.ConnectedSharedResources.Should().Contain(sharedResource2);

            sharedResource1.DirectlyConnectedSharedResources.Should().HaveCount(1);
            sharedResource1.DirectlyConnectedSharedResources.Should().Contain(sharedResource1);
            sharedResource2.DirectlyConnectedSharedResources.Should().HaveCount(1);
            sharedResource2.DirectlyConnectedSharedResources.Should().Contain(sharedResource2);
        }
        public void RemoveDirectConnectionTo_GivenTheResourceItself_ThrowsAnArgumentException()
        {
            // Arrange
            var sharedResource = new SharedResource();

            // Act
            sharedResource.RemoveDirectConnectionTo(sharedResource);
        }
        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));
        }