test_launcher_win.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. """
  2. Copyright (c) Contributors to the Open 3D Engine Project.
  3. For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. SPDX-License-Identifier: Apache-2.0 OR MIT
  5. Unit Tests for windows launcher-wrappers: all are sanity code-path tests, since no interprocess actions should be taken
  6. """
  7. import os
  8. import unittest.mock as mock
  9. import pytest
  10. import ly_test_tools.launchers
  11. import ly_test_tools.launchers.exceptions
  12. pytestmark = pytest.mark.SUITE_smoke
  13. class TestWinLauncher(object):
  14. def test_BinaryPath_DummyPath_AddPathToExe(self):
  15. dummy_path = "dummy_workspace_path"
  16. dummy_project = "dummy_project"
  17. mock_workspace = mock.MagicMock()
  18. mock_workspace.paths.build_directory.return_value = dummy_path
  19. mock_workspace.project = dummy_project
  20. launcher = ly_test_tools.launchers.WinLauncher(mock_workspace, ["some_args"])
  21. under_test = launcher.binary_path()
  22. expected = os.path.join(f'{dummy_path}',
  23. f'{dummy_project}.GameLauncher.exe')
  24. assert expected == under_test
  25. @mock.patch('ly_test_tools.launchers.WinLauncher.binary_path', mock.MagicMock)
  26. @mock.patch('subprocess.Popen')
  27. def test_Launch_DummyArgs_ArgsPassedToPopen(self, mock_subprocess):
  28. dummy_args = ["some_args"]
  29. launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), dummy_args)
  30. launcher.launch()
  31. mock_subprocess.assert_called_once()
  32. name, args, kwargs = mock_subprocess.mock_calls[0]
  33. unpacked_args = args[0] # args is a list inside a tuple
  34. assert len(dummy_args) > 0, "accidentally removed dummy_args"
  35. for expected_arg in dummy_args:
  36. assert expected_arg in unpacked_args
  37. @mock.patch('ly_test_tools.launchers.WinLauncher.is_alive')
  38. def test_Kill_MockAliveFalse_SilentSuccess(self, mock_alive):
  39. mock_alive.return_value = False
  40. mock_proc = mock.MagicMock()
  41. launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  42. launcher._proc = mock_proc
  43. launcher.stop()
  44. mock_proc.kill.assert_called_once()
  45. mock_alive.assert_called()
  46. def test_IsAlive_NoProc_False(self):
  47. launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  48. under_test = launcher.is_alive()
  49. assert under_test is False
  50. def test_IsAlive_MockProcNotReturned_True(self):
  51. mock_proc = mock.MagicMock()
  52. mock_proc.poll.return_value = None
  53. launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  54. launcher._proc = mock_proc
  55. under_test = launcher.is_alive()
  56. assert under_test is True
  57. def test_IsAlive_MockProcHasReturned_False(self):
  58. mock_proc = mock.MagicMock()
  59. mock_proc.poll.return_value = 0
  60. launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  61. launcher._proc = mock_proc
  62. under_test = launcher.is_alive()
  63. assert under_test is False
  64. def test_GetPid_HasProcess_ReturnsPid(self):
  65. mock_pid = 11111
  66. mock_launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  67. mock_proc = mock.MagicMock()
  68. mock_proc.pid = mock_pid
  69. mock_launcher._proc = mock_proc
  70. assert mock_launcher.get_pid() == mock_pid
  71. def test_GetPid_HasNoProcess_ReturnsNone(self):
  72. mock_launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  73. mock_proc = None
  74. mock_launcher._proc = mock_proc
  75. assert mock_launcher.get_pid() is None
  76. def test_GetReturnCode_HasProcess_CallsPoll(self):
  77. mock_launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  78. mock_proc = mock.MagicMock()
  79. mock_launcher._proc = mock_proc
  80. mock_launcher.get_returncode()
  81. mock_proc.poll.assert_called_once()
  82. @mock.patch('subprocess.Popen.poll')
  83. def test_GetReturnCode_HasNoProcess_ReturnsNone(self, under_test):
  84. mock_launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  85. mock_launcher._proc = None
  86. mock_launcher.get_returncode()
  87. under_test.assert_not_called()
  88. @mock.patch('ly_test_tools.launchers.WinLauncher.get_returncode')
  89. def test_CheckReturnCode_Called_CallsGetReturncode(self, under_test):
  90. mock_launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  91. under_test.return_value = 0
  92. mock_launcher.check_returncode()
  93. under_test.assert_called()
  94. @mock.patch('ly_test_tools.launchers.WinLauncher.get_returncode')
  95. def test_CheckReturnCode_ReturnCodeIsZero_ReturnsNone(self, mock_get_returncode):
  96. mock_launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  97. mock_get_returncode.return_value = 0
  98. under_test = mock_launcher.check_returncode()
  99. assert under_test is None
  100. @mock.patch('ly_test_tools.launchers.WinLauncher.get_returncode')
  101. def test_CheckReturnCode_ReturnCodeIsNonZero_RaisesError(self, mock_get_returncode):
  102. mock_launcher = ly_test_tools.launchers.WinLauncher(mock.MagicMock(), ["dummy"])
  103. mock_get_returncode.return_value = 1
  104. with pytest.raises(ly_test_tools.launchers.exceptions.CrashError):
  105. mock_launcher.check_returncode()
  106. class TestWinEditor(object):
  107. def test_BinaryPath_DummyPath_AddPathToExe(self):
  108. dummy_path = "dummy_workspace_path"
  109. mock_workspace = mock.MagicMock()
  110. mock_workspace.paths.build_directory.return_value = dummy_path
  111. launcher = ly_test_tools.launchers.WinEditor(mock_workspace, ["some_args"])
  112. under_test = launcher.binary_path()
  113. assert "Editor.exe" in under_test
  114. assert dummy_path in under_test, "workspace path unexpectedly missing"
  115. class TestDedicatedWinLauncher(object):
  116. def test_BinaryPath_DummyPath_AddPathToExe(self):
  117. dummy_path = "dummy_workspace_path"
  118. dummy_project = "dummy_project"
  119. mock_workspace = mock.MagicMock()
  120. mock_workspace.paths.build_directory.return_value = dummy_path
  121. mock_workspace.project = dummy_project
  122. launcher = ly_test_tools.launchers.DedicatedWinLauncher(mock_workspace, ["some_args"])
  123. under_test = launcher.binary_path()
  124. expected = os.path.join(f'{dummy_path}',
  125. f'{dummy_project}.ServerLauncher.exe')
  126. assert under_test == expected
  127. def test_Build_MockWorkspace_DedicatedBuildRequested(self):
  128. mock_workspace = mock.MagicMock()
  129. launcher = ly_test_tools.launchers.DedicatedWinLauncher(mock_workspace, ["some_args"])
  130. launcher.workspace.build(dedicated=True)
  131. mock_workspace.build.assert_called_once_with(dedicated=True)
  132. class TestWinAtomToolsLauncher(object):
  133. @mock.patch('ly_test_tools.launchers.platforms.win.launcher.os.path.isfile')
  134. def test_BinaryPath_DummyPathExeExists_AddPathToExe(self, mock_os_path_isfile):
  135. dummy_path = "dummy_workspace_path"
  136. dummy_app_file_name = 'SomeCustomLauncher'
  137. mock_os_path_isfile.return_value = True
  138. mock_workspace = mock.MagicMock()
  139. mock_workspace.paths.build_directory.return_value = dummy_path
  140. launcher = ly_test_tools.launchers.WinAtomToolsLauncher(mock_workspace, dummy_app_file_name, ["some_args"])
  141. under_test = launcher.binary_path()
  142. assert dummy_app_file_name in under_test, f"executable named {dummy_app_file_name} not found"
  143. assert dummy_path in under_test, "workspace path unexpectedly missing "
  144. @mock.patch('ly_test_tools.launchers.platforms.win.launcher.os.path.isfile')
  145. def test_BinaryPath_DummyPathExeDoesNotExist_RaiseSetupError(self, mock_os_path_isfile):
  146. dummy_path = "dummy_workspace_path"
  147. dummy_app_file_name = 'SomeCustomLauncher'
  148. mock_os_path_isfile.return_value = False
  149. mock_workspace = mock.MagicMock()
  150. mock_workspace.paths.build_directory.return_value = dummy_path
  151. under_test = ly_test_tools.launchers.WinAtomToolsLauncher(mock_workspace, dummy_app_file_name, ["some_args"])
  152. with pytest.raises(ly_test_tools.launchers.exceptions.SetupError):
  153. under_test.binary_path()