Merge lp:~saviq/unity8/wrap-qmltestrunner into lp:unity8

Proposed by Michał Sawicz
Status: Work in progress
Proposed branch: lp:~saviq/unity8/wrap-qmltestrunner
Merge into: lp:unity8
Diff against target: 252 lines (+138/-17)
5 files modified
cmake/modules/QmlTest.cmake (+36/-14)
tests/CMakeLists.txt (+1/-1)
tests/plugins/LightDM/CMakeLists.txt (+0/-2)
tests/qmltests/CMakeLists.txt (+7/-0)
tools/qmltest_wrapper.py (+94/-0)
To merge this branch: bzr merge lp:~saviq/unity8/wrap-qmltestrunner
Reviewer Review Type Date Requested Status
Michael Zanetti Pending
Review via email: mp+217972@code.launchpad.net

Commit message

Enable autopkgtest for graphical QML tests.

To post a comment you must log in.
lp:~saviq/unity8/wrap-qmltestrunner updated
873. By Michał Sawicz

Fix timeout handling.

874. By Michał Sawicz

Disable lightdm dbus test for now.

Unmerged revisions

874. By Michał Sawicz

Disable lightdm dbus test for now.

873. By Michał Sawicz

Fix timeout handling.

872. By Michał Sawicz

Make wrapper executable.

871. By Michał Sawicz

Refactor how qmltestrunner and qmlscene paths are determined to allow overriding.

870. By Michał Sawicz

