b33cb04e03d161e54e32d963f604ed70b4217103a7fcc3043c891f57301b75891dfd67e73162a71a83b43ef6628e869cb39fa1433e0aca4263a2d22aa21f19 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2012 Google Inc. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Unit tests for the common.py file."""
  6. import gyp.common
  7. import unittest
  8. import sys
  9. import os
  10. from unittest.mock import patch, MagicMock
  11. class TestTopologicallySorted(unittest.TestCase):
  12. def test_Valid(self):
  13. """Test that sorting works on a valid graph with one possible order."""
  14. graph = {
  15. "a": ["b", "c"],
  16. "b": [],
  17. "c": ["d"],
  18. "d": ["b"],
  19. }
  20. def GetEdge(node):
  21. return tuple(graph[node])
  22. assert gyp.common.TopologicallySorted(
  23. graph.keys(), GetEdge) == ["a", "c", "d", "b"]
  24. def test_Cycle(self):
  25. """Test that an exception is thrown on a cyclic graph."""
  26. graph = {
  27. "a": ["b"],
  28. "b": ["c"],
  29. "c": ["d"],
  30. "d": ["a"],
  31. }
  32. def GetEdge(node):
  33. return tuple(graph[node])
  34. self.assertRaises(
  35. gyp.common.CycleError, gyp.common.TopologicallySorted, graph.keys(), GetEdge
  36. )
  37. class TestGetFlavor(unittest.TestCase):
  38. """Test that gyp.common.GetFlavor works as intended"""
  39. original_platform = ""
  40. def setUp(self):
  41. self.original_platform = sys.platform
  42. def tearDown(self):
  43. sys.platform = self.original_platform
  44. def assertFlavor(self, expected, argument, param):
  45. sys.platform = argument
  46. assert expected == gyp.common.GetFlavor(param)
  47. def test_platform_default(self):
  48. self.assertFlavor("freebsd", "freebsd9", {})
  49. self.assertFlavor("freebsd", "freebsd10", {})
  50. self.assertFlavor("openbsd", "openbsd5", {})
  51. self.assertFlavor("solaris", "sunos5", {})
  52. self.assertFlavor("solaris", "sunos", {})
  53. self.assertFlavor("linux", "linux2", {})
  54. self.assertFlavor("linux", "linux3", {})
  55. self.assertFlavor("linux", "linux", {})
  56. def test_param(self):
  57. self.assertFlavor("foobar", "linux2", {"flavor": "foobar"})
  58. class MockCommunicate:
  59. def __init__(self, stdout):
  60. self.stdout = stdout
  61. def decode(self, encoding):
  62. return self.stdout
  63. @patch("os.close")
  64. @patch("os.unlink")
  65. @patch("tempfile.mkstemp")
  66. def test_GetCrossCompilerPredefines(self, mock_mkstemp, mock_unlink, mock_close):
  67. mock_close.return_value = None
  68. mock_unlink.return_value = None
  69. mock_mkstemp.return_value = (0, "temp.c")
  70. def mock_run(env, defines_stdout, expected_cmd):
  71. with patch("subprocess.run") as mock_run:
  72. mock_process = MagicMock()
  73. mock_process.returncode = 0
  74. mock_process.stdout = TestGetFlavor.MockCommunicate(defines_stdout)
  75. mock_run.return_value = mock_process
  76. expected_input = "temp.c" if sys.platform == "win32" else "/dev/null"
  77. with patch.dict(os.environ, env):
  78. defines = gyp.common.GetCrossCompilerPredefines()
  79. flavor = gyp.common.GetFlavor({})
  80. if env.get("CC_target"):
  81. mock_run.assert_called_with(
  82. [
  83. *expected_cmd,
  84. "-dM", "-E", "-x", "c", expected_input
  85. ],
  86. shell=sys.platform == "win32",
  87. capture_output=True, check=True)
  88. return [defines, flavor]
  89. [defines1, _] = mock_run({}, "", [])
  90. assert {} == defines1
  91. [defines2, flavor2] = mock_run(
  92. { "CC_target": "/opt/wasi-sdk/bin/clang" },
  93. "#define __wasm__ 1\n#define __wasi__ 1\n",
  94. ["/opt/wasi-sdk/bin/clang"]
  95. )
  96. assert { "__wasm__": "1", "__wasi__": "1" } == defines2
  97. assert flavor2 == "wasi"
  98. [defines3, flavor3] = mock_run(
  99. { "CC_target": "/opt/wasi-sdk/bin/clang --target=wasm32" },
  100. "#define __wasm__ 1\n",
  101. ["/opt/wasi-sdk/bin/clang", "--target=wasm32"]
  102. )
  103. assert { "__wasm__": "1" } == defines3
  104. assert flavor3 == "wasm"
  105. [defines4, flavor4] = mock_run(
  106. { "CC_target": "/emsdk/upstream/emscripten/emcc" },
  107. "#define __EMSCRIPTEN__ 1\n",
  108. ["/emsdk/upstream/emscripten/emcc"]
  109. )
  110. assert { "__EMSCRIPTEN__": "1" } == defines4
  111. assert flavor4 == "emscripten"
  112. # Test path which include white space
  113. [defines5, flavor5] = mock_run(
  114. {
  115. "CC_target": "\"/Users/Toyo Li/wasi-sdk/bin/clang\" -O3",
  116. "CFLAGS": "--target=wasm32-wasi-threads -pthread"
  117. },
  118. "#define __wasm__ 1\n#define __wasi__ 1\n#define _REENTRANT 1\n",
  119. [
  120. "/Users/Toyo Li/wasi-sdk/bin/clang",
  121. "-O3",
  122. "--target=wasm32-wasi-threads",
  123. "-pthread"
  124. ]
  125. )
  126. assert {
  127. "__wasm__": "1",
  128. "__wasi__": "1",
  129. "_REENTRANT": "1"
  130. } == defines5
  131. assert flavor5 == "wasi"
  132. original_sep = os.sep
  133. os.sep = "\\"
  134. [defines6, flavor6] = mock_run(
  135. { "CC_target": "\"C:\\Program Files\\wasi-sdk\\clang.exe\"" },
  136. "#define __wasm__ 1\n#define __wasi__ 1\n",
  137. ["C:/Program Files/wasi-sdk/clang.exe"]
  138. )
  139. os.sep = original_sep
  140. assert { "__wasm__": "1", "__wasi__": "1" } == defines6
  141. assert flavor6 == "wasi"
  142. if __name__ == "__main__":
  143. unittest.main()