xvfb_unittest.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/env python
  2. # Copyright (c) 2019 The Chromium Authors. 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 xvfb.py functionality.
  6. Each unit test is launching xvfb_test_script.py
  7. through xvfb.py as a subprocess, then tests its expected output.
  8. """
  9. import os
  10. import signal
  11. import subprocess
  12. import sys
  13. import time
  14. import unittest
  15. # pylint: disable=super-with-arguments
  16. TEST_FILE = __file__.replace('.pyc', '.py')
  17. XVFB = TEST_FILE.replace('_unittest', '')
  18. XVFB_TEST_SCRIPT = TEST_FILE.replace('_unittest', '_test_script')
  19. def launch_process(args):
  20. """Launches a sub process to run through xvfb.py."""
  21. return subprocess.Popen(
  22. [XVFB, XVFB_TEST_SCRIPT] + args, stdout=subprocess.PIPE,
  23. stderr=subprocess.STDOUT, env=os.environ.copy())
  24. # pylint: disable=inconsistent-return-statements
  25. def read_subprocess_message(proc, starts_with):
  26. """Finds the value after first line prefix condition."""
  27. for line in proc.stdout.read().decode('utf-8').splitlines(True):
  28. if str(line).startswith(starts_with):
  29. return line.rstrip().replace(starts_with, '')
  30. # pylint: enable=inconsistent-return-statements
  31. def send_signal(proc, sig, sleep_time=0.3):
  32. """Sends a signal to subprocess."""
  33. time.sleep(sleep_time) # gives process time to launch.
  34. os.kill(proc.pid, sig)
  35. proc.wait()
  36. class XvfbLinuxTest(unittest.TestCase):
  37. def setUp(self):
  38. super(XvfbLinuxTest, self).setUp()
  39. if not sys.platform.startswith('linux'):
  40. self.skipTest('linux only test')
  41. self._procs = []
  42. def test_no_xvfb_display(self):
  43. self._procs.append(launch_process(['--no-xvfb']))
  44. self._procs[0].wait()
  45. display = read_subprocess_message(self._procs[0], 'Display :')
  46. self.assertEqual(display, os.environ.get('DISPLAY', 'None'))
  47. def test_xvfb_display(self):
  48. self._procs.append(launch_process([]))
  49. self._procs[0].wait()
  50. display = read_subprocess_message(self._procs[0], 'Display :')
  51. self.assertIsNotNone(display) # Openbox likely failed to open DISPLAY
  52. self.assertNotEqual(display, os.environ.get('DISPLAY', 'None'))
  53. def test_no_xvfb_flag(self):
  54. self._procs.append(launch_process(['--no-xvfb']))
  55. self._procs[0].wait()
  56. def test_xvfb_flag(self):
  57. self._procs.append(launch_process([]))
  58. self._procs[0].wait()
  59. def test_xvfb_race_condition(self):
  60. self._procs = [launch_process([]) for _ in range(15)]
  61. for proc in self._procs:
  62. proc.wait()
  63. display_list = [read_subprocess_message(p, 'Display :')
  64. for p in self._procs]
  65. for display in display_list:
  66. self.assertIsNotNone(display) # Openbox likely failed to open DISPLAY
  67. self.assertNotEqual(display, os.environ.get('DISPLAY', 'None'))
  68. def tearDown(self):
  69. super(XvfbLinuxTest, self).tearDown()
  70. for proc in self._procs:
  71. if proc.stdout:
  72. proc.stdout.close()
  73. class XvfbTest(unittest.TestCase):
  74. def setUp(self):
  75. super(XvfbTest, self).setUp()
  76. if sys.platform == 'win32':
  77. self.skipTest('non-win32 test')
  78. self._proc = None
  79. def test_send_sigint(self):
  80. self._proc = launch_process(['--sleep'])
  81. send_signal(self._proc, signal.SIGINT, 1)
  82. sig = read_subprocess_message(self._proc, 'Signal :')
  83. self.assertIsNotNone(sig) # OpenBox likely failed to start
  84. self.assertEqual(int(sig), int(signal.SIGINT))
  85. def test_send_sigterm(self):
  86. self._proc = launch_process(['--sleep'])
  87. send_signal(self._proc, signal.SIGTERM, 1)
  88. sig = read_subprocess_message(self._proc, 'Signal :')
  89. self.assertIsNotNone(sig) # OpenBox likely failed to start
  90. self.assertEqual(int(sig), int(signal.SIGTERM))
  91. def tearDown(self):
  92. super(XvfbTest, self).tearDown()
  93. if self._proc.stdout:
  94. self._proc.stdout.close()
  95. if __name__ == '__main__':
  96. unittest.main()