Introduce qmltest_wrapper.py to record a vido of failed qmltest output.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cmake/modules/QmlTest.cmake'
2--- cmake/modules/QmlTest.cmake 2014-04-29 15:17:21 +0000
3+++ cmake/modules/QmlTest.cmake 2014-05-01 21:22:23 +0000
4@@ -19,13 +19,31 @@
5 # qmltest_DEFAULT_IMPORT_PATHS
6 # qmltest_DEFAULT_PROPERTIES
7
8-find_program(qmltestrunner_exe qmltestrunner)
9-
10-if(NOT qmltestrunner_exe)
11- msg(FATAL_ERROR "Could not locate qmltestrunner.")
12-endif()
13-
14-set(qmlscene_exe ${CMAKE_BINARY_DIR}/tests/uqmlscene/uqmlscene)
15+if(NOT TARGET qmltestrunner)
16+ find_program(qmltestrunner_exe qmltestrunner)
17+
18+ if(NOT qmltestrunner_exe)
19+ msg(FATAL_ERROR "Could not locate qmltestrunner.")
20+ endif()
21+
22+ add_executable(qmltestrunner IMPORTED)
23+ set_target_properties(qmltestrunner PROPERTIES IMPORTED_LOCATION ${qmltestrunner_exe})
24+endif()
25+
26+if(NOT TARGET qmlscene)
27+ find_program(qmlscene_exe qmlscene)
28+
29+ if(NOT qmlscene_exe)
30+ msg(FATAL_ERROR "Could not locate qmlscene.")
31+ endif()
32+
33+ add_executable(qmlscene IMPORTED)
34+ set_target_properties(qmlscene PROPERTIES IMPORTED_LOCATION ${qmlscene_exe})
35+endif()
36+
37+if(NOT DEFINED ARTIFACTS_DIR)
38+ set(ARTIFACTS_DIR ${CMAKE_BINARY_DIR})
39+endif()
40
41 macro(add_manual_qml_test SUBPATH COMPONENT_NAME)
42 set(options NO_ADD_TEST NO_TARGETS)
43@@ -33,6 +51,8 @@
44
45 cmake_parse_arguments(qmltest "${options}" "" "${multi_value_keywords}" ${ARGN})
46
47+ get_target_property(qmlscene_executable qmlscene LOCATION)
48+
49 set(qmlscene_TARGET try${COMPONENT_NAME})
50 set(qmltest_FILE ${SUBPATH}/tst_${COMPONENT_NAME})
51
52@@ -51,7 +71,7 @@
53
54 set(qmlscene_command
55 env ${qmltest_ENVIRONMENT}
56- ${qmlscene_exe} ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
57+ ${qmlscene_executable} ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
58 ${qmlscene_imports}
59 )
60 add_custom_target(${qmlscene_TARGET} ${qmlscene_command})
61@@ -76,6 +96,8 @@
62 set(qmltest_xvfb_TARGET xvfbtest${COMPONENT_NAME})
63 set(qmltest_FILE ${SUBPATH}/tst_${COMPONENT_NAME})
64
65+ get_target_property(qmltestrunner_executable qmltestrunner LOCATION)
66+
67 set(qmltestrunner_imports "")
68 if(NOT "${qmltest_IMPORT_PATHS}" STREQUAL "")
69 foreach(IMPORT_PATH ${qmltest_IMPORT_PATHS})
70@@ -104,10 +126,10 @@
71
72 set(qmltest_command
73 env ${qmltest_ENVIRONMENT}
74- ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
75+ ${qmltestrunner_executable} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
76 ${qmltestrunner_imports}
77 ${ITERATIONS_STRING}
78- -o ${CMAKE_BINARY_DIR}/${qmltest_TARGET}.xml,xunitxml
79+ -o ${ARTIFACTS_DIR}/${qmltest_TARGET}.xml,xunitxml
80 -o -,txt
81 ${function_ARGS}
82 )
83@@ -119,9 +141,9 @@
84 set(qmltest_xvfb_command
85 env ${qmltest_ENVIRONMENT} ${LD_PRELOAD_PATH}
86 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
87- ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
88+ ${qmltestrunner_executable} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
89 ${qmltestrunner_imports}
90- -o ${CMAKE_BINARY_DIR}/${qmltest_TARGET}.xml,xunitxml
91+ -o ${ARTIFACTS_DIR}/${qmltest_TARGET}.xml,xunitxml
92 -o -,txt
93 ${function_ARGS}
94 )
95@@ -135,7 +157,7 @@
96 set(testCommand
97 LD_LIBRARY_PATH=${LD_PATH}
98 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
99- -o ${CMAKE_BINARY_DIR}/${CLASSNAME}Test.xml,xunitxml
100+ -o ${ARTIFACTS_DIR}/${CLASSNAME}Test.xml,xunitxml
101 -o -,txt)
102
103 add_qmltest_target(test${CLASS_NAME} "${testCommand}" FALSE TRUE)
104@@ -151,7 +173,7 @@
105 LD_LIBRARY_PATH=${LD_PATH}
106 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
107 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
108- -o ${CMAKE_BINARY_DIR}/${CLASS_NAME}Test.xml,xunitxml
109+ -o ${ARTIFACTS_DIR}/${CLASS_NAME}Test.xml,xunitxml
110 -o -,txt)
111
112 add_qmltest_target(xvfbtest${CLASS_NAME} "${xvfbtestCommand}" FALSE TRUE)
113
114=== modified file 'tests/CMakeLists.txt'
115--- tests/CMakeLists.txt 2014-03-18 12:46:07 +0000
116+++ tests/CMakeLists.txt 2014-05-01 21:22:23 +0000
117@@ -7,9 +7,9 @@
118 add_custom_target(qmltests)
119 add_dependencies(qmltests qmlunittests qmluitests)
120
121+add_subdirectory(uqmlscene)
122 add_subdirectory(qmltests)
123 add_subdirectory(mocks)
124 add_subdirectory(whitespace)
125 add_subdirectory(plugins)
126 add_subdirectory(utils)
127-add_subdirectory(uqmlscene)
128
129=== modified file 'tests/plugins/LightDM/CMakeLists.txt'
130--- tests/plugins/LightDM/CMakeLists.txt 2014-01-14 21:01:28 +0000
131+++ tests/plugins/LightDM/CMakeLists.txt 2014-05-01 21:22:23 +0000
132@@ -21,5 +21,3 @@
133
134 add_custom_target(testLightDMDBus dbus-launch env QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full ${CMAKE_CURRENT_BINARY_DIR}/test-lightdm-dbus)
135 add_dependencies(testLightDMDBus test-lightdm-dbus)
136-
137-add_dependencies(qmluitests testLightDMDBus)
138
139=== modified file 'tests/qmltests/CMakeLists.txt'
140--- tests/qmltests/CMakeLists.txt 2014-04-22 08:51:33 +0000
141+++ tests/qmltests/CMakeLists.txt 2014-05-01 21:22:23 +0000
142@@ -1,3 +1,10 @@
143+add_executable(qmlscene ALIAS uqmlscene)
144+
145+if(DEFINED QMLTESTRUNNER_EXECUTABLE)
146+ add_executable(qmltestrunner IMPORTED)
147+ set_target_properties(qmltestrunner PROPERTIES IMPORTED_LOCATION "${QMLTESTRUNNER_EXECUTABLE}")
148+endif()
149+
150 # add_qml_test macro
151 include(QmlTest)
152
153
154=== added file 'tools/qmltest_wrapper.py'
155--- tools/qmltest_wrapper.py 1970-01-01 00:00:00 +0000
156+++ tools/qmltest_wrapper.py 2014-05-01 21:22:23 +0000
157@@ -0,0 +1,94 @@
158+#!/usr/bin/python3
159+
160+import os
161+import sys
162+import subprocess
163+import shutil
164+import tempfile
165+
166+ENCODE_LIMIT=120
167+GRACE_TIME=5
168+
169+recordmydesktop_args = [
170+ "recordmydesktop",
171+ "--quick-subsampling",
172+ "--fps=60",
173+ "--no-sound",
174+ "--overwrite",
175+]
176+
177+if __name__ == "__main__":
178+ """
179+ This script wraps qmltestrunner, recording the screen as the test runs
180+ with recordmydesktop. Maximum encoding time is {0}s, the process is
181+ interrupted after that time. If the test succeeds, recording is aborted
182+ and no video produced.
183+ Output video file name is derived from the first logger option in the
184+ "-o /file/path,format" format with *absolute* paths, the file is saved
185+ next to the test log file with the extension ".ogv", falling back to
186+ "qmltest.ogv" in the current directory.
187+ """
188+
189+ argv = sys.argv.copy()
190+ argv[0] = "qmltestrunner"
191+
192+ outfile = os.path.join(os.curdir, "qmltest.ogv")
193+ returncode = 0
194+
195+ try:
196+ for logger in (argv[k+1] for k, v in enumerate(argv) if v == "-o"):
197+ log = logger.split(',')[0]
198+ if os.path.isabs(log):
199+ outfile = "{0}.ogv".format(os.path.splitext(log)[0])
200+ break
201+ except IndexError as err:
202+ raise ValueError("Missing logger definition:\n{0}".format(argv)) from err
203+
204+
205+ with tempfile.TemporaryDirectory() as tmpdir:
206+ # create a temporary file and close it to let recordmydesktop overwrite it
207+ tmpfd, tmpname = tempfile.mkstemp(dir=tmpdir, suffix=".ogv")
208+ os.close(tmpfd)
209+ recordmydesktop_args.extend(["--workdir={0}".format(tmpdir),
210+ "--output={0}".format(tmpname)])
211+
212+ with subprocess.Popen(recordmydesktop_args, stdout=subprocess.PIPE,
213+ stderr=subprocess.PIPE, universal_newlines=True) as recorder:
214+ try:
215+ subprocess.check_call(argv)
216+ except subprocess.CalledProcessError as err:
217+ # store the exit code to return
218+ returncode = err.returncode
219+
220+ # stop recording, give 60 seconds to encode
221+ recorder.terminate()
222+ try:
223+ recorder.wait(ENCODE_LIMIT)
224+ except subprocess.TimeoutExpired:
225+ print("===== Recorder took too long to encode, recording will be incomplete =====")
226+ recorder.terminate()
227+ try:
228+ recorder.wait(GRACE_TIME)
229+ except subprocess.TimeoutExpired:
230+ pass
231+ if recorder.returncode is 0:
232+ # only store the file if recorder exited cleanly
233+ shutil.move(tmpname, outfile)
234+ else:
235+ # abort the recording, test passed
236+ recorder.send_signal(subprocess.signal.SIGABRT)
237+ try:
238+ recorder.wait(GRACE_TIME)
239+ except subprocess.TimeoutExpired:
240+ pass
241+ finally:
242+ recorder.poll()
243+ # kill the recording if still running
244+ if recorder.returncode is None:
245+ recorder.kill()
246+ print("===== Had to kill recorder =====")
247+ elif recorder.returncode is not 0:
248+ # only print recorder output if terminated successfully
249+ print("===== Recorder error =====\nSTDOUT:\n{0}\n\nSTDERR:\n{1}".format(*recorder.communicate()))
250+
251+ sys.exit(returncode)
252\ No newline at end of file

Subscribers

People subscribed via source and target branches