test_weston.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import os
  2. import time
  3. import infra.basetest
  4. class TestWeston(infra.basetest.BRTest):
  5. config = \
  6. """
  7. BR2_aarch64=y
  8. BR2_TOOLCHAIN_EXTERNAL=y
  9. BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
  10. BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
  11. BR2_ROOTFS_OVERLAY="{}"
  12. BR2_PER_PACKAGE_DIRECTORIES=y
  13. BR2_LINUX_KERNEL=y
  14. BR2_LINUX_KERNEL_CUSTOM_VERSION=y
  15. BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.44"
  16. BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
  17. BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
  18. BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{}"
  19. BR2_PACKAGE_LIBDRM=y
  20. BR2_PACKAGE_MESA3D=y
  21. BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SWRAST=y
  22. BR2_PACKAGE_MESA3D_LLVM=y
  23. BR2_PACKAGE_MESA3D_OPENGL_EGL=y
  24. BR2_PACKAGE_MESA3D_OPENGL_ES=y
  25. BR2_PACKAGE_WAYLAND_UTILS=y
  26. BR2_PACKAGE_WESTON=y
  27. BR2_PACKAGE_WESTON_SIMPLE_CLIENTS=y
  28. BR2_TARGET_ROOTFS_CPIO=y
  29. BR2_TARGET_ROOTFS_CPIO_GZIP=y
  30. # BR2_TARGET_ROOTFS_TAR is not set
  31. """.format(
  32. infra.filepath("tests/package/test_weston/overlay"),
  33. infra.filepath("tests/package/test_weston/linux-vkms.fragment")
  34. )
  35. def gen_read_disp_crcs_cmd(self, count=1):
  36. # DRM CRCs are exposed through a sysfs pseudo file, one measure
  37. # per line. The first column is the frame number, the second
  38. # column is the CRC measure. We use "head" to get the needed
  39. # CRC count.
  40. disp_crc_path = "/sys/kernel/debug/dri/0/crtc-0/crc/data"
  41. cmd = f"head -{count} {disp_crc_path}"
  42. # The DRM CRC sysfs pseudo file lines are terminated by '\n'
  43. # and '\0'. We remove the '\0' to have a text-only output.
  44. cmd += " | tr -d '\\000'"
  45. # Finally, we drop the frame counter, and keep only the second
  46. # column (CRC values)
  47. cmd += " | cut -f 2 -d ' '"
  48. return cmd
  49. def gen_count_unique_disp_crcs_cmd(self, count=10):
  50. # We get the command generating one CRC per line...
  51. cmd = self.gen_read_disp_crcs_cmd(count)
  52. # ...then count the number of unique values
  53. cmd += " | uniq | wc -l"
  54. return cmd
  55. def start_weston(self):
  56. self.assertRunOk("export XDG_RUNTIME_DIR=/tmp")
  57. cmd = "weston"
  58. cmd += " --config=/etc/weston.ini"
  59. cmd += " --continue-without-input"
  60. cmd += " --log=/tmp/weston.log"
  61. cmd += " &> /dev/null &"
  62. self.assertRunOk(cmd)
  63. self.assertRunOk("export WAYLAND_DISPLAY=wayland-1")
  64. def wait_for_weston(self):
  65. # We wait for the wayland socket to appear...
  66. wayland_socket = "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}"
  67. cmd = f"while [ ! -e \"{wayland_socket}\" ] ; do sleep 1 ; done"
  68. self.assertRunOk(cmd, timeout=10)
  69. time.sleep(4)
  70. def stop_weston(self):
  71. cmd = "killall weston && sleep 3"
  72. self.assertRunOk(cmd)
  73. def test_run(self):
  74. img = os.path.join(self.builddir, "images", "rootfs.cpio.gz")
  75. kern = os.path.join(self.builddir, "images", "Image")
  76. self.emulator.boot(arch="aarch64",
  77. kernel=kern,
  78. kernel_cmdline=["console=ttyAMA0"],
  79. options=["-M", "virt",
  80. "-cpu", "cortex-a57",
  81. "-smp", "4",
  82. "-m", "256M",
  83. "-initrd", img])
  84. self.emulator.login()
  85. # Check the weston binary can execute
  86. self.assertRunOk("weston --version")
  87. self.start_weston()
  88. self.wait_for_weston()
  89. # Check a simple info client can communicate with the compositor
  90. self.assertRunOk("wayland-info", timeout=10)
  91. # This test will use the Kernel VKMS DRM Display CRC support,
  92. # which is exposed in debugfs. See:
  93. # https://docs.kernel.org/gpu/drm-uapi.html#display-crc-support
  94. self.assertRunOk("mount -t debugfs none /sys/kernel/debug/")
  95. # We get 10 consecutive DRM frame CRCs and count how many
  96. # unique CRCs we have. Since weston is supposed to run idle,
  97. # we should have 10 times the same display CRC.
  98. cmd = self.gen_count_unique_disp_crcs_cmd()
  99. output, exit_code = self.emulator.run(cmd)
  100. self.assertEqual(exit_code, 0)
  101. self.assertEqual(int(output[0]), 1)
  102. # We save the CRC value of an empty weston desktop for
  103. # later...
  104. cmd = self.gen_read_disp_crcs_cmd()
  105. output, exit_code = self.emulator.run(cmd)
  106. self.assertEqual(exit_code, 0)
  107. weston_desktop_crc = int(output[0], 16)
  108. # We start the weston-simple-egl in background... Every
  109. # rendered frame is supposed to be different (as the triangle
  110. # animation is derived from the system time). Since all the
  111. # rendering (client application and compositor) is in
  112. # software, we sleep a bit to let those program to settle.
  113. self.assertRunOk("weston-simple-egl >/dev/null 2>&1 &")
  114. time.sleep(8)
  115. # Since the weston-simple-egl client is supposed to run and
  116. # display something, we are now supposed to measure a
  117. # different display CRC than the one we measured when the
  118. # desktop was empty.
  119. cmd = self.gen_read_disp_crcs_cmd()
  120. output, exit_code = self.emulator.run(cmd)
  121. self.assertEqual(exit_code, 0)
  122. self.assertNotEqual(int(output[0], 16), weston_desktop_crc)
  123. # While weston-simple-egl is running, we check the VKMS DRM
  124. # CRCs are now changing. We get many CRCs, one per display
  125. # driver refresh (at ~60Hz). Since all the rendering is in
  126. # software, we can expect a slow frame rate. In 300 captured
  127. # CRCs (5s), we expect at least 5 different values (i.e. 1 fps).
  128. # This guarantees the rendering pipeline is working, while we
  129. # remain very permissive to slow emulation situations.
  130. # Increase timeout, as the command is expected to run about 5s,
  131. # which is the default timeout.
  132. cmd = self.gen_count_unique_disp_crcs_cmd(300)
  133. output, exit_code = self.emulator.run(cmd, timeout=10)
  134. self.assertEqual(exit_code, 0)
  135. self.assertGreaterEqual(int(output[0]), 5)
  136. # We stop weston-simple-egl, and sleep a bit to let Weston do
  137. # its cleanup and desktop repaint refresh...
  138. self.assertRunOk("killall weston-simple-egl")
  139. time.sleep(4)
  140. # After we stopped the application, we should have the initial
  141. # weston desktop background. The CRC we measure now should be
  142. # the same as the one we saved earlier.
  143. cmd = self.gen_read_disp_crcs_cmd()
  144. output, exit_code = self.emulator.run(cmd)
  145. self.assertEqual(exit_code, 0)
  146. self.assertEqual(int(output[0], 16), weston_desktop_crc)
  147. self.stop_weston()
  148. # Now weston is supposed to be stopped,
  149. # a simple client is expected to fail.
  150. _, exit_code = self.emulator.run("wayland-info")
  151. self.assertNotEqual(exit_code, 0)