Ejemplo n.º 1
0
 protected SessionHostConfigurationBase(VmConfiguration vmConfiguration, MultiLogger logger, ISystemOperations systemOperations, SessionHostsStartInfo sessionHostsStartInfo)
 {
     _logger                = logger;
     VmConfiguration        = vmConfiguration;
     _systemOperations      = systemOperations;
     _sessionHostsStartInfo = sessionHostsStartInfo;
 }
        public void PublicPortMatchesContainerPort()
        {
            _vmConfiguration = new VmConfiguration(56001, TestVmId, new VmDirectories(_root), true);

            _sessionHostManager.Setup(x => x.LinuxContainersOnWindows).Returns(true);

            VmPathHelper.AdaptFolderPathsForLinuxContainersOnWindows(_vmConfiguration);

            _sessionHostsStartInfo.SessionHostType  = SessionHostType.Container;
            _sessionHostsStartInfo.PortMappingsList = new List <List <PortMapping> >()
            {
                new List <PortMapping>()
                {
                    new PortMapping()
                    {
                        GamePort = new Port()
                        {
                            Name     = "port",
                            Number   = 80,
                            Protocol = "TCP"
                        },
                        PublicPort = 1234,
                        NodePort   = 56001
                    }
                }
            };

            SessionHostContainerConfiguration sessionHostContainerConfiguration =
                new SessionHostContainerConfiguration(_vmConfiguration, _logger, _systemOperations, _dockerClient.Object, _sessionHostsStartInfo, shouldPublicPortMatchGamePort: true);

            IList <PortMapping> result = sessionHostContainerConfiguration.GetPortMappings(0);

            result[0].PublicPort.Should().Be(_sessionHostsStartInfo.PortMappingsList[0][0].PublicPort);
            result[0].GamePort.Number.Should().Be(result[0].PublicPort);
        }
