diff options
| -rwxr-xr-x | bin/camera_test | 143 | ||||
| -rw-r--r-- | units/camera/jobs.pxu | 58 | ||||
| -rw-r--r-- | units/camera/packaging.pxu | 3 | ||||
| -rw-r--r-- | units/camera/test-plan.pxu | 35 | ||||
| -rw-r--r-- | units/led/jobs.pxu | 15 | ||||
| -rw-r--r-- | units/led/test-plan.pxu | 8 | ||||
| -rw-r--r-- | units/miscellanea/jobs.pxu | 2 | ||||
| -rw-r--r-- | units/suspend/suspend.pxu | 65 |
8 files changed, 145 insertions, 184 deletions
diff --git a/bin/camera_test b/bin/camera_test index 6128c0f..4ef90d7 100755 --- a/bin/camera_test +++ b/bin/camera_test @@ -2,7 +2,10 @@ # # This file is part of Checkbox. # -# Copyright 2008-2012 Canonical Ltd. +# Copyright 2008-2018 Canonical Ltd. +# Written by: +# Matt Fischer <matt@mattfischer.com> +# Sylvain Pineau <sylvain.pineau@canonical.com> # # The v4l2 ioctl code comes from the Python bindings for the v4l2 # userspace api (http://pypi.python.org/pypi/v4l2): @@ -15,7 +18,6 @@ # Checkbox is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3, # as published by the Free Software Foundation. - # # Checkbox is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -36,9 +38,7 @@ import os import re import struct import sys -import time -from gi.repository import GObject from glob import glob from subprocess import check_call, CalledProcessError, STDOUT from tempfile import NamedTemporaryFile @@ -151,9 +151,11 @@ class v4l2_fmtdesc(ctypes.Structure): ('reserved', ctypes.c_uint32 * 4), ] + V4L2_FMT_FLAG_COMPRESSED = 0x0001 V4L2_FMT_FLAG_EMULATED = 0x0002 + # ioctl code for video devices VIDIOC_QUERYCAP = _IOR('V', 0, v4l2_capability) VIDIOC_ENUM_FRAMESIZES = _IOWR('V', 74, v4l2_frmsizeenum) @@ -168,6 +170,7 @@ class CameraTest: self.args = args self._width = 640 self._height = 480 + self._devices = [] def detect(self): """ @@ -186,10 +189,10 @@ class CameraTest: print("%s: OK" % device) print(" name : %s" % cp.card.decode('UTF-8')) print(" driver : %s" % cp.driver.decode('UTF-8')) - print(" version: %s.%s.%s" - % (cp.version >> 16, - (cp.version >> 8) & 0xff, - cp.version & 0xff)) + print( + " version: %s.%s.%s" + % (cp.version >> 16, (cp.version >> 8) & 0xff, + cp.version & 0xff)) print(" flags : 0x%x [" % cp.capabilities, ' CAPTURE' if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE else '', @@ -212,51 +215,67 @@ class CameraTest: cap_status = 0 return dev_status | cap_status + def _stop(self): + self.camerabin.set_state(Gst.State.NULL) + Gtk.main_quit() + + def _on_error(self, bus, msg): + Gtk.main_quit() + def _on_destroy(self, *args): Clutter.main_quit() - def _take_photo(self, *args): - Cheese.Camera.take_photo(self.camera, self.filename) + def _take_photo(self, filename): + self.camerabin.set_property("location", filename) + self.camerabin.emit("start-capture") + + def _setup(self, sink=None): + webcam = Gst.ElementFactory.make('v4l2src') + webcam.set_property('device', self.args.device) + wrappercamerabinsrc = Gst.ElementFactory.make('wrappercamerabinsrc') + wrappercamerabinsrc.set_property('video-source', webcam) + self.camerabin = Gst.ElementFactory.make("camerabin") + self.camerabin.set_property('camera-source', wrappercamerabinsrc) + if sink: + vf_sink = Gst.ElementFactory.make(sink) + self.camerabin.set_property('viewfinder-sink', vf_sink) + self.camerabin.set_state(Gst.State.PAUSED) + caps = self.camerabin.get_property('viewfinder-supported-caps') + supported_resolutions = {} + for i in range(caps.get_size()): + key = caps.get_structure(i).get_int('width').value + try: + supported_resolutions[key].add( + caps.get_structure(i).get_int('height').value) + except KeyError: + supported_resolutions[key] = set() + width = min(supported_resolutions.keys(), + key=lambda x: abs(x - self._width)) + height = min(supported_resolutions[width], + key=lambda y: abs(y - self._height)) + vf_caps = Gst.Caps.from_string( + 'video/x-raw, width={}, height={}'.format(width, height)) + self.camerabin.set_property('viewfinder-caps', vf_caps) + bus = self.camerabin.get_bus() + bus.add_signal_watch() + bus.connect('message::error', self._on_error) + self.camerabin.set_state(Gst.State.PLAYING) def led(self): """ Activate camera (switch on led), but don't display any output """ - Clutter.threads_add_timeout(0, 3000, self._on_destroy, None, None) - video_texture = Clutter.Actor() - try: - camera = Cheese.Camera.new( - video_texture, self.args.device, self._width, self._height) - except TypeError: # libcheese < 3.18 still use Clutter.Texture - video_texture = Clutter.Texture() - camera = Cheese.Camera.new( - video_texture, self.args.device, self._width, self._height) - Cheese.Camera.setup(camera, None) - Cheese.Camera.play(camera) - Clutter.main() + self._setup(sink='fakesink') + GLib.timeout_add_seconds(3, self._stop) + Gtk.main() def display(self): """ Displays the preview window """ - stage = Clutter.Stage() - stage.set_title('Camera test') - stage.set_size(self._width, self._height) - stage.connect('destroy', self._on_destroy) - Clutter.threads_add_timeout(0, 10000, self._on_destroy, None, None) - video_texture = Clutter.Actor() - try: - camera = Cheese.Camera.new( - video_texture, self.args.device, self._width, self._height) - except TypeError: # libcheese < 3.18 still use Clutter.Texture - video_texture = Clutter.Texture() - camera = Cheese.Camera.new( - video_texture, self.args.device, self._width, self._height) - stage.add_actor(video_texture) - Cheese.Camera.setup(camera, None) - Cheese.Camera.play(camera) - stage.show() - Clutter.main() + self._setup() + GLib.timeout_add_seconds(10, self._stop) + Gtk.main() def still(self): """ @@ -280,7 +299,7 @@ class CameraTest: "-d", self.args.device, "-r", "%dx%d" % (width, height), filename] - use_cheese = False + use_camerabin = False if pixelformat: if 'MJPG' == pixelformat: # special tweak for fswebcam pixelformat = 'MJPEG' @@ -289,27 +308,12 @@ class CameraTest: try: check_call(command, stdout=open(os.devnull, 'w'), stderr=STDOUT) except (CalledProcessError, OSError): - use_cheese = True - - if use_cheese: - stage = Clutter.Stage() - stage.connect('destroy', self._on_destroy) - video_texture = Clutter.Actor() - try: - self.camera = Cheese.Camera.new( - video_texture, self.args.device, self._width, self._height) - except TypeError: # libcheese < 3.18 still use Clutter.Texture - video_texture = Clutter.Texture() - self.camera = Cheese.Camera.new( - video_texture, self.args.device, self._width, self._height) - Cheese.Camera.setup(self.camera, None) - Cheese.Camera.play(self.camera) - self.filename = filename - Clutter.threads_add_timeout(0, 3000, self._take_photo , None, None) - Clutter.threads_add_timeout(0, 4000, self._on_destroy, None, None) - Clutter.main() - Cheese.Camera.stop(self.camera) - + use_camerabin = True + if use_camerabin: + self._setup(sink='fakesink') + GLib.timeout_add_seconds(3, self._take_photo, filename) + GLib.timeout_add_seconds(4, self._stop) + Gtk.main() if not quiet: stage = Clutter.Stage() stage.set_title('Camera still picture test') @@ -328,7 +332,7 @@ class CameraTest: ret = "" for resolution in supported_resolutions: ret += "Format: %s (%s)\n" % (resolution['pixelformat'], - resolution['description']) + resolution['description']) ret += "Resolutions: " for res in resolution['resolutions']: ret += "%sx%s," % (res[0], res[1]) @@ -568,20 +572,17 @@ if __name__ == "__main__": # Import Gst only for the test cases that will need it if args.test in ['display', 'still', 'led', 'resolutions']: - import contextlib - # Workaround to avoid "cluttervideosink missing" - # See https://bugzilla.gnome.org/show_bug.cgi?id=721277 - with contextlib.suppress(FileNotFoundError): - gst_registry = '~/.cache/gstreamer-1.0/registry.x86_64.bin' - os.remove(os.path.expanduser(gst_registry)) import gi gi.require_version('Gst', '1.0') from gi.repository import Gst - gi.require_version('Cheese', '3.0') - from gi.repository import Cheese + gi.require_version('GLib', '2.0') + from gi.repository import GLib gi.require_version('Clutter', '1.0') from gi.repository import Clutter + gi.require_version('Gtk', '3.0') + from gi.repository import Gtk Gst.init(None) Clutter.init() + Gtk.init([]) camera = CameraTest(args) sys.exit(getattr(camera, args.test)()) diff --git a/units/camera/jobs.pxu b/units/camera/jobs.pxu index 4219462..b1e4b9c 100644 --- a/units/camera/jobs.pxu +++ b/units/camera/jobs.pxu @@ -8,65 +8,95 @@ command: camera_test detect _description: This Automated test attempts to detect a camera. +unit: template +template-resource: device +template-filter: device.category == 'CAPTURE' and device.name != '' +template-unit: job plugin: user-interact-verify category_id: com.canonical.plainbox::camera -id: camera/display +id: camera/display_{name} +_summary: Webcam video display test for {product_slug} estimated_duration: 120.0 depends: camera/detect -requires: - device.category == 'CAPTURE' command: - camera_test display + camera_test display -d /dev/{name} _description: PURPOSE: - This test will check that the built-in camera works + This test will check that the {product_slug} camera works STEPS: 1. Click on Test to display a video capture from the camera for ten seconds. VERIFICATION: Did you see the video capture? +unit: template +template-resource: device +template-filter: device.category == 'CAPTURE' and device.name != '' +template-unit: job +plugin: user-interact-verify +category_id: com.canonical.plainbox::camera +id: camera/led_{name} +_summary: Webcam LED test for {product_slug} +estimated_duration: 120.0 +depends: camera/detect +command: + camera_test led -d /dev/{name} +_description: + PURPOSE: + This test will check that the {product_slug} camera LED works + STEPS: + 1. Select Test to activate camera + 2. Camera LED should light for a few seconds + VERIFICATION: + Did the camera LED light? + +unit: template +template-resource: device +template-filter: device.category == 'CAPTURE' and device.name != '' +template-unit: job plugin: user-interact-verify template-engine: jinja2 category_id: com.canonical.plainbox::camera -id: camera/still +id: camera/still_{{ name }} +_summary: Webcam still image capture test for {{ product_slug }} estimated_duration: 120.0 depends: camera/detect requires: {%- if __on_ubuntucore__ %} executable.name == 'fswebcam' - device.category == 'CAPTURE' {%- else %} package.name == 'gir1.2-gst-plugins-base-1.0' package.name == 'eog' package.name == 'fswebcam' or package.name == 'gir1.2-gst-plugins-base-1.0' - device.category == 'CAPTURE' {% endif -%} command: - camera_test still + camera_test still -d /dev/{{ name }} _description: PURPOSE: - This test will check that the built-in camera works + This test will check that the {{ product_slug }} works STEPS: 1. Click on Test to display a still image from the camera for ten seconds. VERIFICATION: Did you see the image? +unit: template +template-resource: device +template-filter: device.category == 'CAPTURE' and device.name != '' +template-unit: job plugin: shell template-engine: jinja2 category_id: com.canonical.plainbox::camera -id: camera/multiple-resolution-images +id: camera/multiple-resolution-images_{{ name }} +_summary: Webcam multiple resolution capture test for {{ product_slug }} estimated_duration: 1.2 depends: camera/detect requires: {%- if __on_ubuntucore__ %} executable.name == 'fswebcam' - device.category == 'CAPTURE' {%- else %} package.name == 'fswebcam' or package.name == 'gir1.2-gst-plugins-base-1.0' - device.category == 'CAPTURE' {% endif -%} command: - camera_test resolutions + camera_test resolutions -d /dev/{{ name }} _description: Takes multiple pictures based on the resolutions supported by the camera and validates their size and that they are of a valid format. diff --git a/units/camera/packaging.pxu b/units/camera/packaging.pxu deleted file mode 100644 index bb12d64..0000000 --- a/units/camera/packaging.pxu +++ /dev/null @@ -1,3 +0,0 @@ -unit: packaging meta-data -os-id: debian -Depends: gir1.2-cheese-3.0 diff --git a/units/camera/test-plan.pxu b/units/camera/test-plan.pxu index e4302be..578a7ce 100644 --- a/units/camera/test-plan.pxu +++ b/units/camera/test-plan.pxu @@ -14,40 +14,49 @@ _name: Camera tests (Manual) _description: Camera tests (Manual) include: - camera/still certification-status=blocker - camera/display certification-status=blocker - + camera/still_.* certification-status=blocker + camera/display_.* certification-status=blocker +bootstrap_include: + device id: after-suspend-camera-cert-full unit: test plan _name: Camera tests (after suspend) _description: Camera tests (after suspend) include: - camera/display_after_suspend certification-status=blocker - camera/still_after_suspend certification-status=blocker + after-suspend-manual-camera/still_.* certification-status=blocker + after-suspend-manual-camera/display_.* certification-status=blocker +bootstrap_include: + device id: camera-cert-automated unit: test plan _name: Camera tests (automated) _description: Camera tests (automated) include: - camera/detect certification-status=blocker - camera/multiple-resolution-images certification-status=blocker + camera/detect certification-status=blocker + camera/multiple-resolution-images_.* certification-status=blocker +bootstrap_include: + device id: camera-cert-blockers unit: test plan _name: Camera tests (certification blockers only) _description: Camera tests (certification blockers only) include: - camera/detect certification-status=blocker - camera/still certification-status=blocker - camera/display certification-status=blocker - camera/multiple-resolution-images certification-status=blocker + camera/detect certification-status=blocker + camera/still_.* certification-status=blocker + camera/display_.* certification-status=blocker + camera/multiple-resolution-images_.* certification-status=blocker +bootstrap_include: + device id: after-suspend-camera-cert-blockers unit: test plan _name: Camera tests (after suspend, certification blockers only) _description: Camera tests (after suspend, certification blockers only) include: - camera/display_after_suspend certification-status=blocker - camera/still_after_suspend certification-status=blocker + after-suspend-manual-camera/still_.* certification-status=blocker + after-suspend-manual-camera/display_.* certification-status=blocker +bootstrap_include: + device diff --git a/units/led/jobs.pxu b/units/led/jobs.pxu index 15d3065..2c2ea16 100644 --- a/units/led/jobs.pxu +++ b/units/led/jobs.pxu @@ -171,21 +171,6 @@ plugin: manual category_id: led estimated_duration: 180 -plugin: user-interact-verify -category_id: led -id: led/camera -estimated_duration: 20.0 -depends: camera/detect -command: camera_test led -_description: - PURPOSE: - Camera LED verification - STEPS: - 1. Select Test to activate camera - 2. Camera LED should light for a few seconds - VERIFICATION: - Did the camera LED light? - plugin: manual category_id: led id: led/touchpad diff --git a/units/led/test-plan.pxu b/units/led/test-plan.pxu index 88d38a6..0329717 100644 --- a/units/led/test-plan.pxu +++ b/units/led/test-plan.pxu @@ -25,10 +25,12 @@ include: led/battery-charged led/battery-charging led/battery-low - led/camera + camera/led_.* led/caps-lock led/power led/touchpad +bootstrap_include: + device id: led-cert-automated unit: test plan @@ -50,10 +52,12 @@ include: suspend/led_after_suspend/battery-charged suspend/led_after_suspend/battery-charging suspend/led_after_suspend/battery-low - suspend/led_after_suspend/camera + after-suspend-manual-camera/led_.* suspend/led_after_suspend/caps-lock suspend/led_after_suspend/power suspend/led_after_suspend/touchpad +bootstrap_include: + device id: led-full unit: test plan diff --git a/units/miscellanea/jobs.pxu b/units/miscellanea/jobs.pxu index 7ddcc1b..6733a16 100644 --- a/units/miscellanea/jobs.pxu +++ b/units/miscellanea/jobs.pxu @@ -354,7 +354,7 @@ plugin: user-interact-verify category_id: com.canonical.plainbox::miscellanea estimated_duration: 5.0 id: miscellanea/device_check -command: udev_resource -l VIDEO NETWORK WIRELESS DISK ACCELEROMETER | tee >([[ $DISPLAY ]] && zenity --text-info --title="Device report") +command: udev_resource -l VIDEO NETWORK WIRELESS DISK CAPTURE ACCELEROMETER | tee >([[ $DISPLAY ]] && zenity --text-info --title="Device report") _summary: Device Check _purpose: Device check diff --git a/units/suspend/suspend.pxu b/units/suspend/suspend.pxu index 1ab5829..0c3a942 100644 --- a/units/suspend/suspend.pxu +++ b/units/suspend/suspend.pxu @@ -1449,23 +1449,6 @@ _description: VERIFICATION: Did the bluetooth LED turn off and on twice after resuming from suspend? -plugin: user-interact-verify -category_id: com.canonical.plainbox::suspend -id: suspend/led_after_suspend/camera -estimated_duration: 120.0 -depends: - camera/detect - suspend/suspend_advanced -command: camera_test led -_description: - PURPOSE: - Validate that the camera LED still works as expected after resuming from suspend - STEPS: - 1. Select Test to activate camera - 2. Camera LED should light for a few seconds - VERIFICATION: - Did the camera LED still turn on and off after resuming from suspend? - plugin: manual category_id: com.canonical.plainbox::suspend id: suspend/led_after_suspend/touchpad @@ -2090,54 +2073,6 @@ _description: VERIFICATION: Does tap recognition work? -plugin: user-interact-verify -category_id: com.canonical.plainbox::suspend -id: camera/display_after_suspend -estimated_duration: 120.0 -depends: suspend/suspend_advanced -requires: - device.category == 'CAPTURE' -command: camera_test display -_description: - PURPOSE: - This test will check that the built-in camera works after suspend - STEPS: - 1. Click on Test to display a video capture from the camera for ten seconds. - VERIFICATION: - Did you see the video capture? - -plugin: user-interact-verify -category_id: com.canonical.plainbox::suspend -id: camera/still_after_suspend -estimated_duration: 120.0 -depends: camera/display_after_suspend -requires: - package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0' - package.name == 'eog' - package.name == 'fswebcam' or package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0' - device.category == 'CAPTURE' -command: camera_test still -_description: - PURPOSE: - This test will check that the built-in camera works after suspend - STEPS: - 1. Click on Test to display a still image from the camera for ten seconds. - VERIFICATION: - Did you see the image? - -plugin: shell -category_id: com.canonical.plainbox::suspend -id: camera/multiple_resolution_after_suspend -estimated_duration: 1.2 -depends: camera/still_after_suspend -requires: - package.name == 'fswebcam' or package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0' - device.category == 'CAPTURE' -command: camera_test resolutions -_description: - Takes multiple pictures based on the resolutions supported by the camera and - validates their size and that they are of a valid format after suspend - unit: template template-resource: device template-filter: device.category == 'MOUSE' or device.category == 'TOUCHPAD' or device.category == 'TOUCHSCREEN' |