Ejemplo n.º 3
0
        public static LegacyGameInfo FromSessionHostHeartbeatInfo(SessionHostHeartbeatInfo heartbeatInfo, string legacyTitleId)
        {
            LegacyGameInfo result = new LegacyGameInfo();

            result.NextBeatMilliseconds = heartbeatInfo.NextHeartbeatIntervalMs.ToString();
            result.Operation            = heartbeatInfo.Operation;
            if (heartbeatInfo.SessionConfig != null)
            {
                if (heartbeatInfo.SessionConfig.LegacyAllocationInfo != null)
                {
                    result.ClusterManifest = heartbeatInfo.SessionConfig.LegacyAllocationInfo.ClusterManifest;
                }
                else
                {
                    string sessionIdString = heartbeatInfo.SessionConfig.SessionId.ToString();
                    result.ClusterManifest["sessionId"]     = sessionIdString;
                    result.ClusterManifest["sessionUrl"]    = new Uri(SessionDirectoryBaseUrl, sessionIdString).AbsoluteUri;
                    result.ClusterManifest["sessionCookie"] = heartbeatInfo.SessionConfig?.SessionCookie;

                    if (ulong.TryParse(legacyTitleId, out ulong titleIdLong) &&
                        LegacyTitleHelper.LegacyTitleMappings.TryGetValue(VmConfiguration.GetGuidFromTitleId(titleIdLong), out LegacyTitleDetails titleDetails))
                    {
                        result.ClusterManifest["gameVariantId"] = titleDetails.VariantId.ToString();
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 4
0
        public SessionHostsStartInfo ToSessionHostsStartInfo()
        {
            // Clear mount path in process based, otherwise, agent will kick into back-compat mode and try to strip the
            // mount path from the start game command before running
            AssetDetail[] assetDetails = AssetDetails?.Select(x => new AssetDetail()
            {
                MountPath     = RunContainer ? x.MountPath : null,
                LocalFilePath = x.LocalFilePath
            }).ToArray();

            var startInfo = new SessionHostsStartInfo
            {
                AssignmentId      = $"{VmConfiguration.GetGuidFromTitleId(TitleIdUlong)}:{BuildId}:{Region}",
                SessionHostType   = RunContainer ? SessionHostType.Container : SessionHostType.Process,
                PublicIpV4Address = "127.0.0.1",
                FQDN = "localhost",
                HostConfigOverrides = GetHostConfig(),
                ImageDetails        = ContainerStartParameters.ImageDetails,
                AssetDetails        = assetDetails,
                StartGameCommand    = RunContainer ? ContainerStartParameters.StartGameCommand : ProcessStartParameters.StartGameCommand,
                PortMappingsList    = PortMappingsList
            };

            return(startInfo);
        }
Ejemplo n.º 5
0
 public SessionHostContainerConfiguration(
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     Interfaces.ISystemOperations systemOperations,
     IDockerClient dockerClient,
     SessionHostsStartInfo sessionHostsStartInfo) : base(vmConfiguration, logger, systemOperations, sessionHostsStartInfo)
 {
     _dockerClient = dockerClient;
 }
Ejemplo n.º 6
0
 protected BaseSessionHostRunner(
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     ISystemOperations systemOperations)
 {
     _logger           = logger;
     _vmConfiguration  = vmConfiguration;
     _systemOperations = systemOperations;
 }
Ejemplo n.º 7
0
 public ProcessRunner(
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     ISystemOperations systemOperations,
     IProcessWrapper processWrapper = null)
     : base(vmConfiguration, logger, systemOperations)
 {
     _processWrapper = processWrapper;
 }
Ejemplo n.º 8
0
 public ProcessRunner(
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     ISystemOperations systemOperations,
     IProcessWrapper processWrapper = null)
 {
     _logger           = logger;
     _vmConfiguration  = vmConfiguration;
     _systemOperations = systemOperations;
     _processWrapper   = processWrapper;
 }
Ejemplo n.º 9
0
 public DockerContainerEngine(
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     Core.Interfaces.ISystemOperations systemOperations,
     IDockerClient dockerClient         = null,
     bool shouldPublicPortMatchGamePort = false)
     : base(vmConfiguration, logger, systemOperations)
 {
     _dockerClient = dockerClient ?? CreateDockerClient();
     _shouldPublicPortMatchGamePort = shouldPublicPortMatchGamePort;
 }
Ejemplo n.º 10
0
 public MultiplayerServerManager(
     ISystemOperations systemOperations,
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     ISessionHostRunnerFactory sessionHostRunnerFactory)
 {
     _sessionHostRunnerFactory = sessionHostRunnerFactory;
     _systemOperations         = systemOperations;
     _logger          = logger;
     _vmConfiguration = vmConfiguration;
 }
Ejemplo n.º 11
0
 public DockerContainerEngine(
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     Core.Interfaces.ISystemOperations systemOperations,
     IDockerClient dockerClient = null)
 {
     // This can be moved to dependency injection pattern when unit tests are added for this class.
     _logger           = logger;
     _vmConfiguration  = vmConfiguration;
     _systemOperations = systemOperations;
     _dockerClient     = dockerClient ?? CreateDockerClient();
 }
 public SessionHostContainerConfiguration(
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     Interfaces.ISystemOperations systemOperations,
     IDockerClient dockerClient,
     SessionHostsStartInfo sessionHostsStartInfo,
     bool isRunningLinuxContainersOnWindows = false,
     bool shouldPublicPortMatchGamePort     = false) : base(vmConfiguration, logger, systemOperations, sessionHostsStartInfo)
 {
     _dockerClient = dockerClient;
     _isRunningLinuxContainersOnWindows = isRunningLinuxContainersOnWindows;
     _shouldPublicPortMatchGamePort     = shouldPublicPortMatchGamePort;
 }
Ejemplo n.º 13
0
 public MultiplayerServerManager(
     ISystemOperations systemOperations,
     VmConfiguration vmConfiguration,
     MultiLogger logger,
     ISessionHostRunnerFactory sessionHostRunnerFactory,
     BasicAssetExtractor basicAssetExtractor = null)
 {
     _sessionHostRunnerFactory = sessionHostRunnerFactory;
     _systemOperations         = systemOperations;
     _logger              = logger;
     _vmConfiguration     = vmConfiguration;
     _basicAssetExtractor = new BasicAssetExtractor(_systemOperations, _logger);
 }
 protected override string GetLogFolder(string logFolderId, VmConfiguration vmConfiguration)
 {
     // The VM host folder corresponding to the logFolderId gets mounted under this path for each container.
     // So the logFolderId itself isn't of much significance within the container.
     if (_isRunningLinuxContainersOnWindows)
     {
         return(vmConfiguration.VmDirectories.GameLogsRootFolderContainer + Path.AltDirectorySeparatorChar);
     }
     else
     {
         return(vmConfiguration.VmDirectories.GameLogsRootFolderContainer + Path.DirectorySeparatorChar);
     }
 }
Ejemplo n.º 15
0
        public void TestSetUnixOwnerDoesNothing()
        {
            List <string> expectedItemsToOwn = new List <string>()
            {
                _directoryPath,
                _subdirectoryPath,
                _directoryFilePath,
                _subdirectoryFilePath
            };
            VmConfiguration  config           = new VmConfiguration(56001, "vmid", new VmDirectories("root"), false);
            SystemOperations systemOperations = new SystemOperations(config, _logger, _mockFileSystemOperations.Object);

            systemOperations.SetUnixOwnerIfNeeded(_directoryPath, true);
            expectedItemsToOwn.ForEach(
                (item) => _mockFileSystemOperations.Verify(x => x.SetUnixOwner(It.IsAny <string>(), It.IsAny <string>()), Times.Never));
        }
        public void BeforeEachTest()
        {
            string AssignmentId = $"{TestTitleIdUlong}:{TestBuildId}:{TestRegion}";

            _logger             = new MultiLogger(NullLogger.Instance, new TelemetryClient(TelemetryConfiguration.CreateDefault()));
            _systemOperations   = new SystemOperations();
            _dockerClient       = new Mock <IDockerClient>();
            _sessionHostManager = new Mock <ISessionHostManager>();
            _vmConfiguration    = new VmConfiguration(56001, TestVmId, new VmDirectories(_VmDirectoryRoot), true);

            _sessionHostsStartInfo = new SessionHostsStartInfo();
            _sessionHostsStartInfo.AssignmentId      = AssignmentId;
            _sessionHostsStartInfo.PublicIpV4Address = TestPublicIpV4Address;

            _sessionHostManager.Setup(x => x.VmAgentSettings).Returns(new VmAgentSettings());
        }
Ejemplo n.º 17
0
 public SystemOperations(VmConfiguration vmConfiguration = null, MultiLogger logger = null, IFileSystemOperations fileSystemOperations = null)
 {
     _vmConfiguration      = vmConfiguration;
     _logger               = logger;
     _fileSystemOperations = fileSystemOperations ?? new FileSystemOperations();
 }
Ejemplo n.º 18
0
 public SessionHostProcessConfiguration(VmConfiguration vmConfiguration, MultiLogger logger, ISystemOperations systemOperations, SessionHostsStartInfo sessionHostsStartInfo)
     : base(vmConfiguration, logger, systemOperations, sessionHostsStartInfo)
 {
 }
 protected override string GetCertificateFolder(VmConfiguration vmConfiguration)
 {
     return(vmConfiguration.VmDirectories.CertificateRootFolderContainer);
 }
Ejemplo n.º 20
0
 protected override string GetGsdkConfigFilePath(string assignmentId, int instanceNumber)
 {
     return(Path.Combine(
                VmConfiguration.GetConfigRootFolderForSessionHost(instanceNumber),
                VmDirectories.GsdkConfigFilename));
 }
Ejemplo n.º 21
0
        public void Create(int instanceNumber, string sessionHostUniqueId, string agentEndpoint, VmConfiguration vmConfiguration, string logFolderId)
        {
            Dictionary <string, string> certThumbprints =
                _sessionHostsStartInfo.GameCertificates?.Where(x => x.Thumbprint != null).ToDictionary(x => x.Name, x => x.Thumbprint);
            IDictionary <string, string> portMappings = GetPortMappingsDict(instanceNumber);

            if (_sessionHostsStartInfo.IsLegacy)
            {
                CreateLegacyGSDKConfigFile(instanceNumber, sessionHostUniqueId, certThumbprints, portMappings);
            }

            // If the title is marked as legacy GSDK, we support a smooth transition when they decide to use new GSDK
            // A title can start using new GSDK even if it's a legacy title
            CreateNewGSDKConfigFile(instanceNumber, sessionHostUniqueId, certThumbprints, portMappings, agentEndpoint, vmConfiguration, logFolderId);
        }
Ejemplo n.º 22
0
 protected abstract string GetSharedContentFolder(VmConfiguration vmConfiguration);
Ejemplo n.º 23
0
 protected abstract string GetCertificateFolder(VmConfiguration vmConfiguration);
Ejemplo n.º 24
0
 protected abstract string GetLogFolder(string logFolderId, VmConfiguration vmConfiguration);
Ejemplo n.º 25
0
 protected string GetDumpFolder(string logFolderId, VmConfiguration vmConfiguration)
 {
     return(Path.Combine(GetLogFolder(logFolderId, vmConfiguration), VmDirectories.GameDumpsFolderName));
 }
Ejemplo n.º 26
0
        private void CreateNewGSDKConfigFile(int instanceNumber, string sessionHostUniqueId, Dictionary <string, string> certThumbprints, IDictionary <string, string> portMappings, string agentEndpoint, VmConfiguration vmConfiguration, string logFolderId)
        {
            string configFilePath = Path.Combine(VmConfiguration.GetConfigRootFolderForSessionHost(instanceNumber),
                                                 VmDirectories.GsdkConfigFilename);

            _logger.LogInformation($"Creating the configuration file at {configFilePath}");
            GsdkConfiguration gsdkConfig = new GsdkConfiguration
            {
                HeartbeatEndpoint = $"{agentEndpoint}:{VmConfiguration.ListeningPort}",
                SessionHostId     = sessionHostUniqueId,
                VmId                     = vmConfiguration.VmId,
                LogFolder                = GetLogFolder(logFolderId, vmConfiguration),
                CertificateFolder        = vmConfiguration.VmDirectories.CertificateRootFolderContainer,
                SharedContentFolder      = vmConfiguration.VmDirectories.GameSharedContentFolderContainer,
                GameCertificates         = certThumbprints,
                BuildMetadata            = _sessionHostsStartInfo.DeploymentMetadata,
                GamePorts                = portMappings,
                PublicIpV4Address        = _sessionHostsStartInfo.PublicIpV4Address,
                FullyQualifiedDomainName = _sessionHostsStartInfo.FQDN,
                ServerInstanceNumber     = instanceNumber,
                GameServerConnectionInfo = GetGameServerConnectionInfo(instanceNumber)
            };

            string outputJson = JsonConvert.SerializeObject(gsdkConfig, Formatting.Indented, CommonSettings.JsonSerializerSettings);

            // This will overwrite the file if it was already there (which would happen when restarting containers for the same assignment)
            _systemOperations.FileWriteAllText(configFilePath, outputJson);
        }
 protected override string GetSharedContentFolder(VmConfiguration vmConfiguration)
 {
     return(vmConfiguration.VmDirectories.GameSharedContentFolderContainer);
 }
Ejemplo n.º 28
0
 protected override string GetLogFolder(string logFolderId, VmConfiguration vmConfiguration)
 {
     return(Path.Combine(vmConfiguration.VmDirectories.GameLogsRootFolderVm, logFolderId));
 }
        public void TestCreateLegacyGSDKConfigFileWithSessionLinuxContainer()
        {
            _vmConfiguration = new VmConfiguration(56001, TestVmId, new VmDirectories(_root), true);

            _sessionHostManager.Setup(x => x.LinuxContainersOnWindows).Returns(true);

            VmPathHelper.AdaptFolderPathsForLinuxContainersOnWindows(_vmConfiguration);

            _sessionHostsStartInfo.SessionHostType  = SessionHostType.Container;
            _sessionHostsStartInfo.PortMappingsList = new List <List <PortMapping> >()
            {
                new List <PortMapping>()
                {
                    new PortMapping()
                    {
                        GamePort = new Port()
                        {
                            Name     = "port",
                            Number   = 80,
                            Protocol = "TCP"
                        },
                        PublicPort = 1234,
                        NodePort   = 56001
                    }
                }
            };

            List <PortMapping> mockPortMapping = _sessionHostsStartInfo.PortMappingsList[0];

            SessionHostContainerConfiguration sessionHostContainerConfiguration =
                new SessionHostContainerConfiguration(_vmConfiguration, _logger, _systemOperations, _dockerClient.Object, _sessionHostsStartInfo, true);

            sessionHostContainerConfiguration.Create(0, TestdDockerId, TestAgentIPaddress, _vmConfiguration, TestLogFolderId);

            string gsdkConfigFilePath = Path.Combine(_root, "Config", "SH0", "gsdkConfig.json");

            GsdkConfiguration gsdkConfigExpected = new GsdkConfiguration()
            {
                HeartbeatEndpoint = $"{TestAgentIPaddress}:56001",
                SessionHostId     = TestdDockerId,
                VmId                     = TestVmId,
                LogFolder                = "/data/GameLogs/",
                CertificateFolder        = "/data/GameCertificates",
                SharedContentFolder      = "/data/GameSharedContent",
                GamePorts                = mockPortMapping?.ToDictionary(x => x.GamePort.Name, x => x.GamePort.Number.ToString()),
                PublicIpV4Address        = TestPublicIpV4Address,
                GameServerConnectionInfo = new GameServerConnectionInfo
                {
                    PublicIpV4Adress       = TestPublicIpV4Address,
                    GamePortsConfiguration = new List <GamePort>()
                    {
                        new GamePort()
                        {
                            Name = mockPortMapping[0].GamePort.Name,
                            ServerListeningPort  = mockPortMapping[0].GamePort.Number,
                            ClientConnectionPort = mockPortMapping[0].PublicPort
                        }
                    }
                }
            };

            GsdkConfiguration gsdkConfig = JsonConvert.DeserializeObject <GsdkConfiguration>(File.ReadAllText(gsdkConfigFilePath));

            gsdkConfig.Should().BeEquivalentTo(gsdkConfigExpected);
        }
Ejemplo n.º 30
0
        public void BeforeEachTest()
        {
            _directoryPath     = Path.Combine(_root, _directoryName);
            _directoryInfo     = new DirectoryInfo(_directoryPath);
            _subdirectoryPath  = Path.Combine(_directoryPath, _subdirectoryName);
            _subDirectoryInfo  = new DirectoryInfo(_subdirectoryPath);
            _directoryFilePath = Path.Combine(_directoryPath, _directoryFileName);
            FileInfo directoryFileInfo = new FileInfo(_directoryFilePath);

            _subdirectoryFilePath = Path.Combine(_subdirectoryPath, _subdirectoryFileName);
            FileInfo subDirectoryFileInfo = new FileInfo(_subdirectoryFilePath);

            _defaultSourceFile = Path.Combine(_root, "Source");

            _mockFileSystemOperations = new Mock <IFileSystemOperations>();
            _vmConfiguration          = new VmConfiguration(56001, "vmid", new VmDirectories("root"), true);
            _logger           = new MultiLogger(NullLogger.Instance, new TelemetryClient(TelemetryConfiguration.CreateDefault()));
            _systemOperations = new SystemOperations(_vmConfiguration, _logger, _mockFileSystemOperations.Object);

            _mockFileSystemOperations.Setup(x => x.IsDirectory(_root)).Returns(true);
            _mockFileSystemOperations.Setup(x => x.IsDirectory(_subdirectoryPath)).Returns(true);
            _mockFileSystemOperations.Setup(x => x.IsDirectory(_directoryPath)).Returns(true);
            _mockFileSystemOperations.Setup(x => x.IsDirectory(_directoryFilePath)).Returns(false);
            _mockFileSystemOperations.Setup(x => x.IsDirectory(_subdirectoryFilePath)).Returns(false);

            _mockFileSystemOperations.Setup(x => x.GetFiles(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _root)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <FileInfo> toReturn = new List <FileInfo>();
                if (recursive)
                {
                    toReturn.Add(subDirectoryFileInfo);
                    toReturn.Add(directoryFileInfo);
                }
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetFiles(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _directoryPath)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <FileInfo> toReturn = new List <FileInfo>();
                toReturn.Add(directoryFileInfo);
                if (recursive)
                {
                    toReturn.Add(subDirectoryFileInfo);
                }
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetFiles(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _subdirectoryPath)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <FileInfo> toReturn = new List <FileInfo>();
                toReturn.Add(subDirectoryFileInfo);
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetDirectories(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _root)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <DirectoryInfo> toReturn = new List <DirectoryInfo>();
                toReturn.Add(_directoryInfo);
                if (recursive)
                {
                    toReturn.Add(_subDirectoryInfo);
                }
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetDirectories(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _directoryPath)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <DirectoryInfo> toReturn = new List <DirectoryInfo>();
                toReturn.Add(_subDirectoryInfo);
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetDirectories(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _subdirectoryPath)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <DirectoryInfo> toReturn = new List <DirectoryInfo>();
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetFileSystemInfos(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _root)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <FileSystemInfo> toReturn = new List <FileSystemInfo>();
                toReturn.Add(_directoryInfo);
                if (recursive)
                {
                    toReturn.Add(_subDirectoryInfo);
                    toReturn.Add(directoryFileInfo);
                    toReturn.Add(subDirectoryFileInfo);
                }
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetFileSystemInfos(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _directoryPath)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <FileSystemInfo> toReturn = new List <FileSystemInfo>();
                toReturn.Add(_subDirectoryInfo);
                toReturn.Add(directoryFileInfo);
                if (recursive)
                {
                    toReturn.Add(subDirectoryFileInfo);
                }
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.GetFileSystemInfos(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _subdirectoryPath)), It.IsAny <bool>()))
            .Returns <DirectoryInfo, bool>(
                (dirInfo, recursive) =>
            {
                List <FileSystemInfo> toReturn = new List <FileSystemInfo>();
                toReturn.Add(subDirectoryFileInfo);
                return(toReturn);
            });

            _mockFileSystemOperations.Setup(x => x.CreateSubdirectory(It.IsAny <DirectoryInfo>(), It.IsAny <string>()))
            .Returns <DirectoryInfo, string>((info, name) => new DirectoryInfo(Path.Combine(info.FullName, name)));

            DirectoryInfo nullDirInfo = null;
            DirectoryInfo rootDirInfo = new DirectoryInfo(_root);

            _mockFileSystemOperations.Setup(x => x.TryGetParentDirectory(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _root)), out nullDirInfo)).Returns(false);
            _mockFileSystemOperations.Setup(x => x.TryGetParentDirectory(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _directoryPath)), out rootDirInfo)).Returns(true);
            _mockFileSystemOperations.Setup(x => x.TryGetParentDirectory(It.Is <DirectoryInfo>((info) => IsFileSystemInfoEqual(info, _subdirectoryPath)), out _directoryInfo)).Returns(true);
            _mockFileSystemOperations.Setup(x => x.Exists(It.Is <FileSystemInfo>((info) => IsFileSystemInfoEqual((DirectoryInfo)info, _root)))).Returns(true);
            _mockFileSystemOperations.Setup(x => x.Exists(It.IsAny <FileSystemInfo>())).Returns(false);
        }