plainbox-provider-checkbox-0.25/manage.py 0000775 0001750 0001750 00000000541 12646171221 021675 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
from plainbox.provider_manager import setup
from plainbox.provider_manager import N_
setup(
name='plainbox-provider-checkbox',
namespace='2013.com.canonical.certification',
version="0.25",
description=N_("Checkbox provider"),
gettext_domain='plainbox-provider-checkbox',
strict=False, deprecated=False,
)
plainbox-provider-checkbox-0.25/units/ 0000775 0001750 0001750 00000000000 12646152434 021237 5 ustar sylvain sylvain 0000000 0000000 plainbox-provider-checkbox-0.25/units/hwsubmit.pxu 0000664 0001750 0001750 00000001161 12646152433 023635 0 ustar sylvain sylvain 0000000 0000000 id: hwsubmit
_name: All HW Submit Tests
unit: test plan
include:
cdimage
cpuinfo
device
dmi
dpkg
gconf
lsb
meminfo
module
package
uname
usb
info/buildstamp
cpuinfo_attachment
dmesg_attachment
dmi_attachment
dmidecode_attachment
kernel_cmdline_attachment
recovery_info_attachment
dell_bto_xml_attachment
lsmod_attachment
dkms_info_attachment
lspci_attachment
lspci_standard_config_attachment
modinfo_attachment
modprobe_attachment
modules_attachment
sysfs_attachment
sysctl_attachment
udev_attachment
plainbox-provider-checkbox-0.25/units/autotesting.pxu 0000664 0001750 0001750 00000007231 12646152433 024345 0 ustar sylvain sylvain 0000000 0000000 id: autotesting
_name: Automated Tests
unit: test plan
description:
This test plan is used for automated testing of the test cases themselves.
The resources jobs are needed for a valid submission, so they are included
explicitly, even if they are usually run implicitly by jobs requiring them.
include:
IEEE_80211
cpuinfo
dpkg
lsb
package
uname
acpi_sleep_attachment
codecs_attachment
cpuinfo_attachment
dmesg_attachment
dmi_attachment
dmidecode_attachment
efi_attachment
lspci_attachment
lspci_standard_config_attachment
meminfo_attachment
modinfo_attachment
modprobe_attachment
modules_attachment
sysctl_attachment
sysfs_attachment
udev_attachment
recovery_info_attachment
dell_bto_xml_attachment
lsmod_attachment
dkms_info_attachment
audio/alsa_record_playback_automated
bluetooth/detect-output
camera/detect
camera/multiple-resolution-images
cpu/scaling_test
cpu/scaling_test-log-attach
cpu/offlining_test
cpu/topology
disk/read_performance
disk/read_performance_.*
graphics/xorg-version
graphics/1_compiz_check_.*
graphics/xorg-failsafe
graphics/xorg-process
graphics/1_screenshot_.*
1_screenshot_.*.jpg
graphics/1_screenshot_fullscreen_video_.*
1_screenshot_fullscreen_video_.*.jpg
install/apt-get-gets-updates
mediacard/sd-preinserted
memory/info
memory/check
miscellanea/submission-resources
miscellanea/fwts_test
miscellanea/fwts_results.log
ethernet/detect
networking/http
networking/gateway_ping
power-management/tickless_idle
power-management/rtc
power-management/fwts_wakealarm
power-management/fwts_wakealarm-log-attach
usb/detect
usb/storage-preinserted
wireless/wireless_scanning
wireless/wireless_connection_wpa_bg
wireless/wireless_connection_open_bg
wireless/wireless_connection_wpa_n
wireless/wireless_connection_open_n
wireless/wireless_connection_wpa_ac
wireless/wireless_connection_open_ac
wireless/monitor_wireless_connection_udp
suspend/audio_before_suspend
suspend/bluetooth_obex_send_before_suspend
suspend/bluetooth_obex_browse_before_suspend
suspend/bluetooth_obex_get_before_suspend
suspend/cpu_before_suspend
suspend/network_before_suspend
suspend/memory_before_suspend
suspend/suspend_advanced_auto
suspend/suspend-single-log-check
suspend/audio_after_suspend_auto
suspend/network_resume_time_auto
suspend/wifi_resume_time_auto
suspend/usb_storage_preinserted_after_suspend
suspend/record_playback_after_suspend_auto
suspend/bluetooth_obex_send_after_suspend_auto
suspend/bluetooth_obex_browse_after_suspend_auto
suspend/bluetooth_obex_get_after_suspend_auto
suspend/cpu_after_suspend_auto
suspend/memory_after_suspend_auto
suspend/wireless_connection_after_suspend_wpa_bg_auto
suspend/wireless_connection_after_suspend_open_bg_auto
suspend/wireless_connection_after_suspend_wpa_n_auto
suspend/wireless_connection_after_suspend_open_n_auto
suspend/wireless_connection_after_suspend_wpa_ac_auto
suspend/wireless_connection_after_suspend_open_ac_auto
suspend/gpu_lockup_after_suspend
suspend/screenshot_after_suspend
screenshot_after_suspend.jpg
bootstrap_include:
disk/read_performance
graphics/generator_compiz_check
graphics/generator_screenshot
graphics/generator_screenshot.jpg
graphics/generator_screenshot_fullscreen_video
graphics/generator_screenshot_fullscreen_video.jpg
graphics/generator_screenshot_fullscreen_video
graphics/generator_screenshot_fullscreen_video.jpg
plainbox-provider-checkbox-0.25/units/dock.pxu 0000664 0001750 0001750 00000112246 12646152433 022722 0 ustar sylvain sylvain 0000000 0000000 id: dock/docking
plugin: manual
estimated_duration: 30.00
_summary: Docking test
_purpose:
This test will check the device can be used after docking.
_steps:
1. Dock the device to the docking unit.
_verification:
Is the device working as expected after being docked?
id: dock/monitor-displayport
depends: dock/docking
estimated_duration: 120.0
_summary: DisplayPort test on the dock
plugin: manual
_purpose:
This test will check the DisplayPort(s) on the dock.
_steps:
Skip this test if the dock does not have a DisplayPort.
1. Connect a display (if not already connected) to the DisplayPort on the dock
2. Repeat step 1 for each additional DisplayPorts, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/monitor-dvi
depends: dock/docking
estimated_duration: 120.0
_summary: DVI port test on the dock
plugin: manual
_purpose:
This test will check the DVI port(s) on the dock.
_steps:
Skip this test if the dock does not have a DVI port.
1. Connect a display (if not already connected) to the DVI port on the dock
2. Repeat step 1 for each additional DVI port, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/monitor-hdmi
depends: dock/docking
estimated_duration: 120.0
_summary: HDMI port test on the dock
plugin: manual
_purpose:
This test will check the HDMI port(s) on the dock.
_steps:
Skip this test if the dock does not have a HDMI port.
1. Connect a display (if not already connected) to the HDMI port on the dock
2. Repeat step 1 for each additional HDMI port, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/monitor-vga
depends: dock/docking
estimated_duration: 120.0
_summary: VGA port test on the dock
plugin: manual
_purpose:
This test will check the VGA port(s) on the dock.
_steps:
Skip this test if the dock does not have a VGA port.
1. Connect a display (if not already connected) to the VGA port on the dock
2. Repeat step 1 for each additional VGA port, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/monitor-multi-head
depends: dock/docking
estimated_duration: 120.0
_summary: Multiple monitors test while docked
plugin: manual
_purpose:
This test verifies that multi-monitor output works using the dock. You will need at least two external monitors to perform this test.
_steps:
Skip this test if your video card or the dock do not support multiple monitors.
1. If your dock provides more than one monitor outputs, connect two monitors
2. Open the "Displays" tool (open the dash and search for "Displays")
3. Configure your output to provide one desktop across all the monitors
4. Open any application and drag its window from one monitor to the next.
_verification:
Was the stretched desktop displayed correctly across all the screens?
id: dock/keys-video-out
depends: dock/docking
estimated_duration: 120.0
_summary: Video Out hotkey test
plugin: manual
_purpose:
Validate that the External Video hotkey is working as expected
_steps:
1. Plug in an external monitor
2. Press the display hotkey to change the monitors configuration
_verification:
Check that the video signal can be mirrored, extended, displayed on external or onboard only.
### Audio Tests ###
plugin: shell
id: dock/audio-list-devices
estimated_duration: 1.0
_summary: List audio devices
depends: dock/docking
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
command: cat /proc/asound/cards
_description: Test to detect audio devices
id: dock/audio-playback-hdmi
depends: dock/docking
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
_summary: HDMI audio test
plugin: user-interact-verify
estimated_duration: 30.0
command:
audio_settings store --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --verbose --device=hdmi --volume=50
gst_pipeline_test -t 2 --device hdmi 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_purpose:
Dock HDMI audio interface verification
_steps:
1. Plug an external HDMI device with sound to the dock (use only one HDMI/DisplayPort/Thunderbolt interface at a time for this test)
2. Go to the Sound settings and make sure the correct Output is selected
3. Click the Test button
_verification:
Did you hear the sound from the HDMI device?
id: dock/audio-playback-displayport
depends: dock/docking
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
_summary: DisplayPort audio test
plugin: user-interact-verify
estimated_duration: 30.0
command:
audio_settings store --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --verbose --device=hdmi --volume=50
gst_pipeline_test -t 2 --device hdmi 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_purpose:
Dock DisplayPort audio interface verification
_steps:
1. Plug an external DisplayPort device with sound to the dock (use only one HDMI/DisplayPort/Thunderbolt interface at a time for this test)
2. Go to the Sound settings and make sure the correct Output is selected
3. Click the Test button
_verification:
Did you hear the sound from the DisplayPort device?
id: dock/audio-playback-headphones
plugin: user-interact-verify
estimated_duration: 30.0
_summary: Headphones output test
depends: dock/audio-list-devices
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_purpose:
This test will check that headphones connector works correctly.
(Skip this test if there is no headphone connector on the dock)
_steps:
1. Connect a pair of headphones to the dock
2. Click the Test button to play a sound to your audio device
_verification:
Did you hear a sound through the headphones and did the sound play without any distortion, clicks or other strange noises from your headphones?
plugin: user-interact-verify
id: dock/audio-alsa-record-playback-external
estimated_duration: 30.0
_summary: External microphone plugged to the dock to record sound test
depends: dock/audio-playback-headphones
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_purpose:
This test will check that recording sound using an external microphone works correctly
(Skip this test if the dock does not have a microphone connector)
_steps:
1. Connect a microphone to the dock's microphone port
2. Click "Test", then speak into the external microphone
3. After a few seconds, your speech will be played back to you
_verification:
Did you hear your speech played back?
plugin: shell
id: dock/audio-alsa-info-collect
estimated_duration: 2.0
_summary: Collect audio-related system information
depends: dock/docking
command: alsa_info --no-dialog --no-upload --output ${PLAINBOX_SESSION_SHARE}/alsa_info.log
_description:
Collect audio-related system information. This data can be used to
simulate this computer's audio subsystem and perform more detailed tests
under a controlled environment.
plugin: attachment
id: dock/audio-alsa-info-attachment
depends: dock/audio-alsa-info-collect
estimated_duration: 1.0
_summary: Attach audio hardware data log to results
command: [ -e ${PLAINBOX_SESSION_SHARE}/alsa_info.log ] && cat ${PLAINBOX_SESSION_SHARE}/alsa_info.log
_description:
Attaches the audio hardware data collection log to the results.
plugin: manual
id: dock/audio-external-lineout
depends: dock/docking
estimated_duration: 30.0
_summary: Line-out connection test
_purpose:
Check that external line-out connection works correctly
(Skip this test if dock does not have a line out connector)
_steps:
1. Insert cable to speakers (with built-in amplifiers) on the dock's line-out port
2. Open system sound preferences, 'Output' tab, select 'Line-out' on the connector list. Click the Test button
3. On the system sound preferences, select 'Internal Audio' on the device list and click 'Test Speakers' to check left and right channel
_verification:
1. Do you hear a sound in the speakers? The internal speakers should *not* be muted automatically
2. Do you hear the sound coming out on the corresponding channel?
plugin: user-interact-verify
id: dock/audio-external-linein
depends: dock/docking
estimated_duration: 120.0
_summary: Line-in connection test
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_purpose:
Check that external line-in connection works correctly
(Skip this test if the dock does not have a line in connector)
_steps:
1. Use a cable to connect the dock's line-in port to an external line-out source.
2. Open system sound preferences, 'Input' tab, select 'Line-in' on the connector list. Click the Test button
3. After a few seconds, your recording will be played back to you.
_verification:
Did you hear your recording?
id: dock/audio-speaker-headphone-plug-detection
plugin: user-interact
depends: dock/docking
estimated_duration: 60.0
_summary: Headphones recognized when plugged to the dock test
requires:
device.category == 'AUDIO'
package.name == 'pulseaudio-utils'
command: pulse-active-port-change sinks
_purpose:
Check that system detects speakers or headphones being plugged in
(Skip this test if the dock does not have headphones connector)
_steps:
1. Prepare a pair of headphones or speakers with a standard 3.5mm jack
2. Locate the speaker / headphone jack on the dock under test
3. Run the test (you have 30 seconds from now on)
4. Plug headphones or speakers into the appropriate jack
5. Unplug the device for subsequent tests.
_verification:
Verification is automatic, no action is required.
The test times out after 30 seconds (and fails in that case).
id: dock/audio-microphone-plug-detection
plugin: user-interact
depends: dock/docking
estimated_duration: 60.0
_summary: Microphone recognized when plugged to the dock test
requires:
device.category == 'AUDIO'
package.name == 'pulseaudio-utils'
command: pulse-active-port-change sources
_purpose:
Check that system detects a microphone being plugged in
(Skip this test if the dock does not have a microphone connector)
_steps:
1. Prepare a microphone with a standard 3.5mm jack
2. Locate the microphone jack on the dock under test.
Keep in mind that it may be shared with the headphone jack.
3. Run the test (you have 30 seconds from now on)
4. Plug the microphone into the appropriate jack
5. Unplug the device for subsequent tests.
_verification:
Verification is automatic, no action is required.
The test times out after 30 seconds (and fails in that case).
### Networking Tests ###
id: dock/networking-gateway-ping
plugin: user-interact-verify
depends: dock/docking ethernet/detect
command: gateway_ping_test
estimated_duration: 10.00
_summary: Ping test using dock's Ethernet connectivity
_purpose:
Tests whether the system has a working Internet connection.
_steps:
1. Make sure the dock is connected to network using an Ethernet cable
2. Make sure the laptop itself is not connected to any Ethernet cable
3. Launch the test
_verification:
Was the test able to ping the network using the Ethernet connection?
id: dock/networking-ntp
plugin: user-interact-verify
depends: dock/docking
requires: package.name == 'ntpdate'
user: root
command: network_ntp_test
estimated_duration: 10.00
_summary: NTP sync test using dock's Ethernet connectivity
_purpose:
Test to see if we can sync local clock to an NTP server
_steps:
1. Make sure the dock is connected to network using an Ethernet cable
2. Make sure the laptop itself is not connected to any Ethernet cable
3. Launch the test
_verification:
Was the test able to synchronize system time using the Ethernet connection?
### USB Tests ###
plugin: user-interact-verify
id: dock/usb-HID
estimated_duration: 20.0
_summary: USB HID device test
command: keyboard_test
_purpose:
This test will check that you can use a USB HID device
_steps:
1. Enable either a USB mouse or keyboard
2. For mice, perform actions such as moving the pointer, right and left button clicks and double clicks
3. For keyboards, click the Test button to lauch a small tool. Type some text and close the tool.
_verification:
Did the device work as expected?
plugin: user-interact
id: dock/usb-insert
estimated_duration: 10.0
_summary: USB drive insertion test
command: removable_storage_watcher insert usb
_purpose:
This test will check that the system correctly detects the insertion of
a USB storage device plugged on the dock
_steps:
1. Click "Test" and insert a USB storage device, preferably a HDD,
in one of the dock's port.
Although a USB pen drive may be used it might cause performance
related tests to fail. (Note: this test will time-out after 20
seconds.)
2. Do not unplug the device after the test.
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
id: dock/usb3-insert
estimated_duration: 10.0
_summary: USB3 drive insertion test
command: removable_storage_watcher -m 500000000 insert usb
_purpose:
This test will check that the system correctly detects the insertion of
a USB 3.0 storage device
_steps:
1. Click "Test" and insert a USB 3.0 storage device, preferably a HDD,
in one of the dock's USB 3.0 port. Although a USB 3.0 pen drive may
be used it might cause performance related tests to fail.
(Note: this test will time-out after 20 seconds.)
2. Do not unplug the device after the test.
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
id: dock/usb-remove
depends: dock/usb-insert
estimated_duration: 10.0
_summary: USB drive removal test
command: removable_storage_watcher remove usb
_purpose:
This test will check that the system correctly detects the removal of
a USB storage device
_steps:
1. Click "Test" and remove the USB device from the dock.
(Note: this test will time-out after 20 seconds.)
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
id: dock/usb3-remove
depends: dock/usb3-insert
estimated_duration: 10.0
_summary: USB3 drive removal test
command: removable_storage_watcher -m 500000000 remove usb
_purpose:
This test will check that the system correctly detects the removal of
a USB 3.0 storage device
_steps:
1. Click "Test" and remove the USB 3.0 device from the dock.
(Note: this test will time-out after 20 seconds.)
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
id: dock/usb-storage-automated
depends: dock/usb-insert
user: root
estimated_duration: 45.0
_summary: USB drive storage test
command: removable_storage_test -s 268400000 usb
_description:
This test is automated and executes after the dock/usb_insert test is run.
plugin: shell
id: dock/usb3-storage-automated
depends: dock/usb3-insert
user: root
estimated_duration: 45.0
_summary: USB3 drive storage test
command: removable_storage_test -s 268400000 -m 500000000 usb --driver xhci_hcd
_description:
This test is automated and executes after the dock/usb3_insert test is run.
### ACPI ###
id: dock/battery-charging
_summary: Battery charging when docked test
plugin: shell
depends: dock/docking
estimated_duration: 1.0
command:
if [ "`upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep "state" | awk '{print $2}'`" = "discharging" ] ; then exit 1 ; fi
_description:
This test will make sure the laptop is being charged while connected to the dock.
plugin: shell
id: dock/network-before-suspend
depends: ethernet/detect
estimated_duration: 1.2
_summary: Network status before suspend
_description: Record the current network before suspending.
command: set -o pipefail; gateway_ping_test | tee $PLAINBOX_SESSION_SHARE/network_before_suspend.txt
plugin: shell
id: dock/audio-before-suspend
estimated_duration: 1.0
_summary: Audio status before suspend
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
_description: Record mixer settings before suspending.
command: audio_settings store --file=$PLAINBOX_SESSION_SHARE/audio_settings_before_suspend
id: dock/suspend-dock-resume
plugin: manual
estimated_duration: 120.00
_summary: Suspend the device, dock it and resume it
_purpose:
This test will check the device can be suspended, docked and resumed properly
_steps:
1. If the laptop is currently docked, undock it now
2. Suspend the laptop (e.g. by closing its lid)
3. Dock the laptop
4. Resume the laptop (e.g. by pressing the Power button on the dock)
_verification:
Is the device working as expected after being docked and resumed?
id: dock/networking-gateway-ping-after-suspend
plugin: shell
depends: dock/suspend-dock-resume ethernet/detect
command: gateway_ping_test
estimated_duration: 2.00
_summary: Network gateway ping after suspend
_description: Tests whether the system has a working Internet connection.
plugin: user-interact
id: dock/usb-insert-after-suspend
depends: dock/suspend-dock-resume
estimated_duration: 10.0
_summary: USB drive insertion after resuming
command: removable_storage_watcher insert usb
_purpose:
This test will check that the system correctly detects the insertion of
a USB storage device plugged on the dock after suspend
_steps:
1. Click "Test" and insert a USB storage device, preferably a HDD,
in one of the dock's port.
Although a USB pen drive may be used it might cause performance
related tests to fail. (Note: this test will time-out after 20
seconds.)
2. Do not unplug the device after the test.
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
id: dock/usb3-insert-after-suspend
depends: dock/suspend-dock-resume
estimated_duration: 10.0
_summary: USB3 drive insertion after resuming
command: removable_storage_watcher -m 500000000 insert usb
_purpose:
This test will check that the system correctly detects the insertion of
a USB 3.0 storage device after suspend
_steps:
1. Click "Test" and insert a USB 3.0 storage device, preferably a HDD,
in one of the dock's USB 3.0 port. Although a USB 3.0 pen drive may
be used it might cause performance related tests to fail.
(Note: this test will time-out after 20 seconds.)
2. Do not unplug the device after the test.
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
id: dock/usb-remove-after-suspend
depends: dock/usb-insert-after-suspend
estimated_duration: 10.0
_summary: USB drive removal after resuming
command: removable_storage_watcher remove usb
_purpose:
This test will check that the system correctly detects the removal of
a USB storage device after suspend
_steps:
1. Click "Test" and remove the USB device from the dock.
(Note: this test will time-out after 20 seconds.)
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
id: dock/usb3-remove-after-suspend
depends: dock/usb3-insert-after-suspend
estimated_duration: 10.0
_summary: USB3 drive removal after resuming
command: removable_storage_watcher -m 500000000 remove usb
_purpose:
This test will check that the system correctly detects the removal of
a USB 3.0 storage device after suspend
_steps:
1. Click "Test" and remove the USB 3.0 device from the dock.
(Note: this test will time-out after 20 seconds.)
_verification:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
id: dock/usb-storage-automated-after-suspend
depends: dock/usb-insert-after-suspend
user: root
estimated_duration: 45.0
_summary: USB drive storage test after resuming
command: removable_storage_test -s 268400000 usb
_description:
This test is automated and executes after the dock/usb-insert test is run.
plugin: shell
id: dock/usb3-storage-automated-after-suspend
depends: dock/usb3-insert-after-suspend
user: root
estimated_duration: 45.0
_summary: USB3 drive storage test after resuming
command: removable_storage_test -s 268400000 -m 500000000 usb --driver xhci_hcd
_description:
This test is automated and executes after the dock/usb3-insert test is run.
plugin: user-interact-verify
id: dock/usb-HID-after-suspend
depends: dock/suspend-dock-resume
estimated_duration: 20.0
_summary: USB HID device test after resuming
command: keyboard_test
_purpose:
This test will check that you can use a USB HID device
_steps:
1. Enable either a USB mouse or keyboard
2. For mice, perform actions such as moving the pointer, right and left button clicks and double clicks
3. For keyboards, click the Test button to lauch a small tool. Type some text and close the tool.
_verification:
Did the device work as expected?
id: dock/monitor-displayport-after-suspend
depends: dock/suspend-dock-resume
estimated_duration: 120.0
_summary: DisplayPort test on the dock after resuming
plugin: manual
_purpose:
This test will check the DisplayPort(s) on the dock after resuming.
_steps:
Skip this test if the dock does not have a DisplayPort.
1. Connect a display (if not already connected) to the DisplayPort on the dock
2. Repeat step 1 for each additional DisplayPorts, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/monitor-dvi-after-suspend
depends: dock/suspend-dock-resume
estimated_duration: 120.0
_summary: DVI port test on the dock after resuming
plugin: manual
_purpose:
This test will check the DVI port(s) on the dock after resuming.
_steps:
Skip this test if the dock does not have a DVI port.
1. Connect a display (if not already connected) to the DVI port on the dock
2. Repeat step 1 for each additional DVI port, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/monitor-hdmi-after-suspend
depends: dock/suspend-dock-resume
estimated_duration: 120.0
_summary: HDMI port test on the dock after resuming
plugin: manual
_purpose:
This test will check the HDMI port(s) on the dock after resuming.
_steps:
Skip this test if the dock does not have a HDMI port.
1. Connect a display (if not already connected) to the HDMI port on the dock
2. Repeat step 1 for each additional HDMI port, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/monitor-vga-after-suspend
depends: dock/suspend-dock-resume
estimated_duration: 120.0
_summary: VGA port test on the dock after resuming
plugin: manual
_purpose:
This test will check the VGA port(s) on the dock after resuming.
_steps:
Skip this test if the dock does not have a VGA port.
1. Connect a display (if not already connected) to the VGA port on the dock
2. Repeat step 1 for each additional VGA port, if any
_verification:
Was the desktop displayed correctly on both screens?
id: dock/suspend-undock-resume
plugin: manual
estimated_duration: 120.00
_summary: Suspend the device, undock it and resume it
_purpose:
This test will check the device can be suspended, undocked and resumed properly
_steps:
1. If the laptop is currently undocked, dock it now
2. Suspend the laptop (e.g. by closing its lid)
3. Undock the laptop
4. Resume the laptop (e.g. by pressing its Power button)
_verification:
Is the device working as expected after being undocked and resumed?
plugin: shell
id: dock/wireless-connection-after-suspend-wpa-bg
depends: dock/suspend-undock-resume
estimated_duration: 20.0
_summary: Wireless connection after suspend (WPA BG)
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_BG_SSID WPA_BG_PSK
command:
trap "nmcli con delete id $WPA_BG_SSID" EXIT
if create_connection wifi $WPA_BG_SSID --security=wpa --key=$WPA_BG_PSK; then
INTERFACE=`nmcli dev status | awk '/802-11-wireless/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11b/g protocols after the system has been suspended.
plugin: shell
id: dock/wireless-connection-after-suspend-open-bg
depends: dock/suspend-undock-resume
estimated_duration: 1.2
_summary: Wireless connection after suspend (Open BG)
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_BG_SSID
command:
trap "nmcli con delete id $OPEN_BG_SSID" EXIT
if create_connection wifi $OPEN_BG_SSID; then
INTERFACE=`nmcli dev status | awk '/802-11-wireless/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11b/g protocols after the system has been suspended.
plugin: shell
id: dock/wireless-connection-after-suspend-wpa-n
depends: dock/suspend-undock-resume
estimated_duration: 1.2
_summary: Wireless connection after suspend (WPA N)
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_N_SSID WPA_N_PSK
command:
trap "nmcli con delete id $WPA_N_SSID" EXIT
if create_connection wifi $WPA_N_SSID --security=wpa --key=$WPA_N_PSK; then
INTERFACE=`nmcli dev status | awk '/802-11-wireless/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11n protocol after the system has been suspended.
plugin: shell
id: dock/wireless-connection-after-suspend-open-n
depends: dock/suspend-undock-resume
estimated_duration: 1.2
_summary: Wireless connection after suspend (Open N)
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_N_SSID
command:
trap "nmcli con delete id $OPEN_N_SSID" EXIT
if create_connection wifi $OPEN_N_SSID; then
INTERFACE=`nmcli dev status | awk '/802-11-wireless/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11n protocol after the system has been suspended.
plugin: shell
id: dock/wireless-connection-after-suspend-wpa-ac
depends: dock/suspend-undock-resume
estimated_duration: 1.2
_summary: Wireless connection after suspend (WPA AC)
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: WPA_AC_SSID WPA_AC_PSK
command:
trap "nmcli con delete id $WPA_AC_SSID" EXIT
if create_connection wifi $WPA_AC_SSID --security=wpa --key=$WPA_AC_PSK; then
INTERFACE=`nmcli dev status | awk '/802-11-wireless/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11ac protocol after the system has been suspended.
plugin: shell
id: dock/wireless-connection-after-suspend-open-ac
depends: dock/suspend-undock-resume
estimated_duration: 1.2
_summary: Wireless connection after suspend (Open AC)
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: OPEN_AC_SSID
command:
trap "nmcli con delete id $OPEN_AC_SSID" EXIT
if create_connection wifi $OPEN_AC_SSID; then
INTERFACE=`nmcli dev status | awk '/802-11-wireless/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11ac protocol after the system has been suspended.
plugin: shell
id: dock/audio-after-suspend
estimated_duration: 1.0
_summary: Audio after resuming test
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
depends: dock/suspend-undock-resume dock/audio-before-suspend
_description: Verify that mixer settings after suspend are the same as before suspend.
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/audio_settings_after_suspend
diff $PLAINBOX_SESSION_SHARE/audio_settings_before_suspend $PLAINBOX_SESSION_SHARE/audio_settings_after_suspend
plugin: shell
id: dock/record-playback-after-suspend
estimated_duration: 10.0
_summary: Record playback after resuming
depends: dock/suspend-undock-resume
requires:
package.name == 'python3-gi'
package.name == 'gir1.2-gstreamer-1.0'
package.name == 'libgstreamer1.0-0'
package.name == 'gstreamer1.0-plugins-good'
package.name == 'gstreamer1.0-pulseaudio'
package.name == 'alsa-base'
device.category == 'AUDIO'
command: audio_test
_description:
This will check to make sure that your audio device works properly after a suspend and resume. This may work fine with speakers and onboard microphone, however, it works best if used with a cable connecting the audio-out jack to the audio-in jack.
plugin: manual
id: dock/expresscard-verification
estimated_duration: 10.0
_summary: ExpressCard slot verification
depends: dock/docking
_purpose:
This will verify that an ExpressCard slot on the dock can detect inserted devices.
_steps:
Skip this test if you do not have an ExpressCard slot on the dock.
1. Plug an ExpressCard device into the ExpressCard slot
_verification:
Was the device correctly detected?
plugin: user-interact
id: dock/firewire-insert
estimated_duration: 20.0
_summary: FireWire HDD insertion test
depends: dock/docking
command: removable_storage_watcher insert firewire
_purpose:
This test will check the system can detect the insertion of a FireWire HDD on the dock
_steps:
(Skip this test id there is no FireWire connector on the dock)
1. Click 'Test' to begin the test. This test will
timeout and fail if the insertion has not been detected within 20 seconds.
2. Plug a FireWire HDD into an available FireWire port.
_verification:
The verification of this test is automated. Do not change the automatically
selected result
plugin: shell
id: dock/firewire-storage-test
estimated_duration: 45.0
_summary: FireWire HDD storage test
depends: dock/docking dock/firewire-insert
user: root
command: removable_storage_test -s 268400000 firewire
_description:
This is an automated test which performs read/write operations on an attached
FireWire HDD
plugin: user-interact
id: dock/firewire-remove
estimated_duration: 20.0
_summary: FireWire HDD removal test
depends: dock/firewire-insert
command: removable_storage_watcher remove firewire
_purpose:
This test will check the system can detect the removal of a FireWire HDD
_steps:
1. Click 'Test' to begin the test. This test will timeout and fail if
the removal has not been detected within 20 seconds.
2. Remove the previously attached FireWire HDD from the FireWire port on
the dock.
_verification:
The verification of this test is automated. Do not change the automatically
selected result
plugin: user-interact
id: dock/esata-insert
estimated_duration: 20.0
_summary: eSATA HDD insertion test
depends: dock/docking
command: removable_storage_watcher insert ata_serial_esata
_purpose:
This test will check the system can detect the insertion of an eSATA HDD on the dock
_steps:
(Skip this test if there are no eSATA connectors on the dock)
1. Click 'Test' to begin the test. This test will
timeout and fail if the insertion has not been detected within 20 seconds.
2. Plug an eSATA HDD into an available eSATA port on the dock.
_verification:
The verification of this test is automated. Do not change the automatically
selected result
plugin: shell
id: dock/esata-storage-test
estimated_duration: 20.0
_summary: eSATA HDD storage test
user: root
depends: dock/esata-insert
command: removable_storage_test -s 268400000 ata_serial_esata
_description:
This is an automated test which performs read/write operations on an attached
eSATA HDD
plugin: user-interact
id: dock/esata-remove
estimated_duration: 20.0
_summary: eSATA HDD removal test
depends: dock/esata-insert
command: removable_storage_watcher remove ata_serial_esata
_purpose:
This test will check the system can detect the removal of an eSATA HDD from the dock
_steps:
1. Click 'Test' to begin the test. This test will timeout and fail if
the removal has not been detected within 20 seconds.
2. Remove the previously attached eSATA HDD from the eSATA port on the dock.
_verification:
The verification of this test is automated. Do not change the automatically
selected result
plugin: manual
id: dock/optical-read
depends: dock/docking
estimated_duration: 180.0
_summary: Optical media (CD) read test
_purpose:
This test will check the dock's ability to read CD media
_steps:
(Skip this test if the dock does not have an optical reader)
1. Insert appropriate non-blank media into your optical drive(s). Movie and Audio Disks may not work. Self-created data disks have the greatest chance of working.
2. Try to copy a few files from the optical media to the computer.
_verification:
Are the files properly copied to the computer?
plugin: manual
id: dock/optical-write
depends: dock/optical-read
estimated_duration: 300.0
_summary: Optical media (CD-RW, DVD-RW) writing test
_purpose:
This test will check the dock's ability to write CD/DVD media.
Depending on what the dock's optical drive support, you will need
a blank CD-R, CD-RW, DVD-R and/or DVD-RW.
_steps:
1. Insert a blank CD-R into the dock's drive
2. Open Brasero Disc Burner and write some files on the CD-R
3. Repeat steps 1-2 for other compatible media (CD-RW, DVD-R, DVD-RW)
_verification:
Are all kinds of discs properly written?
plugin: user-interact
id: dock/thunderbolt-insert
estimated_duration: 40.0
depends: dock/docking
command: removable_storage_watcher insert --timeout 40 scsi
_summary: Thunderbolt storage insertion detection
_purpose:
This test will check if the connection of a Thunderbolt HDD to the dock could be detected
_steps:
1. Click 'Test' to begin the test. This test will
timeout and fail if the insertion has not been detected within 40 seconds.
2. Plug a Thunderbolt HDD into an available Thunderbolt port on the dock;
if it's not mounted automatically, please click the HDD icon to mount it.
_verification:
The verification of this test is automated. Do not change the automatically
selected result
plugin: shell
id: dock/thunderbolt-storage-test
estimated_duration: 45.0
user: root
depends: dock/thunderbolt-insert
command: removable_storage_test -s 268400000 scsi
_summary: Thunderbolt storage test
_description:
This is an automated test which performs read/write operations on an attached
Thunderbolt HDD
plugin: user-interact
id: dock/thunderbolt-remove
estimated_duration: 20.0
depends: dock/thunderbolt-insert
command: removable_storage_watcher remove scsi
_summary: Thunderbolt storage removal detection
_purpose:
This test will check the system can detect the removal of a Thunderbolt HDD
_steps:
1. Click 'Test' to begin the test. This test will timeout and fail if
the removal has not been detected within 20 seconds.
2. Remove the previously attached Thunderbolt HDD from the Thunderbolt port.
_verification:
The verification of this test is automated. Do not change the automatically
selected result
plainbox-provider-checkbox-0.25/units/smoke.pxu 0000664 0001750 0001750 00000001200 12646152433 023103 0 ustar sylvain sylvain 0000000 0000000 id: smoke
_name: All Smoke Tests
unit: test plan
description:
This is an example test plan to start from.
To use, copy this file and add the jobs you want to run to the copy. Delete
these comments. DO NOT delete the first 9 jobs in tis file.
They are resource gathering jobs and are necessary to do any testing at all.
include:
cpuinfo
cdimage
dmi
dpkg
efi
environment
gconf
lsb
meminfo
module
package
device
uname
smoke/true
smoke/false
smoke/dependency/good
smoke/dependency/bad
smoke/requirement/good
smoke/requirement/bad
smoke/manual
plainbox-provider-checkbox-0.25/units/default.pxu 0000664 0001750 0001750 00000005704 12646152433 023426 0 ustar sylvain sylvain 0000000 0000000 id: default
_name: Default Tests
unit: test plan
include:
optical_drive
miscellanea/submission-resources
miscellanea/is_laptop
codecs_attachment
cpuinfo_attachment
dmesg_attachment
dmi_attachment
dmidecode_attachment
lshw_attachment
efi_attachment
lsmod_attachment
lspci_attachment
modprobe_attachment
modules_attachment
sysfs_attachment
sysctl_attachment
udev_attachment
audio/list_devices
audio/playback_headphones
audio/playback_auto
audio/alsa_record_playback_external
audio/alsa_record_playback_internal
audio/alsa_record_playback_usb
audio/playback_auto
benchmarks/disk/hdparm-read_.*
benchmarks/disk/hdparm-cache-read_.*
bluetooth/detect-output
camera/detect
camera/still
camera/display
cpu/offlining_test
cpu/topology
cpu/clocktest
disk/detect
firewire/insert
firewire/storage-test
firewire/remove
graphics/1_compiz_check.*
graphics/1_resolution.*
graphics/1_minimum_resolution.*
graphics/1_driver_version.*
graphics/VESA_drivers_not_in_use
input/keyboard
input/mouse
keys/super
keys/battery-info
keys/brightness
keys/media-control
keys/mute
keys/volume
keys/wireless
mediacard/mmc-insert
mediacard/mmc-storage
mediacard/mmc-remove
mediacard/sd-insert
mediacard/sd-storage
mediacard/sd-remove
mediacard/sdhc-insert
mediacard/sdhc-storage
mediacard/sdhc-remove
mediacard/cf-insert
mediacard/cf-storage
mediacard/cf-remove
memory/info
monitor/hdmi
monitor/vga
monitor/powersaving
ethernet/detect
wireless/wireless_connection
optical/detect
optical/read_.*
expresscard/verification
power-management/rtc
suspend/audio_before_suspend
suspend/memory_before_suspend
suspend/network_before_suspend
suspend/resolution_before_suspend
suspend/suspend_advanced
suspend/wireless_before_suspend
keys/sleep
suspend/mmc-insert-after-suspend
suspend/mmc-storage-after-suspend
suspend/mmc-remove-after-suspend
suspend/sd-insert-after-suspend
suspend/sd-storage-after-suspend
suspend/sd-remove-after-suspend
suspend/sdhc-insert-after-suspend
suspend/sdhc-storage-after-suspend
suspend/sdhc-remove-after-suspend
mediacard/cf-insert-after-suspend
mediacard/cf-storage-after-suspend
mediacard/cf-remove-after-suspend
suspend/audio_after_suspend
suspend/bluetooth_detect_after_suspend
suspend/memory_after_suspend
suspend/network_after_suspend
suspend/resolution_after_suspend
suspend/wireless_after_suspend
usb/detect
usb/insert
usb/storage-automated
usb/remove
bootstrap_include:
benchmarks/disk/hdparm-read
benchmarks/disk/hdparm-cache-read
optical/read
graphics/generator_compiz_check
graphics/generator_resolution
graphics/generator_minimum_resolution
graphics/generator_driver_version
plainbox-provider-checkbox-0.25/jobs/ 0000775 0001750 0001750 00000000000 12646152434 021032 5 ustar sylvain sylvain 0000000 0000000 plainbox-provider-checkbox-0.25/jobs/mobilebroadband.txt.in 0000664 0001750 0001750 00000011620 12646152433 025303 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::mobilebroadband
id: mobilebroadband/gsm_connection
estimated_duration: 20.0
requires:
package.name == 'network-manager'
package.name == 'modemmanager'
mobilebroadband.gsm == 'supported'
user: root
environ: GSM_CONN_NAME GSM_APN GSM_USERNAME GSM_PASSWORD
command:
if [ -n "${GSM_APN}" ]; then
trap "nmcli con delete id $GSM_CONN_NAME" EXIT
create_connection mobilebroadband gsm \
`[ -n "${GSM_APN}" ] && echo "--apn=$GSM_APN"` \
`[ -n "${GSM_CONN_NAME}" ] && echo "--name=$GSM_CONN_NAME"` \
`[ -n "${GSM_USERNAME}" ] && echo "--username=$GSM_USERNAME"` \
`[ -n "${GSM_PASSWORD}" ] && echo "--password=$GSM_PASSWORD"` || exit 1
fi
INTERFACE=`(nmcli -t -f GENERAL -m tabular dev list 2>/dev/null || nmcli -t -f GENERAL -m tabular dev show) |grep gsm |cut -d ":" -f 13`
echo "connected GSM interface seems to be $INTERFACE"
[ -z $INTERFACE ] && exit 1
curl http://start.ubuntu.com/connectivity-check.html --interface $INTERFACE
EXIT_CODE=$?
if [ -n "${GSM_APN}" ] && [ "`nmcli dev status | awk '/gsm/ {print $3}'`" == "connected" ]; then
nmcli con down id `[ ${GSM_CONN_NAME} ] && echo "$GSM_CONN_NAME" || echo "MobileBB"`
fi
exit $EXIT_CODE
_description: Creates a mobile broadband connection for a GSM based modem and checks the connection to ensure it's working.
plugin: shell
category_id: 2013.com.canonical.plainbox::mobilebroadband
id: mobilebroadband/cdma_connection
estimated_duration: 20.0
requires:
package.name == 'network-manager'
package.name == 'modemmanager'
mobilebroadband.cdma == 'supported'
user: root
environ: CDMA_CONN_NAME CDMA_USERNAME CDMA_PASSWORD
command:
if [ -n "${CDMA_USERNAME}" ]; then
trap "nmcli con delete id $CDMA_CONN_NAME" EXIT
create_connection mobilebroadband cdma \
`[ -n "${CDMA_CONN_NAME}" ] && echo "--name=$CDMA_CONN_NAME"` \
`[ -n "${CDMA_USERNAME}" ] && echo "--username=$CDMA_USERNAME"` \
`[ -n "${CDMA_PASSWORD}" ] && echo "--password=$CDMA_PASSWORD"` || exit 1
fi
INTERFACE=`(nmcli -t -f GENERAL -m tabular dev list 2>/dev/null || nmcli -t -f GENERAL -m tabular dev show) |grep cdma |cut -d ":" -f 13`
echo "connected CDMA interface seems to be $INTERFACE"
[ -z $INTERFACE ] && exit 1
curl http://start.ubuntu.com/connectivity-check.html --interface $INTERFACE
EXIT_CODE=$?
if [ -n "${CDMA_USERNAME}" ] && [ "`nmcli dev status | awk '/cdma/ {print $3}'`" == "connected" ]; then
nmcli con down id `[ ${CDMA_CONN_NAME} ] && echo "$CDMA_CONN_NAME" || echo "MobileBB"`
fi
exit $EXIT_CODE
_description: Creates a mobile broadband connection for a CDMA based modem and checks the connection to ensure it's working.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mobilebroadband
id: mobilebroadband/maximum_bandwidth_gsm_device{__index__}_{interface}
depends: mobilebroadband/gsm_connection
estimated_duration: 330.0
requires:
device.path == '{path}'
package.name == 'zenity'
package.name == 'iperf'
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
user: root
command: network test -i {interface} -t iperf 2>&1 | cat - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'mobile broadband max bw {interface}'
_purpose:
User verification of whether the observed transfer throughput is acceptable
for the type and maximum speed of device {__index__} ({interface}).
_steps:
1. Click "Test".
2. Read the network test summary and confirm that the throughput is acceptable.
3. If needed, click "Test" again to repeat the transfer test.
_verification:
Was the reported throughput acceptable for the type and maximum speed of this interface?
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mobilebroadband
id: mobilebroadband/maximum_bandwidth_cdma_device{__index__}_{interface}
depends: mobilebroadband/cdma_connection
estimated_duration: 330.0
requires:
device.path == '{path}'
package.name == 'zenity'
package.name == 'iperf'
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
user: root
command: network test -i {interface} -t iperf 2>&1 | cat - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'mobile broadband max bw {interface}'
_purpose:
User verification of whether the observed transfer throughput is acceptable
for the type and maximum speed of device {__index__} ({interface}).
_steps:
1. Click "Test".
2. Read the network test summary and confirm that the throughput is acceptable.
3. If needed, click "Test" again to repeat the transfer test.
_verification:
Was the reported throughput acceptable for the type and maximum speed of this interface?
plainbox-provider-checkbox-0.25/jobs/user_apps.txt.in 0000664 0001750 0001750 00000041717 12646152433 024212 0 ustar sylvain sylvain 0000000 0000000 plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/update_manager_finds_updates
depends: ethernet/detect
user: root
requires: package.name == 'update-manager'
_description:
PURPOSE:
This test will check that the update manager can find updates.
STEPS:
1. Click Test to launch update-manager.
2. Follow the prompts and if updates are found, install them.
3. When Update Manager has finished, please close the app by clicking the Close button in the lower right corner.
VERIFICATION:
Did Update manager find and install updates (Pass if no updates are found,
but Fail if updates are found but not installed)
command: update-manager --check-dist-upgrades
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_folder_create
requires: package.name == 'nautilus'
command: nautilus
_description:
PURPOSE:
This test will check that the file browser can create a new folder.
STEPS:
1. Click Test to open the File Browser.
2. On the menu bar, click File -> Create Folder.
3. In the name box for the new folder, enter the name Test Folder and hit Enter.
4. Close the File browser.
VERIFICATION:
Do you now have a new folder called Test Folder?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_folder_copy
depends: software/nautilus_folder_create
command: nautilus
_description:
PURPOSE:
This test will check that the file browser can copy a folder
STEPS:
1. Click Test to open the File Browser.
2. Right click on the folder called Test Folder and click on Copy.
3. Right Click on any white area in the window and click on Paste.
4. Right click on the folder called Test Folder(copy) and click Rename.
5. Enter the name Test Data in the name box and hit Enter.
6. Close the File browser.
VERIFICATION:
Do you now have a folder called Test Data?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_folder_move
depends: software/nautilus_folder_copy
command: nautilus
_description:
PURPOSE:
This test will verify that the file browser can move a folder.
STEPS:
1. Click Test to open the File Browser.
2. Click and drag the folder called Test Data onto the icon called Test Folder.
3. Release the button.
4. Double click the folder called Test Folder to open it up.
5. Close the File Browser.
VERIFICATION:
Was the folder called Test Data successfully moved into the folder called Test Folder?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_file_create
depends: software/nautilus_folder_create
command: nautilus $HOME/"Test Folder"
_description:
PURPOSE:
This test will check that the file browser can create a new file.
STEPS:
1. Click Select Test to open the File Browser.
2. Right click in the white space and click Create Document -> Empty Document.
3. Enter the name Test File 1 in the name box and hit Enter.
4. Close the File browser.
VERIFICATION:
Do you now have a file called Test File 1?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_file_copy
depends: software/nautilus_file_create
command: nautilus $HOME/"Test Folder"
_description:
PURPOSE:
This test will check that the file browser can copy a file.
STEPS:
1. Click Test to open the File Browser.
2. Right click on the file called Test File 1 and click Copy.
3. Right click in the white space and click Paste.
4. Right click on the file called Test File 1(copy) and click Rename.
5. Enter the name Test File 2 in the name box and hit Enter.
6. Close the File Browser.
VERIFICATION:
Do you now have a file called Test File 2?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_file_move
depends: software/nautilus_file_copy
command: nautilus $HOME/"Test Folder"
_description:
PURPOSE:
This test will check that the file browser can move a file.
STEPS:
1. Click Test to open the File Browser.
2. Click and drag the file called Test File 2 onto the icon for the folder called Test Data.
3. Release the button.
4. Double click the icon for Test Data to open that folder up.
5. Close the File Browser.
VERIFICATION:
Was the file Test File 2 successfully moved into the Test Data folder?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_file_delete
depends: software/nautilus_file_create
command: nautilus $HOME/"Test Folder"
_description:
PURPOSE:
This test will check that the file browser can delete a file.
STEPS:
1. Click Test to open the File Browser.
2. Right click on the file called Test File 1 and click on Move To Trash.
3. Verify that Test File 1 has been removed.
4. Close the File Browser.
VERIFICATION:
Is Test File 1 now gone?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/nautilus_folder_delete
depends: software/nautilus_folder_create
command: nautilus
_description:
PURPOSE:
This test will check that the file browser can delete a folder.
STEPS:
1. Click Test to open the File Browser.
2. Right click on the folder called Test Folder and click on Move To Trash.
3. Verify that the folder was deleted.
4. Close the file browser.
VERIFICATION:
Has Test Folder been successfully deleted?
plugin: local
_summary: Common Document Types Test
id: software/view_office_document
requires: package.name == "ubuntu-desktop"
_description: Common Document Types Test
command:
cat <<'EOF' | run_templates -s "find $PLAINBOX_PROVIDER_DATA/documents -type f"
id: `basename $0`_test
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
description:
PURPOSE:
This test will check that common office document types can be opened in the default application.
STEPS:
1. Click Test to open the file '$0' with its default viewer.
2. After the viewer opens, check out the file that was opened.
3. Close the application (LibreOffice, Doc Viewer, etc.)
VERIFICATION:
Did the application open the document properly? (e.g was it displayed and did it function properly?)
command: xdg-open $0
EOF
plugin: local
_summary: Common Document Types Test
id: software/audio_file_play
requires: package.name == "ubuntu-desktop"
_description: Common Document Types Test
command:
cat <<'EOF' | run_templates -s "find $PLAINBOX_PROVIDER_DATA/audio -type f"
id: `basename $0`_test
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
description:
PURPOSE:
This test will check that common audio files can be opened in the default player.
STEPS:
1. Click Test to open the audio file '$0' with its default player.
2. After the player opens listen to the sound.
3. Close the application.
VERIFICATION:
Did the application play the audio file properly? (no skips, crackles, etc)
command: xdg-open $0
EOF
plugin: local
_summary: Common Document Types Test
id: software/video_file_play
requires: package.name == "ubuntu-desktop"
_description: Common Document Types Test
command:
cat <<'EOF' | run_templates -s "find $PLAINBOX_PROVIDER_DATA/video -type f"
id: `basename $0`_test
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
description:
PURPOSE:
This test will check that common video files can be played in the default player.
STEPS:
1. Click Test to play the video '$0' with its default player.
2. Watch the video.
3. Close the application.
VERIFICATION:
Did the application play '$0' proplerly (no video or audio issues with playback?)
command: xdg-open $0
EOF
plugin: local
_summary: Common Document Types Test
id: software/view_image_file
requires: package.name == "ubuntu-desktop"
_description: Common Document Types Test
command:
cat <<'EOF' | run_templates -s "find $PLAINBOX_PROVIDER_DATA/images -type f"
id: `basename $0`_test
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
description:
PURPOSE:
This test will check that common image formats can be opened in the default viewer.
STEPS:
1. Click Test to attempt to open the image '$0' with its default viewer.
2. Check out the file that was opened.
3. Close the application.
VERIFICATION:
Did the image display properly?
command: xdg-open $0
EOF
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/firefox
requires: package.name == 'firefox'
command: firefox $PLAINBOX_PROVIDER_DATA/websites/testindex.html
_description:
PURPOSE:
This test will check that Firefox can render a basic web page.
STEPS:
1. Select Test to launch Firefox and view the test web page.
VERIFICATION:
Did the Ubuntu Test page load correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/firefox-flash
depends: software/firefox
requires: package.name == 'firefox'
command: firefox $PLAINBOX_PROVIDER_DATA/websites/flashtest.html
_description:
PURPOSE:
This test will check that Firefox can run flash applications. Note: this may
require installing additional software to successfully complete.
STEPS:
1. Select Test to launch Firefox and view a sample Flash test.
VERIFICATION:
Did you see the text?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/firefox-flash-video
depends: software/firefox-flash
requires: package.name == 'firefox'
command: firefox $PLAINBOX_PROVIDER_DATA/websites/flashvideo.html
_description:
PURPOSE:
This test will check that Firefox can play a Flash video. Note: this may
require installing additional software to successfully complete.
STEPS:
1. Select Test to launch Firefox and view a short flash video.
VERIFICATION:
Did the video play correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/firefox-totem
depends: software/firefox
requires:
package.name == 'firefox'
package.name == 'gstreamer0.10-ffmpeg'
command: firefox $PLAINBOX_PROVIDER_DATA/video/Quicktime_Video.mov
_description:
PURPOSE:
This test will check that Firefox can play a Quicktime (.mov) video file.
Note: this may require installing additional software to successfully
complete.
STEPS:
1. Select Test to launch Firefox with a sample video.
VERIFICATION:
Did the video play using a plugin?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/empathy-facebook_chat
requires: package.name == "empathy"
command: empathy
_description:
PURPOSE:
This test will check that Empathy messaging client works.
STEPS:
1. Select Test to launch Empathy.
2. Configure it to connect to the Facebook Chat service.
3. Once you have completed the test, please quit Empathy to continue here.
VERIFICATION:
Were you able to connect correctly and send/receive messages?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/empathy-google_talk
requires: package.name == "empathy"
command: empathy
_description:
PURPOSE:
This test will check that Empathy messaging client works.
STEPS:
1. Select Test to launch Empathy.
2. Configure it to connect to the Google Talk (gtalk) service.
3. Once you have completed the test, please quit Empathy to continue here.
VERIFICATION:
Were you able to connect correctly and send/receive messages?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/empathy-jabber
requires: package.name == "empathy"
command: empathy
_description:
PURPOSE:
This test will check that Empathy messaging client works.
STEPS:
1. Select Test to launch Empathy.
2. Configure it to connect to the Jabber service.
3. Once you have completed the test, please quit Empathy to continue here.
VERIFICATION:
Were you able to connect correctly and send/receive messages?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/empathy-aim
requires: package.name == "empathy"
command: empathy
_description:
PURPOSE:
This test will check that Empathy messaging client works.
STEPS:
1. Select Test to launch Empathy.
2. Configure it to connect to the AOL Instant Messaging (AIM) service.
3. Once you have completed the test, please quit Empathy to continue here.
VERIFICATION:
Were you able to connect correctly and send/receive messages?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/empathy-msn
requires: package.name == "empathy"
command: empathy
_description:
PURPOSE:
This test will check that Empathy messaging client works.
STEPS:
1. Select Test to launch Empathy.
2. Configure it to connect to the Microsoft Network (MSN) service.
3. Once you have completed the test, please quit Empathy to continue here.
VERIFICATION:
Were you able to connect correctly and send/receive messages?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/evolution-pop3
requires: package.name == "evolution"
command: evolution
_description:
PURPOSE:
This test will check that Evolution works.
STEPS:
1. Commence the test to launch Evolution.
2. Configure it to connect to a POP3 account.
VERIFICATION:
Were you able to receive and read e-mail correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/evolution-imap
requires: package.name == "evolution"
command: evolution
_description:
PURPOSE:
This test will check that Evolution works.
STEPS:
1. Commence the test to launch Evolution.
2. Configure it to connect to a IMAP account.
VERIFICATION:
Were you able to receive and read e-mail correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/evolution-smtp
requires: package.name == "evolution"
command: evolution
_description:
PURPOSE:
This test will check that Evolution works.
STEPS:
1. Commence the test to launch Evolution.
2. Configure it to connect to a SMTP account.
VERIFICATION:
Were you able to send e-mail without errors?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/gcalctool
requires: package.name == "gcalctool"
command: gcalctool
_description:
PURPOSE:
This test checks that gcalctool (Calculator) works.
STEPS:
Commence the test to open the calculator.
VERIFICATION:
Did it launch correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/gcalctool-functions
depends: software/gcalctool
requires: package.name == "gcalctool"
command: gcalctool
_description:
PURPOSE:
This test checks that gcalctool (Calculator) works.
STEPS:
Commence the test to open the calculator and perform:
1. Simple math functions (+,-,/,*)
2. Nested math functions ((,))
3. Fractional math
4. Decimal math
VERIFICATION:
Did the functions perform as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/gcalctool-memory
depends: software/gcalctool
requires: package.name == "gcalctool"
command: gcalctool
_description:
PURPOSE:
This test checks that gcalctool (Calculator) works.
STEPS:
Commence the test to open the calculator and perform:
1. Memory set
2. Memory reset
3. Memory last clear
4. Memory clear
VERIFICATION:
Did the functions perform as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/gcalctool-clipboard
depends: software/gcalctool
requires: package.name == "gcalctool"
command: gcalctool
_description:
PURPOSE:
This test checks that gcalctool (Calculator) works.
STEPS:
Commence the test to open the calculator and perform:
1. Cut
2. Copy
3. Paste
VERIFICATION:
Did the functions perform as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/gedit
requires: package.name == "gedit"
command: gedit
_description:
PURPOSE:
This test checks that gedit works.
STEPS:
1. Commence the test to open gedit.
2. Enter some text and save the file (make a note of the file name you use), then close gedit.
VERIFICATION:
Did this perform as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/gedit-read
depends: software/gedit
requires: package.name == "gedit"
command: gedit
_description:
PURPOSE:
This test checks that gedit works.
STEPS:
1. Commence the test to open gedit, and re-open the file you created previously.
2. Edit then save the file, then close gedit.
VERIFICATION:
Did this perform as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::user_apps
id: software/gnome-terminal
requires: package.name == "gnome-terminal"
command: gnome-terminal
_description:
PURPOSE:
This test will check that Gnome Terminal works.
STEPS:
1. Commence the test to open Terminal.
2. Type 'ls' and press enter. You should see a list of files and folder in your home directory.
3. Close the terminal window.
VERIFICATION:
Did this perform as expected?
plainbox-provider-checkbox-0.25/jobs/graphics.txt.in 0000664 0001750 0001750 00000056676 12646152433 024023 0 ustar sylvain sylvain 0000000 0000000 id: graphics/generator_driver_version
requires: device.category == 'VIDEO'
_description: Driver version tests
_summary: Driver version tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_driver_version_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
command: graphics_driver
estimated_duration: 0.500
_description: Parses Xorg.0.Log and discovers the running X driver and version for the $product graphics card
_summary: Test X driver/version for $product
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/xorg-version
requires: package.name == "x11-utils"
command: xdpyinfo | grep "^X.Org version" | cut -d ':' -f 2 | tr -d ' '
estimated_duration: 0.018
_description: Test to output the Xorg version
_summary: Test Xorg version
id: graphics/generator_resolution-change
requires: device.category == 'VIDEO'
_description: Resolution change tests
_summary: Resolution change tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: manual
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_resolution-change_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: graphics/xorg-version
_summary: Test changing resolution for $product
_description:
PURPOSE:
This test will verify that the GUI is usable after manually changing resolution on the $product graphics card.
STEPS:
1. Select the $product graphics card (a reboot may be necessary)
2. Open the Displays application
3. Select a new resolution from the dropdown list
4. Click on Apply
5. Select the original resolution from the dropdown list
6. Click on Apply
VERIFICATION:
Did the resolution on the $product graphics card change as expected?
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/xorg-process
requires:
package.name == 'xorg'
package.name == 'procps'
command: pgrep -f '/usr/bin/X' >/dev/null
estimated_duration: 0.100
_description: Test that the X process is running.
_summary: Test that the X process is running.
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/xorg-failsafe
requires: package.name == 'xorg'
command: ! test -e /var/log/Xorg.failsafe.log
estimated_duration: 0.030
_description: Test that the X is not running in failsafe mode.
_summary: Test that X is not in failsafe mode.
id: graphics/generator_resolution
requires: device.category == 'VIDEO'
_description: Default resolution tests
_summary: Default resolution tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_resolution_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires:
device.category == 'VIDEO'
package.name == 'zenity'
command: resolution_test | zenity --text-info
estimated_duration: 10.00
_summary: Test default resolution for $product
_description:
PURPOSE:
This test will verify the default display resolution on the $product graphics card.
STEPS:
1. Click "Test".
2. Confirm that the resolution shown in the text window is acceptable for your display.
VERIFICATION:
Is the resolution shown acceptable for your display on $product graphics card?
EOF
id: graphics/generator_screen_resolution
requires: device.category == 'VIDEO'
_description: Default resolution tests
_summary: Default resolution tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_screen_resolution_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires:
device.category == 'VIDEO'
package.name == 'qmlscene'
command: qmlscene -qt5 --transparent --fullscreen $PLAINBOX_PROVIDER_DATA/resolution_test.qml
estimated_duration: 10.0
_summary: Test default resolution for $product
_description:
PURPOSE:
This test will verify the default display resolution on the $product graphics card
STEPS:
1. Click on Test to display the screen resolution overlay for 5 seconds.
VERIFICATION:
Is this acceptable for your display on the $product graphics card?
EOF
id: graphics/generator_minimum_resolution
requires: device.category == 'VIDEO'
_description: Minimum resolution tests
_summary: Minimum resolution tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_minimum_resolution_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires:
device.category == 'VIDEO'
command: resolution_test --horizontal 800 --vertical 600
estimated_duration: 0.331
_summary: Test that $product meets minimum resolution requirement
_description:
Ensure the current resolution meets or exceeds the recommended minimum
resolution (800x600) on the $product graphics card. See here for details:
https://help.ubuntu.com/community/Installation/SystemRequirements
EOF
id: graphics/generator_maximum_resolution
requires: device.category == 'VIDEO'
_description: Maximum resolution tests
_summary: Maximum resolution tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: graphics/`echo ${index}`_maximum_resolution_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
requires:
device.category == 'VIDEO'
package.name == 'zenity'
command:
maxi="\$(xrandr -q |grep -A 1 "connected\( primary\)* [0-9]" |tail -1 |awk '{print \$1}')"
now="\$(python3 -c 'from gi.repository import Gdk; screen=Gdk.Screen.get_default(); geo = screen.get_monitor_geometry(screen.get_primary_monitor()); print(geo.width, "x", geo.height, sep="")')"
test "\$maxi" != "\$now" && notify="\nPlease switch to the maximum resolution \nfor every graphic tests"
zenity --info --text "Maximum resolution: \$maxi\nCurrent resolution: \$now \$notify"
estimated_duration: 10.0
_summary: Test maximum supported resolution for $product
_description:
PURPOSE:
This test will verify the maximum supported resolution on the $product graphics card.
STEPS:
1. Select the $product graphics card (a reboot may be necessary)
2. Consult the system's specifications and locate the screen's maximum supported resolution.
3. Click on Test to display the maximum resolution that can be used by Ubuntu on the current display.
VERIFICATION:
Is this the maximum resolution for the display connected to the $product graphics card?
EOF
id: graphics/generator_modes
requires: device.category == 'VIDEO'
_description: Mode tests
_summary: Mode tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: graphics/`echo ${index}`_modes_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: graphics_modes_info
estimated_duration: 0.250
_description: Collect info on graphics modes (screen resolution and refresh rate) for $product
_summary: Test graphic modes info for $product
EOF
id: graphics/generator_color_depth
requires: device.category == 'VIDEO'
_description: Color depth tests
_summary: Color depth tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: graphics/`echo ${index}`_color_depth_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: color_depth_info
estimated_duration: 0.150
_description: Collect info on color depth and pixel format for $product
_summary: Test color depth info for $product
EOF
id: graphics/generator_fresh_rate
requires: device.category == 'VIDEO'
_description: Refresh rate tests
_summary: Refresh rate tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: graphics/`echo ${index}`_fresh_rate_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: fresh_rate_info
_description: Collect info on fresh rate for $product.
_summary: Test refresh rate for $product
EOF
id: graphics/generator_graphic_memory
requires: device.category == 'VIDEO'
_description: Graphic memory tests
_summary: Graphic memory tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: graphics/`echo ${index}`_graphic_memory_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: graphic_memory_info
_description: Collect info on graphic memory for $product.
_summary: Test graphic memory info for $product.
EOF
id: graphics/generator_video
requires: device.category == 'VIDEO'
_description: Display video test
_summary: Display video test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: graphics/`echo ${index}`_video_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
requires:
package.name == 'xorg'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
command: gst_pipeline_test -t 2 'videotestsrc ! videoconvert ! autovideosink' || gst_pipeline_test -t 2 'videotestsrc ! ffmpegcolorspace ! autovideosink'
_summary: Test that video can be displayed with ${product}
_description:
PURPOSE:
This test will test the default display with a sample video
STEPS:
1. Click "Test" to display a video test.
VERIFICATION:
Do you see color bars and static?
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/VESA_drivers_not_in_use
command: cat /var/log/Xorg.0.log | perl -e '$a=0;while(<>){$a++ if /Loading.*vesa_drv\.so/;$a-- if /Unloading.*vesa/&&$a}exit 1 if $a'
estimated_duration: 0.011
_description: Check that VESA drivers are not in use
_summary: Test that VESA drivers are not in use
id: graphics/generator_cycle_resolution
requires: device.category == 'VIDEO'
_description: Resolution cycling tests
_summary: Resolution cycling tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_cycle_resolution_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'xorg'
depends: graphics/VESA_drivers_not_in_use
command: xrandr_cycle --screenshot-dir $PLAINBOX_SESSION_SHARE
estimated_duration: 250.000
_summary: Test resolution cycling for $product
_description:
PURPOSE:
This test cycles through the detected video modes for the $product graphics card
STEPS:
1. Click "Test" to start cycling through the video modes
VERIFICATION:
Did the screen appear to be working for each mode?
EOF
id: graphics/generator_rotation
requires: device.category == 'VIDEO'
_description: Rotation tests
_summary: Rotation tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_rotation_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: graphics/xorg-version
command: rotation_test_using_dbus
estimated_duration: 20.000
_summary: Test rotation for $product
_description:
PURPOSE:
This test will test display rotation on the $product graphics card
STEPS:
1. Click "Test" to test display rotation. The display will be rotated every 4 seconds.
2. Check if all rotations (normal right inverted left) took place without permanent screen corruption
VERIFICATION:
Did the display rotation take place without without permanent screen corruption?
EOF
id: graphics/generator_compiz_check
requires: device.category == 'VIDEO'
_description: Compiz support tests
_summary: Compiz support tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_compiz_check_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'nux-tools'
command: ! /usr/lib/nux/unity_support_test -c -p 2>&1 | ansi_parser | grep -e ":\(\s\+\)no$" -ie "error"
estimated_duration: 0.130
_description: Check that $product hardware is able to run compiz
_summary: Test Compiz support for $product
EOF
id: graphics/generator_unity_support
requires: device.category == 'VIDEO'
_description: Unity support tests
_summary: Unity support tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_unity_support_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'nux-tools'
command: ! /usr/lib/nux/unity_support_test -p 2>&1 | ansi_parser | grep -e ":\(\s\+\)no$" -ie "error"
estimated_duration: 0.131
_description: Check that $product hardware is able to run Unity 3D
_summary: Test Unity 3D support for $product
EOF
id: graphics/generator_glxgears
requires: device.category == 'VIDEO'
_description: glxgears tests
_summary: glxgears tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_glxgears_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'mesa-utils'
command: glxgears; true
_summary: Test that glxgears works for $product
_description:
PURPOSE:
This test tests the basic 3D capabilities of your $product video card
STEPS:
1. Click "Test" to execute an OpenGL demo. Press ESC at any time to close.
2. Verify that the animation is not jerky or slow.
VERIFICATION:
1. Did the 3d animation appear?
2. Was the animation free from slowness/jerkiness?
EOF
id: graphics/generator_3d_window_open_close
requires: device.category == 'VIDEO'
_description: 3D window open/close tests
_summary: 3D window open/close tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_3d_window_open_close_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'mesa-utils'
command: window_test -t open-close -i 10
estimated_duration: 60.525
_description: Open and close a 3D window multiple times on the $product video card
_summary: Test 3D window open/close for $product
EOF
id: graphics/generator_3d_window_suspend_resume
requires: device.category == 'VIDEO'
_description: 3D window with suspend/resume tests
_summary: 3D window with suspend/resume tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_3d_window_suspend_resume_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'mesa-utils'
command: window_test -t suspend-resume -i 10
estimated_duration: 121.00
_description: Open, suspend resume and close a 3D window multiple times on the $product video card
_summary: Test a 3D window with suspend/resume for $product
EOF
id: graphics/generator_multi_3d_windows_open_close
requires: device.category == 'VIDEO'
_description: Multiple 3D window open/close
_summary: Multiple 3D window open/close tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_multi_3d_windows_open_close_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'mesa-utils'
command: window_test -t open-close-multi -i 10 -w 4
estimated_duration: 60.000
_description: Open and close 4 3D windows multiple times on the $product video card
_summary: Test Multi 3D window open/close for $product
EOF
id: graphics/generator_3d_window_move
requires: device.category == 'VIDEO'
_description: 3D window movement
_summary: 3D window movement tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_3d_window_move_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires:
package.name == 'mesa-utils'
package.name == 'wmctrl'
command: window_test -t move
estimated_duration: 50.000
_description: Move a 3D window around the screen on the $product video card
_summary: Test 3D window movement for $product
EOF
id: graphics/generator_screenshot
requires: device.category == 'VIDEO'
_description: screenshot tests
_summary: screenshot tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_screenshot_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'fswebcam'
command: set -o pipefail; camera_test still --device=/dev/external_webcam -f ${PLAINBOX_SESSION_SHARE}/screenshot_${index}.jpg -q 2>&1 | ansi_parser
_summary: Test grabbing a screenshot for $product
_description:
PURPOSE:
Take a screengrab of the current screen (logged on Unity desktop) as produced by the $product graphics card
STEPS:
1. Take picture using USB webcam
VERIFICATION:
Review attachment manually later
EOF
id: graphics/generator_screenshot.jpg
requires: device.category == 'VIDEO'
_description: screenshot attachment tests
_summary: screenshot attachment tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: attachment
category_id: 2013.com.canonical.plainbox::graphics
id: `echo ${index}`_screenshot_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`.jpg
depends: graphics/`echo ${index}`_screenshot_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
command: base64 ${PLAINBOX_SESSION_SHARE}/screenshot_${index}.jpg
_description: Attaches the screenshot captured in graphics/screenshot for the $product graphics card.
_summary: Attach results of screenshot test for $product
EOF
id: graphics/generator_screenshot_fullscreen_video
requires: device.category == 'VIDEO'
_description: full screen video screenshot tests
_summary: full screen video screenshot tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_screenshot_fullscreen_video_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'fswebcam'
command:
[ -f ${PLAINBOX_PROVIDER_DATA}/video/Ogg_Theora_Video.ogv ] || { echo "Video file not found"; exit 1; }
gsettings set org.gnome.totem repeat true
totem --fullscreen ${PLAINBOX_PROVIDER_DATA}/video/Ogg_Theora_Video.ogv 2>/dev/null &
set -o pipefail
sleep 15 && camera_test still --device=/dev/external_webcam -f ${PLAINBOX_SESSION_SHARE}/screenshot_fullscreen_video_${index}.jpg -q 2>&1 | ansi_parser
sleep 5 && totem --quit 2>/dev/null
gsettings set org.gnome.totem repeat false
_summary: Test FSV screenshot for $product
_description:
PURPOSE:
Take a screengrab of the current screen during fullscreen video playback using the $product graphics card
STEPS:
1. Start a fullscreen video playback
2. Take picture using USB webcam after a few seconds
VERIFICATION:
Review attachment manually later
EOF
id: graphics/generator_switch_card
requires: device.category == 'VIDEO'
_description: GPU switch prompt tests
_summary: GPU switch prompt tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: manual
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/`echo ${index}`_switch_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
_summary: Test GPU switching for $product
_description:
PURPOSE:
Manually switch to the $product card.
STEPS:
1. If your system is already running with the $product card, then please mark this test as "passed" and proceed.
2. Using the appropriate tool (either NVidia settings or AMD Control Center), switch your system to use the $product graphics card. This will require restarting your session.
3. Once the session restarts, please restart this testing program and select "continue" when prompted for a resume action.
4. Don't answer the verification question until the system has restarted with the $product card enabled.
VERIFICATION:
Is the system using the $product card now?
EOF
id: graphics/generator_screenshot_fullscreen_video.jpg
requires: device.category == 'VIDEO'
_description: full screen video attachment tests
_summary: full screen video attachment tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: attachment
category_id: 2013.com.canonical.plainbox::graphics
id: `echo ${index}`_screenshot_fullscreen_video_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`.jpg
depends: graphics/`echo ${index}`_screenshot_fullscreen_video_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
command: base64 ${PLAINBOX_SESSION_SHARE}/screenshot_fullscreen_video_${index}.jpg
_summary: Attach results of FSV screenshot test for $product
_description: Attaches the screenshot captured in graphics/screenshot_fullscreen_video for the $product graphics card
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/screen-capture-internal
_summary: Obtains a simple screen capture
estimated_duration: 1.0
requires: package.name == 'gnome-screenshot'
command: gnome-screenshot --file ${PLAINBOX_SESSION_SHARE}/screen-capture.png
_description: Obtains a simple screen capture using gnome-screenshot if present
plugin: attachment
category_id: 2013.com.canonical.plainbox::graphics
id: screen-capture-internal.png
_summary: Attaches a simple screen capture
estimated_duration: 1.0
depends: graphics/screen-capture-internal
command: [ -f ${PLAINBOX_SESSION_SHARE}/screen-capture.png ] && base64 ${PLAINBOX_SESSION_SHARE}/screen-capture.png
_description: Attaches the simple screen capture file
unit: job
id: graphics_card_resource
plugin: resource
category_id: 2013.com.canonical.plainbox::graphics
command: graphics_card_resource
unit: template
template-unit: job
template-resource: graphics_card_resource
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: "graphics/{index}_screen-capture-internal_{product}"
_summary: Obtains a simple screen capture of {product}
estimated_duration: 1.0
requires: package.name == 'gnome-screenshot'
command: gnome-screenshot --file $PLAINBOX_SESSION_SHARE/screen-capture-{index}.png
_description: Obtains a simple screen capture of {product} using gnome-screenshot if present
unit: template
template-unit: job
template-resource: graphics_card_resource
plugin: attachment
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/{index}_screen-capture-internal_{product}.png
depends: "graphics/{index}_screen-capture-internal_{product}"
_summary: Attaches a simple screen capture of {product}
estimated_duration: 1.0
command: [ -f $PLAINBOX_SESSION_SHARE/screen-capture-{index}.png ] && base64 $PLAINBOX_SESSION_SHARE/screen-capture-{index}.png
_description: Attaches the simple screen capture file of {product}
plainbox-provider-checkbox-0.25/jobs/networking.txt.in 0000664 0001750 0001750 00000005603 12646152433 024372 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::networking
id: networking/gateway_ping
depends: ethernet/detect
command: gateway_ping_test
estimated_duration: 2.000
_description: Tests whether the system has a working Internet connection.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::networking
id: networking/info_device{__index__}_{interface}
_summary: Network Information of device {__index__} ({interface})
estimated_duration: 1.0
requires: device.path == '{path}'
command: network_info {interface} | zenity --text-info --title="{interface}"
_description:
PURPOSE:
This test will check the network device {__index__} ({interface})
STEPS:
1. Click "Test" to verify the information for this network device
VERIFICATION:
Is this correct?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::networking
id: networking/modem_connection
command: network_check
_description:
PURPOSE:
This test will check that a DSL modem can be configured and connected.
STEPS:
1. Connect the telephone line to the computer
2. Click on the Network icon on the top panel.
3. Select "Edit Connections"
4. Select the "DSL" tab
5. Click on "Add" button
6. Configure the connection parameters properly
7. Click "Test" to verify that it's possible to establish an HTTP connection
VERIFICATION:
Did a notification show and was the connection correctly established?
plugin: shell
category_id: 2013.com.canonical.plainbox::networking
id: networking/ping
command: gateway_ping_test $CHECKBOX_SERVER
_description:
Automated test case to verify availability of some system on the network using ICMP ECHO packets.
plugin: shell
category_id: 2013.com.canonical.plainbox::networking
id: networking/http
command: wget -SO /dev/null http://$TRANSFER_SERVER
_description:
Automated test case to make sure that it's possible to download files through HTTP
plugin: shell
category_id: 2013.com.canonical.plainbox::networking
id: networking/ntp
requires: package.name == 'ntpdate'
user: root
command: network_ntp_test
_description: Test to see if we can sync local clock to an NTP server
plugin: shell
category_id: 2013.com.canonical.plainbox::networking
id: networking/ssh
requires: package.name == 'openssh-client'
command: if [ $CHECKBOX_SERVER ]; then ssh -q -o 'StrictHostKeyChecking=no' -o "UserKnownHostsFile=/tmp/ssh_test_$$" -l ubuntu $CHECKBOX_SERVER "uname -a" && rm /tmp/ssh_test_$$; fi
_description: Verify that an installation of checkbox-server on the network can be reached over SSH.
plugin: shell
category_id: 2013.com.canonical.plainbox::networking
id: networking/printer
requires: package.name == 'cups-client'
command: network_printer_test -s $CHECKBOX_SERVER
_description: Try to enable a remote printer on the network and print a test page.
plainbox-provider-checkbox-0.25/jobs/benchmarks.txt.in 0000664 0001750 0001750 00000030011 12646152433 024307 0 ustar sylvain sylvain 0000000 0000000 plugin: local
_summary: Benchmark for each disk
id: benchmarks/disk/hdparm-read
requires: device.category == 'DISK'
estimated_duration: 1.0
_description: Raw read timing benchmark of each disk using hdparm.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=DISK"'
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/disk/hdparm-read_`ls /sys$path/block`
estimated_duration: 15.0
requires: device.path == "$path"
user: root
command: hdparm -t /dev/`ls /sys$path/block | sed 's|!|/|'` | sed -e :a -e '$!N;s/\n/ /;ta' | sed 's/.*= *//'
description: This test runs hdparm timing of device reads as a benchmark for $path
EOF
plugin: local
_summary: Benchmark for each disk
id: benchmarks/disk/hdparm-cache-read
estimated_duration: 1.0
requires: device.category == 'DISK'
_description: Cached read timing benchmark of each disk using hdparm.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=DISK"'
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/disk/hdparm-cache-read_`ls /sys$path/block`
estimated_duration: 10.0
requires: device.path == "$path"
user: root
command: hdparm -T /dev/`ls /sys$path/block | sed 's|!|/|'` | sed -e :a -e '$!N;s/\n/ /;ta' | sed 's/.*= *//'
description: This test runs hdparm timing of cache reads as a benchmark for $path
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/gtkperf
depends: graphics/xorg-version
requires: package.name == 'gtkperf'
command: python3 -c 'import re,sys,subprocess; (s, o) = subprocess.getstatusoutput("gtkperf -a"); [sys.exit(1) for i in [s] if s]; m = re.search("Total time:\s+(.*)\n", o); [print(i.group(1)+" Seconds") for i in [m] if m]'
estimated_duration: 30.000
_description:
Run gtkperf to make sure that GTK based test cases work
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/render-bench
requires: package.name == 'render-bench'
command: /usr/bin/time -f "%e Seconds" render_bench 2>&1 >/dev/null
estimated_duration: 52.000
_description: Run Render-Bench XRender/Imlib2 benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/qgears2-Xrender-gearsfancy
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="qgears2.render-backend=1; qgears2.test-mode=0" pts_run qgears2
estimated_duration: 180.000
_description: Run Qgears2 XRender Extension gearsfancy benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/qgears2-Xrender-compo
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="qgears2.render-backend=1; qgears2.test-mode=2" pts_run qgears2
estimated_duration: 31.500
_description: Run Qgears2 XRender Extension image scaling benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/qgears2-gl-gearsfancy
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="qgears2.render-backend=2; qgears2.test-mode=0" pts_run qgears2
estimated_duration: 52.000
_description: Run Qgears2 OpenGL gearsfancy benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/qgears2-gl-compo
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="qgears2.render-backend=2; qgears2.test-mode=2" pts_run qgears2
estimated_duration: 23.000
_description: Run Qgears2 OpenGL image scaling benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/glmark2-es2
requires:
package.name == 'glmark2-es2'
'arm' in cpuinfo.type
command:
glmark2-es2 2>&1 | sed -e :a -e '$!N;s/\n/ /;ta' | sed -E 's/.*(Score:\s+[0-9]+).*/\1/'
_description: Run GLmark2-ES2 benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/glmark2
requires:
package.name == 'glmark2'
cpuinfo.platform in ("i386", "x86_64")
command:
glmark2 2>&1 | sed -e :a -e '$!N;s/\n/ /;ta' | sed -E 's/.*(Score:\s+[0-9]+).*/\1/'
estimated_duration: 306.000
_description: Run GLmark2 benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/unigine-sanctuary
requires: package.name == 'phoronix-test-suite'
command: pts_run unigine-sanctuary
_description: Run Unigine Santuary benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/unigine-tropics
requires: package.name == 'phoronix-test-suite'
command: pts_run unigine-tropics
_description: Run Unigine Tropics benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/unigine-heaven
requires: package.name == 'phoronix-test-suite'
command: pts_run unigine-heaven
_description: Run Unigine Heaven benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/lightsmark
requires: package.name == 'phoronix-test-suite'
command: pts_run lightsmark
_description: Run Lightsmark benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/memory/cachebench-read
estimated_duration: 160.0
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="cachebench.test=0" pts_run cachebench
_description: Run Cachebench Read benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/memory/cachebench-write
estimated_duration: 130.0
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="cachebench.test=1" pts_run cachebench
_description: Run Cachebench Write benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/memory/cachebench-read-modify-write
estimated_duration: 140.0
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="cachebench.test=2" pts_run cachebench
_description: Run Cachebench Read / Modify / Write benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/memory/stream-copy
estimated_duration: 6.0
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="stream.run-type=0" pts_run stream
_description: Run Stream Copy benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/memory/stream-scale
estimated_duration: 6.0
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="stream.run-type=1" pts_run stream
_description: Run Stream Scale benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/memory/stream-add
estimated_duration: 5.0
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="stream.run-type=2" pts_run stream
_description: Run Stream Add benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/memory/stream-triad
estimated_duration: 4.0
requires: package.name == 'phoronix-test-suite'
command: PRESET_OPTIONS="stream.run-type=3" pts_run stream
_description: Run Stream Triad benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/network/network-loopback
requires: package.name == 'phoronix-test-suite'
command: pts_run network-loopback
estimated_duration: 85.0
_description: Run Network Loopback benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/network/wifi_time_to_reconnect
requires: device.category == 'WIRELESS'
command: wifi_time2reconnect
_description: Check the time needed to reconnect to a WIFI access point
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/processor/encode-mp3
estimated_duration: 140.0
requires: package.name == 'phoronix-test-suite'
command: pts_run encode-mp3
_description: Run Encode MP3 benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/processor/x264
estimated_duration: 400.0
requires: package.name == 'phoronix-test-suite'
command: pts_run x264
_description: Run x264 H.264/AVC encoder benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/processor/gnupg
requires: package.name == 'phoronix-test-suite'
command: pts_run gnupg
_description: Run GnuPG benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/processor/compress-pbzip2
estimated_duration: 90.0
requires: package.name == 'phoronix-test-suite'
command: pts_run compress-pbzip2
_description: Run Compress PBZIP2 benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/processor/compress-7zip
estimated_duration: 1400
requires: package.name == 'phoronix-test-suite'
command: pts_run compress-7zip
_description: Run Compress 7ZIP benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/processor/n-queens
estimated_duration: 330.0
requires: package.name == 'phoronix-test-suite'
command: pts_run n-queens
_description: Run N-Queens benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/processor/himeno
estimated_duration: 75.0
requires: package.name == 'phoronix-test-suite'
command: pts_run himeno
_description: Run Himeno benchmark
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/system/cpu_on_idle
estimated_duration: 10.0
requires: package.name == 'sysstat'
command: iostat -x -m 1 10 | python3 -c 'import sys, re; lines="".join(sys.stdin.readlines()); l=[float(n) for n in (re.findall("idle\n.*?(\S+)\n", lines))]; print(sum(l)/len(l),"%")'
_description: CPU utilization on an idle system.
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/system/disk_on_idle
estimated_duration: 10.0
requires: package.name == 'sysstat'
command: iostat -x -m 1 10 | python3 -c 'import sys, re; lines="".join(sys.stdin.readlines()); l=[float(n) for n in (re.findall("util\n.*?(\S+)\n", lines))]; print(sum(l)/len(l),"%")'
_description: Disk utilization on an idle system.
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/gputest_furmark_fullscreen_1920x1080
requires:
package.name == 'gputest'
cpuinfo.platform == 'x86_64'
command: gputest_benchmark fur --width 1920 --height 1080 -f
estimated_duration: 75.000
_description:
Run a stress test based on FurMark (OpenGL 2.1 or 3.2)
Fullscreen 1920x1080 no antialiasing
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/gputest_furmark_windowed_1024x640
requires:
package.name == 'gputest'
cpuinfo.platform == 'x86_64'
command: gputest_benchmark fur
estimated_duration: 75.000
_description:
Run a stress test based on FurMark (OpenGL 2.1 or 3.2)
Windowed 1024x640 no antialiasing
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/gputest_gimark_fullscreen_1920x1080
requires:
package.name == 'gputest'
cpuinfo.platform == 'x86_64'
command: gputest_benchmark gi --width 1920 --height 1080 -f
estimated_duration: 75.00
_description:
Run GiMark, a geometry instancing test (OpenGL 3.3)
Fullscreen 1920x1080 no antialiasing
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/gputest_gimark_windowed_1024x640
requires:
package.name == 'gputest'
cpuinfo.platform == 'x86_64'
command: gputest_benchmark gi
estimated_duration: 75.500
_description:
Run GiMark, a geometry instancing test (OpenGL 3.3)
Windowed 1024x640 no antialiasing
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/gputest_tessmark_fullscreen_1920x1080
requires:
package.name == 'gputest'
cpuinfo.platform == 'x86_64'
command: gputest_benchmark tess --width 1920 --height 1080 -f
estimated_duration: 75.000
_description:
Run a tessellation test based on TessMark (OpenGL 4.0)
Fullscreen 1920x1080 no antialiasing
plugin: shell
category_id: 2013.com.canonical.plainbox::benchmarks
id: benchmarks/graphics/gputest_tessmark_windowed_1024x640
requires:
package.name == 'gputest'
cpuinfo.platform == 'x86_64'
command: gputest_benchmark tess
_description:
Run a tessellation test based on TessMark (OpenGL 4.0)
Windowed 1024x640 no antialiasing
plainbox-provider-checkbox-0.25/jobs/wireless.txt.in 0000664 0001750 0001750 00000061013 12646152433 024035 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_scanning
requires:
package.name == 'network-manager'
device.category == 'WIRELESS'
command:
rfkill unblock wlan wifi
if rfkill list wlan wifi | grep -q 'Hard blocked: yes'; then
echo "Hard block is applied to WiFi device. Please remove and retest."
exit 1
fi
wireless_networks=`(nmcli -f SSID dev wifi list 2>/dev/null || nmcli -f SSID dev wifi)`
if [ `echo "$wireless_networks" | wc -l` -gt 1 ]; then
echo "Wireless networks discovered: "
echo "$wireless_networks"
exit 0
fi
echo "No wireless networks discovered."
exit 1
estimated_duration: 0.645
_description: Wireless scanning test. It scans and reports on discovered APs.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/info_automated
requires:
package.name == 'network-manager'
device.category == 'WIRELESS'
command: udev_resource | filter_templates -w "category=WIRELESS" | awk "/interface: / { print \$2 }" | xargs -n 1 network_info
estimated_duration: 1.2
_description:
This is an automated test to gather some info on the current state of your wireless devices. If no devices are found, the test will exit with an error.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection
command: network_check
estimated_duration: 120.0
requires: device.category == 'WIRELESS'
_description:
PURPOSE:
This test will check your wireless connection.
STEPS:
1. Click on the Network icon in the panel.
2. Select a network below the 'Wireless networks' section.
3. Click "Test" to verify that it's possible to establish an HTTP connection.
VERIFICATION:
Did a notification show and was the connection correctly established?
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_wpa_bg
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_BG_SSID WPA_BG_PSK
command:
trap "nmcli con delete id $WPA_BG_SSID" EXIT
if create_connection wifi $WPA_BG_SSID --security=wpa --key=$WPA_BG_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11b/g protocols.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_bg
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_BG_SSID
command:
trap "nmcli con delete id $OPEN_BG_SSID" EXIT
if create_connection wifi $OPEN_BG_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11b/g protocols.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_wpa_n
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_N_SSID WPA_N_PSK
command:
trap "nmcli con delete id $WPA_N_SSID" EXIT
if create_connection wifi $WPA_N_SSID --security=wpa --key=$WPA_N_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11n protocol.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_n
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_N_SSID
command:
trap "nmcli con delete id $OPEN_N_SSID" EXIT
if create_connection wifi $OPEN_N_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11n protocol.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_wpa_ac
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: WPA_AC_SSID WPA_AC_PSK
command:
trap "nmcli con delete id $WPA_AC_SSID" EXIT
if create_connection wifi $WPA_AC_SSID --security=wpa --key=$WPA_AC_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11ac protocol.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_ac
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: OPEN_AC_SSID
command:
trap "nmcli con delete id $OPEN_AC_SSID" EXIT
if create_connection wifi $OPEN_AC_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11ac protocol.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_wpa_bg_manual
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID ROUTER_PSK
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID --security=wpa --key=$ROUTER_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 120.0
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11b/g protocols.
STEPS:
1. Open your router's configuration tool
2. Change the settings to only accept connections on the B and G wireless bands
3. Make sure the SSID is set to the contents of the ROUTER_SSID environment variable
4. Change the security settings to use WPA2 and ensure the PSK matches what is set in the ROUTER_PSK environment variable
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_bg_manual
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 120.0
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using
no security and the 802.11b/g protocols.
STEPS:
1. Open your router's configuration tool
2. Change the settings to only accept connections on the B and G wireless bands
3. Make sure the SSID is set to the contents of the ROUTER_SSID environment variable
4. Change the security settings to use no security
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_wpa_n_manual
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
IEEE_80211.band_5GHz == 'supported'
user: root
environ: ROUTER_SSID ROUTER_PSK
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID --security=wpa --key=$ROUTER_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 120.0
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11n protocols.
STEPS:
1. Open your router's configuration tool
2. Change the settings to only accept connections on the N wireless band
3. Make sure the SSID is set to the contents of the ROUTER_SSID environment variable
4. Change the security settings to use WPA2 and ensure the PSK matches what is set in the ROUTER_PSK environment variable
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_n_manual
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
IEEE_80211.band_5GHz == 'supported'
user: root
environ: ROUTER_SSID
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 120.0
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using
no security and the 802.11n protocol.
STEPS:
1. Open your router's configuration tool
2. Change the settings to only accept connections on the N wireless band
3. Make sure the SSID is set to the contents of the ROUTER_SSID environment variable
4. Change the security settings to use no security
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_wpa_ac_manual
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
IEEE_80211.ac == 'supported'
user: root
environ: ROUTER_SSID ROUTER_PSK
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID --security=wpa --key=$ROUTER_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 120.0
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11ac protocol.
STEPS:
1. Open your router's configuration tool
2. Change the settings to only accept connections with the 802.11ac protocol.
3. Make sure the SSID is set to the contents of the ROUTER_SSID environment variable
4. Change the security settings to use WPA2 and ensure the PSK matches what is set in the ROUTER_PSK environment variable
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_ac_manual
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
IEEE_80211.ac == 'supported'
user: root
environ: ROUTER_SSID
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 120.0
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using
no security and the 802.11ac protocol.
STEPS:
1. Open your router's configuration tool
2. Change the settings to only accept connections with the 802.11ac protocol.
3. Make sure the SSID is set to the contents of the ROUTER_SSID environment variable
4. Change the security settings to use no security
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/monitor_wireless_connection
requires:
package.name == 'iperf'
device.category == 'WIRELESS'
user: root
environ: WPA_BG_SSID WPA_BG_PSK SERVER_IPERF
command:
trap "nmcli con delete id $WPA_BG_SSID" EXIT
if create_connection wifi $WPA_BG_SSID --security=wpa --key=$WPA_BG_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
iperf -c $SERVER_IPERF -t 300 -i 30
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 330.0
_description:
Tests the performance of a system's wireless connection through the iperf tool.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/monitor_wireless_connection_udp
requires:
package.name == 'iperf'
device.category == 'WIRELESS'
user: root
environ: WPA_BG_SSID WPA_BG_PSK SERVER_IPERF
command:
trap "nmcli con delete id $WPA_BG_SSID" EXIT
if create_connection wifi $WPA_BG_SSID --security=wpa --key=$WPA_BG_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
iperf -c $SERVER_IPERF -t 300 -i 30 -u -b 100m -p 5050
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 330.0
_description:
Tests the performance of a system's wireless connection through the iperf tool, using UDP packets.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_a
requires:
device.category == 'WIRELESS'
IEEE_80211.band_5GHz == 'supported'
user: root
environ: OPEN_A_SSID
command:
trap "nmcli con delete id $OPEN_A_SSID" EXIT
if create_connection wifi $OPEN_A_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Test that the system's wireless hardware can connect to a router using the
802.11a protocol. This requires that you have a router pre-configured to only
respond to requests on the 802.11a protocol.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_b
requires:
device.category == 'WIRELESS'
user: root
environ: OPEN_B_SSID
command:
trap "nmcli con delete id $OPEN_B_SSID" EXIT
if create_connection wifi $OPEN_B_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Test that the system's wireless hardware can connect to a router using the
802.11b protocol. This requires that you have a router pre-configured to only
respond to requests on the 802.11b protocol.
unit: template
template-unit: job
template-resource: device
template-filter:
device.category == 'WIRELESS'
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/stress_performance_device{__index__}_{interface}
estimated_duration: 330.0
requires:
device.path == '{path}'
package.name == 'iperf'
environ: TEST_TARGET_IPERF
user: root
command: network test -i {interface} -t stress
_description:
This test executes iperf to generate a load on the network device {__index__} ({interface}) and then performs a ping test to watch for dropped packets and very large latency periods.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_connection_open_g
requires:
device.category == 'WIRELESS'
user: root
environ: OPEN_G_SSID
command:
trap "nmcli con delete id $OPEN_G_SSID" EXIT
if create_connection wifi $OPEN_G_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
estimated_duration: 30.0
_description:
Test that the system's wireless hardware can connect to a router using the
802.11g protocol. This requires that you have a router pre-configured to only
respond to requests on the 802.11g protocol.
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_extension
requires: device.category == 'WIRELESS'
command: wireless_ext
estimated_duration: 1.2
_description:
Test that the MAC80211 modules are loaded and wireless extensions are working.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'WIRELESS'
plugin: shell
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/iwconfig_check_device{__index__}_{interface}
estimated_duration: 1.2
requires: device.path == '{path}'
command: iwconfig {interface}
_description:
This test executes iwconfig requests against wireless device {__index__} ({interface}).
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/wireless_rfkill
command: rfkill list | zenity --text-info --title rfkill-Info
estimated_duration: 120.0
requires: device.category == 'WIRELESS'
_description:
PURPOSE:
This test will check whether or not your driver responds to rfkill commands.
STEPS:
1. Use the hardware switch on the side of your device to switch off wireless.
2. If you do not have a hardware switch disable wireless from the network manager icon in the panel
3. Click "Test" to verify that the hard or soft blocks are in place.
VERIFICATION:
Did the hard or soft blocks show on in the dialog?
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'WIRELESS'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::wireless
id: wireless/maximum_bandwidth_device{__index__}_{interface}
estimated_duration: 120.0
requires:
device.path == '{path}'
package.name == 'zenity'
package.name == 'iperf'
environ: TEST_TARGET_IPERF
user: root
command: network test -i {interface} -t iperf 2>&1 | cat - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'mobile broadband max bw {interface}'
_purpose:
User verification of whether the observed transfer throughput is acceptable
for the type and maximum speed of wireless device {__index__} ({interface}).
_steps:
1. Click "Test".
2. Read the network test summary and confirm that the throughput is acceptable.
3. If needed, click "Test" again to repeat the transfer test.
_verification:
Was the reported throughput acceptable for the type and maximum speed of this interface?
plainbox-provider-checkbox-0.25/jobs/camera.txt.in 0000664 0001750 0001750 00000003470 12646152433 023433 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::camera
id: camera/detect
estimated_duration: 1.2
requires:
device.category == 'CAPTURE'
command: camera_test detect
_description: This Automated test attempts to detect a camera.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::camera
id: camera/display
estimated_duration: 120.0
depends: camera/detect
requires:
device.category == 'CAPTURE'
command: camera_test display
_description:
PURPOSE:
This test will check that the built-in 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?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::camera
id: camera/still
estimated_duration: 120.0
depends: camera/detect
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
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: 2013.com.canonical.plainbox::camera
id: camera/multiple-resolution-images
estimated_duration: 1.2
depends: camera/detect
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.
plainbox-provider-checkbox-0.25/jobs/smoke.txt.in 0000664 0001750 0001750 00000002137 12646152433 023320 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
id: smoke/true
command: true
_description:
Check success result from shell test case
plugin: shell
id: smoke/false
command: false
_description:
Check failed result from shell test case
plugin: shell
id: smoke/dependency/good
depends: smoke/true
command: true
_description:
Check job is executed when dependency succeeds
plugin: shell
id: smoke/dependency/bad
depends: smoke/false
command: true
_description:
Check job result is set to uninitiated when dependency fails
plugin: shell
id: smoke/requirement/good
requires: package.name == "checkbox"
command: true
_description:
Check job is executed when requirements are met
plugin: shell
id: smoke/requirement/bad
requires: package.name == "unknown-package"
command: true
_description:
Check job result is set to "not required on this system" when requirements are not met
plugin: manual
id: smoke/manual
_description:
PURPOSE:
This test checks that the manual plugin works fine
STEPS:
1. Add a comment
2. Set the result as passed
VERIFICATION:
Check that in the report the result is passed and the comment is displayed
plainbox-provider-checkbox-0.25/jobs/codecs.txt.in 0000664 0001750 0001750 00000002165 12646152433 023443 0 ustar sylvain sylvain 0000000 0000000 plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::codecs
id: codecs/ogg-vorbis
requires:
package.name == 'gstreamer0.10-plugins-base' or package.name == 'gstreamer1.0-plugins-base'
package.name == 'totem'
package.name == 'ubuntu-sounds'
command: totem /usr/share/sounds/ubuntu/stereo/system-ready.ogg
_description:
PURPOSE:
This test will verify your system's ability to play Ogg Vorbis audio files.
STEPS:
1. Click Test to play an Ogg Vorbis file (.ogg)
2. Please close the player to proceed.
VERIFICATION:
Did the sample play correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::codecs
id: codecs/wav
requires:
package.name == 'gstreamer0.10-plugins-good' or package.name == 'gstreamer1.0-plugins-good'
package.name == 'totem'
package.name == 'alsa-utils'
command: totem /usr/share/sounds/alsa/Noise.wav
_description:
PURPOSE:
This test will verify your system's ability to play Wave Audio files.
STEPS:
1. Select Test to play a Wave Audio format file (.wav)
2. Please close the player to proceed.
VERIFICATION:
Did the sample play correctly?
plainbox-provider-checkbox-0.25/jobs/thunderbolt.pxu 0000664 0001750 0001750 00000006163 12646152433 024127 0 ustar sylvain sylvain 0000000 0000000 unit: manifest entry
id: has_thunderbolt
_name: Thunderbolt Support
value-type: bool
plugin: user-interact
category_id: 2013.com.canonical.plainbox::disk
id: thunderbolt/insert
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_thunderbolt == 'True'
estimated_duration: 20.0
command: removable_storage_watcher insert --timeout 40 scsi
_summary: Storage insert detection on Thunderbolt
_description:
PURPOSE:
This test will check if the insertion of a Thunderbolt HDD could be detected
STEPS:
1. Click 'Test' to begin the test. This test will
timeout and fail if the insertion has not been detected within 40 seconds.
2. Plug a Thunderbolt HDD into an available Thunderbolt port, if it's not
mounted automatically, please click the HDD icon to mount it.
VERIFICATION:
The verification of this test is automated. Do not change the automatically
selected result
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: thunderbolt/storage-test
user: root
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_thunderbolt == 'True'
depends: thunderbolt/insert
estimated_duration: 45.0
command: removable_storage_test -s 268400000 scsi
_summary: Storage test on Thunderbolt
_description:
This is an automated test which performs read/write operations on an attached
Thunderbolt HDD
plugin: user-interact
category_id: 2013.com.canonical.plainbox::disk
id: thunderbolt/remove
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_thunderbolt == 'True'
depends: thunderbolt/insert
estimated_duration: 10.0
command: removable_storage_watcher remove scsi
_summary: Storage removal detection on Thunderbolt
_description:
PURPOSE:
This test will check the system can detect the removal of a Thunderbolt HDD
STEPS:
1. Click 'Test' to begin the test. This test will timeout and fail if
the removal has not been detected within 20 seconds.
2. Remove the previously attached Thunderbolt HDD from the Thunderbolt port.
VERIFICATION:
The verification of this test is automated. Do not change the automatically
selected result
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::disk
id: thunderbolt/daisy-chain
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_thunderbolt == 'True'
estimated_duration: 45.0
command: removable_storage_test -s 268400000 scsi
_summary: Daisy-chain testing for Thunderbolt storage and display device
_description:
PURPOSE:
This test will check if your system can support daisy-chaining of a storage
and a monitor over Thunderbolt port
STEPS:
1. Connect your Thunderbolt monitor to your systems
2. Connect and mount your Thunderbolt HDD to another Thunderbolt port of the
monitor (you can do this with HDD first as well)
3. Click 'Test' to perform the storage test on the Thunderbolt HDD
VERIFICATION:
1. The verification for storage is automated, please select the result combine
with the result for the display.
2. Was the desktop displayed correctly on the Thunderbolt-connected screen?
plainbox-provider-checkbox-0.25/jobs/monitor.txt.in 0000664 0001750 0001750 00000017276 12646152433 023703 0 ustar sylvain sylvain 0000000 0000000 id: monitor/generator_vga
_description: VGA port test
_summary: VGA port test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_vga_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.vga == 'supported' or display.dp == 'supported'
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_description:
PURPOSE:
This test will check your VGA port.
STEPS:
Skip this test if your system does not have a VGA port.
1. Connect a display (if not already connected) to the VGA port on your system
VERIFICATION:
Was the desktop displayed correctly on both screens?
EOF
id: monitor/generator_dvi
_description: DVI port test
_summary: DVI port test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_dvi_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.dvi == 'supported'
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_description:
PURPOSE:
This test will check your DVI port.
STEPS:
Skip this test if your system does not have a DVI port.
1. Connect a display (if not already connected) to the DVI port on your system
VERIFICATION:
Was the desktop displayed correctly on both screens?
EOF
id: monitor/generator_displayport
_description: DisplayPort test
_summary: DisplayPort test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_displayport_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.dp == 'supported'
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_description:
PURPOSE:
This test will check your DisplayPort port.
STEPS:
Skip this test if your system does not have a DisplayPort port.
1. Connect a display (if not already connected) to the DisplayPort port on your system
VERIFICATION:
Was the desktop displayed correctly on both screens?
EOF
id: monitor/generator_hdmi
_description: HDMI port test
_summary: HDMI port test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_hdmi_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.hdmi == 'supported'
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_description:
PURPOSE:
This test will check your HDMI port.
STEPS:
Skip this test if your system does not have a HDMI port.
1. Connect a display (if not already connected) to the HDMI port on your system
VERIFICATION:
Was the desktop displayed correctly on both screens?
EOF
id: monitor/generator_svideo
_description: S-VIDEO port test
_summary: S-VIDEO port test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_svideo_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.svideo == 'supported'
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_description:
PURPOSE:
This test will check your S-VIDEO port.
STEPS:
Skip this test if your system does not have a S-VIDEO port.
1. Connect a display (if not already connected) to the S-VIDEO port on your system
VERIFICATION:
Was the desktop displayed correctly on both screens?
EOF
id: monitor/generator_rca
_description: RCA port test
_summary: RCA port test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_rca_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.rca == 'supported'
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_description:
PURPOSE:
This test will check your RCA port.
STEPS:
Skip this test if your system does not have a RCA port.
1. Connect a display (if not already connected) to the RCA port on your system
VERIFICATION:
Was the desktop displayed correctly on both screens?
EOF
id: monitor/generator_multi-head
_description: Multi-monitor test
_summary: Multi-monitor test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_multi-head_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: dmi.product in ['Desktop','Low Profile Desktop','Tower','Mini Tower']
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_description:
PURPOSE:
This test verifies that multi-monitor output works on your desktop system. This is NOT the same test as the external monitor tests you would run on your laptop. You will need two monitors to perform this test.
STEPS:
Skip this test if your video card does not support multiple monitors.
1. If your second monitor is not already connected, connect it now
2. Open the "Displays" tool (open the dash and search for "Displays")
3. Configure your output to provide one desktop across both monitors
4. Open any application and drag it from one monitor to the next.
VERIFICATION:
Was the stretched desktop displayed correctly across both screens?
EOF
id: monitor/generator_powersaving
_description: Monitor power-saving test
_summary: Monitor power-saving test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_powersaving_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::monitor
command: xset dpms force off
_description:
PURPOSE:
This test will check your monitor power saving capabilities
STEPS:
1. Click "Test" to try the power saving capabilities of your monitor
2. Press any key or move the mouse to recover
VERIFICATION:
Did the monitor go blank and turn on again?
EOF
id: monitor/generator_dim_brightness
_description: Screen dimming test
_summary: Screen dimming test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_dim_brightness_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: dmi.product in ['Notebook','Laptop','Portable','All In One','All-In-One','AIO']
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::monitor
user: root
command: brightness_test
_description:
PURPOSE:
This test will test changes to screen brightness
STEPS:
1. Click "Test" to try to dim the screen.
2. Check if the screen was dimmed approximately to half of the maximum brightness.
3. The screen will go back to the original brightness in 2 seconds.
VERIFICATION:
Was your screen dimmed approximately to half of the maximum brightness?
EOF
id: monitor/generator_thunderbolt
_description: Thunderbolt monitor test
_summary: Thunderbolt monitor test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: monitor/`echo ${index}`_thunderbolt_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_thunderbolt == 'True'
estimated_duration: 15.0
plugin: manual
category_id: 2013.com.canonical.plainbox::monitor
_summary: Display connected via Thunderbolt for $product
_description:
PURPOSE:
This test will check your Thunderbolt port as a monitor interconnect for $product.
STEPS:
1. Connect a display (if not already connected) to the Thunderbolt port on
your system
2. Switch display modes between in your Display Settings, check if it can be
set to mirrored, extended, displayed on external or onboard only
VERIFICATION:
Was the desktop displayed correctly with $product on the Thunderbolt-connected
screen in every mode?
EOF
plainbox-provider-checkbox-0.25/jobs/cpu.txt.in 0000664 0001750 0001750 00000006153 12646152433 022773 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/scaling_test
estimated_duration: 150.0
requires:
package.name == 'fwts'
user: root
environ: PLAINBOX_SESSION_SHARE
command: fwts_test -t cpufreq -l ${PLAINBOX_SESSION_SHARE}/scaling_test.log
_description:
Test the CPU scaling capabilities using Firmware Test Suite (fwts cpufreq).
plugin: attachment
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/scaling_test-log-attach
estimated_duration: 1.0
depends: cpu/scaling_test
command: [[ -e ${PLAINBOX_SESSION_SHARE}/scaling_test.log ]] && cat ${PLAINBOX_SESSION_SHARE}/scaling_test.log
_description:
Attaches the log generated by cpu/scaling_test to the results submission.
plugin: shell
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/maxfreq_test
estimated_duration: 0.6
requires:
package.name == 'fwts'
user: root
command: fwts_test -t maxfreq -l $PLAINBOX_SESSION_SHARE/maxfreq_test.log
_description:
Test that the CPU can run at its max frequency using Firmware Test Suite (fwts cpufreq).
plugin: attachment
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/maxfreq_test-log-attach
estimated_duration: 1.0
depends: cpu/maxfreq_test
command: [ -e $PLAINBOX_SESSION_SHARE/maxfreq_test.log ] && cat $PLAINBOX_SESSION_SHARE/maxfreq_test.log
_description:
Attaches the log generated by cpu/maxfreq_test to the results submission.
plugin: shell
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/clocktest
estimated_duration: 60.0
command: clocktest
_description:
Tests the CPU for clock jitter.
plugin: shell
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/offlining_test
estimated_duration: 1.0
user: root
command: cpu_offlining
_description:
Test offlining of each CPU core in a multicore system.
plugin: shell
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/topology
estimated_duration: 1.0
requires: int(cpuinfo.count) > 1 and (cpuinfo.platform == 'i386' or cpuinfo.platform == 'x86_64')
command: cpu_topology
_description:
This test checks cpu topology for accuracy between proc and sysfs.
plugin: shell
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/frequency_governors
estimated_duration: 22.0
user: root
command: nice -n -20 frequency_governors_test --debug
_description:
This test checks that CPU frequency governors are obeyed when set.
plugin: shell
category_id: 2013.com.canonical.plainbox::cpu
id: cpu/arm_vfp_support
estimated_duration: 1.0
requires: 'arm' in cpuinfo.type
command: grep VFP /var/log/syslog
_description:
Validate that the Vector Floating Point Unit is running on ARM device
plugin:shell
id: cpu/cstates
estimated_duration: 10.0
requires:
package.name == 'fwts'
user: root
_description:
Run Firmware Test Suite (fwts) cstates tests.
environ: PLAINBOX_SESSION_SHARE
command:
fwts_test -l $PLAINBOX_SESSION_SHARE/fwts_cstates_results.log -t cstates
plugin: attachment
category_id: 2013.com.canonical.plainbox::cpu
estimated_duration: 0.5
id: cpu/cstates_results.log
command:
[ -e ${PLAINBOX_SESSION_SHARE}/fwts_cstates_results.log ] && cat ${PLAINBOX_SESSION_SHARE}/fwts_cstates_results.log
_description: Attaches the FWTS desktop diagnosis results log to the submission
plainbox-provider-checkbox-0.25/jobs/server-services.txt.in 0000664 0001750 0001750 00000002374 12646152433 025334 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
id: services/open_ssh_test
requires: package.name == 'ssh'
command: pgrep sshd >/dev/null || (echo 'FAIL: sshd is not running.' 2>&1 && false)
_description: Verifies that sshd is running.
plugin: shell
id: services/print_server_test
requires: package.name == 'cups'
command: pgrep cupsd >/dev/null || (echo 'FAIL: cupsd is not running.' 2>&1 && false)
_description: Verifies that Print/CUPs server is running.
plugin: shell
id: services/dns_server_test
requires:
package.name == 'bind9'
package.name == 'dnsutils'
user: root
command: dns_server_test
_description: Verifies that DNS server is running and working.
plugin: shell
id: services/samba_test
requires:
package.name == 'samba'
package.name == 'winbind'
user: root
command: samba_test
_description: Verifies that Samba server is running.
plugin: shell
id: services/lamp_test
requires:
package.name == 'apache2'
package.name == 'php5-mysql'
package.name == 'libapache2-mod-php5'
package.name == 'mysql-server'
user: root
command: lamp_test
_description: Verifies that the LAMP stack is running (Apache, MySQL and PHP).
plugin: shell
id: services/tomcat_test
requires: package.name == 'tomcat6'
user: root
command: tomcat_test
_description: Verifies that Tomcat server is running and working.
plainbox-provider-checkbox-0.25/jobs/install.txt.in 0000664 0001750 0001750 00000000512 12646152433 023643 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
id: install/apt-get-gets-updates
requires: package.name == 'apt'
user: root
command: apt-get -d -y --force-yes dist-upgrade
_description:
Tests to see that apt can access repositories and get updates (does
not install updates). This is done to confirm that you could recover
from an incomplete or broken update.
plainbox-provider-checkbox-0.25/jobs/graphics-legacy.txt.in 0000664 0001750 0001750 00000022715 12646152433 025250 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/driver_version
command: graphics_driver
estimated_duration: 0.500
_description: Parses Xorg.0.Log and discovers the running X driver and version
_summary: Test X driver/version
plugin: manual
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/resolution-change
depends: graphics/xorg-version
_summary: Test changing resolution
_description:
PURPOSE:
This test will verify that the GUI is usable after manually changing resolution
STEPS:
1. Open the Displays application
2. Select a new resolution from the dropdown list
3. Click on Apply
4. Select the original resolution from the dropdown list
5. Click on Apply
VERIFICATION:
Did the resolution change as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/resolution
requires:
device.category == 'VIDEO'
flags: deprecated
command: resolution_test
estimated_duration: 0.750
_summary: Test default resolution (for old checkbox)
_description:
PURPOSE:
This test will verify the default display resolution
STEPS:
1. This display is using the following resolution:
INFO:
$output
VERIFICATION:
Is this acceptable for your display?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/screen-resolution
requires:
device.category == 'VIDEO'
package.name == 'qmlscene'
command: qmlscene -qt5 --transparent --fullscreen $PLAINBOX_PROVIDER_DATA/resolution_test.qml
estimated_duration: 10.0
_summary: Test default resolution
_description:
PURPOSE:
This test will verify the default display resolution
STEPS:
1. Click on Test to display the screen resolution overlay for 5 seconds.
VERIFICATION:
Is this acceptable for your display?
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/minimum_resolution
requires:
device.category == 'VIDEO'
command: resolution_test --horizontal 800 --vertical 600
estimated_duration: 0.331
_summary: Test that system meets minimum resolution requirement
_description:
Ensure the current resolution meets or exceeds the recommended minimum
resolution (800x600). See here for details:
.
https://help.ubuntu.com/community/Installation/SystemRequirements
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/maximum_resolution
requires:
device.category == 'VIDEO'
package.name == 'zenity'
command: zenity --info --text "Maximum resolution: $(xrandr -q |grep -A 1 "connected\( primary\)* [0-9]" |tail -1 |awk '{print $1}')"
estimated_duration: 10
_summary: Test maximum supported resolution
_description:
PURPOSE:
This test will verify the display is operating at its maximum supported resolution
STEPS:
1. Consult the system's specifications and locate the screen's maximum supported resolution.
2. Click on Test to display the maximum resolution that can be used by Ubuntu on the current display.
VERIFICATION:
Is this the display's maximum resolution?
id: graphics/modes
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: graphics_modes_info
estimated_duration: 0.250
_description: Collect info on graphics modes (screen resolution and refresh rate)
_summary: Collect info on graphics modes
id: graphics/color_depth
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: color_depth_info
estimated_duration: 0.150
_description: Collect info on color depth and pixel format.
_summary: Collect info on color depth and pixel format.
id: graphics/fresh_rate
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: fresh_rate_info
_description: Collect info on fresh rate.
_summary: Collect info on fresh rate.
id: graphics/graphic_memory
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
command: graphic_memory_info
_description: Collect info on graphic memory.
_summary: Collect info on graphic memory.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/cycle_resolution
requires: package.name == 'xorg'
depends: graphics/VESA_drivers_not_in_use
command: xrandr_cycle --screenshot-dir $PLAINBOX_SESSION_SHARE
estimated_duration: 250.000
_summary: Test resolution cycling
_description:
PURPOSE:
This test cycles through the detected video modes
STEPS:
1. Click "Test" to start cycling through the video modes
VERIFICATION:
Did the screen appear to be working for each mode?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/rotation
depends: graphics/xorg-version
command: rotation_test
estimated_duration: 20.000
_summary: Test rotation
_description:
PURPOSE:
This test will test display rotation
STEPS:
1. Click "Test" to test display rotation. The display will be rotated every 4 seconds.
2. Check if all rotations (normal right inverted left) took place without permanent screen corruption
VERIFICATION:
Did the display rotation take place without without permanent screen corruption?
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/compiz_check
requires: package.name == 'nux-tools'
command: ! /usr/lib/nux/unity_support_test -c -p 2>&1 | ansi_parser | grep -e ":\(\s\+\)no$" -ie "error"
estimated_duration: 0.130
_summary: Test Compiz support
_description: Check that hardware is able to run compiz
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/unity-support
requires: package.name == 'nux-tools'
command: ! /usr/lib/nux/unity_support_test -p 2>&1 | ansi_parser | grep -e ":\(\s\+\)no$" -ie "error"
estimated_duration: 0.131
_description: Check that hardware is able to run Unity 3D
_summary: Test Unity 3D support
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/glxgears
requires: package.name == 'mesa-utils'
command: glxgears; true
_summary: Test that glxgears works
_description:
PURPOSE:
This test tests the basic 3D capabilities of your video card
STEPS:
1. Click "Test" to execute an OpenGL demo. Press ESC at any time to close.
2. Verify that the animation is not jerky or slow.
VERIFICATION:
1. Did the 3d animation appear?
2. Was the animation free from slowness/jerkiness?
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/3d_window_open_close
requires: package.name == 'mesa-utils'
command: window_test -t open-close -i 10
estimated_duration: 60.525
_summary: Test 3D window open/close
_description: Open and close a 3D window multiple times
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/3d_window_suspend_resume
requires: package.name == 'mesa-utils'
command: window_test -t suspend-resume -i 10
estimated_duration: 121.00
_description: Open, suspend resume and close a 3D window multiple times
_summary: Test a 3D window with suspend/resume
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/multi_3d_windows_open_close
requires: package.name == 'mesa-utils'
command: window_test -t open-close-multi -i 10 -w 4
estimated_duration: 60.000
_description: Open and close 4 3D windows multiple times
_summary: Test Multi 3D window open/close
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/3d_window_move
requires: package.name == 'mesa-utils'
command: window_test -t move
estimated_duration: 50.000
_description: Move a 3D window around the screen
_summary: Test 3D window movement
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/screenshot
requires: package.name == 'fswebcam'
command: set -o pipefail; camera_test still --device=/dev/external_webcam -f ${PLAINBOX_SESSION_SHARE}/screenshot.jpg -q 2>&1 | ansi_parser
_summary: Test grabbing a screenshot
_description:
PURPOSE:
Take a screengrab of the current screen (logged on Unity desktop)
STEPS:
1. Take picture using USB webcam
VERIFICATION:
Review attachment manually later
plugin: attachment
category_id: 2013.com.canonical.plainbox::graphics
id: screenshot.jpg
depends: graphics/screenshot
command: base64 ${PLAINBOX_SESSION_SHARE}/screenshot.jpg
_description: Attaches the screenshot captured in graphics/screenshot.
_summary: Attach results of screenshot test
plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: graphics/screenshot_fullscreen_video
requires: package.name == 'fswebcam'
command:
[ -f ${PLAINBOX_PROVIDER_DATA}/video/Ogg_Theora_Video.ogv ] || { echo "Video file not found"; exit 1; }
gsettings set org.gnome.totem repeat true
totem --fullscreen ${PLAINBOX_PROVIDER_DATA}/video/Ogg_Theora_Video.ogv 2>/dev/null &
set -o pipefail
sleep 15 && camera_test still --device=/dev/external_webcam -f ${PLAINBOX_SESSION_SHARE}/screenshot_fullscreen_video.jpg -q 2>&1 | ansi_parser
sleep 5 && totem --quit 2>/dev/null
gsettings set org.gnome.totem repeat false
_summary: Test FSV screenshot
_description:
PURPOSE:
Take a screengrab of the current screen during fullscreen video playback
STEPS:
1. Start a fullscreen video playback
2. Take picture using USB webcam after a few seconds
VERIFICATION:
Review attachment manually later
plugin: attachment
category_id: 2013.com.canonical.plainbox::graphics
id: screenshot_fullscreen_video.jpg
depends: graphics/screenshot_fullscreen_video
command: base64 ${PLAINBOX_SESSION_SHARE}/screenshot_fullscreen_video.jpg
_description: Attaches the screenshot captured in graphics/screenshot_fullscreen_video.
_summary: Attach results of FSV screenshot test
plainbox-provider-checkbox-0.25/jobs/local.txt.in 0000664 0001750 0001750 00000015610 12646152433 023274 0 ustar sylvain sylvain 0000000 0000000 id: __audio__
plugin: local
_description: Audio tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/audio.txt?(.in)
id: __benchmarks__
plugin: local
_description: Benchmarks tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/benchmarks.txt?(.in)
id: __bluetooth__
plugin: local
_description: Bluetooth tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/bluetooth.txt?(.in)
id: __camera__
plugin: local
_description: Camera tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/camera.txt?(.in)
id: __codecs__
plugin: local
_description: Codec tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/codecs.txt?(.in)
id: __cpu__
plugin: local
_description: CPU tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/cpu.txt?(.in)
id: __daemons__
plugin: local
_description: System Daemon tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/daemons.txt?(.in)
id: __disk__
plugin: local
_description: Disk tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/disk.txt?(.in)
id: __dock__
plugin: local
_description: Docking tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_UNITS/dock.pxu
id: __ethernet__
plugin: local
_description: Ethernet Device tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/ethernet.txt?(.in)
id: __esata__
plugin: local
_description: eSATA disk tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/esata.txt?(.in)
id: __fingerprint__
plugin: local
_description: Fingerprint reader tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/fingerprint.txt?(.in)
id: __firewire__
plugin: local
_description: Firewire disk tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/firewire.txt?(.in)
id: __firmware__
plugin: local
_description: Firmware tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/firmware.txt?(.in)
id: __floppy__
plugin: local
_description: Floppy disk tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/floppy.txt?(.in)
id: __graphics__
plugin: local
_description: Graphics tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/graphics.txt?(.in) $PLAINBOX_PROVIDER_DATA/../jobs/graphics-legacy.txt?(.in)
id: __hibernate__
plugin: local
_description: Hibernation tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/hibernate.txt?(.in)
id: __info__
plugin: local
_description: Informational tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/info.txt?(.in)
id: __input__
plugin: local
_description: Input Devices tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/input.txt?(.in)
id: __install__
plugin: local
_description: Software Installation tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/install.txt?(.in)
id: __keys__
plugin: local
_description: Hotkey tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/keys.txt?(.in)
id: __led__
plugin: local
_description: LED tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/led.txt?(.in)
id: __mediacard__
plugin: local
_description: Media Card tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/mediacard.txt?(.in)
id: __memory__
plugin: local
_description: Memory tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/memory.txt?(.in)
id: __rendercheck__
plugin: local
_description: Rendercheck tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/rendercheck.txt?(.in)
id: __mir__
plugin: local
_description: MIR tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/mir.txt?(.in)
id: __miscellanea__
plugin: local
_description: Miscellaneous tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/miscellanea.txt?(.in)
id: __monitor__
plugin: local
_description: Monitor tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/monitor.txt?(.in)
id: __networking__
plugin: local
_description: Non-device specific networking tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/networking.txt?(.in)
id: __optical__
plugin: local
_description: Optical Drive tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/optical.txt?(.in)
id: __panel_clock__
plugin: local
_description: Panel Clock Verification tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/panel_clock_test.txt?(.in)
id: __panel_reboot__
plugin: local
_description: Panel Reboot Verification tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/panel_reboot.txt?(.in)
id: __expresscard__
plugin: local
_description: ExpressCard tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/expresscard.txt?(.in)
id: __peripheral__
plugin: local
_description: Peripheral tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/peripheral.txt?(.in)
id: __power-management__
plugin: local
_description: Power Management tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/power-management.txt?(.in)
id: __server-services__
plugin: local
_description: Server Services checks
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/server-services.txt?(.in)
id: __suspend__
plugin: local
_description: Suspend tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/suspend.txt?(.in)
id: __thunderbolt__
plugin: local
_description: Thunderbolt tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/thunderbolt.pxu
id: __touchpad__
plugin: local
_description: Touchpad tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/touchpad.txt?(.in)
id: __touchscreen__
plugin: local
_description: Touchscreen tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/touchscreen.txt?(.in)
id: __usb__
plugin: local
_description: USB tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/usb.txt?(.in)
id: __user_apps__
plugin: local
_description: User Applications
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/user_apps.txt?(.in)
id: __virtualization__
plugin: local
_description: Virtualization tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/virtualization.txt?(.in)
id: __wireless__
plugin: local
_description: Wireless networking tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/wireless.txt?(.in)
id: __mobilebroadband__
plugin: local
_description: Mobile broadband tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/mobilebroadband.txt?(.in)
id: __stress__
plugin: local
_description: Stress tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/stress.txt?(.in)
id: __smoke__
plugin: local
_description: Smoke tests
command:
shopt -s extglob
cat $PLAINBOX_PROVIDER_DATA/../jobs/smoke.txt?(.in)
plainbox-provider-checkbox-0.25/jobs/ethernet.txt.in 0000664 0001750 0001750 00000011537 12646152433 024024 0 ustar sylvain sylvain 0000000 0000000 unit: packaging meta-data
os-id: debian
Depends: module-init-tools
plugin: shell
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/detect
requires:
device.category == 'NETWORK' or device.category == 'WIRELESS'
package.name == 'module-init-tools'
package.name == 'pciutils'
command: network_device_info
estimated_duration: 1.2
_description:
Test to detect and return information about available network controllers on
the system under test.
plugin: shell
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/info_automated
requires:
executable.name == 'ip'
device.category == 'NETWORK'
command: udev_resource | filter_templates -w "category=NETWORK" | awk "/interface: / { print \$2 }" | xargs -n 1 network_info
estimated_duration: 30.0
_description:
Gathers some info on the current state of your network devices. If no devices
are found, the test will exit with an error.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/wired_connection
command: network_check
estimated_duration: 1.2
_description:
PURPOSE:
This test will check your wired connection
STEPS:
1. Click on the Network icon in the top panel
2. Select a network below the "Wired network" section
3. Click "Test" to verify that it's possible to establish a HTTP connection
VERIFICATION:
Did a notification show and was the connection correctly established?
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: shell
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/multi_nic_device{__index__}_{interface}
_summary: Multi-NIC Iperf testing for NIC {interface}
estimated_duration: 7400.0
requires:
device.path == '{path}'
package.name == 'iperf'
package.name == 'ethtool'
package.name == 'nmap'
user: root
environ: TEST_TARGET_IPERF
command: network test -i {interface} -t iperf --fail-threshold 80 --datasize 200 --num_runs 4
_description:
This test uses iperf to ensure network devices pass data at an acceptable
minimum percentage of advertized speed.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: shell
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/multi_iperf3_nic_device{__index__}_{interface}
_summary: Multi-NIC Iperf3 testing for NIC {interface}
estimated_duration: 7400.0
requires:
device.path == '{path}'
package.name == 'iperf3'
package.name == 'ethtool'
package.name == 'nmap'
user: root
environ: TEST_TARGET_IPERF
command: network test -i {interface} -t iperf --iperf3 --fail-threshold 80 --cpu-load-fail-threshold 90 --datasize 200 --num_runs 4
_description:
This test uses iperf3 to ensure network devices pass data at an acceptable
minimum percentage of advertized speed.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: shell
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/ethertool_check_device{__index__}_{interface}
_summary: ethtool check for NIC {interface}
estimated_duration: 330.0
requires:
device.path == '{path}'
package.name == 'ethtool'
command: ethtool {interface}
_description:
This test executes ethtool requests against ethernet device {__index__} ({interface}).
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/maximum_bandwidth_device{__index__}_{interface}
_summary: Maximum bandwidth test of device {__index__} ({interface})
estimated_duration: 330.0
requires:
device.path == '{path}'
package.name == 'zenity'
package.name == 'iperf'
user: root
environ: TEST_TARGET_IPERF
command: network test -i {interface} -t iperf 2>&1 | cat - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'ethernet max bw {interface}'
_purpose:
User verification of whether the observed transfer throughput is acceptable
for the type and maximum speed of each ethernet interface.
_steps:
1. Click "Test".
2. Read the network test summary and confirm that the throughput is acceptable.
3. If needed, click "Test" again to repeat the transfer test.
_verification:
Was the reported throughput acceptable for the type and maximum speed of this interface?
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: shell
category_id: 2013.com.canonical.plainbox::ethernet
id: ethernet/stress_performance_device{__index__}_{interface}
_summary: Stress and performance test of ethernet device {__index__} ({interface})
estimated_duration: 330.0
requires:
device.path == '{path}'
package.name == 'ethtool'
command: network test -i {interface} -t stress
_description:
Automated test that tests performance of ethernet device {__index__} ({interface}).
plainbox-provider-checkbox-0.25/jobs/keys.txt.in 0000664 0001750 0001750 00000021012 12646152433 023146 0 ustar sylvain sylvain 0000000 0000000 plugin: user-interact
category_id: 2013.com.canonical.plainbox::keys
id: keys/lock-screen
estimated_duration: 30.0
requires:
device.category == 'KEYBOARD'
command: lock_screen_watcher
_description:
PURPOSE:
This test will test the screen lock key
STEPS:
1. Commence the test. If there is no such key, please skip this test.
2. Press the lock screen button on the keyboard in 30 seconds.
3. If the screen is locked, move the mouse or press any key to activate the prompt.
4. Input the password to unlock the screen.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/brightness
estimated_duration: 30.0
requires: dmi.product in ['Notebook','Laptop','Portable','All In One','All-In-One','AIO']
_description:
PURPOSE:
This test will test the brightness key
STEPS:
1. Press the brightness buttons on the keyboard
VERIFICATION:
Did the brightness change following to your key presses?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::keys
id: keys/volume
estimated_duration: 30.0
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s '0xe02e,0xe0ae:Volume Down' '0xe030,0xe0b0:Volume Up'
_description:
PURPOSE:
This test will test the volume keys of your keyboard
STEPS:
Skip this test if your computer has no volume keys.
1. Click test to open a window on which to test the volume keys.
2. If all the keys work, the test will be marked as passed.
VERIFICATION:
Do the keys work as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::keys
id: keys/mute
estimated_duration: 30.0
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s '0xe020,0xe0a0:Mute'
_description:
PURPOSE:
This test will test the mute key of your keyboard
STEPS:
1. Click test to open a window on which to test the mute key.
2. If the key works, the test will pass and the window will close.
VERIFICATION:
Does the mute key work as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/sleep
estimated_duration: 90.0
requires:
device.category == 'KEYBOARD'
_description:
PURPOSE:
This test will test the sleep key
STEPS:
1. Press the sleep key on the keyboard
2. Wake your system up by pressing the power button
VERIFICATION:
Did the system go to sleep after pressing the sleep key?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::keys
id: keys/battery-info
estimated_duration: 30.0
requires: dmi.product in ['Notebook','Laptop','Portable']
user: root
command: key_test -s '0xe071,0xef1:Battery Info'
_description:
PURPOSE:
This test will test the battery information key
STEPS:
Skip this test if you do not have a Battery Button.
1. Click Test to begin
2. Press the Battery Info button (or combo like Fn+F3)
3: Close the Power Statistics tool if it opens
VERIFICATION:
Did the Battery Info key work as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/wireless
estimated_duration: 90.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
This test will test the wireless key
STEPS:
1. Press the wireless key on the keyboard
2. Check that the wifi LED turns off or changes color
3. Check that wireless is disabled
4. Press the same key again
5. Check that the wifi LED turns on or changes color
6. Check that wireless is enabled
VERIFICATION:
Did the wireless turn off on the first press and on again on the second?
(NOTE: the LED functionality will be reviewed in a following test. Please
only consider the functionality of the wifi itself here.)
plugin: user-interact
category_id: 2013.com.canonical.plainbox::keys
id: keys/media-control
estimated_duration: 30.0
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s 0xe010,0xe090:Previous 0xe024,0xe0a4:Stop 0xe019,0xe099:Next 0xe022,0xe0a2:Play
_description:
PURPOSE:
This test will test the media keys of your keyboard
STEPS:
Skip this test if your computer has no media keys.
1. Click test to open a window on which to test the media keys.
2. If all the keys work, the test will be marked as passed.
VERIFICATION:
Do the keys work as expected?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::keys
id: keys/super
estimated_duration: 30.0
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s '0xe05b,0xe0db:Left Super Key'
_description:
PURPOSE:
This test will test the super key of your keyboard
STEPS:
1. Click test to open a window on which to test the super key.
2. If the key works, the test will pass and the window will close.
VERIFICATION:
Does the super key work as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/video-out
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
Validate that the External Video hot key is working as expected
STEPS:
1. Plug in an external monitor
2. Press the display hot key to change the monitors configuration
VERIFICATION:
Check that the video signal can be mirrored, extended, displayed on external or onboard only.
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/touchpad
estimated_duration: 30.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
Verify touchpad hotkey toggles touchpad functionality on and off
STEPS:
1. Verify the touchpad is functional
2. Tap the touchpad toggle hotkey
3. Tap the touchpad toggle hotkey again
VERIFICATION:
Verify the touchpad has been disabled and re-enabled.
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/keyboard-backlight
estimated_duration: 30.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
Verify that the keyboard backlight toggle key works properly
STEPS:
1. Tap the keyboard backlight key
2. Confirm that the keyboard backlight was toggled to the opposite state
3. Tap the keyboard backlight key again
4. Confirm that the keyboard backlight was toggled to the opposite state
VERIFICATION:
Did the keyboard backlight state change on each press?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::keys
id: keys/microphone-mute
estimated_duration: 60.0
requires:
device.category == 'AUDIO'
device.category == 'KEYBOARD'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will test the mute key for your microphone
STEPS:
1. Click "Test" then speak: "Imagination is more important than knowledge" (or anything else) into your microphone.
2. While you are speaking, please press the mute key for the microphone to mute it and press it again to unmute.
3. After a few seconds, your speech will be played back to you. If the key works, your speech should be interrupted for a few seconds.
VERIFICATION:
Does the microphone mute key work as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/hibernate
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
This test will test the hibernate key
STEPS:
1. Press the hibernate key on the keyboard
2. Check that the system hibernated correctly
3. Wake your system after hibernating by pressing the power button
VERIFICATION:
Did the system go to hibernate after pressing the hibernate key?
plugin: manual
category_id: 2013.com.canonical.plainbox::keys
id: keys/keyboard-overhead-light
estimated_duration: 30.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
This test will test the keyboard overhead light key or switch
STEPS:
1. Press the keyboard overhead light key or swtich on the light
2. Check the the keyboard overhead light turn on correctly
3. Press the key or switch again to toggle off the light
VERIFICATION:
Did the keyboard overhead light key or switch turns on and off the light?
plainbox-provider-checkbox-0.25/jobs/info.txt.in 0000664 0001750 0001750 00000030667 12646152433 023146 0 ustar sylvain sylvain 0000000 0000000 # The dkms_info script requires python3-debian package
unit: packaging meta-data
os-id: debian
Depends: python3-debian
# The dkms_info script requires python3-guacamole package
unit: packaging meta-data
os-id: debian
Depends: python3-guacamole (>= 0.9)
id: codecs_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
requires: device.driver == 'snd_hda_intel'
command: cat /proc/asound/card*/codec#*
estimated_duration: 0.023
_description: Attaches a report of installed codecs for Intel HDA
id: cpuinfo_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: cat /proc/cpuinfo
estimated_duration: 0.006
_description: Attaches a report of CPU information
_summary: Attach a copy of /proc/cpuinfo
id: dmesg_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: cat /var/log/dmesg | ansi_parser
estimated_duration: 0.640
_description: Attaches a copy of /var/log/dmesg to the test results
_summary: Attach a copy of /var/log/dmesg
id: dmi_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: [ -d /sys/class/dmi/id/ ] && (grep -r . /sys/class/dmi/id/ 2>/dev/null || true) || false
estimated_duration: 0.044
_description: Attaches info on DMI
_summary: Attach a copy of /sys/class/dmi/id/*
id: dmidecode_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
requires: package.name == 'dmidecode'
user: root
command: dmidecode | iconv -t 'utf-8' -c
estimated_duration: 0.030
_description: Attaches dmidecode output
_summary: Attach a copy of of the output of dmidecode
id: lshw_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
requires: package.name == 'lshw'
user: root
command: lshw | iconv -t 'utf-8' -c
_description: Attaches lshw output
id: efi_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
user: root
command: [ -d /sys/firmware/efi ] && grep -m 1 -o --color=never 'EFI v.*' /var/log/kern.log* || true
estimated_duration: 0.5
_description: Attaches the firmware version
id: lspci_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: lspci -vvnn | iconv -t 'utf-8' -c
estimated_duration: 0.042
_description: Attaches very verbose lspci output.
_summary: Attach a list of PCI devices
id: lspci_network_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: lspci -vvnnQ | iconv -t 'utf-8' -c
estimated_duration: 1.322
_description: Attaches very verbose lspci output (with central database Query).
id: lspci_standard_config_attachment
_summary: Attach PCI configuration space hex dump
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: lspci -x
estimated_duration: 0.1
_description:
Attaches a hex dump of the standard part of the PCI configuration
space for all PCI devices.
id: lsusb_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
requires: package.name == 'usbutils'
user: root
command: lsusb -vv | iconv -t 'utf-8' -c
estimated_duration: 0.700
_description: Attaches a list of detected USB devices.
id: meminfo_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: cat /proc/meminfo
estimated_duration: 0.043
_description: Attaches info on system memory as seen in /proc/meminfo.
id: modprobe_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: find /etc/modprobe.* -name \*.conf | xargs cat
estimated_duration: 0.015
_description: Attaches the contents of the various modprobe conf files.
_summary: Attach the contents of modprobe configuration files
id: modinfo_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
_summary: Attach modinfo information
command:
for mod in $(lsmod | cut -f 1 -d " ")
do
printf "%-16s%s\n" "name:" "$mod"
modinfo $mod
echo
done
estimated_duration: 1.5
_description: Attaches modinfo information for all currently loaded modules
id: modules_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: cat /etc/modules
estimated_duration: 0.004
_description: Attaches the contents of the /etc/modules file.
_summary: Attach the contents of /etc/modules
id: sysctl_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: find /etc/sysctl.* -name \*.conf | xargs cat
estimated_duration: 0.014
_description: Attaches the contents of various sysctl config files.
_summary: Attach sysctl configuration files.
id: sysfs_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
_description: Attaches a report of sysfs attributes.
command:
for i in `udevadm info --export-db | sed -n 's/^P: //p'`; do
echo "P: $i"
udevadm info --attribute-walk --path=/sys$i 2>/dev/null | sed -n 's/ ATTR{\(.*\)}=="\(.*\)"/A: \1=\2/p'
echo
done
estimated_duration: 6.344
_summary: Attach detailed sysfs property output from udev
id: udev_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: udevadm info --export-db | xml_sanitize
estimated_duration: 1.465
_description: Attaches a dump of the udev database showing system hardware information.
_summary: Attach hardware database (udev)
id: udev_resource_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: udev_resource
estimated_duration: 0.432
_description: Attaches the output of udev_resource, for debugging purposes
id: gcov_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
requires: package.name == 'lcov'
user: root
command: gcov_tarball
_description: Attaches a tarball of gcov data if present.
id: lsmod_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: lsmod_info
estimated_duration: 0.5
_description: Attaches a list of the currently running kernel modules.
_summary: Attach a list of currently running kernel modules
id: dkms_info_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: dkms_info --format json
_description: Attaches json dumps of installed dkms package information.
_summary: Attaches json dumps of installed dkms package information.
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: acpi_sleep_attachment
command: [ -e /proc/acpi/sleep ] && cat /proc/acpi/sleep || echo "No /proc/acpi/sleep found"
estimated_duration: 0.5
_description: Attaches the contents of /proc/acpi/sleep if it exists.
plugin: shell
category_id: 2013.com.canonical.plainbox::info
id: info/bootchart
_description: Bootchart information.
requires: package.name == 'bootchart' or package.name == 'pybootchartgui'
user: root
command:
process_wait -u root bootchart collector ureadahead; \
[ `ls /var/log/bootchart/*.tgz 2>/dev/null | wc -l` -lt 2 ] && reboot && sleep 100
plugin: local
_summary: SATA/IDE device information.
id: info/hdparm
estimated_duration: 1.0
_description: Attaches SATA/IDE device information reported by hdparm.
requires:
package.name == 'hdparm'
device.category == 'DISK'
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=DISK"'
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/hdparm_`ls /sys$path/block`.txt
estimated_duration: 1.0
requires:
device.path == "$path"
block_device.`ls /sys$path/block`_state != 'removable'
user: root
command: hdparm -I /dev/`ls /sys$path/block`
EOF
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: bootchart.png
depends: info/bootchart
requires: package.name == 'pybootchartgui'
_description: Attaches the bootchart png file for bootchart runs
command:
file=`ls /var/log/bootchart/*.png 2>/dev/null | tail -1`; \
[ -e "$file" ] && cat "$file"
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: bootchart.tgz
depends: info/bootchart
_description: Attaches the bootchart log for bootchart test runs.
command:
file=`ls /var/log/bootchart/*.tgz 2>/dev/null | tail -1`; \
[ -e "$file" ] && cat "$file"
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: installer_bootchart.tgz
command: [ -f /var/log/installer/bootchart.tgz ] && base64 /var/log/installer/bootchart.tgz
_description: installs the installer bootchart tarball if it exists.
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: installer_debug.gz
user: root
command: [ -f /var/log/installer/debug ] && gzip -9 -c /var/log/installer/debug | base64
estimated_duration: 0.1
_description: Attaches the installer debug log if it exists.
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/touchpad_driver
requires: device.category == 'TOUCHPAD'
command: touchpad_driver_info
estimated_duration: 0.384
_description:
Returns the name, driver name and driver version of any touchpad discovered on
the system.
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/audio_device_driver
requires:
package.name == 'pulseaudio-utils'
package.name == 'module-init-tools'
device.category == 'AUDIO'
command: audio_driver_info
estimated_duration: 0.177
_description: Lists the device driver and version for all audio devices.
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/network_devices
requires:
device.category == 'NETWORK' or device.category == 'WIRELESS'
package.name == 'module-init-tools'
package.name == 'pciutils'
command: network_device_info
estimated_duration: 0.550
_description: Provides information about network devices
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/mobile_broadband_info
command: broadband_info
estimated_duration: 0.5
_description: Provides information about wwan/mobile broadband devices
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/xrandr
command: xrandr -q --verbose
_description: Provides information about displays attached to the system
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/disk_partitions
estimated_duration: 1.0
user: root
command: parted -l -s
_description: Attaches information about disk partitions
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/buildstamp
estimated_duration: 0.1
_description: Attaches the buildstamp identifier for the preinstalled OS
_summary: Attach /etc/buildstamp
command: [ -s /etc/buildstamp ] && cat /etc/buildstamp
plugin: shell
category_id: 2013.com.canonical.plainbox::info
id: info/detect_recovery
requires: package.name == 'dell-recovery' or package.name == 'ubuntu-recovery'
user: root
estimated_duration: 0.2
_summary: Check existence of recovery partition
_description: Check existence of recovery partition
command: recovery_info
plugin: shell
category_id: 2013.com.canonical.plainbox::info
id: info/detect_dell_recovery
depends: info/detect_recovery
requires: package.name == 'dell-recovery'
user: root
estimated_duration: 0.2
_summary: Check the recovery type is dell or not
_description: Check the recovery type is dell or not
command: recovery_info checktype DELL
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: recovery_info_attachment
depends: info/detect_recovery
requires: package.name == 'dell-recovery' or package.name == 'ubuntu-recovery'
user: root
estimated_duration: 0.2
_summary: Attach the recovery partition versions
_description:
Attach the recovery partition version
image_version is the preinstalled OS image version
bto_version is only for dell_recovery
Example:
image_version: somerville-trusty-amd64-20140620-0
bto_version: A00_dell-bto-trusty-houston-15-A11-iso-20141203-0.iso
command: recovery_info version
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: dell_bto_xml_attachment
depends: info/detect_dell_recovery
requires: package.name == 'dell-recovery'
user: root
estimated_duration: 0.5
_summary: Attach the bto.xml in Dell recovery partition
_description:
bto.xml is basically a Fish manifest
The information include:
- fish packages
- dell recovery stage 2 boot log
command: recovery_info file bto.xml
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
id: info/kvm_output
estimated_duration: 0.1
_description:
Attaches the debug log from the virtualization/kvm_check_vm test
to the results submission.
command: [ -f $PLAINBOX_SESSION_SHARE/virt_debug ] && cat $PLAINBOX_SESSION_SHARE/virt_debug
id: kernel_cmdline_attachment
plugin: attachment
category_id: 2013.com.canonical.plainbox::info
command: cat /proc/cmdline
estimated_duration: 0.005
_description: Attaches the kernel command line used to boot
_summary: Attach a copy of /proc/cmdline
plainbox-provider-checkbox-0.25/jobs/expresscard.txt.in 0000664 0001750 0001750 00000000577 12646152433 024533 0 ustar sylvain sylvain 0000000 0000000 plugin: manual
category_id: 2013.com.canonical.plainbox::expresscard
id: expresscard/verification
_description:
PURPOSE:
This will verify that an ExpressCard slot can detect inserted devices.
STEPS:
Skip this test if you do not have an ExpressCard slot.
1. Plug an ExpressCard device into the ExpressCard slot
VERIFICATION:
Was the device correctly detected?
plainbox-provider-checkbox-0.25/jobs/disk.txt.in 0000664 0001750 0001750 00000012275 12646152433 023140 0 ustar sylvain sylvain 0000000 0000000 # This is for bin/disk_info
unit: packaging meta-data
os-id: debian
Depends: lshw
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: disk/detect
estimated_duration: 0.25
user: root
command: disk_info
_description:
Displays information about each disk detected on the system under test.
unit: template
template-unit: job
template-imports: from 2013.com.canonical.certification import device
template-resource: device
template-filter: device.category == 'DISK' and device.name != ''
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: staging/disk/stats_{name}
requires:
block_device.{name}_state != 'removable'
user: root
command: disk_stats_test {name}
_summary: Disk statistics for /dev/{name}
_description:
This test checks disk stats, generates some activity and rechecks stats to
verify they've changed. It also verifies that disks appear in the various
files they're supposed to.
.
This test will inspect the following disk:
.
product name: {product}
sysfs path: {path}
device node path: /dev/{name}
plugin: local
_summary: Check stats changes for each disk
flags: deprecated
id: disk/stats
requires: device.category == 'DISK'
_description:
This test generates some disk activity and checks the stats to ensure drive
activity is being recorded properly.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=DISK"'
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: disk/stats_`ls /sys$path/block`
flags: deprecated
requires:
device.path == "$path"
block_device.`ls /sys$path/block`_state != 'removable'
user: root
command: disk_stats_test `ls /sys$path/block | sed 's|!|/|'`
description: This test checks disk stats, generates some activity and rechecks stats to verify they've changed. It also verifies that disks appear in the various files they're supposed to.
EOF
plugin: local
_summary: SMART test
id: disk/smart
estimated_duration: 0.30
requires:
package.name == 'smartmontools'
device.category == 'DISK'
_description:
This tests the SMART capabilities of disks detected on the system.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=DISK"'
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: disk/smart_`ls /sys$path/block`
requires:
device.path == "$path"
block_device.`ls /sys$path/block`_state != 'removable'
block_device.`ls /sys$path/block`_smart == 'True'
description:
This tests the SMART capabilities for $product (Note that this test will not work against hardware RAID)
user: root
command: disk_smart -b /dev/`ls /sys$path/block | sed 's|!|/|'` -s 130 -t 530
EOF
plugin: local
_summary: Verify system storage performs at or above baseline performance
id: disk/read_performance
estimated_duration: 0.30
requires:
device.category == 'DISK'
_description: Verify system storage performs at or above a baseline speed.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=DISK"'
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: disk/read_performance_`ls /sys$path/block`
estimated_duration: 65.0
requires:
device.path == "$path"
block_device.`ls /sys$path/block`_state != 'removable'
description: Disk performance test for $product
user: root
command: disk_read_performance_test `ls /sys$path/block | sed 's|!|/|'`
EOF
plugin: local
_summary: Verify that storage devices, such as Fibre Channel and RAID, perform under stress.
id: disk/storage_devices
estimated_duration: 1.0
requires:
device.category == 'DISK'
_description:
Verify that storage devices, such as Fibre Channel and RAID, perform under
stress without data loss or corruption.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=DISK"'
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: disk/storage_device_`ls /sys$path/block`
estimated_duration: 375.0
user: root
requires:
device.path == "$path"
block_device.`ls /sys$path/block`_state != 'removable'
description: Disk I/O stress test for $product
command: storage_test `ls /sys$path/block | sed 's|!|/|'`
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::disk
id: disk/spindown
estimated_duration: 875.0
requires:
device.category == 'DISK'
package.name == 'smartmontools'
user: root
command: spindown
_description:
Some new hard drives include a feature that parks the drive heads after a short period of inactivity. This is a power-saving feature, but it can have a bad interaction with the operating system that results in the drive constantly parked then activated. This produces excess wear on the drive, potentially leading to early failures.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::disk
id: disk/hdd-parking
estimated_duration: 60.0
requires:
device.category == 'DISK'
package.name == 'hdapsd'
depends: input/accelerometer
user: root
command: hdd_parking
_description:
PURPOSE:
This test checks that a systems drive protection mechanism works properly.
STEPS:
1. Click on Test
2. Move the system under test around, ensuring it is raised and lowered at some point.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plainbox-provider-checkbox-0.25/jobs/peripheral.txt.in 0000664 0001750 0001750 00000003133 12646152433 024332 0 ustar sylvain sylvain 0000000 0000000 plugin: manual
category_id: 2013.com.canonical.plainbox::peripheral
id: peripheral/printer
_description:
PURPOSE:
This test will verify that a network printer is usable
STEPS:
1. Make sure that a printer is available in your network
2. Click on the Gear icon in the upper right corner and then click on Printers
3. If the printer isn't already listed, click on Add
4. The printer should be detected and proper configuration values should be displayed
5. Print a test page
VERIFICATION:
Were you able to print a test page to the network printer?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::peripheral
id: peripheral/external-usb-modem
command: network_check
_description:
PURPOSE:
This test will verify that a USB DSL or Mobile Broadband modem works
STEPS:
1. Connect the USB cable to the computer
2. Right click on the Network icon in the panel
3. Select 'Edit Connections'
4. Select the 'DSL' (for ADSL modem) or 'Mobile Broadband' (for 3G modem) tab
5. Click on 'Add' button
6. Configure the connection parameters properly
7. Notify OSD should confirm that the connection has been established
8. Select Test to verify that it's possible to establish an HTTP connection
VERIFICATION:
Was the connection correctly established?
plugin: shell
category_id: 2013.com.canonical.plainbox::peripheral
id: peripheral/external-usb-modem-http
depends: peripheral/external-usb-modem
command: wget -SO /dev/null http://$TRANSFER_SERVER
_description:
Automated test case to make sure that it's possible to download files through HTTP
plainbox-provider-checkbox-0.25/jobs/power-management.txt.in 0000664 0001750 0001750 00000021726 12646152433 025455 0 ustar sylvain sylvain 0000000 0000000 plugin: manual
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/shutdown-boot
estimated_duration: 300.0
_description:
PURPOSE:
This test will check your system shutdown/booting cycle.
STEPS:
1. Shutdown your machine.
2. Boot your machine.
3. Repeat steps 1 and 2 at least 5 times.
VERIFICATION:
Did the system shutdown and rebooted correctly?
plugin: shell
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/fwts_wakealarm
environ: PLAINBOX_SESSION_SHARE
estimated_duration: 25.0
user: root
_description: Test ACPI Wakealarm (fwts wakealarm)
requires:
package.name == 'fwts'
command: fwts_test -f aborted -t wakealarm -l $PLAINBOX_SESSION_SHARE/fwts-wakealarm.log
plugin: attachment
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/fwts_wakealarm-log-attach
depends: power-management/fwts_wakealarm
estimated_duration: 2.0
_description: Attach log from fwts wakealarm test
requires:
package.name == 'fwts'
command: [ -e ${PLAINBOX_SESSION_SHARE}/fwts-wakealarm.log ] && cat ${PLAINBOX_SESSION_SHARE}/fwts-wakealarm.log
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/poweroff
estimated_duration: 120.0
depends: power-management/fwts_wakealarm
user: root
environ: PLAINBOX_SESSION_SHARE
requires:
package.name == 'upstart'
package.name == 'fwts'
command: pm_test poweroff --log-level=debug --log-dir=$PLAINBOX_SESSION_SHARE
flags: noreturn
_description:
PURPOSE:
This test will check the system's ability to power-off and boot.
STEPS:
1. Select "Test" to begin.
2. The machine will shut down.
3. Power the machine back on.
4. After rebooting, wait for the test prompts to inform you that the test is complete.
5. Once the test has completed, restart checkbox and select 'Re-run' when prompted.
VERIFICATION:
If the machine successfully shuts down and boots, select 'Yes', otherwise,
select 'No'.
plugin: attachment
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/poweroff-log-attach
estimated_duration: 1.0
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/*poweroff.1.log | base64
_description:
This will attach any logs from the power-management/poweroff test to the results.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/reboot
estimated_duration: 120.0
user: root
environ: PLAINBOX_SESSION_SHARE
requires:
package.name == 'upstart'
package.name == 'fwts'
command: pm_test reboot --log-level=debug --log-dir=$PLAINBOX_SESSION_SHARE
flags: noreturn
_description:
PURPOSE:
This test will check the system's ability to reboot cleanly.
STEPS:
1. Select "Test" to begin.
2. The machine will reboot.
3. After rebooting, wait for the test prompts to inform you that the test is complete.
4. Once the test has completed, restart checkbox and select Re-Run when prompted.
VERIFICATION:
If the machine successfully reboots, select Yes then select Next.
plugin: attachment
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/reboot-log-attach
estimated_duration: 1.0
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/*reboot.1.log | base64
_description:
This will attach any logs from the power-management/reboot test to the results.
plugin: manual
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/lid
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
This test will check your lid sensors.
STEPS:
1. Close your laptop lid.
VERIFICATION:
Does closing your laptop lid cause your system to suspend?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/lid_close
estimated_duration: 60.0
requires: device.product == 'Lid Switch'
command:
for i in `seq 20`; do
state=`cat /proc/acpi/button/lid/*/state | awk '{print $2}'`
[ "$state" = "closed" ] && exit 0 || sleep 0.5
done
exit 1
_description:
PURPOSE:
This test will check your lid sensors
STEPS:
1. Click "Test".
2. Close and open the lid.
VERIFICATION:
Did the screen turn off while the lid was closed?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/lid_open
estimated_duration: 60.0
requires: device.product == 'Lid Switch'
command:
for i in `seq 20`; do
state=`cat /proc/acpi/button/lid/*/state | awk '{print $2}'`
[ "$state" = "open" ] && exit 0 || sleep 0.5
done
exit 1
_description:
PURPOSE:
This test will check your lid sensors.
STEPS:
1. Click "Test".
2. Close the lid.
3. Wait 5 seconds with the lid closed.
4. Open the lid.
VERIFICATION:
Did the system resume when the lid was opened?
plugin: shell
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/rtc
requires:
rtc.state == 'supported'
package.name == 'util-linux'
cpuinfo.other != 'emulated by qemu'
user: root
command: hwclock -r
estimated_duration: 0.02
_description:
Verify that the Real-time clock (RTC) device functions properly, if present.
plugin: shell
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/tickless_idle
estimated_duration: 1.0
requires: cpuinfo.platform in ('i386', 'x86_64', 'ppc64el', 'pSeries')
_description: Check to see if CONFIG_NO_HZ is set in the kernel (this is just a simple regression check)
command:
zgrep 'CONFIG_NO_HZ=y' /boot/config-`uname -r` >/dev/null 2>&1 || ( echo "WARNING: Tickless Idle is NOT set" >&2 && exit 1 )
plugin: manual
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/unplug_ac
estimated_duration: 30.0
_description:
PURPOSE:
This test will ensure that the AC is unplugged for the battery drain tests to run.
STEPS:
1. Unplug laptop from AC.
VERIFICATION:
Was the laptop unplugged from AC?
plugin: shell
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/battery_drain_idle
estimated_duration: 90.0
requires: package.name == 'upower'
depends: power-management/unplug_ac
_description: Checks the battery drain during idle. Reports time and capacity until empty.
command:
battery_test -t 90 --idle
plugin: shell
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/battery_drain_movie
estimated_duration: 90.0
requires:
package.name == 'upower'
depends: power-management/unplug_ac
_description: Checks the battery drain while watching a movie. Reports time and capacity until empty. Requires MOVIE_VAR to be set.
command:
battery_test -t 90 --movie $MOVIE_VAR
plugin: shell
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/battery_drain_sleep
estimated_duration: 140.0
user: root
requires:
package.name == 'upower'
package.name == 'fwts'
depends: power-management/unplug_ac
_description: Checks the battery drain during suspend. Reports time and capacity until empty.
command:
battery_test -t 120 --sleep
plugin: manual
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/plug_ac
estimated_duration: 30.0
depends: power-management/battery_drain_idle power-management/battery_drain_movie power-management/battery_drain_sleep
_description:
PURPOSE:
This test will ensure that the AC is plugged back in after the battery.
tests
STEPS:
1. Plug laptop into AC.
VERIFICATION:
Was the laptop plugged into AC?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/reboot_manual
estimated_duration: 120.0
user:root
command: shutdown -r now
_description:
PURPOSE:
This test will verify that your system can successfully reboot.
STEPS:
1. Select 'Test' to initiate a system reboot.
2. When the grub boot menu is displayed, boot into Ubuntu (Or allow the
system to automatically boot on its own).
3. Once the system has restarted, log in and restart checkbox-certification-server.
4. Select 'Re-Run' to return to this test.
5. Select 'Yes' to indicate the test has passed if the system rebooted
successfully, otherwise, select 'No' to indicate there was a problem.
VERIFICATION:
Did the system reboot correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::power-management
id: power-management/shutdown_manual
estimated_duration: 120.0
user: root
command: shutdown -h now
_description:
PURPOSE:
This test will check your system shutdown/booting cycle
STEPS:
1. Select 'Test' to initiate a system shutdown.
2. Power the system back on.
3. From the grub menu, boot into the Xen Hypervisor.
4. When the system has restarted, log in and restart checkbox-certification-server.
5. Select 'Re-Run' to return to this test.
6. Select 'Yes' to indicate the test has passed if the machine shut down
successfully otherwise, Select 'No' to indicate there was a problem.
VERIFICATION:
Did the system shutdown and boot correctly?
plainbox-provider-checkbox-0.25/jobs/virtualization.txt.in 0000664 0001750 0001750 00000002240 12646152433 025261 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::virtualization
id: virtualization/kvm_check_vm
user: root
environ: KVM_TIMEOUT KVM_IMAGE http_proxy https_proxy
estimated_duration: 300.0
requires:
package.name == 'qemu-system'
package.name == 'qemu-utils'
virtualization.kvm == 'supported'
command: virtualization kvm --debug --log-file=$PLAINBOX_SESSION_SHARE/virt_debug
_description:
Verifies that a KVM guest can be created and booted using an Ubuntu Server
cloud image.
_summary:
Verify KVM VM boots
plugin: shell
category_id: 2013.com.canonical.plainbox::virtualization
id: virtualization/xen_ok
requires: package.name == 'libvirt-bin'
user: root
estimated_duration: 1.0
command: virsh -c xen:/// domstate Domain-0
_description:
Test to verify that the Xen Hypervisor is running.
_summary:
Verify Xen is running
plugin: shell
category_id: 2013.com.canonical.plainbox::virtualization
id: virtualization/xen_check_vm
depends: virtualization/xen_ok
user: root
estimated_duration: 300.0
command: xen_test /images/xentest.img /images/xentest.xml
_description:
Test to check that a Xen domU image can boot and run on Xen on Ubuntu
_summary:
Verify Xen domU can boot
plainbox-provider-checkbox-0.25/jobs/floppy.txt.in 0000664 0001750 0001750 00000000742 12646152433 023513 0 ustar sylvain sylvain 0000000 0000000 plugin: local
_summary: Floppy test
id: floppy/check
requires: device.driver == 'floppy'
_description: Floppy test
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "driver=floppy"'
plugin: shell
category_id: 2013.com.canonical.plainbox::floppy
id: floppy/check_`ls /sys$path/driver/*/*/*/block`
requires: device.path == "$path"
description: Floppy test for $product
user: root
command: floppy_test /dev/`ls /sys$path/driver/*/*/*/block`
EOF
plainbox-provider-checkbox-0.25/jobs/miscellanea.txt.in 0000664 0001750 0001750 00000022771 12646152433 024465 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/submission-resources
depends:
cpuinfo
dmi
dpkg
lsb
package
requirements
uname
dmi_attachment
sysfs_attachment
udev_attachment
estimated_duration: 1.0
command: true
_description:
A meta-job that verifies the data necessary for a complete result
submission are present. Failure indicates that the results are incomplete
and may be rejected.
plugin: manual
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/tester-info
_description:
PURPOSE:
Keep tester related information in the report
STEPS:
1. Tester Information
2. Please enter the following information in the comments field:
a. Name
b. Email Address
c. Reason for this test run
VERIFICATION:
Nothing to verify for this test
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/chvt
requires:
package.name == 'kbd'
user: root
command: cycle_vts
_description:
PURPOSE:
This test will check that the system can switch to a virtual terminal and back to X
STEPS:
1. Click "Test" to switch to another virtual terminal and then back to X
VERIFICATION:
Did your screen change temporarily to a text console and then switch back to your current session?
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/fwts_test
estimated_duration: 1.2
requires:
package.name == 'fwts'
user: root
_description:
Run Firmware Test Suite (fwts) automated tests.
environ: PLAINBOX_SESSION_SHARE
command:
fwts_test -l $PLAINBOX_SESSION_SHARE/fwts_results.log
plugin: attachment
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/fwts_results.log
command:
[[ -e ${PLAINBOX_SESSION_SHARE}/fwts_results.log ]] && cat ${PLAINBOX_SESSION_SHARE}/fwts_results.log
_description: Attaches the miscellanes/fwts_test results log to the submission.
plugin: attachment
category_id: 2013.com.canonical.plainbox::miscellanea
estimated_duration: 0.5
id: miscellanea/fwts_results_hwe.log.gz
command:
[ -f $PLAINBOX_SESSION_SHARE/fwts_results_hwe.log ] && gzip -c $PLAINBOX_SESSION_SHARE/fwts_results_hwe.log | base64
_description: Attaches the FWTS results log to the submission (to HWE)
_summary: Attach FWTS log to submission (to HWE)
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/ipmi_test
requires: package.name == 'ipmitool'
user: root
command: ipmi_test
_description:
This will run some basic commands in-band against a BMC, verifying that IPMI
works. Use of MAAS to deploy the system implicitly tests out-of-band BMC
control.
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
estimated_duration: 0.5
id: miscellanea/boot_mode
requires:
cpuinfo.platform in ("i386", "x86_64", "aarch64")
_summary: EFI-mode boot test
_description:
Test to verify that the system booted in EFI mode rather than Legacy/BIOS mode.
command:
if [ -d "/sys/firmware/efi" ] ; then
echo "System booted in EFI mode"
else
echo "System did NOT boot in EFI mode"
exit 1
fi
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/bmc_info
requires: package.name == 'ipmitool'
estimated_duration: 0.5
user: root
command: bmc_info
_description:
This will gather some info about the BMC itself for diagnostic purposes. This
will not works on non-IPMI systems like AMT and blade/sled type systems.
_summary:
Gather BMC Identification info
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/cpus_are_not_samples
requires: package.name == 'dmidecode'
estimated_duration: 0.5
user: root
command: dmitest cpu-check
_description:
Sanity check of CPU information; fails if CPU is an engineering sample
_summary:
CPU sanity check
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/dmitest_server
requires: package.name == 'dmidecode'
estimated_duration: 0.5
user: root
command: dmitest --test_versions --test_serials server
_description:
Sanity check of DMI system identification data (for servers)
_summary:
DMI ID sanity check (servers)
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/dmitest_client
requires: package.name == 'dmidecode'
estimated_duration: 0.5
user: root
command: dmitest --test_versions --test_serials desktop
_description:
Sanity check of DMI system identification data (for desktops & laptops)
_summary:
DMI ID sanity check (desktops/laptops)
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/is_laptop
user: root
_description:
Determine if we need to run tests specific to portable computers that may not apply to desktops.
command: check_is_laptop
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/apport-directory
requires: package.name == 'apport'
command: if [ -d /var/crash ]; then if [ $(find /var/crash -type f | grep -v .lock | wc -l) -eq 0 ]; then echo "/var/crash is empty"; else echo `ls /var/crash`; false; fi; else echo "/var/crash does not exist"; fi
_description:
Test that the /var/crash directory doesn't contain anything. Lists the files contained within if it does, or echoes the status of the directory (doesn't exist/is empty)
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/sources-list
command: sources_test $SOURCES_LIST "$REPOSITORIES"
_description: Checks that a specified sources list file contains the requested repositories
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: manual
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/pxe_boot_device{__index__}_{interface}
_summary: PXE verification test of device {__index__} ({interface})
estimated_duration: 30.0
_purpose:
This test will verify that you have attempted to PXE boot this machine from
the network device {__index__} ({interface}).
_steps:
1. Prior to running this test, you should have attempted to boot this system via PXE on every Network Port available.
_verification:
1. Select Yes if you successfully used PXE boot this system using the NIC {interface}
2. Select No if you did not attempt to PXE boot this system using the NIC {interface}
3. Select No if you attempted to PXE boot via {interface} and it failed for some reason.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: manual
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/remote_shared_ipmi_device{__index__}_{interface}
_summary: Remote Shared IPMI verification test for device {__index__} ({interface})
estimated_duration: 30.0
_purpose:
This test will verify that you have attempted IPMI control of this machine from the network device {__index__} ({interface}).
_steps:
1. Prior to running this test, you should have configured and used IPMI to power this machine off and on using every Network Port available.
_verification:
1. Select Yes if you successfully used IPMI to remotely power this system off and on using the NIC {interface}
2. Select No if you did not attempt to use IPMI to remotely power this sytem off and on via the NIC {interface}
3. Select No if you attempted to use IPMI to remotely power off/on this system via {interface} and it failed for some reason.
plugin: manual
category_id: 2013.com.canonical.plainbox::miscellanea
id: miscellanea/remote_dedicated_ipmi
_description:
PURPOSE:
Some systems do not share IPMI over all NICs but instead have a dedicated management port directly connected to the BMC. This test verifies that you have used that port for remote IPMI connections and actions.
STEPS:
1. Prior to running the test, you should have configured and used the Dedicated Management Port to remotely power off/on this sytem.
VERIFICATION:
Skip this test if this system ONLY uses shared management/ethernet ports OR if this system does not have a BMC (Management Console)
1. Select Yes if you successfully used IPMI to remotely power this system off and on using the dedicated management port.
2. Select No if you attempted to use the dedicated management port to remotely power this system off/on and it failed for some reason.
plugin:shell
id: miscellanea/oops
estimated_duration: 10.0
requires:
package.name == 'fwts'
user: root
_description:
Run Firmware Test Suite (fwts) oops tests.
environ: PLAINBOX_SESSION_SHARE
command:
fwts_test -l $PLAINBOX_SESSION_SHARE/fwts_oops_results.log -t oops
plugin: attachment
category_id: 2013.com.canonical.plainbox::miscellanea
estimated_duration: 0.5
id: miscellanea/oops_results.log
command:
[ -e ${PLAINBOX_SESSION_SHARE}/fwts_oops_results.log ] && cat ${PLAINBOX_SESSION_SHARE}/fwts_oops_results.log
_description: Attaches the FWTS oops results log to the submission
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
estimated_duration: 0.1
id: miscellanea/get_maas_version
command:
if [ -s /etc/installed-by-maas ]; then
cat /etc/installed-by-maas
else
echo "MAAS VERSION NOT FOUND" >&2
false
fi
_description: If system was installed via MAAS from a cert server, the MAAS version used should be contained in /etc/installed-by-maas
_summary: Gets the version of MAAS used to deploy the SUT
plugin: shell
category_id: 2013.com.canonical.plainbox::miscellanea
estimated_duration: 30.0
id: miscellanea/get_make_and_model
user: root
command: get_make_and_model
_description: Retrieve the computer's make and model for easier access than digging through the dmidecode output.
_summary: Retrieve the computer's make and model
plainbox-provider-checkbox-0.25/jobs/fingerprint.txt.in 0000664 0001750 0001750 00000002614 12646152433 024531 0 ustar sylvain sylvain 0000000 0000000 plugin: manual
category_id: 2013.com.canonical.plainbox::fingerprint
id: fingerprint/login
_description:
PURPOSE:
This test will verify that a fingerprint reader will work properly for logging into your system. This test case assumes that there's a testing account from which test cases are run and a personal account that the tester uses to verify the fingerprint reader
STEPS:
1. Click on the User indicator on the left side of the panel (your user name).
2. Select "Switch User Account"
3. On the LightDM screen select your username.
4. Use the fingerprint reader to login.
5. Click on the user switcher applet.
6. Select the testing account to continue running tests.
VERIFICATION:
Did the authentication procedure work correctly?
plugin: manual
category_id: 2013.com.canonical.plainbox::fingerprint
id: fingerprint/unlock
_description:
PURPOSE:
This test will verify that a fingerprint reader can be used to unlock a locked system.
STEPS:
1. Click on the Session indicator (Cog icon on the Left side of the panel) .
2. Select 'Lock screen'.
3. Press any key or move the mouse.
4. A window should appear that provides the ability to unlock either typing your password or using fingerprint authentication.
5. Use the fingerprint reader to unlock.
6. Your screen should be unlocked.
VERIFICATION:
Did the authentication procedure work correctly?
plainbox-provider-checkbox-0.25/jobs/optical.txt.in 0000664 0001750 0001750 00000022337 12646152433 023641 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::optical
id: optical/detect
requires: device.category == 'CDROM'
estimated_duration: 1.2
_description: Detects optical drives (CD/DVD) attached to the system.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"' | sed '/^$/d'
$vendor $product
EOF
plugin: local
_summary: Optical read test.
id: optical/read
estimated_duration: 1.0
requires:
device.category == 'CDROM'
_description: Optical read test.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::optical
id: optical/read_`ls /sys$path/block`
requires: device.path == "$path"
estimated_duration: 120.0
user: root
command: optical_read_test /dev/`ls /sys$path/block`
description:
PURPOSE:
This test will check your $product device's ability to read CD media
STEPS:
1. Insert appropriate non-blank media into your optical drive(s). Movie and Audio Disks may not work. Self-created data disks have the greatest chance of working.
2. If a file browser window opens, you can safely close or ignore that window.
3. Click "Test" to begin the test.
VERIFICATION:
This test should automatically select "Yes" if it passes, "No" if it fails.
EOF
plugin: local
_summary: Automated optical read test.
id: optical/read-automated
estimated_duration: 1.0
requires:
device.category == 'CDROM'
_description:
Automated test to read a data CD/DVD and ensure the optical drive works properly.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: shell
category_id: 2013.com.canonical.plainbox::optical
id: optical/read-automated_`ls /sys$path/block`
estimated_duration: 120.0
requires: device.path == "$path"
user: root
command: optical_read_test /dev/`ls /sys$path/block`
description:
This is an automated version of optical/read. It assumes you have already inserted a data CD into your optical drive prior to running Checkbox.
EOF
plugin: local
_summary: CD write test.
id: optical/cdrom-write
estimated_duration: 1.0
requires:
device.category == 'CDROM'
_description: CD write test.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::optical
id: optical/cdrom-write_`ls /sys$path/block`
estimated_duration: 120.0
requires:
device.path == "$path"
optical_drive_`ls /sys$path/block`.cd_write == 'supported'
user: root
command: set -o pipefail; optical_write_test /dev/`ls /sys$path/block` cd | ansi_parser
description:
PURPOSE:
This test will check your system's $product CD writing capabilities. This test requires a blank CD-R or CD+R.
STEPS:
Skip this test if you do not have a blank CD disk.
1. Insert a blank CD-R or CD+R into your drive
2. Click "Test" to begin.
3. When the CD tray ejects the media after burning, close it (DO NOT remove the disk, it is needed for the second portion of the test). Note, you must close the drive within 5 minutes or the test will time out.
VERIFICATION:
This test should automatically select "Yes" if it passes, "No" if it fails.
EOF
plugin: local
_summary: Automated CD write test
id: optical/cdrom-write-automated
estimated_duration: 1.0
requires:
device.category == 'CDROM'
_description: Automated CD write test
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: shell
category_id: 2013.com.canonical.plainbox::optical
id: optical/cdrom-write-automated_`ls /sys$path/block`
estimated_duration: 120.0
requires:
device.path == "$path"
optical_drive_`ls /sys$path/block`.cd_write == 'supported'
user: root
command: set -o pipefail; optical_write_test /dev/`ls /sys$path/block` cd | ansi_parser
description:
This is an automated version of optical/cdrom-write. It assumes you have already inserted a data CD into your optical drive prior to running Checkbox.
EOF
plugin: manual
category_id: 2013.com.canonical.plainbox::optical
id: optical/cdrom-audio-playback
depends: optical/read
estimated_duration: 120.0
_description:
PURPOSE:
This test will check your CD audio playback capabilities
STEPS:
1. Insert an audio CD in your optical drive
2. When prompted, launch the Music Player
3. Locate the CD in the display of the Music Player
4. Select the CD in the Music Player
5. Click the Play button to listen to the music on the CD
6. Stop playing after some time
7. Right click on the CD icon and select "Eject Disc"
8. The CD should be ejected
9. Close the Music Player
VERIFICATION:
Did all the steps work?
plugin: local
_summary: DVD write test.
id: optical/dvd-write
estimated_duration: 1.0
requires:
device.category == 'CDROM'
_description: DVD write test.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::optical
id: optical/dvd-write_`ls /sys$path/block`
requires:
device.path == "$path"
optical_drive_`ls /sys$path/block`.dvd_write == 'supported'
estimated_duration: 120.0
user: root
command: set -o pipefail; optical_write_test /dev/`ls /sys$path/block` dvd | ansi_parser
description:
PURPOSE:
This test will check your system's $product writing capabilities. This test requires a blank DVD-R or DVD+R.
STEPS:
Skip this test if you do not have a blank DVD disk.
1. Enter a blank DVD-R or DVD+R into your drive
2. Click "Test" to begin.
3. When the CD tray ejects the media after burning, close it (DO NOT remove the disk, it is needed for the second portion of the test). Note, you must close the drive within 5 minutes or the test will time out.
VERIFICATION:
This test should automatically select "Yes" if it passes, "No" if it fails.
EOF
plugin: local
_summary: Automated DVD write test.
id: optical/dvd-write-automated
estimated_duration: 1.0
requires:
device.category == 'CDROM'
_description: Automated DVD write test.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: shell
category_id: 2013.com.canonical.plainbox::optical
id: optical/dvd-write-automated_`ls /sys$path/block`
estimated_duration: 120.0
requires:
device.path == "$path"
optical_drive_`ls /sys$path/block`.dvd_write == 'supported'
user: root
command: set -o pipefail; optical_write_test /dev/`ls /sys$path/block` dvd | ansi_parser
description:
This is an automated version of optical/dvd-write. It assumes you have already inserted a data DVD into your optical drive prior to running Checkbox.
EOF
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::optical
id: optical/dvd_playback
command: totem /media/cdrom
estimated_duration: 120.0
requires:
device.category == 'CDROM'
package.name == 'totem'
_description:
PURPOSE:
This test will check your DVD playback capabilities
STEPS:
1. Insert a DVD that contains any movie in your optical drive
2. Click "Test" to play the DVD in Totem
VERIFICATION:
Did the file play?
plugin: local
_summary: Automated Blu-Ray read test.
id: optical/bluray-read
estimated_duration: 1.0
requires: device.category == 'CDROM'
_description: Automated Blu-Ray read test.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: user-interact
category_id: 2013.com.canonical.plainbox::optical
id: optical/bluray-read_`ls /sys$path/block`
estimated_duration: 120.0
requires:
device.path == "$path"
optical_drive_`ls /sys$path/block`.bd_read == "supported"
user: root
command: optical_read_test /dev/`ls /sys$path/block`
description:
PURPOSE:
This test will check your $product device's ability to read Blu-Ray (BD) media
STEPS:
1. Insert appropriate non-blank media into your Blu-Ray drive. Movie and Audio Disks may not work. Self-created data disks have the greatest chance of working.
2. If a file browser window opens, you can safely close or ignore that window.
3. Click "Test" to begin the test.
VERIFICATION:
This test should automatically select "Yes" if it passes, "No" if it fails.
EOF
plugin: local
_summary: Automated Blu-Ray write test.
id: optical/bluray-write
estimated_duration: 1.0
requires: device.category == 'CDROM'
_description: Automated Blu-Ray write test.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=CDROM"'
plugin: user-interact
category_id: 2013.com.canonical.plainbox::optical
id: optical/bluray-write_`ls /sys$path/block`
requires:
device.path == "$path"
optical_drive_`ls /sys$path/block`.bd_write == "supported"
package.name == "growisofs"
user: root
command: set -o pipefail; optical_write_test /dev/`ls /sys$path/block` bd | ansi_parser
estimated_duration: 120.00
description:
PURPOSE:
This test will check your $product device's ability to write Blu-Ray (BD) media
STEPS:
Skip this test if you do not have a blank BD-R disc
1. Insert appropriate writable media into your Blu-Ray drive.
2. Click "Test" to begin the test.
VERIFICATION:
This test should automatically select "Yes" if it passes, "No" if it fails.
EOF
plainbox-provider-checkbox-0.25/jobs/led.txt.in 0000664 0001750 0001750 00000016601 12646152433 022747 0 ustar sylvain sylvain 0000000 0000000 plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/power
estimated_duration: 15.0
_description:
PURPOSE:
Power LED verification
STEPS:
1. Power LED should be on while device is switched on
VERIFICATION:
Does the power LED light as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/power-blink-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
_description:
PURPOSE:
Power LED verification
STEPS:
1. The Power LED should blink or change color while the system is suspended
VERIFICATION:
Did the Power LED blink or change color while the system was suspended for the previous suspend test?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
_description:
PURPOSE:
Suspend LED verification.
STEPS:
Skip this test if your system does not have a dedicated Suspend LED.
1. The Suspend LED should blink or change color while the system is
suspended
VERIFICATION
Did the Suspend LED blink or change color while the system was suspended?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/battery-charging
estimated_duration: 120.0
_description:
PURPOSE:
Validate that the battery light shows charging status
STEPS:
1. Let system run on battery for a while
2. Plug in AC plug
VERIFICATION:
Did the battery indicator LED turn orange?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/battery-charged
estimated_duration: 240.0
_description:
PURPOSE:
Validate that the battery LED properly displays charged status
STEPS:
1. Let system run on battery for a short time
2. Plug in AC
3. Let system run on AC
VERIFICATION:
Does the orange battery LED shut off when system is fully charged?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/battery-low
estimated_duration: 30.0
_description:
PURPOSE:
Validate that the battery LED indicated low power
STEPS:
1. Let system run on battery for several hours
2. Monitor battery LED carefully
VERIFICATION:
Does the LED light orange when battery is low?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::led
id: led/hdd
estimated_duration: 30.0
command: led_hdd_test
_description:
PURPOSE:
HDD LED verification
STEPS:
1. Select "Test" to write and read a temporary file for a few seconds
2. HDD LED should light when writing to/reading from HDD
VERIFICATION:
Did the HDD LED light?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::led
id: led/numeric-keypad
estimated_duration: 30.0
command: keyboard_test
_description:
PURPOSE:
Numeric keypad LED verification
STEPS:
1. Press "Block Num" key to toggle numeric keypad LED
2. Click on the "Test" button to open a window to verify your typing
3. Type using the numeric keypad both when the LED is on and off
VERIFICATION:
1. Numeric keypad LED status should toggle everytime the "Block Num" key is pressed
2. Numbers should only be entered in the keyboard verification window when the LED is on
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/caps-lock
estimated_duration: 30.0
_description:
PURPOSE:
Block cap keys LED verification
STEPS:
1. Press "Block Cap Keys" to activate/deactivate cap keys blocking
2. Cap Keys LED should be switched on/off every time the key is pressed
VERIFICATION:
Did the Cap Keys LED light as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/wlan
depends: keys/wireless
estimated_duration: 60.0
_description:
PURPOSE:
WLAN LED verification
STEPS:
1. During the keys/wireless test you should have observed the
wireless LED while turning wireless back on.
2. WLAN LED should light or change color when wireless is turned on
VERIFICATION:
Did the WLAN LED turn on or change color as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/wlan-disabled
estimated_duration: 30.0
depends: keys/wireless
_description:
PURPOSE:
Validate that WLAN LED shuts off when disabled
STEPS:
1. During the keys/wireless test you should have observed the WLAN LED
while performing that test after turning wireless off.
2. WLAN LED should turn off or change color when wireless is turned off
VERIFICATION:
Did the WLAN LED turn off or change color as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/bluetooth
estimated_duration: 60.0
depends: bluetooth/detect-output
_description:
PURPOSE:
Validate that the Bluetooth LED turns on and off when BT is enabled/disabled
STEPS:
1. Switch bluetooth off from a hardware switch (if present)
2. Switch bluetooth back on
3. Switch bluetooth off from the panel applet
4. Switch bluetooth back on
VERIFICATION:
Did the bluetooth LED turn off and on twice?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::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: 2013.com.canonical.plainbox::led
id: led/touchpad
estimated_duration: 30.0
_description:
PURPOSE:
Touchpad LED verification
STEPS:
1. Click on the touchpad button or press key combination to enable/disable touchpad button
2. Slide your finger on the touchpad
VERIFICATION:
1. Touchpad LED status should toggle everytime the button is clicked or the key combination is pressed
2. When the LED is on, the mouse pointer should move on touchpad usage
3. When the LED is off, the mouse pointer should not move on touchpad usage
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/wireless
estimated_duration: 120.0
_description:
PURPOSE:
Wireless (WLAN + Bluetooth) LED verification
STEPS:
1. Make sure WLAN connection is established and Bluetooth is enabled.
2. WLAN/Bluetooth LED should light
3. Switch WLAN and Bluetooth off from a hardware switch (if present)
4. Switch them back on
5. Switch WLAN and Bluetooth off from the panel applet
6. Switch them back on
VERIFICATION:
Did the WLAN/Bluetooth LED light as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/mute
depends: keys/mute
estimated_duration: 30.0
_description:
PURPOSE:
Audio Mute LED verification.
STEPS:
Skip this test if your system does not have a special Audio Mute LED.
1. Press the Mute key twice and observe the Audio LED to determine if it
either turned off and on or changed colors.
VERIFICATION:
Did the Audio LED turn on and off or change color as expected?
plugin: manual
category_id: 2013.com.canonical.plainbox::led
id: led/microphone-mute
estimated_duration: 30.0
depends: keys/microphone-mute
_description:
PURPOSE:
Microphone Mute LED verification.
STEPS:
Skip this test if your system does not have a special Microphone Mute LED.
1. Press the Microphone Mute key twice and observe the Microphone LED to
determine if it either turned off and on or changed colors.
VERIFICATION:
Did the Microphone Mute LED turn on and off or change color as expected?
plainbox-provider-checkbox-0.25/jobs/firmware.txt.in 0000664 0001750 0001750 00000006446 12646152433 024025 0 ustar sylvain sylvain 0000000 0000000 plugin: local
_summary: Automated tests for firmware using Firmware Test Suite.
id: firmware/generator_fwts
estimated_duration: 0.5
requires: package.name == 'fwts'
_description: Automated tests for firmware using Firmware Test Suite.
command:
cat << 'EOF' | run_templates -s 'fwts_test --list'
estimated_duration: 1.2
plugin: shell
category_id: 2013.com.canonical.plainbox::firmware
id: firmware/fwts_$1
requires: package.name == 'fwts'
user: root
command: fwts_test -t $1 -l $PLAINBOX_SESSION_SHARE/fwts_$1.log
_description: Run $1 test from Firmware Test Suite.
_summary: Run $1 test from Firmware Test Suite.
EOF
plugin: local
_summary: Automated tests for firmware using Firmware Test Suite.
id: firmware/generator_fwts_logs
estimated_duration: 0.5
requires: package.name == 'fwts'
_description: Automated tests for firmware using Firmware Test Suite.
command:
cat << 'EOF' | run_templates -s 'fwts_test --list'
estimated_duration: 1.2
plugin: attachment
category_id: 2013.com.canonical.plainbox::firmware
id: firmware/fwts_$1.log
requires: package.name == 'fwts'
user: root
command: [[ -e ${PLAINBOX_SESSION_SHARE}/fwts_$1.log ]] && cat ${PLAINBOX_SESSION_SHARE}/fwts_$1.log
_description: Attach log for FWTS $1 test.
_summary: Attach log for FWTS $1 test.
EOF
plugin:shell
id: firmware/fwts_desktop_diagnosis
estimated_duration: 10.0
requires:
package.name == 'fwts'
user: root
_description:
Run Firmware Test Suite (fwts) QA-concerned desktop-specific diagnosis tests.
_summary: Run FWTS QA-concerned desktop-specific diagnosis tests.
environ: PLAINBOX_SESSION_SHARE
command:
fwts_test --qa -l $PLAINBOX_SESSION_SHARE/fwts_desktop_diagnosis_results.log
plugin:shell
id: firmware/fwts_desktop_diagnosis_hwe
estimated_duration: 5.0
requires:
package.name == 'fwts'
user: root
_description:
Run Firmware Test Suite (fwts) HWE-concerned desktop-specific diagnosis tests.
_summary: Run FWTS HWE-concerned desktop-specific diagnosis tests.
environ: PLAINBOX_SESSION_SHARE
command:
fwts_test --hwe -l $PLAINBOX_SESSION_SHARE/fwts_desktop_diagnosis_results_hwe.log
plugin: attachment
category_id: 2013.com.canonical.plainbox::firmware
estimated_duration: 0.5
id: firmware/fwts_desktop_diagnosis_results.log.gz
command:
[ -f $PLAINBOX_SESSION_SHARE/fwts_desktop_diagnosis_results.log ] && gzip -c $PLAINBOX_SESSION_SHARE/fwts_desktop_diagnosis_results.log | base64
_description: Attaches the FWTS desktop diagnosis results log to the submission
_summary: Attach FWTS desktop diagnosis log to submission
plugin: attachment
category_id: 2013.com.canonical.plainbox::firmware
estimated_duration: 0.5
id: firmware/fwts_desktop_diagnosis_results_hwe.log.gz
command:
[ -f $PLAINBOX_SESSION_SHARE/fwts_desktop_diagnosis_results_hwe.log ] && gzip -c $PLAINBOX_SESSION_SHARE/fwts_desktop_diagnosis_results_hwe.log | base64
_description: Attaches the FWTS desktop diagnosis results log to the submission (to HWE)
_summary: Attach FWTS desktop diagnosis log to submission (to HWE)
plugin: shell
category_id: 2013.com.canonical.plainbox::firmware
id: firmware/no_ACPI_REV_interface
_summary: No _REV interface in ACPI [DS]SDT tables
user: root
estimated_duration: 0.5
command: ! sudo grep -r "_REV" /sys/firmware/acpi/tables/* | grep [DS]SDT
_description: This Automated test checks misuse of the _REV interface in ACPI DSDT and SSDT tables
plainbox-provider-checkbox-0.25/jobs/firewire.txt.in 0000664 0001750 0001750 00000003064 12646152433 024016 0 ustar sylvain sylvain 0000000 0000000 plugin: user-interact
category_id: 2013.com.canonical.plainbox::firewire
id: firewire/insert
require: device.category == 'FIREWIRE'
command: removable_storage_watcher insert firewire
_description:
PURPOSE:
This test will check the system can detect the insertion of a FireWire HDD
STEPS:
1. Click 'Test' to begin the test. This test will
timeout and fail if the insertion has not been detected within 20 seconds.
2. Plug a FireWire HDD into an available FireWire port.
VERIFICATION:
The verification of this test is automated. Do not change the automatically
selected result
plugin: shell
category_id: 2013.com.canonical.plainbox::firewire
id: firewire/storage-test
user: root
require: device.category == 'FIREWIRE'
depends: firewire/insert
command: removable_storage_test -s 268400000 firewire
_description:
This is an automated test which performs read/write operations on an attached
FireWire HDD
plugin: user-interact
category_id: 2013.com.canonical.plainbox::firewire
id: firewire/remove
depends: firewire/insert
require: device.category == 'FIREWIRE'
command: removable_storage_watcher remove firewire
_description:
PURPOSE:
This test will check the system can detect the removal of a FireWire HDD
STEPS:
1. Click 'Test' to begin the test. This test will timeout and fail if
the removal has not been detected within 20 seconds.
2. Remove the previously attached FireWire HDD from the FireWire port.
VERIFICATION:
The verification of this test is automated. Do not change the automatically
selected result
plainbox-provider-checkbox-0.25/jobs/touchscreen.txt.in 0000664 0001750 0001750 00000013355 12646152433 024530 0 ustar sylvain sylvain 0000000 0000000 unit: manifest entry
id: has_touchscreen
_name: Touchscreen
value-type: bool
plugin: shell
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/nontouch-automated
requires:
xinput.device_class == 'XITouchClass' and xinput.touch_mode != 'direct'
command: true
estimated_duration: 1.2
_description:
Determine whether the screen is detected as a non-touch device automatically.
plugin: shell
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/multitouch-automated
requires:
xinput.device_class == 'XITouchClass' and xinput.touch_mode == 'direct'
command: true
estimated_duration: 1.2
_description:
Determine whether the screen is detected as a multitouch device automatically.
plugin: manual
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/multitouch-manual
depends: touchscreen/nontouch-automated
estimated_duration: 120.0
_description:
PURPOSE:
Touchscreen capability manual detection.
STEPS:
1. Look at the specifications for your system.
VERIFICATION:
Your screen was detected as a non touch screen. Select PASS if this is correct.
plugin: manual
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/tap-detect
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
estimated_duration: 120.0
_description:
PURPOSE:
Check touchscreen tap recognition
STEPS:
1. Tap an object on the screen with finger. The cursor should jump to location tapped and object should highlight
VERIFICATION:
Does tap recognition work?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/drag-n-drop
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
estimated_duration: 120.0
_description:
PURPOSE:
Check touchscreen drag & drop
STEPS:
1. Tap and hold an object on the desktop
2. Drag and drop the object in a different location
VERIFICATION:
Does drag and drop work?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/multitouch-zoom
_summary: Check touchscreen pinch gesture for zoom
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
command: qmlscene -qt5 $PLAINBOX_PROVIDER_DATA/touch_zoom_test.qml 2>&1 |grep -o PASS
estimated_duration: 120.0
_description:
PURPOSE:
Check touchscreen pinch gesture for zoom
STEPS:
1. Commence the test
2. Using 2 fingers, resize the blue square until it turns green, then release it.
VERIFICATION:
Did the blue square change size following the gesture?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/multitouch-rotate
_summary: Check touchscreen pinch gesture for rotate
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
command: qmlscene -qt5 $PLAINBOX_PROVIDER_DATA/touch_rotate_test.qml 2>&1 |grep -o PASS
estimated_duration: 120.0
_description:
PURPOSE:
Check touchscreen pinch gesture for rotate
STEPS:
1. Commence the test
2. Using 2 fingers, rotate the blue square until it turns green, then release it.
VERIFICATION:
Did the blue square rotate following the gesture?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/multitouch-window-move
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
estimated_duration: 120.0
_description:
PURPOSE:
Validate that 3-touch drag is operating as expected
STEPS:
1. Open a windows and bring it to the foreground
2. 3-touch the window and drag
VERIFICATION:
Did the window move along with the drag?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/multitouch-dash
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
estimated_duration: 120.0
_description:
PURPOSE:
Validate that 4-touch tap is operating as expected
STEPS:
1. 4-touch tap anywhere on the touchscreen
VERIFICATION:
Did the tap open the Dash?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/3-touch-tap
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
estimated_duration: 15.0
_description:
PURPOSE:
Validate that 3-touch tap is operating as expected
STEPS:
1. Commence the test
2. Tap the screen within the test area with 3 fingers simultaneously.
3. Once 3 fingers are on the screen you should see the indicator they are recognized.
VERIFICATION:
Did you see the green circles around the three fingers?
command:
manage_compiz_plugin unityshell disable
qmlscene -qt5 $PLAINBOX_PROVIDER_DATA/touch_tap_test.qml --touchpoints=3 2>&1 | grep -o PASS
EXIT=$?
sleep 5
manage_compiz_plugin unityshell enable
exit $EXIT
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::touchscreen
id: touchscreen/4-touch-tap
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
estimated_duration: 15.0
_description:
PURPOSE:
Validate that 4-touch tap is operating as expected
STEPS:
1. Commence the test
2. Tap the screen within the test area with 4 fingers simultaneously.
3. Once 4 fingers are on the screen you should see the indicator they are recognized.
VERIFICATION:
Did you see the green circles around the four fingers?
command:
manage_compiz_plugin unityshell disable
qmlscene -qt5 $PLAINBOX_PROVIDER_DATA/touch_tap_test.qml --touchpoints=4 2>&1 | grep -o PASS
EXIT=$?
sleep 5
manage_compiz_plugin unityshell enable
exit $EXIT
plainbox-provider-checkbox-0.25/jobs/panel_clock_test.txt.in 0000664 0001750 0001750 00000002066 12646152433 025514 0 ustar sylvain sylvain 0000000 0000000 id: panel_clock/verify
plugin: manual
requires: package.name == 'gnome-system-tools'
_description:
PURPOSE:
This test will verify that the desktop clock displays the correct date and time
STEPS:
1. Check the clock in the upper right corner of your desktop.
VERIFICATION:
Is the clock displaying the correct date and time for your timezone?
id: panel_clock/test
plugin: user-interact-verify
depends: panel_clock/verify
requires: package.name == 'gnome-system-tools'
user: root
command: date -s "`date -d '1 hour'`"
_description:
PURPOSE:
This test will verify that the desktop clock synchronizes with the system clock.
STEPS:
1. Commence the test and verify the clock moves ahead by 1 hour.
Note: It may take a minute or so for the clock to refresh
2. Right click on the clock, then click on "Time & Date Settings..."
3. Ensure that your clock application is set to manual.
4. Change the time 1 hour back
5. Close the window and reboot
VERIFICATION:
Is your system clock displaying the correct date and time for your timezone?
plainbox-provider-checkbox-0.25/jobs/memory.txt.in 0000664 0001750 0001750 00000001276 12646152433 023515 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::memory
id: memory/info
estimated_duration: 5.0
user: root
command: memory_compare
_description:
This test checks the amount of memory which is reporting in meminfo against
the size of the memory modules detected by DMI.
plugin: shell
category_id: 2013.com.canonical.plainbox::memory
id: memory/check
estimated_duration: 1000.0
user: root
requires:
uname.name == 'Linux'
command: memory_test
_description:
Test to perform some basic stress and exercise of system memory. This test
also includes an over-commit function to force swapping to disk, thus SUTs
should have suitably large swap files for the amount of RAM they have
installed.
plainbox-provider-checkbox-0.25/jobs/mediacard.txt.in 0000664 0001750 0001750 00000046525 12646152433 024124 0 ustar sylvain sylvain 0000000 0000000 plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/mmc-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a Multimedia Card (MMC) media
STEPS:
1. Click "Test" and then insert an MMC card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/mmc-storage
estimated_duration: 30.0
depends: mediacard/mmc-insert
user: root
command: removable_storage_test -s 67120000 --memorycard sdio usb scsi --auto-reduce-size
_description:
This test is automated and executes after the mediacard/mmc-insert
test is run. It tests reading and writing to the MMC card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/mmc-remove
estimated_duration: 30.0
depends: mediacard/mmc-insert
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of the MMC card from the systems card reader.
STEPS:
1. Click "Test" and then remove the MMC card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sd-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of an UNLOCKED Secure Digital (SD) media card
STEPS:
1. Click "Test" and then insert an UNLOCKED SD card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sd-storage
estimated_duration: 30.0
depends: mediacard/sd-insert
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/sd-insert
test is run. It tests reading and writing to the SD card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sd-remove
estimated_duration: 30.0
depends: mediacard/sd-insert
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of an SD card from the systems card reader.
STEPS:
1. Click "Test" and then remove the SD card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sd-preinserted
estimated_duration: 30.0
user: root
requires: device.category == 'CARDREADER'
command: removable_storage_test -s 268400000 --memorycard -l sdio usb scsi && removable_storage_test --memorycard sdio usb scsi
_description:
This is a fully automated version of mediacard/sd-automated and assumes that the
system under test has a memory card device plugged in prior to checkbox execution.
It is intended for SRU automated testing.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdhc-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a UNLOCKED Secure Digital High-Capacity
(SDHC) media card
STEPS:
1. Click "Test" and then insert an UNLOCKED SDHC card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdhc-storage
estimated_duration: 30.0
depends: mediacard/sdhc-insert
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/sdhc-insert
test is run. It tests reading and writing to the SDHC card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdhc-remove
estimated_duration: 30.0
depends: mediacard/sdhc-insert
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of an SDHC card from the systems card reader.
STEPS:
1. Click "Test" and then remove the SDHC card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/cf-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a Compact Flash (CF) media card
STEPS:
1. Click "Test" and then insert a CF card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/cf-storage
estimated_duration: 30.0
depends: mediacard/cf-insert
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/cf-insert
test is run. It tests reading and writing to the CF card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/cf-remove
depends: mediacard/cf-storage
estimated_duration: 30.0
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of a CF card from the systems card reader.
STEPS:
1. Click "Test" and then remove the CF card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdxc-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a Secure Digital Extended Capacity (SDXC) media card
STEPS:
1. Click "Test" and then insert an UNLOCKED SDXC card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdxc-storage
estimated_duration: 30.0
depends: mediacard/sdxc-insert
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/sdxc-insert
test is run. It tests reading and writing to the SDXC card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdxc-remove
estimated_duration: 30.0
depends: mediacard/sdxc-insert
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of a SDXC card from the systems card reader.
STEPS:
1. Click "Test" and then remove the SDXC card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/ms-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a Memory Stick (MS) media card
STEPS:
1. Click "Test" and then insert a MS card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/ms-storage
estimated_duration: 30.0
depends: mediacard/ms-insert
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/ms-insert
test is run. It tests reading and writing to the MS card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/ms-remove
estimated_duration: 30.0
depends: mediacard/ms-insert
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of a MS card from the systems card reader.
STEPS:
1. Click "Test" and then remove the MS card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/msp-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a Memory Stick Pro (MSP) media card
STEPS:
1. Click "Test" and then insert a MSP card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/msp-storage
estimated_duration: 30.0
depends: mediacard/msp-insert
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/msp-insert
test is run. It tests reading and writing to the MSP card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/msp-remove
estimated_duration: 30.0
depends: mediacard/msp-insert
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of a MSP card from the systems card reader.
STEPS:
1. Click "Test" and remove the MSP card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/xd-insert
estimated_duration: 30.0
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a Extreme Digital (xD) media card
STEPS:
1. Click "Test" and then insert a xD card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/xd-storage
estimated_duration: 30.0
depends: mediacard/xd-insert
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/xd-insert
test is run. It tests reading and writing to the xD card.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/xd-remove
estimated_duration: 30.0
depends: mediacard/xd-insert
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of a xD card from the systems card reader.
STEPS:
1. Click "Test" and then remove the xD card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sd-performance-manual
depends: mediacard/sd-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'SD Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert SD card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdhc-performance-manual
depends: mediacard/sdhc-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'SDHC Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert SDHC card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/mmc-performance-manual
depends: mediacard/mmc-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'MMC Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert MMC card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/cf-performance-manual
depends: mediacard/cf-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'CF Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert CF card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/sdxc-performance-manual
depends: mediacard/sdxc-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'SDXC Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert SDXC card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/ms-performance-manual
depends: mediacard/ms-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'MS Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert MS card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/msp-performance-manual
depends: mediacard/msp-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'MSP Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert MSP card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::mediacard
id: mediacard/xd-performance-manual
depends: mediacard/xd-insert
estimated_duration: 120.0
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb | cat <(echo "Working...") - <(echo; echo "Verify the result and click OK to decide on the outcome") | zenity --text-info --title 'xD Card Performance'
_description:
PURPOSE:
This test will check your Media Card data transfer performance.
STEPS:
1. Insert xD card into the reader slot on this computer.
2. Commence the test.
VERIFICATION:
Did the results of the test match the expected performance of the inserted device?
plainbox-provider-checkbox-0.25/jobs/rendercheck.txt.in 0000664 0001750 0001750 00000001576 12646152433 024465 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::graphics
id: rendercheck/tests
requires:
package.name == 'x11-apps'
command: ( rendercheck_test -b repeat -b gradients -d -o $PLAINBOX_SESSION_SHARE/rendercheck-results && echo "Rendercheck tests completed successfully" ) || ( echo "Error running rendercheck. Please see the log $PLAINBOX_SESSION_SHARE/rendercheck-results for details" >&2 && false )
_description:
Runs all of the rendercheck test suites. This test can take a few minutes.
plugin: attachment
category_id: 2013.com.canonical.plainbox::graphics
id: rendercheck/tarball
depends: rendercheck/tests
command: [ -e $PLAINBOX_SESSION_SHARE/rendercheck-results ] && tar cvfz $PLAINBOX_SESSION_SHARE/rendercheck-results.tar.gz $PLAINBOX_SESSION_SHARE/rendercheck-results && cat $PLAINBOX_SESSION_SHARE/rendercheck-results.tar.gz
_description: Attach log from rendercheck tests
plainbox-provider-checkbox-0.25/jobs/daemons.txt.in 0000664 0001750 0001750 00000005171 12646152433 023631 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/atd
requires: package.name == 'at'
command: pgrep -f '/usr/sbin/atd' >/dev/null
_description: Test if the atd daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/cron
requires: package.name == 'cron'
command: pgrep -f '/usr/sbin/cron' >/dev/null
_description: Test if the cron daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/cupsd
requires: package.name == 'cupsys'
command: pgrep -f '/usr/sbin/cupsd' >/dev/null
_description: Test if the cupsd daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/getty
requires: package.name == 'util-linux'
command: pgrep -f '/sbin/getty' >/dev/null
_description: Test if the getty daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/init
requires: package.name == 'upstart'
command: pgrep -f '/sbin/init' >/dev/null
_description: Test if the init daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/klogd
requires: package.name == 'klogd'
command: pgrep -f '/sbin/klogd' >/dev/null
_description: Test if the klogd daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/nmbd
requires: package.name == 'samba'
command: pgrep -f '/usr/sbin/nmbd' >/dev/null
_description: Test if the nmbd daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/smbd
requires: package.name == 'samba'
command: pgrep -f '/usr/sbin/smbd' >/dev/null
_description: Test if the smbd daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/syslogd
requires: package.name == 'syslogd'
command: pgrep -f '/sbin/syslogd' >/dev/null
_description: Test if the syslogd daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/udevd
requires:
package.name == 'udevd'
command: pgrep -f '/sbin/udevd' >/dev/null
_description: Test if the udevd daemon is running when the package is installed.
plugin: shell
category_id: 2013.com.canonical.plainbox::daemons
id: daemons/winbindd
requires: package.name == 'winbind'
command: pgrep -f '/usr/sbin/winbindd' >/dev/null
_description: Test if the winbindd daemon is running when the package is installed.
plainbox-provider-checkbox-0.25/jobs/panel_reboot.txt.in 0000664 0001750 0001750 00000000734 12646152433 024654 0 ustar sylvain sylvain 0000000 0000000 plugin: manual
id: panel_reboot_test
_description:
PURPOSE:
This test will verify that you can reboot your system from the desktop menu
STEPS:
1. Click the Gear icon in the upper right corner of the desktop and click on "Shut Down"
2. Click the "Restart" button on the left side of the Shut Down dialog
3. After logging back in, restart System Testing and it should resume here
VERIFICATION:
Did your system restart and bring up the GUI login cleanly?
plainbox-provider-checkbox-0.25/jobs/mir.txt.in 0000664 0001750 0001750 00000002015 12646152433 022764 0 ustar sylvain sylvain 0000000 0000000 plugin: local
_summary: MIR Integration tests
id: mir/integration
requires: package.name == 'mir-test-tools'
_description: MIR Integration tests
command:
cat << 'EOF' | run_templates -s "mir_integration_tests --gtest_list_tests | sed -n '/\.$/s/\.$//p'"
estimated_duration: 0.5
plugin: shell
category_id: 2013.com.canonical.plainbox::mir
id: mir/integration/$1
requires: package.name == 'mir-test-tools'
command: mir_integration_tests --gtest_filter=$1*
_description: Run $1 test from MIR Integration tests.
EOF
plugin: local
_summary: MIR Acceptance tests
id: mir/acceptance
requires: package.name == 'mir-test-tools'
_description: MIR Acceptance tests
command:
cat << 'EOF' | run_templates -s "mir_acceptance_tests --gtest_list_tests | sed -n '/\.$/s/\.$//p'"
estimated_duration: 0.5
plugin: shell
category_id: 2013.com.canonical.plainbox::mir
id: mir/acceptance/$1
requires: package.name == 'mir-test-tools'
command: mir_acceptance_tests --gtest_filter=$1*
_description: Run $1 test from MIR Acceptance tests.
EOF
plainbox-provider-checkbox-0.25/jobs/stress.txt.in 0000664 0001750 0001750 00000037615 12646152433 023536 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/cpu_stress_test
estimated_duration: 7200.0
requires:
package.name == 'stress'
user: root
command: num_vm=$(awk '/MemTotal/ {x=$2/262144; print ((x == int(x)) ? x : int(x) +1)}' /proc/meminfo); vm_bytes=$(($(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo)/$num_vm/4))M; stress --cpu `cpuinfo_resource | awk '/count:/ {print $2}'` --vm $num_vm --vm-bytes $vm_bytes --timeout 7200s
_description:
Simulate high system load using the 'stress' tool to exercise the CPU for
several hours. The test is considered passed if the system does not freeze or
abend.
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/hibernate_30_cycles
estimated_duration: 5400.00
depends:
power-management/hibernate_advanced
requires:
sleep.disk == 'supported'
rtc.state == 'supported'
environ: PLAINBOX_SESSION_SHARE
user: root
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
fwts_test -l $PLAINBOX_SESSION_SHARE/hibernate_30_cycles -f none -s s4 --s4-device-check --s4-device-check-delay=45 --s4-sleep-delay=120 --s4-multiple=30
else
echo "Calling sleep_test"
set -o pipefail; sleep_test -s disk -i 30 -w 120 | tee $PLAINBOX_SESSION_SHARE/hibernate_30_cycles.log
fi
_description:
PURPOSE:
This is an automated stress test that will force the system to hibernate/resume for 30 cycles
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/hibernate-30-cycles-log-check
estimated_duration: 1.0
command: [ -e $PLAINBOX_SESSION_SHARE/hibernate_30_cycles.log ] && sleep_test_log_check -v s4 $PLAINBOX_SESSION_SHARE/hibernate_30_cycles.log
_description:
Automated check of the 30 cycle hibernate log for errors detected by fwts.
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: power-management/hibernate-30-cycle-log-attach
estimated_duration: 1.0
command: [ -e $PLAINBOX_SESSION_SHARE/hibernate_30_cycles.log ] && cat $PLAINBOX_SESSION_SHARE/hibernate_30_cycles.log
_description:
Attaches the log from the 30 cycle Hibernate/Resume test if it exists
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend_30_cycles_with_reboots
estimated_duration: 5400.0
depends:
power-management/rtc
suspend/suspend_advanced
user: root
command:
pm_test reboot --fwts --log-level=debug --log-dir=$PLAINBOX_SESSION_SHARE --suspends-before-reboot=30 -r 3
_description:
This is an automated stress test that will run a sequence of '30 suspend/resume cycles and one reboot' 3 times.
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend_30_cycles
estimated_duration: 2400.0
depends:
power-management/rtc
suspend/suspend_advanced
environ: PLAINBOX_SESSION_SHARE
user: root
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
set -o pipefail; fwts_test -l $PLAINBOX_SESSION_SHARE/suspend_30_cycles -f none -s s3 --s3-device-check --s3-device-check-delay=45 --s3-sleep-delay=30 --s3-multiple=30 | tee $PLAINBOX_SESSION_SHARE/suspend_30_cycles_times.log
else
echo "Calling sleep_test"
set -o pipefail; sleep_test -p -s mem -i 30 | tee $PLAINBOX_SESSION_SHARE/suspend_30_cycles.log
fi
_description:
PURPOSE:
This is an automated stress test that will force the system to suspend/resume for 30 cycles.
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend-30-cycles-log-check
depends: power-management/suspend_30_cycles
estimated_duration: 1.0
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_30_cycles.log ] && sleep_test_log_check -v s3 $PLAINBOX_SESSION_SHARE/suspend_30_cycles.log
_description:
Automated check of the 30 cycle suspend log for errors detected by fwts.
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend-30-cycles-log-check-with-reboots
depends: power-management/suspend_30_cycles_with_reboots
estimated_duration: 1.0
command: [ -e $PLAINBOX_SESSION_SHARE/pm_test.reboot.3.log ] && sleep_test_log_check -v s3 $PLAINBOX_SESSION_SHARE/pm_test.reboot.3.log
_description:
Automated check of the '30 cycle suspend and 1 reboot times 3' logs for errors detected by fwts.
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend-30-cycle-log-attach
estimated_duration: 1.0
depends: power-management/suspend_30_cycles
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_30_cycles.log ] && cat $PLAINBOX_SESSION_SHARE/suspend_30_cycles.log
_description:
Attaches the log from the 30 cycle Suspend/Resume test if it exists
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend-30-cycle-log-attach-with-reboots
estimated_duration: 1.0
depends: power-management/suspend_30_cycles_with_reboots
command: [ -e $PLAINBOX_SESSION_SHARE/pm_test.reboot.3.log ] && cat $PLAINBOX_SESSION_SHARE/pm_test.reboot.3.log
_description:
Attaches the log from the '30 cycle Suspend/Resume and one reboot times 3' test if it exists
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend-30-cycles-time-check
estimated_duration: 1.0
depends: power-management/suspend_30_cycles
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_30_cycles_times.log ] && sleep_time_check $PLAINBOX_SESSION_SHARE/suspend_30_cycles_times.log
_description:
Checks the sleep times to ensure that a machine suspends and resumes within a given threshold
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: power-management/suspend-30-cycles-time-check-with-reboots
estimated_duration: 1.0
depends: power-management/suspend_30_cycles_with_reboots
command: [ -e $PLAINBOX_SESSION_SHARE/pm_test.reboot.3.log ] && sleep_time_check $PLAINBOX_SESSION_SHARE/pm_test.reboot.3.log
_description:
Checks the sleep times to ensure that a machine suspends and resumes within a given threshold
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/hibernate_250_cycles
estimated_duration: 43400.0
depends: power-management/rtc
environ: PLAINBOX_SESSION_SHARE
user: root
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
fwts_test -l $PLAINBOX_SESSION_SHARE/hibernate_250_cycles -s s4 --s4-device-check --s4-device-check-delay=45 --s4-sleep-delay=120 --s4-multiple=250
else
echo "Calling sleep_test"
set -o pipefail; sleep_test -s disk -i 250 -w 120 | tee $PLAINBOX_SESSION_SHARE/hibernate_250_cycles.log
fi
_description:
PURPOSE:
This is an automated stress test that will force the system to hibernate/resume for 250 cycles
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/hibernate-250-cycle-log-attach
estimated_duration: 1.0
command: [ -e $PLAINBOX_SESSION_SHARE/hibernate_250_cycles.log ] && cat $PLAINBOX_SESSION_SHARE/hibernate_250_cycles.log
_description:
Attaches the log from the 250 cycle Hibernate/Resume test if it exists
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/suspend_250_cycles
estimated_duration: 18750.0
depends: power-management/rtc
environ: PLAINBOX_SESSION_SHARE
user: root
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
set -o pipefail; fwts_test -l $PLAINBOX_SESSION_SHARE/suspend_250_cycles -s s3 --s3-device-check --s3-device-check-delay=45 --s3-sleep-delay=30 --s3-multiple=250 | tee $PLAINBOX_SESSION_SHARE/suspend_250_cycles_times.log
else
echo "Calling sleep_test"
set -o pipefail; sleep_test -p -s mem -i 250 | tee $PLAINBOX_SESSION_SHARE/suspend_250_cycles.log
fi
_description:
PURPOSE:
This is an automated stress test that will force the system to suspend/resume for 250 cycles.
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/suspend-250-cycle-log-attach
estimated_duration: 1.0
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_250_cycles.log ] && cat $PLAINBOX_SESSION_SHARE/suspend_250_cycles.log
_description:
Attaches the log from the 250 cycle Suspend/Resume test if it exists
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/suspend-250-cycles-time-check
estimated_duration: 1.0
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_250_cycles_times.log ] && sleep_time_check $PLAINBOX_SESSION_SHARE/suspend_250_cycles_times.log
_description:
Checks the sleep times to ensure that a machine suspends and resumes within a given threshold
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot
estimated_duration: 4500.0
requires:
package.name == 'upstart'
package.name == 'fwts'
command: pm_test -r 100 --silent --log-level=notset reboot --log-dir=$PLAINBOX_SESSION_SHARE
flags: noreturn
user: root
environ: PLAINBOX_SESSION_SHARE
_description:
Stress reboot system (100 cycles)
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot_log
estimated_duration: 1.0
depends: stress/reboot
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/*reboot.100.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot_30
requires:
package.name == 'upstart'
package.name == 'fwts'
command: pm_test -r 30 --silent --log-level=notset reboot --log-dir=$PLAINBOX_SESSION_SHARE
flags: noreturn
estimated_duration: 2700
user: root
environ: PLAINBOX_SESSION_SHARE
_description:
Stress reboot system (30 cycles)
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot_30_log
depends: stress/reboot_30
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/*reboot.30.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff
estimated_duration: 4500.0
requires:
package.name == 'upstart'
package.name == 'fwts'
command: pm_test -r 100 --silent --log-level=notset poweroff --log-dir=$PLAINBOX_SESSION_SHARE
flags: noreturn
user: root
environ: PLAINBOX_SESSION_SHARE
_description:
Stress poweroff system (100 cycles)
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff_log
estimated_duration: 1.0
depends: stress/poweroff
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/*poweroff.100.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff_30
requires:
package.name == 'upstart'
package.name == 'fwts'
command: pm_test -r 30 --silent --log-level=notset poweroff --log-dir=$PLAINBOX_SESSION_SHARE
flags: noreturn
estimated_duration: 3600
user: root
environ: PLAINBOX_SESSION_SHARE
_description:
Stress poweroff system (30 cycles)
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff_30_log
depends: stress/poweroff_30
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/*poweroff.30.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot_30_check
estimated_duration: 1.0
depends: stress/reboot_30
command: pm_log_check --log-level=notset $PLAINBOX_SESSION_SHARE/pm_test.reboot.30.log $PLAINBOX_SESSION_SHARE/pm_log_check_reboot.30.log
_description: Check logs for the stress reboot (30 cycles) test case
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot_30_check_log
estimated_duration: 1.0
depends: stress/reboot_30_check
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/pm_log_check_reboot.30.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff_30_check
estimated_duration: 1.0
depends: stress/poweroff_30
command: pm_log_check --log-level=notset $PLAINBOX_SESSION_SHARE/pm_test.poweroff.30.log $PLAINBOX_SESSION_SHARE/pm_log_check_poweroff.30.log
_description: Check logs for the stress poweroff (30 cycles) test case
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff_30_check_log
estimated_duration: 1.0
depends: stress/poweroff_30_check
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/pm_log_check_poweroff.30.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot_check
estimated_duration: 1.0
depends: stress/reboot
command: pm_log_check --log-level=notset $PLAINBOX_SESSION_SHARE/pm_test.reboot.100.log $PLAINBOX_SESSION_SHARE/pm_log_check_reboot.100.log
_description: Check logs for the stress reboot (100 cycles) test case
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/reboot_check_log
estimated_duration: 1.0
depends: stress/reboot_check
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/pm_log_check_reboot.100.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff_check
estimated_duration: 1.0
depends: stress/poweroff
command: pm_log_check --log-level=notset $PLAINBOX_SESSION_SHARE/pm_test.poweroff.100.log $PLAINBOX_SESSION_SHARE/pm_log_check_poweroff.100.log
_description: Check logs for the stress poweroff (100 cycles) test case
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/poweroff_check_log
estimated_duration: 1.0
depends: stress/poweroff_check
command:
set -o pipefail
tar cvz $PLAINBOX_SESSION_SHARE/pm_log_check_poweroff.100.log | base64
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/graphics
estimated_duration: 600.0
requires:
package.name == 'x11-apps'
user: root
environ: PLAINBOX_SESSION_SHARE
command: graphics_stress_test --iterations 20 -b repeat -d -o $PLAINBOX_SESSION_SHARE/graphics-stress-results && echo "Graphics Stress Test completed successfully" || echo "Graphics Stress Test completed, but there are errors. Please see the log $PLAINBOX_SESSION_SHARE/graphics-stress-results for details" && false
_description:
Run the graphics stress test. This test can take a few minutes.
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/graphics-tarball
estimated_duration: 1.0
requires:
package.name == 'x11-apps'
command: [ -f $PLAINBOX_SESSION_SHARE/graphics-stress-results ] && tar cvz $PLAINBOX_SESSION_SHARE/graphics-stress-results | base64
_description: Attaches the graphics stress results to the submission.
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/usb
estimated_duration: 710.0
user: root
command: removable_storage_test -s 10240000 -c 100 -i 3 usb
_description: Runs a test that transfers 100 10MB files 3 times to usb.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::stress
id: stress/sdhc
user: root
_summary: Stress test for SDHC card
estimated_duration: 780.0
command: removable_storage_test -s 10240000 -c 100 -i 3 sdio scsi usb --memorycard
_description:
PURPOSE:
This test will transfers 100 10MB files 3 times to a SDHC card, to
check that the systems media card reader can transfer large amounts
of data.
STEPS:
1. Insert a SDHC card into the reader and then Click "Test".
If a file browser opens up, you can safely close it.
2. Do not remove the device during this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::stress
id: stress/network_restart
estimated_duration: 1500.0
user: root
environ: PLAINBOX_SESSION_SHARE
command: network_restart -t 100 -o $PLAINBOX_SESSION_SHARE
_description: Ping ubuntu.com and restart network interfaces 100 times
plugin: attachment
category_id: 2013.com.canonical.plainbox::stress
id: stress/network_restart_log
estimated_duration: 1.0
depends: stress/network_restart
command: file=$PLAINBOX_SESSION_SHARE/network_restart.log; if [ -e "$file" ]; then iconv -t 'ascii' -c "$file"; fi
plugin: manual
category_id: 2013.com.canonical.plainbox::stress
id: stress/wireless_hotkey
estimated_duration: 60.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
To make sure that stressing the wifi hotkey does not cause applets to disappear from the panel or the system to lock up
STEPS:
1. Log in to desktop
2. Press wifi hotkey at a rate of 1 press per second and slowly increase the speed of the tap, until you are tapping as fast as possible
VERIFICATION:
Verify the system is not frozen and the wifi and bluetooth applets are still visible and functional
plainbox-provider-checkbox-0.25/jobs/bluetooth.txt.in 0000664 0001750 0001750 00000013272 12646152433 024211 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::bluetooth
id: bluetooth/detect-output
estimated_duration: 1.2
requires:
package.name == 'bluez'
device.category == 'BLUETOOTH'
command:
if rfkill list bluetooth | grep -q 'Hard blocked: yes'; then
echo "rfkill shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'; then
echo "rfkill shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
output=$(hcitool dev | tail -n+2 | awk '{print $2}' | tee $PLAINBOX_SESSION_SHARE/bluetooth_address)
echo "$output"
if [ -z "$output" ]; then
"BT hardware not available"
exit 1
fi
_description:
Automated test to store bluetooth device information in checkbox report
plugin: manual
category_id: 2013.com.canonical.plainbox::bluetooth
id: bluetooth/browse-files
depends: bluetooth/detect-output
estimated_duration: 120.0
_description:
PURPOSE:
This test will check that bluetooth connection works correctly
STEPS:
1. Enable bluetooth on any mobile device (PDA, smartphone, etc.)
2. Click on the bluetooth icon in the menu bar
3. Select 'Setup new device'
4. Look for the device in the list and select it
5. In the device write the PIN code automatically chosen by the wizard
6. The device should pair with the computer
7. Right-click on the bluetooth icon and select browse files
8. Authorize the computer to browse the files in the device if needed
9. You should be able to browse the files
VERIFICATION:
Did all the steps work?
plugin: manual
category_id: 2013.com.canonical.plainbox::bluetooth
id: bluetooth/file-transfer
depends: bluetooth/browse-files bluetooth/detect-output
estimated_duration: 120.0
_description:
PURPOSE:
This test will check that you can transfer information through a bluetooth connection
STEPS:
1. Make sure that you're able to browse the files in your mobile device
2. Copy a file from the computer to the mobile device
3. Copy a file from the mobile device to the computer
VERIFICATION:
Were all files copied correctly?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::bluetooth
id: bluetooth/audio-a2dp
depends: bluetooth/detect-output
estimated_duration: 120.0
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
idx=`pactl list cards short | awk '/bluez/{print $1}'`
bt_sink=`pactl list sinks short | awk '/bluez/{print $2}'`
pactl set-card-profile $idx a2dp
pactl set-default-sink $bt_sink
gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check the High Fidelity Playback (A2DP) capability of your Bluetooth device,
to see if you can hear audio from it.
STEPS:
1. Enable and pair the bluetooth headset
2. Click "Test" to play a brief tone on your Bluetooth device, if it failed to set the Mode to A2DP,
please select the device and change it manually in the "Sound Settings"
VERIFICATION:
Did you hear the tone?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::bluetooth
id: bluetooth/audio
depends: bluetooth/detect-output
estimated_duration: 120.0
command: audio_bluetooth_loopback_test
_description:
PURPOSE:
This test will check the Telephony Duplex capability of your bluetooth device,
to see if you can record and hear audio from it simultaneously.
STEPS:
1. Enable the bluetooth headset
2. Click on the bluetooth icon in the menu bar
3. Select "Setup new device"
4. Look for the device in the list and pair it
5. Click the sound icon
6. Click "Sound Settings"
7. Select device and ensure Mode is set to "Telephony Duplex (HSP/HFP)"
8. Click "Test" to record and play for five seconds in the bluetooth device
VERIFICATION:
Did you hear the sound you recorded in the bluetooth with a slight intended delay?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::bluetooth
id: bluetooth/HID
depends: bluetooth/detect-output
estimated_duration: 120.0
command: keyboard_test
_description:
PURPOSE:
This test will check that you can use a BlueTooth HID device
STEPS:
1. Enable either a BT mouse or keyboard
2. Click on the bluetooth icon in the menu bar
3. Select 'Setup new device'
4. Look for the device in the list and select it
5. For mice, perform actions such as moving the pointer, right and left button clicks and double clicks
6. For keyboards, commence the test to launch a small tool. Enter some text into the tool and close it.
VERIFICATION:
Did the device work as expected?
plugin: shell
category_id: 2013.com.canonical.plainbox::bluetooth
id: bluetooth/file_transfer_stress
estimated_duration: 300.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in plainbox.conf"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
bluetooth_transfer_stress $BTDEVADDR
_description:
This is an automated Bluetooth file transfer test. It sends a large file
to the device specified by the BTDEVADDR environment variable, then
retrieves it again using Bluetooth and verifies the checksum to ensure the
transfer didn't corrupt the file.
plainbox-provider-checkbox-0.25/jobs/input.txt.in 0000664 0001750 0001750 00000006505 12646152433 023344 0 ustar sylvain sylvain 0000000 0000000 plugin: local
_summary: Pointing device tests.
id: input/pointing
estimated_duration: 30.0
requires:
device.category == 'MOUSE' or device.category == 'TOUCHPAD' or device.category == 'TOUCHSCREEN'
_description: Pointing device tests.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=MOUSE" -w "category=TOUCHPAD" -w "category=TOUCHSCREEN"'
plugin: manual
category_id: 2013.com.canonical.plainbox::input
id: input/pointing_`echo "${product}_${category}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`_`basename $path`
requires: device.path == "$path"
description:
PURPOSE:
This will test your $product device
STEPS:
1. Move the cursor with your $product.
VERIFICATION:
Did the cursor move?
EOF
plugin: manual
category_id: 2013.com.canonical.plainbox::input
id: input/mouse
estimated_duration: 30.0
_description:
PURPOSE:
This test will test your pointing device
STEPS:
1. Move the cursor using the pointing device or touch the screen.
2. Perform some single/double/right click operations.
VERIFICATION:
Did the pointing device work as expected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::input
id: input/keyboard
estimated_duration: 30.0
command: keyboard_test
requires: device.category == 'KEYBOARD'
_description:
PURPOSE:
This test will test your keyboard
STEPS:
1. Click on Test
2. On the open text area, use your keyboard to type something
VERIFICATION:
Is your keyboard working properly?
plugin: manual
category_id: 2013.com.canonical.plainbox::input
id: input/accelerometer_verify
estimated_duration: 30.0
_description:
PURPOSE:
Manual detection of accelerometer.
STEPS:
1. Look at the specifications for your system.
VERIFICATION:
Is this system supposed to have an accelerometer?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::input
id: input/accelerometer
estimated_duration: 60.0
user: root
depends: input/accelerometer_verify
command: accelerometer_test -m
_description:
PURPOSE:
This test will test your accelerometer to see if it is detected
and operational as a joystick device.
STEPS:
1. Click on Test
2. Tilt your hardware in the directions onscreen until the axis threshold is met.
VERIFICATION:
Is your accelerometer properly detected? Can you use the device?
plugin: local
id: input/clicking
estimated_duration: 1.0
requires:
device.category == 'MOUSE' or device.category == 'TOUCHPAD'
_summary: Create click tests for pointing devices.
_description: Click tests for pointing devices.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=MOUSE" -w "category=TOUCHPAD"'
plugin: manual
category_id: 2013.com.canonical.plainbox::input
estimated_duration: 30.0
id: input/clicking_`echo "${product}_${category}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`_`basename $path`
requires: device.path == "$path"
_summary: Check button functionality for $product
_description:
PURPOSE:
This will test the buttons of your $product device
STEPS:
1. Click the left button with your $product.
2. Click the right button with your $product.
3. Click the middle button with your $product (if available).
4. Double-click the left button with your $product.
VERIFICATION:
Did these buttons work as expected?
EOF
plainbox-provider-checkbox-0.25/jobs/suspend.txt.in 0000664 0001750 0001750 00000334655 12646152433 023700 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/network_before_suspend
depends: ethernet/detect
estimated_duration: 1.2
_description: Record the current network before suspending.
command: set -o pipefail; gateway_ping_test | tee $PLAINBOX_SESSION_SHARE/network_before_suspend.txt
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/resolution_before_suspend
estimated_duration: 1.2
_description: Record the current resolution before suspending.
command: xrandr -q |grep '*'| awk '{print $1}' > $PLAINBOX_SESSION_SHARE/resolution_before_suspend.txt
plugin: local
id: suspend/generator_resolution_before_suspend
_description: Record the current resolution before suspending.
_summary: Record the current resolution before suspending.
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_resolution_before_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: graphics/`echo ${index}`_switch_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
estimated_duration: 1.2
_description: Record the current resolution before suspending.
command: xrandr -q |grep '*'| awk '{print $1}' > $PLAINBOX_SESSION_SHARE/`echo ${index}`_resolution_before_suspend.txt
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/audio_before_suspend
estimated_duration: 1.0
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
_description: Record mixer settings before suspending.
command: audio_settings store --file=$PLAINBOX_SESSION_SHARE/audio_settings_before_suspend
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/cpu_before_suspend
estimated_duration: 1.2
_description: Verify that all the CPUs are online before suspending
command: cpuinfo_resource > $PLAINBOX_SESSION_SHARE/cpuinfo_before_suspend
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/memory_before_suspend
estimated_duration: 1.2
_description:
Dumps memory info to a file for comparison after suspend test has been run
command: meminfo_resource > $PLAINBOX_SESSION_SHARE/meminfo_before_suspend
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_before_suspend
depends: wireless/wireless_connection
requires: device.category == 'WIRELESS'
command: nmcli -t -f UUID con status > $PLAINBOX_SESSION_SHARE/connections && connect_wireless && gateway_ping_test --interface=`(nmcli dev list 2>/dev/null || nmcli dev show) | grep -B 1 -e 'wireless' -e 'wifi' | grep GENERAL.DEVICE | awk '{print $2}'` && for con in `cat $PLAINBOX_SESSION_SHARE/connections`; do nmcli con up uuid "$con"; done
estimated_duration: 20.0
_description:
This test disconnects all connections and then connects to the wireless
interface. It then checks the connection to confirm it's working as expected.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_before_suspend_ether_auto_device{__index__}_{interface}
depends: ethernet/detect
estimated_duration: 20.0
requires:
device.path == '{path}'
package.name == 'iperf'
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command: network -i {interface} -t iperf
_description:
This test executes iperf connection performance/stability against device {__index__} ({interface}) before suspend.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'WIRELESS'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_before_suspend_wifi_auto_device{__index__}_{interface}
depends: wireless/wireless_connection
estimated_duration: 20.0
requires:
device.path == '{path}'
package.name == 'iperf'
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command: network -i {interface} -t iperf
_description:
This test executes iperf connection performance/stability against device {__index__} ({interface}) before suspend.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_before_suspend_mobilebroadband_gsm_auto
depends: mobilebroadband/gsm_connection
estimated_duration: 20.0
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command:
INTERFACE=`(nmcli -t -f GENERAL -m tabular dev list 2>/dev/null || nmcli -t -f GENERAL -m tabular dev show) |grep gsm |cut -d ":" -f 13`
[ -z $INTERFACE ] && exit 1
network test -i $INTERFACE -t iperf
_description:
This test executes iperf connection performance/stability against the broadband device found on the system before suspend.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_before_suspend_mobilebroadband_cdma_auto
depends: mobilebroadband/cdma_connection
estimated_duration: 20.0
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command:
INTERFACE=`(nmcli -t -f GENERAL -m tabular dev list 2>/dev/null || nmcli -t -f GENERAL -m tabular dev show) |grep cdma |cut -d ":" -f 13`
[ -z $INTERFACE ] && exit 1
network test -i $INTERFACE -t iperf
_description:
This test executes iperf connection performance/stability against the broadband device found on the system before suspend.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_send_before_suspend
estimated_duration: 10.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR send 2>&1 | ansi_parser
_description:
This is an automated Bluetooth file transfer test. It sends an image to the device specified by the BTDEVADDR environment variable.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_browse_before_suspend
estimated_duration: 10.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR browse 2>&1 | ansi_parser
_description:
This is an automated Bluetooth test. It emulates browsing on a remote device specified by the BTDEVADDR environment variable.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_get_before_suspend
estimated_duration: 20.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR get 2>&1 | ansi_parser
_description:
This is an automated Bluetooth test. It receives the given file from a remote host specified by the BTDEVADDR environment variable
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/suspend_advanced
requires:
sleep.mem == 'supported'
rtc.state == 'supported'
user: root
environ: PLAINBOX_SESSION_SHARE
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
set -o pipefail; fwts_test -f none -l $PLAINBOX_SESSION_SHARE/suspend_single -s s3 --s3-sleep-delay=30 --s3-device-check --s3-device-check-delay=45 | tee $PLAINBOX_SESSION_SHARE/suspend_single_times.log
else
echo "Calling sleep_test"
set -o pipefail; sleep_test -p | tee $PLAINBOX_SESSION_SHARE/2_suspend_single_times.log
fi
estimated_duration: 90.0
_description:
PURPOSE:
This test will check suspend and resume
STEPS:
1. Click "Test" and your system will suspend for about 30 - 60 seconds
2. Observe the Power LED to see if it blinks or changes color during suspend
3. If your system does not wake itself up after 60 seconds, please press the power button momentarily to wake the system manually
4. If your system fails to wake at all and must be rebooted, restart System Testing after reboot and mark this test as Failed
VERIFICATION:
Did your system suspend and resume correctly?
(NOTE: Please only consider whether the system successfully suspended and resumed. Power/Suspend LED verification will occur after this test is completed.)
id: suspend/generator_suspend_after_switch_to_card
requires: device.category == 'VIDEO'
_description: Suspend after graphics card switch tests
_summary: Suspend after graphics card switch tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires:
sleep.mem == 'supported'
rtc.state == 'supported'
depends: graphics/`echo ${index}`_switch_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
user: root
environ: PLAINBOX_SESSION_SHARE
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
set -o pipefail; fwts_test -f none -l $PLAINBOX_SESSION_SHARE/`echo ${index}`_suspend_single -s s3 --s3-sleep-delay=30 --s3-device-check --s3-device-check-delay=45 | tee $PLAINBOX_SESSION_SHARE/`echo ${index}`_suspend_single_times.log
else
echo "Calling sleep_test"
set -o pipefail; sleep_test -p | tee $PLAINBOX_SESSION_SHARE/`echo ${index}`_suspend_single_times.log
fi
estimated_duration: 90.0
_summary: Test suspend/resume after switching to $product
_description:
PURPOSE:
This test will check suspend and resume after switching to $product graphics card.
STEPS:
1. Ensure you have switched to $product graphics card.
2. Click "Test" and your system will suspend for about 30 - 60 seconds
3. Observe the Power LED to see if it blinks or changes color during suspend
4. If your system does not wake itself up after 60 seconds, please press the power button momentarily to wake the system manually
5. If your system fails to wake at all and must be rebooted, restart System Testing after reboot and mark this test as Failed
VERIFICATION:
Did your system suspend and resume correctly after switching to $product graphics card?
(NOTE: Please only consider whether the system successfully suspended and resumed. Power/Suspend LED verification will occur after this test is completed.)
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/suspend_advanced_auto
requires:
sleep.mem == 'supported'
rtc.state == 'supported'
_description:
This is the automated version of suspend/suspend_advanced.
user: root
environ: PLAINBOX_SESSION_SHARE
command: set -o pipefail; fwts_test -f none -l $PLAINBOX_SESSION_SHARE/suspend_single -s s3 --s3-sleep-delay=30 --s3-device-check --s3-device-check-delay=45 | tee $PLAINBOX_SESSION_SHARE/suspend_single_times.log
estimated_duration: 90.000
id: suspend/generator_hybrid_sleep
_description: Hybrid sleep test
_summary: Hybrid sleep test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_hybrid_sleep_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
user: root
command:
set -o pipefail; fwts_test -f none -l $PLAINBOX_SESSION_SHARE/`echo ${index}`_hybrid_sleep_single -s s3 --s3-hybrid --s3-sleep-delay=30 --s3-device-check --s3-device-check-delay=45 --pm-method=pm-utils | tee $PLAINBOX_SESSION_SHARE/`echo ${index}`_hybrid_sleep_single_times.log
estimated_duration: 90.0
_description:
PURPOSE:
This test will check hybrid sleep and resume
STEPS:
1. Click "Test" and your system will go into hybrid sleep mode for about 30 - 60 seconds
2. Observe the Power LED to see if it blinks or changes color during suspend
3. If your system does not wake itself up after 60 seconds, please press the power button momentarily to wake the system manually
4. If your system fails to wake at all and must be rebooted, restart System Testing after reboot and mark this test as Failed
VERIFICATION:
Did your system enter hybrid sleep and then resume correctly?
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/suspend-single-log-check
estimated_duration: 1.2
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_single.log ] && sleep_test_log_check -v s3 $PLAINBOX_SESSION_SHARE/suspend_single.log
_description:
Automated check of the suspend log to look for errors reported by fwts
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/suspend-single-log-attach
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_single.log ] && cat $PLAINBOX_SESSION_SHARE/suspend_single.log
_description:
Attaches the log from the single suspend/resume test to the results
id: suspend/generator_suspend-single-log-attach
_description: Suspend log attach
_summary: Suspend log attach
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_suspend-single-log-attach_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
command: [ -e $PLAINBOX_SESSION_SHARE/`echo ${index}`_suspend_single.log ] && cat $PLAINBOX_SESSION_SHARE/`echo ${index}`_suspend_single.log
_description:
Attaches the log from the single suspend/resume test to the results
EOF
id: suspend/generator_hybrid-sleep-single-log-check
_description: Hybrid sleep log check test
_summary: Hybrid sleep log check test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_hybrid-sleep-single-log-check
depends: suspend/`echo ${index}`_hybrid_sleep_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
estimated_duration: 1.2
command: [ -e $PLAINBOX_SESSION_SHARE/`echo ${index}`_hybrid_sleep_single.log ] && sleep_test_log_check -v s3 $PLAINBOX_SESSION_SHARE/`echo ${index}`_hybrid_sleep_single.log
_description:
Automated check of the hybrid sleep log to look for errors reported by fwts
EOF
id: suspend/generator_hybrid-sleep-single-log-attach
_description: Hybrid sleep log attach
_summary: Hybrid sleep log attach
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_hybrid-sleep-single-log-attach_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_hybrid_sleep_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
command: [ -e $PLAINBOX_SESSION_SHARE/`echo ${index}`_hybrid_sleep_single.log ] && cat $PLAINBOX_SESSION_SHARE/`echo ${index}`_hybrid_sleep_single.log
_description:
Attaches the log from the single hybrid sleep/resume test to the results
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/suspend-time-check
estimated_duration: 1.2
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_single_times.log ] && sleep_time_check $PLAINBOX_SESSION_SHARE/suspend_single_times.log
_description:
Checks the sleep times to ensure that a machine suspends and resumes within a given threshold
id: suspend/generator_suspend-time-check
_description: Suspend time check test
_summary: Suspend time check test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_suspend-time-check_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
estimated_duration: 1.2
command: [ -e $PLAINBOX_SESSION_SHARE/`echo ${index}`_suspend_single_times.log ] && sleep_time_check $PLAINBOX_SESSION_SHARE/`echo ${index}`_suspend_single_times.log
_description: Checks the sleep times to ensure that a machine suspends and resumes within a given threshold
EOF
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: power-management/usb_wakeup_keyboard
user: root
depends: suspend/suspend_advanced
estimated_duration: 120.0
command: pm-suspend
_description:
PURPOSE:
Wake up by USB keyboard
STEPS:
1. Enable "Wake by USB KB/Mouse" item in BIOS
2. Press "Test" to enter suspend (S3) mode
3. Press any key of USB keyboard to wake system up
VERIFICATION:
Did the system wake up from suspend mode when you pressed a keyboard key?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: power-management/usb_wakeup_mouse
user: root
depends: suspend/suspend_advanced
estimated_duration: 120.0
command: pm-suspend
_description:
PURPOSE:
Wake up by USB mouse
STEPS:
1. Enable "Wake by USB KB/Mouse" item in BIOS
2. Press "Test" to enter suspend (S3) mode
3. Press any button of USB mouse to wake system up
VERIFICATION:
Did the system wake up from suspend mode when you pressed the mouse button?
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/network_after_suspend
estimated_duration: 20.0
depends: suspend/suspend_advanced suspend/network_before_suspend
_description: Test the network after resuming.
command: network_wait; gateway_ping_test | diff $PLAINBOX_SESSION_SHARE/network_before_suspend.txt -
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/resolution_after_suspend
depends: suspend/suspend_advanced suspend/resolution_before_suspend
estimated_duration: 1.2
_description: Test to see that we have the same resolution after resuming as before.
command: xrandr -q |grep '*'| awk '{print $1}' | diff $PLAINBOX_SESSION_SHARE/resolution_before_suspend.txt -
plugin: local
id: suspend/generator_resolution_after_suspend
_description: Resolution consistency check after suspend with the valuse we got before suspend.
_summary: Resolution consistency check after suspend with the valuse we got before suspend.
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_resolution_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
estimated_duration: 1.2
depends: suspend/`echo ${index}`_resolution_before_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'` suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
_description: Test to see that we have the same resolution after resuming as before.
command: xrandr -q |grep '*'| awk '{print $1}' | diff $PLAINBOX_SESSION_SHARE/`echo ${index}`_resolution_before_suspend.txt -
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/audio_after_suspend
estimated_duration: 1.0
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
depends: suspend/suspend_advanced suspend/audio_before_suspend
_description: Verify that mixer settings after suspend are the same as before suspend.
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/audio_settings_after_suspend
diff $PLAINBOX_SESSION_SHARE/audio_settings_before_suspend $PLAINBOX_SESSION_SHARE/audio_settings_after_suspend
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/audio_after_suspend_auto
estimated_duration: 1.2
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
depends: suspend/suspend_advanced_auto suspend/audio_before_suspend
_description: Verify that mixer settings after suspend are the same as before suspend.
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/audio_settings_after_suspend
diff $PLAINBOX_SESSION_SHARE/audio_settings_before_suspend $PLAINBOX_SESSION_SHARE/audio_settings_after_suspend
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/speaker-headphone-plug-detection-after-suspend
depends: suspend/suspend_advanced
estimated_duration: 60.0
requires:
device.category == 'AUDIO'
package.name == 'pulseaudio-utils'
command: pulse-active-port-change sinks
_description:
PURPOSE:
Check that system detects speakers or headphones being plugged in after suspend
STEPS:
1. Prepare a pair of headphones or speakers with a standard 3.5mm jack
2. Locate the speaker / headphone jack on the device under test
3. Run the test (you have 30 seconds from now on)
4. Plug headphones or speakers into the appropriate jack
5. Unplug the device for subsequent tests.
VERIFICATION:
Verification is automatic, no action is required.
The test times out after 30 seconds (and fails in that case).
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/microphone-plug-detection-after-suspend
depends: suspend/suspend_advanced
estimated_duration: 60.0
requires:
device.category == 'AUDIO'
package.name == 'pulseaudio-utils'
command: pulse-active-port-change sources
_description:
PURPOSE:
Check that system detects a microphone being plugged in after suspend
STEPS:
1. Prepare a microphone with a standard 3.5mm jack
2. Locate the microphone jack on the device under test.
Keep in mind that it may be shared with the headphone jack.
3. Run the test (you have 30 seconds from now on)
4. Plug the microphone into the appropriate jack
5. Unplug the device for subsequent tests.
VERIFICATION:
Verification is automatic, no action is required.
The test times out after 30 seconds (and fails in that case).
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/playback_headphones-after-suspend
estimated_duration: 20.0
depends: audio/list_devices suspend/suspend_advanced
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that headphones connector works correctly after suspend
STEPS:
1. Connect a pair of headphones to your audio device
2. Commence the test to play a sound to your audio device
VERIFICATION:
Did you hear a sound through the headphones and did the sound play without any distortion, clicks or other strange noises from your headphones?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/alsa_record_playback_external-after-suspend
estimated_duration: 20.0
depends: suspend/playback_headphones-after-suspend suspend/suspend_advanced
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that recording sound using an external microphone works correctly after suspend
STEPS:
1. Connect a microphone to your microphone port
2. Click "Test", then speak into the external microphone
3. After a few seconds, your speech will be played back to you
VERIFICATION:
Did you hear your speech played back?
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/cpu_after_suspend
estimated_duration: 1.2
depends: suspend/suspend_advanced suspend/cpu_before_suspend
_description: Verify that all CPUs are online after resuming.
command: cpuinfo_resource | diff $PLAINBOX_SESSION_SHARE/cpuinfo_before_suspend -
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/cpu_after_suspend_auto
estimated_duration: 1.2
depends: suspend/suspend_advanced_auto suspend/cpu_before_suspend
_description: Verify that all CPUs are online after resuming.
command: cpuinfo_resource | diff $PLAINBOX_SESSION_SHARE/cpuinfo_before_suspend -
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/memory_after_suspend
estimated_duration: 1.2
depends: suspend/suspend_advanced suspend/memory_before_suspend
_description:
Verify that all memory is available after resuming from suspend.
command: meminfo_resource | diff $PLAINBOX_SESSION_SHARE/meminfo_before_suspend -
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/memory_after_suspend_auto
estimated_duration: 1.2
depends: suspend/suspend_advanced_auto suspend/memory_before_suspend
_description:
Verify that all memory is available after resuming from suspend.
command: meminfo_resource | diff $PLAINBOX_SESSION_SHARE/meminfo_before_suspend -
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/display_after_suspend
estimated_duration: 120.0
depends: suspend/suspend_advanced
_description:
PURPOSE:
This test will check that the display is correct after suspend and resume
STEPS:
1. Check that your display does not show up visual artifacts after resuming.
VERIFICATION:
Does the display work normally after resuming from suspend?
id: suspend/generator_display_after_suspend
requires: device.category == 'VIDEO'
_description: Display after suspend tests
_summary: Display after suspend tests
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_display_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
_summary: Test display function after suspend for $product
_description:
PURPOSE:
This test will check that the display is correct after suspend and resume on the $product graphics card.
STEPS:
1. Check that your display does not show up visual artifacts after resuming.
VERIFICATION:
Does the display work normally after resuming from suspend using the $product graphics card?
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_after_suspend
depends: suspend/suspend_advanced suspend/wireless_before_suspend
requires:
device.category == 'WIRELESS'
command: connect_wireless && gateway_ping_test --interface=`(nmcli dev list 2>/dev/null || nmcli dev show) | grep -B 1 -e wireless -e wifi | grep GENERAL.DEVICE | awk '{print $2}'` && for con in `cat $PLAINBOX_SESSION_SHARE/connections`; do nmcli con up uuid "$con"; done
estimated_duration: 20.0
_description:
This test checks that the wireless interface is working after suspending the system. It
disconnects all interfaces and then connects to the wireless interface and checks that the
connection is working as expected.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_bg
depends: suspend/suspend_advanced
estimated_duration: 20.0
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_BG_SSID WPA_BG_PSK
command:
trap "nmcli con delete id $WPA_BG_SSID" EXIT
if create_connection wifi $WPA_BG_SSID --security=wpa --key=$WPA_BG_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11b/g protocols after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_bg
depends: suspend/suspend_advanced
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_BG_SSID
command:
trap "nmcli con delete id $OPEN_BG_SSID" EXIT
if create_connection wifi $OPEN_BG_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11b/g protocols after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_n
depends: suspend/suspend_advanced
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_N_SSID WPA_N_PSK
command:
trap "nmcli con delete id $WPA_N_SSID" EXIT
if create_connection wifi $WPA_N_SSID --security=wpa --key=$WPA_N_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11n protocol after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_n
depends: suspend/suspend_advanced
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_N_SSID
command:
trap "nmcli con delete id $OPEN_N_SSID" EXIT
if create_connection wifi $OPEN_N_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11n protocol after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_ac
depends: suspend/suspend_advanced
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: WPA_AC_SSID WPA_AC_PSK
command:
trap "nmcli con delete id $WPA_AC_SSID" EXIT
if create_connection wifi $WPA_AC_SSID --security=wpa --key=$WPA_AC_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11ac protocol after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_ac
depends: suspend/suspend_advanced
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: OPEN_AC_SSID
command:
trap "nmcli con delete id $OPEN_AC_SSID" EXIT
if create_connection wifi $OPEN_AC_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11ac protocol after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_bg_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_BG_SSID WPA_BG_PSK
command:
trap "nmcli con delete id $WPA_BG_SSID" EXIT
if create_connection wifi $WPA_BG_SSID --security=wpa --key=$WPA_BG_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11b/g protocols after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_bg_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_BG_SSID
command:
trap "nmcli con delete id $OPEN_BG_SSID" EXIT
if create_connection wifi $OPEN_BG_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11b/g protocols after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_n_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: WPA_N_SSID WPA_N_PSK
command:
trap "nmcli con delete id $WPA_N_SSID" EXIT
if create_connection wifi $WPA_N_SSID --security=wpa --key=$WPA_N_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11n protocol after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_n_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
user: root
environ: OPEN_N_SSID
command:
trap "nmcli con delete id $OPEN_N_SSID" EXIT
if create_connection wifi $OPEN_N_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11n protocol after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_ac_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: WPA_AC_SSID WPA_AC_PSK
command:
trap "nmcli con delete id $WPA_AC_SSID" EXIT
if create_connection wifi $WPA_AC_SSID --security=wpa --key=$WPA_AC_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11ac protocol after the system has been suspended.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_ac_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 1.2
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'multiple'
IEEE_80211.ac == 'supported'
user: root
environ: OPEN_AC_SSID
command:
trap "nmcli con delete id $OPEN_AC_SSID" EXIT
if create_connection wifi $OPEN_AC_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
Tests that the systems wireless hardware can connect to a router using no
security and the 802.11ac protocol after the system has been suspended.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'NETWORK'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_after_suspend_ether_auto_device{__index__}_{interface}
depends: suspend/suspend_advanced
estimated_duration: 30.0
requires:
device.path == '{path}'
package.name == 'iperf'
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command: network -i {interface} -t iperf
_description:
This test executes iperf connection performance/stability against device {__index__} ({interface}) after suspend.
unit: template
template-unit: job
template-resource: device
template-filter: device.category == 'WIRELESS'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_after_suspend_wifi_auto_device{__index__}_{interface}
depends: suspend/suspend_advanced
estimated_duration: 30.0
requires:
device.path == '{path}'
package.name == 'iperf'
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command: network -i {interface} -t iperf
_description:
This test executes iperf connection performance/stability against device {__index__} ({interface}) after suspend.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_after_suspend_mobilebroadband_gsm_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 20.0
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command:
INTERFACE=`(nmcli -t -f GENERAL -m tabular dev list 2>/dev/null || nmcli -t -f GENERAL -m tabular dev show) |grep gsm |cut -d ":" -f 13`
[ -z $INTERFACE ] && exit 1
network test -i $INTERFACE -t iperf
_description:
This test executes iperf connection performance/stability against the broadband device found on the system after suspend.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/iperf_after_suspend_mobilebroadband_cdma_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 20.0
user: root
environ: TEST_TARGET_FTP TEST_TARGET_IPERF TEST_USER TEST_PASS
command:
INTERFACE=`(nmcli -t -f GENERAL -m tabular dev list 2>/dev/null || nmcli -t -f GENERAL -m tabular dev show) |grep cdma |cut -d ":" -f 13`
[ -z $INTERFACE ] && exit 1
network test -i $INTERFACE -t iperf
_description:
This test executes iperf connection performance/stability against the broadband device found on the system after suspend.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_bg_manual
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID ROUTER_PSK
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID --security=wpa --key=$ROUTER_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11b/g protocols.
STEPS:
1. Open your routers configuration tool
2. Change the settings to only accept connections on the B and G wireless bands
3. Make sure the SSID is set to ROUTER_SSID
4. Change the security settings to use WPA2 and ensure the PSK matches that set in ROUTER_PSK
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_bg_manual
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using
no security and the 802.11b/g protocols.
STEPS:
1. Open your routers configuration tool
2. Change the settings to only accept connections on the B and G wireless bands
3. Make sure the SSID is set to ROUTER_SSID
4. Change the security settings to use no security
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_n_manual
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID ROUTER_PSK
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID --security=wpa --key=$ROUTER_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11n protocols.
STEPS:
1. Open your routers configuration tool
2. Change the settings to only accept connections on the N wireless band
3. Make sure the SSID is set to ROUTER_SSID
4. Change the security settings to use WPA2 and ensure the PSK matches that set in ROUTER_PSK
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_n_manual
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using
no security and the 802.11n protocol.
STEPS:
1. Open your routers configuration tool
2. Change the settings to only accept connections on the N wireless band
3. Make sure the SSID is set to ROUTER_SSID
4. Change the security settings to use no security
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_wpa_ac_manual
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID ROUTER_PSK
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID --security=wpa --key=$ROUTER_PSK; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using WPA
security and the 802.11ac protocol.
STEPS:
1. Open your routers configuration tool
2. Change the settings to only accept connections on the 802.11ac protocol.
3. Make sure the SSID is set to ROUTER_SSID
4. Change the security settings to use WPA2 and ensure the PSK matches that set in ROUTER_PSK
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wireless_connection_after_suspend_open_ac_manual
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'WIRELESS'
environment.ROUTERS == 'single'
user: root
environ: ROUTER_SSID
command:
trap "nmcli con delete id $ROUTER_SSID" EXIT
if create_connection wifi $ROUTER_SSID; then
connect_wireless # lp:1471663
INTERFACE=`nmcli dev status | awk '/802-11-wireless|wifi/ {print $1}'`
iw dev $INTERFACE link
gateway_ping_test --interface=$INTERFACE
STATUS=$?
# We reconnect the Ethernet connection if any (lp:1471663)
WIRED=$(nmcli -f UUID,TYPE c | grep -oP ".*(?=\s+.*ethernet)")
if [[ ! -z $WIRED ]]; then
nmcli c up uuid $WIRED
fi
exit $STATUS
else
exit 1
fi
_description:
PURPOSE:
Tests that the systems wireless hardware can connect to a router using
no security and the 802.11ac protocol.
STEPS:
1. Open your routers configuration tool
2. Change the settings to only accept connections on the 802.11ac protocol.
3. Make sure the SSID is set to ROUTER_SSID
4. Change the security settings to use no security
5. Commence the test to create a connection to the router and test the connection
VERIFICATION:
Verification is automated, do not change the automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_detect_after_suspend
depends: suspend/suspend_advanced bluetooth/detect-output
estimated_duration: 1.2
requires:
package.name == 'bluez'
device.category == 'BLUETOOTH'
command:
if rfkill list bluetooth | grep -q 'Hard blocked: yes'; then
echo "rfkill shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'; then
echo "rfkill shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
output=$(hcitool dev | tail -n+2 | awk '{print $2}')
echo $output | diff $PLAINBOX_SESSION_SHARE/bluetooth_address -
if [ -z "$output" ]; then
echo "BT hardware not available"
exit 1
fi
_description:
This test grabs the hardware address of the bluetooth adapter after suspend and compares it to the address grabbed before suspend.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_send_after_suspend
depends: suspend/suspend_advanced
estimated_duration: 10.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR send 2>&1 | ansi_parser
_description:
This is an automated Bluetooth file transfer test. It sends an image to the device specified by the BTDEVADDR environment variable.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_send_after_suspend_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 10.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR send 2>&1 | ansi_parser
_description:
This is an automated Bluetooth file transfer test. It sends an image to the device specified by the BTDEVADDR environment variable.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_browse_after_suspend
depends: suspend/suspend_advanced
estimated_duration: 10.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR browse 2>&1 | ansi_parser
_description:
This is an automated Bluetooth test. It emulates browsing on a remote device specified by the BTDEVADDR environment variable.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_browse_after_suspend_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 20.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR browse 2>&1 | ansi_parser
_description:
This is an automated Bluetooth test. It emulates browsing on a remote device specified by the BTDEVADDR environment variable.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_get_after_suspend
estimated_duration: 20.0
depends: suspend/suspend_advanced
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR get 2>&1 | ansi_parser
_description:
This is an automated Bluetooth test. It receives the given file from a remote host specified by the BTDEVADDR environment variable
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/bluetooth_obex_get_after_suspend_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 20.0
requires:
package.name == 'bluez'
package.name == 'obexftp'
device.category == 'BLUETOOTH'
command:
if [ -z "$BTDEVADDR" ]
then
echo "btdevaddr option not set to device address of Bluetooth target in checkbox.ini"
exit 1
fi
if rfkill list bluetooth | grep -q 'Hard blocked: yes'
then
echo "rfkill list shows BT is hard blocked"
fi
if rfkill list bluetooth | grep -q 'Soft blocked: yes'
then
echo "rfkill list shows BT is soft blocked, removing before testing"
rfkill unblock bluetooth
sleep 3
fi
set -o pipefail; bluetooth_test $PLAINBOX_PROVIDER_DATA/images/JPEG_Color_Image_Ubuntu.jpg $BTDEVADDR get 2>&1 | ansi_parser
_description:
This is an automated Bluetooth test. It receives the given file from a remote host specified by the BTDEVADDR environment variable
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/cycle_resolutions_after_suspend
estimated_duration: 120.0
requires: package.name == 'xorg'
depends: suspend/suspend_advanced
command: xrandr_cycle --keyword=after_suspend --screenshot-dir $PLAINBOX_SESSION_SHARE
_description:
PURPOSE:
This test will cycle through the detected display modes
STEPS:
1. Click "Test" and the display will cycle trough the display modes
VERIFICATION:
Did your display look fine in the detected mode?
plugin: local
id: suspend/generator_cycle_resolutions_after_suspend
requires: device.category == 'VIDEO'
_description: Cycle resolution after suspend tests
_summary: Cycle resolution after suspend tests
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_cycle_resolutions_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'xorg'
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
estimated_duration: 120.0
command: xrandr_cycle --keyword=`echo ${index}`_after_suspend --screenshot-dir $PLAINBOX_SESSION_SHARE
_description:
PURPOSE:
This test will cycle through the detected display modes
STEPS:
1. Click "Test" and the display will cycle trough the display modes
VERIFICATION:
Did your display look fine in the detected mode?
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/cycle_resolutions_after_suspend_auto
estimated_duration: 1.2
requires: package.name == 'xorg'
depends: suspend/suspend_advanced_auto
_description:
This test will check to make sure supported video modes work after a suspend and resume.
This is done automatically by taking screenshots and uploading them as an attachment.
command: xrandr_cycle --keyword=after_suspend --screenshot-dir $PLAINBOX_SESSION_SHARE
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/xrandr_screens_after_suspend.tar.gz
depends: suspend/cycle_resolutions_after_suspend
command: [ -f $PLAINBOX_SESSION_SHARE/xrandr_screens_after_suspend.tgz ] && base64 $PLAINBOX_SESSION_SHARE/xrandr_screens_after_suspend.tgz
_description: This attaches screenshots from the suspend/cycle_resolutions_after_suspend test to the results submission.
plugin: local
id: suspend/generator_xrandr_screens_after_suspend.tar.gz
_description: Attach screenshots from the suspend/cycle_resolution_after_suspend test to the results submission.
_summary: Attach screenshots from the suspend/cycle_resolution_after_suspend test to the results submission.
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_xrandr_screens_after_suspend.tar.gz
depends: suspend/`echo ${index}`_cycle_resolutions_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
command: [ -f $PLAINBOX_SESSION_SHARE/`echo ${index}`_xrandr_screens_after_suspend.tgz ] && base64 $PLAINBOX_SESSION_SHARE/`echo ${index}`_xrandr_screens_after_suspend.tgz
_description: This attaches screenshots from the suspend/cycle_resolutions_after_suspend test to the results submission.
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/record_playback_after_suspend
estimated_duration: 10.0
depends: suspend/suspend_advanced
requires:
package.name == 'python3-gi'
package.name == 'gir1.2-gstreamer-1.0'
package.name == 'libgstreamer1.0-0'
package.name == 'gstreamer1.0-plugins-good'
package.name == 'gstreamer1.0-pulseaudio'
package.name == 'alsa-base'
device.category == 'AUDIO'
command: audio_test
_description:
This will check to make sure that your audio device works properly after a suspend and resume. This may work fine with speakers and onboard microphone, however, it works best if used with a cable connecting the audio-out jack to the audio-in jack.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/record_playback_after_suspend_auto
estimated_duration: 10.0
depends: suspend/suspend_advanced_auto
requires:
package.name == 'python3-gi'
package.name == 'gir1.2-gstreamer-1.0'
package.name == 'libgstreamer1.0-0'
package.name == 'gstreamer1.0-plugins-good'
package.name == 'gstreamer1.0-pulseaudio'
package.name == 'alsa-base'
device.category == 'AUDIO'
command: audio_test
_description:
This will check to make sure that your audio device works properly after a suspend and resume. This may work fine with speakers and onboard microphone, however, it works best if used with a cable connecting the audio-out jack to the audio-in jack.
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/suspend-auto-single-log-attach
command: [ -e $PLAINBOX_SESSION_SHARE/suspend_auto_single_log ] && cat $PLAINBOX_SESSION_SHARE/suspend_auto_single_log
_description:
Attaches the log from the single suspend/resume test to the results
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/screenshot_after_suspend
estimated_duration: 10.0
depends: suspend/suspend_advanced_auto
requires: package.name == 'fswebcam'
command: set -o pipefail; camera_test still --device=/dev/external_webcam -f ${PLAINBOX_SESSION_SHARE}/screenshot_after_suspend.jpg -q 2>&1 | ansi_parser
_description:
PURPOSE:
Take a screengrab of the current screen after suspend (logged on Unity desktop)
STEPS:
1. Take picture using USB webcam
VERIFICATION:
Review attachment manually later
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
id: screenshot_after_suspend.jpg
depends: suspend/screenshot_after_suspend
command: base64 ${PLAINBOX_SESSION_SHARE}/screenshot_after_suspend.jpg
_description: Attaches the screenshot captured in graphics/screenshot.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/gpu_lockup_after_suspend
estimated_duration: 10.0
requires:
package.name == 'wmctrl'
package.name == 'mesa-utils'
package.name == 'firefox'
depends: suspend/suspend_advanced_auto
command: gpu_test
_description:
PURPOSE:
Do some challenging operations then check for lockup on the GPU
STEPS:
1. Create 2 glxgears windows and move them quickly
2. Switch workspaces with wmctrl
3. Launch an HTML5 video playback in firefox
VERIFICATION:
After a 60s workload, check kern.log for reported GPU errors
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wifi_resume_time
depends: suspend/suspend_advanced
requires:
device.category == 'WIRELESS'
command: network_reconnect_resume_test -t 90 -d wifi
estimated_duration: 0.530
_description:
Checks the length of time it takes to reconnect an existing wifi connection
after a suspend/resume cycle.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/wifi_resume_time_auto
estimated_duration: 1.2
depends: suspend/suspend_advanced_auto
requires:
device.category == 'WIRELESS'
command: network_reconnect_resume_test -t 90 -d wifi
_description:
Checks the length of time it takes to reconnect an existing wifi connection
after a suspend/resume cycle.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/network_resume_time
depends: suspend/suspend_advanced
estimated_duration: 1.2
requires:
device.category == 'NETWORK'
command: network_reconnect_resume_test -t 10 -d wired
_description:
Checks the length of time it takes to reconnect an existing wired connection
after a suspend/resume cycle.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/network_resume_time_auto
depends: suspend/suspend_advanced_auto
estimated_duration: 1.2
requires:
device.category == 'NETWORK'
command: network_reconnect_resume_test -t 10 -d wired
_description:
Checks the length of time it takes to reconnect an existing wired connection
after a suspend/resume cycle.
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/power
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Validate that the power LED operated the same after resuming from suspend
STEPS:
1. Power LED should be on while device is switched on
VERIFICATION:
Does the power LED remain on after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/battery-charging
estimated_duration: 120.0
depends: suspend/suspend_advanced
_description:
PURPOSE:
Validate that the battery light shows charging status after resuming from suspend
STEPS:
1. Let system run on battery for a while
2. Plug in AC plug
VERIFICATION:
Did the battery indicator LED still turn orange after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/battery-charged
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Validate that the battery LED properly displays charged status after resuming from suspend
STEPS:
1. Let system run on battery for a short time
2. Plug in AC
3. Let system run on AC
VERIFICATION:
Does the orange battery LED still shut off when system is fully charged after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/battery-low
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Validate that the battery LED indicated low power after resuming from suspend
STEPS:
1. Let system run on battery for several hours
2. Monitor battery LED carefully
VERIFICATION:
Does the LED light orange when battery is low after resuming from suspend?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/hdd
depends: suspend/suspend_advanced
estimated_duration: 120.0
command: led_hdd_test
_description:
PURPOSE:
Validate that the HDD LED still operates as expected after resuming from suspend
STEPS:
1. Select "Test" to write and read a temporary file for a few seconds
2. HDD LED should blink when writing to/reading from HDD
VERIFICATION:
Did the HDD LED still blink with HDD activity after resuming from suspend?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/numeric-keypad
estimated_duration: 120.0
depends: suspend/suspend_advanced
command: keyboard_test
_description:
PURPOSE:
Validate that the numeric keypad LED operates the same before and after resuming from suspend
STEPS:
1. Press "Block Num" key to toggle numeric keypad LED
2. Click on the "Test" button to open a window to verify your typing
3. Type using the numeric keypad both when the LED is on and off
VERIFICATION:
1. Numeric keypad LED status should toggle everytime the "Block Num" key is pressed
2. Numbers should only be entered in the keyboard verification window when the LED is on
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/caps-lock
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Validate that the Caps Lock key operates the same before and after resuming from suspend
STEPS:
1. Press "Block Cap Keys" to activate/deactivate cap keys blocking
2. Cap Keys LED should be switched on/off every time the key is pressed
VERIFICATION:
Did the Cap Keys LED light as expected after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/wlan
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
WLAN LED verification after resuming from suspend
STEPS:
1. Make sure WLAN connection is established
2. WLAN LED should light
VERIFICATION:
Did the WLAN LED light as expected after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/wlan-disabled
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Validate that WLAN LED shuts off when disabled after resuming from suspend
STEPS:
1. Connect to AP
2. Use Physical switch to disable WLAN
3. Re-enable
4. Use Network-Manager to disable WLAN
VERIFICATION:
Did the LED turn off then WLAN is disabled after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/bluetooth
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Validate that the Bluetooth LED turns on and off when BT is enabled/disabled after resuming from suspend
STEPS:
1. Switch bluetooth off from a hardware switch (if present)
2. Switch bluetooth back on
3. Switch bluetooth off from the panel applet
4. Switch bluetooth back on
VERIFICATION:
Did the bluetooth LED turn off and on twice after resuming from suspend?
plugin: user-interact-verify
category_id: 2013.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: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/touchpad
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Touchpad LED verification after resuming from suspend
STEPS:
1. Click on the touchpad button or press key combination to enable/disable touchpad button
2. Slide your finger on the touchpad
VERIFICATION:
1. Touchpad LED status should toggle everytime the button is clicked or the key combination is pressed
2. When the LED is on, the mouse pointer should move on touchpad usage
3. When the LED is off, the mouse pointer should not move on touchpad usage
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/led_after_suspend/wireless
depends: suspend/suspend_advanced
estimated_duration: 120.0
_description:
PURPOSE:
Validate Wireless (WLAN + Bluetooth) LED operated the same after resuming from suspend
STEPS:
1. Make sure WLAN connection is established and Bluetooth is enabled.
2. WLAN/Bluetooth LED should light
3. Switch WLAN and Bluetooth off from a hardware switch (if present)
4. Switch them back on
5. Switch WLAN and Bluetooth off from the panel applet
6. Switch them back on
VERIFICATION:
Did the WLAN/Bluetooth LED light as expected after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/brightness
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable','All In One','All-In-One','AIO']
_description:
PURPOSE:
This test will test the brightness key after resuming from suspend
STEPS:
1. Press the brightness buttons on the keyboard
VERIFICATION:
Did the brightness change following to your key presses after resuming from suspend?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/volume
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s '0xe02e,0xe0ae:Volume Up' '0xe030,0xe0b0:Volume Down'
_description:
PURPOSE:
This test will test the volume keys of your keyboard after resuming from suspend
STEPS:
Skip this test if your computer has no volume keys.
1. Click test to open a window on which to test the volume keys.
2. If all the keys work, the test will be marked as passed.
VERIFICATION:
Did the volume change following to your key presses?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/mute
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s '0xe020,0xe0a0:Mute'
_description:
PURPOSE:
This test will test the mute key of your keyboard after resuming from suspend
STEPS:
1. Click test to open a window on which to test the mute key.
2. If the key works, the test will pass and the window will close.
VERIFICATION:
Did the volume mute following your key presses?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/sleep
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'KEYBOARD'
_description:
PURPOSE:
This test will test the sleep key after resuming from suspend
STEPS:
1. Press the sleep key on the keyboard
2. Wake your system up by pressing the power button
VERIFICATION:
Did the system go to sleep after pressing the sleep key after resuming from suspend?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/battery-info
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable']
user: root
command: key_test -s '0xe071,0xef1:Battery Info'
_description:
PURPOSE:
This test will test the battery information key after resuming from suspend
STEPS:
Skip this test if you do not have a Battery Button.
1. Click Test to begin
2. Press the Battery Info button (or combo like Fn+F3)
3: Close the Power Statistics tool if it opens
VERIFICATION:
Did the Battery Info key work as expected after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/wireless
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
This test will test the wireless key after resuming from suspend
STEPS:
1. Press the wireless key on the keyboard
2. Press the same key again
VERIFICATION:
Did the wireless go off on the first press and on again on the second after resuming from suspend?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/media-control
estimated_duration: 120.0
depends: suspend/suspend_advanced
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s 0xe010,0xe090:Previous 0xe024,0xe0a4:Stop 0xe019,0xe099:Next 0xe022,0xe0a2:Play
_description:
PURPOSE:
This test will test the media keys of your keyboard after resuming from suspend
STEPS:
Skip this test if your computer has no media keys.
1. Click test to open a window on which to test the media keys.
2. If all the keys work, the test will be marked as passed.
VERIFICATION:
Do the keys work as expected after resuming from suspend?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/super
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires:
device.category == 'KEYBOARD'
user: root
command: key_test -s '0xe05b,0xe0db:Left Super Key'
_description:
PURPOSE:
This test will test the super key of your keyboard after resuming from suspend
STEPS:
1. Click test to open a window on which to test the super key.
2. If the key works, the test will pass and the window will close.
VERIFICATION:
Does the super key work as expected after resuming from suspend?
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/video-out
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
Validate that the External Video hot key is working as expected after resuming from suspend
STEPS:
1. Plug in an external monitor
2. Press the display hot key to change the monitors configuration
VERIFICATION:
Check that the video signal can be mirrored, extended, displayed on external or onboard only, after resuming from suspend.
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/keys_after_suspend/touchpad
depends: suspend/suspend_advanced
estimated_duration: 120.0
requires: dmi.product in ['Notebook','Laptop','Portable']
_description:
PURPOSE:
Verify touchpad hotkey toggles touchpad functionality on and off after resuming from suspend
STEPS:
1. Verify the touchpad is functional
2. Tap the touchpad toggle hotkey
3. Tap the touchpad toggle hotkey again
VERIFICATION:
Verify the touchpad has been disabled and re-enabled.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb_insert_after_suspend
estimated_duration: 30.0
depends:
suspend/suspend_advanced
command: removable_storage_watcher insert usb
_description:
PURPOSE:
This test will check that the system correctly detects the insertion of
a USB storage device after suspend and resume.
STEPS:
1. Click "Test" and insert a USB storage device (pen-drive/HDD).
(Note: this test will time-out after 20 seconds.)
2. Do not unplug the device after the test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb3_insert_after_suspend
estimated_duration: 30.0
requires:
usb.usb3 == 'supported'
depends:
suspend/suspend_advanced
command: removable_storage_watcher -m 500000000 insert usb
_description:
PURPOSE:
This test will check that the system correctly detects the insertion of
a USB 3.0 storage device after suspend and resume.
STEPS:
1. Click "Test" and insert a USB 3.0 storage device (pen-drive/HDD) in
a USB 3.0 port. (Note: this test will time-out after 20 seconds.)
2. Do not unplug the device after the test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb_remove_after_suspend
estimated_duration: 30.0
depends:
suspend/usb_insert_after_suspend
command: removable_storage_watcher remove usb
_description:
PURPOSE:
This test will check that the system correctly detects the removal of
a USB storage device after suspend.
STEPS:
1. Click "Test" and remove the USB device.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb3_remove_after_suspend
estimated_duration: 30.0
depends:
suspend/usb3_insert_after_suspend
requires:
usb.usb3 == 'supported'
command: removable_storage_watcher -m 500000000 remove usb
_description:
PURPOSE:
This test will check that the system correctly detects the removal of
a USB 3.0 storage device after suspend
STEPS:
1. Click "Test" and remove the USB 3.0 device.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb_storage_automated_after_suspend
estimated_duration: 1.2
depends: suspend/usb_insert_after_suspend
user: root
command: removable_storage_test -s 268400000 usb
_description:
This test is automated and executes after the suspend/usb_insert_after_suspend
test is run.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb3_storage_automated_after_suspend
estimated_duration: 1.2
requires:
usb.usb3 == 'supported'
depends: suspend/usb3_insert_after_suspend
user: root
command: removable_storage_test -s 268400000 -m 500000000 usb --driver xhci_hcd
_description:
This test is automated and executes after the suspend/usb3_insert_after_suspend
test is run.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb_storage_preinserted_after_suspend
estimated_duration: 1.2
user: root
depends: suspend/suspend_advanced_auto
command: removable_storage_test -l usb && removable_storage_test -s 268400000 usb
_description:
This is an automated version of usb/storage-automated and assumes that the
server has usb storage devices plugged in prior to checkbox execution. It
is intended for servers and SRU automated testing.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb3_storage_preinserted_after_suspend
estimated_duration: 1.2
user: root
requires:
usb.usb3 == 'supported'
depends: suspend/suspend_advanced_auto
command: removable_storage_test -l usb && removable_storage_test -s 268400000 -m 500000000 usb --driver xhci_hcd
_description:
This is an automated version of usb3/storage-automated and assumes that the
server has usb 3.0 storage devices plugged in prior to checkbox execution. It
is intended for servers and SRU automated testing.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb_performance_after_suspend
depends: suspend/usb_insert_after_suspend
user: root
estimated_duration: 45.00
command: removable_storage_test -s 268400000 -p 15 usb
_description:
This test will check that your USB 2.0 port transfers data at a
minimum expected speed.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/usb3_superspeed_performance_after_suspend
requires:
usb.usb3 == 'supported'
depends: suspend/usb3_insert_after_suspend
user: root
estimated_duration: 45.00
command: removable_storage_test -s 268400000 -m 500000000 usb --driver xhci_hcd
_description:
This test will check that your USB 3.0 port could be recognized
as SuperSpeed USB device using xhci_hcd driver and transfers data correctly.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/mmc-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of an MMC card after the system has been suspended
STEPS:
1. Click "Test" and insert an MMC card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/mmc-storage-after-suspend
depends: suspend/mmc-insert-after-suspend
estimated_duration: 10.0
user: root
command: removable_storage_test -s 67120000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/mmc-insert-after-suspend test
is run. It tests reading and writing to the MMC card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/mmc-remove-after-suspend
depends: suspend/mmc-insert-after-suspend
estimated_duration: 30.0
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects the removal
of an MMC card from the systems card reader after the system has been suspended.
STEPS:
1. Click "Test" and remove the MMC card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/sd-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of an UNLOCKED SD card after the system
has been suspended
STEPS:
1. Click "Test" and insert an UNLOCKED SD card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/sd-storage-after-suspend
estimated_duration: 10.0
depends: suspend/sd-insert-after-suspend
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/sd-insert-after-suspend test
is run. It tests reading and writing to the SD card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/sd-remove-after-suspend
estimated_duration: 30.0
depends: suspend/sd-insert-after-suspend
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects
the removal of an SD card from the systems card reader
after the system has been suspended.
STEPS:
1. Click "Test" and remove the SD card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/sdhc-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of an UNLOCKED SDHC media card after the
system has been suspended
STEPS:
1. Click "Test" and insert an UNLOCKED SDHC card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/sdhc-storage-after-suspend
estimated_duration: 10.0
depends: suspend/sdhc-insert-after-suspend
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/sdhc-insert-after-suspend test
is run. It tests reading and writing to the SDHC card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/sdhc-remove-after-suspend
estimated_duration: 30.0
depends: suspend/sdhc-insert-after-suspend
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects the removal
of an SDHC card from the systems card reader after the system has been suspended.
STEPS:
1. Click "Test" and remove the SDHC card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/cf-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a CF card after the system has been suspended
STEPS:
1. Click "Test" and insert a CF card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/cf-storage-after-suspend
estimated_duration: 10.0
depends: mediacard/cf-insert-after-suspend
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/cf-insert-after-suspend test
is run. It tests reading and writing to the CF card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/cf-remove-after-suspend
estimated_duration: 30.0
depends: mediacard/cf-insert-after-suspend
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects the removal
of a CF card from the systems card reader after the system has been suspended.
STEPS:
1. Click "Test" and remove the CF card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/sdxc-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a SDXC card after the system has been suspended
STEPS:
1. Click "Test" and insert a SDXC card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/sdxc-storage-after-suspend
estimated_duration: 10.0
depends: mediacard/sdxc-insert-after-suspend
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/sdxc-insert-after-suspend test
is run. It tests reading and writing to the SDXC card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/sdxc-remove-after-suspend
depends: mediacard/sdxc-insert-after-suspend
estimated_duration: 30.0
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects the removal
of a SDXC card from the systems card reader after the system has been suspended.
STEPS:
1. Click "Test" and remove the SDXC card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/ms-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a MS card after the system has been suspended
STEPS:
1. Click "Test" and insert a MS card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/ms-storage-after-suspend
estimated_duration: 10.0
depends: mediacard/ms-insert-after-suspend
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/ms-insert-after-suspend test
is run. It tests reading and writing to the MS card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/ms-remove-after-suspend
estimated_duration: 30.0
depends: mediacard/ms-insert-after-suspend
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects the removal
of a MS card from the systems card reader after the system has been suspended.
STEPS:
1. Click "Test" and remove the MS card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/msp-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a MSP card after the system has been suspended
STEPS:
1. Click "Test" and insert a MSP card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/msp-storage-after-suspend
estimated_duration: 10.0
depends: mediacard/msp-insert-after-suspend
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/msp-insert-after-suspend test
is run. It tests reading and writing to the MSP card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/msp-remove-after-suspend
estimated_duration: 30.0
depends: mediacard/msp-insert-after-suspend
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects the removal
of a MSP card from the systems card reader after the system has been suspended.
STEPS:
1. Click "Test" and remove the MSP card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/xd-insert-after-suspend
estimated_duration: 30.0
depends: suspend/suspend_advanced
command: removable_storage_watcher --memorycard insert sdio usb scsi
_description:
PURPOSE:
This test will check that the systems media card reader can
detect the insertion of a xD card after the system has been suspended
STEPS:
1. Click "Test" and insert a xD card into the reader.
If a file browser opens up, you can safely close it.
(Note: this test will time-out after 20 seconds.)
2. Do not remove the device after this test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/xd-storage-after-suspend
estimated_duration: 10.0
depends: mediacard/xd-insert-after-suspend
user: root
command: removable_storage_test -s 268400000 --memorycard sdio usb scsi
_description:
This test is automated and executes after the mediacard/xd-insert-after-suspend test
is run. It tests reading and writing to the xD card after the system has been suspended.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::suspend
id: mediacard/xd-remove-after-suspend
estimated_duration: 30.0
depends: mediacard/xd-insert-after-suspend
command: removable_storage_watcher --memorycard remove sdio usb scsi
_description:
PURPOSE:
This test will check that the system correctly detects the removal
of a xD card from the systems card reader after the system has been suspended.
STEPS:
1. Click "Test" and remove the xD card from the reader.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: touchpad/touchpad_after_suspend
depends: suspend/suspend_advanced_auto
requires:
dmi.product in ['Notebook','Laptop','Portable']
xinput.device_class == 'XITouchClass' and xinput.touch_mode != 'dependent'
command: true
estimated_duration: 1.2
_description:
Determine if the touchpad is still functioning after suspend/resume.
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: touchscreen/touchscreen_after_suspend
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_touchscreen == 'True'
depends: suspend/suspend_advanced_auto
estimated_duration: 30.0
_description:
PURPOSE:
Check touchscreen tap recognition
STEPS:
1. Tap an object on the screen with finger. The cursor should jump to location tapped and object should highlight
VERIFICATION:
Does tap recognition work?
plugin: user-interact-verify
category_id: 2013.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: 2013.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: 2013.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
plugin: local
_summary: Pointing device tests after suspend.
id: suspend/pointing-after-suspend
requires:
device.category == 'MOUSE' or device.category == 'TOUCHPAD' or device.category == 'TOUCHSCREEN'
_description: Pointing device tests after suspend.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=MOUSE" -w "category=TOUCHPAD" -w "category=TOUCHSCREEN"'
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/pointing-after-suspend_`echo "${product}_${category}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`_`basename $path`
depends: suspend/suspend_advanced
requires: device.path == "$path"
description:
PURPOSE:
This will test your $product device after suspend.
STEPS:
1. Move the cursor with your $product.
VERIFICATION:
Did the cursor move?
EOF
plugin: local
_summary: Create click tests for pointing devices after suspend.
id: suspend/clicking-after-suspend
estimated_duration: 1.0
requires:
device.category == 'MOUSE' or device.category == 'TOUCHPAD'
_description: Click tests for pointing devices after suspend.
command:
cat <<'EOF' | run_templates -t -s 'udev_resource | filter_templates -w "category=MOUSE" -w "category=TOUCHPAD"'
plugin: manual
category_id: 2013.com.canonical.plainbox::suspend
estimated_duration: 30.0
id: suspend/clicking-after-suspend_`echo "${product}_${category}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`_`basename $path`
depends: suspend/suspend_advanced
requires: device.path == "$path"
_summary: Check post suspend button functionality for $product
_description:
PURPOSE:
This will test the buttons of your $product device after suspend
STEPS:
1. Click the left button with your $product.
2. Click the right button with your $product.
3. Click the middle button with your $product (if available).
4. Double-click the left button with your $product.
VERIFICATION:
Did these buttons work as expected?
EOF
id: suspend/generator_compiz_check_after_suspend
requires: device.category == 'VIDEO'
_description: Compiz support tests after suspend
_summary: Compiz support tests after suspend
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_compiz_check_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'nux-tools'
command: ! /usr/lib/nux/unity_support_test -c -p 2>&1 | ansi_parser | grep -e ":\(\s\+\)no$" -ie "error"
estimated_duration: 0.130
_description: Check that $product hardware is able to run compiz after suspend
_summary: Test Compiz support for $product after suspend
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/compiz_check_after_suspend
depends: suspend/suspend_advanced
requires: package.name == 'nux-tools'
command: ! /usr/lib/nux/unity_support_test -c -p 2>&1 | ansi_parser | grep -e ":\(\s\+\)no$" -ie "error"
estimated_duration: 0.130
_description: Check that the hardware is able to run compiz after suspend
_summary: Test Compiz support after suspend
id: suspend/generator_glxgears_after_suspend
requires: device.category == 'VIDEO'
_description: glxgears tests after suspend
_summary: glxgears tests after suspend
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_glxgears_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: package.name == 'mesa-utils'
command: glxgears; true
_summary: Test that glxgears works for $product after suspend
_description:
PURPOSE:
This test tests the basic 3D capabilities of your $product video card after suspend
STEPS:
1. Click "Test" to execute an OpenGL demo. Press ESC at any time to close.
2. Verify that the animation is not jerky or slow.
VERIFICATION:
1. Did the 3d animation appear?
2. Was the animation free from slowness/jerkiness?
EOF
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/glxgears_after_suspend
depends: suspend/suspend_advanced
requires:
package.name == 'mesa-utils'
device.category == 'VIDEO'
command: glxgears; true
_summary: Test that glxgears works after suspend
_description:
PURPOSE:
This test tests the basic 3D capabilities of your $product video card after suspend
STEPS:
1. Click "Test" to execute an OpenGL demo. Press ESC at any time to close.
2. Verify that the animation is not jerky or slow.
VERIFICATION:
1. Did the 3d animation appear?
2. Was the animation free from slowness/jerkiness?
id: suspend/generator_video_after_suspend
requires: device.category == 'VIDEO'
_description: Display video test after suspend
_summary: Display video test after suspend
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: suspend/`echo ${index}`_video_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
requires:
package.name == 'xorg'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
command: gst_pipeline_test -t 2 'videotestsrc ! videoconvert ! autovideosink' || gst_pipeline_test -t 2 'videotestsrc ! ffmpegcolorspace ! autovideosink'
_summary: Test that video can be displayed after suspend with ${product}
_description:
PURPOSE:
This test will test the default display after suspend with a sample video
STEPS:
1. Click "Test" to display a video test.
VERIFICATION:
Do you see color bars and static?
EOF
id: suspend/video_after_suspend
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::suspend
depends: suspend/suspend_advanced
requires:
device.category == 'VIDEO'
package.name == 'xorg'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
command: gst_pipeline_test -t 2 'videotestsrc ! videoconvert ! autovideosink' || gst_pipeline_test -t 2 'videotestsrc ! ffmpegcolorspace ! autovideosink'
_summary: Test that video can be displayed after suspend
_description:
PURPOSE:
This test will test the default display after suspend with a sample video
STEPS:
1. Click "Test" to display a video test.
VERIFICATION:
Do you see color bars and static?
id: suspend/generator_driver_version_after_suspend
requires: device.category == 'VIDEO'
_description: Driver version tests after suspend
_summary: Driver version tests after suspend
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
id: suspend/`echo ${index}`_driver_version_after_suspend_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: suspend/`echo ${index}`_suspend_after_switch_to_card_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
command: graphics_driver
estimated_duration: 0.500
_description: Parses Xorg.0.Log and discovers the running X driver and version after suspend for the $product graphics card
_summary: Test X driver/version after suspend for $product
EOF
id: suspend/driver_version_after_suspend
requires: device.category == 'VIDEO'
depends: suspend/suspend_advanced
plugin: shell
category_id: 2013.com.canonical.plainbox::suspend
command: graphics_driver
estimated_duration: 0.500
_description: Parses Xorg.0.Log and discovers the running X driver and version after suspend
_summary: Test X driver/version after suspend
id: suspend/oops_after_suspend
depends: suspend/suspend_advanced
plugin:shell
estimated_duration: 10.0
requires:
package.name == 'fwts'
user: root
_description:
Run Firmware Test Suite (fwts) oops tests after suspend.
environ: PLAINBOX_SESSION_SHARE
command:
fwts_test -l $PLAINBOX_SESSION_SHARE/fwts_oops_results_after_s3.log -t oops
id: suspend/oops_results_after_suspend.log
plugin: attachment
category_id: 2013.com.canonical.plainbox::suspend
estimated_duration: 0.5
command:
[ -e ${PLAINBOX_SESSION_SHARE}/fwts_oops_results_after_s3.log ] && cat ${PLAINBOX_SESSION_SHARE}/fwts_oops_results_after_s3.log
_description: Attaches the FWTS oops results log to the submission after suspend
plainbox-provider-checkbox-0.25/jobs/hibernate.txt.in 0000664 0001750 0001750 00000007541 12646152433 024147 0 ustar sylvain sylvain 0000000 0000000 plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::hibernate
id: power-management/hibernate_advanced
requires:
sleep.disk == 'supported'
rtc.state == 'supported'
environ: PLAINBOX_SESSION_SHARE
user: root
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
fwts_test -l $PLAINBOX_SESSION_SHARE/hibernate-single -f none -s s4 --s4-device-check --s4-device-check-delay=45 --s4-sleep-delay=120
else
echo "Calling sleep_test"
sleep_test -s disk -w 120
fi
estimated_duration: 300.00
_description:
PURPOSE:
This test will check to make sure your system can successfully hibernate (if supported)
STEPS:
1. Click on Test
2. The system will hibernate and should wake itself within 5 minutes
3. If your system does not wake itself after 5 minutes, please press the power button to wake the system manually
4. If the system fails to resume from hibernate, please restart System Testing and mark this test as Failed
VERIFICATION:
Did the system successfully hibernate and did it work properly after waking up?
id: power-management/generator_hibernate_advanced
requires:
sleep.disk == 'supported'
rtc.state == 'supported'
_description: Hibernate test
_summary: Hibernate test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::hibernate
id: power-management/`echo ${index}`_hibernate_advanced_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
user: root
environ: PLAINBOX_SESSION_SHARE
estimated_duration: 300.00
command:
if type -P fwts >/dev/null; then
echo "Calling fwts"
fwts_test -l $PLAINBOX_SESSION_SHARE/`echo ${index}`_hibernate-single -f none -s s4 --s4-device-check --s4-device-check-delay=45 --s4-sleep-delay=120
else
echo "Calling sleep_test"
sleep_test -s disk -w 120
fi
_description:
PURPOSE:
This test will check to make sure your system can successfully hibernate (if supported)
STEPS:
1. Click on Test
2. The system will hibernate and should wake itself within 5 minutes
3. If your system does not wake itself after 5 minutes, please press the power button to wake the system manually
4. If the system fails to resume from hibernate, please restart System Testing and mark this test as Failed
VERIFICATION:
Did the system successfully hibernate and did it work properly after waking up?
EOF
plugin: shell
category_id: 2013.com.canonical.plainbox::hibernate
id: power-management/hibernate-single-log-check
command: [ -e $PLAINBOX_SESSION_SHARE/hibernate-single.log ] && sleep_test_log_check -v s4 $PLAINBOX_SESSION_SHARE/hibernate-single.log
_description:
Automated check of the hibernate log for errors discovered by fwts
plugin: attachment
category_id: 2013.com.canonical.plainbox::hibernate
id: power-management/hibernate-single-log-attach
depends: power-management/hibernate_advanced
command: [ -e $PLAINBOX_SESSION_SHARE/hibernate-single.log ] && cat $PLAINBOX_SESSION_SHARE/hibernate-single.log
estimated_duration: 0.5
_description: attaches log from single hibernate/resume test to results
id: power-management/generator_hibernate-single-log-attach
_description: Hibernate log attach
_summary: Hibernate log attach
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
plugin: attachment
category_id: 2013.com.canonical.plainbox::hibernate
id: power-management/`echo ${index}`_hibernate-single-log-attach_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
depends: power-management/`echo ${index}`_hibernate_advanced_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
estimated_duration: 0.5
command: [ -e $PLAINBOX_SESSION_SHARE/`echo ${index}`_hibernate-single.log ] && cat $PLAINBOX_SESSION_SHARE/`echo ${index}`_hibernate-single.log
_description: attaches log from single hibernate/resume test to results
EOF
plainbox-provider-checkbox-0.25/jobs/esata.txt.in 0000664 0001750 0001750 00000002655 12646152433 023304 0 ustar sylvain sylvain 0000000 0000000 plugin: user-interact
category_id: 2013.com.canonical.plainbox::esata
id: esata/insert
command: removable_storage_watcher insert ata_serial_esata
_description:
PURPOSE:
This test will check the system can detect the insertion of an eSATA HDD
STEPS:
1. Click 'Test' to begin the test. This test will
timeout and fail if the insertion has not been detected within 20 seconds.
2. Plug an eSATA HDD into an available eSATA port.
VERIFICATION:
The verification of this test is automated. Do not change the automatically
selected result
plugin: shell
category_id: 2013.com.canonical.plainbox::esata
id: esata/storage-test
user: root
depends: esata/insert
command: removable_storage_test -s 268400000 ata_serial_esata
_description:
This is an automated test which performs read/write operations on an attached
eSATA HDD
plugin: user-interact
category_id: 2013.com.canonical.plainbox::esata
id: esata/remove
depends: esata/insert
command: removable_storage_watcher remove ata_serial_esata
_description:
PURPOSE:
This test will check the system can detect the removal of an eSATA HDD
STEPS:
1. Click 'Test' to begin the test. This test will timeout and fail if
the removal has not been detected within 20 seconds.
2. Remove the previously attached eSATA HDD from the eSATA port.
VERIFICATION:
The verification of this test is automated. Do not change the automatically
selected result
plainbox-provider-checkbox-0.25/jobs/usb.txt.in 0000664 0001750 0001750 00000015773 12646152433 023005 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::usb
id: usb/detect
estimated_duration: 1.0
command: set -o pipefail; lsusb 2>/dev/null | sed 's/.*\(ID .*\)/\1/' | head -n 4 || echo "No USB devices were detected" >&2
_description: Detects and shows USB devices attached to this system.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::usb
id: usb/disk_detect
depends: usb/detect
estimated_duration: 1.0
command: removable_storage_test -l usb
_description:
PURPOSE:
This test will check that your system detects USB storage devices.
STEPS:
1. Plug in one or more USB keys or hard drives.
2. Click on "Test".
VERIFICATION:
Were the drives detected?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::usb
id: usb/HID
depends: usb/detect
estimated_duration: 1.0
command: keyboard_test
_description:
PURPOSE:
This test will check that you can use a USB HID device
STEPS:
1. Enable either a USB mouse or keyboard
2. For mice, perform actions such as moving the pointer, right and left button clicks and double clicks
3. For keyboards, commence the test to launch a small tool. Type some text and close the tool.
VERIFICATION:
Did the device work as expected?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::usb
id: usb/insert
depends: usb/detect
estimated_duration: 10.0
command: removable_storage_watcher insert usb
_description:
PURPOSE:
This test will check that the system correctly detects the insertion of
a USB storage device
STEPS:
1. Click "Test" and insert a USB storage device
(Note: this test will time-out after 20 seconds.)
2. Do not unplug the device after the test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::usb
id: usb3/insert
requires:
usb.usb3 == 'supported'
estimated_duration: 10.0
command: removable_storage_watcher -m 500000000 insert usb
_description:
PURPOSE:
This test will check that the system correctly detects the insertion of
a USB 3.0 storage device
STEPS:
1. Click "Test" and insert a USB 3.0 storage device in a USB 3.0 port.
(Note: this test will time-out after 20 seconds.)
2. Do not unplug the device after the test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::usb
id: usb/remove
depends: usb/insert
estimated_duration: 10.0
command: removable_storage_watcher remove usb
_description:
PURPOSE:
This test will check that the system correctly detects the removal of
a USB storage device
STEPS:
1. Click "Test" and remove the USB device.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::usb
id: usb3/remove
depends: usb3/insert
requires:
usb.usb3 == 'supported'
estimated_duration: 10.0
command: removable_storage_watcher -m 500000000 remove usb
_description:
PURPOSE:
This test will check that the system correctly detects the removal of
a USB 3.0 storage device
STEPS:
1. Click "Test" and remove the USB 3.0 device.
(Note: this test will time-out after 20 seconds.)
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::usb
id: usb/storage-transfer
depends: usb/insert
user: root
estimated_duration: 45.0
command: removable_storage_test -s 268400000 usb
_description:
PURPOSE:
This test will check your USB connection.
STEPS:
1. Plug a USB HDD or thumbdrive into the computer.
2. An icon should appear on the Launcher.
3. Click "Test" to begin the test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::usb
id: usb3/storage-transfer
requires:
usb.usb3 == 'supported'
depends: usb3/insert
user: root
estimated_duration: 45.0
command: removable_storage_test -s 268400000 -m 500000000 usb
_description:
PURPOSE:
This test will check your USB 3.0 connection.
STEPS:
1. Plug a USB 3.0 HDD or thumbdrive into a USB 3.0 port in the computer.
2. An icon should appear on the Launcher.
3. Click "Test" to begin the test.
VERIFICATION:
The verification of this test is automated. Do not change the
automatically selected result.
plugin: shell
category_id: 2013.com.canonical.plainbox::usb
id: usb/storage-automated
depends: usb/insert
user: root
estimated_duration: 45.0
command: removable_storage_test -s 268400000 usb
_description:
This test is automated and executes after the usb/insert test is run.
plugin: shell
category_id: 2013.com.canonical.plainbox::usb
id: usb3/storage-automated
requires:
usb.usb3 == 'supported'
depends: usb3/insert
user: root
estimated_duration: 45.0
command: removable_storage_test -s 268400000 -m 500000000 usb --driver xhci_hcd
_description:
This test is automated and executes after the usb3/insert test is run.
plugin: shell
category_id: 2013.com.canonical.plainbox::usb
id: usb/storage-preinserted
user: root
estimated_duration: 45.0
command: removable_storage_test -l usb && removable_storage_test -s 268400000 usb
_description:
Tests USB 2.0 or 1.1 ports on a system by doing write/read/compare tests on
randomly created data. It requires that a USB stick is plugged into an
available USB port before running the certification suite.
plugin: shell
category_id: 2013.com.canonical.plainbox::usb
id: usb3/storage-preinserted
user: root
requires:
usb.usb3 == 'supported'
estimated_duration: 45.0
command: removable_storage_test -l usb && removable_storage_test -s 268400000 -m 500000000 usb --driver xhci_hcd
_description:
Tests USB 3.0 ports on a system by doing write/read/compare tests on
randomly created data. It requires that a USB stick is plugged into an
available USB port before running the certification suite. Additionally, it
will only work with USB sticks and ports rated for USB 3.0 speeds or faster.
plugin: manual
category_id: 2013.com.canonical.plainbox::usb
id: usb/panels
_description:
PURPOSE:
This test will check your USB connection.
STEPS:
1. Connect a USB storage device to an external USB slot on this computer.
2. An icon should appear on the Launcher.
3. Confirm that the icon appears.
4. Eject the device.
5. Repeat with each external USB slot.
VERIFICATION:
Do all USB slots work with the device?
plugin: shell
category_id: 2013.com.canonical.plainbox::usb
id: usb/performance
depends: usb/insert
user: root
estimated_duration: 45.00
command: removable_storage_test -s 268400000 -p 15 usb
_description:
This test will check that your USB 2.0 port transfers data at a
minimum expected speed.
plainbox-provider-checkbox-0.25/jobs/touchpad.txt.in 0000664 0001750 0001750 00000017646 12646152433 024024 0 ustar sylvain sylvain 0000000 0000000 plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/basic
requires: dmi.product in ['Notebook','Laptop','Portable']
estimated_duration: 120.0
_description:
PURPOSE:
Touchpad manual verification
STEPS:
1. Make sure that touchpad is enabled.
2. Move cursor using the touchpad.
VERIFICATION:
Did the cursor move?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/horizontal
requires:
dmi.product in ['Notebook','Laptop','Portable']
'Button Horiz Wheel Left' in xinput.button_labels and 'Button Horiz Wheel Right' in xinput.button_labels
command: touchpad_test right left --edge-scroll
estimated_duration: 120.0
_description:
PURPOSE:
Touchpad horizontal scroll verification
STEPS:
1. Select "Test" when ready and place your cursor within the borders of the displayed test window.
2. Verify that you can move the horizontal slider by moving your finger right and left in the lower part of the touchpad.
VERIFICATION:
Could you scroll right and left?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/vertical
requires:
dmi.product in ['Notebook','Laptop','Portable']
'Button Wheel Up' in xinput.button_labels and 'Button Wheel Down' in xinput.button_labels
command: touchpad_test up down --edge-scroll
estimated_duration: 120.0
_description:
PURPOSE:
Touchpad vertical scroll verification
STEPS:
1. Select "Test" when ready and place your cursor within the borders of the displayed test window.
2. Verify that you can move the vertical slider by moving your finger up and down in the right part of the touchpad.
VERIFICATION:
Could you scroll up and down?
plugin: shell
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/singletouch-automated
requires:
dmi.product in ['Notebook','Laptop','Portable']
xinput.device_class == 'XITouchClass' and xinput.touch_mode != 'dependent'
command: true
estimated_duration: 1.2
_description:
Determine whether the touchpad is detected as a singletouch device automatically.
plugin: shell
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/multitouch-automated
estimated_duration: 1.2
requires:
dmi.product in ['Notebook','Laptop','Portable']
xinput.device_class == 'XITouchClass' and xinput.touch_mode == 'dependent'
command: true
_description:
Determine whether the touchpad is detected as a multitouch device automatically.
plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/multitouch-manual
requires: dmi.product in ['Notebook','Laptop','Portable']
depends: touchpad/singletouch-automated
estimated_duration: 120.0
_description:
PURPOSE:
Touchpad manual detection of multitouch.
STEPS:
1. Look at the specifications for your system.
VERIFICATION:
Is the touchpad supposed to be multitouch?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/singletouch-corner
requires: dmi.product in ['Notebook','Laptop','Portable']
estimated_duration: 120.0
_description:
PURPOSE:
Determine that the hot corner feature is working as expected
STEPS:
1. Launch a browser.
2. Go to a website, and hover the cursor over a link.
3. Tap the upper right corner on the touchpad.
VERIFICATION:
Did the tap trigger a new tab to be opened?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/singletouch-selection
requires: dmi.product in ['Notebook','Laptop','Portable']
estimated_duration: 120.0
_description:
PURPOSE:
Determine that the selection window function is working as expected.
STEPS:
1. Open a file folder
2. Double tap and drag the cursor across several file.
VERIFICATION:
Did a selection window open and were several files selected?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/multitouch-rightclick
requires: dmi.product in ['Notebook','Laptop','Portable']
depends: touchpad/multitouch-automated
estimated_duration: 120.0
_description:
PURPOSE:
Determine that the right click function is working as expected.
STEPS:
1. Open a file folder
2. Hover cursor over file in folder
3. 2-touch tap.
VERIFICATION:
Did the right click pop up menu appear?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/multitouch-horizontal
requires: dmi.product in ['Notebook','Laptop','Portable']
command: touchpad_test right left
estimated_duration: 120.0
_description:
PURPOSE:
Touchpad 2-touch horizontal scroll verification
STEPS:
1. Select "Test" when ready and place your cursor within the borders of the displayed test window.
2. Verify that you can move the horizontal slider by moving 2 fingers right and left along the touchpad.
VERIFICATION:
Could you scroll right and left?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/multitouch-vertical
requires: dmi.product in ['Notebook','Laptop','Portable']
command: touchpad_test up down
estimated_duration: 120.0
_description:
PURPOSE:
Touchpad 2-touch vertical scroll verification
STEPS:
1. Select "Test" when ready and place your cursor within the borders of the displayed test window.
2. Verify that you can move the vertical slider by moving 2 fingers up and down along the touchpad.
VERIFICATION:
Could you scroll up and down?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/drag-and-drop
requires: dmi.product in ['Notebook','Laptop','Portable']
estimated_duration: 120.0
_description:
PURPOSE:
Determine that the drag and drop function is working as expected.
STEPS:
1. Browse to the examples folder in the current user's home directory
2. Double tap and hold to select the "Ubuntu_Free_Culture_Showcase" folder
2. Drag the selected folder to the desktop and remove finger from touchpad.
VERIFICATION:
Did a selected folder move to the desktop?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/multitouch-zoom
requires: dmi.product in ['Notebook','Laptop','Portable']
depends: touchpad/multitouch-automated
estimated_duration: 120.0
_summary: Check touchpad pinch-to-zoom gesture
_description:
PURPOSE:
Check touchpad pinch gesture for zoom
STEPS:
1. Open gallery-app with an image
2. Place two fingers on the touchpad and pinch them together
3. Place two fingers on the touchpad and move them apart
VERIFICATION:
Does the image zoom in and out?
plugin: manual
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/multitouch-dash
requires: dmi.product in ['Notebook','Laptop','Portable']
depends: touchpad/multitouch-automated
estimated_duration: 120.0
_summary: Check 4-finger tap gesture
_description:
PURPOSE:
Validate that 4-touch tap is operating as expected
STEPS:
1. 4-touch tap (tap with 4 fingers) anywhere on the touchpad
VERIFICATION:
Did the tap open the Dash?
plugin: shell
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/detected-as-mouse
requires: dmi.product in ['Notebook','Laptop','Portable']
estimated_duration: 1.2
command:
info=`touchpad_driver_info`
if [ $? -eq 0 ]; then
echo -e "touchpad detected with:\n$info"
else
echo "$info"
exit 1
fi
_description:
This test will check if your touchpad was detected as a mouse.
plugin: user-interact
category_id: 2013.com.canonical.plainbox::touchpad
id: touchpad/continuous-move
requires: dmi.product in ['Notebook','Laptop','Portable']
estimated_duration: 12
command: qmlscene -qt5 --fullscreen $PLAINBOX_PROVIDER_DATA/touch_continuous_move_test.qml 2>&1 | grep -o PASS
_description:
PURPOSE:
Touchpad continuous move verification
STEPS:
1. Select "Test" when ready and continuously move your cursor within the borders of the displayed test window.
You'll need to keep moving your finger on the touchpad for 10 seconds.
VERIFICATION:
Did the mouse cursor move without interruption?
plainbox-provider-checkbox-0.25/jobs/audio.txt.in 0000664 0001750 0001750 00000050735 12646152433 023312 0 ustar sylvain sylvain 0000000 0000000 plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/list_devices
estimated_duration: 1.0
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
command: cat /proc/asound/cards
_description: Test to detect audio devices
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/playback_auto
estimated_duration: 5.0
depends: audio/list_devices
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that internal speakers work correctly
STEPS:
1. Make sure that no external speakers or headphones are connected
When testing a desktop, you can skip this test if there is no
internal speaker, we will test the external output later
2. Commence the test to play a brief tone on your audio device
VERIFICATION:
Did you hear a tone?
id: audio/generator_playback_hdmi
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
_description: HDMI audio test
_summary: HDMI audio test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: audio/`echo ${index}`_playback_hdmi_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.hdmi == 'supported'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
estimated_duration: 30.0
command:
audio_settings store --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --verbose --device=hdmi --volume=50
gst_pipeline_test -t 2 --device hdmi 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
HDMI audio interface verification
STEPS:
1. Plug an external HDMI device with sound (Use only one HDMI/DisplayPort/Thunderbolt interface at a time for this test)
2. Commence the test
VERIFICATION:
Did you hear the sound from the HDMI device?
EOF
id: audio/generator_playback_displayport
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
_description: DisplayPort audio test
_summary: DisplayPort audio test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: audio/`echo ${index}`_playback_displayport_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
requires: display.dp == 'supported'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
estimated_duration: 30.0
command:
audio_settings store --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --verbose --device=hdmi --volume=50
gst_pipeline_test -t 2 --device hdmi 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
DisplayPort audio interface verification
STEPS:
1. Plug an external DisplayPort device with sound (Use only one HDMI/DisplayPort/Thunderbolt interface at a time for this test)
2. Commence the test
VERIFICATION:
Did you hear the sound from the DisplayPort device?
EOF
id: audio/generator_playback_thunderbolt
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
_description: Thunderbolt audio test
_summary: Thunderbolt audio test
plugin: local
command:
cat <<'EOF' | run_templates -t -s 'graphics_card_resource'
id: audio/`echo ${index}`_playback_thunderbolt_`echo "${product}" | sed 's/ /_/g;s/[^_a-zA-Z0-9-]//g'`
imports: from 2013.com.canonical.plainbox import manifest
requires: manifest.has_thunderbolt == 'True'
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
estimated_duration: 5.0
command:
audio_settings store --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --verbose --device=hdmi --volume=50
gst_pipeline_test -t 2 --device hdmi 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --verbose --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
Thunderbolt audio interface verification
STEPS:
1. Plug an external Thunderbolt device with sound (Use only one HDMI/DisplayPort/Thunderbolt interface at a time for this test)
2. Commence the test
VERIFICATION:
Did you hear the sound from the Thunderbolt device?
EOF
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/playback_headphones
estimated_duration: 20.0
depends: audio/list_devices
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that headphones connector works correctly
STEPS:
1. Connect a pair of headphones to your audio device
2. Commence the test to play a sound to your audio device
VERIFICATION:
Did you hear a sound through the headphones and did the sound play without any distortion, clicks or other strange noises from your headphones?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/alsa_record_playback_internal
estimated_duration: 20.0
depends: audio/playback_auto
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that recording sound using the onboard microphone works correctly
STEPS:
1. Disconnect any external microphones that you have plugged in
2. Click "Test", then speak into your internal microphone
3. After a few seconds, your speech will be played back to you.
VERIFICATION:
Did you hear your speech played back?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/alsa_record_playback_external
estimated_duration: 20.0
depends: audio/playback_headphones
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that recording sound using an external microphone works correctly
STEPS:
1. Connect a microphone to your microphone port
2. Click "Test", then speak into the external microphone
3. After a few seconds, your speech will be played back to you
VERIFICATION:
Did you hear your speech played back?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/alsa_record_playback_usb
estimated_duration: 120.0
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=usb --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that a USB audio device works correctly
STEPS:
1. Connect a USB audio device to your system
2. Click "Test", then speak into the microphone
3. After a few seconds, your speech will be played back to you
VERIFICATION:
Did you hear your speech played back through the USB headphones?
plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/alsa_record_playback_automated
estimated_duration: 10.0
requires:
package.name == 'python3-gi'
package.name == 'gir1.2-gstreamer-1.0'
package.name == 'libgstreamer1.0-0'
package.name == 'gstreamer1.0-plugins-good'
package.name == 'gstreamer1.0-pulseaudio'
package.name == 'alsa-base'
device.category == 'AUDIO'
command: audio_test
_description:
Play back a sound on the default output and listen for it on the
default input.
plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/alsa_info_collect
estimated_duration: 2.0
command: alsa_info --no-dialog --no-upload --output ${PLAINBOX_SESSION_SHARE}/alsa_info.log
_description:
Collect audio-related system information. This data can be used to
simulate this computer's audio subsystem and perform more detailed tests
under a controlled environment.
plugin: attachment
category_id: 2013.com.canonical.plainbox::audio
id: audio/alsa_info_attachment
depends: audio/alsa_info_collect
estimated_duration: 1.0
command: [ -e ${PLAINBOX_SESSION_SHARE}/alsa_info.log ] && cat ${PLAINBOX_SESSION_SHARE}/alsa_info.log
_description:
Attaches the audio hardware data collection log to the results.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/channels
estimated_duration: 20.0
command: speaker-test -c 2 -l 1 -t wav
_description:
PURPOSE:
Check that the various audio channels are working properly
STEPS:
1. Commence the test
VERIFICATION:
You should clearly hear a voice from the different audio channels
plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/check_volume
estimated_duration: 1.0
requires:
package.name == 'pulseaudio-utils'
device.category == 'AUDIO'
command: volume_test --minvol 1 --maxvol 100
_description:
This test will verify that the volume levels are at an acceptable level on
your local system. The test will validate that the volume is greater than
or equal to minvol and less than or equal to maxvol for all sources (inputs)
and sinks (outputs) recognized by PulseAudio. It will also validate that the
active source and sink are not muted. You should not manually adjust the
volume or mute before running this test.
plugin: manual
category_id: 2013.com.canonical.plainbox::audio
id: audio/external-lineout
estimated_duration: 30.0
_description:
PURPOSE:
Check that external line out connection works correctly
STEPS:
1. Insert cable to speakers (with built-in amplifiers) on the line out port
2. Open system sound preferences, 'Output' tab, select 'Line-out' on the connector list. Commence the test
3. On the system sound preferences, select 'Internal Audio' on the device list and click 'Test Speakers' to check left and right channel
VERIFICATION:
1. Do you hear a sound in the speakers? The internal speakers should *not* be muted automatically
2. Do you hear the sound coming out on the corresponding channel?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/external-linein
estimated_duration: 120.0
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'pulseaudio-utils'
package.name == 'gstreamer1.0-plugins-good' or package.name == 'gstreamer0.10-plugins-good'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
alsa_record_playback
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
Check that external line in connection works correctly
STEPS:
1. Use a cable to connect the line in port to an external line out source.
2. Open system sound preferences, 'Input' tab, select 'Line-in' on the connector list. Commence the test
3. After a few seconds, your recording will be played back to you.
VERIFICATION:
Did you hear your recording?
plugin: user-interact
category_id: 2013.com.canonical.plainbox::audio
id: audio/speaker-headphone-plug-detection
estimated_duration: 60.0
requires:
device.category == 'AUDIO'
package.name == 'pulseaudio-utils'
command: pulse-active-port-change sinks
_description:
PURPOSE:
Check that system detects speakers or headphones being plugged in
STEPS:
1. Prepare a pair of headphones or speakers with a standard 3.5mm jack
2. Locate the speaker / headphone jack on the device under test
3. Run the test (you have 30 seconds from now on)
4. Plug headphones or speakers into the appropriate jack
5. Unplug the device for subsequent tests.
VERIFICATION:
Verification is automatic, no action is required.
The test times out after 30 seconds (and fails in that case).
plugin: user-interact
category_id: 2013.com.canonical.plainbox::audio
id: audio/microphone-plug-detection
estimated_duration: 60.0
requires:
device.category == 'AUDIO'
package.name == 'pulseaudio-utils'
command: pulse-active-port-change sources
_description:
PURPOSE:
Check that system detects a microphone being plugged in
STEPS:
1. Prepare a microphone with a standard 3.5mm jack
2. Locate the microphone jack on the device under test.
Keep in mind that it may be shared with the headphone jack.
3. Run the test (you have 30 seconds from now on)
4. Plug the microphone into the appropriate jack
5. Unplug the device for subsequent tests.
VERIFICATION:
Verification is automatic, no action is required.
The test times out after 30 seconds (and fails in that case).
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/balance_internal_speaker
estimated_duration: 20.0
depends: audio/playback_auto
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
gst_pipeline_test -t 10 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
Check that balance control works correctly on internal speakers
STEPS:
1. Check that moving the balance slider from left to right works smoothly
2. Commence the test to play an audio tone for 10 seconds.
3. Move the balance slider from left to right and back.
4. Check that actual speaker audio balance follows your setting.
VERIFICATION:
Does the slider move smoothly, as well as being followed by the setting by the actual audio output?
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/balance_headphones
depends: audio/playback_headphones
estimated_duration: 30.0
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
gst_pipeline_test -t 10 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
Check that balance control works correctly on external headphone
STEPS:
1. Check that moving the balance slider from left to right works smoothly
2. Commence the test to play an audio tone for 10 seconds.
3. Move the balance slider from left to right and back.
4. Check that actual headphone audio balance follows your setting.
VERIFICATION:
Does the slider move smoothly, as well as being followed by the setting by the actual audio output?
plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/list_devices_after_suspend_30_cycles
estimated_duration: 1.0
depends: power-management/suspend_30_cycles
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
command: cat /proc/asound/cards
_description: Test to detect audio devices after suspending 30 times.
plugin: user-interact-verify
category_id: 2013.com.canonical.plainbox::audio
id: audio/playback_auto_after_suspend_30_cycles
estimated_duration: 5.0
depends: audio/list_devices power-management/suspend_30_cycles
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
package.name == 'pulseaudio-utils'
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
audio_settings set --device=pci --volume=50
gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! autoaudiosink'
EXIT_CODE=$?
audio_settings restore --file=$PLAINBOX_SESSION_SHARE/pulseaudio_settings
exit $EXIT_CODE
_description:
PURPOSE:
This test will check that internal speakers work correctly after suspending 30 times.
STEPS:
1. Make sure that no external speakers or headphones are connected
When testing a desktop, you can skip this test if there is no
internal speaker, we will test the external output later
2. Commence the test to play a brief tone on your audio device
VERIFICATION:
Did you hear a tone?
plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/alsa_record_playback_automated_after_suspend_30_cycles
estimated_duration: 10.0
depends: power-management/suspend_30_cycles
requires:
package.name == 'python3-gi'
package.name == 'gir1.2-gstreamer-1.0'
package.name == 'libgstreamer1.0-0'
package.name == 'gstreamer1.0-plugins-good'
package.name == 'gstreamer1.0-pulseaudio'
package.name == 'alsa-base'
device.category == 'AUDIO'
command: audio_test
_description:
Play back a sound on the default output and listen for it on the
default input, after suspending 30 times.
plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/check_volume_after_suspend_30_cycles
estimated_duration: 1.0
depends: power-management/suspend_30_cycles
requires:
package.name == 'pulseaudio-utils'
device.category == 'AUDIO'
command: volume_test --minvol 1 --maxvol 100
_description:
This test will verify that the volume levels are at an acceptable level on
your local system. The test will validate that the volume is greater than
or equal to minvol and less than or equal to maxvol for all sources (inputs)
and sinks (outputs) recognized by PulseAudio. It will also validate that the
active source and sink are not muted. You should not manually adjust the
volume or mute before running this test.
plugin: shell
category_id: 2013.com.canonical.plainbox::audio
id: audio/audio_after_suspend_30_cycles
estimated_duration: 1.0
depends: power-management/suspend_30_cycles
requires:
device.category == 'AUDIO'
package.name == 'alsa-base'
_description: Record mixer settings after suspending 30 times.
command:
audio_settings store --file=$PLAINBOX_SESSION_SHARE/audio_settings_after_suspend_30_cycles
diff $PLAINBOX_SESSION_SHARE/audio_settings_before_suspend $PLAINBOX_SESSION_SHARE/audio_settings_after_suspend_30_cycles
plainbox-provider-checkbox-0.25/COPYING 0000664 0001750 0001750 00000104513 12646152433 021133 0 ustar sylvain sylvain 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
plainbox-provider-checkbox-0.25/bin/ 0000775 0001750 0001750 00000000000 12646152434 020645 5 ustar sylvain sylvain 0000000 0000000 plainbox-provider-checkbox-0.25/bin/dns_server_test 0000775 0001750 0001750 00000002563 12646152433 024011 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# Verify dns server setup
# Packages and ports can be verified offline but external connections
# require a network connection. The script will check for this.
#
# Verify process is running. Expected output 'pgrep named' is a $pid
check=`pgrep named`
if [ -z "$check" ]; then
echo "FAIL: DNS bind is not running."
exit 1
fi
# Check ports
result1=`host www.ubuntu.com localhost | grep "#53"`
result2=`host -T -6 www.ubuntu.com ip6-localhost | grep "#53"`
if [ -z "$result1" ]; then
echo "FAIL: DNS is not using port 53."
exit 1
elif [ -z "$result2" ]; then
echo "FAIL: DNS is not using port 53 on IPv6."
exit 1
fi
# Check if udp is established
udpCheck=`netstat -auvpn | egrep '(:53)' |egrep 'udp'`
if [ -z "$udpCheck" ]; then
echo "FAIL: DNS udp setup is not established."
exit 1
fi
# Check if external dns queries work but first verify the network
# is up and running
check=`ping -c 2 www.ubuntu.com |grep "2 received"`
if [ -n "$check" ]; then
failure="2(SERVFAIL)"
result1=`host www.ubuntu.com localhost | grep "SERVFAIL" |awk '{print $5}'`
result2=`host -T -6 www.ubuntu.com ip6-localhost | grep "SERVFAIL" |awk '{print $5}'`
if [ "$result1" = $failure ]; then
echo "FAIL: DNS external connection fails."
exit 1
elif [ "$result2" = $failure ]; then
echo "FAIL: DNS external connection via IPv6 fails."
exit 1
fi
fi
exit 0
plainbox-provider-checkbox-0.25/bin/disk_read_performance_test 0000775 0001750 0001750 00000004741 12646152433 026145 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# Verify that disk storage performs at or above baseline performance
#
#Default to a lower bound of 15 MB/s
DEFAULT_BUF_READ=15
for disk in $@; do
echo "Beginning $0 test for $disk"
echo "---------------------------------------------------"
disk_type=`udevadm info --name /dev/$disk --query property | grep "ID_BUS" | awk '{gsub(/ID_BUS=/," ")}{printf $1}'`
dev_path=`udevadm info --name /dev/$disk --query property | grep "DEVPATH" | awk '{gsub(/DEVPATH=/," ")}{printf $1}'`
echo "INFO: $disk type is $disk_type"
case $disk_type in
"usb" )
#Custom metrics are guesstimates for now...
MIN_BUF_READ=7
# Increase MIN_BUF_READ if a USB3 device is plugged in a USB3 hub port
if [[ $dev_path =~ ((.*usb[0-9]+).*\/)[0-9]-[0-9\.:\-]+\/.* ]]; then
device_version=`cat '/sys/'${BASH_REMATCH[1]}'/version'`
hub_port_version=`cat '/sys/'${BASH_REMATCH[2]}'/version'`
if [ $(echo "$device_version >= 3.00"|bc -l) -eq 1 -a $(echo "$hub_port_version >= 3.00"|bc -l) -eq 1 ]; then
MIN_BUF_READ=80
fi
fi
;;
"ide" ) MIN_BUF_READ=40;;
* ) MIN_BUF_READ=$DEFAULT_BUF_READ;;
esac
echo "INFO: $disk_type: Using $MIN_BUF_READ MB/sec as the minimum throughput speed"
max_speed=0
echo ""
echo "Beginning hdparm timing runs"
echo "---------------------------------------------------"
for iteration in `seq 1 10`; do
speed=`hdparm -t /dev/$disk 2>/dev/null | grep "Timing buffered disk reads" | awk -F"=" '{print $2}' | awk '{print $1}'`
echo "INFO: Iteration $iteration: Detected speed is $speed MB/sec"
if [ -z "$speed" ]; then
echo "WARNING: Device $disk is too small! Aborting test."
exit 0
fi
speed=${speed/.*}
if [ $speed -gt $max_speed ]; then
max_speed=$speed
fi
done
echo "INFO: Maximum detected speed is $max_speed MB/sec"
echo "---------------------------------------------------"
echo ""
result=0
if [ $max_speed -gt $MIN_BUF_READ ]; then
echo "PASS: $disk Max Speed of $max_speed MB/sec is faster than Minimum Buffer Read Speed of $MIN_BUF_READ MB/sec"
else
echo "FAIL: $disk Max Speed of $max_speed MB/sec is slower than Minimum Buffer Read Speed of $MIN_BUF_READ MB/sec"
result=1
fi
done
if [ $result -gt 0 ]; then
echo "WARNING: One or more disks failed testing!"
exit 1
else
echo "All devices passed testing!"
exit 0
fi
plainbox-provider-checkbox-0.25/bin/camera_test 0000775 0001750 0001750 00000051664 12646152433 023075 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
#
# This file is part of Checkbox.
#
# Copyright 2008-2012 Canonical Ltd.
#
# The v4l2 ioctl code comes from the Python bindings for the v4l2
# userspace api (http://pypi.python.org/pypi/v4l2):
# Copyright (C) 1999-2009 the contributors
#
# The JPEG metadata parser is a part of bfg-pages:
# http://code.google.com/p/bfg-pages/source/browse/trunk/pages/getimageinfo.py
# Copyright (C) Tim Hoffman
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
#
import argparse
import ctypes
import errno
import fcntl
import imghdr
import logging
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
_IOC_NRBITS = 8
_IOC_TYPEBITS = 8
_IOC_SIZEBITS = 14
_IOC_NRSHIFT = 0
_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS
_IOC_WRITE = 1
_IOC_READ = 2
def _IOC(dir_, type_, nr, size):
return (
ctypes.c_int32(dir_ << _IOC_DIRSHIFT).value |
ctypes.c_int32(ord(type_) << _IOC_TYPESHIFT).value |
ctypes.c_int32(nr << _IOC_NRSHIFT).value |
ctypes.c_int32(size << _IOC_SIZESHIFT).value)
def _IOC_TYPECHECK(t):
return ctypes.sizeof(t)
def _IOR(type_, nr, size):
return _IOC(_IOC_READ, type_, nr, ctypes.sizeof(size))
def _IOWR(type_, nr, size):
return _IOC(_IOC_READ | _IOC_WRITE, type_, nr, _IOC_TYPECHECK(size))
class v4l2_capability(ctypes.Structure):
"""
Driver capabilities
"""
_fields_ = [
('driver', ctypes.c_char * 16),
('card', ctypes.c_char * 32),
('bus_info', ctypes.c_char * 32),
('version', ctypes.c_uint32),
('capabilities', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 4),
]
# Values for 'capabilities' field
V4L2_CAP_VIDEO_CAPTURE = 0x00000001
V4L2_CAP_VIDEO_OVERLAY = 0x00000004
V4L2_CAP_READWRITE = 0x01000000
V4L2_CAP_STREAMING = 0x04000000
v4l2_frmsizetypes = ctypes.c_uint
(
V4L2_FRMSIZE_TYPE_DISCRETE,
V4L2_FRMSIZE_TYPE_CONTINUOUS,
V4L2_FRMSIZE_TYPE_STEPWISE,
) = range(1, 4)
class v4l2_frmsize_discrete(ctypes.Structure):
_fields_ = [
('width', ctypes.c_uint32),
('height', ctypes.c_uint32),
]
class v4l2_frmsize_stepwise(ctypes.Structure):
_fields_ = [
('min_width', ctypes.c_uint32),
('min_height', ctypes.c_uint32),
('step_width', ctypes.c_uint32),
('min_height', ctypes.c_uint32),
('max_height', ctypes.c_uint32),
('step_height', ctypes.c_uint32),
]
class v4l2_frmsizeenum(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('discrete', v4l2_frmsize_discrete),
('stepwise', v4l2_frmsize_stepwise),
]
_fields_ = [
('index', ctypes.c_uint32),
('pixel_format', ctypes.c_uint32),
('type', ctypes.c_uint32),
('_u', _u),
('reserved', ctypes.c_uint32 * 2)
]
_anonymous_ = ('_u',)
class v4l2_fmtdesc(ctypes.Structure):
_fields_ = [
('index', ctypes.c_uint32),
('type', ctypes.c_int),
('flags', ctypes.c_uint32),
('description', ctypes.c_char * 32),
('pixelformat', ctypes.c_uint32),
('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)
VIDIOC_ENUM_FMT = _IOWR('V', 2, v4l2_fmtdesc)
class CameraTest:
"""
A simple class that displays a test image via GStreamer.
"""
def __init__(self, args, gst_plugin=None, gst_video_type=None):
self.args = args
self._mainloop = GObject.MainLoop()
self._width = 640
self._height = 480
self._gst_plugin = gst_plugin
self._gst_video_type = gst_video_type
def detect(self):
"""
Display information regarding webcam hardware
"""
cap_status = dev_status = 1
for i in range(10):
cp = v4l2_capability()
device = '/dev/video%d' % i
try:
with open(device, 'r') as vd:
fcntl.ioctl(vd, VIDIOC_QUERYCAP, cp)
except IOError:
continue
dev_status = 0
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(" flags : 0x%x [" % cp.capabilities,
' CAPTURE' if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE
else '',
' OVERLAY' if cp.capabilities & V4L2_CAP_VIDEO_OVERLAY
else '',
' READWRITE' if cp.capabilities & V4L2_CAP_READWRITE
else '',
' STREAMING' if cp.capabilities & V4L2_CAP_STREAMING
else '',
' ]', sep="")
resolutions = self._get_supported_resolutions(device)
print(' ',
self._supported_resolutions_to_string(resolutions).replace(
"\n", " "),
sep="")
if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE:
cap_status = 0
return dev_status | cap_status
def led(self):
"""
Activate camera (switch on led), but don't display any output
"""
pipespec = ("v4l2src device=%(device)s "
"! %(type)s "
"! %(plugin)s "
"! testsink"
% {'device': self.args.device,
'type': self._gst_video_type,
'plugin': self._gst_plugin})
logging.debug("LED test with pipeline %s", pipespec)
self._pipeline = Gst.parse_launch(pipespec)
self._pipeline.set_state(Gst.State.PLAYING)
time.sleep(3)
self._pipeline.set_state(Gst.State.NULL)
def display(self):
"""
Displays the preview window
"""
pipespec = ("v4l2src device=%(device)s "
"! %(type)s,width=%(width)d,height=%(height)d "
"! %(plugin)s "
"! autovideosink"
% {'device': self.args.device,
'type': self._gst_video_type,
'width': self._width,
'height': self._height,
'plugin': self._gst_plugin})
logging.debug("display test with pipeline %s", pipespec)
self._pipeline = Gst.parse_launch(pipespec)
self._pipeline.set_state(Gst.State.PLAYING)
time.sleep(10)
self._pipeline.set_state(Gst.State.NULL)
def still(self):
"""
Captures an image to a file
"""
if self.args.filename:
self._still_helper(self.args.filename, self._width, self._height,
self.args.quiet)
else:
with NamedTemporaryFile(prefix='camera_test_', suffix='.jpg') as f:
self._still_helper(f.name, self._width, self._height,
self.args.quiet)
def _still_helper(self, filename, width, height, quiet, pixelformat=None):
"""
Captures an image to a given filename. width and height specify the
image size and quiet controls whether the image is displayed to the
user (quiet = True means do not display image).
"""
command = ["fswebcam", "-D 1", "-S 50", "--no-banner",
"-d", self.args.device,
"-r", "%dx%d"
% (width, height), filename]
use_gstreamer = False
if pixelformat:
if 'MJPG' == pixelformat: # special tweak for fswebcam
pixelformat = 'MJPEG'
command.extend(["-p", pixelformat])
try:
check_call(command, stdout=open(os.devnull, 'w'), stderr=STDOUT)
except (CalledProcessError, OSError):
use_gstreamer = True
if use_gstreamer:
pipespec = ("v4l2src device=%(device)s "
"! %(type)s,width=%(width)d,height=%(height)d "
"! %(plugin)s "
"! jpegenc "
"! filesink location=%(filename)s"
% {'device': self.args.device,
'type': self._gst_video_type,
'width': width,
'height': height,
'plugin': self._gst_plugin,
'filename': filename})
logging.debug("still test with gstreamer and "
"pipeline %s", pipespec)
self._pipeline = Gst.parse_launch(pipespec)
self._pipeline.set_state(Gst.State.PLAYING)
time.sleep(3)
self._pipeline.set_state(Gst.State.NULL)
if not quiet:
try:
check_call(["timeout", "-k", "11", "10", "eog", filename])
except CalledProcessError:
pass
def _supported_resolutions_to_string(self, supported_resolutions):
"""
Return a printable string representing a list of supported resolutions
"""
ret = ""
for resolution in supported_resolutions:
ret += "Format: %s (%s)\n" % (resolution['pixelformat'],
resolution['description'])
ret += "Resolutions: "
for res in resolution['resolutions']:
ret += "%sx%s," % (res[0], res[1])
# truncate the extra comma with :-1
ret = ret[:-1] + "\n"
return ret
def resolutions(self):
"""
After querying the webcam for supported formats and resolutions,
take multiple images using the first format returned by the driver,
and see if they are valid
"""
resolutions = self._get_supported_resolutions(self.args.device)
# print supported formats and resolutions for the logs
print(self._supported_resolutions_to_string(resolutions))
# pick the first format, which seems to be what the driver wants for a
# default. This also matches the logic that fswebcam uses to select
# a default format.
resolution = resolutions[0]
if resolution:
print("Taking multiple images using the %s format"
% resolution['pixelformat'])
for res in resolution['resolutions']:
w = res[0]
h = res[1]
f = NamedTemporaryFile(prefix='camera_test_%s%sx%s' %
(resolution['pixelformat'], w, h),
suffix='.jpg', delete=False)
print("Taking a picture at %sx%s" % (w, h))
self._still_helper(f.name, w, h, True,
pixelformat=resolution['pixelformat'])
if self._validate_image(f.name, w, h):
print("Validated image %s" % f.name)
os.remove(f.name)
else:
print("Failed to validate image %s" % f.name,
file=sys.stderr)
os.remove(f.name)
return 1
return 0
def _get_pixel_formats(self, device, maxformats=5):
"""
Query the camera to see what pixel formats it supports. A list of
dicts is returned consisting of format and description. The caller
should check whether this camera supports VIDEO_CAPTURE before
calling this function.
"""
supported_formats = []
fmt = v4l2_fmtdesc()
fmt.index = 0
fmt.type = V4L2_CAP_VIDEO_CAPTURE
try:
while fmt.index < maxformats:
with open(device, 'r') as vd:
if fcntl.ioctl(vd, VIDIOC_ENUM_FMT, fmt) == 0:
pixelformat = {}
# save the int type for re-use later
pixelformat['pixelformat_int'] = fmt.pixelformat
pixelformat['pixelformat'] = "%s%s%s%s" % \
(chr(fmt.pixelformat & 0xFF),
chr((fmt.pixelformat >> 8) & 0xFF),
chr((fmt.pixelformat >> 16) & 0xFF),
chr((fmt.pixelformat >> 24) & 0xFF))
pixelformat['description'] = fmt.description.decode()
supported_formats.append(pixelformat)
fmt.index = fmt.index + 1
except IOError as e:
# EINVAL is the ioctl's way of telling us that there are no
# more formats, so we ignore it
if e.errno != errno.EINVAL:
print("Unable to determine Pixel Formats, this may be a "
"driver issue.")
return supported_formats
return supported_formats
def _get_supported_resolutions(self, device):
"""
Query the camera for supported resolutions for a given pixel_format.
Data is returned in a list of dictionaries with supported pixel
formats as the following example shows:
resolution['pixelformat'] = "YUYV"
resolution['description'] = "(YUV 4:2:2 (YUYV))"
resolution['resolutions'] = [[width, height], [640, 480], [1280, 720] ]
If we are unable to gather any information from the driver, then we
return YUYV and 640x480 which seems to be a safe default.
Per the v4l2 spec the ioctl used here is experimental
but seems to be well supported.
"""
supported_formats = self._get_pixel_formats(device)
if not supported_formats:
resolution = {}
resolution['description'] = "YUYV"
resolution['pixelformat'] = "YUYV"
resolution['resolutions'] = [[640, 480]]
supported_formats.append(resolution)
return supported_formats
for supported_format in supported_formats:
resolutions = []
framesize = v4l2_frmsizeenum()
framesize.index = 0
framesize.pixel_format = supported_format['pixelformat_int']
with open(device, 'r') as vd:
try:
while fcntl.ioctl(vd,
VIDIOC_ENUM_FRAMESIZES,
framesize) == 0:
if framesize.type == V4L2_FRMSIZE_TYPE_DISCRETE:
resolutions.append([framesize.discrete.width,
framesize.discrete.height])
# for continuous and stepwise, let's just use min and
# max they use the same structure and only return
# one result
elif (framesize.type in (V4L2_FRMSIZE_TYPE_CONTINUOUS,
V4L2_FRMSIZE_TYPE_STEPWISE)):
resolutions.append([framesize.stepwise.min_width,
framesize.stepwise.min_height]
)
resolutions.append([framesize.stepwise.max_width,
framesize.stepwise.max_height]
)
break
framesize.index = framesize.index + 1
except IOError as e:
# EINVAL is the ioctl's way of telling us that there are no
# more formats, so we ignore it
if e.errno != errno.EINVAL:
print("Unable to determine supported framesizes "
"(resolutions), this may be a driver issue.")
supported_format['resolutions'] = resolutions
return supported_formats
def _validate_image(self, filename, width, height):
"""
Given a filename, ensure that the image is the width and height
specified and is a valid image file.
"""
if imghdr.what(filename) != 'jpeg':
return False
outw = outh = 0
with open(filename, mode='rb') as jpeg:
jpeg.seek(2)
b = jpeg.read(1)
try:
while (b and ord(b) != 0xDA):
while (ord(b) != 0xFF):
b = jpeg.read(1)
while (ord(b) == 0xFF):
b = jpeg.read(1)
if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
jpeg.seek(3, 1)
h, w = struct.unpack(">HH", jpeg.read(4))
break
b = jpeg.read(1)
outw, outh = int(w), int(h)
except (struct.error, ValueError):
pass
if outw != width:
print("Image width does not match, was %s should be %s" %
(outw, width), file=sys.stderr)
return False
if outh != height:
print("Image width does not match, was %s should be %s" %
(outh, height), file=sys.stderr)
return False
return True
return True
def parse_arguments(argv):
"""
Parse command line arguments
"""
parser = argparse.ArgumentParser(description="Run a camera-related test")
subparsers = parser.add_subparsers(dest='test',
title='test',
description='Available camera tests')
parser.add_argument('--debug', dest='log_level',
action="store_const", const=logging.DEBUG,
default=logging.INFO, help="Show debugging messages")
def add_device_parameter(parser):
group = parser.add_mutually_exclusive_group()
group.add_argument("-d", "--device", default="/dev/video0",
help="Device for the webcam to use")
group.add_argument("--highest-device", action="store_true",
help=("Use the /dev/videoN "
"where N is the highest value available"))
group.add_argument("--lowest-device", action="store_true",
help=("Use the /dev/videoN "
"where N is the lowest value available"))
subparsers.add_parser('detect')
led_parser = subparsers.add_parser('led')
add_device_parameter(led_parser)
display_parser = subparsers.add_parser('display')
add_device_parameter(display_parser)
still_parser = subparsers.add_parser('still')
add_device_parameter(still_parser)
still_parser.add_argument("-f", "--filename",
help="Filename to store the picture")
still_parser.add_argument("-q", "--quiet", action="store_true",
help=("Don't display picture, "
"just write the picture to a file"))
resolutions_parser = subparsers.add_parser('resolutions')
add_device_parameter(resolutions_parser)
args = parser.parse_args(argv)
def get_video_devices():
devices = sorted(glob('/dev/video[0-9]'),
key=lambda d: re.search(r'\d', d).group(0))
assert len(devices) > 0, "No video devices found"
return devices
if hasattr(args, 'highest_device') and args.highest_device:
args.device = get_video_devices()[-1]
elif hasattr(args, 'lowest_device') and args.lowest_device:
args.device = get_video_devices()[0]
return args
if __name__ == "__main__":
args = parse_arguments(sys.argv[1:])
if not args.test:
args.test = 'detect'
logging.basicConfig(level=args.log_level)
# Import Gst only for the test cases that will need it
if args.test in ['display', 'still', 'led', 'resolutions']:
from gi.repository import Gst
if Gst.version()[0] > 0:
gst_plugin = 'videoconvert'
gst_video_type = 'video/x-raw'
else:
gst_plugin = 'ffmpegcolorspace'
gst_video_type = 'video/x-raw-yuv'
Gst.init(None)
camera = CameraTest(args, gst_plugin, gst_video_type)
else:
camera = CameraTest(args)
sys.exit(getattr(camera, args.test)())
plainbox-provider-checkbox-0.25/bin/create_connection 0000775 0001750 0001750 00000022276 12646152433 024265 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import sys
import os
import time
from subprocess import check_call, check_output, CalledProcessError
try:
from subprocess import DEVNULL # >= python3.3
except ImportError:
import os
DEVNULL = open(os.devnull, 'wb')
from uuid import uuid4
from argparse import ArgumentParser
CONNECTIONS_PATH = '/etc/NetworkManager/system-connections/'
def wifi_connection_section(ssid, uuid):
if not uuid:
uuid = uuid4()
connection = """
[connection]
id=%s
uuid=%s
type=802-11-wireless
""" % (ssid, uuid)
wireless = """
[802-11-wireless]
ssid=%s
mode=infrastructure""" % (ssid)
return connection + wireless
def wifi_security_section(security, key):
# Add security field to 802-11-wireless section
wireless_security = """
security=802-11-wireless-security
[802-11-wireless-security]
"""
if security.lower() == 'wpa':
wireless_security += """
key-mgmt=wpa-psk
auth-alg=open
psk=%s
""" % key
elif security.lower() == 'wep':
wireless_security += """
key-mgmt=none
wep-key=%s
""" % key
return wireless_security
def wifi_ip_sections():
ip = """
[ipv4]
method=auto
[ipv6]
method=auto
"""
return ip
def mobilebroadband_connection_section(name, uuid, connection_type):
if not uuid:
uuid = uuid4()
connection_section = """
[connection]
id={name}
uuid={uuid}
type={type}
autoconnect=false
""".format(name=name, uuid=uuid, type=connection_type)
return connection_section
def mobilebroadband_type_section(connection_type, apn,
username, password, pin):
number = ('*99#' if connection_type == 'gsm' else '#777')
type_section = """
[{type}]
number={number}
""".format(type=connection_type, number=number)
if apn:
type_section += "\napn={apn}".format(apn=apn)
if username:
type_section += "\nusername={username}".format(username=username)
if password:
type_section += "\npassword={password}".format(password=password)
if pin:
type_section += "\npin={pin}".format(pin=pin)
return type_section
def mobilebroadband_ppp_section():
return """
[ppp]
lcp-echo-interval=4
lcp-echo-failure=30
"""
def mobilebroadband_ip_section():
return """
[ipv4]
method=auto
"""
def mobilebroadband_serial_section():
return """
[serial]
baud=115200
"""
def block_until_created(connection, retries, interval):
while retries > 0:
try:
nmcli_con_list = check_output(['nmcli', 'con', 'list'],
stderr=DEVNULL,
universal_newlines=True)
except CalledProcessError:
check_call(['nmcli', 'con', 'reload'])
nmcli_con_list = check_output(['nmcli', 'con', 'show'],
stderr=DEVNULL,
universal_newlines=True)
if connection in nmcli_con_list:
print("Connection %s registered" % connection)
break
time.sleep(interval)
retries = retries - 1
if retries <= 0:
print("Failed to register %s." % connection, file=sys.stderr)
sys.exit(1)
else:
try:
nmcli_con_up = check_call(['nmcli', 'con', 'up', 'id', connection])
print("Connection %s activated." % connection)
except CalledProcessError as error:
print("Failed to activate %s." % connection, file=sys.stderr)
sys.exit(error.returncode)
def write_connection_file(name, connection_info):
try:
connection_file = open(CONNECTIONS_PATH + name, 'w')
connection_file.write(connection_info)
os.fchmod(connection_file.fileno(), 0o600)
connection_file.close()
except IOError:
print("Can't write to " + CONNECTIONS_PATH + name
+ ". Is this command being run as root?", file=sys.stderr)
sys.exit(1)
def create_wifi_connection(args):
wifi_connection = wifi_connection_section(args.ssid, args.uuid)
if args.security:
# Set security options
if not args.key:
print("You need to specify a key using --key "
"if using wireless security.", file=sys.stderr)
sys.exit(1)
wifi_connection += wifi_security_section(args.security, args.key)
elif args.key:
print("You specified an encryption key "
"but did not give a security type "
"using --security.", file=sys.stderr)
sys.exit(1)
try:
check_call(['rfkill', 'unblock', 'wlan', 'wifi'])
except CalledProcessError:
print("Could not unblock wireless "
"devices with rfkill.", file=sys.stderr)
# Don't fail the script if unblock didn't work though
wifi_connection += wifi_ip_sections()
# NetworkManager replaces forward-slashes in SSIDs with asterisks
name = args.ssid.replace('/', '*')
write_connection_file(name, wifi_connection)
return name
def create_mobilebroadband_connection(args):
name = args.name
mobilebroadband_connection = mobilebroadband_connection_section(name,
args.uuid,
args.type)
mobilebroadband_connection += mobilebroadband_type_section(args.type,
args.apn,
args.username,
args.password,
args.pin)
if args.type == 'cdma':
mobilebroadband_connection += mobilebroadband_ppp_section()
mobilebroadband_connection += mobilebroadband_ip_section()
mobilebroadband_connection += mobilebroadband_serial_section()
write_connection_file(name, mobilebroadband_connection)
return name
def main():
parser = ArgumentParser()
subparsers = parser.add_subparsers(help="sub command help")
wifi_parser = subparsers.add_parser('wifi',
help='Create a Wifi connection.')
wifi_parser.add_argument('ssid',
help="The SSID to connect to.")
wifi_parser.add_argument('-S', '--security',
choices=['wpa', 'wep'],
help=("The type of security to be used by the "
"connection. No security will be used if "
"nothing is specified."))
wifi_parser.add_argument('-K', '--key',
help="The encryption key required by the router.")
wifi_parser.set_defaults(func=create_wifi_connection)
mobilebroadband_parser = subparsers.add_parser('mobilebroadband',
help="Create a "
"mobile "
"broadband "
"connection.")
mobilebroadband_parser.add_argument('type',
choices=['gsm', 'cdma'],
help="The type of connection.")
mobilebroadband_parser.add_argument('-n', '--name',
default='MobileBB',
help="The name of the connection.")
mobilebroadband_parser.add_argument('-a', '--apn',
help="The APN to connect to.")
mobilebroadband_parser.add_argument('-u', '--username',
help="The username required by the "
"mobile broadband access point.")
mobilebroadband_parser.add_argument('-p', '--password',
help="The password required by the "
"mobile broadband access point.")
mobilebroadband_parser.add_argument('-P', '--pin',
help="The PIN of the SIM "
"card, if set.")
mobilebroadband_parser.set_defaults(func=create_mobilebroadband_connection)
parser.add_argument('-U', '--uuid',
help="""The uuid to assign to the connection for use by
NetworkManager. One will be generated if not
specified here.""")
parser.add_argument('-R', '--retries',
help="""The number of times to attempt bringing up the
connection until it is confirmed as active.""",
default=5)
parser.add_argument('-I', '--interval',
help=("The time to wait between attempts to detect "
"the registration of the connection."),
default=2)
args = parser.parse_args()
# Call function to create the appropriate connection type
connection_name = args.func(args)
# Make sure we don't exit until the connection is fully created
block_until_created(connection_name, args.retries, args.interval)
if __name__ == "__main__":
main()
plainbox-provider-checkbox-0.25/bin/audio_driver_info 0000775 0001750 0001750 00000006537 12646152433 024274 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
import sys
import re
from argparse import ArgumentParser
from subprocess import check_output, STDOUT, CalledProcessError
from checkbox_support.parsers.modinfo import ModinfoParser
TYPES = ("source", "sink")
entries_regex = re.compile("index.*?(?=device.icon_name)", re.DOTALL)
driver_regex = re.compile("(?<=driver_name = )\"(.*)\"")
name_regex = re.compile("(?<=name:).*")
class PacmdAudioDevice():
"""
Class representing an audio device with information gathered from pacmd
"""
def __init__(self, name, driver):
self._name = name
self._driver = driver
self._modinfo = self._modinfo_parser(driver)
self._driver_version = self._find_driver_ver()
def __str__(self):
retstr = "Device: %s\n" % self._name
if self._driver:
retstr += "Driver: %s (%s)" % (self._driver, self._driver_version)
else:
retstr += "Driver: Unknown"
return retstr
def _modinfo_parser(self, driver):
cmd = ['/sbin/modinfo', driver]
try:
stream = check_output(cmd, stderr=STDOUT, universal_newlines=True)
except CalledProcessError as err:
print("Error running %s:" % cmd, file=sys.stderr)
print(err.output, file=sys.stderr)
return None
if not stream:
print("Error: modinfo returned nothing", file=sys.stderr)
return None
else:
parser = ModinfoParser(stream)
modinfo = parser.get_all()
return modinfo
def _find_driver_ver(self):
# try the version field first, then vermagic second, some audio
# drivers don't report version if the driver is in-tree
if self._modinfo['version']:
return self._modinfo['version']
else:
# vermagic will look like this (below) and we only care about the
# first part:
# "3.2.0-29-generic SMP mod_unload modversions"
return self._modinfo['vermagic'].split()[0]
def list_device_info():
"""
Lists information on audio devices including device driver and version
"""
retval = 0
for vtype in TYPES:
try:
pacmd_entries = check_output(["pacmd", "list-%ss" % vtype],
universal_newlines=True)
except Exception as e:
print("Error when running pacmd list-%ss: %s" % (vtype, e),
file=sys.stderr)
return 1
entries = entries_regex.findall(pacmd_entries)
for entry in entries:
name_match = name_regex.search(entry)
if name_match:
name = name_match.group().strip()
else:
print("Unable to determine device bus information from the"
" pacmd list-%ss output\npacmd output was: %s" %
(vtype, pacmd_entries), file=sys.stderr)
return 1
driver_name = driver_regex.findall(entry)
if driver_name:
driver = driver_name[0]
else:
driver = None
print("%s\n" % PacmdAudioDevice(name, driver))
return retval
def main():
parser = ArgumentParser("List audio device and driver information")
args = parser.parse_args()
return list_device_info()
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/cking_suite 0000775 0001750 0001750 00000005475 12646152433 023111 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
import posixpath
import subprocess
from optparse import OptionParser
DEFAULT_DIRECTORY = "/tmp/checkbox.cking-scripts"
DEFAULT_LOCATION = "git://kernel.ubuntu.com/cking/scripts"
COMMAND_TEMPLATE = "cd %(scripts)s; ./%(script)s"
def print_line(key, value):
if type(value) is list:
print("%s:" % key)
for v in value:
print(" %s" % v)
else:
print("%s: %s" % (key, value))
def print_element(element):
for key, value in element.items():
print_line(key, value)
print()
def clone_cking_scripts(location, directory):
if posixpath.exists(directory):
return
dirname = posixpath.dirname(directory)
if not posixpath.exists(dirname):
os.makedirs(dirname)
process = subprocess.Popen(["git", "clone", location, directory],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
if process.wait():
raise Exception("Failed to clone cking scripts from %s" % location)
def run_cking_scripts(scripts, location, directory, dry_run):
if not dry_run:
clone_cking_scripts(location, directory)
for script in scripts:
path = posixpath.join(directory, script)
# Initialize test structure
test = {}
test["plugin"] = "shell"
test["name"] = posixpath.splitext(posixpath.basename(path))[0]
test["command"] = COMMAND_TEMPLATE % {
"scripts": posixpath.dirname(path),
"script": posixpath.basename(path)}
# Get description from first line of the README file
readme_path = posixpath.join(posixpath.dirname(path), "README")
if os.path.exists(readme_path):
file = open(readme_path)
test["description"] = file.readline().strip()
file.close
else:
test["description"] = "No description found"
yield test
def main(args):
usage = "Usage: %prog [OPTIONS] [SCRIPTS]"
parser = OptionParser(usage=usage)
parser.add_option("--dry-run",
default=False,
action="store_true",
help="Dry run to avoid branching from the given location.")
parser.add_option("-d", "--directory",
default=DEFAULT_DIRECTORY,
help="Directory where to branch qa-regression-testing")
parser.add_option("-l", "--location",
default=DEFAULT_LOCATION,
help="Location from where to branch qa-regression-testing")
(options, scripts) = parser.parse_args(args)
if not scripts:
parser.error("Must specify a script")
tests = run_cking_scripts(scripts, options.location, options.directory,
options.dry_run)
if not tests:
return 1
for test in tests:
print_element(test)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/sleep_time_check 0000775 0001750 0001750 00000005035 12646152433 024060 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import sys
import argparse
from statistics import mean
def main():
parser = argparse.ArgumentParser()
parser.add_argument('filename',
action='store',
help='The output file from sleep tests to parse')
parser.add_argument('--s',
dest='sleep_threshold',
action='store',
type=float,
default=10.00,
help=('The max time a system should have taken to '
'enter a sleep state. (Default: %(default)s)'
))
parser.add_argument('--r',
action='store',
dest='resume_threshold',
type=float,
default=5.00,
help=('The max time a system should have taken to '
'resume from a sleep state. (Default: '
'%(default)s)'))
args = parser.parse_args()
try:
with open(args.filename) as file:
lines = file.readlines()
except IOError as e:
print(e)
return False
sleep_time = None
sleep_times = []
resume_time = None
resume_times = []
# find our times
for line in lines:
if "Average time to sleep" in line:
sleep_time = float(line.split(':')[1].strip())
sleep_times.append(sleep_time)
elif "Average time to resume" in line:
resume_time = float(line.split(':')[1].strip())
resume_times.append(resume_time)
if (sleep_time is None or resume_time is None) or \
(len(sleep_times) != len(resume_times)):
print("ERROR: One or more times was not reported correctly")
return False
print("Average time to enter sleep state: %.4f seconds" % mean(sleep_times))
print("Average time to resume from sleep state: %.4f seconds" % mean(resume_times))
failed = False
if sleep_time > args.sleep_threshold:
print("System failed to suspend in less than %s seconds" %
args.sleep_threshold)
failed = True
if resume_time > args.resume_threshold:
print("System failed to resume in less than %s seconds" %
args.resume_threshold)
failed = True
if sleep_time <= 0.00 or resume_time <= 0.00:
print("ERROR: One or more times was not reported correctly")
failed = True
return failed
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/touchpad_driver_info 0000775 0001750 0001750 00000004342 12646152433 024772 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import sys
from io import StringIO
from subprocess import Popen, PIPE, check_output, STDOUT, CalledProcessError
from checkbox_support.parsers.udevadm import UdevadmParser
from checkbox_support.parsers.modinfo import ModinfoParser
# Command to retrieve udev information.
COMMAND = 'udevadm info --export-db'
class TouchResult:
attributes = {}
def addDevice(self, device):
if getattr(device, 'category') == 'TOUCHPAD':
self.attributes['driver'] = getattr(device, 'driver')
self.attributes['product'] = getattr(device, 'product')
class TouchpadDriver():
def __init__(self, driver):
self._driver = driver
self.driver_version = self._find_driver_version()
def _find_driver_version(self):
cmd = ['/sbin/modinfo', self._driver]
try:
stream = check_output(cmd, stderr=STDOUT,
universal_newlines=True)
except CalledProcessError as err:
print("Error communicating with modinfo.")
print(err.output)
return None
if not stream:
print("Error: modinfo returned nothing.")
else:
parser = ModinfoParser(stream)
version = parser.get_field('version')
if not version:
version = parser.get_field('vermagic').split()[0]
return version
def get_touch_attributes():
output, err = Popen(COMMAND, stdout=PIPE, shell=True).communicate()
if err:
print("Error running $s" % ' '.join(COMMAND))
print(err)
return None
udev = UdevadmParser(StringIO(output.decode("unicode-escape")))
result = TouchResult()
udev.run(result)
return result.attributes
def main():
attributes = get_touch_attributes()
if attributes:
modinfo = TouchpadDriver(attributes['driver'])
attributes['version'] = modinfo.driver_version
print("%s: %s\n%s: %s\n%s: %s\n" %
('Device', attributes['product'],
'Driver', attributes['driver'],
'Driver Version', attributes['version']))
else:
print("No Touchpad Detected")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/virtualization 0000775 0001750 0001750 00000037000 12646152433 023656 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
"""
Script to test virtualization functionality
Copyright (C) 2013, 2014 Canonical Ltd.
Authors
Jeff Marcom
Daniel Manrique
This program 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
from argparse import ArgumentParser
import configparser
from glob import glob
import os
import re
import logging
import lsb_release
import shlex
import signal
from subprocess import (
Popen,
PIPE,
CalledProcessError,
check_output,
call
)
import sys
import tempfile
import tarfile
import time
import urllib.request
DEFAULT_TIMEOUT = 500
class XENTest(object):
pass
# The "TAR" type is a tarball that contains both
# a disk image and a kernel binary. This is useful
# on architectures that don't (yet) have a bootloader
# in the disk image that we can chain to, and instead
# we need to have qemu load boot files externally
CLOUD_IMAGE_TYPE_TAR = 1
CLOUD_IMAGE_TYPE_DISK = 2
QEMU_DISK_TYPE_SD = 1
QEMU_DISK_TYPE_VIRTIO = 2
QEMU_DISK_TYPE_VIRTIO_BLK = 3
QEMU_ARCH_CONFIG = {
'arm64': {
'cloudimg_type': CLOUD_IMAGE_TYPE_TAR,
'cloudimg_arch': 'arm64',
'qemu_bin': 'qemu-system-aarch64',
'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO_BLK,
'qemu_extra_args': [
'-cpu', 'host',
'-enable-kvm',
],
},
'armhf': {
'cloudimg_type': CLOUD_IMAGE_TYPE_TAR,
'cloudimg_arch': 'armhf',
'qemu_bin': 'qemu-system-arm',
'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO_BLK,
'qemu_extra_args': [
'-machine', 'virt',
'-cpu', 'host',
'-enable-kvm',
'-serial', 'stdio',
],
},
'amd64': {
'cloudimg_type': CLOUD_IMAGE_TYPE_DISK,
'cloudimg_arch': 'i386',
'qemu_bin': 'qemu-system-x86_64',
'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO,
'qemu_extra_args': [
'-machine', 'accel=kvm:tcg',
],
},
'i386': {
'cloudimg_type': CLOUD_IMAGE_TYPE_DISK,
'cloudimg_arch': 'i386',
'qemu_bin': 'qemu-system-x86_64',
'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO,
'qemu_extra_args': [
'-machine', 'accel=kvm:tcg',
],
},
'ppc64el': {
'cloudimg_type': CLOUD_IMAGE_TYPE_DISK,
'cloudimg_arch': 'ppc64el',
'qemu_bin': 'qemu-system-ppc64',
'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO,
'qemu_extra_args': [
'-machine', 'pseries',
],
},
}
class QemuRunner(object):
def __init__(self, arch):
self.arch = arch
self.config = QEMU_ARCH_CONFIG[arch]
self.drive_id = 0
# Parameters common to all architectures
self.params = [
self.config['qemu_bin'],
"-m", "256",
"-display", "none",
"-nographic",
"-net", "nic",
"-net", "user,net=10.0.0.0/8,host=10.0.0.1,hostfwd=tcp::2222-:22",
]
# If arch is arm64, add the machine type for gicv3, or default to old
# type
if self.arch == 'arm64':
if glob("/sys/firmware/devicetree/base/interrupt-controller@*/compatible"):
self.config['qemu_extra_args'].extend(
['-machine', 'virt,gic_version=3'])
else:
self.config['qemu_extra_args'].extend(['-machine', 'virt'])
# Add any architecture-specific parameters
if 'qemu_extra_args' in self.config:
self.params = self.params + self.config['qemu_extra_args']
self.append = []
if self.config['cloudimg_type'] == CLOUD_IMAGE_TYPE_TAR:
self.append = self.append + [
'console=ttyAMA0',
'earlyprintk=serial',
'ro',
'rootfstype=ext4',
'root=LABEL=cloudimg-rootfs',
'rootdelay=10',
]
def add_boot_files(self, kernel=None, initrd=None, dtb=None):
if kernel:
self.params = self.params + ['-kernel', kernel]
if initrd:
self.params = self.params + ['-initrd', initrd]
if dtb:
self.params = self.params + ['-dtb', dtb]
def add_drive(self, cloudimg):
drive = ["-drive"]
if self.config['qemu_disk_type'] == QEMU_DISK_TYPE_SD:
drive = drive + ["file=%s,if=sd,cache=writeback" % (cloudimg)]
elif self.config['qemu_disk_type'] == QEMU_DISK_TYPE_VIRTIO:
drive = drive + ["file=%s,if=virtio" % (cloudimg)]
elif self.config['qemu_disk_type'] == QEMU_DISK_TYPE_VIRTIO_BLK:
drive = drive + ["file=%s,if=none,id=disk.%d"
% (cloudimg, self.drive_id)]
drive = drive + ["-device", "virtio-blk-device,drive=disk.%d"
% (self.drive_id)]
self.params = self.params + drive
self.drive_id = self.drive_id + 1
def get_params(self):
params = self.params
if self.append:
params = params + ['-append', '"%s"' % (" ".join(self.append))]
return params
class KVMTest(object):
def __init__(self, image=None, timeout=500, debug_file=None):
self.image = image
self.timeout = timeout
self.debug_file = debug_file
self.arch = check_output(['dpkg', '--print-architecture'],
universal_newlines=True).strip()
self.qemu_config = QEMU_ARCH_CONFIG[self.arch]
def download_image(self):
"""
Downloads Cloud image for same release as host machine
"""
# Check Ubuntu release info. Example {quantal, precise}
release = lsb_release.get_lsb_information()["CODENAME"]
# Construct URL
cloud_url = "http://cloud-images.ubuntu.com"
if self.qemu_config['cloudimg_type'] == CLOUD_IMAGE_TYPE_TAR:
cloud_iso = "%s-server-cloudimg-%s.tar.gz" % (
release, self.qemu_config['cloudimg_arch'])
elif self.qemu_config['cloudimg_type'] == CLOUD_IMAGE_TYPE_DISK:
cloud_iso = "%s-server-cloudimg-%s-disk1.img" % (
release, self.qemu_config['cloudimg_arch'])
else:
logging.error("Unknown cloud image type")
return False
image_url = "/".join((
cloud_url, release, "current", cloud_iso))
logging.debug("Downloading {}, from {}".format(cloud_iso, cloud_url))
# Attempt download
try:
resp = urllib.request.urlretrieve(image_url, cloud_iso)
except (IOError,
OSError,
urllib.error.HTTPError,
urllib.error.URLError) as exception:
logging.error("Failed download of image from %s: %s",
image_url, exception)
return False
# Unpack img file from tar
if self.qemu_config['cloudimg_type'] == CLOUD_IMAGE_TYPE_TAR:
cloud_iso_tgz = tarfile.open(cloud_iso)
cloud_iso = cloud_iso.replace('tar.gz', 'img')
cloud_iso_tgz.extract(cloud_iso)
if not os.path.isfile(cloud_iso):
return False
return cloud_iso
def boot_image(self, data_disk):
"""
Attempts to boot the newly created qcow image using
the config data defined in config.iso
"""
logging.debug("Attempting boot for:{}".format(data_disk))
qemu = QemuRunner(self.arch)
# Assume that a tar type image is not self-bootable, so
# therefore requires explicit bootfiles (otherwise, why
# not just use the disk format directly?
if self.qemu_config['cloudimg_type'] == CLOUD_IMAGE_TYPE_TAR:
for dir in ['/boot', '/']:
kernel = os.path.join(dir, 'vmlinuz')
initrd = os.path.join(dir, 'initrd.img')
if os.path.isfile(kernel):
qemu.add_boot_files(kernel=kernel, initrd=initrd)
break
qemu.add_drive(data_disk)
# Should we attach the cloud config disk
if os.path.isfile("seed.iso"):
logging.debug("Attaching Cloud config disk")
qemu.add_drive("seed.iso")
params = qemu.get_params()
logging.debug("Using params:{}".format(" ".join(params)))
logging.info("Storing VM console output in {}".format(
os.path.realpath(self.debug_file)))
# Open VM STDERR/STDOUT log file for writing
try:
file = open(self.debug_file, 'w')
except IOError:
logging.error("Failed creating file:{}".format(self.debug_file))
return False
# Start Virtual machine
self.process = Popen(
params, stdin=PIPE, stderr=file, stdout=file,
universal_newlines=True, shell=False)
def create_cloud_disk(self):
"""
Generate Cloud meta data and creates an iso object
to be mounted as virtual device to instance during boot.
"""
user_data = """\
#cloud-config
runcmd:
- [ sh, -c, echo "========= CERTIFICATION TEST =========" ]
power_state:
mode: halt
message: Bye
timeout: 480
final_message: CERTIFICATION BOOT COMPLETE
"""
meta_data = """\
{ echo instance-id: iid-local01; echo local-hostname, certification; }
"""
for file in ['user-data', 'meta-data']:
logging.debug("Creating cloud %s", file)
with open(file, "wt") as data_file:
os.fchmod(data_file.fileno(), 0o777)
data_file.write(vars()[file.replace("-", "_")])
# Create Data ISO hosting user & meta cloud config data
try:
iso_build = check_output(
['genisoimage', '-output', 'seed.iso', '-volid',
'cidata', '-joliet', '-rock', 'user-data', 'meta-data'],
universal_newlines=True)
except CalledProcessError as exception:
logging.exception("Cloud data disk creation failed")
def start(self):
logging.debug('Starting KVM Test')
status = 1
# Create temp directory:
date = time.strftime("%b_%d_%Y_")
with tempfile.TemporaryDirectory("_kvm_test", date) as temp_dir:
os.chmod(temp_dir, 0o744)
os.chdir(temp_dir)
if not self.image:
logging.debug('No image specified, downloading one now.')
# Download cloud image
self.image = self.download_image()
if self.image and os.path.isfile(self.image):
if "cloud" in self.image:
# Will assume we need to supply cloud meta data
# for instance boot to be successful
self.create_cloud_disk()
# Boot Virtual Machine
instance = self.boot_image(self.image)
time.sleep(self.timeout)
# If running in console, reset console window to regain
# control from VM Serial I/0
if sys.stdout.isatty():
call('reset')
# Check to be sure VM boot was successful
with open(self.debug_file, 'r') as debug_file:
file_contents = debug_file.read()
if "CERTIFICATION BOOT COMPLETE" in file_contents:
if "END SSH HOST KEY KEYS" in file_contents:
print("Booted successfully", file=sys.stderr)
else:
print("Booted successfully (Previously "
"initalized VM)", file=sys.stderr)
status = 0
else:
print("E: KVM instance failed to boot",
file=sys.stderr)
print("Console output".center(72, "="),
file=sys.stderr)
with open(self.debug_file, 'r') as console_log:
print(console_log.read(), file=sys.stderr)
print("E: KVM instance failed to boot",
file=sys.stderr)
self.process.terminate()
elif not self.image:
print("Could not find downloaded image")
else:
print("Could not find: {}".format(self.image),
file=sys.stderr)
return status
def test_kvm(args):
print("Executing KVM Test", file=sys.stderr)
DEFAULT_CFG = "/etc/checkbox.d/virtualization.cfg"
image = ""
timeout = ""
# Configuration data can come from three sources.
# Lowest priority is the config file.
config_file = DEFAULT_CFG
config = configparser.SafeConfigParser()
try:
config.readfp(open(config_file))
except IOError:
logging.warn("No config file found")
else:
try:
timeout = config.getfloat("KVM", "timeout")
except ValueError:
logging.warning('Invalid or Empty timeout in config file. '
'Falling back to default')
except configparser.NoSectionError as e:
logging.exception(e)
try:
image = config.get("KVM", "image")
except configparser.NoSectionError:
logging.exception('Invalid or Empty image in config file.')
# Next in priority are environment variables.
if 'KVM_TIMEOUT' in os.environ:
try:
timeout = float(os.environ['KVM_TIMEOUT'])
except ValueError as err:
logging.warning("TIMEOUT env variable: %s" % err)
timeout = DEFAULT_TIMEOUT
if 'KVM_IMAGE' in os.environ:
image = os.environ['KVM_IMAGE']
# Finally, highest-priority are command line arguments.
if args.timeout:
timeout = args.timeout
elif not timeout:
timeout = DEFAULT_TIMEOUT
if args.image:
image = args.image
kvm_test = KVMTest(image, timeout, args.log_file)
result = kvm_test.start()
sys.exit(result)
def main():
parser = ArgumentParser(description="Virtualization Test")
subparsers = parser.add_subparsers()
# Main cli options
kvm_test_parser = subparsers.add_parser(
'kvm', help=("Run kvm virtualization test"))
# Sub test options
kvm_test_parser.add_argument(
'-i', '--image', type=str, default=None)
kvm_test_parser.add_argument(
'-t', '--timeout', type=int)
kvm_test_parser.add_argument(
'-l', '--log-file', default='virt_debug',
help="Location for debugging output log. Defaults to %(default)s.")
kvm_test_parser.add_argument('--debug', dest='log_level',
action="store_const", const=logging.DEBUG,
default=logging.INFO)
kvm_test_parser.set_defaults(func=test_kvm)
args = parser.parse_args()
try:
logging.basicConfig(level=args.log_level)
except AttributeError:
pass # avoids exception when trying to run without specifying 'kvm'
# to check if not len(sys.argv) > 1
if len(vars(args)) == 0:
parser.print_help()
return False
args.func(args)
if __name__ == "__main__":
main()
plainbox-provider-checkbox-0.25/bin/cycle_vts 0000775 0001750 0001750 00000000771 12646152433 022572 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
set -o errexit
# NB: This script must be run with root privileges in order to have any effect!
CURRENT_VT=`/bin/fgconsole`
if [ "$CURRENT_VT" == "" ]
then
echo "Unable to determine current virtual terminal." >&2
exit 1
fi
if [ "$CURRENT_VT" -ne "1" ]
then
chvt 1
else
chvt 2
fi
sleep 2
chvt "$CURRENT_VT"
sleep 2
# make sure we switched back
END_VT=`/bin/fgconsole`
if [ "$END_VT" -ne "$CURRENT_VT" ]
then
echo "didn't get back to the original VT" >&2
exit 1
fi
plainbox-provider-checkbox-0.25/bin/network_ntp_test 0000775 0001750 0001750 00000016105 12646152433 024206 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
'''
Program to test that ntpdate will sync the clock with an internet time server.
Copyright (C) 2010 Canonical Ltd.
Author:
Jeff Lane
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
The purpose of this script is to test to see whether the test system can
connect to an internet time server and sync the local clock.
It will also check to see if ntpd is running locally, and if so, stop it for
the duration of the test and restart it after the test is finished.
By default, we're hitting ntp.ubuntu.com, however you can use any valid NTP
server by passing the URL to the program via --server
'''
import sys
import os
import logging
import signal
import time
from datetime import datetime, timedelta
from subprocess import Popen, PIPE
from argparse import ArgumentParser
def SilentCall(*popenargs):
'''
Modified version of subprocess.call() to supress output from the command
that is executed. Wait for command to complete, then return the returncode
attribute.
'''
null_fh = open('/dev/null', 'wb', 0)
try:
return (Popen(*popenargs, shell=True, stdout=null_fh, stderr=null_fh)
.wait())
finally:
null_fh.close()
def CheckNTPD():
'''
This checks to see if nptd is running or not, if so it returns a tuple
(status,pid,command) where status is either on or off.
'''
ps_list = (Popen('ps axo pid,comm', shell=True, stdout=PIPE)
.communicate()[0].splitlines())
for item in ps_list:
fields = item.split()
if fields[1] == 'ntpd':
logging.debug('Found %s with PID %s'
% (fields[1], fields[0]))
break
if fields[1] == 'ntpd':
return ('on', fields[0], fields[1])
else:
return ('off', '0', '0')
def StartStopNTPD(state, pid=0):
'''
This is used to either start or stop ntpd if its running.
'''
if state == 'off':
logging.info('Stopping ntpd process PID: %s' % pid)
os.kill(int(pid), signal.SIGHUP)
elif state == 'on':
logging.info('Starting ntp process')
SilentCall('/etc/init.d/ntp start')
ntpd_status = CheckNTPD()
if status == 0:
logging.debug('ntpd restarted with PID: %s' % ntpd_status[1])
else:
logging.error('ntpd restart failed for some reason')
else:
logging.error('%s is an unknown state, unable to start/stop ntpd' %
state)
def SyncTime(server):
'''
This is used to sync time to the specified ntp server. We use -b here as
that syncs time faster than the slewed method that ntpdate uses by default,
meaning we'll see something meaningful faster.
'''
cmd = 'ntpdate -b ' + server
logging.debug('using %s' % server)
sync = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
result = sync.communicate()
if sync.returncode == 0:
logging.info('Successful NTP update from %s' % server)
logging.debug(result[0].strip().decode())
return True
else:
logging.error('Failed to sync with %s' % server)
logging.error(result[1].strip().decode())
return False
def TimeCheck():
'''
Returns current time in a time.localtime() struct
'''
return time.localtime()
def SkewTime():
'''
Optional function. We can skew time by 1 hour if we'd like to see real sync
changes being enforced
'''
TIME_SKEW = 1
logging.info('Time Skewing has been selected. Setting clock ahead 1 hour')
# Let's get our current time
skewed = datetime.now() + timedelta(hours=TIME_SKEW)
logging.info('Current time is: %s' % time.asctime())
# Now create new time string in the form MMDDhhmmYYYY for the date program
date_time_string = skewed.strftime('%m%d%H%M%Y')
logging.debug('New date string is: %s' % date_time_string)
logging.debug('Setting new system time/date')
# This call is necessary for testing, otherwise TimeSkew() does nothing.
SilentCall('/bin/date %s' % date_time_string)
logging.info('Pre-sync time is: %s' % time.asctime())
def main():
description = 'Tests the ability to skew and sync the clock with an NTP server'
parser = ArgumentParser(description=description)
parser.add_argument('--server',
action='store',
default='ntp.ubuntu.com',
help='The NTP server to sync from. The default server \
is %(default)s')
parser.add_argument('--skew-time',
action='store_true',
default=False,
help='Setting this will change system time ahead by 1 \
hour to make the results of ntp syncing more dramatic \
and noticeable.')
parser.add_argument('-d', '--debug',
action='store_true',
default=False,
help='Verbose output for debugging purposes')
args = parser.parse_args()
if os.geteuid() != 0:
parser.error("You must run this script as root")
# Set up logging
format = '%(asctime)s %(levelname)-8s %(message)s'
date_format = '%Y-%m-%d %H:%M:%S'
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(format, date_format))
logger = logging.getLogger()
logger.setLevel(logging.INFO)
if args.debug:
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
# Make sure NTP is installed
if not os.access('/usr/sbin/ntpdate', os.F_OK):
logging.error('NTP is not installed!')
return 1
# Check for and stop the ntp daemon
ntpd_status = CheckNTPD()
logging.debug('Pre-sync ntpd status: %s %s %s' % (ntpd_status[0],
ntpd_status[1],
ntpd_status[2]))
if ntpd_status[0] == 'on':
logging.debug('Since ntpd is currently running, stopping it now')
StartStopNTPD('off', ntpd_status[1])
if args.skew_time:
logging.debug('Setting system time ahead one hour')
SkewTime()
else:
logging.info('Pre-sync time is: %s' % time.asctime(TimeCheck()))
sync = SyncTime(args.server)
logging.info('Current system time is: %s' % time.asctime(TimeCheck()))
# Restart ntp daemon
if ntpd_status[0] == 'on':
logging.debug('Since ntpd was previously running, starting it again')
StartStopNTPD('on')
if sync is True:
return 0
else:
return 1
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/color_depth_info 0000775 0001750 0001750 00000003705 12646152433 024114 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# color_depth_info
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Alberto Milone
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
"""
The get_color_depth got information from Xorg.*.log
"""
import os
import re
import sys
from glob import glob
def get_color_depth(log_dir='/var/log/'):
'''Return color depth and pixmap format'''
# find the most recent X.org log
depth = 8
pixmap_format = 8
log = None
max_time = 0
for log in glob(os.path.join(log_dir, 'Xorg.*.log')):
mtime = os.stat(log).st_mtime
if mtime > max_time:
max_time = mtime
current_log = log
if current_log is None:
depth = 0
pixmap_format = 0
return (depth, pixmap_format)
with open(current_log, 'rb') as stream:
for match in re.finditer('Depth (\d+) pixmap format is (\d+) bpp',
str(stream.read())):
depth = int(match.group(1))
pixmap_format = int(match.group(2))
return (depth, pixmap_format)
def main():
'''main function'''
depth, pixmap_format = get_color_depth()
print('Color Depth: {0}\nPixmap Format: {1} bpp'.format(depth,
pixmap_format))
if depth == 8:
return 1
return 0
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/lsmod_info 0000775 0001750 0001750 00000002317 12646152433 022726 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import sys
from checkbox_support.parsers.modinfo import ModinfoParser
from subprocess import Popen, PIPE, check_output, CalledProcessError
def main():
process = Popen('lsmod', stdout=PIPE, stderr=PIPE, universal_newlines=True)
data = process.stdout.readlines()
# Delete the first item because it's headers from lsmod output
data.pop(0)
module_list = [module.split()[0].strip() for module in data]
cmd = '/sbin/modinfo'
for module in sorted(module_list):
version = ''
stream = b''
try:
stream = check_output([cmd, module],
stderr=PIPE,
universal_newlines=False)
except CalledProcessError as e:
if e.returncode != 1:
raise e
else:
version = 'Unavailable'
stream = stream.decode('utf-8')
parser = ModinfoParser(stream)
if not version:
version = parser.get_field('version')
if not version:
version = parser.get_field('vermagic').split()[0]
print('%s: %s' % (module, version))
return 0
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/alsa_record_playback 0000775 0001750 0001750 00000000364 12646152433 024721 0 ustar sylvain sylvain 0000000 0000000 #!/bin/sh
OUTPUT=`mktemp -d`
gst_pipeline_test -t 5 "autoaudiosrc ! audioconvert ! level name=recordlevel interval=10000000 ! audioconvert ! wavenc ! filesink location=$OUTPUT/test.wav"
aplay $OUTPUT/test.wav
rm $OUTPUT/test.wav
rmdir $OUTPUT
plainbox-provider-checkbox-0.25/bin/optical_write_test 0000775 0001750 0001750 00000007740 12646152433 024506 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
TEMP_DIR='/tmp/optical-test'
ISO_NAME='optical-test.iso'
SAMPLE_FILE_PATH='/usr/share/example-content/'
SAMPLE_FILE='Ubuntu_Free_Culture_Showcase'
MD5SUM_FILE='optical_test.md5'
START_DIR=$PWD
create_working_dirs(){
# First, create the temp dir and cd there
echo "Creating Temp directory and moving there ..."
mkdir -p $TEMP_DIR || return 1
cd $TEMP_DIR
echo "Now working in $PWD ..."
}
get_sample_data(){
# Get our sample files
echo "Getting sample files from $SAMPLE_FILE_PATH ..."
cp -a $SAMPLE_FILE_PATH/$SAMPLE_FILE $TEMP_DIR
return $?
}
generate_md5(){
# Generate the md5sum
echo "Generating md5sums of sample files ..."
CUR_DIR=$PWD
cd $SAMPLE_FILE
md5sum * > $TEMP_DIR/$MD5SUM_FILE
# Check the sums for paranoia sake
check_md5 $TEMP_DIR/$MD5SUM_FILE
rt=$?
cd $CUR_DIR
return $rt
}
check_md5(){
echo "Checking md5sums ..."
md5sum -c $1
return $?
}
generate_iso(){
# Generate ISO image
echo "Creating ISO Image ..."
genisoimage -input-charset UTF-8 -r -J -o $ISO_NAME $SAMPLE_FILE
return $?
}
burn_iso(){
# Burn the ISO with the appropriate tool
echo "Sleeping 10 seconds in case drive is not yet ready ..."
sleep 10
echo "Beginning image burn ..."
if [ "$OPTICAL_TYPE" == 'cd' ]
then
wodim -eject dev=$OPTICAL_DRIVE $ISO_NAME
elif [ "$OPTICAL_TYPE" == 'dvd' ] || [ "$OPTICAL_TYPE" == 'bd' ]
then
growisofs -dvd-compat -Z $OPTICAL_DRIVE=$ISO_NAME
else
echo "Invalid type specified '$OPTICAL_TYPE'"
exit 1
fi
rt=$?
return $rt
}
check_disk(){
TIMEOUT=300
SLEEP_COUNT=0
INTERVAL=3
# Give the tester up to 5 minutes to reload the newly created CD/DVD
echo "Waiting up to 5 minutes for drive to be mounted ..."
while true; do
sleep $INTERVAL
SLEEP_COUNT=`expr $SLEEP_COUNT + $INTERVAL`
mount $OPTICAL_DRIVE 2>&1 |egrep -q "already mounted"
rt=$?
if [ $rt -eq 0 ]; then
echo "Drive appears to be mounted now"
break
fi
# If they exceed the timeout limit, make a best effort to load the tray
# in the next steps
if [ $SLEEP_COUNT -ge $TIMEOUT ]; then
echo "WARNING: TIMEOUT Exceeded and no mount detected!"
break
fi
done
echo "Deleting original data files ..."
rm -rf $SAMPLE_FILE
if [ -n "$(mount | grep $OPTICAL_DRIVE)" ]; then
MOUNT_PT=$(mount | grep $OPTICAL_DRIVE | awk '{print $3}')
echo "Disk is mounted to $MOUNT_PT"
else
echo "Attempting best effort to mount $OPTICAL_DRIVE on my own"
MOUNT_PT=$TEMP_DIR/mnt
echo "Creating temp mount point: $MOUNT_PT ..."
mkdir $MOUNT_PT
echo "Mounting disk to mount point ..."
mount $OPTICAL_DRIVE $MOUNT_PT
rt=$?
if [ $rt -ne 0 ]; then
echo "ERROR: Unable to re-mount $OPTICAL_DRIVE!" >&2
return 1
fi
fi
echo "Copying files from ISO ..."
cp $MOUNT_PT/* $TEMP_DIR
check_md5 $MD5SUM_FILE
return $?
}
cleanup(){
echo "Moving back to original location"
cd $START_DIR
echo "Now residing in $PWD"
echo "Cleaning up ..."
umount "$MOUNT_PT"
rm -fr $TEMP_DIR
echo "Ejecting spent media ..."
eject $OPTICAL_DRIVE
}
failed(){
echo $1
echo "Attempting to clean up ..."
cleanup
exit 1
}
if [ -e $1 ]; then
OPTICAL_DRIVE=$(readlink -f $1)
else
OPTICAL_DRIVE='/dev/sr0'
fi
if [ -n "$2" ]; then
OPTICAL_TYPE=$2
else
OPTICAL_TYPE='cd'
fi
create_working_dirs || failed "Failed to create working directories"
get_sample_data || failed "Failed to copy sample data"
generate_md5 || failed "Failed to generate initial md5"
generate_iso || failed "Failed to create ISO image"
burn_iso || failed "Failed to burn ISO image"
check_disk || failed "Failed to verify files on optical disk"
cleanup || failed "Failed to clean up"
exit 0
plainbox-provider-checkbox-0.25/bin/frequency_governors_test 0000775 0001750 0001750 00000064201 12646152433 025741 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import decimal
import os
import re
import sys
import time
import argparse
import logging
from subprocess import check_output, check_call, CalledProcessError, PIPE
class CPUScalingTest(object):
def __init__(self):
self.speedUpTolerance = 10.0 # percent
self.retryLimit = 5
self.retryTolerance = 5.0 # percent
self.sysCPUDirectory = "/sys/devices/system/cpu"
self.cpufreqDirectory = os.path.join(self.sysCPUDirectory,
"cpu0", "cpufreq")
self.idaFlag = "ida"
self.idaSpeedupFactor = 8.0 # percent
self.selectorExe = "cpufreq-selector"
self.ifSelectorExe = None
def getCPUFreqDirectories(self):
logging.debug("Getting CPU Frequency Directories")
if not os.path.exists(self.sysCPUDirectory):
logging.error("No file %s" % self.sysCPUDirectory)
return None
# look for cpu subdirectories
pattern = re.compile("cpu(?P[0-9]+)")
self.cpufreqDirectories = list()
for subdirectory in os.listdir(self.sysCPUDirectory):
match = pattern.search(subdirectory)
if match and match.group("cpuNumber"):
cpufreqDirectory = os.path.join(self.sysCPUDirectory,
subdirectory, "cpufreq")
if not os.path.exists(cpufreqDirectory):
logging.error("CPU %s has no cpufreq directory %s"
% (match.group("cpuNumber"), cpufreqDirectory))
return None
# otherwise
self.cpufreqDirectories.append(cpufreqDirectory)
if len(self.cpufreqDirectories) is 0:
return None
# otherwise
logging.debug("Located the following CPU Freq Directories:")
for line in self.cpufreqDirectories:
logging.debug(" %s" % line)
return self.cpufreqDirectories
def checkParameters(self, file):
logging.debug("Checking Parameters for %s" % file)
current = None
for cpufreqDirectory in self.cpufreqDirectories:
parameters = self.getParameters(cpufreqDirectory, file)
if not parameters:
logging.error("Error: could not determine cpu parameters from %s"
% os.path.join(cpufreqDirectory, file))
return None
if not current:
current = parameters
elif not current == parameters:
return None
return current
def getParameters(self, cpufreqDirectory, file):
logging.debug("Getting Parameters for %s" % file)
path = os.path.join(cpufreqDirectory, file)
file = open(path)
while 1:
line = file.readline()
if not line:
break
if len(line.strip()) > 0:
return line.strip().split()
return None
def setParameter(self, setFile, readFile, value,
skip=False, automatch=False):
def findParameter(targetFile):
logging.debug("Finding parameters for %s" % targetFile)
for root, _, files in os.walk(self.sysCPUDirectory):
for f in files:
rf = os.path.join(root, f)
if targetFile in rf:
return rf
return None
logging.debug("Setting %s to %s" % (setFile,value))
path = None
if not skip:
if automatch:
path = findParameter(setFile)
else:
path = os.path.join(self.cpufreqDirectory, setFile)
try:
check_call("echo \"%s\" > %s" % (value, path), shell=True)
except CalledProcessError as exception:
logging.exception("Command failed:")
logging.exception(exception)
return False
# verify it has changed
if automatch:
path = findParameter(readFile)
else:
path = os.path.join(self.cpufreqDirectory, readFile)
parameterFile = open(path)
line = parameterFile.readline()
if not line or line.strip() != str(value):
logging.error("Error: could not verify that %s was set to %s"
% (path, value))
if line:
logging.error("Actual Value: %s" % line)
else:
logging.error("parameter file was empty")
return False
return True
def checkSelectorExecutable(self):
logging.debug("Determining if %s is executable" % self.selectorExe)
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
if self.ifSelectorExe is None:
# cpufreq-selector default path
exe = os.path.join("/usr/bin/", self.selectorExe)
if is_exe(exe):
self.ifSelectorExe = True
return True
for path in os.environ["PATH"].split(os.pathsep):
exe = os.path.join(path, self.selectorExe)
if is_exe(exe):
self.ifSelectorExe = True
return True
self.ifSelectorExe = False
return False
def setParameterWithSelector(self, switch, setFile, readFile, value):
logging.debug("Setting %s with %s to %s" % (setFile, switch, value))
# Try the command for all CPUs
skip = True
if self.checkSelectorExecutable():
try:
check_call("cpufreq-selector -%s %s"
% (switch, value), shell=True)
except CalledProcessError as exception:
logging.exception("Note: command failed: %s" % exception.cmd)
skip = False
else:
skip = False
return self.setParameter(setFile, readFile, value, skip)
def setFrequency(self, frequency):
logging.debug("Setting Frequency to %s" % frequency)
return self.setParameterWithSelector("f", "scaling_setspeed",
"scaling_cur_freq", frequency)
def setGovernor(self, governor):
logging.debug("Setting Governor to %s" % governor)
return self.setParameterWithSelector("g", "scaling_governor",
"scaling_governor", governor)
def getParameter(self, parameter):
value = None
logging.debug("Getting %s" % parameter)
parameterFilePath = os.path.join(self.cpufreqDirectory, parameter)
try:
parameterFile = open(parameterFilePath)
line = parameterFile.readline()
if not line:
logging.error("Error: failed to get %s for %s"
% (parameter, self.cpufreqDirectory))
return None
value = line.strip()
return value
except IOError as exception:
logging.exception("Error: could not open %s" % parameterFilePath)
logging.exception(exception)
return None
def getParameterList(self, parameter):
logging.debug("Getting parameter list")
values = list()
for cpufreqDirectory in self.cpufreqDirectories:
path = os.path.join(cpufreqDirectory, parameter)
parameterFile = open(path)
line = parameterFile.readline()
if not line:
logging.error("Error: failed to get %s for %s"
% (parameter, cpufreqDirectory))
return None
values.append(line.strip())
logging.debug("Found parameters:")
for line in values:
logging.debug(" %s" % line)
return values
def runLoadTest(self):
logging.info("Running CPU load test...")
try:
output = check_output("taskset -pc 0 %s" % os.getpid(), shell=True)
for line in output.decode().splitlines():
logging.info(line)
except CalledProcessError as exception:
logging.exception("Could not set task affinity")
logging.exception(exception)
return None
runTime = None
tries = 0
while tries < self.retryLimit:
sys.stdout.flush()
(start_utime, start_stime, start_cutime,
start_cstime, start_elapsed_time) = os.times()
self.pi()
(stop_utime, stop_stime, stop_cutime,
stop_cstime, stop_elapsed_time) = os.times()
if not runTime:
runTime = stop_elapsed_time - start_elapsed_time
else:
thisTime = stop_elapsed_time - start_elapsed_time
if ((abs(thisTime - runTime) / runTime) * 100
< self.retryTolerance):
return runTime
else:
runTime = thisTime
tries += 1
logging.error("Could not repeat load test times within %.1f%%"
% self.retryTolerance)
return None
def pi(self):
decimal.getcontext().prec = 500
s = decimal.Decimal(1)
h = decimal.Decimal(3).sqrt() / 2
n = 6
for i in range(170):
s2 = ((1 - h) ** 2 + s ** 2 / 4)
s = s2.sqrt()
h = (1 - s2 / 4).sqrt()
n = 2 * n
return True
def verifyMinimumFrequency(self, waitTime=5):
logging.debug("Verifying minimum frequency")
logging.info("Waiting %d seconds..." % waitTime)
time.sleep(waitTime)
logging.info("Done.")
minimumFrequency = self.getParameter("scaling_min_freq")
currentFrequency = self.getParameter("scaling_cur_freq")
if (not minimumFrequency
or not currentFrequency
or (minimumFrequency != currentFrequency)):
return False
# otherwise
return True
def getSystemCapabilities(self):
logging.info("System Capabilites:")
logging.info("-------------------------------------------------")
# Do the CPUs support scaling?
if not self.getCPUFreqDirectories():
return False
if len(self.cpufreqDirectories) > 1:
logging.info("System has %u cpus" % len(self.cpufreqDirectories))
# Ensure all CPUs support the same frequencies
freqFileName = "scaling_available_frequencies"
self.frequencies = self.checkParameters(freqFileName)
if not self.frequencies:
return False
logging.info("Supported CPU Frequencies: ")
for freq in self.frequencies:
f = int(freq) / 1000
logging.info(" %u MHz" % f)
# Check governors to verify all CPUs support the same control methods
governorFileName = "scaling_available_governors"
self.governors = self.checkParameters(governorFileName)
if not self.governors:
return False
logging.info("Supported Governors: ")
for governor in self.governors:
logging.info(" %s" % governor)
self.originalGovernors = self.getParameterList("scaling_governor")
if self.originalGovernors:
logging.info("Current governors:")
i = 0
for g in self.originalGovernors:
logging.info(" cpu%u: %s" % (i, g))
i += 1
else:
logging.error("Error: could not determine current governor settings")
return False
self.getCPUFlags()
return True
def getCPUFlags(self):
logging.debug("Getting CPU flags")
self.cpuFlags = None
try:
cpuinfo_file = open('/proc/cpuinfo', 'r')
cpuinfo = cpuinfo_file.read().split("\n")
cpuinfo_file.close()
for line in cpuinfo:
if line.startswith('flags'):
pre, post = line.split(':')
self.cpuFlags = post.strip().split()
break
logging.debug("Found the following CPU Flags:")
for line in self.cpuFlags:
logging.debug(" %s" % line)
except:
logging.warning("Could not read CPU flags")
def runUserSpaceTests(self):
logging.info("Userspace Governor Test:")
logging.info("-------------------------------------------------")
self.minimumFrequencyTestTime = None
self.maximumFrequencyTestTime = None
success = True
differenceSpeedUp = None
governor = "userspace"
if governor not in self.governors:
logging.warning("Note: %s governor not supported" % governor)
else:
# Set the governor to "userspace" and verify
logging.info("Setting governor to %s" % governor)
if not self.setGovernor(governor):
success = False
# Set the the CPU speed to it's lowest value
frequency = self.frequencies[-1]
logging.info("Setting CPU frequency to %u MHz" % (int(frequency) / 1000))
if not self.setFrequency(frequency):
success = False
# Verify the speed is set to the lowest value
minimumFrequency = self.getParameter("scaling_min_freq")
currentFrequency = self.getParameter("scaling_cur_freq")
if (not minimumFrequency
or not currentFrequency
or (minimumFrequency != currentFrequency)):
logging.error("Could not verify that cpu frequency is set to the minimum value of %s"
% minimumFrequency)
success = False
# Run Load Test
self.minimumFrequencyTestTime = self.runLoadTest()
if not self.minimumFrequencyTestTime:
logging.error("Could not retrieve the minimum frequency test's execution time.")
success = False
else:
logging.info("Minimum frequency load test time: %.2f"
% self.minimumFrequencyTestTime)
# Set the CPU speed to it's highest value as above.
frequency = self.frequencies[0]
logging.info("Setting CPU frequency to %u MHz" % (int(frequency) / 1000))
if not self.setFrequency(frequency):
success = False
maximumFrequency = self.getParameter("scaling_max_freq")
currentFrequency = self.getParameter("scaling_cur_freq")
if (not maximumFrequency
or not currentFrequency
or (maximumFrequency != currentFrequency)):
logging.error("Could not verify that cpu frequency is set to the maximum value of %s"
% maximumFrequency)
success = False
# Repeat workload test
self.maximumFrequencyTestTime = self.runLoadTest()
if not self.maximumFrequencyTestTime:
logging.error("Could not retrieve the maximum frequency test's execution time.")
success = False
else:
logging.info("Maximum frequency load test time: %.2f"
% self.maximumFrequencyTestTime)
# Verify MHz increase is comparable to time % decrease
predictedSpeedup = (float(maximumFrequency)
/ float(minimumFrequency))
# If "ida" turbo thing, increase the expectation by 8%
if self.cpuFlags and self.idaFlag in self.cpuFlags:
logging.info("Found %s flag, increasing expected speedup by %.1f%%"
% (self.idaFlag, self.idaSpeedupFactor))
predictedSpeedup = \
(predictedSpeedup
* (1.0 / (1.0 - (self.idaSpeedupFactor / 100.0))))
if self.minimumFrequencyTestTime and self.maximumFrequencyTestTime:
measuredSpeedup = (self.minimumFrequencyTestTime
/ self.maximumFrequencyTestTime)
logging.info("CPU Frequency Speed Up: %.2f" % predictedSpeedup)
logging.info("Measured Speed Up: %.2f" % measuredSpeedup)
differenceSpeedUp = (((measuredSpeedup - predictedSpeedup) / predictedSpeedup) * 100)
logging.info("Percentage Difference %.1f%%" % differenceSpeedUp)
if differenceSpeedUp > self.speedUpTolerance:
logging.error("Measured speedup vs expected speedup is %.1f%% and is not within %.1f%% margin."
% (differenceSpeedUp, self.speedUpTolerance))
success = False
elif differenceSpeedUp < 0:
logging.info("""
Measured speed up %.2f exceeded expected speedup %.2f
""" % (measuredSpeedup, predictedSpeedup))
else:
logging.error("Not enough timing data to calculate speed differences.")
return success
def runOnDemandTests(self):
logging.info("On Demand Governor Test:")
logging.info("-------------------------------------------------")
differenceOnDemandVsMaximum = None
onDemandTestTime = None
governor = "ondemand"
success = True
if governor not in self.governors:
logging.warning("%s governor not supported" % governor)
else:
# Set the governor to "ondemand"
logging.info("Setting governor to %s" % governor)
if not self.setGovernor(governor):
success = False
# Wait a fixed period of time, then verify current speed
# is the slowest in as before
if not self.verifyMinimumFrequency():
logging.error("Could not verify that cpu frequency has settled to the minimum value")
success = False
# Repeat workload test
onDemandTestTime = self.runLoadTest()
if not onDemandTestTime:
logging.warning("No On Demand load test time available.")
success = False
else:
logging.info("On Demand load test time: %.2f" % onDemandTestTime)
if onDemandTestTime and self.maximumFrequencyTestTime:
# Compare the timing to the max results from earlier,
# again time should be within self.speedUpTolerance
differenceOnDemandVsMaximum = \
(abs(onDemandTestTime - self.maximumFrequencyTestTime)
/ self.maximumFrequencyTestTime) * 100
logging.info("Percentage Difference vs. maximum frequency: %.1f%%"
% differenceOnDemandVsMaximum)
if differenceOnDemandVsMaximum > self.speedUpTolerance:
logging.error("On demand performance vs maximum of %.1f%% is not within %.1f%% margin"
% (differenceOnDemandVsMaximum,
self.speedUpTolerance))
success = False
else:
logging.error("Not enough timing data to calculate speed differences.")
# Verify the current speed has returned to the lowest speed again
if not self.verifyMinimumFrequency():
logging.error("Could not verify that cpu frequency has settled to the minimum value")
success = False
return success
def runPerformanceTests(self):
logging.info("Performance Governor Test:")
logging.info("-------------------------------------------------")
differencePerformanceVsMaximum = None
governor = "performance"
success = True
if governor not in self.governors:
logging.warning("%s governor not supported" % governor)
else:
# Set the governor to "performance"
logging.info("Setting governor to %s" % governor)
if not self.setGovernor(governor):
success = False
# Verify the current speed is the same as scaling_max_freq
maximumFrequency = self.getParameter("scaling_max_freq")
currentFrequency = self.getParameter("scaling_cur_freq")
if (not maximumFrequency
or not currentFrequency
or (maximumFrequency != currentFrequency)):
logging.error("Current cpu frequency of %s is not set to the maximum value of %s"
% (currentFrequency, maximumFrequency))
success = False
# Repeat work load test
performanceTestTime = self.runLoadTest()
if not performanceTestTime:
logging.error("No Performance load test time available.")
success = False
else:
logging.info("Performance load test time: %.2f" % performanceTestTime)
if performanceTestTime and self.maximumFrequencyTestTime:
# Compare the timing to the max results
differencePerformanceVsMaximum = \
(abs(performanceTestTime - self.maximumFrequencyTestTime)
/ self.maximumFrequencyTestTime) * 100
logging.info("Percentage Difference vs. maximum frequency: %.1f%%"
% differencePerformanceVsMaximum)
if differencePerformanceVsMaximum > self.speedUpTolerance:
logging.error("Performance setting vs maximum of %.1f%% is not within %.1f%% margin"
% (differencePerformanceVsMaximum,
self.speedUpTolerance))
success = False
else:
logging.error("Not enough timing data to calculate speed differences.")
return success
def runConservativeTests(self):
logging.info("Conservative Governor Test:")
logging.info("-------------------------------------------------")
differenceConservativeVsMinimum = None
governor = "conservative"
success = True
if governor not in self.governors:
logging.warning("%s governor not supported" % governor)
else:
# Set the governor to "conservative"
logging.info("Setting governor to %s" % governor)
if not self.setGovernor(governor):
success = False
# Set the frequency step to 20,
# so that it jumps to minimum frequency
path = os.path.join("conservative", "freq_step")
if not self.setParameter(path, path, 20, automatch=True):
success = False
# Wait a fixed period of time,
# then verify current speed is the slowest in as before
if not self.verifyMinimumFrequency(10):
logging.error("Could not verify that cpu frequency has settled to the minimum value")
success = False
# Set the frequency step to 0,
# so that it doesn't gradually increase
if not self.setParameter(path, path, 0, automatch=True):
success = False
# Repeat work load test
conservativeTestTime = self.runLoadTest()
if not conservativeTestTime:
logging.error("No Conservative load test time available.")
success = False
else:
logging.info("Conservative load test time: %.2f"
% conservativeTestTime)
if conservativeTestTime and self.minimumFrequencyTestTime:
# Compare the timing to the max results
differenceConservativeVsMinimum = \
(abs(conservativeTestTime - self.minimumFrequencyTestTime)
/ self.minimumFrequencyTestTime) * 100
logging.info("Percentage Difference vs. minimum frequency: %.1f%%"
% differenceConservativeVsMinimum)
if differenceConservativeVsMinimum > self.speedUpTolerance:
logging.error("Performance setting vs minimum of %.1f%% is not within %.1f%% margin"
% (differenceConservativeVsMinimum,
self.speedUpTolerance))
success = False
else:
logging.error("Not enough timing data to calculate speed differences.")
return success
def restoreGovernors(self):
logging.info("Restoring original governor to %s" % (self.originalGovernors[0]))
self.setGovernor(self.originalGovernors[0])
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-q", "--quiet", action="store_true",
help="Suppress output.")
parser.add_argument("-c", "--capabilities", action="store_true",
help="Only output CPU capabilities.")
parser.add_argument("-d", "--debug", action="store_true",
help="Turn on debug level output for extra info during test run.")
args = parser.parse_args()
# Set up the logging system (unless we don't want ANY logging)
if not args.quiet or args.debug:
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
format = '%(asctime)s %(levelname)-8s %(message)s'
date_format = '%Y-%m-%d %H:%M:%S'
# If we DO want console output
if not args.quiet:
console_handler = logging.StreamHandler() #logging.StreamHandler()
console_handler.setFormatter(logging.Formatter(format,date_format))
console_handler.setLevel(logging.INFO)
logger.addHandler(console_handler)
# If we ALSO want to create a file for future reference
if args.debug:
console_handler.setLevel(logging.DEBUG)
test = CPUScalingTest()
if not os.path.exists(test.cpufreqDirectory):
logging.info("CPU Frequency Scaling not supported")
return 0
if not test.getSystemCapabilities():
logging.error("Failed to get system capabilities")
return 1
returnValues = []
if not args.capabilities:
logging.info("Beginning Frequency Governors Testing")
returnValues.append(test.runUserSpaceTests())
returnValues.append(test.runOnDemandTests())
returnValues.append(test.runPerformanceTests())
returnValues.append(test.runConservativeTests())
test.restoreGovernors()
return 1 if False in returnValues else 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/resolution_test 0000775 0001750 0001750 00000002457 12646152433 024044 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import sys
from argparse import ArgumentParser
from gi.repository import Gdk
def check_resolution():
screen = Gdk.Screen.get_default()
n = screen.get_n_monitors()
for i in range(n):
geom = screen.get_monitor_geometry(i)
print('Monitor %d:' % (i + 1))
print(' %d x %d' % (geom.width, geom.height))
def compare_resolution(min_h, min_v):
# Evaluate just the primary display
screen = Gdk.Screen.get_default()
geom = screen.get_monitor_geometry(screen.get_primary_monitor())
print("Minimum acceptable display resolution: %d x %d" % (min_h, min_v))
print("Detected display resolution: %d x %d" % (geom.width, geom.height))
return geom.width >= min_h and geom.height >= min_v
def main():
parser = ArgumentParser()
parser.add_argument("--horizontal",
type=int,
default=0,
help="Minimum acceptable horizontal resolution.")
parser.add_argument("--vertical",
type=int,
default=0,
help="Minimum acceptable vertical resolution.")
args = parser.parse_args()
if (args.horizontal > 0) and (args.vertical > 0):
return not compare_resolution(args.horizontal, args.vertical)
else:
check_resolution()
return 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/ansi_parser 0000775 0001750 0001750 00000010772 12646152433 023107 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
import sys
from optparse import OptionParser
def parse_buffer(input):
output = [""]
row = -1
col = 0
escape = ""
saved = [0, 0]
for ch in input:
if ord(ch) == 27 or len(escape) > 0:
# On ESC
if chr(27) in [escape, ch]:
escape = ""
if ch == "c":
output = [""]
row = -1
col = 0
saved = [0, 0]
elif ch == "D":
row += 1
if row == 0:
row = -1
output.append("")
elif ch == "M":
row -= 1
if row < -len(output):
output = [""] + output
elif ch == "7":
saved = [row + len(output), col]
elif ch == "8":
[row, col] = saved
row -= len(output)
elif ord(ch) in [27, 91]:
escape = ch
continue
# Just after hitting the extended ESC marker
elif escape == "[":
escape = ""
if ch in "0123456789;":
escape += ch
continue
elif ch in "Hf":
opts = escape.split(";") + ["", ""]
row = -len(output) + max(0, int("0" + opts[0]) - 1)
col = max(0, int("0" + opts[1]) - 1)
elif ch in "s":
saved = [row + len(output), col]
elif ch in "u":
[row, col] = saved
row -= len(output)
elif ch in "K":
if escape == "1":
output[row] = " " * (col + 1) + output[row][col + 1:]
elif escape == "2":
output[row] = ""
else:
output[row] = output[row][:col]
elif ch in "J":
if len(escape) == 0:
output = output[:row] + [""]
else:
for i in range(row + len(output) + 1):
output[i] = ""
elif ch in "A":
row -= max(1, int("0" + escape.split(";")[0]))
if row <= len(output):
row = -len(output)
elif ch in "B":
row += max(1, int("0" + escape.split(";")[0]))
while row >= 0:
output.append("")
row -= 1
elif ch in "C":
col += max(1, int("0" + escape.split(";")[0]))
elif ch in "D":
col = max(0, col - max(1, int("0" + escape.split(";")[0])))
escape = ""
continue
# Control char
if ch in "\r\n\f\t\b":
if ch == "\r":
col = 0
if ch in "\n\f":
row += 1
if row == 0:
row = -1
output.append("")
col = 0
if ch == "\t":
col = (col + 8) & ~7
if ch == "\b":
col = max(0, col - 1)
continue
# Keep to ascii
if ord(ch) not in range(32, 127):
ch = "?"
if len(output[row]) < col:
output[row] += " " * (col - len(output[row]))
output[row] = output[row][:col] + ch + output[row][col + 1:]
col += 1
return "\n".join(output)
def parse_file(file):
output = file.read()
return parse_buffer(output)
def parse_filename(filename):
file = open(filename)
try:
output = parse_file(file)
finally:
file.close()
return output
def main(args):
usage = "Usage: %prog [OPTIONS] [FILE...]"
parser = OptionParser(usage=usage)
parser.add_option("-o", "--output",
metavar="FILE",
help="File where to output the result.")
(options, args) = parser.parse_args(args)
# Write to stdout
if not options.output or options.output == "-":
output = sys.stdout
# Or from given option
else:
output = open(options.output, "w")
# Read from sdin
if not args or (len(args) == 1 and args[0] == "-"):
output.write(parse_file(sys.stdin))
# Or from filenames given as arguments
else:
for arg in args:
output.write(parse_filename(arg))
if options.output and options.output != "-":
output.close()
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/network 0000775 0001750 0001750 00000054667 12646152433 022305 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
"""
Copyright (C) 2012-2015 Canonical Ltd.
Authors
Jeff Marcom
Daniel Manrique
Jeff Lane
This program 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
from argparse import (
ArgumentParser,
RawTextHelpFormatter
)
import fcntl
import logging
import os
import re
import shlex
import socket
import struct
import subprocess
import tempfile
from subprocess import (
CalledProcessError,
check_call,
check_output,
STDOUT
)
import sys
import time
class IPerfPerformanceTest(object):
"""Measures performance of interface using iperf client
and target. Calculated speed is measured against theorectical
throughput of selected interface"""
def __init__(
self,
interface,
target,
fail_threshold,
cpu_load_fail_threshold,
iperf3,
protocol="tcp",
data_size="1"):
self.iface = Interface(interface)
self.target = target
self.protocol = protocol
self.fail_threshold = fail_threshold
self.cpu_load_fail_threshold = cpu_load_fail_threshold
self.iperf3 = iperf3
self.data_size = data_size
def run(self):
# if max_speed is 0, assume it's wifi and move on
if self.iface.max_speed == 0:
logging.warning("No max speed detected, assuming Wireless device "
"and continuing with test.")
# Otherwise, no sense in running if we're not running at full speed.
elif self.iface.max_speed > self.iface.link_speed:
logging.error("Detected link speed (%s) is lower than "
"detected max speed (%s)" %
(self.iface.link_speed, self.iface.max_speed))
logging.error("Check your device configuration and try again")
return 1
# Because we can vary the data size, we need to vary the timeout as
# well. It takes an estimated 15 minutes to send 1GB over 10Mb/s.
# 802.11b is 11 Mb/s. So we'll assume 1.2x15 minutes or 18 minutes
# or 1080 seconds per Gigabit. This will allow for a long period of
# time without timeout to catch devices that slow down, and also not
# prematurely end iperf on low-bandwidth devices.
self.timeout = 1080*int(self.data_size)
if (self.iperf3):
cmd = "timeout {} iperf3 -c {} -n {}G -i 1 -f m -V".format(
self.timeout, self.target, self.data_size)
else:
cmd = "timeout {} iperf -c {} -n {}G -i 1 -f m".format(
self.timeout, self.target, self.data_size)
logging.debug(cmd)
logging.info("Starting iperf against {}, this could take a while...".
format(self.target))
try:
iperf_return = check_output(
shlex.split(cmd), universal_newlines=True)
except CalledProcessError as iperf_exception:
if iperf_exception.returncode != 124:
# timeout command will return 124 if iperf timed out, so any
# other return value means something did fail
logging.error("Failed executing iperf: %s",
iperf_exception.output)
return iperf_exception.returncode
else:
# this is normal so we "except" this exception and we
# "pass through" whatever output iperf did manage to produce.
# When confronted with SIGTERM iperf should stop and output
# a partial (but usable) result.
logging.info("iperf timed out - this should be OK")
iperf_return = iperf_exception.output
logging.debug(iperf_return)
# "CPU Utilization" line present only in iperf3 output
cpu = re.findall(r"CPU Utilization.*local/sender\s([\w\.]+)",
iperf_return)
# iperf3 provides "sender" and "receiver" summaries; remove them
iperf_return = re.sub(r".*(sender|receiver)", "", iperf_return)
speeds = list(map(float, re.findall(r"([\w\.]+)\sMbits/sec",
iperf_return)))
invalid_speed = False
if speeds:
throughput = sum(speeds)/len(speeds)
try:
percent = throughput / int(self.iface.max_speed) * 100
except (ZeroDivisionError, TypeError):
# Catches a condition where the interface functions fine but
# ethtool fails to properly report max speed. In this case
# it's up to the reviewer to pass or fail.
percent = 0
invalid_speed = True
logging.info("Min Transfer speed: {} Mb/s".format(min(speeds)))
logging.info("Max Transfer speed: {} Mb/s".format(max(speeds)))
logging.info("Avg Transfer speed: {} Mb/s".format(throughput))
if invalid_speed:
# If we have no link_speed (e.g. wireless interfaces don't
# report this), then we shouldn't penalize them because
# the transfer may have been reasonable. So in this case,
# we'll exit with a pass-warning.
logging.info("Unable to obtain maximum speed.")
logging.info("Considering the test as passed.")
return 0
# Below is guaranteed to not throw an exception because we'll
# have exited above if it did.
logging.info("{:03.2f}% of theoretical max {} Mb/s".
format(percent, int(self.iface.max_speed)))
if cpu:
logging.info("")
logging.info("CPU utilization: {}%".format(cpu[0]))
cpu_load = float(cpu[0])
else:
cpu_load = 0.0
if percent < self.fail_threshold or \
cpu_load > self.cpu_load_fail_threshold:
logging.warn("Poor network performance detected against {}".
format(self.target))
if percent < self.fail_threshold:
logging.warn(" Transfer speed: {} Mb/s".
format(throughput))
logging.warn(" {:03.2f}% of theoretical max {} Mb/s\n".
format(percent, int(self.iface.max_speed)))
if cpu_load > self.cpu_load_fail_threshold:
logging.warn(" CPU load: {}%".format(cpu_load))
logging.warn(" CPU load is above {}% maximum\n".
format(self.cpu_load_fail_threshold))
return 30
logging.debug("Passed benchmark against {}".format(self.target))
else:
logging.error("Failed iperf benchmark against {}".
format(self.target))
return 1
class StressPerformanceTest:
def __init__(self, interface, target, iperf3):
self.interface = interface
self.target = target
self.iperf3 = iperf3
def run(self):
if self.iperf3:
iperf_cmd = 'timeout 320 iperf3 -c {} -t 300'.format(self.target)
else:
iperf_cmd = 'timeout 320 iperf -c {} -t 300'.format(self.target)
print("Running iperf...")
iperf = subprocess.Popen(shlex.split(iperf_cmd))
ping_cmd = 'ping -I {} {}'.format(self.interface, self.target)
ping = subprocess.Popen(shlex.split(ping_cmd), stdout=subprocess.PIPE)
iperf.communicate()
ping.terminate()
(out, err) = ping.communicate()
if iperf.returncode != 0:
return iperf.returncode
print("Running ping test...")
result = 0
time_re = re.compile('(?<=time=)[0-9]*')
for line in out.decode().split('\n'):
time = time_re.search(line)
if time and int(time.group()) > 2000:
print(line)
print("ICMP packet was delayed by > 2000 ms.")
result = 1
if 'unreachable' in line.lower():
print(line)
result = 1
return result
class Interface(socket.socket):
"""
Simple class that provides network interface information.
"""
def __init__(self, interface):
super(Interface, self).__init__(
socket.AF_INET, socket.IPPROTO_ICMP)
self.interface = interface
self.dev_path = os.path.join("/sys/class/net", self.interface)
def _read_data(self, type):
try:
return open(os.path.join(self.dev_path, type)).read().strip()
except OSError:
logging.info("%s: Attribute not found", type)
@property
def ipaddress(self):
freq = struct.pack('256s', self.interface[:15].encode())
try:
nic_data = fcntl.ioctl(self.fileno(), 0x8915, freq)
except IOError:
logging.error("No IP address for %s", self.interface)
return 1
return socket.inet_ntoa(nic_data[20:24])
@property
def netmask(self):
freq = struct.pack('256s', self.interface.encode())
try:
mask_data = fcntl.ioctl(self.fileno(), 0x891b, freq)
except IOError:
logging.error("No netmask for %s", self.interface)
return 1
return socket.inet_ntoa(mask_data[20:24])
@property
def link_speed(self):
return int(self._read_data("speed"))
@property
def max_speed(self):
# Parse ethtool data for max speed since /sys/class/net/DEV/speed only
# reports link speed.
# Search for things that look like 100baseSX,
# 40000baseNX, 10000baseT
try:
ethinfo = check_output(['ethtool', self.interface],
universal_newlines=True,
stderr=STDOUT).split(' ')
except FileNotFoundError:
logging.warning('ethtool not found! Unable to get max speed')
ethinfo = None
except CalledProcessError as e:
logging.error('ethtool returned an error!')
logging.error(e.output)
ethinfo = None
finally:
expression = '(\\d+)(base)([A-Z]+)'
regex = re.compile(expression)
speeds = [0]
if ethinfo:
for i in ethinfo:
hit = regex.search(i)
if hit:
speeds.append(int(hit.group(1)))
return max(speeds)
@property
def macaddress(self):
return self._read_data("address")
@property
def duplex_mode(self):
return self._read_data("duplex")
@property
def status(self):
return self._read_data("operstate")
@property
def device_name(self):
return self._read_data("device/label")
def get_test_parameters(args, environ):
# Decide the actual values for test parameters, which can come
# from one of two possible sources: command-line
# arguments, or environment variables.
# - If command-line args were given, they take precedence
# - Next come environment variables, if set.
params = {"test_target_iperf": None}
# See if we have environment variables
for key in params.keys():
params[key] = os.environ.get(key.upper(), "")
# Finally, see if we have the command-line arguments that are the ultimate
# override.
if args.target:
params["test_target_iperf"] = args.target
return params
def can_ping(the_interface, test_target):
working_interface = False
num_loops = 0
while (not working_interface) and (num_loops < 48):
working_interface = True
try:
with open(os.devnull, 'wb') as DEVNULL:
check_call(["ping", "-I", the_interface,
"-c", "1", test_target],
stdout=DEVNULL, stderr=DEVNULL)
except CalledProcessError as excp:
working_interface = False
if num_loops == 0:
logging.warning("Ping failure on {} ({})".
format(the_interface, excp))
if not working_interface:
time.sleep(5)
num_loops += 1
return working_interface
def run_test(args, test_target):
# Ensure that interface is fully up by waiting until it can
# ping the test server
if not can_ping(args.interface, test_target):
logging.error("Can't ping test server {} on {}".format(test_target,
args.interface))
return 1
# Execute requested networking test
if args.test_type.lower() == "iperf":
error_number = 0
iperf_benchmark = IPerfPerformanceTest(args.interface, test_target,
args.fail_threshold,
args.cpu_load_fail_threshold,
args.iperf3)
if args.datasize:
iperf_benchmark.data_size = args.datasize
run_num = 0
while not error_number and run_num < args.num_runs:
error_number = iperf_benchmark.run()
run_num += 1
logging.info(" Finished run number %s ".center(60, "-"), run_num)
elif args.test_type.lower() == "stress":
stress_benchmark = StressPerformanceTest(args.interface,
test_target, args.iperf3)
error_number = stress_benchmark.run()
else:
logging.error("Unknown test type {}".format(args.test_type))
return 10
return error_number
def interface_test(args):
if not ("test_type" in vars(args)):
return
# Get the actual test data from one of two possible sources
test_parameters = get_test_parameters(args, os.environ)
if (args.test_type.lower() == "iperf" or
args.test_type.lower() == "stress"):
test_targets = test_parameters["test_target_iperf"]
# Validate that we got reasonable values
if not test_targets or "example.com" in test_targets:
# Default values found in config file
logging.error("Target server has not been supplied.")
logging.info("Configuration settings can be configured 3 different ways:")
logging.info("1- If calling the script directly, pass the --target option")
logging.info("2- Define the TEST_TARGET_IPERF environment variable")
logging.info("3- (If running the test via checkbox/plainbox, define the ")
logging.info("target in /etc/xdg/canonical-certification.conf)")
logging.info("Please run this script with -h to see more details on how to configure")
sys.exit(1)
# Testing begins here!
#
# Make sure that the interface is indeed connected
try:
check_call(["ip", "link", "set", "dev", args.interface, "up"])
except CalledProcessError as interface_failure:
logging.error("Failed to use %s:%s", args.interface, interface_failure)
return 1
# Back up routing table, since network down/up process
# tends to trash it....
temp = tempfile.TemporaryFile()
try:
check_call(["ip", "route", "save", "table", "all"], stdout=temp)
except CalledProcessError as route_error:
logging.warning("Unable to save routing table: %s", route_error)
error_number = 0
# Stop all other interfaces
extra_interfaces = \
[iface for iface in os.listdir("/sys/class/net")
if iface != "lo" and iface != args.interface]
for iface in extra_interfaces:
logging.debug("Shutting down interface:%s", iface)
try:
check_call(["ip", "link", "set", "dev", iface, "down"])
except CalledProcessError as interface_failure:
logging.error("Failed to shut down %s:%s",
iface, interface_failure)
error_number = 3
if error_number == 0:
test_targets_list = test_targets.split(",")
test_targets_list.reverse()
# Keep testing until a success or we run out of targets
while test_targets_list:
test_target = test_targets_list.pop().strip()
error_number = run_test(args, test_target)
if not error_number:
break
for iface in extra_interfaces:
logging.debug("Restoring interface:%s", iface)
try:
check_call(["ip", "link", "set", "dev", iface, "up"])
except CalledProcessError as interface_failure:
logging.error("Failed to restore %s:%s", iface, interface_failure)
error_number = 3
# Restore routing table to original state
temp.seek(0)
try:
# Harmless "RTNETLINK answers: File exists" messages on stderr
with open(os.devnull, 'wb') as DEVNULL:
check_call(["ip", "route", "restore"], stdin=temp,
stderr=DEVNULL)
except CalledProcessError as restore_failure:
logging.warning("Unable to restore routing table: %s", restore_failure)
temp.close()
return error_number
def interface_info(args):
info_set = ""
if "all" in vars(args):
info_set = args.all
for key, value in vars(args).items():
if value is True or info_set is True:
key = key.replace("-", "_")
try:
print(
key + ":", getattr(Interface(args.interface), key),
file=sys.stderr)
except AttributeError:
pass
def main():
intro_message = """
Network module
This script provides benchmarking and information for a specified network
interface.
Example NIC information usage:
network info -i eth0 --max-speed
For running iperf test:
network test -i eth0 -t iperf --target 192.168.0.1
NOTE: The iperf test requires an iperf server running on the same network
segment that the test machine is running on.
Configuration
=============
Configuration can be supplied in three different ways, with the following
priorities:
1- Command-line parameters (see above).
2- Environment variables (example will follow).
3- If run via checkbox/plainbox, /etc/xdg/checkbox-certification.conf
can have the below-mentioned environment variables defined in the
[environment] section. An example file is provided and can be simply
modified with the correct values.
Environment variables
=====================
The variables are:
TEST_TARGET_IPERF
example config file
===================
[environment]
TEST_TARGET_IPERF = iperf-server.example.com
**NOTE**
"""
parser = ArgumentParser(
description=intro_message, formatter_class=RawTextHelpFormatter)
subparsers = parser.add_subparsers()
# Main cli options
test_parser = subparsers.add_parser(
'test', help=("Run network performance test"))
info_parser = subparsers.add_parser(
'info', help=("Gather network info"))
# Sub test options
test_parser.add_argument(
'-i', '--interface', type=str, required=True)
test_parser.add_argument(
'-t', '--test_type', type=str,
choices=("iperf", "stress"), default="iperf",
help=("[iperf *Default*]"))
test_parser.add_argument(
'-3', '--iperf3', default=False, action="store_true")
test_parser.add_argument('--target', type=str)
test_parser.add_argument(
'--datasize', type=str,
default="1",
help=("Amount of data to send. For iperf tests this will direct "
"iperf to send DATASIZE GB of data to the target."))
test_parser.add_argument(
'--config', type=str,
default="/etc/checkbox.d/network.cfg",
help="Supply config file for target/host network parameters")
test_parser.add_argument(
'--fail-threshold', type=int,
default=40,
help=("IPERF Test ONLY. Set the failure threshold (Percent of maximum "
"theoretical bandwidth) as a number like 80. (Default is "
"%(default)s)"))
test_parser.add_argument(
'--cpu-load-fail-threshold', type=int,
default=100,
help=("(IPERF Test ONLY and meaningful ONLY with --iperf3. Set the "
"failure threshold (above which the CPU load must not rise) as "
"a number like 80. (Default is %(default)s)"))
test_parser.add_argument(
'--num_runs', type=int,
default=1,
help=("Number of times to run the test. (Default is %(default)s)"))
test_parser.add_argument(
'--debug', default=False, action="store_true",
help="Turn on verbose output")
# Sub info options
info_parser.add_argument(
'-i', '--interface', type=str, required=True)
info_parser.add_argument(
'--all', default=False, action="store_true")
info_parser.add_argument(
'--duplex-mode', default=False, action="store_true")
info_parser.add_argument(
'--link-speed', default=False, action="store_true")
info_parser.add_argument(
'--max-speed', default=False, action="store_true")
info_parser.add_argument(
'--ipaddress', default=False, action="store_true")
info_parser.add_argument(
'--netmask', default=False, action="store_true")
info_parser.add_argument(
'--device-name', default=False, action="store_true")
info_parser.add_argument(
'--macaddress', default=False, action="store_true")
info_parser.add_argument(
'--status', default=False, action="store_true",
help=("displays connection status"))
info_parser.add_argument(
'--debug', default=False, action="store_true",
help="Turn on verbose output")
test_parser.set_defaults(func=interface_test)
info_parser.set_defaults(func=interface_info)
args = parser.parse_args()
if args.cpu_load_fail_threshold != 100 and not args.iperf3:
parser.error('--cpu-load-fail-threshold can only be set with --iperf3.')
if args.debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
if 'func' not in args:
parser.print_help()
else:
return args.func(args)
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/connect_wireless 0000775 0001750 0001750 00000003626 12646152433 024147 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
# Check nmcli version
NMCLI_GTE_0_9_10=0
nmcli general 2>&1 >/dev/null
if [ $? -eq 0 ]; then
NMCLI_GTE_0_9_10=1
fi
# Any active connections?
conn=''
if [ $NMCLI_GTE_0_9_10 -eq 0 ]; then
active_connection=$(nmcli -f SSID,ACTIVE dev wifi list | grep yes)
if [ $? -eq 0 ]; then
ap=$(echo $active_connection | awk -F\' '{print $2}')
conn=$(nmcli -t -f UUID,TYPE,NAME con list | grep wireless | grep -e "$ap$" | head -n 1 | awk -F\: '{print $1}')
else
conn=$(nmcli -t -f UUID,TYPE con list | grep wireless | head -n 1 | awk -F\: '{print $1}')
fi
else
active_connection=$(nmcli -f SSID,ACTIVE dev wifi | grep yes)
if [ $? -eq 0 ]; then
ap=$(echo $active_connection | awk '{print $1}')
conn=$(nmcli -t -f UUID,TYPE,NAME con show | grep wireless | grep -e "$ap$" | head -n 1 | awk -F\: '{print $1}')
else
conn=$(nmcli -t -f UUID,TYPE con show | grep wireless | head -n 1 | awk -F\: '{print $1}')
fi
fi
#Strip trailing/leading whitespace
conn=$(echo $conn |sed 's/^[ \t]*//;s/[ \t]*$//')
# Find out if wireless is enabled
if [ $NMCLI_GTE_0_9_10 -eq 0 ]; then
nmcli nm wifi | grep -q 'enabled'
else
nmcli radio wifi | grep -q 'enabled'
fi
if [ $? -ne 0 ]
then
# Find out why
rfkill list wifi | grep 'Hard blocked' | grep -q yes
if [ $? -eq 0 ]
then
blkmessage='Your wireless may be hardware blocked. You may need
to use your wireless key/switch to re-enable it.'
echo $blkmessage
fi
fi
# Check if there's a connection already (wireless or otherwise)
nmcli dev status | grep -q '\'
if [ $? -eq 0 ]
then
# Disconnect, pause for a short time
for iface in `(nmcli -f GENERAL dev list 2>/dev/null || nmcli -f GENERAL dev show) | grep 'GENERAL.DEVICE' | awk '{print $2}'`
do
nmcli dev disconnect iface $iface
done
sleep 2
fi
nmcli con up uuid "$conn"
plainbox-provider-checkbox-0.25/bin/graphics_modes_info 0000775 0001750 0001750 00000005143 12646152433 024577 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# graphics_modes_info
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Alberto Milone
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
from __future__ import print_function
from __future__ import unicode_literals
import sys
from checkbox_support.contrib import xrandr
def print_modes_info(screen):
"""Print some information about the detected screen and its outputs"""
xrandr._check_required_version((1, 0))
print("Screen %s: minimum %s x %s, current %s x %s, maximum %s x %s" %\
(screen._screen,
screen._width_min, screen._height_min,
screen._width, screen._height,
screen._width_max, screen._height_max))
print(" %smm x %smm" % (screen._width_mm, screen._height_mm))
print("Outputs:")
for o in list(screen.outputs.keys()):
output = screen.outputs[o]
print(" %s" % o, end=' ')
if output.is_connected():
print("(%smm x %smm)" % (output.get_physical_width(),
output.get_physical_height()))
modes = output.get_available_modes()
print(" Modes:")
for m in range(len(modes)):
mode = modes[m]
refresh = mode.dotClock / (mode.hTotal * mode.vTotal)
print(" [%s] %s x %s @ %s Hz" % (m,
mode.width,
mode.height,
refresh), end=' ')
if mode.id == output._mode:
print("(current)", end=' ')
if m == output.get_preferred_mode():
print("(preferred)", end=' ')
print("")
else:
print("(not connected)")
def main():
screen = xrandr.get_current_screen()
try:
print_modes_info(screen)
except(xrandr.UnsupportedRRError):
print('Error: RandR version lower than 1.0', file=sys.stderr)
if __name__ == '__main__':
main()
plainbox-provider-checkbox-0.25/bin/keyboard_test 0000775 0001750 0001750 00000003626 12646152433 023440 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
from gettext import gettext as _
import gettext
def cli_prompt():
import termios
limit = 50
separator = ord("\n")
fileno = sys.stdin.fileno()
saved_attributes = termios.tcgetattr(fileno)
attributes = termios.tcgetattr(fileno)
attributes[3] = attributes[3] & ~(termios.ICANON)
attributes[6][termios.VMIN] = 1
attributes[6][termios.VTIME] = 0
termios.tcsetattr(fileno, termios.TCSANOW, attributes)
sys.stdout.write(_("Enter text:\n"))
input = ""
try:
while len(input) < limit:
ch = str(sys.stdin.read(1))
if ord(ch) == separator:
break
input += ch
finally:
termios.tcsetattr(fileno, termios.TCSANOW, saved_attributes)
def gtk_prompt():
from gi.repository import Gtk, Gdk
# create a new window
window = Gtk.Window()
window.set_type_hint(Gdk.WindowType.TOPLEVEL)
window.set_size_request(200, 100)
window.set_resizable(False)
window.set_title(_("Type Text"))
window.connect("delete_event", lambda w, e: Gtk.main_quit())
vbox = Gtk.VBox()
vbox.set_homogeneous(False)
vbox.set_spacing(0)
window.add(vbox)
vbox.show()
entry = Gtk.Entry()
entry.set_max_length(50)
vbox.pack_start(entry, True, True, 0)
entry.show()
hbox = Gtk.HBox()
hbox.set_homogeneous(False)
hbox.set_spacing(0)
vbox.add(hbox)
hbox.show()
button = Gtk.Button(stock=Gtk.STOCK_CLOSE)
button.connect("clicked", lambda w: Gtk.main_quit())
vbox.pack_start(button, False, False, 0)
button.set_can_default(True)
button.grab_default()
button.show()
window.show()
Gtk.main()
def main(args):
gettext.textdomain("checkbox")
if "DISPLAY" in os.environ:
gtk_prompt()
else:
cli_prompt()
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/rendercheck_test 0000775 0001750 0001750 00000022024 12646152433 024106 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# rendercheck_test
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Alberto Milone
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
from subprocess import Popen, PIPE
from argparse import ArgumentParser
import logging
import os
import re
import tempfile
import errno
class RenderCheck(object):
"""A simple class to run the rendercheck suites"""
def __init__(self, temp_dir=None):
self._temp_dir = temp_dir
def _print_test_info(self, suites='all', iteration=1, show_errors=False):
'''Print the output of the test suite'''
main_command = 'rendercheck'
passed = 0
total = 0
if self._temp_dir:
# Use the specified path
temp_file = tempfile.NamedTemporaryFile(dir=self._temp_dir,
delete=False)
else:
# Use /tmp
temp_file = tempfile.NamedTemporaryFile(delete=False)
if suites == all:
full_command = [main_command, '-f', 'a8r8g8b8']
else:
full_command = [main_command, '-t', suites, '-f', 'a8r8g8b8']
try:
# Let's dump the output into file as it can be very large
# and we don't want to store it in memory
process = Popen(full_command, stdout=temp_file,
universal_newlines=True)
except OSError as exc:
if exc.errno == errno.ENOENT:
logging.error('Error: please make sure that rendercheck '
'is installed.')
exit(1)
else:
raise
exit_code = process.wait()
temp_file.close()
# Read values from the file
errors = re.compile('.*test error.*')
results = re.compile('(.+) tests passed of (.+) total.*')
first_error = True
with open(temp_file.name) as temp_handle:
for line in temp_handle:
match_output = results.match(line)
match_errors = errors.match(line)
if match_output:
passed = int(match_output.group(1).strip())
total = int(match_output.group(2).strip())
logging.info('Results:')
logging.info(' %d tests passed out of %d.'
% (passed, total))
if show_errors and match_errors:
error = match_errors.group(0).strip()
if first_error:
logging.debug('Rendercheck %s suite errors '
'from iteration %d:'
% (suites, iteration))
first_error = False
logging.debug(' %s' % error)
# Remove the file
os.unlink(temp_file.name)
return (exit_code, passed, total)
def run_test(self, suites=[], iterations=1, show_errors=False):
exit_status = 0
for suite in suites:
for it in range(iterations):
logging.info('Iteration %d of Rendercheck %s suite...'
% (it + 1, suite))
(status, passed, total) = \
self._print_test_info(suites=suite,
iteration=it + 1,
show_errors=show_errors)
if status != 0:
# Make sure to catch a non-zero exit status
logging.info('Iteration %d of Rendercheck %s suite '
'exited with status %d.'
% (it + 1, suite, status))
exit_status = status
it += 1
# exit with 1 if passed < total
if passed < total:
if exit_status == 0:
exit_status = 1
return exit_status
def get_suites_list(self):
'''Return a list of the available test suites'''
try:
process = Popen(['rendercheck', '--help'], stdout=PIPE,
stderr=PIPE, universal_newlines=True)
except OSError as exc:
if exc.errno == errno.ENOENT:
logging.error('Error: please make sure that rendercheck '
'is installed.')
exit(1)
else:
raise
proc = process.communicate()[1].split('\n')
found = False
tests_pattern = re.compile('.*Available tests: *(.+).*')
temp_line = ''
tests = []
for line in proc:
if found:
temp_line += line
match = tests_pattern.match(line)
if match:
first_line = match.group(1).strip().lower()
found = True
temp_line += first_line
for elem in temp_line.split(','):
test = elem.strip()
if elem:
tests.append(test)
return tests
def main():
usage = 'Usage: %prog [OPTIONS]'
all_tests = RenderCheck().get_suites_list()
parser = ArgumentParser(usage)
parser.add_argument('-i', '--iterations',
type=int,
default=1,
help='The number of times to run the test. \
Default is 1')
parser.add_argument('-t', '--test',
default='all',
help='The name of the test suit to run. \
Available tests: \
%s. \
Default is all' % (', '.join(all_tests)))
parser.add_argument('-b', '--blacklist',
action='append',
help='The name of a test which should not be run.')
parser.add_argument('-d', '--debug',
action='store_true',
help='Choose this to add verbose output \
for debug purposes')
parser.add_argument('-o', '--output',
default='',
help='The path to the log which will be dumped. \
Default is stdout')
parser.add_argument('-tp', '--temp',
default='',
help='The path where to store temporary files. \
Default is /tmp')
args = parser.parse_args()
# Set up logging to console
format = '%(message)s'
console_handler = logging.StreamHandler()
console_handler.setFormatter(logging.Formatter(format))
# Set up the overall logger
logger = logging.getLogger()
# This is necessary to ensure debug messages are passed through the logger
# to the handler
logger.setLevel(logging.DEBUG)
# This is what happens when -d and/or -o are passed:
# -o -> stdout (info) - log (info)
# -d -> only stdout (info and debug) - no log
# -d -o -> stdout (info) - log (info and debug)
# Write to a log
if args.output:
# Write INFO to stdout
console_handler.setLevel(logging.INFO)
logger.addHandler(console_handler)
# Specify a log file
logfile = args.output
logfile_handler = logging.FileHandler(logfile)
if args.debug:
# Write INFO and DEBUG to a log
logfile_handler.setLevel(logging.DEBUG)
else:
# Write INFO to a log
logfile_handler.setLevel(logging.INFO)
logfile_handler.setFormatter(logging.Formatter(format))
logger.addHandler(logfile_handler)
log_path = os.path.abspath(logfile)
logging.info("The log can be found at %s" % log_path)
# Write only to stdout
else:
if args.debug:
# Write INFO and DEBUG to stdout
console_handler.setLevel(logging.DEBUG)
logger.addHandler(console_handler)
else:
# Write INFO to stdout
console_handler.setLevel(logging.INFO)
logger.addHandler(console_handler)
exit_status = 0
if args.test == 'all':
tests = all_tests
else:
tests = args.test.split(',')
for test in args.blacklist:
if test in tests:
tests.remove(test)
rendercheck = RenderCheck(args.temp)
exit_status = rendercheck.run_test(tests, args.iterations,
args.debug)
exit(exit_status)
if __name__ == '__main__':
main()
plainbox-provider-checkbox-0.25/bin/manage_compiz_plugin 0000775 0001750 0001750 00000004220 12646152433 024757 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# This file is part of Checkbox.
#
# Copyright 2014-2015 Canonical Ltd.
# Written by:
# Daniel Manrique
# Sylvain Pineau
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
"""
manage_compiz_plugin
====================
This script allows enabling or disabling compiz plugins using
gsettings. Changes take effect on the fly.
"""
from gettext import gettext as _
import argparse
import gettext
import os
import sys
import subprocess
import time
PATH="org.compiz.core:/org/compiz/profiles/unity/plugins/core/"
KEY="active-plugins"
gettext.textdomain("2013.com.canonical.certification.checkbox")
gettext.bindtextdomain("2013.com.canonical.certification.checkbox",
os.getenv("CHECKBOX_PROVIDER_LOCALE_DIR", None))
plugins = eval(subprocess.check_output(["gsettings", "get", PATH, KEY]))
parser = argparse.ArgumentParser(description=_("enable/disable compiz plugins"),
epilog=_("Available plugins: {}").format(plugins))
parser.add_argument("plugin", type=str, help=_('Name of plugin to control'))
parser.add_argument("action", type=str, choices=['enable', 'disable'],
help=_("What to do with the plugin"))
args = parser.parse_args()
if args.action == 'enable':
if args.plugin in plugins:
raise SystemExit(_("Plugin {} already enabled").format(args.plugin))
plugins.append(args.plugin)
else:
if args.plugin not in plugins:
raise SystemExit(_("Plugin {} doesn't exist").format(args.plugin))
plugins.remove(args.plugin)
subprocess.call(["gsettings", "set", PATH, KEY, str(plugins)])
time.sleep(3)
plainbox-provider-checkbox-0.25/bin/gpu_test 0000775 0001750 0001750 00000016025 12646152433 022430 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# Copyright 2013 Canonical Ltd.
# Written by:
# Sylvain Pineau
#
# This program 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
"""
Script checking gpu lockups.
Several threads are started to exercise the GPU in ways that can cause gpu
lockups.
Inspired by the workload directory of the xdiagnose package.
"""
import os
import re
import subprocess
import sys
import time
from gi.repository import Gio
from math import cos, sin
from threading import Thread
class GlxThread(Thread):
"""
Start a thread running glxgears
"""
def run(self):
try:
self.process = subprocess.Popen(
["glxgears","-geometry", "400x400"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
self.process.communicate()
except (subprocess.CalledProcessError, FileNotFoundError) as er:
print("WARNING: Unable to start glxgears (%s)" % er)
def terminate(self):
if not hasattr(self, 'id'):
print("WARNING: Attempted to terminate non-existing window.")
if hasattr(self, 'process'):
self.process.terminate()
class RotateGlxThread(Thread):
"""
Start a thread performing glxgears windows rotations
"""
def __init__(self, id, offset):
Thread.__init__(self)
self.id = id
self.offset = offset
self.cancel = False
def run(self):
while(1):
for j in range(60):
x = int(200 * self.offset + 100 * sin(j * 0.2))
y = int(200 * self.offset + 100 * cos(j * 0.2))
coords = "%s,%s" % (x, y)
subprocess.call(
'wmctrl -i -r %s -e 0,%s,-1,-1' % (self.id, coords),
shell=True
)
time.sleep(0.002 * self.offset)
if self.cancel:
return
class ChangeWorkspace(Thread):
"""
Start a thread performing fast workspace switches
"""
def __init__(self, hsize, vsize, xsize, ysize):
Thread.__init__(self)
self.hsize = hsize
self.vsize = vsize
self.xsize = xsize
self.ysize = ysize
self.cancel = False
def run(self):
while(1):
for i in range(self.hsize):
for j in range(self.vsize):
subprocess.call(
'wmctrl -o %s,%s' % (self.xsize * j, self.ysize * i),
shell=True)
time.sleep(0.5)
if self.cancel:
# Switch back to workspace #1
subprocess.call('wmctrl -o 0,0', shell=True)
return
class Html5VideoThread(Thread):
"""
Start a thread performing playback of an HTML5 video in firefox
"""
@property
def html5_path(self):
if os.getenv('PLAINBOX_PROVIDER_DATA'):
return os.path.join(
os.getenv('PLAINBOX_PROVIDER_DATA'),
'websites/html5_video.html')
def run(self):
if self.html5_path and os.path.isfile(self.html5_path):
subprocess.call(
'firefox %s' % self.html5_path,
stdout=open(os.devnull, 'w'),
stderr=subprocess.STDOUT,
shell=True)
else:
print("WARNING: unable to start html5 video playback.")
print("WARNING: test results may be invalid.")
def terminate(self):
if self.html5_path and os.path.isfile(self.html5_path):
subprocess.call("pkill firefox", shell=True)
def check_gpu(log=None):
if not log:
log = subprocess.check_output(['dmesg'], universal_newlines=True)
if re.findall(r'gpu\s+hung', log, flags=re.I):
print("GPU hung Detected")
return 1
def main():
if check_gpu():
return 1
GlxWindows = []
GlxRotate = []
subprocess.call("pkill 'glxgears|firefox'", shell=True)
Html5Video = Html5VideoThread()
Html5Video.start()
source = Gio.SettingsSchemaSource.get_default()
for i in range(2):
GlxWindows.append(GlxThread())
GlxWindows[i].start()
time.sleep(5)
try:
windows = subprocess.check_output(
'wmctrl -l | grep glxgears',
shell=True)
except subprocess.CalledProcessError as er:
print("WARNING: Got an exception %s" % er)
windows = ""
for app in sorted(windows.splitlines(), reverse=True):
if not b'glxgears' in app:
continue
GlxWindows[i].id = str(
re.match(b'^(0x\w+)', app).group(0), 'utf-8')
break
if hasattr(GlxWindows[i], "id"):
rotator = RotateGlxThread(GlxWindows[i].id, i + 1)
GlxRotate.append(rotator)
rotator.start()
else:
print("WARNING: Window {} not found, not rotating it.".format(i))
hsize = vsize = 2
hsize_ori = vsize_ori = None
if source.lookup("org.compiz.core", True):
settings = Gio.Settings(
"org.compiz.core",
"/org/compiz/profiles/unity/plugins/core/"
)
hsize_ori = settings.get_int("hsize")
vsize_ori = settings.get_int("vsize")
settings.set_int("hsize", hsize)
settings.set_int("vsize", vsize)
time.sleep(5)
else:
hsize = int(subprocess.check_output(
'gconftool --get /apps/compiz-1/general/screen0/options/hsize',
shell=True))
vsize = int(subprocess.check_output(
'gconftool --get /apps/compiz-1/general/screen0/options/vsize',
shell=True))
(x_res, y_res) = re.search(
b'DG:\s+(\d+)x(\d+)',
subprocess.check_output('wmctrl -d', shell=True)).groups()
DesktopSwitch = ChangeWorkspace(
hsize, vsize, int(x_res) // hsize, int(y_res) // vsize)
DesktopSwitch.start()
time.sleep(35)
for i in range(len(GlxRotate)):
GlxRotate[i].cancel = True
for i in range(len(GlxWindows)):
GlxWindows[i].terminate()
DesktopSwitch.cancel = True
time.sleep(10)
Html5Video.terminate()
if check_gpu() or not Html5Video.html5_path:
return 1
if source.lookup("org.compiz.core", True):
settings = Gio.Settings(
"org.compiz.core",
"/org/compiz/profiles/unity/plugins/core/")
settings.set_int("hsize", hsize_ori)
settings.set_int("vsize", vsize_ori)
Gio.Settings.sync()
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/sleep_test 0000775 0001750 0001750 00000035552 12646152433 022753 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
'''
Program to automate system entering and resuming from sleep states
Copyright (C) 2010-2014 Canonical Ltd.
Author:
Jeff Lane
Daniel Manrique
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
'''
import logging
import os
import re
import sys
import syslog
from optparse import OptionParser, OptionGroup
from subprocess import call
class ListDictHandler(logging.StreamHandler):
'''
Extends logging.StreamHandler to handle list, tuple and dict objects
internally, rather than through external code, mainly used for debugging
purposes.
'''
def emit(self, record):
if isinstance(record.msg, (list, tuple,)):
for msg in record.msg:
logger = logging.getLogger(record.name)
new_record = logger.makeRecord(record.name, record.levelno,
record.pathname, record.lineno,
msg, record.args,
record.exc_info,
record.funcName)
logging.StreamHandler.emit(self, new_record)
elif isinstance(record.msg, dict):
for key, val in record.msg.items():
logger = logging.getLogger(record.name)
new_msg = '%s: %s' % (key, val)
new_record = logger.makeRecord(record.name, record.levelno,
record.pathname, record.lineno,
new_msg, record.args,
record.exc_info,
record.funcName)
logging.StreamHandler.emit(self, new_record)
else:
logging.StreamHandler.emit(self, record)
class SuspendTest():
'''
Creates an object to handle the actions necessary for suspend/resume
testing.
'''
def __init__(self):
self.wake_time = 0
self.current_time = 0
self.last_time = 0
def CanWeSleep(self, mode):
'''
Test to see if S3 state is available to us. /proc/acpi/* is old
and will be deprecated, using /sys/power to maintain usefulness for
future kernels.
'''
states_fh = open('/sys/power/state', 'rb', 0)
try:
states = states_fh.read().decode('ascii').split()
finally:
states_fh.close()
logging.debug('The following sleep states were found:')
logging.debug(states)
if mode in states:
return True
else:
return False
def GetCurrentTime(self):
time_fh = open('/sys/class/rtc/rtc0/since_epoch', 'rb', 0)
try:
time = int(time_fh.read().decode('ascii'))
finally:
time_fh.close()
return time
def SetWakeTime(self, time):
'''
Get the current epoch time from /sys/class/rtc/rtc0/since_epoch
then add time and write our new wake_alarm time to
/sys/class/rtc/rtc0/wakealarm.
The math could probably be done better but this method avoids having to
worry about whether or not we're using UTC or local time for both the
hardware and system clocks.
'''
self.last_time = self.GetCurrentTime()
logging.debug('Current epoch time: %s' % self.last_time)
wakealarm_fh = open('/sys/class/rtc/rtc0/wakealarm', 'wb', 0)
try:
wakealarm_fh.write('0\n'.encode('ascii'))
wakealarm_fh.flush()
wakealarm_fh.write('+{}\n'.format(time).encode('ascii'))
wakealarm_fh.flush()
finally:
wakealarm_fh.close()
logging.debug('Wake alarm in %s seconds' % time)
def DoSuspend(self, mode):
'''
Suspend the system and hope it wakes up.
Previously tried writing new state to /sys/power/state but that
seems to put the system into an uncrecoverable S3 state. So far,
pm-suspend seems to be the most reliable way to go.
'''
# Set up our start and finish markers
self.time_stamp = self.GetCurrentTime()
self.start_marker = 'CHECKBOX SLEEP TEST START %s' % self.time_stamp
self.end_marker = 'CHECKBOX SLEEP TEST STOP %s' % self.time_stamp
self.MarkLog(self.start_marker)
if mode == 'mem':
status = call('/usr/sbin/pm-suspend')
elif mode == 'disk':
status = call('/usr/sbin/pm-hibernate')
else:
logging.debug('Unknown sleep state passed: %s' % mode)
status == 1
if status == 0:
logging.debug('Successful suspend')
else:
logging.debug('Error while running pm-suspend')
self.MarkLog(self.end_marker)
def GetResults(self, mode, perf):
'''
This will parse /var/log/messages for our start and end markers. Then
it'll find a few key phrases that are part of the sleep and resume
process, grab their timestamps, Bob's your Uncle and return a
three-tuple consisting of: (PASS/FAIL,Sleep elapsed time, Resume
elapsed time)
'''
# figure out our elapsed time
logfile = '/var/log/syslog'
log_fh = open(logfile, 'r')
line = ''
run_complete = 'Fail'
sleep_start_time = 0.0
sleep_end_time = 0.0
resume_start_time = 0.0
resume_end_time = 0.0
while self.start_marker not in line:
line = log_fh.readline()
if self.start_marker in line:
logging.debug("Found Start Marker")
loglist = log_fh.readlines()
if perf:
for idx in range(0, len(loglist)):
if 'PM: Syncing filesystems' in loglist[idx]:
sleep_start_time = re.split('[\[\]]',
loglist[idx])[1].strip()
logging.debug('Sleep started at %s' % sleep_start_time)
if 'ACPI: Low-level resume complete' in loglist[idx]:
sleep_end_time = re.split('[\[\]]',
loglist[idx - 1])[1].strip()
logging.debug('Sleep ended at %s' % sleep_end_time)
resume_start_time = re.split('[\[\]]',
loglist[idx])[1].strip()
logging.debug('Resume started at %s' % resume_start_time)
idx += 1
if 'Restarting tasks' in loglist[idx]:
resume_end_time = re.split('[\[\]]',
loglist[idx])[1].strip()
logging.debug('Resume ended at %s' % resume_end_time)
if self.end_marker in loglist[idx]:
logging.debug('End Marker found, run appears to '
'have completed')
run_complete = 'Pass'
break
sleep_elapsed = float(sleep_end_time) - float(sleep_start_time)
resume_elapsed = float(resume_end_time) - float(resume_start_time)
logging.debug('Sleep elapsed: %.4f seconds' % sleep_elapsed)
logging.debug('Resume elapsed: %.4f seconds' % resume_elapsed)
else:
if self.end_marker in loglist:
logging.debug('End Marker found, '
'run appears to have completed')
run_complete = 'Pass'
sleep_elapsed = None
resume_elapsed = None
return (run_complete, sleep_elapsed, resume_elapsed)
def MarkLog(self, marker):
'''
Write a stamped marker to syslogd (will appear in /var/log/messages).
This is used to calculate the elapsed time for each iteration.
'''
syslog.syslog(syslog.LOG_INFO, '---' + marker + '---')
def CheckAlarm(self, mode):
'''
A better method for checking if system woke via rtc alarm IRQ. If the
system woke via IRQ, then alarm_IRQ will be 'no' and wakealarm will be
an empty file. Otherwise, alarm_IRQ should still say yes and wakealarm
should still have a number in it (the original alarm time), indicating
the system did not wake by alarm IRQ, but by some other means.
'''
rtc = {}
rtc_fh = open('/proc/driver/rtc', 'rb', 0)
alarm_fh = open('/sys/class/rtc/rtc0/wakealarm', 'rb', 0)
try:
rtc_data = rtc_fh.read().decode('ascii').splitlines()
for item in rtc_data:
rtc_entry = item.partition(':')
rtc[rtc_entry[0].strip()] = rtc_entry[2].strip()
finally:
rtc_fh.close()
try:
alarm = int(alarm_fh.read().decode('ascii'))
except ValueError:
alarm = None
finally:
alarm_fh.close()
logging.debug('Current RTC entries')
logging.debug(rtc)
logging.debug('Current wakealarm %s' % alarm)
# see if there's something in wakealarm or alarm_IRQ
# Return True indicating the alarm is still set
# Return False indicating the alarm is NOT set.
# This is currently held up by a bug in PM scripts that
# does not reset alarm_IRQ when waking from hibernate.
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/571977
if mode == 'mem':
if (alarm is not None) or (rtc['alarm_IRQ'] == 'yes'):
logging.debug('alarm is %s' % alarm)
logging.debug('rtc says alarm_IRQ: %s' % rtc['alarm_IRQ'])
return True
else:
logging.debug('alarm was cleared')
return False
else:
# This needs to be changed after we get a way around the
# hibernate bug. For now, pretend that the alarm is unset for
# hibernate tests.
logging.debug('mode is %s so we\'re skipping success check' % mode)
return False
def main():
usage = 'Usage: %prog [OPTIONS]'
parser = OptionParser(usage)
group = OptionGroup(parser, 'This will not work for hibernat testing due'
' to a kernel timestamp bug when doing an S4 '
'(hibernate/resume) sleep cycle')
group.add_option('-p', '--perf',
action='store_true',
default=False,
help='Add some output that tells you how long it '
'takes to enter a sleep state and how long it '
'takes to resume.')
parser.add_option('-i', '--iterations',
action='store',
type='int',
metavar='NUM',
default=1,
help='The number of times to run the suspend/resume '
'loop. Default is %default')
parser.add_option('-w', '--wake-in',
action='store',
type='int',
metavar='NUM',
default=60,
dest='wake_time',
help='Sets wake up time (in seconds) in the future '
'from now. Default is %default.')
parser.add_option('-s', '--sleep-state',
action='store',
default='mem',
metavar='MODE',
dest='mode',
help='Sets the sleep state to test. Passing mem will '
'set the sleep state to Suspend-To-Ram or S3. Passing '
'disk will set the sleep state to Suspend-To-Disk or S4 '
'(hibernate). Default sleep state is %default')
parser.add_option('-d', '--debug',
action='store_true',
default=False,
help='Choose this to add verbose output for debug \
purposes')
parser.add_option_group(group)
(options, args) = parser.parse_args()
options_dict = vars(options)
if not (os.geteuid() == 0):
parser.error("Must be run as root.")
return 1
# Set up logging handler
format = '%(message)s'
handler = ListDictHandler(sys.stdout)
handler.setFormatter(logging.Formatter(format))
handler.setLevel(logging.INFO)
# Set up the logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
if options.debug:
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
logging.debug('Running with these options')
logging.debug(options_dict)
suspender = SuspendTest()
run_result = {}
run_count = 0
fail_count = 0
# Chcek fo the S3 state availability
if not suspender.CanWeSleep(options.mode):
logging.error('%s sleep state not supported' % options.mode)
return 1
else:
logging.debug('%s sleep state supported, continuing test'
% options.mode)
# We run the following for the number of iterations requested
for iteration in range(0, options.iterations):
# Set new alarm time and suspend.
suspender.SetWakeTime(options.wake_time)
suspender.DoSuspend(options.mode)
run_count += 1
run_result[run_count] = suspender.GetResults(options.mode,
options.perf)
if suspender.CheckAlarm(options.mode):
logging.debug('The alarm is still set')
if options.perf:
sleep_total = 0.0
resume_total = 0.0
logging.info('=' * 20 + ' Test Results ' + '=' * 20)
logging.info(run_result)
for k in run_result.keys():
sleep_total += run_result[k][1]
resume_total += run_result[k][2]
sleep_avg = sleep_total / run_count
resume_avg = resume_total / run_count
logging.info('Average time to sleep: %.4f' % sleep_avg)
logging.info('Average time to resume: %.4f' % resume_avg)
for run in run_result.keys():
if 'Fail' in run_result[run]:
fail_count += 1
if fail_count > 0:
logging.error('%s sleep/resume test cycles failed' %
fail_count)
logging.error(run_result)
return 1
else:
logging.info('Successfully completed %s sleep iterations' %
options.iterations)
return 0
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/samba_test 0000775 0001750 0001750 00000001227 12646152433 022716 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# Confirm Samba service is running
# Requires: samba winbind
#
#Verify Samba processes are running
smbd=`pgrep smbd`
if [ -z "$smbd" ]; then
echo "FAIL: smbd is not running."
exit 1
fi
nmbd=`pgrep nmbd`
if [ -z "$nmbd" ]; then
echo "FAIL: nmbd is not running."
exit 1
fi
winbindd=`pgrep winbindd`
if [ -z "$winbindd" ]; then
echo "FAIL: winbindd is not running."
exit 1
fi
sid=`net getlocalsid | grep "S-1-5"` #req. root
if [ -z "$sid" ]; then
echo "FAIL: Default samba workgroup is not set."
exit 1
fi
users=`net usersidlist | grep "UBUNTU"`
if [ -z "$sid" ]; then
echo "FAIL: samba userId is not set."
exit 1
fi
exit 0
plainbox-provider-checkbox-0.25/bin/disk_smart 0000775 0001750 0001750 00000026524 12646152433 022743 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
"""
Script to automate disk SMART testing.
Copyright (C) 2010-2016 Canonical Ltd.
Authors
Jeff Lane
Brendan Donegan
Rod Smith
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
The purpose of this script is to simply interact with an onboard hard disk and
check for SMART capability and then do a little bit of interaction to make sure
we can at least do some limited interaction with the hard disk's SMART
functions.
We assume that SMART is available. The test will fail if this is not the case.
The block_device_resource script includes a test of SMART availability.
Checkbox tests for SMART availability as part of the disk/smart provider
definition, which uses block_device_resource as part of its requires: test.
This script runs the SMART short self test. It returns 0 if it's all good,
and 1 if it fails.
NOTE: This may not work correctly on systems where the onboard storage is
controlled by a hardware RAID controller, on external RAID systems, SAN, and
USB/eSATA/eSAS attached storage devices. Such systems should be filtered
out by the SMART availability test in block_device_resource.
Changelog:
v1.4: Fix script failure on disks with no pre-existing SMART tests
v1.3: Fix detection of SMART availability & activate SMART if available
but deactivated. Also use smartctl return value rather than string-
matching to determine if a test has failed; this should be more
robust, as output strings vary between disks.
v1.2: Handle multiple output formats for "smartctl -l"
v1.1: Put delay before first attempt to acces log, rather than after
v1.0: added debugger class and code to allow for verbose debug output if needed
v0.4: corrected some minor things
added option parsing to allow for many disks, or disks other than
"/dev/sda"
V0.3: Removed the arbitrary wait time and implemented a polling method
to shorten the test time.
Added in Pass/Fail criteria for the final outcome.
Added in documentation.
V0.2: added minor debug routine
V0.1: Fixed some minor bugs and added the SmartEnabled() function
V0: First draft
"""
import os
import sys
import time
import logging
import shlex
from subprocess import Popen, PIPE, check_call, check_output
from subprocess import CalledProcessError
from argparse import ArgumentParser
class ListHandler(logging.StreamHandler):
def emit(self, record):
if isinstance(record.msg, (list, tuple)):
for msg in record.msg:
if type(msg) is bytes:
msg = msg.decode()
logger = logging.getLogger(record.name)
new_record = logger.makeRecord(record.name, record.levelno,
record.pathname, record.lineno,
msg, record.args,
record.exc_info,
record.funcName)
logging.StreamHandler.emit(self, new_record)
else:
logging.StreamHandler.emit(self, record)
def enable_smart(disk):
"""Log data and, if necessary, enable SMART on the specified disk.
See also smart_support() in block_device_resource script.
:param disk:
disk device filename (e.g., /dev/sda)
:returns:
True if enabling smart was successful, False otherwise
"""
# Check with smartctl to record basic SMART data on the disk
command = 'smartctl -i %s' % disk
diskinfo_bytes = (Popen(command, stdout=PIPE, shell=True)
.communicate()[0])
diskinfo = (diskinfo_bytes.decode(encoding='utf-8', errors='ignore')
.splitlines())
logging.debug('SMART Info for disk %s', disk)
logging.debug(diskinfo)
if len(diskinfo) > 2 and not any("SMART support is" in s and "Enabled"
in s for s in diskinfo):
logging.debug('SMART disabled; attempting to enable it.')
command = 'smartctl -s on %s' % disk
try:
check_call(shlex.split(command))
return True
except CalledProcessError:
return False
return True
def run_smart_test(disk, type='short'):
ctl_command = 'smartctl -t %s %s' % (type, disk)
logging.debug('Beginning test with %s', ctl_command)
smart_proc = Popen(ctl_command, stderr=PIPE, stdout=PIPE,
universal_newlines=True, shell=True)
ctl_output, ctl_error = smart_proc.communicate()
logging.debug(ctl_error + ctl_output)
return smart_proc.returncode
def get_smart_entries(disk, type='selftest'):
entries = []
try:
stdout = check_output(['smartctl', '-l', type, disk],
universal_newlines=True)
returncode = 0
except CalledProcessError as err:
stdout = err.output
returncode = err.returncode
# Skip intro lines
stdout_lines = iter(stdout.splitlines())
for line in stdout_lines:
if (line.startswith('SMART') or
line.startswith('No self-tests have been logged')):
break
# Get lengths from header
try:
line = next(stdout_lines)
except StopIteration:
logging.info('No entries found in log')
if not line.startswith('Num'):
entries.append('No entries found in log yet')
return entries, returncode
columns = ['number', 'description', 'status',
'remaining', 'lifetime', 'lba']
lengths = [line.index(i) for i in line.split()]
lengths[columns.index('remaining')] += len('Remaining') - len('100%')
lengths.append(len(line))
# Get remaining lines
entries = []
for line in stdout_lines:
if line.startswith('#'):
entry = {}
for i, column in enumerate(columns):
entry[column] = line[lengths[i]:lengths[i + 1]].strip()
# Convert some columns to integers
entry['number'] = int(entry['number'][1:])
entries.append(entry)
return entries, returncode
# Returns True if an "in-progress" message is found in the smartctl
# output, False if such a message is not found. In the former case,
# the in-progress message entries are logged.
def in_progress(current_entries):
statuses = [entry for entry in current_entries
if isinstance(entry, dict)
and 'status' in entry
and (entry['status'] == 'Self-test routine in progress'
or "Self test in progress" in entry['status'])]
if statuses:
for entry in statuses:
logging.debug('%s %s %s %s' % (entry['number'],
entry['description'],
entry['status'],
entry['remaining']))
return True
else:
return False
# Wait for SMART test to complete; return status and return code.
# Note that different disks return different types of values.
# Some return no status reports while a test is ongoing; others
# show a status line at the START of the list of tests, and
# others show a status line at the END of the list of tests
# (and then move it to the top once the tests are done).
def poll_for_status(args, disk, previous_entries):
# Priming read... this is here in case our test is finished or fails
# immediate after it beginsAccording to.
logging.debug('Polling selftest.log for status')
keep_going = True
while keep_going:
# Poll every sleep seconds until test is complete$
time.sleep(args.sleep)
current_entries, returncode = get_smart_entries(disk)
if current_entries != previous_entries:
if not in_progress(current_entries):
keep_going = False
if args.timeout is not None:
if args.timeout <= 0:
logging.debug('Polling timed out')
return 'Polling timed out', 1
else:
args.timeout -= args.sleep
if isinstance(current_entries[0], str):
return current_entries[0], returncode
else:
return current_entries[0]['status'], returncode
def main():
description = 'Tests that SMART capabilities on disks that support SMART function.'
parser = ArgumentParser(description=description)
parser.add_argument('-b', '--block-dev',
metavar='DISK',
default='/dev/sda',
help=('the DISK to run this test against '
'[default: %(default)s]'))
parser.add_argument('-d', '--debug',
action='store_true',
default=False,
help='prints some debug info')
parser.add_argument('-s', '--sleep',
type=int,
default=5,
help=('number of seconds to sleep between checks '
'[default: %(default)s].'))
parser.add_argument('-t', '--timeout',
type=int,
help='number of seconds to timeout from sleeping.')
args = parser.parse_args()
# Set logging
format = '%(levelname)-8s %(message)s'
handler = ListHandler()
handler.setFormatter(logging.Formatter(format))
logger = logging.getLogger()
logger.addHandler(handler)
if args.debug:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
# Make sure we're root, because smartctl doesn't work otherwise.
if not os.geteuid() == 0:
parser.error("You must be root to run this program")
disk = args.block_dev
if not enable_smart(disk):
logging.warning('SMART could not be enabled on %s' % disk)
return 1
# Initiate a self test and start polling until the test is done
previous_entries, returncode = get_smart_entries(disk)
logging.info("Starting SMART self-test on %s", disk)
if run_smart_test(disk) != 0:
logging.error("Error reported during smartctl test")
return 1
if len(previous_entries) > 20:
# Abort the previous instance
# so that polling can identify the difference
run_smart_test(disk)
previous_entries, returncode = get_smart_entries(disk)
status, returncode = poll_for_status(args, disk, previous_entries)
if returncode != 0:
log, returncode = get_smart_entries(disk)
logging.error("FAIL: SMART Self-Test appears to have failed for some reason. "
"Run 'sudo smartctl -l selftest %s' to see the SMART log",
disk)
logging.debug("Last smartctl return code: %d", returncode)
logging.debug("Last smartctl run status: %s", status)
return 1
else:
logging.info("PASS: SMART Self-Test completed without error")
return 0
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/graphic_memory_info 0000775 0001750 0001750 00000004507 12646152433 024620 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# graphic_memory_info
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Shawn Wang
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
"""
The graphic_memory_info got information from lspci
"""
import re
import sys
import subprocess
# 00:01.0 VGA compatible controller: \
# Advanced Micro Devices [AMD] nee ATI Wrestler [Radeon HD 6320] \
# (prog-if 00 [VGA controller])
def vgamem_paser(data=None):
'''Parsing type vga and find memory information'''
device = None
vgamems = list()
for line in data.split('\n'):
for match in re.finditer('(\d\d:\d\d\.\d) VGA(.+): (.+)', line):
device = match.group(1)
name = match.group(3)
if device is None:
continue
#Memory at e0000000 (32-bit, prefetchable) [size=256M]
for match in re.finditer('Memory(.+) prefetchable\) \[size=(\d+)M\]',
line):
vgamem_size = match.group(2)
vgamem = {'device': device,
'name': name,
'vgamem_size': vgamem_size}
vgamems.append(vgamem)
return vgamems
def main():
'''main function
lspci -v -s 00:01.0 | grep ' prefetchable'
'''
try:
data = subprocess.check_output(['lspci', '-v'],
universal_newlines=True)
except subprocess.CalledProcessError as exc:
return exc.returncode
vgamems = vgamem_paser(data)
for vgamem in vgamems:
output_str = "Device({0})\t Name: {1}\tVGA Memory Size: {2}M"
print(output_str.format(vgamem['device'],
vgamem['name'],
vgamem['vgamem_size']))
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/removable_storage_test 0000775 0001750 0001750 00000102041 12646152433 025327 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import argparse
import collections
import dbus
import hashlib
import logging
import os
import subprocess
import sys
import tempfile
import time
from gi.repository import GUdev
from checkbox_support.dbus import connect_to_system_bus
from checkbox_support.dbus.udisks2 import UDISKS2_BLOCK_INTERFACE
from checkbox_support.dbus.udisks2 import UDISKS2_DRIVE_INTERFACE
from checkbox_support.dbus.udisks2 import UDISKS2_FILESYSTEM_INTERFACE
from checkbox_support.dbus.udisks2 import UDisks2Model, UDisks2Observer
from checkbox_support.dbus.udisks2 import is_udisks2_supported
from checkbox_support.dbus.udisks2 import lookup_udev_device
from checkbox_support.dbus.udisks2 import map_udisks1_connection_bus
from checkbox_support.heuristics.udisks2 import is_memory_card
from checkbox_support.helpers.human_readable_bytes import HumanReadableBytes
from checkbox_support.parsers.udevadm import CARD_READER_RE
from checkbox_support.parsers.udevadm import GENERIC_RE
from checkbox_support.parsers.udevadm import FLASH_RE
from checkbox_support.udev import get_interconnect_speed
from checkbox_support.udev import get_udev_block_devices
from checkbox_support.udev import get_udev_xhci_devices
class ActionTimer():
'''Class to implement a simple timer'''
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
self.stop = time.time()
self.interval = self.stop - self.start
class RandomData():
'''Class to create data files'''
def __init__(self, size):
self.tfile = tempfile.NamedTemporaryFile(delete=False)
self.path = ''
self.name = ''
self.path, self.name = os.path.split(self.tfile.name)
self._write_test_data_file(size)
def _generate_test_data(self):
seed = "104872948765827105728492766217823438120"
phrase = '''
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat
volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse
molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero
eros et accumsan et iusto odio dignissim qui blandit praesent luptatum
zzril delenit augue duis dolore te feugait nulla facilisi.
'''
words = phrase.replace('\n', '').split()
word_deque = collections.deque(words)
seed_deque = collections.deque(seed)
while True:
yield ' '.join(list(word_deque))
word_deque.rotate(int(seed_deque[0]))
seed_deque.rotate(1)
def _write_test_data_file(self, size):
data = self._generate_test_data()
while os.path.getsize(self.tfile.name) < size:
self.tfile.write(next(data).encode('UTF-8'))
return self
def md5_hash_file(path):
md5 = hashlib.md5()
try:
with open(path, 'rb') as stream:
while True:
data = stream.read(8192)
if not data:
break
md5.update(data)
except IOError as exc:
logging.error("unable to checksum %s: %s", path, exc)
return None
else:
return md5.hexdigest()
class DiskTest():
''' Class to contain various methods for testing removable disks '''
def __init__(self, device, memorycard):
self.rem_disks = {} # mounted before the script running
self.rem_disks_nm = {} # not mounted before the script running
self.rem_disks_memory_cards = {}
self.rem_disks_memory_cards_nm = {}
self.rem_disks_speed = {}
# LP: #1313581, TODO: extend to be rem_disks_driver
self.rem_disks_xhci = {}
self.data = ''
self.device = device
self.memorycard = memorycard
self._probe_disks()
def read_file(self, source):
with open(source, 'rb') as infile:
try:
self.data = infile.read()
except IOError as exc:
logging.error("Unable to read data from %s: %s", source, exc)
return False
else:
return True
def write_file(self, data, dest):
try:
outfile = open(dest, 'wb', 0)
except OSError as exc:
logging.error("Unable to open %s for writing.", dest)
logging.error(" %s", exc)
return False
with outfile:
try:
outfile.write(self.data)
except IOError as exc:
logging.error("Unable to write data to %s: %s", dest, exc)
return False
else:
outfile.flush()
os.fsync(outfile.fileno())
return True
def clean_up(self, target):
try:
os.unlink(target)
except OSError as exc:
logging.error("Unable to remove tempfile %s", target)
logging.error(" %s", exc)
def _probe_disks(self):
"""
Internal method used to probe for available disks
Indirectly sets:
self.rem_disks{,_nm,_memory_cards,_memory_cards_nm,_speed}
"""
bus, loop = connect_to_system_bus()
if is_udisks2_supported(bus):
self._probe_disks_udisks2(bus)
else:
self._probe_disks_udisks1(bus)
def _probe_disks_udisks2(self, bus):
"""
Internal method used to probe / discover available disks using udisks2
dbus interface using the provided dbus bus (presumably the system bus)
"""
# We'll need udisks2 and udev to get the data we need
udisks2_observer = UDisks2Observer()
udisks2_model = UDisks2Model(udisks2_observer)
udisks2_observer.connect_to_bus(bus)
udev_client = GUdev.Client()
# Get a collection of all udev devices corresponding to block devices
udev_devices = get_udev_block_devices(udev_client)
# Get a collection of all udisks2 objects
udisks2_objects = udisks2_model.managed_objects
# Let's get a helper to simplify the loop below
def iter_filesystems_on_block_devices():
"""
Generate a collection of UDisks2 object paths that
have both the filesystem and block device interfaces
"""
for udisks2_object_path, interfaces in udisks2_objects.items():
if (UDISKS2_FILESYSTEM_INTERFACE in interfaces and
UDISKS2_BLOCK_INTERFACE in interfaces):
yield udisks2_object_path
# We need to know about all IO candidates,
# let's iterate over all the block devices reported by udisks2
for udisks2_object_path in iter_filesystems_on_block_devices():
# Get interfaces implemented by this object
udisks2_object = udisks2_objects[udisks2_object_path]
# Find the path of the udisks2 object that represents the drive
# this object is a part of
drive_object_path = (
udisks2_object[UDISKS2_BLOCK_INTERFACE]['Drive'])
# Lookup the drive object, if any. This can fail when
try:
drive_object = udisks2_objects[drive_object_path]
except KeyError:
logging.error(
"Unable to locate drive associated with %s",
udisks2_object_path)
continue
else:
drive_props = drive_object[UDISKS2_DRIVE_INTERFACE]
# Get the connection bus property from the drive interface of the
# drive object. This is required to filter out the devices we don't
# want to look at now.
connection_bus = drive_props["ConnectionBus"]
desired_connection_buses = set([
map_udisks1_connection_bus(device)
for device in self.device])
# Skip devices that are attached to undesired connection buses
if connection_bus not in desired_connection_buses:
continue
# Lookup the udev object that corresponds to this object
try:
udev_device = lookup_udev_device(udisks2_object, udev_devices)
except LookupError:
logging.error(
"Unable to locate udev object that corresponds to: %s",
udisks2_object_path)
continue
# Get the block device pathname,
# to avoid the confusion, this is something like /dev/sdbX
dev_file = udev_device.get_device_file()
# Get the list of mount points of this block device
mount_points = (
udisks2_object[UDISKS2_FILESYSTEM_INTERFACE]['MountPoints'])
# Get the speed of the interconnect that is associated with the
# block device we're looking at. This is purely informational but
# it is a part of the required API
interconnect_speed = get_interconnect_speed(udev_device)
if interconnect_speed:
self.rem_disks_speed[dev_file] = (
interconnect_speed * 10 ** 6)
else:
self.rem_disks_speed[dev_file] = None
# We need to skip-non memory cards if we look for memory cards and
# vice-versa so let's inspect the drive and use heuristics to
# detect memory cards (a memory card reader actually) now.
if self.memorycard != is_memory_card(drive_props['Vendor'],
drive_props['Model'],
drive_props['Media']):
continue
# The if/else test below simply distributes the mount_point to the
# appropriate variable, to keep the API requirements. It is
# confusing as _memory_cards is variable is somewhat dummy.
if mount_points:
# XXX: Arbitrarily pick the first of the mount points
mount_point = mount_points[0]
self.rem_disks_memory_cards[dev_file] = mount_point
self.rem_disks[dev_file] = mount_point
else:
self.rem_disks_memory_cards_nm[dev_file] = None
self.rem_disks_nm[dev_file] = None
def _probe_disks_udisks1(self, bus):
"""
Internal method used to probe / discover available disks using udisks1
dbus interface using the provided dbus bus (presumably the system bus)
"""
ud_manager_obj = bus.get_object("org.freedesktop.UDisks",
"/org/freedesktop/UDisks")
ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks')
for dev in ud_manager.EnumerateDevices():
device_obj = bus.get_object("org.freedesktop.UDisks", dev)
device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
udisks = 'org.freedesktop.UDisks.Device'
if not device_props.Get(udisks, "DeviceIsDrive"):
dev_bus = device_props.Get(udisks, "DriveConnectionInterface")
if dev_bus in self.device:
parent_model = parent_vendor = ''
if device_props.Get(udisks, "DeviceIsPartition"):
parent_obj = bus.get_object(
"org.freedesktop.UDisks",
device_props.Get(udisks, "PartitionSlave"))
parent_props = dbus.Interface(
parent_obj, dbus.PROPERTIES_IFACE)
parent_model = parent_props.Get(udisks, "DriveModel")
parent_vendor = parent_props.Get(udisks, "DriveVendor")
parent_media = parent_props.Get(udisks, "DriveMedia")
if self.memorycard:
if (dev_bus != 'sdio'
and not FLASH_RE.search(parent_media)
and not CARD_READER_RE.search(parent_model)
and not GENERIC_RE.search(parent_vendor)):
continue
else:
if (FLASH_RE.search(parent_media)
or CARD_READER_RE.search(parent_model)
or GENERIC_RE.search(parent_vendor)):
continue
dev_file = str(device_props.Get(udisks, "DeviceFile"))
dev_speed = str(device_props.Get(udisks,
"DriveConnectionSpeed"))
self.rem_disks_speed[dev_file] = dev_speed
if len(device_props.Get(udisks, "DeviceMountPaths")) > 0:
devPath = str(device_props.Get(udisks,
"DeviceMountPaths")[0])
self.rem_disks[dev_file] = devPath
self.rem_disks_memory_cards[dev_file] = devPath
else:
self.rem_disks_nm[dev_file] = None
self.rem_disks_memory_cards_nm[dev_file] = None
def get_disks_xhci(self):
"""
Compare
1. the pci slot name of the devices using xhci
2. the pci slot name of the disks,
which is usb3 disks in this case so far,
to make sure the usb3 disk does be on the controller using xhci
"""
# LP: #1378724
udev_client = GUdev.Client()
# Get a collection of all udev devices corresponding to block devices
udev_devices = get_udev_block_devices(udev_client)
# Get a collection of all udev devices corresponding to xhci devices
udev_devices_xhci = get_udev_xhci_devices(udev_client)
for udev_device_xhci in udev_devices_xhci:
pci_slot_name = udev_device_xhci.get_property('PCI_SLOT_NAME')
for udev_device in udev_devices:
devpath = udev_device.get_property('DEVPATH')
if (self._compare_pci_slot_from_devpath(devpath,
pci_slot_name)):
self.rem_disks_xhci[
udev_device.get_property('DEVNAME')] = 'xhci'
return self.rem_disks_xhci
def mount(self):
passed_mount = {}
for key in self.rem_disks_nm:
temp_dir = tempfile.mkdtemp()
if self._mount(key, temp_dir) != 0:
logging.error("can't mount %s", key)
else:
passed_mount[key] = temp_dir
if len(self.rem_disks_nm) == len(passed_mount):
self.rem_disks_nm = passed_mount
return 0
else:
count = len(self.rem_disks_nm) - len(passed_mount)
self.rem_disks_nm = passed_mount
return count
def _mount(self, dev_file, mount_point):
return subprocess.call(['mount', dev_file, mount_point])
def umount(self):
errors = 0
for disk in self.rem_disks_nm:
if not self.rem_disks_nm[disk]:
continue
if self._umount(disk) != 0:
errors += 1
logging.error("can't umount %s on %s",
disk, self.rem_disks_nm[disk])
return errors
def _umount(self, mount_point):
# '-l': lazy umount, dealing problem of unable to umount the device.
return subprocess.call(['umount', '-l', mount_point])
def clean_tmp_dir(self):
for disk in self.rem_disks_nm:
if not self.rem_disks_nm[disk]:
continue
if not os.path.ismount(self.rem_disks_nm[disk]):
os.rmdir(self.rem_disks_nm[disk])
def _compare_pci_slot_from_devpath(self, devpath, pci_slot_name):
# LP: #1334991
# a smarter parser to get and validate a pci slot name from DEVPATH
# then compare this pci slot name to the other
dl = devpath.split('/')
s = set([x for x in dl if dl.count(x) > 1])
if ((pci_slot_name in dl)
and (dl.index(pci_slot_name) < dl.index('block'))
and (not(pci_slot_name in s))):
# 1. there is such pci_slot_name
# 2. sysfs topology looks like
# DEVPATH = ....../pci_slot_name/....../block/......
# 3. pci_slot_name should be unique in DEVPATH
return True
else:
return False
def main():
parser = argparse.ArgumentParser()
parser.add_argument('device',
choices=['usb', 'firewire', 'sdio',
'scsi', 'ata_serial_esata'],
nargs='+',
help=("The type of removable media "
"(usb, firewire, sdio, scsi or ata_serial_esata)"
"to test."))
parser.add_argument('-l', '--list',
action='store_true',
default=False,
help="List the removable devices and mounting status")
parser.add_argument('-m', '--min-speed',
action='store',
default=0,
type=int,
help="Minimum speed a device must support to be "
"considered eligible for being tested (bits/s)")
parser.add_argument('-p', '--pass-speed',
action='store',
default=0,
type=int,
help="Minimum average throughput from all eligible"
"devices for the test to pass (MB/s)")
parser.add_argument('-i', '--iterations',
action='store',
default='1',
type=int,
help=("The number of test cycles to run. One cycle is"
"comprised of generating --count data files of "
"--size bytes and writing them to each device."))
parser.add_argument('-c', '--count',
action='store',
default='1',
type=int,
help='The number of random data files to generate')
parser.add_argument('-s', '--size',
action='store',
type=HumanReadableBytes,
default='1MiB',
help=("The size of the test data file to use. "
"You may use SI or IEC suffixes like: 'K', 'M',"
"'G', 'T', 'Ki', 'Mi', 'Gi', 'Ti', etc. Default"
" is %(default)s"))
parser.add_argument('--auto-reduce-size',
action='store_true',
default=False,
help=("Automatically reduce size to fit in the target"
"filesystem. Reducing until fits in 1MiB"))
parser.add_argument('-n', '--skip-not-mount',
action='store_true',
default=False,
help=("skip the removable devices "
"which haven't been mounted before the test."))
parser.add_argument('--memorycard', action="store_true",
help=("Memory cards devices on bus other than sdio "
"require this parameter to identify "
"them as such"))
parser.add_argument('--driver',
choices=['xhci_hcd'],
help=("Detect the driver of the host controller."
"Only xhci_hcd for usb3 is supported so far."))
args = parser.parse_args()
test = DiskTest(args.device, args.memorycard)
errors = 0
# If we do have removable drives attached and mounted
if len(test.rem_disks) > 0 or len(test.rem_disks_nm) > 0:
if args.list: # Simply output a list of drives detected
print('-' * 20)
print("Removable devices currently mounted:")
if args.memorycard:
if len(test.rem_disks_memory_cards) > 0:
for disk, mnt_point in test.rem_disks_memory_cards.items():
print("%s : %s" % (disk, mnt_point))
else:
print("None")
print("Removable devices currently not mounted:")
if len(test.rem_disks_memory_cards_nm) > 0:
for disk in test.rem_disks_memory_cards_nm:
print(disk)
else:
print("None")
else:
if len(test.rem_disks) > 0:
for disk, mnt_point in test.rem_disks.items():
print("%s : %s" % (disk, mnt_point))
else:
print("None")
print("Removable devices currently not mounted:")
if len(test.rem_disks_nm) > 0:
for disk in test.rem_disks_nm:
print(disk)
else:
print("None")
print('-' * 20)
return 0
else: # Create a file, copy to disk and compare hashes
if args.skip_not_mount:
disks_all = test.rem_disks
else:
# mount those haven't be mounted yet.
errors_mount = test.mount()
if errors_mount > 0:
print("There're total %d device(s) failed at mounting."
% errors_mount)
errors += errors_mount
disks_all = dict(list(test.rem_disks.items())
+ list(test.rem_disks_nm.items()))
if len(disks_all) > 0:
print("Found the following mounted %s partitions:"
% ', '.join(args.device))
for disk, mount_point in disks_all.items():
supported_speed = test.rem_disks_speed[disk]
print(" %s : %s : %s bits/s" %
(disk, mount_point, supported_speed),
end="")
if (args.min_speed and
int(args.min_speed) > int(supported_speed)):
print(" (Will not test it, speed is below %s bits/s)" %
args.min_speed, end="")
print("")
print('-' * 20)
disks_eligible = {disk: disks_all[disk] for disk in disks_all
if not args.min_speed or
int(test.rem_disks_speed[disk])
>= int(args.min_speed)}
if len(disks_eligible) == 0:
logging.error(
"No %s disks with speed higher than %s bits/s",
args.device, args.min_speed)
return 1
write_sizes = []
test_files = {}
disks_freespace = {}
for disk, path in disks_eligible.items():
stat = os.statvfs(path)
disks_freespace[disk] = stat.f_bfree * stat.f_bsize
smallest_freespace = min(disks_freespace.values())
desired_size = args.size
if desired_size > smallest_freespace:
if args.auto_reduce_size:
min_space = HumanReadableBytes("1MiB")
if smallest_freespace < min_space:
raise IOError("Not enough space. {} is required"
.format(min_space))
new_size = HumanReadableBytes(int(0.8 * smallest_freespace))
logging.warning("Automatically reducing test data size"
". {} requested. Reducing to {}."
.format(desired_size, new_size))
desired_size = new_size
else:
raise IOError("Not enough space. {} is required"
.format(desired_size))
# Generate our data file(s)
for count in range(args.count):
test_files[count] = RandomData(desired_size)
write_sizes.append(os.path.getsize(
test_files[count].tfile.name))
total_write_size = sum(write_sizes)
try:
for disk, mount_point in disks_eligible.items():
print("%s (Total Data Size / iteration: %0.4f MB):" %
(disk, (total_write_size / 1024 / 1024)))
iteration_write_size = (
total_write_size * args.iterations) / 1024 / 1024
iteration_write_times = []
for iteration in range(args.iterations):
target_file_list = []
write_times = []
for file_index in range(args.count):
parent_file = test_files[file_index].tfile.name
parent_hash = md5_hash_file(parent_file)
target_filename = (
test_files[file_index].name +
'.%s' % iteration)
target_path = mount_point
target_file = os.path.join(target_path,
target_filename)
target_file_list.append(target_file)
test.read_file(parent_file)
with ActionTimer() as timer:
if not test.write_file(test.data,
target_file):
logging.error(
"Failed to copy %s to %s",
parent_file, target_file)
errors += 1
continue
write_times.append(timer.interval)
child_hash = md5_hash_file(target_file)
if parent_hash != child_hash:
logging.warning(
"[Iteration %s] Parent and Child"
" copy hashes mismatch on %s!",
iteration, target_file)
logging.warning(
"\tParent hash: %s", parent_hash)
logging.warning(
"\tChild hash: %s", child_hash)
errors += 1
for file in target_file_list:
test.clean_up(file)
total_write_time = sum(write_times)
# avg_write_time = total_write_time / args.count
try:
avg_write_speed = ((
total_write_size / total_write_time)
/ 1024 / 1024)
except ZeroDivisionError:
avg_write_speed = 0.00
finally:
iteration_write_times.append(total_write_time)
print("\t[Iteration %s] Average Speed: %0.4f"
% (iteration, avg_write_speed))
for iteration in range(args.iterations):
iteration_write_time = sum(iteration_write_times)
print("\tSummary:")
print("\t\tTotal Data Attempted: %0.4f MB"
% iteration_write_size)
print("\t\tTotal Time to write: %0.4f secs"
% iteration_write_time)
print("\t\tAverage Write Time: %0.4f secs" %
(iteration_write_time / args.iterations))
try:
avg_write_speed = (iteration_write_size /
iteration_write_time)
except ZeroDivisionError:
avg_write_speed = 0.00
finally:
print("\t\tAverage Write Speed: %0.4f MB/s" %
avg_write_speed)
finally:
for key in range(args.count):
test.clean_up(test_files[key].tfile.name)
if (len(test.rem_disks_nm) > 0):
if test.umount() != 0:
errors += 1
test.clean_tmp_dir()
if errors > 0:
logging.warning(
"Completed %s test iterations, but there were"
" errors", args.count)
return 1
else:
# LP: 1313581
# Try to figure out whether the disk
# is SuperSpeed USB and using xhci_hcd driver.
if (args.driver == 'xhci_hcd'):
# The speed reported by udisks is sometimes
# less than 5G bits/s, for example,
# it may be 705032705 bits/s
# So using
# 500000000
# = 500 M bits/s
# > 480 M bits/s ( USB 2.0 spec.)
# to make sure that it is higher USB version than 2.0
#
# int() for int(test.rem_disks_speed[disk])
# is necessary
# because the speed value of
# the dictionary rem_disks_speed is
# 1. str or int from _probe_disks_udisks2
# 2. int from _probe_disks_udisks1.
# This is really a mess. : (
print("\t\t--------------------------------")
if(500000000 < int(test.rem_disks_speed[disk])):
print("\t\tDevice Detected: SuperSpeed USB")
# Unlike rem_disks_speed,
# which must has the connect speed
# for each disk devices,
# disk devices may not use xhci as
# controller drivers.
# This will raise KeyError for no
# associated disk device was found.
xhci_disks = test.get_disks_xhci()
# pep8 style suggest to limit the try clause
# to the absolute minimum amount of code necessary
try:
disk_xhci_flag = xhci_disks[disk]
except KeyError:
print("\t\tDisk does not use xhci_hci.")
return 1
else:
if('xhci' == disk_xhci_flag):
print("\t\tDriver Detected: xhci_hcd")
else:
print("\t\tDisk does not use xhci_hci.")
logging.debug("disk_xhci_flag is not xhci")
return 1
else:
# Give it a hint for the detection failure.
# LP: #1362902
print(("\t\tNo SuperSpeed USB using xhci_hcd "
"was detected correctly."))
print(("\t\tHint: please use dmesg to check "
"the system status again."))
return 1
# Pass is not assured
if (not args.pass_speed or
avg_write_speed >= args.pass_speed):
return 0
else:
print("FAIL: Average speed was lower than desired "
"pass speed of %s MB/s" % args.pass_speed)
return 1
else:
logging.error("No device being mounted successfully "
"for testing, aborting")
return 1
else: # If we don't have removable drives attached and mounted
logging.error("No removable drives were detected, aborting")
return 1
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/network_check 0000775 0001750 0001750 00000003504 12646152433 023422 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
"""
Check that it's possible to establish a http connection against
ubuntu.com
"""
from subprocess import call
from argparse import ArgumentParser
import http.client
import urllib.request, urllib.error, urllib.parse
import sys
def check_url(url):
"""
Open URL and return True if no exceptions were raised
"""
try:
urllib.request.urlopen(url)
except (urllib.error.URLError, http.client.InvalidURL):
return False
return True
def main():
"""
Check HTTP and connection
"""
parser = ArgumentParser()
parser.add_argument('-u', '--url',
action='store',
default='http://cdimage.ubuntu.com',
help='The target URL to try. Default is %(default)s')
parser.add_argument('-a', '--auto',
action='store_true',
default=False,
help='Runs in Automated mode, with no visible output')
args = parser.parse_args()
url = {"http": args.url}
results = {}
for protocol, value in url.items():
results[protocol] = check_url(value)
bool2str = {True: 'Success', False: 'Failed'}
message = ("HTTP connection: %(http)s\n"
% dict([(protocol, bool2str[value])
for protocol, value in results.items()]))
command = ["zenity", "--title=Network",
"--text=%s" % message]
if all(results.values()):
command.append("--info")
else:
command.append("--error")
if not args.auto:
try:
call(command)
except OSError:
print("Zenity missing; unable to report test result:\n %s" % message)
if any(results.values()):
return 0
else:
return 1
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/brightness_test 0000775 0001750 0001750 00000013054 12646152433 024004 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# brightness_test
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Alberto Milone
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
import sys
import os
import time
from sys import stdout, stderr
from glob import glob
class Brightness(object):
def __init__(self, path='/sys/class/backlight'):
self.sysfs_path = path
self._interfaces = self._get_interfaces_from_path()
def read_value(self, path):
'''Read the value from a file'''
# See if the source is a file or a file object
# and act accordingly
file = path
if file == None:
lines_list = []
else:
# It's a file
if not hasattr(file, 'write'):
myfile = open(file, 'r')
lines_list = myfile.readlines()
myfile.close()
# It's a file object
else:
lines_list = file.readlines()
return int(''.join(lines_list).strip())
def write_value(self, value, path, test=None):
'''Write a value to a file'''
value = '%d' % value
# It's a file
if not hasattr(path, 'write'):
if test:
path = open(path, 'a')
else:
path = open(path, 'w')
path.write(value)
path.close()
# It's a file object
else:
path.write(value)
def get_max_brightness(self, path):
full_path = os.path.join(path, 'max_brightness')
return self.read_value(full_path)
def get_actual_brightness(self, path):
full_path = os.path.join(path, 'actual_brightness')
return self.read_value(full_path)
def get_last_set_brightness(self, path):
full_path = os.path.join(path, 'brightness')
return self.read_value(full_path)
def _get_interfaces_from_path(self):
'''check all the files in a directory looking for quirks'''
interfaces = []
if os.path.isdir(self.sysfs_path):
for d in glob(os.path.join(self.sysfs_path, '*')):
if os.path.isdir(d):
interfaces.append(d)
return interfaces
def get_best_interface(self):
'''Get the best acpi interface'''
# Follow the heuristic in https://www.kernel.org/doc/Documentation/
#ABI/stable/sysfs-class-backlight
if len(self._interfaces) == 0:
return None
else:
interfaces = {}
for interface in self._interfaces:
try:
with open(interface + '/type') as type_file:
iface_type = type_file.read().strip()
except IOError:
continue
interfaces[iface_type] = interface
if interfaces.get('firmware'):
return interfaces.get('firmware')
elif interfaces.get('platform'):
return interfaces.get('platform')
elif interfaces.get('raw'):
return interfaces.get('raw')
else:
fallback_type = sorted(interfaces.keys())[0]
print("WARNING: no interface of type firmware/platform/raw "
"found. Using {} of type {}".format(
interfaces[fallback_type],
fallback_type))
return interfaces[fallback_type]
def was_brightness_applied(self, interface):
'''See if the selected brightness was applied
Note: this doesn't guarantee that screen brightness
changed.
'''
if (abs(self.get_actual_brightness(interface) -
self.get_last_set_brightness(interface)) > 1):
return False
else:
return True
def main():
brightness = Brightness()
# Make sure that we have root privileges
if os.geteuid() != 0:
print('Error: please run this program as root',
file=sys.stderr)
exit(1)
interface = brightness.get_best_interface()
# If no backlight interface can be found
if not interface:
exit(1)
# Get the current brightness which we can restore later
current_brightness = brightness.get_actual_brightness(interface)
# Get the maximum value for brightness
max_brightness = brightness.get_max_brightness(interface)
# Set the brightness to half the max value
brightness.write_value(max_brightness / 2,
os.path.join(interface,
'brightness'))
# Check that "actual_brightness" reports the same value we
# set "brightness" to
exit_status = not brightness.was_brightness_applied(interface)
# Wait a little bit before going back to the original value
time.sleep(2)
# Set the brightness back to its original value
brightness.write_value(current_brightness,
os.path.join(interface,
'brightness'))
exit(exit_status)
if __name__ == '__main__':
main()
plainbox-provider-checkbox-0.25/bin/fresh_rate_info 0000775 0001750 0001750 00000004175 12646152433 023736 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# fresh_rate_info
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Shawn Wang
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
"""
The fresh_rate_info got information from xrandr
"""
import re
import sys
import subprocess
def xrandr_paser(data=None):
'''return an array(xrandrs)'''
resolution = None
xrandrs = list()
for line in str(data).split('\n'):
for match in re.finditer('(.+) connected (\d+x\d+)\+', line):
connector = match.group(1)
resolution = match.group(2)
break
if resolution is None:
continue
for match in re.finditer('{0}\s+(.+)\*'.format(resolution),
line):
refresh_rate = match.group(1)
xrandr = {'connector': connector,
'resolution': resolution,
'refresh_rate': refresh_rate}
xrandrs.append(xrandr)
return xrandrs
def main():
'''main function'''
try:
data = subprocess.check_output(['xrandr', '--current'],
universal_newlines=True)
except subprocess.CalledProcessError as exc:
return exc.returncode
xrandrs = xrandr_paser(data)
for xrandr in xrandrs:
output_str = "Connector({0}):\t Resolution: {1} \t RefreshRate: {2}"
print(output_str.format(xrandr['connector'],
xrandr['resolution'],
xrandr['refresh_rate']))
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/dkms_info 0000775 0001750 0001750 00000044455 12646152433 022557 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# encoding: utf-8
# Copyright 2015 Canonical Ltd.
# Written by:
# Shawn Wang
# Zygmunt Krynicki
#
# This program 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
"""
dkms_info provides device package information.
supported package types:
- dkms (Dynamic Kernel Module Support): provides kernel modules
- non-dkms: packages that with modaliases header and don't exist in dkms list
- hardware modalias: might be unused dkms or config package
- oemalias: It is like non-dkms(w/o modalias)
supported output format:
- onelines: one line per packages with matched modaliases information
- dumps: json output (fully information)
"""
import fnmatch
import functools
import email.parser
import io
import json
import logging
import os
import subprocess
import sys
import unittest
from guacamole import Command
try:
from unittest import mock
except ImportError:
from plainbox.vendor import mock
_logger = logging.getLogger(None)
@functools.lru_cache()
def get_system_module_list():
"""
Use lsmod to list current kernel modules.
:returns:
A list of module names that are loaded into the current kernel.
"""
_logger.info("Looking at inserted kernel modules")
modules = []
with io.open("/proc/modules", 'rt',
encoding='UTF-8') as stream:
for line in stream.readlines():
modules.append(line.split()[0].strip())
return modules
@functools.lru_cache()
def get_system_modaliases():
r"""
List machine modaliases.
:returns:
dict of hardware modaliases.
key: modalias_type
value: list of modalias_string
"""
_logger.info("Looking for modalias files in /sys/devices")
result = {}
name = "modalias"
for root, dirs, files in os.walk("/sys/devices/"):
if name in files:
with io.open(os.path.join(root, name), 'rt',
encoding='UTF-8') as stream:
data = stream.read().strip()
(modalias_type, modalias_string) = data.split(":", 1)
if modalias_type not in result:
result[modalias_type] = []
if modalias_string not in result[modalias_type]:
result[modalias_type].append(modalias_string)
return result
def get_installed_dkms_modules():
"""
Query dkms_status from /var/lib/dkms/.
An installed dkms module has the below directory.
/var/lib/dkms///
:returns:
list of (, )
"""
_dkmses = []
_logger.info("Querying dkms database")
path = "/var/lib/dkms/"
for root, dirs, files in os.walk(path):
if os.uname().release in dirs:
dkms = root[len(path):].split("/")
if len(dkms) != 2:
continue
_dkmses.append(dkms)
return _dkmses
@functools.lru_cache()
def match_patterns(patterns):
"""
Check modalias patterns matched with modalias, or type is oemalias.
oemalias is a special pattern_type for oem.
:param patterns:
list of modalias pattern from debian package.
:returns:
list of modalias pattern matched with hardware modalias
"""
_logger.info("Looking for modalias objects matching")
matched = []
if not patterns:
return matched
hw_modaliases = get_system_modaliases()
for pattern in patterns:
pattern_array = pattern.split(":", 1)
if len(pattern_array) < 2:
_logger.info("skip pattern {}, can't find type".format(pattern))
continue
(pattern_type, pattern_string) = pattern_array
if pattern_type == "oemalias":
matched.append(pattern)
if pattern_type not in hw_modaliases:
continue
for item in hw_modaliases[pattern_type]:
if fnmatch.fnmatch(item, pattern_string):
matched.append(pattern)
return matched
class SystemInfoTests(unittest.TestCase):
"""Tests for System Information Parsing and Collection."""
_proc_modules = """\
xt_REDIRECT 16384 3 - Live 0x0000000000000000
nf_nat_redirect 16384 1 xt_REDIRECT, Live 0x0000000000000000
xt_hl 16384 3 - Live 0x0000000000000000
hid_generic 16384 0 - Live 0x0000000000000000
usbhid 53248 0 - Live 0x0000000000000000
hid 110592 2 hid_generic,usbhid, Live 0x0000000000000000
overlay 45056 1 - Live 0x0000000000000000
"""
_modalias = """\
usb:v1D6Bp0003d0319dc09dsc00dp03ic09isc00ip00in00
"""
def setUp(self):
"""Common setup code."""
get_system_module_list.cache_clear()
get_system_modaliases.cache_clear()
@mock.patch('io.open', mock.mock_open(read_data=_proc_modules))
def test_get_module_list__calls_and_parses_lsmod(self):
"""Ensure that get_module_list() parses lsmod output."""
# NOTE: Return value was loaded from my system running kernel 4.0.
# The first few and last rows to be precise.
modules = get_system_module_list()
self.assertEqual(modules, [
'xt_REDIRECT', 'nf_nat_redirect', 'xt_hl', 'hid_generic',
'usbhid', 'hid', 'overlay'])
@mock.patch('io.open', mock.mock_open(read_data=_proc_modules))
def test_get_module_list_is_cached(self):
"""Ensure that get_module_list() cache works."""
modules1 = get_system_module_list()
modules2 = get_system_module_list()
self.assertIn('xt_REDIRECT', modules1)
self.assertIn('overlay', modules2)
self.assertEqual(modules1, modules2)
@mock.patch('os.walk')
@mock.patch('io.open', mock.mock_open(read_data=_modalias))
def test_get_system_modalias(self, mock_os_walk):
"""test_get_system_modalias."""
mock_os_walk.return_value = [
("/sys/devices/pci0000:00/0000:00:14.0/usb2/2-0:1.0/modalias",
["driver", "subsystem"],
["modalias", "uevent"]),
]
"""fetch hw_modaliases from machine and check modalis types."""
modaliases = get_system_modaliases()
self.assertEqual(len(modaliases), 1)
self.assertIn("usb", modaliases)
@mock.patch('os.uname')
@mock.patch('os.walk')
def test_get_installed_dkms_modules(self, mock_os_walk, mock_os_uname):
"""test_get_installed_dkms_modules."""
mock_os_walk.return_value = [
("/var/lib/dkms/hello/0.1",
["3.19.0-15-generic", "build", "source"],
[]),
]
o = mock.Mock()
o.release = "3.19.0-15-generic"
mock_os_uname.return_value = o
self.assertEqual([['hello', '0.1']],
get_installed_dkms_modules())
@mock.patch('__main__.get_system_modaliases')
def test_match_patterns(self, mock_get_system_modaliases):
"""Test of match_patterns."""
mock_get_system_modaliases.return_value = {
"pci": ["v0000168Cd00000036sv0000103Csd0000217Fbc02sc80i00",
"v00008086d00008C26sv0000103Csd000022D9bc0Csc03i20"],
"usb": ["v8087p8000d0005dc09dsc00dp01ic09isc00ip00in00",
"v1D6Bp0002d0319dc09dsc00dp00ic09isc00ip00in00"],
}
pkg_modalieses = ["pci:v00008086d00008C26sv*sd*bc*sc*i*",
"usb:v07B4p010Ad0102dc*dsc*dp*ic*isc*ip*in*",
"oemalias:test"]
matched_modalieses = match_patterns(tuple(pkg_modalieses))
# match_patterns
self.assertIn("pci:v00008086d00008C26sv*sd*bc*sc*i*",
matched_modalieses)
self.assertIn("oemalias:test",
matched_modalieses)
self.assertNotIn("usb:v07B4p010Ad0102dc*dsc*dp*ic*isc*ip*in*",
matched_modalieses)
class DkmsPackage(object):
"""
Handle DKMS type device package, DKMS is a kernel module framework.
It generate modules for installed kernel or different kernel versions.
The dkms modules will be copied to /lib/modulesa/`uname -r`/updates/dkms/.
Those modules might be load by modaliases information.
"""
def __init__(self, name, version):
"""
init of DkmsPackage, define all the attribute.
:param name:
DKMS module name
:param version:
DKMS module version
"""
self.dkms_name = name
self.dkms_ver = version
self.pkg_name = self._query_package()
self.kernel_ver = os.uname().release
self.arch = os.uname().machine
self.mods = self._list_modules()
self.install_mods = self._list_install_modules()
self.pkg = None
def _query_package(self):
"""
Query debian package of dkms.
Use dpkg -S to check dkms src path of debian package.
:return:
string of package name or None
"""
path = "/usr/src/{}-{}/dkms.conf".format(self.dkms_name, self.dkms_ver)
_logger.info("Looking for packages that provide: %s", path)
dpkg_info_root = "/var/lib/dpkg/info"
for fn in os.listdir(dpkg_info_root):
if not fn.endswith(".list"):
continue
with io.open(os.path.join(dpkg_info_root, fn), 'rt',
encoding='UTF-8') as stream:
if path in stream.read():
return fn[:-len(".list")]
return None
def _list_modules(self):
"""
List all the kernel modules that provide by the dkms package.
Module name (.ko) with "-" will be replace to "_" when module loaded.
:param path:
The directory to look at.
:return:
List of kernel modules
"""
path = "/var/lib/dkms/{}/{}/{}/{}/module".format(
self.dkms_name, self.dkms_ver, self.kernel_ver, self.arch)
_logger.info("Looking for kernel modules in %s", path)
result = []
for module_file in os.listdir(path):
(module, extension) = os.path.splitext(module_file)
if extension == ".ko":
result.append(module.replace("-", "_"))
return result
def _list_install_modules(self):
"""
Return a dict of install_modules.
key is installed module name
value is tuple of matched patterns
:return:
Dict of installed dkms modules
"""
install_mods = {}
for m in self.mods:
if m not in get_system_module_list():
continue
_logger.info("Inspecting module %s", m)
output = subprocess.check_output(["modinfo", m],
universal_newlines=True)
aliases = []
for line in output.splitlines():
if not line.startswith("alias:"):
continue
key, value = line.split(':', 1)
aliases.append(value.strip())
install_mods[m] = match_patterns(tuple(aliases))
return install_mods
def _headers_to_dist(pkg_str):
"""
Convert rft822 headers string to dict.
:param headers:
deb822 headers object
:return:
dict, the key is lowercase of deb822 headers key
"""
header = email.parser.Parser().parsestr(pkg_str)
target = {}
for key in header.keys():
target[key.lower()] = header[key]
return target
class DebianPackageHandler(object):
"""Use rtf822(email) to handle the package information from file_object."""
def __init__(self, extra_pkgs=[], file_object=None):
"""
DebianPackageHandler.
:param file_object:
default file open from /var/lib/dpkg/status,
where stored system package information
"""
if file_object is None:
file_object = io.open('/var/lib/dpkg/status', 'rt',
encoding='UTF-8')
self._file_object = file_object
self.extra_pkgs = extra_pkgs
self.pkgs = self._get_device_pkgs()
def _gen_all_pkg_strs(self):
"""
Get package information in /var/lib/dpkg/status.
:returns:
A generator of debian package.
"""
_logger.info("Loading information about all packages")
for pkg_str in self._file_object.read().split('\n\n'):
yield pkg_str
def _get_device_pkgs(self):
"""
Only device packages have debian package header 'Modaliases'.
This method get packages with the key ``modaliases``.
Use the method instead of get_all_pkgs for performance issues.
:returns:
A list of dict , the dict is converted from debian package header.
"""
_logger.info("Looking for packages providing modaliases")
_modalias_pkgs = {}
target_str = ""
result = {}
for pkg_str in self._gen_all_pkg_strs():
for pkg in self.extra_pkgs:
if pkg.pkg_name is None:
continue
pstr = "Package: {}".format(pkg.pkg_name)
if pstr in pkg_str:
_logger.info("Gathering information of package, {}".format(
pkg.pkg_name))
pkg.pkg = _headers_to_dist(pkg_str)
break
else:
if "Modaliases:" in pkg_str:
pkg = _headers_to_dist(pkg_str)
(modalias_header, pattern_str) = \
pkg['modaliases'].strip(")").split("(")
patterns = pattern_str.split(', ')
patterns.sort()
pkg['match_patterns'] = match_patterns(tuple(patterns))
with io.open("/var/lib/dpkg/info/{}.list".format(pkg['package']),
'rt', encoding='UTF-8') as stream:
if "/dkms.conf" in stream.read():
pkg['unused_dkms'] = True
result[pkg['package']] = pkg
return result
def to_json(self):
return json.dumps({ "dkms": self.extra_pkgs, "non-dkms": self.pkgs }, default=lambda o: o.__dict__, sort_keys=True, indent=4)
def to_outline(self):
result = ""
for pkg in self.extra_pkgs:
if pkg.pkg is None:
continue
result = "{}\n{}_{}: {}".format(
result,
pkg.pkg_name,
pkg.pkg["version"],
pkg.install_mods)
for pkg_name, pkg in self.pkgs.items():
extra_str = ""
if "unused_dkms" in pkg:
extra_str = "- "
result = "{}\n{}{}_{}: {}".format(
result,
extra_str,
pkg_name,
pkg["version"],
pkg['match_patterns'])
return result
class DebianPackageHandlerTest(unittest.TestCase):
"""Test of DebianPackageHandler."""
_var_lib_dpkg_status = """\
Package: foo
Status: install ok installed
Modaliases: hwe(pci:v000099DDd00000036sv*sd*bc*sc*i*)
Package: foo1
Status: install ok installed
Modaliases: hwe(pci:v0000AADDd00000036sv*sd*bc*sc*i*)
Package: foo2
Status: install ok installed
Package: foo3
Status: install ok installed
Package: bar
Status: install ok installed
"""
@mock.patch('io.open', mock.mock_open(read_data=_var_lib_dpkg_status))
@mock.patch('__main__.get_system_modaliases')
def test_get_pkgs(self, mock_get_system_modaliases):
"""Test of test_get_pkgs."""
mock_get_system_modaliases.return_value = {
"pci": ["v0000168Cd00000036sv0000103Csd0000217Fbc02sc80i00",
"v00008086d00008C26sv0000103Csd000022D9bc0Csc03i20"],
"usb": ["v8087p8000d0005dc09dsc00dp01ic09isc00ip00in00",
"v1D6Bp0002d0319dc09dsc00dp00ic09isc00ip00in00"],
}
self.pkg_handler = DebianPackageHandler(
file_object=io.StringIO(self._var_lib_dpkg_status))
self.assertEqual(len(self.pkg_handler.pkgs), 2)
class DeviceInfo(Command):
"""
Implementation of the dkms-info command.
dkms_info provides device package information.
@EPILOG@
supported package types:
- dkms (Dynamic Kernel Module Support): provides kernel modules
- non-dkms: packages that with modaliases header and don't exist in dkms
list
- hardware modalias: might be unused dkms or config package
- oemalias: It is like non-dkms(w/o modalias)
supported output formats:
- onelines: one line per packages with matched modaliases information
- dumps: json output (fully information)
"""
def register_arguments(self, parser):
"""Register command line arguments for dkms-info."""
parser.add_argument(
'--format', default="onelines",
choices=["summary", "json"],
help=("Choose output format type: "
"summary (one line per packages) "
"or json (json format, fully information)"))
parser.add_argument(
'--output', default=None,
help=("Output filename to store the output date"))
def invoked(self, ctx):
"""Invoke dkms-info."""
logging.basicConfig(
level=logging.INFO, format='[%(relativeCreated)06dms] %(message)s')
_logger.info("Started")
dkms_pkgs = []
for (dkms_name, dkms_ver) in get_installed_dkms_modules():
dkms_pkg = DkmsPackage(dkms_name, dkms_ver)
dkms_pkgs.append(dkms_pkg)
output = sys.stdout
if ctx.args.output is not None:
output = open(ctx.args.output, 'wt', encoding='UTF-8')
pkg_handler = DebianPackageHandler(extra_pkgs=dkms_pkgs)
if ctx.args.format == "summary":
output.write(pkg_handler.to_outline())
else:
output.write(pkg_handler.to_json())
_logger.info("Data collected")
if __name__ == '__main__':
if '--test' in sys.argv:
sys.argv.remove('--test')
unittest.main()
else:
DeviceInfo().main()
plainbox-provider-checkbox-0.25/bin/get_make_and_model 0000775 0001750 0001750 00000001412 12646152433 024346 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os.path
import shlex
from subprocess import check_output
def print_data(key, value):
print("{}: {}".format(key, value))
def main():
keys = {'Manufacturer': 'vendor',
'Model': 'product',
'Version': 'version'}
cmd = "lshw -C system"
out = check_output(shlex.split(cmd),
universal_newlines = True)
output = out.split('\n')
data = {}
for key in keys:
for line in output:
if keys[key] in line:
data[key] = line.split(':')[1].strip()
break
else:
data[key] = "NOT FOUND"
for key in data:
print_data(key, data[key])
if __name__ == "__main__":
raise SystemExit(main())
plainbox-provider-checkbox-0.25/bin/dmitest 0000775 0001750 0001750 00000024565 12646152433 022257 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
#
# This file is part of Checkbox.
#
# Copyright 2014 Canonical Ltd.
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
#
# Test for sane dmidecode output, particularly with respect to
# various manufacturer information fields. Also, verify that the
# system reports a chassis type that suits its class (server or
# desktop/laptop)
#
# By: Rod Smith
"""Script to test dmidecode output for sanity.
:param --dmifile:
Input filename; optional. If specified, file is used instead of
dmidecode output.
:param --test_versions:
Include chassis, system, and base boad version numbers among tests.
:param --test_serials:
Include system and base board serial numbers among tests.
:param cpu_check:
Don't perform usual tests, except for CPU test.
:param desktop:
SUT is a desktop or laptop
:param server:
SUT is a server
"""
import re
import subprocess
import sys
from argparse import ArgumentParser
def find_in_section(stream, section, label, strings, find_empty):
"""Search for a set of strings on a line in the output.
:param stream:
input text stream (dmidecode output)
:param section:
section label in which to search (e.g., "Chassis Information")
:param label:
label of line on which to search (e.g., "Type:")
:param strings:
set of strings for which to search (e.g., ["server", "blade"])
:param find_empty:
if True, matches empty label field (as if '""' were passed as
a strings value)
:returns found:
True if one or more of strings was found on "label" line in "section"
section, or if "label" line is empty AND find_empty is True;
False otherwise
"""
start_looking = False
found = False
empty = True
for line in stream:
if line == section:
start_looking = True
if start_looking and re.search(label, line):
print("\n" + section)
print(line.strip())
empty = len(line.strip()) == len(label)
if empty and find_empty:
found = True
for s in strings:
if re.search(s, line, flags=re.IGNORECASE):
found = True
break
start_looking = False
return found
def standard_tests(args, stream):
"""
Perform the standard set of tests.
:param args:
Arguments passed to script
:param stream:
Input stream containing dmidecode output
:returns retval:
Number of problems found
"""
retval = 0
"""
NOTE: System type is encoded in both the "Chassis Information" and "Base
Board Type" sections. The former is more reliable, so we do a whitelist
test on it -- the type MUST be specified correctly. The "Base Board Type"
section is less reliable, so rather than flag large numbers of systems
for having "Unknown", "Other", or something similar here, we just flag
it when it's at odds with the type passed on the command line. Also,
the "Base Board Type" may specify a desktop or tower system on servers
shipped in those form factors, so we don't flag that combination as an
error.
"""
if args.test_type == 'server':
if not find_in_section(stream, 'Chassis Information', 'Type:',
['server', 'rack mount', 'blade',
'expansion chassis', 'multi-system', 'tower'],
False):
print("*** Incorrect or unknown server chassis type!")
retval += 1
if find_in_section(stream, 'Base Board Information', 'Type:',
['portable', 'notebook', 'space-saving',
'all in one'], False):
print("*** Incorrect server base board type!")
retval += 1
else:
if not find_in_section(stream, 'Chassis Information', 'Type:',
['notebook', 'portable', 'laptop', 'desktop',
'lunch box', 'space-saving', 'tower',
'all in one', 'hand held'], False):
print("*** Incorrect or unknown desktop chassis type!")
retval += 1
if find_in_section(stream, 'Base Board Information', 'Type:',
['rack mount', 'server', 'multi-system',
'interconnect board'], False):
print("*** Incorrect desktop base board type!")
retval += 1
if find_in_section(stream, 'Chassis Information', 'Manufacturer:',
['empty', 'chassis manufacture', 'null', 'insyde',
'to be filled by o\.e\.m\.', 'no enclosure',
'\.\.\.\.\.'], True):
print("*** Invalid chassis manufacturer!")
retval += 1
if find_in_section(stream, 'System Information', 'Manufacturer:',
['system manufacture', 'insyde', 'standard',
'to be filled by o\.e\.m\.', 'no enclosure'], True):
print("*** Invalid system manufacturer!")
retval += 1
if find_in_section(stream, 'Base Board Information', 'Manufacturer:',
['to be filled by o\.e\.m\.'], True):
print("*** Invalid base board manufacturer!")
retval += 1
if find_in_section(stream, 'System Information', 'Product Name:',
['system product name', 'to be filled by o\.e\.m\.'],
False):
print("*** Invalid system product name!")
retval += 1
if find_in_section(stream, 'Base Board Information', 'Product Name:',
['base board product name',
'to be filled by o\.e\.m\.'], False):
print("*** Invalid base board product name!")
retval += 1
return retval
def version_tests(args, stream):
"""
Perform the version tests.
:param args:
Arguments passed to script
:param stream:
Input stream containing dmidecode output
:returns retval:
Number of problems found
"""
retval = 0
if find_in_section(stream, 'Chassis Information', 'Version:',
['to be filled by o\.e\.m\.', 'empty'],
False):
print("*** Invalid chassis version!")
retval += 1
if find_in_section(stream, 'System Information', 'Version:',
['to be filled by o\.e\.m\.', '\(none\)',
'null', 'system version', 'not applicable',
'\.\.\.\.\.'], False):
print("*** Invalid system information version!")
retval += 1
if find_in_section(stream, 'Base Board Information', 'Version:',
['base board version',
'empty', 'to be filled by o\.e\.m\.'], False):
print("*** Invalid base board version!")
retval += 1
return retval
def serial_tests(args, stream):
"""
Perform the serial number tests.
:param args:
Arguments passed to script
:param stream:
Input stream containing dmidecode output
:returns retval:
Number of problems found
"""
retval = 0
if find_in_section(stream, 'System Information', 'Serial Number:',
['to be filled by o\.e\.m\.',
'system serial number', '\.\.\.\.\.'],
False):
print("*** Invalid system information serial number!")
retval += 1
if find_in_section(stream, 'Base Board Information', 'Serial Number:',
['n/a', 'base board serial number',
'to be filled by o\.e\.m\.', 'empty', '\.\.\.'],
False):
print("*** Invalid base board serial number!")
retval += 1
return retval
def main():
"""Main function."""
parser = ArgumentParser("dmitest")
parser.add_argument('test_type',
help="Test type ('server', 'desktop' or 'cpu-check').",
choices=['server', 'desktop', 'cpu-check'])
parser.add_argument('--dmifile',
help="File to use in lieu of dmidecode.")
parser.add_argument('--test_versions', action="store_true",
help="Set to check version information")
parser.add_argument('--test_serials', action="store_true",
help="Set to check serial number information")
args = parser.parse_args()
# Command to retrieve DMI information
COMMAND = "dmidecode"
try:
if args.dmifile:
print("Reading " + args.dmifile + " as DMI data")
stream = subprocess.check_output(['cat', args.dmifile],
universal_newlines=True).splitlines()
else:
stream = subprocess.check_output(COMMAND,
universal_newlines=True).splitlines()
except subprocess.CalledProcessError as err:
print("Error running {}: {}".format(COMMAND, err))
return 1
retval = 0
if args.test_type == 'server' or args.test_type == 'desktop':
retval += standard_tests(args, stream)
if args.test_versions:
retval += version_tests(args, stream)
if args.test_serials:
retval += serial_tests(args, stream)
if find_in_section(stream, 'Processor Information', 'Version:',
['sample'], False):
print("*** Invalid processor information!")
retval += 1
# In review of dmidecode data on 10/23/2014, no conspicuous problems
# found in BIOS Information section's Vendor, Version, or Release Date
# fields. Therefore, no tests based on these fields have been written.
if retval > 0:
if retval == 1:
print("\nFailed 1 test (see above)")
else:
print("\nFailed {0} tests (see above)".format(retval))
else:
print("\nPassed all tests")
return retval
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/xrandr_cycle 0000775 0001750 0001750 00000016270 12646152433 023255 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import argparse
import errno
import os
import re
import shutil
import subprocess
import sys
import tarfile
import time
parser = argparse.ArgumentParser()
parser.add_argument('--keyword', default='',
help=('A keyword to distinguish the screenshots '
'taken in this run of the script'))
parser.add_argument('--screenshot-dir',
default=os.environ['HOME'],
help=('Specify a directory to store screenshots in. '
'Default is %(default)s'))
args = parser.parse_args()
device_context = '' # track what device's modes we are looking at
modes = [] # keep track of all the devices and modes discovered
current_modes = [] # remember the user's current settings for cleanup later
failures = 0 # count the number of failed modesets
failure_messages = [] # remember which modes failed
success_messages = [] # remember which modes succeeded
# Run xrandr and ask it what devices and modes are supported
xrandrinfo = subprocess.Popen('xrandr -q', shell=True, stdout=subprocess.PIPE)
output = xrandrinfo.communicate()[0].decode().split('\n')
# The results from xrandr are given in terms of the available display devices.
# One device can have zero or more associated modes. Unfortunately xrandr
# indicates this through indentation and is kinda wordy, so we have to keep
# track of the context we see mode names in as we parse the results.
for line in output:
# I haven't seen any blank lines in xrandr's output in my tests, but meh
if line == '':
break
# luckily the various data from xrandr are separated by whitespace...
foo = line.split()
# Check to see if the second word in the line indicates a new context
# -- if so, keep track of the context of the device we're seeing
if len(foo) >= 2: # throw out any weirdly formatted lines
if foo[1] == 'disconnected':
# we have a new context, but it should be ignored
device_context = ''
if foo[1] == 'connected':
# we have a new context that we want to test
device_context = foo[0]
elif device_context != '': # we've previously seen a 'connected' dev
# mode names seem to always be of the format [horiz]x[vert]
# (there can be non-mode information inside of a device context!)
if foo[0].find('x') != -1:
modes.append((device_context, foo[0]))
# we also want to remember what the current mode is, which xrandr
# marks with a '*' character, so we can set things back the way
# we found them at the end:
if foo[1].find('*') != -1:
current_modes.append((device_context, foo[0]))
# Now we have a list of the modes we need to test. So let's do just that.
profile_path = os.environ['HOME'] + '/.shutter/profiles/'
screenshot_path = os.path.join(args.screenshot_dir, 'xrandr_screens')
# Where to find the shutter.xml template? Two possible locations.
shutter_xml_template = None
if 'PLAINBOX_PROVIDER_DATA' in os.environ:
shutter_xml_template = os.path.join(os.environ['PLAINBOX_PROVIDER_DATA'],
"settings", "shutter.xml")
else:
shutter_xml_template = os.path.join(os.path.split(os.path.dirname(
os.path.realpath(__file__)))[0],
"data",
"settings",
"shutter.xml")
if args.keyword:
screenshot_path = screenshot_path + '_' + args.keyword
regex = re.compile(r'filename="[^"\r\n]*"')
# Keep the shutter profile in place before starting
# Any errors creating the directories or copying the template is fatal,
# since things won't work if we fail.
try:
os.makedirs(profile_path, exist_ok=True)
os.makedirs(screenshot_path, exist_ok=True)
except OSError as excp:
raise SystemExit("ERROR: Unable to create "
"required directories: {}".format(excp))
try:
shutil.copy(shutter_xml_template, profile_path)
except (IOError, OSError) as excp:
print("ERROR: Unable to copy {} to {}: {}".format(shutter_xml_template,
profile_path,
excp))
if excp.errno == errno.ENOENT:
print("Try setting PLAINBOX_PROVIDER_DATA to the the data path of a")
print("provider shipping the 'shutter.xml' template file, usually ")
print("found under /usr/share.")
raise SystemExit()
try:
old_profile = open(profile_path + 'shutter.xml', 'r')
content = old_profile.read()
new_profile = open(profile_path + 'shutter.xml', 'w')
# Replace the folder name with the desired one
new_profile.write(re.sub(r'folder="[^"\r\n]*"',
'folder="%s"' % screenshot_path, content))
new_profile.close()
old_profile.close()
except:
raise SystemExit("ERROR: While updating folder name "
"in shutter profile: {}".format(sys.exc_info()))
for mode in modes:
cmd = 'xrandr --output ' + mode[0] + ' --mode ' + mode[1]
retval = subprocess.call(cmd, shell=True)
if retval != 0:
failures = failures + 1
message = 'Failed to set mode ' + mode[1] + ' for output ' + mode[0]
failure_messages.append(message)
else:
# Update shutter profile to save the image as the right name
mode_string = mode[0] + '_' + mode[1]
try:
old_profile = open(profile_path + 'shutter.xml', 'r')
content = old_profile.read()
new_profile = open(profile_path + 'shutter.xml', 'w')
new_profile.write(regex.sub('filename="%s"' % mode_string,
content))
new_profile.close()
old_profile.close()
shuttercmd = ['shutter', '--profile=shutter', '--full', '-e']
retval = subprocess.call(shuttercmd, shell=False)
if retval != 0:
print("""Could not capture screenshot -
you may need to install the package 'shutter'.""")
except:
print("""Could not configure screenshot tool -
you may need to install the package 'shutter',
or check that {}/{} exists and is writable.""".format(
profile_path,
'shutter.xml'))
message = 'Set mode ' + mode[1] + ' for output ' + mode[0]
success_messages.append(message)
time.sleep(3) # let the hardware recover a bit
# Put things back the way we found them
for mode in current_modes:
cmd = 'xrandr --output ' + mode[0] + ' --mode ' + mode[1]
subprocess.call(cmd, shell=True)
# Tar up the screenshots for uploading
try:
with tarfile.open(screenshot_path + '.tgz', 'w:gz') as screen_tar:
for screen in os.listdir(screenshot_path):
screen_tar.add(screenshot_path + '/' + screen, screen)
except:
pass
# Output some fun facts and knock off for the day
for message in failure_messages:
print(message, file=sys.stderr)
for message in success_messages:
print(message)
if failures != 0:
exit(1)
else:
exit(0)
plainbox-provider-checkbox-0.25/bin/rotation_test_using_dbus 0000775 0001750 0001750 00000002772 12646152433 025722 0 ustar sylvain sylvain 0000000 0000000 #!/bin/sh
#
# rotation_test_using_dbus
#
# This script is used to trigger a main screen rotation directly from DBUS to
# simulate the way screen rotation is done when using System Settings screen.
# Indeed, when using xrandr command or Python lib, we sometimes have weird
# behaviours, specifically when used with NVidia cards with proprietary drivers.
#
# This file is part of Checkbox.
#
# Copyright 2015 Canonical Ltd.
#
# Authors: Pierre Equoy
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
rotate() {
dbus-send --session --print-reply --dest=org.gnome.SettingsDaemon /org/gnome/SettingsDaemon/XRANDR org.gnome.SettingsDaemon.XRANDR_2.RotateTo int32:$1 int64:0 > /dev/null 2>&1
}
# Rotate the screen in-between the following modes and the normal mode:
# 2 - left
# 4 - inverted
# 8 - right
# 1 - normal
for i in 2 1 4 1 8 1
do
rotate $i
sleep 4
done
# Rotate one more time to "normal" so next time we logout/login,
# the screen will be set in normal mode.
rotate 1
plainbox-provider-checkbox-0.25/bin/audio_settings 0000775 0001750 0001750 00000000213 12646152433 023607 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
import sys
from checkbox_support.scripts.audio_settings import main
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/cpu_topology 0000775 0001750 0001750 00000006620 12646152433 023321 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
'''
cpu_topology
Written by Jeffrey Lane
'''
import sys
import os
class proc_cpuinfo():
'''
Class to get and handle information from /proc/cpuinfo
Creates a dictionary of data gleaned from that file.
'''
def __init__(self):
self.cpuinfo = {}
cpu_fh = open('/proc/cpuinfo', 'r')
try:
temp = cpu_fh.readlines()
finally:
cpu_fh.close()
for i in temp:
if i.startswith('processor'):
key = 'cpu' + (i.split(':')[1].strip())
self.cpuinfo[key] = {'core_id':'', 'physical_package_id':''}
elif i.startswith('core id'):
self.cpuinfo[key].update({'core_id': i.split(':')[1].strip()})
elif i.startswith('physical id'):
self.cpuinfo[key].update({'physical_package_id':
i.split(':')[1].strip()})
else:
continue
class sysfs_cpu():
'''
Class to get and handle information from sysfs as relates to CPU topology
Creates an informational class to present information on various CPUs
'''
def __init__(self, proc):
self.syscpu = {}
self.path = '/sys/devices/system/cpu/' + proc + '/topology'
items = ['core_id', 'physical_package_id']
for i in items:
try:
syscpu_fh = open(os.path.join(self.path, i), 'r')
except OSError as e:
print("ERROR: %s" % e)
sys.exit(1)
else:
self.syscpu[i] = syscpu_fh.readline().strip()
syscpu_fh.close()
def compare(proc_cpu, sys_cpu):
cpu_map = {}
'''
If there is only 1 CPU the test don't look for core_id
and physical_package_id because those information are absent in
/proc/cpuinfo on singlecore system
'''
for key in proc_cpu.keys():
if 'cpu1' not in proc_cpu:
cpu_map[key] = True
else:
for subkey in proc_cpu[key].keys():
if proc_cpu[key][subkey] == sys_cpu[key][subkey]:
cpu_map[key] = True
else:
cpu_map[key] = False
return cpu_map
def main():
cpuinfo = proc_cpuinfo()
sys_cpu = {}
keys = cpuinfo.cpuinfo.keys()
for k in keys:
sys_cpu[k] = sysfs_cpu(k).syscpu
cpu_map = compare(cpuinfo.cpuinfo, sys_cpu)
if False in cpu_map.values() or len(cpu_map) < 1:
print("FAIL: CPU Topology is incorrect", file=sys.stderr)
print("-" * 52, file=sys.stderr)
print("{0}{1}".format("/proc/cpuinfo".center(30), "sysfs".center(25)),
file=sys.stderr)
print("{0}{1}{2}{3}{1}{2}".format(
"CPU".center(6),
"Physical ID".center(13),
"Core ID".center(9),
"|".center(3)), file=sys.stderr)
for key in sorted(sys_cpu.keys()):
print("{0}{1}{2}{3}{4}{5}".format(
key.center(6),
cpuinfo.cpuinfo[key]['physical_package_id'].center(13),
cpuinfo.cpuinfo[key]['core_id'].center(9),
"|".center(3),
sys_cpu[key]['physical_package_id'].center(13),
sys_cpu[key]['core_id'].center(9)), file=sys.stderr)
return 1
else:
return 0
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/rotation_test 0000775 0001750 0001750 00000004215 12646152433 023472 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# rotation_test
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Alberto Milone
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
import time
import sys
from checkbox_support.contrib import xrandr
def rotate_screen(rotation):
# Refresh the screen. Required by NVIDIA
screen = xrandr.get_current_screen()
screen.set_rotation(rotation)
return screen.apply_config()
def main():
screen = xrandr.get_current_screen()
rotations = {'normal': xrandr.RR_ROTATE_0,
'right': xrandr.RR_ROTATE_90,
'inverted': xrandr.RR_ROTATE_180,
'left': xrandr.RR_ROTATE_270}
rots_statuses = {}
for rot in rotations:
try:
status = rotate_screen(rotations[rot])
except (xrandr.RRError, xrandr.UnsupportedRRError) as exc:
status = 1
error = exc
else:
error = 'N/A'
# Collect the status and the error message
rots_statuses[rot] = (status, error)
time.sleep(4)
# Try to set the screen back to normal
try:
rotate_screen(xrandr.RR_ROTATE_0)
except(xrandr.RRError, xrandr.UnsupportedRRError) as error:
print(error)
result = 0
for elem in rots_statuses:
status = rots_statuses.get(elem)[0]
error = rots_statuses.get(elem)[1]
if status != 0:
print('Error: rotation "%s" failed with status %d: %s.' %
(elem, status, error), file=sys.stderr)
result = 1
return result
if __name__ == '__main__':
exit(main())
plainbox-provider-checkbox-0.25/bin/battery_test 0000775 0001750 0001750 00000014374 12646152433 023314 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import time
import re
import subprocess
import sys
import argparse
from gi.repository import Gio
class Battery():
def __init__(self, data):
lines = data.split("\n")
for line in lines:
if line.find("state:") != -1:
self._state = line.split(':')[1].strip()
elif line.find("energy:") != -1:
self._energy, self._energy_units = self._get_capacity(line)
elif line.find("energy-full:") != -1:
self._energy_full, self._energy_full_units =\
self._get_capacity(line)
elif line.find("energy-full-design:") != -1:
self._energy_full_design, self._energy_full_design_units =\
self._get_capacity(line)
def _get_capacity(self, line):
"""
Given a line of input that represents a battery capacity (energy)
value, return a tuple of (value, units). Value is returned as a
float.
"""
capacity = line.split(':')[1].strip()
values = capacity.split()
return (float(values[0]), values[1])
def __str__(self):
ret = "-----------------------------------------\n"
ret += "State: %s\n" % self._state
ret += "Energy: %s %s\n" % (self._energy, self._energy_units)
ret += "Energy Full: %s %s\n" % (self._energy_full,
self._energy_full_units)
ret += "Energy Full-Design: %s %s\n" % (self._energy_full_design,
self._energy_full_design_units)
return ret
def find_battery():
batinfo = subprocess.Popen('upower -d',
stdout=subprocess.PIPE, shell=True,
universal_newlines=True)
if not batinfo:
return None
else:
out, err = batinfo.communicate()
if out:
device_regex = re.compile("Device: (.*battery_.*)")
batteries = device_regex.findall(out)
if len(batteries) == 0:
return None
elif len(batteries) > 1:
print("Warning: This system has more than 1 battery, only the"
"first battery will be measured")
return batteries[0]
else:
return None
def get_battery_state():
battery_name = find_battery()
if battery_name is None:
return None
batinfo = subprocess.Popen('upower -i %s' % battery_name,
stdout=subprocess.PIPE, shell=True,
universal_newlines=True)
if not batinfo:
return None
else:
out, err = batinfo.communicate()
if out:
return Battery(out)
else:
return None
def validate_battery_info(battery):
if battery is None:
print ("Error obtaining battery info")
return False
if battery._state != "discharging":
print ("Error: battery is not discharging, test will not be valid")
return False
return True
def battery_life(before, after, time):
capacity_difference = before._energy - after._energy
print("Battery drained by %f %s" % (capacity_difference,
before._energy_units))
if capacity_difference == 0:
print("Battery capacity did not change, unable to determine remaining"
" time", file=sys.stderr)
return 1
drain_per_second = capacity_difference / time
print("Battery drained %f %s per second" % (drain_per_second,
before._energy_units))
# the battery at it's max design capacity (when it was brand new)
design_life_minutes = round(
((before._energy_full_design / drain_per_second) / 60), 2)
print("Battery Life with full battery at design capacity (when new): %.2f"
"minutes" % (design_life_minutes))
# the battery at it's current max capacity
current_full_life_minutes = round(
((before._energy_full / drain_per_second) / 60), 2)
print("Battery Life with a full battery at current capacity: %.2f minutes"
% (current_full_life_minutes))
# the battery at it's current capacity
current_life_minutes = round(
((before._energy / drain_per_second) / 60), 2)
print("Battery Life with at current battery capacity: %.2f minutes" %
(current_life_minutes))
return 0
def main():
parser = argparse.ArgumentParser(
description="""Determine battery drain and battery life by running
the specified action. Battery life is shown for:
current capacity, capacity when battery is full,
and capacity when battery is full and was brand new
(design capacity)""")
parser.add_argument('-i', '--idle', help="Run the test while system is"
" idling", action='store_true')
parser.add_argument('-s3', '--sleep', help="Run the test while system"
" is suspended", action='store_true')
parser.add_argument('-t', '--time',
help="Specify the allotted time in seconds to run",
type=int, required=True)
parser.add_argument('-m', '--movie',
help="Run the test while playing the file MOVIE")
args = parser.parse_args()
test_time = args.time
battery_before = get_battery_state()
if not validate_battery_info(battery_before):
return 1
print(battery_before)
if args.idle:
time.sleep(test_time)
elif args.movie:
totem_settings = Gio.Settings.new("org.gnome.totem")
totem_settings.set_boolean("repeat", True)
a = subprocess.Popen(['totem', '--fullscreen', args.movie])
time.sleep(test_time)
a.kill()
totem_settings = Gio.Settings.new("org.gnome.totem")
totem_settings.set_boolean("repeat", False)
elif args.sleep:
subprocess.call(['fwts', 's3', '--s3-sleep-delay=' + str(test_time)])
battery_after = get_battery_state()
if not validate_battery_info(battery_after):
return 1
print(battery_after)
return(battery_life(battery_before, battery_after, test_time))
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/bluetooth_transfer_stress 0000775 0001750 0001750 00000003601 12646152433 026106 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# Copyright (C) 2014 Canonical
#
# Authors:
# Daniel Manrique
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
BTDEVADDR="$1"
if [ -z "$BTDEVADDR" ]; then
echo "Please give Bluetooth device address as first parameter"
exit 1
fi
ORIGIN=$(mktemp --tmpdir bluetooth-stress.XXXXXX)
DESTINATION=$(mktemp --tmpdir bluetooth-stress.XXXXXX)
REMOTE=$RANDOM
SIZEKB=10240
echo "Creating ${SIZEKB}KB file to test transfer"
dd if=/dev/urandom of=$ORIGIN count=$SIZEKB bs=1024
ORIGIN_SUM=$(sha256sum $ORIGIN | cut -f 1 -d ' ')
set -o pipefail
echo "Sending file using Bluetooth"
time obexftp -v -b $BTDEVADDR -o $REMOTE --put $ORIGIN 2>&1 | ansi_parser
sleep 5
echo "Receiving file using Bluetooth"
time obexftp -v -b $BTDEVADDR -o $DESTINATION --get $REMOTE 2>&1 | ansi_parser
# Now checksum destination and compare
DESTINATION_SUM=$(sha256sum $DESTINATION | cut -f 1 -d ' ')
# Clean up before reporting
rm $ORIGIN $DESTINATION
if [ "$ORIGIN_SUM" = "$DESTINATION_SUM" ]; then
echo "Checksums match, file transfer succeeded"
exit 0
else
echo "Checksums don't match, file was corrupted during transfers."
echo "Original checksum: $ORIGIN_SUM"
echo "Checksum of received file: $DESTINATION_SUM"
exit 1
fi
plainbox-provider-checkbox-0.25/bin/cpu_offlining 0000775 0001750 0001750 00000002476 12646152433 023425 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
echo "Beginning CPU Offlining Test" 1>&2
result=0
cpu_count=0
# Turn CPU cores off
for cpu_num in `ls /sys/devices/system/cpu | grep -o cpu[0-9]*`; do
if [ -f /sys/devices/system/cpu/$cpu_num/online ]; then
if [ "$cpu_num" != "cpu0" ]; then
((cpu_count++))
echo "Offlining $cpu_num" 1>&2
echo 0 > /sys/devices/system/cpu/$cpu_num/online
grep -w -i -q $cpu_num /proc/interrupts
if [ $? -eq 0 ]; then
echo "ERROR: Failed to offline $cpu_num" 1>&2
result=1
fi
fi
fi
done
# Back on again
for cpu_num in `ls /sys/devices/system/cpu | grep -o cpu[0-9]*`; do
if [ -f /sys/devices/system/cpu/$cpu_num/online ]; then
if [ "$cpu_num" != "cpu0" ]; then
echo "Onlining $cpu_num" 1>&2
echo 1 > /sys/devices/system/cpu/$cpu_num/online
grep -w -i -q $cpu_num /proc/interrupts
if [ $? -eq 1 ]; then
echo "ERROR: Failed to online $cpu_num" 1>&2
result=1
fi
fi
fi
done
if [ $result -eq 0 ]; then
echo "Successfully turned $cpu_count cores off and back on"
else
echo "Error with offlining one or more cores. CPU offline may not work if this is an ARM system." 1>&2
fi
exit $result
plainbox-provider-checkbox-0.25/bin/memory_info 0000775 0001750 0001750 00000001304 12646152433 023113 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import re
import sys
def get_meminfo():
meminfo = {}
for line in open("/proc/meminfo").readlines():
match = re.match(r"(.*):\s+(.*)", line)
if match:
key = match.group(1)
value = match.group(2)
meminfo[key] = value
return meminfo
def main(args):
meminfo = get_meminfo()
amount, units = meminfo["MemTotal"].split()
amount = float(amount)
next_units = {'kB': 'MB',
'MB': 'GB'}
while amount > 1024:
amount = amount / 1024
units = next_units[units]
print("%.1f %s" % (amount, units))
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/audio_bluetooth_loopback_test 0000775 0001750 0001750 00000004161 12646152433 026673 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# This file is part of Checkbox.
#
# Copyright 2014 Canonical Ltd.
#
# Authors: Daniel Manrique
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
#
# This simple script finds a bluetooth source and sink, and records from the
# source for 6 seconds, playing the recording back into the sink. It helps a
# human validate that record/playback is working, human can speak into
# microphone and just ensure the speech can be heard instantly in the headset.
[ -x "`which pactl`" ] || exit 1
[ -x "`which pacat`" ] || exit 1
SINK=$(pactl list | sed -n '/monitor/d;s/Name: \(bluez_sink\.\)/\1/p')
SOURCE=$(pactl list | sed -n '/monitor/d;s/Name: \(bluez_source\.\)/\1/p')
if [ -n "$SINK" ] && [ -n "$SOURCE" ]; then
PLAYBACK_LOG=$(mktemp --tmpdir audio_bluetooth_loopback.XXXXX)
RECORD_LOG=$(mktemp --tmpdir audio_bluetooth_loopback.XXXXX)
trap "rm $PLAYBACK_LOG $RECORD_LOG" EXIT
# ensure we exit with failure if parec fails, and not with pacat
# --playback's error code
set -o pipefail
# Use a short latency parameter so time between speech and hearing it is
# short, makes for a nicer interactive experience
LATENCY="--latency-msec=50"
# time out after 6 seconds, forcibly kill after 8 seconds if pacat didn't
# respond
echo "Recording and playing back, please speak into bluetooth microphone"
timeout -k 8 6 pacat $LATENCY --record -v -d $SOURCE 2>$RECORD_LOG | \
pacat $LATENCY --playback -v -d $SINK 2>$PLAYBACK_LOG
echo "RECORD LOG"
cat $RECORD_LOG
echo ""
echo "PLAYBACK LOG"
cat $PLAYBACK_LOG
else
echo "No bluetooth audio device found"
exit 1
fi
plainbox-provider-checkbox-0.25/bin/tomcat_test 0000775 0001750 0001750 00000001042 12646152433 023115 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# Confirm Tomcat server is running and working properly
# Requires: tomcat6
#
# Check tomcat is running
run1=`netstat -ltnp | grep '8080' | grep 'java'`
if [ -z "$run1" ]; then
echo "FAIL: Tomcat is not running."
exit 1
fi
# Check if Tomcat is working; requires network connection so check it
check=`ping -c 2 www.ubuntu.com |grep "2 received"`
if [ -n "$check" ]; then
work1=`w3m http://127.0.0.1:8080 | grep "works"`
if [ -z "$work1" ]; then
echo "FAIL: Tomcat is not working properly."
exit 1
fi
fi
exit 0
plainbox-provider-checkbox-0.25/bin/run_templates 0000775 0001750 0001750 00000006733 12646152433 023465 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import re
import sys
import uuid
from optparse import OptionParser
from subprocess import Popen, PIPE
from checkbox_support.lib.template import Template
DEFAULT_INPUT = "-"
DEFAULT_OUTPUT = "-"
COMMAND_TEMPLATE = """cat <<%(separator)s
%(input)s
%(separator)s"""
class Runner(object):
def __init__(self, input, output):
self.input = input
self.output = output
def get_args(self, record):
return []
def get_env(self, record):
env = dict(os.environ)
env["NF"] = str(len(record))
return env
def process(self, args, shell=False):
process = Popen(
args, shell=shell, stdout=PIPE, universal_newlines=True)
records = self.process_output(process.stdout)
for nr, record in enumerate(records):
args = self.get_args(record)
env = self.get_env(record)
env["NR"] = str(nr)
command_string = COMMAND_TEMPLATE % {
"input": self.input,
"separator": uuid.uuid4()}
command = ["sh", "-c", command_string] + args
process = Popen(command,
env=env,
stdout=self.output,
universal_newlines=True)
process.communicate()
def process_output(self, output):
raise NotImplementedError
class LineRunner(Runner):
field_separator = r"\s+"
record_separator = r"(?:\r?\n)"
def get_args(self, record):
args = [record]
args.extend(re.split(self.field_separator, record))
return args
def process_output(self, file):
# Strip trailing separator
data = re.sub(r"%s$" % self.record_separator, "", file.read())
return re.split(self.record_separator, data)
class TemplateRunner(Runner):
def get_env(self, record):
env = super(TemplateRunner, self).get_env(record)
env.update(record)
return env
def process_output(self, output):
template = Template()
return template.load_file(output)
def main(args):
usage = "Usage: %prog [OPTIONS] [COMMAND]"
parser = OptionParser(usage=usage)
parser.add_option("-i", "--input",
metavar="FILE",
default=DEFAULT_INPUT,
help="Input from the given file name, - for stdin")
parser.add_option("-o", "--output",
metavar="FILE",
default=DEFAULT_OUTPUT,
help="Output to the given file name, - for stdout")
parser.add_option("-s", "--shell",
action="store_true",
help="Run the command as a shell script")
parser.add_option("-t", "--template",
action="store_true",
help="Interpret the command output as a template")
(options, args) = parser.parse_args(args)
# Default args to echo command
if not args:
args = ["echo"]
# Read input
if options.input == "-":
input = sys.stdin.read()
else:
input_file = open(options.input, "r")
try:
input = input_file.read()
finally:
input_file.close()
# Open output
if options.output == "-":
output_file = sys.stdout
else:
output_file = open(options.output, "w")
# Determine runner class
if options.template:
runner_class = TemplateRunner
else:
runner_class = LineRunner
runner = runner_class(input, output_file)
runner.process(args, options.shell)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/pm_log_check 0000775 0001750 0001750 00000020504 12646152433 023205 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
import re
import difflib
import logging
from argparse import ArgumentParser
# Script return codes
SUCCESS = 0
NOT_MATCH = 1
NOT_FINISHED = 2
NOT_FOUND = 3
def main():
args = parse_args()
if not os.path.isfile(args.input_log_filename):
sys.stderr.write('Log file {0!r} not found\n'
.format(args.input_log_filename))
sys.exit(NOT_FOUND)
LoggingConfiguration.set(args.log_level,
args.output_log_filename)
parser = Parser(args.input_log_filename)
results = parser.parse()
if not compare_results(results):
sys.exit(NOT_MATCH)
sys.exit(SUCCESS)
class Parser(object):
"""
Reboot test log file parser
"""
is_logging_line = (re.compile('^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}')
.search)
is_getting_info_line = (re.compile('Gathering hardware information...$')
.search)
is_executing_line = (re.compile("Executing: '(?P.*)'...$")
.search)
is_output_line = re.compile('Output:$').search
is_field_line = (re.compile('^- (?Preturncode|stdout|stderr):$')
.match)
is_test_complete_line = re.compile('test complete$').search
def __init__(self, filename):
self.filename = filename
def parse(self):
"""
Parse log file and return results
"""
with open(self.filename) as f:
results = self._parse_file(LineIterator(f))
return results
def _parse_file(self, iterator):
"""
Parse all lines in iterator and return results
"""
results = []
result = {}
for line in iterator:
if self.is_getting_info_line(line):
if result:
# Add last result to list of results
results.append(result)
# Initialize for a new iteration results
result = {}
match = self.is_executing_line(line)
if match:
command = match.group('command')
command_output = self._parse_command_output(iterator)
if command_output is not None:
result[command] = command_output
else:
if result:
# Add last result to list of results
results.append(result)
if not self.is_test_complete_line(line):
sys.stderr.write("Test didn't finish properly according to logs\n")
sys.exit(NOT_FINISHED)
return results
def _parse_command_output(self, iterator):
"""
Parse one command output
"""
command_output = None
# Skip all lines until command output is found
for line in iterator:
if self.is_output_line(line):
command_output = {}
break
if (self.is_executing_line(line)
or self.is_getting_info_line(line)):
# Skip commands with no output
iterator.unnext(line)
return None
# Parse command output message
for line in iterator:
match = self.is_field_line(line)
if match:
field = match.group('field')
value = self._parse_command_output_field(iterator)
command_output[field] = value
# Exit when all command output fields
# have been gathered
else:
iterator.unnext(line)
break
return command_output
def _parse_command_output_field(self, iterator):
"""
Parse one command output field
"""
# Accummulate as many lines as needed
# for the field value
value = []
for line in iterator:
if (self.is_logging_line(line)
or self.is_field_line(line)):
iterator.unnext(line)
break
value.append(line)
value = ''.join(value)
return value
class LineIterator:
"""
Iterator wrapper to make it possible
to push back lines that shouldn't have been consumed
"""
def __init__(self, iterator):
self.iterator = iterator
self.buffer = []
def __iter__(self):
return self
def __next__(self):
if self.buffer:
return self.buffer.pop()
return next(self.iterator)
def unnext(self, line):
self.buffer.append(line)
class LoggingConfiguration(object):
@classmethod
def set(cls, log_level, log_filename):
"""
Configure a rotating file logger
"""
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# Log to sys.stderr using log level passed through command line
if log_level != logging.NOTSET:
log_handler = logging.StreamHandler()
formatter = logging.Formatter('%(levelname)-8s %(message)s')
log_handler.setFormatter(formatter)
log_handler.setLevel(log_level)
logger.addHandler(log_handler)
# Log to rotating file using DEBUG log level
log_handler = logging.FileHandler(log_filename, mode='w')
formatter = logging.Formatter('%(asctime)s %(levelname)-8s '
'%(message)s')
log_handler.setFormatter(formatter)
log_handler.setLevel(logging.DEBUG)
logger.addHandler(log_handler)
def compare_results(results):
"""
Compare results using first one as a baseline
"""
baseline = results[0]
success = True
for index, result in enumerate(results[1:]):
for command in baseline.keys():
baseline_output = baseline[command]
result_output = result[command]
error_messages = []
fields = (set(baseline_output.keys())
| set(result_output.keys()))
for field in fields:
baseline_field = baseline_output.get(field, '')
result_field = result_output.get(field, '')
if baseline_field != result_field:
differ = difflib.Differ()
message = ["** {field!r} field doesn't match:"
.format(field=field)]
comparison = differ.compare(baseline_field.splitlines(),
result_field.splitlines())
message.extend(list(comparison))
error_messages.append('\n'.join(message))
if not error_messages:
logging.debug('[Iteration {0}] {1}...\t[OK]'
.format(index + 1, command))
else:
success = False
if command.startswith('fwts'):
logging.error('[Iteration {0}] {1}...\t[FAIL]'
.format(index + 1, command))
else:
logging.error('[Iteration {0}] {1}...\t[FAIL]\n'
.format(index + 1, command))
for message in error_messages:
logging.error(message)
return success
def parse_args():
"""
Parse command-line arguments
"""
parser = ArgumentParser(description=('Check power management '
'test case results'))
parser.add_argument('input_log_filename', metavar='log_filename',
help=('Path to the input log file '
'on which to perform the check'))
parser.add_argument('output_log_filename', metavar='log_filename',
help=('Path to the output log file '
'for the results of the check'))
log_levels = ['notset', 'debug', 'info', 'warning', 'error', 'critical']
parser.add_argument('--log-level', dest='log_level', default='info',
choices=log_levels,
help=('Log level. '
'One of {0} or {1} (%(default)s by default)'
.format(', '.join(log_levels[:-1]),
log_levels[-1])))
args = parser.parse_args()
args.log_level = getattr(logging, args.log_level.upper())
return args
if __name__ == '__main__':
main()
plainbox-provider-checkbox-0.25/bin/network_wait 0000775 0001750 0001750 00000000703 12646152433 023307 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
x=1
while true; do
state=$(/usr/bin/nmcli -t -f STATE nm 2>/dev/null)
if [[ $? != 0 ]]; then
state=$(/usr/bin/nmcli -t -f STATE general 2>/dev/null)
rc=$?
if [[ $rc != 0 ]]; then
exit $rc
fi
fi
if [ "$state" = "connected" ]; then
echo $state
exit 0
fi
x=$(($x + 1))
if [ $x -gt 12 ]; then
echo $state
exit 1
fi
sleep 5
done
plainbox-provider-checkbox-0.25/bin/xml_sanitize 0000775 0001750 0001750 00000002576 12646152433 023312 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
import errno
import io
import sys
from argparse import ArgumentParser, FileType
VALID_XML_CHARS = frozenset([0x9, 0xA, 0xD] +
list(range(0x20, 0xD7FF)) +
list(range(0xE000, 0xFFFD)) +
list(range(0x10000, 0x10FFFF)))
def is_valid_xml_char(ch):
# Is this character valid in XML?
# http://www.w3.org/TR/xml/#charsets
return ord(ch) in VALID_XML_CHARS
def main():
parser = ArgumentParser("Receives as input some text and outputs "
"the same text without characters which are "
"not valid in the XML specification.")
parser.add_argument('input_file',
type=FileType('r'),
nargs='?',
help='The name of the file to sanitize.')
args = parser.parse_args()
if args.input_file:
text = ''.join([c for c in args.input_file.read() if
is_valid_xml_char(c)])
else:
with io.TextIOWrapper(
sys.stdin.buffer, encoding='UTF-8', errors="ignore") as stdin:
text = ''.join([c for c in stdin.read() if is_valid_xml_char(c)])
print(text)
if __name__ == "__main__":
try:
sys.exit(main())
except Exception as err:
if err.errno != errno.EPIPE:
raise(err)
plainbox-provider-checkbox-0.25/bin/storage_test 0000775 0001750 0001750 00000005673 12646152433 023310 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
# take the path of the storage device and test is it a block device.
function run_bonnie() {
echo "Running bonnie++ on $1..."
mount_point=$(df -h | grep -m 1 $1 | awk '{print $6}')
echo "Putting scratch disk at $mount_point"
mkdir -p "$mount_point/tmp/scratchdir"
# When running on disks with small drives (SSD/flash) we need to do
# some tweaking. Bonnie uses 2x RAM by default to write data. If that's
# more than available disk space, the test will fail inappropriately.
free_space=$(df -m | grep -m 1 $1 | awk '{print $4}')
echo " Disk $1 has ${free_space}MB available"
memory=$(free -m |grep Mem|awk '{print $2}')
echo " System has ${memory}MB RAM"
disk_needed=$((memory * 2))
echo " We need ${disk_needed}MB of disk space for testing"
if [[ "$disk_needed" -ge "$free_space" ]]; then
echo " Insufficient disk space available for defaults."
echo " reducing memory footprint to be 1/2 of free disk space."
# we need to pass an amount that's 1/2 the amount of available disk
# space to bonnie++ so she doesn't overwrite and fail.
disk_needed=$(($free_space/2))
bonnie++ -d $mount_point/tmp/scratchdir -u root -r $disk_needed
else
echo " Free disk space is sufficient to continue testing."
bonnie++ -d $mount_point/tmp/scratchdir -u root
fi
}
disk=/dev/$1
if [ -b $disk ]
then
echo "$disk is a block device"
#Add a check for warnings
WARN=$(parted -s ${disk} print | grep "^Warning.*${disk}.*[Rr]ead-only" 2>&1)
if [[ $? == 0 ]]
then
echo "Warning found in parted output:"
echo $WARN
echo "Aborting Test"
exit 1
fi
# Regex changed to better handle when $disk appears more than once
# in parted output (such as in warning messages or not caught in the
# check above)
size=`parted -l -s |grep "Disk.*${disk}" |awk '{print $3}'`
if [ -n "$size" ]
then
echo "$disk reports a size of $size."
# Have to account for the end of the size descriptor
size_range=${size:(-2)}
if mount | grep -q $disk
then
echo "$disk is mounted, proceeding."
else
echo "$disk is not mounted. It must be mounted before testing."
exit 1
fi
if [ $size_range == "KB" ]
then
echo "$disk size reported in KB, seems to be too small for testing."
exit 1
elif [ $size_range == "MB" ]
then
size_int=${size::${#size}-2}
if [ $size_int -gt 10 ]
then
run_bonnie $disk
else
echo "$disk is too small to be used for testing."
exit 1
fi
else
run_bonnie $disk
fi
else
echo "$disk doesn't report a size."
exit 1
fi
else
echo "$disk is not listed as a block device."
exit 1
fi
plainbox-provider-checkbox-0.25/bin/optical_detect 0000775 0001750 0001750 00000001150 12646152433 023552 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import re
import sys
def main(args):
line_pattern = r"\s*(\d+)\s+dev='([^']+)'" \
"\s+([wr-]{6})\s:\s'([^']+)'\s'([^']+)'"
line_regex = re.compile(line_pattern)
count = 0
command = "wodim --devices"
for line in os.popen(command).readlines():
match = re.match(line_regex, line)
if match:
count += 1
print(match.group(4), match.group(5))
if not count:
print("No optical devices detected.", file=sys.stderr)
return 1
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/gcov_tarball 0000775 0001750 0001750 00000000230 12646152433 023224 0 ustar sylvain sylvain 0000000 0000000 #!/bin/sh
set -o errexit
cd /usr/share
tar -xzf gcov.tar.gz
cd /tmp
lcov -q -c -o gcov.info
genhtml -q -o gcov gcov.info 2>/dev/null
tar -czf - gcov
plainbox-provider-checkbox-0.25/bin/bluetooth_test 0000775 0001750 0001750 00000012574 12646152433 023647 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
from subprocess import CalledProcessError, check_output, STDOUT
from tempfile import TemporaryDirectory
import argparse
import logging
import os
import re
import sys
import time
OBEX_RESPONSE_CODE = {
0x10: "Continue",
0x20: "OK, Success",
0x21: "Created",
0x22: "Accepted",
0x23: "Non-Authoritative Information",
0x24: "No Content",
0x25: "Reset Content",
0x26: "Partial Content",
0x30: "Multiple Choices",
0x31: "Moved Permanently",
0x32: "Moved temporarily",
0x33: "See Other",
0x34: "Not modified",
0x35: "Use Proxy",
0x40: "Bad Request - server couldn't understand request",
0x41: "Unauthorized",
0x42: "Payment required",
0x43: "Forbidden - operation is understood but refused",
0x44: "Not Found",
0x45: "Method not allowed",
0x46: "Not Acceptable",
0x47: "Proxy Authentication required",
0x48: "Request Time Out",
0x49: "Conflict",
0x4A: "Gone",
0x4B: "Length Required",
0x4C: "Precondition failed",
0x4D: "Requested entity too large",
0x4E: "Request URL too large",
0x4F: "Unsupported media type",
0x50: "Internal Server Error",
0x51: "Not Implemented",
0x52: "Bad Gateway",
0x53: "Service Unavailable",
0x54: "Gateway Timeout",
0x55: "HTTP version not supported",
0x60: "Database Full",
0x61: "Database Locked"
}
class ObexFTPTest:
def __init__(self, path, btaddr):
self._file = path
self._filename = os.path.basename(path)
self._filesize = os.path.getsize(path)
self._btaddr = btaddr
def _error_helper(self, pattern, **extra):
# obexftp 0.23 version returns 255 on success, see:
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549623
if 'exception' in extra:
exception = extra.get('exception')
if re.search(pattern, exception.output):
logging.info("PASS")
return 0
else:
logging.error(exception.output.strip())
if exception.returncode in OBEX_RESPONSE_CODE:
logging.error(OBEX_RESPONSE_CODE.get(exception.returncode))
return exception.returncode
elif 'output' in extra:
output = extra.get('output')
if re.search(pattern, output):
logging.info("PASS")
return 0
else:
logging.error(output)
return 1
def _run_command(self, command, expected_pattern, cwd=None):
try:
output = check_output(command, stderr=STDOUT,
universal_newlines=True, cwd=cwd)
return self._error_helper(expected_pattern, output=output)
except OSError as e:
logging.error(e)
logging.error("Binary not found, "
"maybe obexftp is not installed")
except CalledProcessError as e:
return self._error_helper(expected_pattern, exception=e)
finally:
# Let the Bluetooth stack enough time to close the connection
# before doing another test
time.sleep(5)
def send(self):
logging.info("[ Send test ]".center(80, '='))
logging.info("Using {} as a test file".format(self._filename))
logging.info("Sending {} to {}".format(self._file, self._btaddr))
return self._run_command(["obexput", "-b", self._btaddr, self._file],
"Sending.*?done")
def browse(self):
logging.info("[ Browse test ]".center(80, '='))
logging.info("Checking {} for {}".format(self._btaddr, self._file))
logging.info("Will check for a filesize of {}".format(self._filesize))
return self._run_command(["obexftp", "-b", self._btaddr, "-l"],
'{}.*?size="{}"'.format(self._filename,
self._filesize))
def remove(self):
logging.info("[ Remove test ]".center(80, '='))
logging.info("Removing {} from {}".format(self._filename,
self._btaddr))
return self._run_command(
["obexrm", "-b", self._btaddr, self._filename],
"Sending.*?done")
def get(self):
with TemporaryDirectory() as tmpdirname:
logging.info("[ Get test ]".center(80, '='))
logging.info("Getting file {} from {}".format(self._filename,
self._btaddr))
# Dont trust "get" returncode, it's always 0...
return self._run_command(
["obexget", "-b", self._btaddr, self._filename],
"Receiving.*?done", cwd=tmpdirname)
def main():
description = "Bluetooth tests using ObexFTP"
parser = argparse.ArgumentParser(description=description)
parser.add_argument('file', type=argparse.FileType('rb'))
parser.add_argument('btaddr', help='bluetooth mac address')
parser.add_argument('action', choices=['send', 'browse', 'remove', 'get'])
args = parser.parse_args()
args.file.close()
# Configure logging as requested
logging.basicConfig(
level=logging.INFO,
stream=sys.stdout,
format='%(levelname)s: %(message)s')
return getattr(ObexFTPTest(args.file.name, args.btaddr), args.action)()
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/memory_compare 0000775 0001750 0001750 00000010306 12646152433 023610 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# This file is part of Checkbox.
#
# Copyright 2014 Canonical Ltd.
#
# Authors:
# Brendan Donegan
# Jeff Lane
# Sylvain Pineau
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
import os
import sys
import re
from math import log, copysign
from subprocess import check_output, PIPE
from checkbox_support.helpers.human_readable_bytes import HumanReadableBytes
from checkbox_support.parsers.lshwjson import LshwJsonParser
from checkbox_support.parsers.meminfo import MeminfoParser
class LshwJsonResult:
memory_reported = 0
banks_reported = 0
# jlane LP:1525009
# Discovered the case can change, my x86 systems used "System Memory"
# Failing ARM system used "System memory"
desc_regex = re.compile('System Memory', re.IGNORECASE)
def addHardware(self, hardware):
if self.desc_regex.match(str(hardware.get('description',0))):
self.memory_reported += int(hardware.get('size', 0))
elif 'bank' in hardware['id']:
self.banks_reported += int(hardware.get('size', 0))
def get_installed_memory_size():
lshw = LshwJsonParser(check_output(['lshw', '-json'],
universal_newlines=True,
stderr=PIPE))
result = LshwJsonResult()
lshw.run(result)
if result.memory_reported:
return result.memory_reported
else:
return result.banks_reported
class MeminfoResult:
memtotal = 0
def setMemory(self, memory):
self.memtotal = memory['total']
def get_visible_memory_size():
parser = MeminfoParser(open('/proc/meminfo'))
result = MeminfoResult()
parser.run(result)
return result.memtotal
def get_threshold(installed_memory):
GB = 1024**3
if installed_memory <= 2 * GB:
return 25
elif installed_memory <= 6 * GB:
return 20
else:
return 10
def main():
if os.geteuid() != 0:
print("This script must be run as root.", file=sys.stderr)
return 1
installed_memory = HumanReadableBytes(get_installed_memory_size())
visible_memory = HumanReadableBytes(get_visible_memory_size())
threshold = get_threshold(installed_memory)
difference = HumanReadableBytes(installed_memory - visible_memory)
try:
percentage = difference / installed_memory * 100
except ZeroDivisionError:
print("Results:")
print("\t/proc/meminfo reports:\t{}".format(visible_memory),
file=sys.stderr)
print("\tlshw reports:\t{}".format(installed_memory),
file=sys.stderr)
print("\nFAIL: Either lshw or /proc/meminfo returned a memory size "
"of 0 kB", file=sys.stderr)
return 1
if percentage <= threshold:
print("Results:")
print("\t/proc/meminfo reports:\t{}".format(visible_memory))
print("\tlshw reports:\t{}".format(installed_memory))
print("\nPASS: Meminfo reports %s less than lshw, a "
"difference of %.2f%%. This is less than the "
"%d%% variance allowed." % (difference, percentage, threshold))
return 0
else:
print("Results:", file=sys.stderr)
print("\t/proc/meminfo reports:\t{}".format(visible_memory),
file=sys.stderr)
print("\tlshw reports:\t{}".format(installed_memory), file=sys.stderr)
print("\nFAIL: Meminfo reports %d less than lshw, "
"a difference of %.2f%%. Only a variance of %d%% in "
"reported memory is allowed." %
(difference, percentage, threshold), file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/volume_test 0000775 0001750 0001750 00000012133 12646152433 023140 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
import sys
import re
from argparse import ArgumentParser
from subprocess import check_output
TYPES = ("source", "sink")
active_entries_regex = re.compile("\* index.*?(?=properties)", re.DOTALL)
entries_regex = re.compile("index.*?(?=properties)", re.DOTALL)
index_regex = re.compile("(?<=index: )[0-9]*")
muted_regex = re.compile("(?<=muted: ).*")
volume_regex = re.compile("(?<=volume: 0: )\s*[0-9]*")
name_regex = re.compile("(?<=name:).*")
def check_muted():
"""
Checks that the active source/sink are not muted. This does not test
inactive sources/sinks.
"""
retval = 0
for vtype in TYPES:
try:
pacmd_entries = check_output(["pacmd", "list-%ss" % vtype],
universal_newlines=True)
except Exception as e:
print("Error when running pacmd list-%ss: %s" % (vtype, e),
file=sys.stderr)
return 1
active_entry_match = active_entries_regex.search(pacmd_entries)
if active_entry_match:
active_entry = active_entry_match.group()
else:
print("Unable to find a %s active_entry in the pacmd list-%ss"\
" output\npacmd output was: %s" %
(vtype, vtype, pacmd_entries), file=sys.stderr)
return 1
name_match = name_regex.search(active_entry)
if name_match:
name = name_match.group()
else:
print("Unable to determine device bus information from the"\
" pacmd list-%ss output\npacmd output was: %s" %
(vtype, pacmd_entries), file=sys.stderr)
return 1
muted_match = muted_regex.search(active_entry)
if muted_match:
muted = muted_match.group().strip()
if muted.lower() == "yes":
print("FAIL: Audio is muted on %s %s" % (name, vtype))
retval = 1
else:
print("PASS: Audio is not muted on %s %s" % (name, vtype))
else:
print("Unable to find mute information in the pacmd list-%ss"\
" output for device %s\npacmd output was: %s" %
(vtype, name, pacmd_entries), file=sys.stderr)
return 1
return retval
def check_volume(minvol, maxvol):
"""
Checks that the volume for all sources/sinks is between min and max.
Volume must be < min and > max to pass.
"""
retval = 0
for vtype in TYPES:
try:
pacmd_entries = check_output(["pacmd", "list-%ss" % vtype],
universal_newlines=True)
except Exception as e:
print("Error when running pacmd list-%ss: %s" % (vtype, e),
file=sys.stderr)
return 1
entries = entries_regex.findall(pacmd_entries)
for entry in entries:
name_match = name_regex.search(entry)
if name_match:
name = name_match.group()
else:
print("Unable to determine device bus information from the"\
" pacmd list-%ss output\npacmd output was: %s" %
(vtype, pacmd_entries), file=sys.stderr)
return 1
volume_match = volume_regex.search(entry)
if volume_match:
volume = int(volume_match.group().strip())
if volume > maxvol:
print ("FAIL: Volume of %d is greater than"\
" maximum of %d for %s %s" % (volume, maxvol,
name, vtype))
retval = 1
elif volume < minvol:
print ("FAIL: Volume of %d is less than"\
" minimum of %d for %s %s" % (volume, minvol,
name, vtype))
retval = 1
else:
print ("PASS: Volume is %d for %s %s" % (volume, name,
vtype))
else:
print("Unable to find volume information in the pacmd"\
" list-%ss output for device %s.\npacmd output "\
"was: %s" %
(vtype, name, pacmd_entries), file=sys.stderr)
return 1
return retval
def main():
parser = ArgumentParser("Check the audio volume")
parser.add_argument("-n", "--minvol", type=int, required=True,
help="""The minimum volume for a check_volume call.
Volume must be greater than this number to
be considered a pass.""")
parser.add_argument("-x", "--maxvol", type=int, required=True,
help="""The maximum volume for a check_volume call.
Volume must be less than this number to
be considered a pass.""")
args = parser.parse_args()
check_muted_retval = check_muted()
check_volume_retval = check_volume(args.minvol, args.maxvol)
return check_muted_retval or check_volume_retval
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/check_is_laptop 0000775 0001750 0001750 00000000774 12646152433 023731 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
# Establish the system type based on DMI info
TYPE=$(dmidecode -t 3 | awk '/Type:/ { print $2 }')
echo "Type: " $TYPE
BATTERY="NO"
for device in `find /sys -name "type"`
do
if [ "$(cat $device)" == "Battery" ]; then
BATTERY="YES"
fi
done
echo "Battery: " $BATTERY
case $TYPE in
Notebook|Laptop|Portable)
exit 0
;;
*)
# Give the system a second chance based on the battery info
if [ $BATTERY == "YES" ]; then
exit 0
else
exit 1
fi
;;
esac
plainbox-provider-checkbox-0.25/bin/max_diskspace_used 0000775 0001750 0001750 00000001560 12646152433 024427 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
# Verify default partitioning has used the entire local hard disk.
# Please remove any non-local attached storage prior to running this
# test.
for disk in $@; do
echo "Checking maximum disk space available on : $disk"
psize=`parted -l | grep $disk | awk '{print $3}'`
if [ -n "$psize" ]
then
echo "Disk space available : $psize"
fsizes=`df -B ${psize:(-2)} | grep $disk | awk '{print $2}'`
if [ -n "$fsizes" ]
then
echo "Disk space used : $fsizes"
fsize=0
for i in $fsizes; do
i=`echo $i | grep -oe '[0-9\.]*'`
fsize=$(($fsize + $i))
done
psize=`echo $psize | grep -oe '[0-9\.]*'`
pct_difference=`awk "BEGIN{print(($psize - $fsize) / $fsize)}"`
echo "Difference ( > 0.15 fails ) : $pct_difference"
awk "BEGIN{exit($pct_difference > 0.15)}" || exit 1
fi
fi
done
plainbox-provider-checkbox-0.25/bin/graphics_stress_test 0000775 0001750 0001750 00000036744 12646152433 025052 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# graphics_stress_test
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Alberto Milone
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
import errno
import logging
import os
import re
import sys
import tempfile
import time
from argparse import ArgumentParser
from subprocess import call, Popen, PIPE
from checkbox_support.contrib import xrandr
class VtWrapper(object):
"""docstring for VtWrapper"""
def __init__(self):
self.x_vt = self._get_x_vt()
def _get_x_vt(self):
'''Get the vt where X lives'''
vt = 0
proc = Popen(['ps', 'aux'], stdout=PIPE, universal_newlines=True)
proc_output = proc.communicate()[0].split('\n')
proc_line = re.compile('.*tty(\d+).+/usr/bin/X.*')
for line in proc_output:
match = proc_line.match(line)
if match:
vt = match.group(1).strip().lower()
return int(vt)
def set_vt(self, vt):
retcode = call(['chvt', '%d' % vt])
return retcode
class SuspendWrapper(object):
def __init__(self):
pass
def can_we_sleep(self, mode):
'''
Test to see if S3 state is available to us. /proc/acpi/* is old
and will be deprecated, using /sys/power to maintine usefulness for
future kernels.
'''
states_fh = open('/sys/power/state', 'r')
try:
states = states_fh.read().split()
finally:
states_fh.close()
if mode in states:
return True
else:
return False
def get_current_time(self):
cur_time = 0
time_fh = open('/sys/class/rtc/rtc0/since_epoch', 'r')
try:
cur_time = int(time_fh.read())
finally:
time_fh.close()
return cur_time
def set_wake_time(self, time):
'''
Get the current epoch time from /sys/class/rtc/rtc0/since_epoch
then add time and write our new wake_alarm time to
/sys/class/rtc/rtc0/wakealarm.
The math could probably be done better but this method avoids having to
worry about whether or not we're using UTC or local time for both the
hardware and system clocks.
'''
cur_time = self.get_current_time()
logging.debug('Current epoch time: %s' % cur_time)
wakealarm_fh = open('/sys/class/rtc/rtc0/wakealarm', 'w')
try:
wakealarm_fh.write('0\n')
wakealarm_fh.flush()
wakealarm_fh.write('+%s\n' % time)
wakealarm_fh.flush()
finally:
wakealarm_fh.close()
logging.debug('Wake alarm in %s seconds' % time)
def do_suspend(self, mode):
'''
Suspend the system and hope it wakes up.
Previously tried writing new state to /sys/power/state but that
seems to put the system into an uncrecoverable S3 state. So far,
pm-suspend seems to be the most reliable way to go.
'''
if mode == 'mem':
status = call('/usr/sbin/pm-suspend')
elif mode == 'disk':
status = call('/usr/sbin/pm-hibernate')
else:
logging.debug('Unknown sleep state passed')
status == 1
return status
class RotationWrapper(object):
def __init__(self):
self._rotations = {'normal': xrandr.RR_ROTATE_0,
'right': xrandr.RR_ROTATE_90,
'inverted': xrandr.RR_ROTATE_180,
'left': xrandr.RR_ROTATE_270}
def _rotate_screen(self, rotation):
# Refresh the screen. Required by NVIDIA
screen = xrandr.get_current_screen()
screen.set_rotation(rotation)
return screen.apply_config()
def do_rotation_cycle(self):
'''Cycle through all possible rotations'''
rots_statuses = {}
for rot in self._rotations:
try:
status = self._rotate_screen(self._rotations[rot])
except(xrandr.RRError, xrandr.UnsupportedRRError) as err:
status = 1
error = err
else:
error = 'N/A'
# Collect the status and the error message
rots_statuses[rot] = (status, error)
time.sleep(4)
# Try to set the screen back to normal
try:
self._rotate_screen(xrandr.RR_ROTATE_0)
except(xrandr.RRError, xrandr.UnsupportedRRError) as error:
print(error)
result = 0
for elem in rots_statuses:
status = rots_statuses.get(elem)[0]
error = rots_statuses.get(elem)[1]
if status != 0:
logging.error('Error: rotation "%s" failed with status %d: %s.'
% (elem, status, error))
result = 1
return result
class RenderCheckWrapper(object):
"""A simple class to run the rendercheck suites"""
def __init__(self, temp_dir=None):
self._temp_dir = temp_dir
def _print_test_info(self, suites='all', iteration=1, show_errors=False):
'''Print the output of the test suite'''
main_command = 'rendercheck'
passed = 0
total = 0
if self._temp_dir:
# Use the specified path
temp_file = tempfile.NamedTemporaryFile(dir=self._temp_dir,
delete=False)
else:
# Use /tmp
temp_file = tempfile.NamedTemporaryFile(delete=False)
if suites == all:
full_command = [main_command, '-f', 'a8r8g8b8']
else:
full_command = [main_command, '-t', suites, '-f', 'a8r8g8b8']
try:
# Let's dump the output into file as it can be very large
# and we don't want to store it in memory
process = Popen(full_command, stdout=temp_file,
universal_newlines=True)
except OSError as exc:
if exc.errno == errno.ENOENT:
logging.error('Error: please make sure that rendercheck '
'is installed.')
exit(1)
else:
raise
exit_code = process.wait()
temp_file.close()
# Read values from the file
errors = re.compile('.*test error.*')
results = re.compile('(.+) tests passed of (.+) total.*')
first_error = True
with open(temp_file.name) as temp_handle:
for line in temp_handle:
match_output = results.match(line)
match_errors = errors.match(line)
if match_output:
passed = int(match_output.group(1).strip())
total = int(match_output.group(2).strip())
logging.info('Results:')
logging.info(' %d tests passed out of %d.'
% (passed, total))
if show_errors and match_errors:
error = match_errors.group(0).strip()
if first_error:
logging.debug('Rendercheck %s suite errors '
'from iteration %d:'
% (suites, iteration))
first_error = False
logging.debug(' %s' % error)
# Remove the file
os.unlink(temp_file.name)
return (exit_code, passed, total)
def run_test(self, suites=[], iterations=1, show_errors=False):
exit_status = 0
for suite in suites:
for it in range(iterations):
logging.info('Iteration %d of Rendercheck %s suite...'
% (it + 1, suite))
(status, passed, total) = \
self._print_test_info(suites=suite,
iteration=it + 1,
show_errors=show_errors)
if status != 0:
# Make sure to catch a non-zero exit status
logging.info('Iteration %d of Rendercheck %s suite '
'exited with status %d.'
% (it + 1, suite, status))
exit_status = status
it += 1
# exit with 1 if passed < total
if passed < total:
if exit_status == 0:
exit_status = 1
return exit_status
def get_suites_list(self):
'''Return a list of the available test suites'''
try:
process = Popen(['rendercheck', '--help'], stdout=PIPE,
stderr=PIPE, universal_newlines=True)
except OSError as exc:
if exc.errno == errno.ENOENT:
logging.error('Error: please make sure that rendercheck '
'is installed.')
exit(1)
else:
raise
proc = process.communicate()[1].split('\n')
found = False
tests_pattern = re.compile('.*Available tests: *(.+).*')
temp_line = ''
tests = []
for line in proc:
if found:
temp_line += line
match = tests_pattern.match(line)
if match:
first_line = match.group(1).strip().lower()
found = True
temp_line += first_line
for elem in temp_line.split(','):
test = elem.strip()
if elem:
tests.append(test)
return tests
def main():
# Make sure that we have root privileges
if os.geteuid() != 0:
print('Error: please run this program as root',
file=sys.stderr)
exit(1)
usage = 'Usage: %prog [OPTIONS]'
parser = ArgumentParser(usage)
parser.add_argument('-i', '--iterations',
type=int,
default=10,
help='The number of times to run the test. \
Default is 10')
parser.add_argument('-d', '--debug',
action='store_true',
help='Choose this to add verbose output \
for debug purposes')
parser.add_argument('-b', '--blacklist',
nargs='+',
help='Name(s) of rendercheck test(s) to blacklist.')
parser.add_argument('-o', '--output',
default='',
help='The path to the log which will be dumped. \
Default is stdout')
parser.add_argument('-tp', '--temp',
default='',
help='The path where to store temporary files. \
Default is /tmp')
args = parser.parse_args()
# Set up logging to console
format = '%(message)s'
console_handler = logging.StreamHandler()
console_handler.setFormatter(logging.Formatter(format))
# Set up the overall logger
logger = logging.getLogger()
# This is necessary to ensure debug messages are passed through the logger
# to the handler
logger.setLevel(logging.DEBUG)
# This is what happens when -d and/or -o are passed:
# -o -> stdout (info) - log (info)
# -d -> only stdout (info and debug) - no log
# -d -o -> stdout (info) - log (info and debug)
# Write to a log
if args.output:
# Write INFO to stdout
console_handler.setLevel(logging.INFO)
logger.addHandler(console_handler)
# Specify a log file
logfile = args.output
logfile_handler = logging.FileHandler(logfile)
if args.debug:
# Write INFO and DEBUG to a log
logfile_handler.setLevel(logging.DEBUG)
else:
# Write INFO to a log
logfile_handler.setLevel(logging.INFO)
logfile_handler.setFormatter(logging.Formatter(format))
logger.addHandler(logfile_handler)
log_path = os.path.abspath(logfile)
# Write only to stdout
else:
if args.debug:
# Write INFO and DEBUG to stdout
console_handler.setLevel(logging.DEBUG)
logger.addHandler(console_handler)
else:
# Write INFO to stdout
console_handler.setLevel(logging.INFO)
logger.addHandler(console_handler)
status = 0
rendercheck = RenderCheckWrapper(args.temp)
tests = rendercheck.get_suites_list()
for test in args.blacklist:
if test in tests:
tests.remove(test)
# Switch between the tty where X lives and tty10
vt_wrap = VtWrapper()
target_vt = 10
if vt_wrap.x_vt != target_vt:
logging.info('== Vt switch test ==')
for it in range(args.iterations):
logging.info('Iteration %d...', it)
retcode = vt_wrap.set_vt(target_vt)
if retcode != 0:
logging.error('Error: switching to tty%d failed with code %d '
'on iteration %d' % (target_vt, retcode, it))
status = 1
else:
logging.info('Switching to tty%d: passed' % (target_vt))
time.sleep(2)
retcode = vt_wrap.set_vt(vt_wrap.x_vt)
if retcode != 0:
logging.error('Error: switching to tty%d failed with code %d '
'on iteration %d' % (vt_wrap.x_vt, retcode, it))
else:
logging.info('Switching to tty%d: passed' % (vt_wrap.x_vt))
status = 1
else:
logging.error('Error: please run X on a tty other than 10')
# Call sleep x times
logging.info('== Sleep test ==')
sleep_test = SuspendWrapper()
sleep_mode = 'mem'
# See if we can sleep
if sleep_test.can_we_sleep(sleep_mode):
for it in range(args.iterations):
# Run the test
logging.info('Iteration %d...', it + 1)
# Set wake time
sleep_test.set_wake_time(20)
# Suspend to RAM
if sleep_test.do_suspend(sleep_mode) == 0:
logging.info('Passed')
else:
logging.error('Failed')
status = 1
else:
# Skip the test
logging.info('Skipped (the system does not seem to support S3')
# Rotate the screen x times
# The app already rotates the screen 5 times
logging.info('== Rotation test ==')
rotation_test = RotationWrapper()
for it in range(args.iterations):
logging.info('Iteration %d...', it + 1)
if rotation_test.do_rotation_cycle() == 0:
logging.info('Passed')
else:
logging.error('Failed')
status = 1
# Call rendercheck x times
logging.info('== Rendercheck test ==')
if rendercheck.run_test(tests, args.iterations,
args.debug) == 0:
logging.info('Passed')
else:
logging.error('Failed')
status = 1
return status
if __name__ == '__main__':
exit(main())
plainbox-provider-checkbox-0.25/bin/ipmi_test 0000775 0001750 0001750 00000002507 12646152433 022573 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
# Now make sure the modules are loaded
for module in ipmi_si ipmi_devintf ipmi_msghandler; do
if lsmod |grep -q $module; then
echo "$module already loaded"
else
echo "Loading $module..."
modprobe $module
result=$?
# If the IPMI drivers don't load, it could be the system has no BMC, or
# the IPMI driver is bad. We should error and Fail here.
if [ $result -eq 1 ]; then
echo "ERROR: Unable to load module $module" >&2
echo "Aborting IPMI test run." >&2
exit 1
else
echo "Successfully loaded module $module"
fi
fi
done
# Now get our info from ipmitool to make sure communication works
# First lest check chassis status
echo "Checking for chassis status"
ipmitool chassis status && echo "Successfully got chassis status" && chassis=0 || chassis=1
echo "Checking to see if we can get sensor data"
ipmitool sdr list full && echo "Successfully got sensor data" && sensor=0 || sensor=1
echo "Checking to see if we can get info on the BMC"
ipmitool bmc info && echo "Successfully got BMC information" && bmc=0 || bmc=1
# if everything passes, exit 0
[ $chassis -eq 0 ] && [ $sensor -eq 0 ] && [ $bmc -eq 0 ] && exit 0 || echo "FAILURE: chassis: $chassis sensor: $sensor bmc: $bmc"
# otherwise exit 1
exit 1
plainbox-provider-checkbox-0.25/bin/network_restart 0000775 0001750 0001750 00000024541 12646152433 024035 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
"""
Reboot networking, wait for a while and check if it's possible to send
some pings
"""
import sys
import os
import time
import threading
import logging
import logging.handlers
from subprocess import check_output, check_call, CalledProcessError, STDOUT
from argparse import ArgumentParser
try:
from gi.repository import Gtk, GObject, GLib
GLib.threads_init()
GObject.threads_init()
gtk_found = True
except (ImportError, RuntimeError):
gtk_found = False
class PingError(Exception):
def __init__(self, address, reason):
self.address = address
self.reason = reason
def main():
args = parse_args()
# Verify that script is run as root
if os.getuid():
sys.stderr.write(
'This script needs superuser permissions to run correctly\n')
return 1
configure_logging(args.log_level, args.output)
# Select interface based on graphich capabilities available
if 'DISPLAY' in os.environ and gtk_found:
factory = GtkApplication
else:
factory = CliApplication
app = factory(args.address, args.times)
return app.run()
class Application:
"""
Network restart application
"""
def __init__(self, address, times):
self.address = address
self.times = times
self.return_code = 0
def run(self):
"""
Restart networking as many times as requested
and use ping to verify
"""
networking = Networking(self.address)
logging.info('Initial connectivity check')
success = ping(self.address)
if not success:
raise PingError(self.address, 'Some interface is down')
for i in range(self.times):
if self.return_code:
break
if self.progress_cb:
fraction = float(i) / self.times
self.progress_cb(fraction)
logging.info('Iteration {0}/{1}...'.format(i + 1, self.times))
networking.restart()
else:
if self.progress_cb:
self.progress_cb(1.0)
logging.info('Test successful')
return self.return_code
class CliApplication(Application):
progress_cb = None
class GtkApplication(Application):
def __init__(self, address, times):
Application.__init__(self, address, times)
dialog = Gtk.Dialog(title='Network restart',
buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL))
dialog.set_default_size(300, 100)
alignment = Gtk.Alignment()
alignment.set(0.5, 0.5, 1.0, 0.1)
alignment.set_padding(10, 10, 10, 10)
progress_bar = Gtk.ProgressBar()
progress_bar.set_show_text(True)
alignment.add(progress_bar)
content_area = dialog.get_content_area()
content_area.pack_start(alignment, expand=True, fill=True, padding=0)
dialog.connect('response', self.response_cb)
dialog.show_all()
# Add new logger handler to write info logs to progress bar
logger = logging.getLogger()
stream = ProgressBarWriter(progress_bar)
formatter = logging.Formatter('%(message)s')
log_handler = logging.StreamHandler(stream)
log_handler.setLevel(logging.INFO)
log_handler.setFormatter(formatter)
logger.addHandler(log_handler)
self.return_code = 0
self.dialog = dialog
self.progress_bar = progress_bar
self.progress_log_handler = log_handler
def response_cb(self, dialog, response_id):
"""
Cancel test case execution
when cancel or close button are closed
"""
self.return_code = response_id
logging.info('Test cancelled')
Gtk.main_quit()
def progress_cb(self, fraction):
"""
Update progress bar
"""
GLib.idle_add(self.progress_bar.set_fraction, fraction)
def thread_target(self):
"""
Run test case in a separate thread
"""
try:
Application.run(self)
except PingError as exception:
logging.error('Failed to ping {0!r}\n{1}'
.format(exception.address, exception.reason))
self.return_code = -1
except CalledProcessError:
self.return_code = -1
finally:
Gtk.main_quit()
def run(self):
"""
Launch test case and gtk mainloop
"""
thread = threading.Thread(target=self.thread_target)
thread.daemon = True
thread.start()
Gtk.main()
return self.return_code
class ProgressBarWriter:
"""
Write logs to a progress bar
"""
def __init__(self, progressbar):
self.progressbar = progressbar
def write(self, message):
if message == '\n':
return
GLib.idle_add(self.progressbar.set_text, message)
def ping(address):
"""
Send ping to a given address
"""
logging.info('Pinging {0!r}...'.format(address))
try:
check_call('ping -c 1 -w 5 {0}'.format(address),
stdout=open(os.devnull, 'w'), stderr=STDOUT, shell=True)
except CalledProcessError:
return False
return True
class Networking:
"""
Networking abstraction to start/stop all interfaces
"""
def __init__(self, address):
self.address = address
self.interfaces = self._get_interfaces()
def _get_interfaces(self):
"""
Get all network interfaces
"""
output = check_output(['/sbin/ifconfig', '-s', '-a'])
lines = output.splitlines()[1:]
interfaces = ([interface for interface in
[line.split()[0] for line in lines] if interface != 'lo'])
return interfaces
def restart(self):
"""
Restart networking
"""
self._stop()
self._start()
def _start(self):
"""
Start networking
"""
logging.info('Bringing all interfaces up...')
for interface in self.interfaces:
try:
check_output(['/sbin/ifconfig', interface, 'up'])
except CalledProcessError:
logging.error('Unable to bring up interface {0!r}'
.format(interface))
raise
logging.info('Starting network manager...')
try:
check_output(['/sbin/start', 'network-manager'])
except CalledProcessError:
logging.error('Unable to start network manager')
raise
# Verify that network interface is up
for timeout in [2, 4, 8, 16, 32, 64]:
logging.debug('Waiting ({0} seconds)...'.format(timeout))
time.sleep(timeout)
success = ping(self.address)
if success:
break
else:
raise PingError(self.address,
'Some interface is still down')
def _stop(self):
"""
Stop network manager
"""
logging.info('Stopping network manager...')
try:
check_output(['/sbin/stop', 'network-manager'])
except CalledProcessError:
logging.error('Unable to stop network manager')
raise
logging.info('Bringing all interfaces down...')
for interface in self.interfaces:
try:
check_output(['/sbin/ifconfig', interface, 'down'])
except CalledProcessError:
logging.error('Unable to bring down interface {0!r}'
.format(interface))
raise
# Verify that network interface is down
for timeout in [2, 4, 8]:
logging.debug('Waiting ({0} seconds)...'.format(timeout))
time.sleep(timeout)
success = ping(self.address)
if not success:
break
else:
raise PingError(self.address,
'Some interface is still up')
def parse_args():
"""
Parse command line options
"""
parser = ArgumentParser('Reboot networking interface '
'and verify that is up again afterwards')
parser.add_argument('-a', '--address', default='ubuntu.com',
help=('Address to ping to verify that network connection is up '
"('%(default)s' by default)"))
parser.add_argument('-o', '--output',
default='/var/log',
help='The path to the log directory. \
Default is /var/log')
parser.add_argument('-t', '--times',
type=int, default=1,
help=('Number of times that the network interface has to be restarted '
'(%(default)s by default)'))
log_levels = ['notset', 'debug', 'info', 'warning', 'error', 'critical']
parser.add_argument('--log-level', dest='log_level_str', default='notset',
choices=log_levels,
help=('Log level. '
'One of {0} or {1} (%(default)s by default)'
.format(', '.join(log_levels[:-1]), log_levels[-1])))
args = parser.parse_args()
args.log_level = getattr(logging, args.log_level_str.upper())
return args
def configure_logging(log_level, output):
"""
Configure logging
"""
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# Log to sys.stderr using log level passed through command line
if log_level != logging.NOTSET:
log_handler = logging.StreamHandler()
formatter = logging.Formatter('%(levelname)-8s %(message)s')
log_handler.setFormatter(formatter)
log_handler.setLevel(log_level)
logger.addHandler(log_handler)
# Log to rotating file using DEBUG log level
log_filename = os.path.join(output,
'{0}.log'.format(os.path.basename(__file__)))
rollover = os.path.exists(log_filename)
log_handler = logging.handlers.RotatingFileHandler(log_filename, mode='a+',
backupCount=3)
formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
log_handler.setFormatter(formatter)
log_handler.setLevel(logging.DEBUG)
logger.addHandler(log_handler)
if rollover:
log_handler.doRollover()
if __name__ == '__main__':
try:
sys.exit(main())
except PingError as exception:
logging.error('Failed to ping {0!r}\n{1}'
.format(exception.address, exception.reason))
sys.exit(1)
plainbox-provider-checkbox-0.25/bin/graphics_driver 0000775 0001750 0001750 00000032064 12646152433 023752 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# ========================================================================
#
# based on xlogparse
#
# DESCRIPTION
#
# Parses Xlog.*.log format files and allows looking up data from it
#
# AUTHOR
# Bryce W. Harrington
#
# COPYRIGHT
# Copyright (C) 2010-2012 Bryce W. Harrington
# All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# ========================================================================
import re
import sys
import os
from subprocess import Popen, PIPE, check_output, CalledProcessError
class XorgLog(object):
def __init__(self, logfile=None):
self.modules = []
self.errors = []
self.warnings = []
self.info = []
self.notimpl = []
self.notices = []
self.cards = []
self.displays = {}
self.xserver_version = None
self.boot_time = None
self.boot_logfile = None
self.kernel_version = None
self.video_driver = None
self.xorg_conf_path = None
self.logfile = logfile
if logfile:
self.parse(logfile)
def parse(self, filename):
self.displays = {}
display = {}
display_name = "Unknown"
in_file = open(filename, errors='ignore')
gathering_module = False
found_ddx = False
module = None
for line in in_file.readlines():
# Errors and Warnings
m = re.search(r'\(WW\) (.*)$', line)
if m:
self.warnings.append(m.group(1))
continue
m = re.search(r'\(EE\) (.*)$', line)
if m:
self.errors.append(m.group(1))
continue
# General details
m = re.search(r'Current Operating System: (.*)$', line)
if m:
uname = m.group(1)
self.kernel_version = uname.split()[2]
continue
m = re.search(r'Kernel command line: (.*)$', line)
if m:
self.kernel_command_line = m.group(1)
continue
m = re.search(r'Build Date: (.*)$', line)
if m:
self.kernel_command_line = m.group(1)
continue
m = re.search(r'Log file: "(.*)", Time: (.*)$', line)
if m:
self.boot_logfile = m.group(1)
self.boot_time = m.group(2)
m = re.search(r'xorg-server ([^ ]+) .*$', line)
if m:
self.xserver_version = m.group(1)
continue
m = re.search(r'Using a default monitor configuration.', line)
if m and self.xorg_conf_path is None:
self.xorg_conf_path = 'default'
continue
m = re.search(r'Using config file: "(.*)"', line)
if m:
self.xorg_conf_path = m.group(1)
continue
# Driver related information
m = re.search(r'\(..\)', line)
if m:
if gathering_module and module is not None:
self.modules.append(module)
gathering_module = False
module = None
m = re.search(
'\(II\) Loading.*modules\/drivers\/(.+)_drv\.so', line)
if m:
found_ddx = True
continue
m = re.search(r'\(II\) Module (\w+):', line)
if m:
module = {
'name': m.group(1),
'vendor': None,
'version': None,
'class': None,
'abi_name': None,
'abi_version': None,
'ddx': found_ddx,
}
found_ddx = False
gathering_module = True
if gathering_module:
m = re.search(r'vendor="(.*:?)"', line)
if m:
module['vendor'] = m.group(1)
m = re.search(r'module version = (.*)', line)
if m:
module['version'] = m.group(1)
if module['name'] == 'nvidia':
try:
version = check_output(
"nvidia-settings -v",
shell=True,
universal_newlines=True)
m = re.search(r'.*version\s+([0-9\.]+).*', version)
if m:
module['version'] = m.group(1)
except CalledProcessError:
pass
m = re.search(r'class: (.*)', line)
if m:
module['class'] = m.group(1)
m = re.search(r'ABI class:\s+(.*:?), version\s+(.*:?)', line)
if m:
if m.group(1)[:5] == "X.Org":
module['abi_name'] = m.group(1)[6:]
else:
module['abi_name'] = m.group(1)
module['abi_version'] = m.group(2)
continue
# EDID and Modelines
# We use this part to determine which driver is in use
# For Intel / RADEON
m = re.search(r'\(II\) (.*)\(\d+\): EDID for output (.*)', line)
if m:
self.displays[display_name] = display
self.video_driver = m.group(1)
display_name = m.group(2)
display = {'Output': display_name}
continue
m = re.search(
r'\(II\) (.*)\(\d+\): Assigned Display Device: (.*)$', line)
if m:
self.displays[display_name] = display
self.video_driver = m.group(1)
display_name = m.group(2)
display = {'Output': display_name}
continue
# For NVIDIA
m = re.search(r'\(II\) (.*)\(\d+\): Setting mode "(.*?):', line)
if not m:
m = re.search(r'\(II\) (.*)\(\d+\): Setting mode "(NULL)"', line)
if m:
self.displays[display_name] = display
self.video_driver = m.group(1)
display_name = m.group(2)
display = {'Output': display_name}
continue
# For 4th Intel after 3.11
m = re.search(
r'\(II\) (.*)\(\d+\): switch to mode .* using (.*),', line)
if m:
self.displays[display_name] = display
self.video_driver = 'intel' # 'intel' is what we expect to see
display_name = m.group(2)
display = {'Output': display_name}
continue
m = re.search(
r'Manufacturer: (.*) *Model: (.*) *Serial#: (.*)', line)
if m:
display['display manufacturer'] = m.group(1)
display['display model'] = m.group(2)
display['display serial no.'] = m.group(3)
m = re.search(r'EDID Version: (.*)', line)
if m:
display['display edid version'] = m.group(1)
m = re.search(r'EDID vendor \"(.*)\", prod id (.*)', line)
if m:
display['vendor'] = m.group(1)
display['product id'] = m.group(2)
m = re.search(
r'Max Image Size \[(.*)\]: *horiz.: (.*) *vert.: (.*)', line)
if m:
display['size max horizontal'] = "%s %s" % (
m.group(2), m.group(1))
display['size max vertical'] = "%s %s" % (
m.group(3), m.group(1))
m = re.search(r'Image Size: *(.*) x (.*) (.*)', line)
if m:
display['size horizontal'] = "%s %s" % (m.group(1), m.group(3))
display['size vertical'] = "%s %s" % (m.group(2), m.group(3))
m = re.search(r'(.*) is preferred mode', line)
if m:
display['mode preferred'] = m.group(1)
m = re.search(r'Modeline \"(\d+)x(\d+)\"x([0-9\.]+) *(.*)$', line)
if m:
key = "mode %sx%s@%s" % (m.group(1), m.group(2), m.group(3))
display[key] = m.group(4)
continue
if display_name not in self.displays.keys():
self.displays[display_name] = display
in_file.close()
def errors_filtered(self):
excludes = set([
'error, (NI) not implemented, (??) unknown.',
'Failed to load module "fglrx" (module does not exist, 0)',
'Failed to load module "nv" (module does not exist, 0)',
])
return [err for err in self.errors if err not in excludes]
def warnings_filtered(self):
excludes = set([
'warning, (EE) error, (NI) not implemented, (??) unknown.',
'The directory "/usr/share/fonts/X11/cyrillic" does not exist.',
'The directory "/usr/share/fonts/X11/100dpi/" does not exist.',
'The directory "/usr/share/fonts/X11/75dpi/" does not exist.',
'The directory "/usr/share/fonts/X11/100dpi" does not exist.',
'The directory "/usr/share/fonts/X11/75dpi" does not exist.',
'Warning, couldn\'t open module nv',
'Warning, couldn\'t open module fglrx',
'Falling back to old probe method for vesa',
'Falling back to old probe method for fbdev',
])
return [err for err in self.warnings if err not in excludes]
def get_driver_info(xlog):
'''Return the running driver and version'''
print('-' * 13, 'VIDEO DRIVER INFORMATION', '-' * 13)
if xlog.video_driver:
for module in xlog.modules:
if module['name'] == xlog.video_driver.lower():
print("Video Driver: %s" % module['name'])
print("Driver Version: %s" % module['version'])
print('\n')
return 0
else:
print("ERROR: No video driver loaded! Possibly in failsafe mode!",
file=sys.stderr)
return 1
def is_laptop():
return os.path.isdir('/proc/acpi/button/lid')
def hybrid_graphics_check(xlog):
'''Check for Hybrid Graphics'''
card_id1 = re.compile('.*0300: *(.+):(.+) \(.+\)')
card_id2 = re.compile('.*03..: *(.+):(.+)')
cards_dict = {'8086': 'Intel', '10de': 'NVIDIA', '1002': 'AMD'}
cards = []
drivers = []
formatted_cards = []
output = Popen(['lspci', '-n'], stdout=PIPE, universal_newlines=True)
card_list = output.communicate()[0].split('\n')
# List of discovered cards
for line in card_list:
m1 = card_id1.match(line)
m2 = card_id2.match(line)
if m1:
id1 = m1.group(1).strip().lower()
id2 = m1.group(2).strip().lower()
id = id1 + ':' + id2
cards.append(id)
elif m2:
id1 = m2.group(1).strip().lower()
id2 = m2.group(2).strip().lower()
id = id1 + ':' + id2
cards.append(id)
print('-' * 13, 'HYBRID GRAPHICS CHECK', '-' * 16)
for card in cards:
formatted_name = cards_dict.get(card.split(':')[0], 'Unknown')
formatted_cards.append(formatted_name)
print('Graphics Chipset: %s (%s)' % (formatted_name, card))
for module in xlog.modules:
if module['ddx'] and module['name'] not in drivers:
drivers.append(module['name'])
print('Loaded DDX Drivers: %s' % ', '.join(drivers))
has_hybrid_graphics = (len(cards) > 1 and is_laptop()
and (cards_dict.get('8086') in formatted_cards
or cards_dict.get('1002') in formatted_cards))
print('Hybrid Graphics: %s' % (has_hybrid_graphics
and 'yes' or 'no'))
return 0
def main():
xlog = XorgLog("/var/log/Xorg.0.log")
results = []
results.append(get_driver_info(xlog))
results.append(hybrid_graphics_check(xlog))
return 1 if 1 in results else 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/touchpad_test 0000775 0001750 0001750 00000013723 12646152433 023446 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import sys
import gettext
from gettext import gettext as _
from gi.repository import Gio, Gtk, Gdk
from optparse import OptionParser
EXIT_WITH_FAILURE = 1
EXIT_WITH_SUCCESS = 0
EXIT_TIMEOUT = 30
class Direction(object):
def __init__(self, name):
self.name = name
self.tested = False
self.value = getattr(Gdk.ScrollDirection, name.upper())
class GtkScroller(object):
touchpad_key = "org.gnome.settings-daemon.peripherals.touchpad"
exit_code = EXIT_WITH_FAILURE
def __init__(self, directions, edge_scroll=False):
self.directions = directions
self.edge_scroll = edge_scroll
# Initialize GTK constants
self.ICON_SIZE = Gtk.IconSize.BUTTON
self.ICON_TESTED = Gtk.STOCK_YES
self.ICON_UNTESTED = Gtk.STOCK_INDEX
self.ICON_NOT_REQUIRED = Gtk.STOCK_REMOVE
self.button_factory = Gtk.Button
self.hbox_factory = Gtk.HBox
self.image_factory = Gtk.Image
self.label_factory = Gtk.Label
self.vbox_factory = Gtk.VBox
# Create GTK window.
window = Gtk.Window()
window.set_type_hint(Gdk.WindowType.TOPLEVEL)
window.add_events(
Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.SMOOTH_SCROLL_MASK)
window.set_size_request(200, 100)
window.set_resizable(False)
window.set_title(_("Type Text"))
window.connect("delete-event", lambda w, e: self.quit())
window.connect("scroll-event", self.on_scroll)
window.show()
# Add common widgets to the window.
vbox = self._add_vbox(window)
self.label = self._add_label(vbox)
button_hbox = self._add_hbox(vbox)
validation_hbox = self._add_hbox(vbox)
self.status = self._add_label(vbox)
self.exit_button = self._add_button(vbox, Gtk.STOCK_CLOSE)
self.exit_button.connect("clicked", lambda w: self.quit())
# Add widgets for each direction.
self.icons = {}
for direction in self.directions:
self._add_label(button_hbox, direction.name)
self.icons[direction] = self._add_image(
validation_hbox, Gtk.STOCK_INDEX)
self.show_text(
_("Please move the mouse cursor to this window.") +
"\n" +
_("Then scroll in each direction on your touchpad."))
def _add_button(self, context, stock):
button = self.button_factory(stock=stock)
context.add(button)
button.show()
return button
def _add_hbox(self, context, spacing=4):
hbox = self.hbox_factory()
context.add(hbox)
hbox.set_spacing(4)
hbox.show()
return hbox
def _add_image(self, context, stock):
image = self.image_factory(stock=stock, icon_size=self.ICON_SIZE)
context.add(image)
image.show()
return image
def _add_label(self, context, text=None):
label = self.label_factory()
context.add(label)
label.set_size_request(0, 0)
label.set_line_wrap(True)
if text:
label.set_text(text)
label.show()
return label
def _add_vbox(self, context):
vbox = self.vbox_factory()
vbox.set_homogeneous(False)
vbox.set_spacing(8)
context.add(vbox)
vbox.show()
return vbox
def run(self):
# Save touchpad settings.
touchpad_settings = Gio.Settings.new(self.touchpad_key)
self.saved_horiz_scroll_enabled = touchpad_settings.get_boolean(
"horiz-scroll-enabled")
self.saved_scroll_method = touchpad_settings.get_string(
"scroll-method")
# Set touchpad settings.
touchpad_settings.set_boolean("horiz-scroll-enabled", True)
if self.edge_scroll:
touchpad_settings.set_string("scroll-method", "edge-scrolling")
Gtk.main()
def quit(self):
# Reset touchpad settings.
touchpad_settings = Gio.Settings.new(self.touchpad_key)
touchpad_settings.set_boolean(
"horiz-scroll-enabled", self.saved_horiz_scroll_enabled)
touchpad_settings.set_string(
"scroll-method", self.saved_scroll_method)
Gtk.main_quit()
def show_text(self, text, widget=None):
if widget is None:
widget = self.label
widget.set_text(text)
def found_direction(self, direction):
direction.tested = True
self.icons[direction].set_from_stock(
self.ICON_TESTED, size=self.ICON_SIZE)
self.check_directions()
def check_directions(self):
if all([direction.tested for direction in self.directions]):
self.show_text(
_("All required directions have been tested!"), self.status)
self.exit_code = EXIT_WITH_SUCCESS
self.exit_button.grab_focus()
def on_scroll(self, window, event):
for direction in self.directions:
if direction.value == event.direction:
self.found_direction(direction)
break
return True
def main(args):
gettext.textdomain("checkbox")
usage = """Usage: %prog DIRECTION... [--edge-scroll]"""
parser = OptionParser(usage=usage)
parser.add_option("--edge-scroll", action="store_true", default=False,
help="Force touchpad to use edge scrolling only")
(options, args) = parser.parse_args(args)
if not args:
parser.error("Must specify directions to test.")
directions = []
for arg in args:
try:
direction = Direction(arg)
except AttributeError:
parser.error("Unsupported direction: %s" % arg)
directions.append(direction)
scroller = GtkScroller(directions, edge_scroll=options.edge_scroll)
try:
scroller.run()
except KeyboardInterrupt:
scroller.show_text(_("Test interrupted"), self.status)
scroller.quit()
return scroller.exit_code
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/network_reconnect_resume_test 0000775 0001750 0001750 00000006474 12646152433 026755 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# Copyright (C) 2012 Canonical, Ltd.
import re
import subprocess
import argparse
import sys
def get_time_difference(device):
"""
Returns the difference in seconds between the last resume from suspend (S3)
and the time it took to reconnect to Wifi. If there is a problem finding
the information, None is returned.
"""
resume_time = get_resume_time()
if resume_time is None:
print("Unable to obtain wakeup/resume time from dmesg."
"Please be sure the system has been suspended", file=sys.stderr)
return None
if device == "wifi":
reconnect_times = list(get_wifi_reconnect_times())
elif device == "wired":
reconnect_times = list(get_wired_reconnect_times())
if not reconnect_times:
print("Unable to obtain %s connection time after a S3. Please be sure"
" that the system has been suspended" % device, file=sys.stderr)
return None
# since some wifi & wired tests can disconnect and reconnect us multiple
# times after a suspend, we need to find the reconnect that occurs
# immediately after the resume from S3
for reconnect_time in reconnect_times:
if reconnect_time >= resume_time:
return round((reconnect_time - resume_time), 2)
return None
def get_wifi_reconnect_times():
"""
Returns a list of all the timestamps for wifi reconnects.
"""
data = subprocess.check_output(['dmesg'], universal_newlines=True)
syntax = re.compile("\[(.*)\] wlan.* associated")
results = re.findall(syntax, data)
return map(float, results)
def get_wired_reconnect_times():
"""
Returns a list of all the timestamps for wired reconnects.
"""
data = subprocess.check_output(['dmesg'], universal_newlines=True)
syntax = re.compile("\[(.*)\].*eth.* Link is [uU]p")
results = re.findall(syntax, data)
return map(float, results)
def get_resume_time():
"""
Returns the last (most recent) timestamp for an ACPI resume from sleep (S3)
If no resume is found, None is returned.
"""
data = subprocess.check_output(['dmesg'], universal_newlines=True)
syntax = re.compile("\[(.*)\].ACPI: Waking up from system sleep state S3")
results = re.findall(syntax, data)
if not results:
return None
else:
return float(results[-1])
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--timeout',
type=int,
help="Specified max time allowed for Wifi/Wired to"
" reconnect in seconds",
required=True)
parser.add_argument('-d', '--device',
help="Specify the device to test either, eth or wlan",
required=True,
choices=['wifi', 'wired'])
args = parser.parse_args()
timedif = get_time_difference(args.device)
if not timedif:
return 0
print("Your %s resumed in %s seconds after the last suspend" % (
args.device, timedif))
if timedif > args.timeout:
print("FAIL: the network failed to reconnect within the allotted time")
return 1
else:
print("PASS: the network connected within the allotted time")
return 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/gateway_ping_test 0000775 0001750 0001750 00000025620 12646152433 024314 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# This file is part of Checkbox.
#
# Copyright 2007-2014 Canonical Ltd.
# Written by:
# Brendan Donegan
# Daniel Manrique
# David Murphy
# Javier Collado
# Jeff Lane
# Marc Tardif
# Mathieu Trudel-Lapierre
# Zygmunt Krynicki
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
from gettext import gettext as _
import argparse
import errno
import gettext
import logging
import os
import re
import socket
import struct
import subprocess
import sys
import time
class Route:
"""
Gets routing information from the system.
"""
def _num_to_dotted_quad(self, number):
"""
Convert long int to dotted quad string
"""
return socket.inet_ntoa(struct.pack("\w+)\s+00000000\s+"
"(?P[\w]+)\s+")
w = h.search(route)
if w:
if w.group("def_gateway"):
return self._num_to_dotted_quad(
int(w.group("def_gateway"), 16))
else:
logging.error(
_("Could not find def gateway info in /proc"))
return None
else:
logging.error(_("Could not find def gateway info in /proc"))
return None
def _get_default_gateway_from_bin_route(self):
"""
Get default gateway from /sbin/route -n
Called by get_default_gateway
and is only used if could not get that from /proc
"""
logging.debug(
_("Reading default gateway information from route binary"))
routebin = subprocess.getstatusoutput(
"export LANGUAGE=C; " "/usr/bin/env route -n")
if routebin[0] == 0:
h = re.compile("\n0.0.0.0\s+(?P[\w.]+)\s+")
w = h.search(routebin[1])
if w:
def_gateway = w.group("def_gateway")
if def_gateway:
return def_gateway
logging.error(_("Could not find default gateway by running route"))
return None
def get_hostname(self):
return socket.gethostname()
def get_default_gateway(self):
t1 = self._get_default_gateway_from_proc()
if not t1:
t1 = self._get_default_gateway_from_bin_route()
return t1
def get_host_to_ping(interface=None, verbose=False, default=None):
# Get list of all IPs from all my interfaces,
interface_list = subprocess.check_output(["ip", "-o", 'addr', 'show'])
reg = re.compile('\d: (?P\w+) +inet (?P[\d\.]+)/'
'(?P[\d]+) brd (?P[\d\.]+)')
# Will magically exclude lo because it lacks brd field
interfaces = reg.findall(interface_list.decode())
# ping -b the network on each one (one ping only)
# exclude the ones not specified in iface
for iface in interfaces:
if not interface or iface[0] == interface:
# Use check_output even if I'll discard the output
# looks cleaner than using .call and redirecting stdout to null
try:
subprocess.check_output(["ping", "-q", "-c", "1", "-b",
iface[3]], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
pass
# If default host given, ping it as well,
# to try to get it into the arp table.
# Needed in case it's not responding to broadcasts.
if default:
try:
subprocess.check_output(["ping", "-q", "-c", "1", default],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
pass
ARP_POPULATE_TRIES = 10
num_tries = 0
while num_tries < ARP_POPULATE_TRIES:
# Get output from arp -a -n to get known IPs
known_ips = subprocess.check_output(["arp", "-a", "-n"])
reg = re.compile('\? \((?P[\d.]+)\) at (?P[a-f0-9\:]+) '
'\[ether\] on (?P[\w\d]+)')
# Filter (if needed) IPs not on the specified interface
pingable_ips = [pingable[0] for pingable in reg.findall(
known_ips.decode()) if not interface
or pingable[2] == interface]
# If the default given ip is among the remaining ones,
# ping that.
if default and default in pingable_ips:
if verbose:
print(_(
"Desired ip address {0} is reachable, using it"
).format(default))
return default
# If not, choose another IP.
address_to_ping = pingable_ips[0] if len(pingable_ips) else None
if verbose:
print(_(
"Desired ip address {0} is not reachable from {1},"
" using {2} instead"
).format(default, interface, address_to_ping))
if address_to_ping:
return address_to_ping
time.sleep(2)
num_tries += 1
# Wait time expired
return None
def ping(host, interface, count, deadline, verbose=False):
command = ["ping", str(host), "-c", str(count), "-w", str(deadline)]
if interface:
command.append("-I{}".format(interface))
reg = re.compile(
r"(\d+) packets transmitted, (\d+) received, (\d+)% packet loss")
ping_summary = {'transmitted': 0, 'received': 0, 'pct_loss': 0}
try:
output = subprocess.check_output(command, universal_newlines=True)
except OSError as exc:
if exc.errno == errno.ENOENT:
# No ping command present;
# default exception message is informative enough.
print(exc)
else:
raise
except subprocess.CalledProcessError as excp:
# Ping returned fail exit code
print(_("ERROR: ping result: {0}").format(excp))
else:
if verbose:
print(output)
received = re.findall(reg, output)
if received:
ping_summary = received[0]
ping_summary = {
'transmitted': int(ping_summary[0]),
'received': int(ping_summary[1]),
'pct_loss': int(ping_summary[2])}
return ping_summary
def main(args):
gettext.textdomain("2013.com.canonical.certification.checkbox")
gettext.bindtextdomain("2013.com.canonical.certification.checkbox",
os.getenv("CHECKBOX_PROVIDER_LOCALE_DIR", None))
default_count = 2
default_delay = 4
route = Route()
parser = argparse.ArgumentParser()
parser.add_argument(
"host", nargs='?', default=route.get_default_gateway(),
help=_("host to ping"))
parser.add_argument(
"-c", "--count", default=default_count, type=int,
help=_("number of packets to send"))
parser.add_argument(
"-d", "--deadline", default=default_delay, type=int,
help=_("timeout in seconds"))
parser.add_argument(
"-t", "--threshold", default=0, type=int,
help=_("allowed packet loss percentage (default: %(default)s)"))
parser.add_argument(
"-v", "--verbose", action='store_true', help=_("be verbose"))
parser.add_argument(
"-I", "--interface", help=_("use specified interface to send packets"))
args = parser.parse_args()
# Ensure count and deadline make sense. Adjust them if not.
if args.deadline != default_delay and args.count != default_count:
# Ensure they're both consistent, and exit with a warning if not,
# rather than modifying what the user explicitly set.
if args.deadline <= args.count:
# FIXME: this cannot ever be translated correctly
print(_(
"ERROR: not enough time for {0} pings in {1} seconds"
).format(args.count, args.deadline))
return 1
elif args.deadline != default_delay:
# Adjust count according to delay.
args.count = args.deadline - 1
if args.count < 1:
args.count = 1
if args.verbose:
# FIXME: this cannot ever be translated correctly
print(_(
"Adjusting ping count to {0} to fit in {1}-second deadline"
).format(args.count, args.deadline))
else:
# Adjust delay according to count
args.deadline = args.count + 1
if args.verbose:
# FIXME: this cannot ever be translated correctly
print(_(
"Adjusting deadline to {0} seconds to fit {1} pings"
).format(args.deadline, args.count))
# If given host is not pingable, override with something pingable.
host = get_host_to_ping(
interface=args.interface, verbose=args.verbose, default=args.host)
if args.verbose:
print(_("Checking connectivity to {0}").format(host))
ping_summary = None
if host:
ping_summary = ping(host, args.interface, args.count,
args.deadline, args.verbose)
if ping_summary is None or ping_summary['received'] == 0:
print(_("No Internet connection"))
return 1
elif ping_summary['transmitted'] != ping_summary['received']:
print(_("Connection established, but lost {0}% of packets").format(
ping_summary['pct_loss']))
if ping_summary['pct_loss'] > args.threshold:
print(_(
"FAIL: {0}% packet loss is higher than {1}% threshold"
).format(ping_summary['pct_loss'], args.threshold))
return 1
else:
print(_(
"PASS: {0}% packet loss is within {1}% threshold"
).format(ping_summary['pct_loss'], args.threshold))
return 0
else:
print(_("Internet connection fully established"))
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/removable_storage_watcher 0000775 0001750 0001750 00000127235 12646152433 026021 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import argparse
import collections
import copy
import dbus
import logging
import sys
from gi.repository import GObject, GUdev
from checkbox_support.dbus import connect_to_system_bus
from checkbox_support.dbus.udisks2 import UDisks2Model, UDisks2Observer
from checkbox_support.dbus.udisks2 import is_udisks2_supported
from checkbox_support.dbus.udisks2 import lookup_udev_device
from checkbox_support.dbus.udisks2 import map_udisks1_connection_bus
from checkbox_support.heuristics.udisks2 import is_memory_card
from checkbox_support.parsers.udevadm import CARD_READER_RE, GENERIC_RE, FLASH_RE
from checkbox_support.udev import get_interconnect_speed, get_udev_block_devices
# Record representing properties of a UDisks1 Drive object needed by the
# UDisks1 version of the watcher implementation
UDisks1DriveProperties = collections.namedtuple(
'UDisks1DriveProperties', 'file bus speed model vendor media')
# Delta record that encapsulates difference:
# delta_dir -- directon of the difference, either DELTA_DIR_PLUS or
# DELTA_DIR_MINUS
# value -- the actual value being removed or added, either InterfaceDelta or
# PropertyDelta instance, see below
DeltaRecord = collections.namedtuple("DeltaRecord", "delta_dir value")
# Delta value for representing interface changes
InterfaceDelta = collections.namedtuple(
"InterfaceDelta",
"delta_type object_path iface_name")
# Delta value for representing property changes
PropertyDelta = collections.namedtuple(
"PropertyDelta",
"delta_type object_path iface_name prop_name prop_value")
# Tokens that encode additions and removals
DELTA_DIR_PLUS = '+'
DELTA_DIR_MINUS = '-'
# Tokens that encode interface and property deltas
DELTA_TYPE_IFACE = 'i'
DELTA_TYPE_PROP = 'p'
def format_bytes(size):
"""
Format size to be easily read by humans
The result is disk-size compatible (using multiples of 10
rather than 2) string like "4.5GB"
"""
for index, prefix in enumerate(" KMGTPEZY", 0):
factor = 10 ** (index * 3)
if size // factor <= 1000:
break
return "{}{}B".format(size // factor, prefix.strip())
class UDisks1StorageDeviceListener:
def __init__(self, system_bus, loop, action, devices, minimum_speed,
memorycard):
self._action = action
self._devices = devices
self._minimum_speed = minimum_speed
self._memorycard = memorycard
self._bus = system_bus
self._loop = loop
self._error = False
self._change_cache = []
def check(self, timeout):
udisks = 'org.freedesktop.UDisks'
if self._action == 'insert':
signal = 'DeviceAdded'
logging.debug("Adding signal listener for %s.%s", udisks, signal)
self._bus.add_signal_receiver(self.add_detected,
signal_name=signal,
dbus_interface=udisks)
elif self._action == 'remove':
signal = 'DeviceRemoved'
logging.debug("Adding signal listener for %s.%s", udisks, signal)
self._bus.add_signal_receiver(self.remove_detected,
signal_name=signal,
dbus_interface=udisks)
self._starting_devices = self.get_existing_devices()
logging.debug("Starting with the following devices: %r",
self._starting_devices)
def timeout_callback():
print("%s seconds have expired "
"waiting for the device to be inserted." % timeout)
self._error = True
self._loop.quit()
logging.debug("Adding timeout listener, timeout=%r", timeout)
GObject.timeout_add_seconds(timeout, timeout_callback)
logging.debug("Starting event loop...")
self._loop.run()
return self._error
def verify_device_change(self, changed_devices, message=""):
logging.debug("Verifying device change: %s", changed_devices)
# Filter the applicable bus types, as provided on the command line
# (values of self._devices can be 'usb', 'firewire', etc)
desired_bus_devices = [
device
for device in changed_devices
if device.bus in self._devices]
logging.debug("Desired bus devices: %s", desired_bus_devices)
for dev in desired_bus_devices:
if self._memorycard:
if (dev.bus != 'sdio'
and not FLASH_RE.search(dev.media)
and not CARD_READER_RE.search(dev.model)
and not GENERIC_RE.search(dev.vendor)):
logging.debug("The device does not seem to be a memory"
" card (bus: %r, model: %r), skipping",
dev.bus, dev.model)
return
print(message % {'bus': 'memory card', 'file': dev.file})
else:
if (FLASH_RE.search(dev.media)
or CARD_READER_RE.search(dev.model)
or GENERIC_RE.search(dev.vendor)):
logging.debug("The device seems to be a memory"
" card (bus: %r (model: %r), skipping",
dev.bus, dev.model)
return
print(message % {'bus': dev.bus, 'file': dev.file})
if self._minimum_speed:
if dev.speed >= self._minimum_speed:
print("with speed of %(speed)s bits/s "
"higher than %(min_speed)s bits/s" %
{'speed': dev.speed,
'min_speed': self._minimum_speed})
else:
print("ERROR: speed of %(speed)s bits/s lower "
"than %(min_speed)s bits/s" %
{'speed': dev.speed,
'min_speed': self._minimum_speed})
self._error = True
logging.debug("Device matches requirements, exiting event loop")
self._loop.quit()
def job_change_detected(self, devices, job_in_progress, job_id,
job_num_tasks, job_cur_task_id,
job_cur_task_percentage):
logging.debug("UDisks1 reports a job change has been detected:"
" devices: %s, job_in_progress: %s, job_id: %s,"
" job_num_tasks: %s, job_cur_task_id: %s,"
" job_cur_task_percentage: %s",
devices, job_in_progress, job_id, job_num_tasks,
job_cur_task_id, job_cur_task_percentage)
if job_id == "FilesystemMount":
if devices in self._change_cache:
logging.debug("Ignoring filesystem mount,"
" the device is present in change cache")
return
logging.debug("Adding devices to change cache: %r", devices)
self._change_cache.append(devices)
logging.debug("Starting devices were: %s", self._starting_devices)
current_devices = self.get_existing_devices()
logging.debug("Current devices are: %s", current_devices)
inserted_devices = list(set(current_devices) -
set(self._starting_devices))
logging.debug("Computed inserted devices: %s", inserted_devices)
if self._memorycard:
message = "Expected memory card device %(file)s inserted"
else:
message = "Expected %(bus)s device %(file)s inserted"
self.verify_device_change(inserted_devices,
message=message)
def add_detected(self, added_path):
logging.debug("UDisks1 reports device has been added: %s", added_path)
logging.debug("Resetting change_cache to []")
self._change_cache = []
signal_name = 'DeviceJobChanged'
dbus_interface = 'org.freedesktop.UDisks'
logging.debug("Adding signal listener for %s.%s",
dbus_interface, signal_name)
self._bus.add_signal_receiver(self.job_change_detected,
signal_name=signal_name,
dbus_interface=dbus_interface)
def remove_detected(self, removed_path):
logging.debug("UDisks1 reports device has been removed: %s",
removed_path)
logging.debug("Starting devices were: %s", self._starting_devices)
current_devices = self.get_existing_devices()
logging.debug("Current devices are: %s", current_devices)
removed_devices = list(set(self._starting_devices) -
set(current_devices))
logging.debug("Computed removed devices: %s", removed_devices)
self.verify_device_change(removed_devices,
message="Removable %(bus)s device %(file)s has been removed")
def get_existing_devices(self):
logging.debug("Getting existing devices from UDisks1")
ud_manager_obj = self._bus.get_object("org.freedesktop.UDisks",
"/org/freedesktop/UDisks")
ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks')
existing_devices = []
for dev in ud_manager.EnumerateDevices():
try:
device_obj = self._bus.get_object("org.freedesktop.UDisks",
dev)
device_props = dbus.Interface(device_obj,
dbus.PROPERTIES_IFACE)
udisks = 'org.freedesktop.UDisks.Device'
_device_file = device_props.Get(udisks,
"DeviceFile")
_bus = device_props.Get(udisks,
"DriveConnectionInterface")
_speed = device_props.Get(udisks,
"DriveConnectionSpeed")
_parent_model = ''
_parent_media = ''
_parent_vendor = ''
if device_props.Get(udisks, "DeviceIsPartition"):
parent_obj = self._bus.get_object(
"org.freedesktop.UDisks",
device_props.Get(udisks, "PartitionSlave"))
parent_props = dbus.Interface(
parent_obj, dbus.PROPERTIES_IFACE)
_parent_model = parent_props.Get(udisks, "DriveModel")
_parent_vendor = parent_props.Get(udisks, "DriveVendor")
_parent_media = parent_props.Get(udisks, "DriveMedia")
if not device_props.Get(udisks, "DeviceIsDrive"):
device = UDisks1DriveProperties(
file=str(_device_file),
bus=str(_bus),
speed=int(_speed),
model=str(_parent_model),
vendor=str(_parent_vendor),
media=str(_parent_media))
existing_devices.append(device)
except dbus.DBusException:
pass
return existing_devices
def udisks2_objects_delta(old, new):
"""
Compute the delta between two snapshots of udisks2 objects
The objects are encoded as {s:{s:{s:v}}} where the first dictionary maps
from DBus object path to a dictionary that maps from interface name to a
dictionary that finally maps from property name to property value.
The result is a generator of DeltaRecord objects that encodes the changes:
* the 'delta_dir' is either DELTA_DIR_PLUS or DELTA_DIR_MINUS
* the 'value' is a tuple that differs for interfaces and properties.
Interfaces use the format (DELTA_TYPE_IFACE, object_path, iface_name)
while properties use the format (DELTA_TYPE_PROP, object_path,
iface_name, prop_name, prop_value)
Interfaces are never "changed", they are only added or removed. Properties
can be changed and this is encoded as removal followed by an addition where
both differ only by the 'delta_dir' and the last element of the 'value'
tuple.
"""
# Traverse all objects, old or new
all_object_paths = set()
all_object_paths |= old.keys()
all_object_paths |= new.keys()
for object_path in sorted(all_object_paths):
old_object = old.get(object_path, {})
new_object = new.get(object_path, {})
# Traverse all interfaces of each object, old or new
all_iface_names = set()
all_iface_names |= old_object.keys()
all_iface_names |= new_object.keys()
for iface_name in sorted(all_iface_names):
if iface_name not in old_object and iface_name in new_object:
# Report each ADDED interface
assert iface_name in new_object
delta_value = InterfaceDelta(
DELTA_TYPE_IFACE, object_path, iface_name)
yield DeltaRecord(DELTA_DIR_PLUS, delta_value)
# Report all properties ADDED on that interface
for prop_name, prop_value in new_object[iface_name].items():
delta_value = PropertyDelta(DELTA_TYPE_PROP, object_path,
iface_name, prop_name,
prop_value)
yield DeltaRecord(DELTA_DIR_PLUS, delta_value)
elif iface_name not in new_object and iface_name in old_object:
# Report each REMOVED interface
assert iface_name in old_object
delta_value = InterfaceDelta(
DELTA_TYPE_IFACE, object_path, iface_name)
yield DeltaRecord(DELTA_DIR_MINUS, delta_value)
# Report all properties REMOVED on that interface
for prop_name, prop_value in old_object[iface_name].items():
delta_value = PropertyDelta(DELTA_TYPE_PROP, object_path,
iface_name, prop_name,
prop_value)
yield DeltaRecord(DELTA_DIR_MINUS, delta_value)
else:
# Analyze properties of each interface that existed both in old
# and new object trees.
assert iface_name in new_object
assert iface_name in old_object
old_props = old_object[iface_name]
new_props = new_object[iface_name]
all_prop_names = set()
all_prop_names |= old_props.keys()
all_prop_names |= new_props.keys()
# Traverse all properties, old or new
for prop_name in sorted(all_prop_names):
if prop_name not in old_props and prop_name in new_props:
# Report each ADDED property
delta_value = PropertyDelta(
DELTA_TYPE_PROP, object_path, iface_name,
prop_name, new_props[prop_name])
yield DeltaRecord(DELTA_DIR_PLUS, delta_value)
elif prop_name not in new_props and prop_name in old_props:
# Report each REMOVED property
delta_value = PropertyDelta(
DELTA_TYPE_PROP, object_path, iface_name,
prop_name, old_props[prop_name])
yield DeltaRecord(DELTA_DIR_MINUS, delta_value)
else:
old_value = old_props[prop_name]
new_value = new_props[prop_name]
if old_value != new_value:
# Report each changed property
yield DeltaRecord(DELTA_DIR_MINUS, PropertyDelta(
DELTA_TYPE_PROP, object_path, iface_name,
prop_name, old_value))
yield DeltaRecord(DELTA_DIR_PLUS, PropertyDelta(
DELTA_TYPE_PROP, object_path, iface_name,
prop_name, new_value))
class UDisks2StorageDeviceListener:
"""
Implementation of the storage device listener concept for UDisks2 backend.
Loosely modeled on the UDisks-based implementation above.
Implementation details
^^^^^^^^^^^^^^^^^^^^^^
The class, once configured reacts to asynchronous events from the event
loop. Those are either DBus signals or GLib timeout.
The timeout, if reached, terminates the test and fails with an appropriate
end-user message. The user is expected to manipulate storage devices while
the test is running.
DBus signals (that correspond to UDisks2 DBus signals) cause callbacks into
this code. Each time a signal is reported "delta" is computed and verified
to determine if there was a successful match. The delta contains a list or
DeltaRecord objects that encode difference (either addition or removal) and
the value of the difference (interface name or interface property value).
This delta is computed by udisks2_objects_delta(). The delta is then passed
to _validate_delta() which has a chance to end the test but also prints
diagnostic messages in verbose mode. This is very useful for understanding
what the test actually sees occurring.
Insertion/removal detection strategy
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compared to initial state, the following changes objects need to be
detected
* At least one UDisks2 object with the following _all_ interfaces:
* UDisks2.Partition
(because we want a partitioned device)
* UDisks2.Block
(because we want that device to have a block device that users can
format)
- having IdUsage == 'filesystem'
(because it should not be a piece of raid or lvm)
- having Size > 0
(because it should not be and empty removable storage reader)
* UDisks2.Filesystem
(because we want to ensure that a filesystem gets mounted)
- having MountPoints != []
- as a special exception this rule is REMOVED from eSATA and SATA
devices as they are not automatically mounted anymore.
This object must be traceable to an UDisks.Drive object:
(because we need the medium to be inserted somewhere)
- having ConnectionBus in (desired_connection_buses)
- as a special exception this rule is weakened for eSATA because
for such devices the ConnectionBus property is empty.
"""
# Name of the DBus interface exposed UDisks2 for various drives
UDISKS2_DRIVE_INTERFACE = "org.freedesktop.UDisks2.Drive"
# Name of the DBus property provided by the "Drive" interface above
UDISKS2_DRIVE_PROPERTY_CONNECTION_BUS = "ConnectionBus"
def __init__(self, system_bus, loop, action, devices, minimum_speed,
memorycard):
# Store the desired minimum speed of the device in Mbit/s. The argument
# is passed as the number of bits per second so let's fix that.
self._desired_minimum_speed = minimum_speed / 10 ** 6
# Compute the allowed UDisks2.Drive.ConnectionBus value based on the
# legacy arguments passed from the command line.
self._desired_connection_buses = set([
map_udisks1_connection_bus(device) for device in devices])
# Check if we are explicitly looking for memory cards
self._desired_memory_card = memorycard
# Store the desired "delta" direction depending on
# whether we test for insertion or removal
if action == "insert":
self._desired_delta_dir = DELTA_DIR_PLUS
elif action == "remove":
self._desired_delta_dir = DELTA_DIR_MINUS
else:
raise ValueError("Unsupported action: {}".format(action))
# Store DBus bus object as we need to pass it to UDisks2 observer
self._bus = system_bus
# Store event loop object
self._loop = loop
# Setup UDisks2Observer class to track changes published by UDisks2
self._udisks2_observer = UDisks2Observer()
# Set the initial value of reference_objects.
# The actual value is only set once in check()
self._reference_objects = None
# As above, just initializing in init for sake of consistency
self._is_reference = None
# Setup UDisks2Model to know what the current state is. This is needed
# when remove events are reported as they don't carry enough state for
# the program to work correctly. Since UDisks2Model only applies the
# changes _after_ processing the signals from UDisks2Observer we can
# reliably check all of the properties of the removed object / device.
self._udisks2_model = UDisks2Model(self._udisks2_observer)
# Whenever anything changes call our local change handler
# This handler always computes the full delta (versus the
# reference state) and decides if we have a match or not
self._udisks2_model.on_change.connect(self._on_change)
# We may need an udev context for checking the speed of USB devices
self._udev_client = GUdev.Client()
# A snapshot of udev devices, set in check()
self._reference_udev_devices = None
# Assume the test passes, this is changed when timeout expires or when
# an incorrect device gets inserted.
self._error = False
def _dump_reference_udisks_objects(self):
logging.debug("Reference UDisks2 objects:")
for udisks2_object in self._reference_objects:
logging.debug(" - %s", udisks2_object)
def _dump_reference_udev_devices(self):
logging.debug("Reference udev devices:")
for udev_device in self._reference_udev_devices:
interconnect_speed = get_interconnect_speed(udev_device)
if interconnect_speed:
logging.debug(" - %s (USB %dMBit/s)",
udev_device.get_device_file(),
interconnect_speed)
else:
logging.debug(" - %s", udev_device.get_device_file())
def check(self, timeout):
"""
Run the configured test and return the result
The result is False if the test has failed. The timeout, when
non-zero, will make the test fail after the specified seconds have
elapsed without conclusive result.
"""
# Setup a timeout if requested
if timeout > 0:
GObject.timeout_add_seconds(timeout, self._on_timeout_expired)
# Connect the observer to the bus. This will start giving us events
# (actually when the loop starts later below)
self._udisks2_observer.connect_to_bus(self._bus)
# Get the reference snapshot of available devices
self._reference_objects = copy.deepcopy(self._current_objects)
self._dump_reference_udisks_objects()
# Mark the current _reference_objects as ... reference, this is sadly
# needed by _summarize_changes() as it sees the snapshot _after_ a
# change has occurred and cannot determine if the slope of the 'edge'
# of the change. It is purely needed for UI in verbose mode
self._is_reference = True
# A collection of objects that we gladly ignore because we already
# reported on them being somehow inappropriate
self._ignored_objects = set()
# Get the reference snapshot of available udev devices
self._reference_udev_devices = get_udev_block_devices(
self._udev_client)
self._dump_reference_udev_devices()
# Start the loop and wait. The loop will exit either when:
# 1) A proper device has been detected (either insertion or removal)
# 2) A timeout (optional) has expired
self._loop.run()
# Return the outcome of the test
return self._error
def _on_timeout_expired(self):
"""
Internal function called when the timer expires.
Basically it's just here to tell the user the test failed or that the
user was unable to alter the device during the allowed time.
"""
print("You have failed to perform the required manipulation in time")
# Fail the test when the timeout was reached
self._error = True
# Stop the loop now
self._loop.quit()
def _on_change(self):
"""
Internal method called by UDisks2Model whenever a change had occurred
"""
# Compute the changes that had occurred since the reference point
delta_records = list(self._get_delta_records())
# Display a summary of changes when we are done
self._summarize_changes(delta_records)
# If the changes are what we wanted stop the loop
matching_devices = self._get_matching_devices(delta_records)
if matching_devices:
print("Expected device manipulation complete: {}".format(
', '.join(matching_devices)))
# And call it a day
self._loop.quit()
def _get_matching_devices(self, delta_records):
"""
Internal method called that checks if the delta records match the type
of device manipulation we were expecting. Only called from _on_change()
Returns a set of paths of block devices that matched
"""
# Results
results = set()
# Group changes by DBus object path
grouped_records = collections.defaultdict(list)
for record in delta_records:
grouped_records[record.value.object_path].append(record)
# Create another snapshot od udev devices so that we don't do it over
# and over in the loop below (besides, if we did that then results
# could differ each time).
current_udev_devices = get_udev_block_devices(self._udev_client)
# Iterate over all UDisks2 objects and their delta records
for object_path, records_for_object in grouped_records.items():
# Skip objects we already ignored and complained about before
if object_path in self._ignored_objects:
continue
needs = set(('block-fs', 'partition', 'non-empty', 'mounted'))
# As a special exception when the ConnectionBus is allowed to be
# empty, as is the case with eSATA devices, do not require the
# filesystem to be mounted as gvfs may choose not to mount it
# automatically.
found = set()
drive_object_path = None
object_block_device = None
for record in records_for_object:
# Skip changes opposite to the ones we need
if record.delta_dir != self._desired_delta_dir:
continue
# For devices with empty "ConnectionBus" property, don't
# require the device to be mounted
if (record.value.iface_name ==
"org.freedesktop.UDisks2.Drive"
and record.value.delta_type == DELTA_TYPE_PROP
and record.value.prop_name == "ConnectionBus"
and record.value.prop_value == ""):
needs.remove('mounted')
# Detect block devices designated for filesystems
if (record.value.iface_name ==
"org.freedesktop.UDisks2.Block"
and record.value.delta_type == DELTA_TYPE_PROP
and record.value.prop_name == "IdUsage"
and record.value.prop_value == "filesystem"):
found.add('block-fs')
# Memorize the block device path
elif (record.value.iface_name ==
"org.freedesktop.UDisks2.Block"
and record.value.delta_type == DELTA_TYPE_PROP
and record.value.prop_name == "PreferredDevice"):
object_block_device = record.value.prop_value
# Ensure the device is a partition
elif (record.value.iface_name ==
"org.freedesktop.UDisks2.Partition"
and record.value.delta_type == DELTA_TYPE_IFACE):
found.add('partition')
# Ensure the device is not empty
elif (record.value.iface_name ==
"org.freedesktop.UDisks2.Block"
and record.value.delta_type == DELTA_TYPE_PROP
and record.value.prop_name == "Size"
and record.value.prop_value > 0):
found.add('non-empty')
# Ensure the filesystem is mounted
elif (record.value.iface_name ==
"org.freedesktop.UDisks2.Filesystem"
and record.value.delta_type == DELTA_TYPE_PROP
and record.value.prop_name == "MountPoints"
and record.value.prop_value != []):
found.add('mounted')
# Finally memorize the drive the block device belongs to
elif (record.value.iface_name ==
"org.freedesktop.UDisks2.Block"
and record.value.delta_type == DELTA_TYPE_PROP
and record.value.prop_name == "Drive"):
drive_object_path = record.value.prop_value
logging.debug("Finished analyzing %s, found: %s, needs: %s"
" drive_object_path: %s", object_path, found, needs,
drive_object_path)
if needs != found or drive_object_path is None:
continue
# We've found our candidate, let's look at the drive it belongs
# to. We need to do this as some properties are associated with
# the drive, not the filesystem/block device and the drive may
# not have been inserted at all.
try:
drive_object = self._current_objects[drive_object_path]
except KeyError:
# The drive may be removed along with the device, let's check
# if we originally saw it
try:
drive_object = self._reference_objects[drive_object_path]
except KeyError:
logging.error(
"A block device belongs to a drive we could not find")
logging.error("missing drive: %r", drive_object_path)
continue
try:
drive_props = drive_object["org.freedesktop.UDisks2.Drive"]
except KeyError:
logging.error(
"A block device belongs to an object that is not a Drive")
logging.error("strange object: %r", drive_object_path)
continue
# Ensure the drive is on the appropriate bus
connection_bus = drive_props["ConnectionBus"]
if connection_bus not in self._desired_connection_buses:
logging.warning("The object %r belongs to drive %r that"
" is attached to the bus %r but but we are"
" looking for one of %r so it cannot match",
object_block_device, drive_object_path,
connection_bus,
", ".join(self._desired_connection_buses))
# Ignore this object so that we don't spam the user twice
self._ignored_objects.add(object_path)
continue
# Ensure it is a media card reader if this was explicitly requested
drive_is_reader = is_memory_card(
drive_props['Vendor'], drive_props['Model'],
drive_props['Media'])
if self._desired_memory_card and not drive_is_reader:
logging.warning(
"The object %s belongs to drive %s that does not seem to"
" be a media reader", object_block_device,
drive_object_path)
# Ignore this object so that we don't spam the user twice
self._ignored_objects.add(object_path)
continue
# Ensure the desired minimum speed is enforced
if self._desired_minimum_speed:
# We need to discover the speed of the UDisks2 object that is
# about to be matched. Sadly UDisks2 no longer supports this
# property so we need to poke deeper and resort to udev.
#
# The UDisks2 object that we are interested in implements a
# number of interfaces, most notably
# org.freedesktop.UDisks2.Block, that has the Device property
# holding the unix filesystem path (like /dev/sdb1). We already
# hold a reference to that as 'object_block_device'
#
# We take this as a start and attempt to locate the udev Device
# (don't confuse with UDisks2.Device, they are _not_ the same)
# that is associated with that path.
if self._desired_delta_dir == DELTA_DIR_PLUS:
# If we are looking for additions then look at _current_
# collection of udev devices
udev_devices = current_udev_devices
udisks2_object = self._current_objects[object_path]
else:
# If we are looking for removals then look at referece
# collection of udev devices
udev_devices = self._reference_udev_devices
udisks2_object = self._reference_objects[object_path]
try:
# Try to locate the corresponding udev device among the
# collection we've selected. Use the drive object as the
# key -- this looks for the drive, not partition objects!
udev_device = lookup_udev_device(udisks2_object,
udev_devices)
except LookupError:
logging.error("Unable to map UDisks2 object %s to udev",
object_block_device)
# Ignore this object so that we don't spam the user twice
self._ignored_objects.add(object_path)
continue
interconnect_speed = get_interconnect_speed(udev_device)
# Now that we know the speed of the interconnect we can try to
# validate it against our desired speed.
if interconnect_speed is None:
logging.warning("Unable to determine interconnect speed of"
" device %s", object_block_device)
# Ignore this object so that we don't spam the user twice
self._ignored_objects.add(object_path)
continue
elif interconnect_speed < self._desired_minimum_speed:
logging.warning(
"Device %s is connected via an interconnect that has"
" the speed of %dMbit/s but the required speed was"
" %dMbit/s", object_block_device, interconnect_speed,
self._desired_minimum_speed)
# Ignore this object so that we don't spam the user twice
self._ignored_objects.add(object_path)
continue
else:
logging.info("Device %s is connected via an USB"
" interconnect with the speed of %dMbit/s",
object_block_device, interconnect_speed)
# Yay, success
results.add(object_block_device)
return results
@property
def _current_objects(self):
return self._udisks2_model.managed_objects
def _get_delta_records(self):
"""
Internal method used to compute the delta between reference devices and
current devices. The result is a generator of DeltaRecord objects.
"""
assert self._reference_objects is not None, "Only usable after check()"
old = self._reference_objects
new = self._current_objects
return udisks2_objects_delta(old, new)
def _summarize_changes(self, delta_records):
"""
Internal method used to summarize changes (compared to reference state)
called whenever _on_change() gets called. Only visible in verbose mode
"""
# Filter out anything but interface changes
flat_records = [record
for record in delta_records
if record.value.delta_type == DELTA_TYPE_IFACE]
# Group changes by DBus object path
grouped_records = collections.defaultdict(list)
for record in flat_records:
grouped_records[record.value.object_path].append(record)
# Bail out quickly when nothing got changed
if not flat_records:
if not self._is_reference:
logging.info("You have returned to the reference state")
self._is_reference = True
return
else:
self._is_reference = False
# Iterate over grouped delta records for all objects
logging.info("Compared to the reference state you have:")
for object_path in sorted(grouped_records.keys()):
records_for_object = sorted(
grouped_records[object_path],
key=lambda record: record.value.iface_name)
# Skip any job objects as they just add noise
if any((record.value.iface_name == "org.freedesktop.UDisks2.Job"
for record in records_for_object)):
continue
logging.info("For object %s", object_path)
for record in records_for_object:
# Ignore property changes for now
if record.value.delta_type != DELTA_TYPE_IFACE:
continue
# Get the name of the interface that was affected
iface_name = record.value.iface_name
# Get the properties for that interface (for removals get the
# reference values, for additions get the current values)
if record.delta_dir == DELTA_DIR_PLUS:
props = self._current_objects[object_path][iface_name]
action = "inserted"
else:
props = self._reference_objects[object_path][iface_name]
action = "removed"
# Display some human-readable information associated with each
# interface change
if iface_name == "org.freedesktop.UDisks2.Drive":
logging.info("\t * %s a drive", action)
logging.info("\t vendor and name: %r %r",
props['Vendor'], props['Model'])
logging.info("\t bus: %s", props['ConnectionBus'])
logging.info("\t size: %s", format_bytes(props['Size']))
logging.info("\t is media card: %s", is_memory_card(
props['Vendor'], props['Model'], props['Media']))
logging.info("\t current media: %s",
props['Media'] or "???" if
props['MediaAvailable'] else "N/A")
elif iface_name == "org.freedesktop.UDisks2.Block":
logging.info("\t * %s block device", action)
logging.info("\t from drive: %s", props['Drive'])
logging.info("\t having device: %s", props['Device'])
logging.info("\t having usage, type and version:"
" %s %s %s", props['IdUsage'],
props['IdType'], props['IdVersion'])
logging.info("\t having label: %s", props['IdLabel'])
elif iface_name == "org.freedesktop.UDisks2.PartitionTable":
logging.info("\t * %s partition table", action)
logging.info("\t having type: %r", props['Type'])
elif iface_name == "org.freedesktop.UDisks2.Partition":
logging.info("\t * %s partition", action)
logging.info("\t from partition table: %s",
props['Table'])
logging.info("\t having size: %s",
format_bytes(props['Size']))
logging.info("\t having name: %r", props['Name'])
elif iface_name == "org.freedesktop.UDisks2.Filesystem":
logging.info("\t * %s file system", action)
logging.info("\t having mount points: %r",
props['MountPoints'])
def main():
description = "Wait for the specified device to be inserted or removed."
parser = argparse.ArgumentParser(description=description)
parser.add_argument('action', choices=['insert', 'remove'])
parser.add_argument('device', choices=['usb', 'sdio', 'firewire', 'scsi',
'ata_serial_esata'], nargs="+")
memorycard_help = ("Memory cards devices on bus other than sdio require "
"this parameter to identify them as such")
parser.add_argument('--memorycard', action="store_true",
help=memorycard_help)
parser.add_argument('--timeout', type=int, default=20)
min_speed_help = ("Will only accept a device if its connection speed "
"attribute is higher than this value "
"(in bits/s)")
parser.add_argument('--minimum_speed', '-m', help=min_speed_help,
type=int, default=0)
parser.add_argument('--verbose', action='store_const', const=logging.INFO,
dest='logging_level', help="Enable verbose output")
parser.add_argument('--debug', action='store_const', const=logging.DEBUG,
dest='logging_level', help="Enable debugging")
parser.set_defaults(logging_level=logging.WARNING)
args = parser.parse_args()
# Configure logging as requested
# XXX: This may be incorrect as logging.basicConfig() fails after any other
# call to logging.log(). The proper solution is to setup a verbose logging
# configuration and I didn't want to do it now.
logging.basicConfig(
level=args.logging_level,
format='[%(asctime)s] %(levelname)s:%(name)s:%(message)s')
# Connect to the system bus, we also get the event
# loop as we need it to start listening for signals.
system_bus, loop = connect_to_system_bus()
# Check if system bus has the UDisks2 object
if is_udisks2_supported(system_bus):
# Construct the listener with all of the arguments provided on the
# command line and the explicit system_bus, loop objects.
logging.debug("Using UDisks2 interface")
listener = UDisks2StorageDeviceListener(
system_bus, loop,
args.action, args.device, args.minimum_speed, args.memorycard)
else:
# Construct the listener with all of the arguments provided on the
# command line and the explicit system_bus, loop objects.
logging.debug("Using UDisks1 interface")
listener = UDisks1StorageDeviceListener(
system_bus, loop,
args.action, args.device, args.minimum_speed, args.memorycard)
# Run the actual listener and wait till it either times out of discovers
# the appropriate media changes
try:
return listener.check(args.timeout)
except KeyboardInterrupt:
return 1
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/disk_info 0000775 0001750 0001750 00000004637 12646152433 022551 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
#
# This file is part of Checkbox.
#
# Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
# Industrial Technology Research Institute
#
# Authors:
# Nelson Chu
# Jeff Lane
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
"""
disk_info
Uses lshw to gather information about disks seen by the OS.
Outputs logical name, vendor, description, size and product data
"""
import sys
import xml.etree.ElementTree as ET
from subprocess import check_output
def get_item(disk, attribute):
try:
return disk.find(attribute).text
except AttributeError:
return "Unknown"
def main():
hwinfo_xml = check_output(['lshw', '-c', 'disk', '-xml'])
root = ET.fromstring(hwinfo_xml)
# Parse lshw XML for gathering disk information.
disk_list = root.findall(".//node[@class='disk']")
if not disk_list:
print("No disk information discovered.")
return 10
for disk in disk_list:
if disk.get('id') == 'disk':
print("Name: {}".format(get_item(disk, 'logicalname')))
print("\t{k:15}\t{v}".format(k="Description:",
v=get_item(disk, 'description')))
print("\t{k:15}\t{v}".format(k="Vendor:",
v=get_item(disk, 'vendor')))
print("\t{k:15}\t{v}".format(k="Product:",
v=get_item(disk, 'product')))
try:
disk_size = ("%dGB" % (
int(disk.find('size').text) / (1000**3)))
except TypeError:
disk_size = "No Reported Size"
except AttributeError:
disk_size = "No Reported Size"
print("\t{k:15}\t{v}".format(k="Size:",
v=disk_size))
return 0
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/floppy_test 0000775 0001750 0001750 00000007721 12646152433 023151 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
import filecmp
import subprocess
import posixpath
DEFAULT_DIR = "/tmp/checkbox.floppy"
DEFAULT_DEVICE_DIR = "floppy_device"
DEFAULT_IMAGE_DIR = "floppy_image"
DEFAULT_IMAGE = "floppy.img"
class FloppyTest(object):
def __init__(self, device):
self.device = device
self.device_dir = os.path.join(DEFAULT_DIR, DEFAULT_DEVICE_DIR)
self.image_dir = os.path.join(DEFAULT_DIR, DEFAULT_IMAGE_DIR)
self.image = os.path.join(DEFAULT_DIR, DEFAULT_IMAGE)
self.interactive = True
for dir in (self.device_dir, self.image_dir):
if not posixpath.exists(dir):
os.makedirs(dir)
def run(self):
floppyDevice = self.device
if floppyDevice:
print(" Testing on floppy drive %s " % floppyDevice)
else:
print(" Error ! No floppy drive found !")
return 1
# remove temp files if they exist
os.system("umount /media/floppy 2>/dev/null")
if (os.path.exists(self.device_dir)
or os.path.exists(self.image_dir)
or os.path.exists(self.image)):
os.system("umount %s %s 2>/dev/null"
% (self.device_dir, self.image_dir))
os.system("rm -rf %s %s %s 2>/dev/null"
% (self.device_dir, self.image_dir, self.image))
# Create the test images
os.mkdir(self.device_dir)
os.mkdir(self.image_dir)
os.system("dd if=/dev/zero of=%s bs=1k count=1440" % self.image)
os.system("mkdosfs %s" % self.image)
os.system("mount -o loop %s %s" % (self.image, self.image_dir))
os.system("cp -a /etc/*.conf %s 2> /dev/null" % self.image_dir)
os.system("umount %s" % self.image_dir)
# start testing
(noFloppyDisk, junkOutput1) = \
subprocess.getstatusoutput("dd bs=1c if=%s count=0 2>/dev/null"
% floppyDevice)
if noFloppyDisk != 0:
print("Error ! No floppy disc or bad media in %s !" % floppyDevice)
return 1
else:
# writing files
print(" Writing data to floppy disc ... ")
(ddStatus, ddOutput) = \
subprocess.getstatusoutput("dd if=%s of=%s bs=1k count=1440"
% (self.image, floppyDevice))
if ddStatus == 0:
print(" Write data to floppy disc done ! ")
else:
print(" Error ! Write data to floppy disc error ! ")
print(" Please check if your floppy disc is write-protected !")
return 1
# comparing files
os.system("mount %s %s" % (floppyDevice, self.device_dir))
os.system("mount -o loop %s %s" % (self.image, self.image_dir))
print(" Comparing files ... ")
fileList = os.listdir(self.image_dir)
returnValue = 0
for textFile in fileList:
file1 = os.path.join(self.device_dir, textFile)
file2 = os.path.join(self.image_dir, textFile)
if filecmp.cmp(file1, file2):
print(" comparing file %s" % textFile)
else:
print(" -- Error ! File %s comparison failed ! -- "
% textFile)
returnValue = 1
print(" File comparison done ! ")
# remove temp files
os.system("umount /media/floppy 2>/dev/null")
os.system("umount %s %s " % (self.image_dir, self.device_dir))
os.system("rm -rf %s %s %s"
% (self.device_dir, self.image_dir, self.image))
print("Done !")
return returnValue
def main(args):
return_values = []
for device in args:
test = FloppyTest(device)
return_values.append(test.run())
return 1 in return_values
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/pulse-active-port-change 0000775 0001750 0001750 00000013026 12646152433 025402 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# This file is part of Checkbox.
#
# Copyright 2014 Canonical Ltd.
# Written by:
# Zygmunt Krynicki
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
"""
pulse-active-port-change
========================
This script checks if the active port on either sinks (speakers or headphones)
or sources (microphones, webcams) is changed after an appropriate device is
plugged into the DUT. The script is fully automatic and either times out after
30 seconds or returns as soon as the change is detected.
The script monitors pulse audio events with `pactl subscribe`. Any changes to
sinks (or sources, depending on the mode) are treated as a possible match. A
match is verified by running `pactl list sinks` (or `pactl list sources`) and
constructing a set of tuples (sink-source-name, sink-source-active-port,
sink-source-availability). Any change to the computed set, as compared to the
initially computed set, is considered a match.
Due to the algorithm used, it will also detect things like USB headsets, HDMI
monitors/speakers, webcams, etc.
The script depends on:
python3-checkbox-support
Which depends on:
python3-pyparsing
"""
import argparse
import os
import pty
import signal
import subprocess
from checkbox_support.parsers.pactl import parse_pactl_output
class AudioPlugDetection:
def __init__(self, timeout, mode):
# store parameters
self.timeout = timeout
self.mode = mode
# get the un-localized environment
env = dict(os.environb)
env[b'LANG'] = b''
env[b'LANGUAGE'] = b''
env[b'LC_ALL'] = b'C.UTF-8'
self.unlocalized_env = env
# set SIGALRM handler
signal.signal(signal.SIGALRM, self.on_timeout)
def get_sound_config(self):
text = subprocess.check_output(
["pactl", "list", self.mode], # either 'sources' or 'sinks'
env=self.unlocalized_env, universal_newlines=True)
doc = parse_pactl_output(text)
cfg = set()
for record in doc.record_list:
active_port = None
# We go through the attribute list once to try to find an active port
for attr in record.attribute_list:
if attr.name == "Active Port":
active_port = attr.value
# If there is one, we retrieve its availability flag
if active_port:
for attr in record.attribute_list:
if attr.name == "Ports":
for port in attr.value:
if port.name == active_port:
port_availability = port.availability
cfg.add((record.name, active_port, port_availability))
return cfg
def on_timeout(self, signum, frame):
print("Time is up")
raise SystemExit(1)
@classmethod
def main(cls):
parser = argparse.ArgumentParser(
description=__doc__.split("")[0],
epilog=__doc__.split("")[1],
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
'mode', choices=['sinks', 'sources'],
help='Monitor either sinks or sources')
parser.add_argument(
'-t', '--timeout', type=int, default=30,
help='Timeout after which the script fails')
ns = parser.parse_args()
return cls(ns.timeout, ns.mode).run()
def run(self):
found = False
if self.mode == 'sinks':
look_for = "Event 'change' on sink #"
look_for2 = "Event 'change' on server #"
elif self.mode == 'sources':
look_for = "Event 'change' on source #"
look_for2 = "Event 'change' on server #"
else:
assert False
# Get the initial / baseline configuration
initial_cfg = self.get_sound_config()
print("Starting with config: {}".format(initial_cfg))
print("You have {} seconds to plug something".format(self.timeout))
# Start the timer
signal.alarm(self.timeout)
# run subscribe in a pty as it doesn't fflush() after every event
pid, master_fd = pty.fork()
if pid == 0:
os.execlpe("pactl", "pactl", "subscribe", self.unlocalized_env)
else:
child_stream = os.fdopen(master_fd, "rt", encoding='UTF-8')
try:
for line in child_stream:
if line.startswith(look_for) or line.startswith(look_for2):
new_cfg = self.get_sound_config()
print("Now using config: {}".format(new_cfg))
if new_cfg != initial_cfg:
print("It seems to work!")
found = True
break
except KeyboardInterrupt:
pass
finally:
os.kill(pid, signal.SIGTERM)
os.close(master_fd)
return 0 if found else 1
if __name__ == "__main__":
raise SystemExit(AudioPlugDetection.main())
plainbox-provider-checkbox-0.25/bin/hdd_parking 0000775 0001750 0001750 00000004454 12646152433 023053 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# hdd_parking
#
# This file is part of Checkbox.
#
# Copyright 2014 Canonical Ltd.
#
# Authors: Brendan Donegan
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
"""
This script verifies that a systems HDD protection capabilities
are triggered when appropriate. There are many implementations
of HDD protection from different OEMs, each implemented in a
different way, so this script can only support implementations
which are known to work and are testable. Currently the list
of supported implementations is:
- HDAPS (Lenovo)
"""
import sys
import time
from argparse import ArgumentParser
from subprocess import Popen, PIPE
TIMEOUT = 15.0
def hdaps_test(run_time):
try:
hdapsd = Popen(['/usr/sbin/hdapsd'], stdout=PIPE, stderr=PIPE,
universal_newlines=True)
except OSError as err:
print("Unable to start hdapsd: {}".format(err))
return 1
time.sleep(float(run_time))
hdapsd.terminate()
# Look for parking message in hdapsd output.
stdout = hdapsd.communicate()[0]
print(stdout)
for line in stdout.split('\n'):
if line.endswith('parking'):
return 0
return 1
def main():
# First establish the driver used
parser = ArgumentParser("Tests a systems HDD protection capabilities. "
"Requires the system to be moved by the tester.")
parser.add_argument('-t', '--timeout',
default=TIMEOUT,
help='The time allowed before the test fails.')
print('Starting HDD protection test - move the system around on '
'all axis. No particular force should be required.')
return hdaps_test(parser.parse_args().timeout)
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/key_test 0000775 0001750 0001750 00000030704 12646152433 022425 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
import os
import sys
import fcntl
import gettext
import struct
import termios
from gettext import gettext as _
from gi.repository import GObject
from optparse import OptionParser
EXIT_WITH_FAILURE = 1
EXIT_WITH_SUCCESS = 0
EXIT_TIMEOUT = 30
# Keyboard options from /usr/include/linux/kd.h
K_RAW = 0x00
K_XLATE = 0x01
K_MEDIUMRAW = 0x02
K_UNICODE = 0x03
K_OFF = 0x04
KDGKBMODE = 0x4B44
KDSKBMODE = 0x4B45
def ioctl_p_int(fd, request, value=0):
s = struct.pack("i", value)
s2 = fcntl.ioctl(fd, request, s)
(ret,) = struct.unpack("i", s2) # This always returns a tuple.
return ret
class Key:
def __init__(self, codes, name=None):
self.codes = codes
self.name = name
self.tested = False
self.required = True
@property
def status(self):
if not self.required:
return _("Not required")
if not self.tested:
return _("Untested")
return _("Tested")
class Reporter(object):
exit_code = EXIT_WITH_FAILURE
def __init__(self, main_loop, keys, scancodes=False):
self.main_loop = main_loop
self.keys = keys
self.scancodes = scancodes
self.fileno = os.open("/dev/console", os.O_RDONLY)
GObject.io_add_watch(self.fileno, GObject.IO_IN, self.on_key)
# Set terminal attributes
self.saved_attributes = termios.tcgetattr(self.fileno)
attributes = termios.tcgetattr(self.fileno)
attributes[3] &= ~(termios.ICANON | termios.ECHO)
attributes[6][termios.VMIN] = 1
attributes[6][termios.VTIME] = 0
termios.tcsetattr(self.fileno, termios.TCSANOW, attributes)
# Set keyboard mode
self.saved_mode = ioctl_p_int(self.fileno, KDGKBMODE)
mode = K_RAW if scancodes else K_MEDIUMRAW
fcntl.ioctl(self.fileno, KDSKBMODE, mode)
def _parse_codes(self, raw_bytes):
"""Parse the given string of bytes to scancodes or keycodes."""
if self.scancodes:
return self._parse_scancodes(raw_bytes)
else:
return self._parse_keycodes(raw_bytes)
def _parse_scancodes(self, raw_bytes):
"""Parse the bytes in raw_bytes into a scancode."""
index = 0
length = len(raw_bytes)
while index < length:
if (index + 1 < length and raw_bytes[index] == 0xE0):
code = ((raw_bytes[index] << 8) | raw_bytes[index + 1])
index += 2
else:
code = raw_bytes[0]
index += 1
yield code
def _parse_keycodes(self, raw_bytes):
"""Parse the bytes in raw_bytes into a keycode."""
index = 0
length = len(raw_bytes)
while index < length:
if (index + 2 < length and (raw_bytes[index] & 0x7f) == 0
and (raw_bytes[index + 1] & 0x80) != 0
and (raw_bytes[index + 2] & 0x80) != 0):
code = (((raw_bytes[index + 1] & 0x7f) << 7) |
(raw_bytes[2] & 0x7f))
index += 3
else:
code = (raw_bytes[0] & 0x7f)
index += 1
yield code
@property
def required_keys_tested(self):
"""Returns True if all keys marked as required have been tested"""
return all([key.tested for key in self.keys if key.required])
def show_text(self, string):
pass
def quit(self, exit_code=EXIT_WITH_FAILURE):
self.exit_code = exit_code
termios.tcsetattr(self.fileno, termios.TCSANOW, self.saved_attributes)
fcntl.ioctl(self.fileno, KDSKBMODE, self.saved_mode)
# FIXME: Having a reference to the mainloop is suboptimal.
self.main_loop.quit()
def found_key(self, key):
key.tested = True
def toggle_key(self, key):
key.required = not key.required
key.tested = False
def on_key(self, source, cb_condition):
raw_bytes = os.read(source, 18)
for code in self._parse_codes(raw_bytes):
if code == 1:
# Check for ESC key pressed
self.show_text(_("Test cancelled"))
self.quit()
elif code > 1 and code < 10:
# Check for number to skip
self.toggle_key(self.keys[code - 2])
else:
# Check for other key pressed
for key in self.keys:
if code in key.codes:
self.found_key(key)
break
return True
class CLIReporter(Reporter):
def __init__(self, *args, **kwargs):
super(CLIReporter, self).__init__(*args, **kwargs)
self.show_text(_("Please press each key on your keyboard."))
self.show_text(_("I will exit automatically once all keys "
"have been pressed."))
self.show_text(_("If your keyboard lacks one or more keys, "
"press its number to skip testing that key."))
self.show_text(_("You can also close me by pressing ESC or Ctrl+C."))
self.show_keys()
def show_text(self, string):
sys.stdout.write(string + "\n")
sys.stdout.flush()
def show_keys(self):
self.show_text("---")
for index, key in enumerate(self.keys):
self.show_text(
"%(number)d - %(key)s - %(status)s" %
{"number": index + 1, "key": key.name, "status": key.status})
def found_key(self, key):
super(CLIReporter, self).found_key(key)
self.show_text(
_("%(key_name)s key has been pressed" % {'key_name': key.name}))
self.show_keys()
if self.required_keys_tested:
self.show_text(_("All required keys have been tested!"))
self.quit(EXIT_WITH_SUCCESS)
def toggle_key(self, key):
super(CLIReporter, self).toggle_key(key)
self.show_keys()
class GtkReporter(Reporter):
def __init__(self, *args, **kwargs):
super(GtkReporter, self).__init__(*args, **kwargs)
from gi.repository import Gdk, Gtk
# Initialize GTK constants
self.ICON_SIZE = Gtk.IconSize.BUTTON
self.ICON_TESTED = Gtk.STOCK_YES
self.ICON_UNTESTED = Gtk.STOCK_INDEX
self.ICON_NOT_REQUIRED = Gtk.STOCK_REMOVE
self.button_factory = Gtk.Button
self.hbox_factory = Gtk.HBox
self.image_factory = Gtk.Image
self.label_factory = Gtk.Label
self.vbox_factory = Gtk.VBox
# Create GTK window.
window = Gtk.Window()
window.set_type_hint(Gdk.WindowType.TOPLEVEL)
window.set_size_request(100, 100)
window.set_resizable(False)
window.set_title(_("Key test"))
window.connect("delete_event", lambda w, e: self.quit())
window.connect(
"key-release-event",
lambda w, k: k.keyval == Gdk.KEY_Escape and self.quit())
window.show()
# Add common widgets to the window.
vbox = self._add_vbox(window)
self.label = self._add_label(vbox)
button_hbox = self._add_hbox(vbox)
validation_hbox = self._add_hbox(vbox)
skip_hbox = self._add_hbox(vbox)
exit_button = self._add_button(vbox, _("_Exit"), True)
exit_button.connect("clicked", lambda w: self.quit())
# Add widgets for each key.
self.icons = {}
for key in self.keys:
stock = getattr(Gtk, "STOCK_MEDIA_%s" % key.name.upper(), None)
if stock:
self._add_image(button_hbox, stock)
else:
self._add_label(button_hbox, key.name)
self.icons[key] = self._add_image(validation_hbox, Gtk.STOCK_INDEX)
button = self._add_button(skip_hbox, _("Skip"))
button.connect("clicked", self.on_skip, key)
self.show_text(_("Please press each key on your keyboard."))
self.show_text(_("If a key is not present in your keyboard, "
"press the 'Skip' button below it to remove it "
"from the test."))
def _add_button(self, context, label, use_underline=False):
button = self.button_factory(label=label, use_underline=use_underline)
context.add(button)
button.show()
return button
def _add_hbox(self, context, spacing=4):
hbox = self.hbox_factory()
context.add(hbox)
hbox.set_spacing(4)
hbox.show()
return hbox
def _add_image(self, context, stock):
image = self.image_factory(stock=stock, icon_size=self.ICON_SIZE)
context.add(image)
image.show()
return image
def _add_label(self, context, text=None):
label = self.label_factory()
context.add(label)
label.set_size_request(0, 0)
label.set_line_wrap(True)
if text:
label.set_text(text)
label.show()
return label
def _add_vbox(self, context):
vbox = self.vbox_factory()
vbox.set_homogeneous(False)
vbox.set_spacing(8)
context.add(vbox)
vbox.show()
return vbox
def show_text(self, string):
self.label.set_text(self.label.get_text() + "\n" + string)
def check_keys(self):
if self.required_keys_tested:
self.show_text(_("All required keys have been tested!"))
self.quit(EXIT_WITH_SUCCESS)
def found_key(self, key):
super(GtkReporter, self).found_key(key)
self.icons[key].set_from_stock(self.ICON_TESTED, size=self.ICON_SIZE)
self.check_keys()
def on_skip(self, sender, key):
self.toggle_key(key)
if key.required:
stock_icon = self.ICON_UNTESTED
else:
stock_icon = self.ICON_NOT_REQUIRED
self.icons[key].set_from_stock(stock_icon, self.ICON_SIZE)
self.check_keys()
def main(args):
gettext.textdomain("checkbox")
usage = """\
Usage: %prog [OPTIONS] CODE...
Syntax for codes:
57435 - Decimal code without name
0160133:Super - Octal code with name
0xe05b,0xe0db:Super - Multiple hex codes with name
Hint to find codes:
The showkey command can show keycodes and scancodes.
"""
parser = OptionParser(usage=usage)
parser.add_option("-i", "--interface",
default="auto",
help="Interface to use: cli, gtk or auto")
parser.add_option("-s", "--scancodes",
default=False,
action="store_true",
help="Test for scancodes instead of keycodes.")
(options, args) = parser.parse_args(args)
# Get reporter factory from options or environment.
if options.interface == "auto":
if "DISPLAY" in os.environ:
reporter_factory = GtkReporter
else:
reporter_factory = CLIReporter
elif options.interface == "cli":
reporter_factory = CLIReporter
elif options.interface == "gtk":
reporter_factory = GtkReporter
else:
parser.error("Unsupported interface: %s" % options.interface)
if not args:
parser.error("Must specify codes to test.")
# Get keys from command line arguments.
keys = []
for codes_name in args:
if ":" in codes_name:
codes, name = codes_name.split(":", 1)
else:
codes, name = codes_name, codes_name
# Guess the proper base from the string.
codes = [int(code, 0) for code in codes.split(",")]
key = Key(codes, name)
keys.append(key)
main_loop = GObject.MainLoop()
try:
reporter = reporter_factory(main_loop, keys, options.scancodes)
except:
parser.error("Failed to initialize interface: %s" % options.interface)
try:
main_loop.run()
except KeyboardInterrupt:
reporter.show_text(_("Test interrupted"))
reporter.quit()
return reporter.exit_code
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/pts_run 0000775 0001750 0001750 00000001715 12646152433 022270 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
# Exit on any error
set -o errexit
# Accept Terms & Conditions, disable anonymous reporting
echo -e "Y\nn\nn" | phoronix-test-suite > /dev/null
# Disable batch result saving and all test options selection
echo -e "n\nn" | phoronix-test-suite batch-setup > /dev/null
# Don't show the browser after each test.
# The implementation is a bit hacky but works.
phoronix-test-suite user-config-set DefaultBrowser=/bin/true
# Run each test only one time
export FORCE_TIMES_TO_RUN=1
# Run only the following resolution
export OVERRIDE_VIDEO_MODES=800x600
set +o errexit
rv=0
output=$(phoronix-test-suite batch-benchmark $@ 2>&1)
#The output does NOT report success. It may contain, if it fails:
# The test did not produce a result
# The test failed to run properly
# Failed to Fetch
if (echo "$output" | grep -q -i "Failed to fetch" ); then
rv=1
fi
if ( echo "$output" | grep -q -i 'This test failed to run properly'); then
rv=1
fi
echo "$output"
exit $rv
plainbox-provider-checkbox-0.25/bin/window_test 0000775 0001750 0001750 00000024337 12646152433 023151 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# window_test
#
# This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
#
# Authors: Alberto Milone
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
import threading
import time
import os
import sys
from signal import SIGTSTP, SIGCONT, SIGTERM
from subprocess import check_call, check_output, Popen, PIPE
from argparse import ArgumentParser
class AppThread(threading.Thread):
def __init__(self, app_name):
self._appname = app_name
self.stdout = None
self.stderr = None
self.pid = None
threading.Thread.__init__(self)
def run(self):
proc = Popen(self._appname, stdout=PIPE, stderr=PIPE)
self.pid = proc.pid
print(' Starting "%s", PID: %d' %
(self._appname, self.pid))
self.stdout, self.stderr = proc.communicate()
def open_close_process(app, timeout):
'''Open and close a process after a timeout'''
status = 0
# Start the process in a separate thread
app_thread = AppThread(app)
app_thread.start()
# Wait until we have a pid
while app_thread.pid is None:
continue
pid = app_thread.pid
# Wait a bit and kill the process
time.sleep(timeout)
print(' Killing "%s", PID: %d' % (app, pid))
os.kill(pid, SIGTERM)
if app_thread.stderr:
print('Errors:\n%s' % app_thread.stderr, file=sys.stderr)
status = 1
time.sleep(timeout)
return status
def open_close_multi_process(app, timeout, apps_num):
'''Open and close multiple processes after a timeout'''
status = 0
threads = []
for thread in range(apps_num):
app_thread = AppThread(app)
app_thread.start()
threads.append(app_thread)
for thread in threads:
# Wait until we have a pid
while thread.pid is None:
continue
# Wait a bit and kill the process
time.sleep(timeout)
for thread in threads:
print(' Killing "%s", PID: %d' % (app, thread.pid))
os.kill(thread.pid, SIGTERM)
if thread.stderr:
print('Errors:\n%s' % thread.stderr, file=sys.stderr)
status = 1
time.sleep(timeout)
return status
def open_suspend_close_process(app, timeout):
'''Open, suspend and close a process after a timeout'''
status = 0
# Start the process in a separate thread
app_thread = AppThread(app)
app_thread.start()
# Wait until we have a pid
while app_thread.pid is None:
continue
pid = app_thread.pid
# Wait a bit and suspend the process
time.sleep(timeout)
print(' Suspending "%s", PID: %d' % (app, pid))
os.kill(pid, SIGTSTP)
# Wait a bit and resume the process
time.sleep(timeout)
print(' Resuming "%s", PID: %d' % (app, pid))
os.kill(pid, SIGCONT)
# Wait a bit and kill the process
time.sleep(timeout)
print(' Killing "%s", PID: %d' % (app, pid))
os.kill(pid, SIGTERM)
if app_thread.stderr:
print('Errors:\n%s' % app_thread.stderr, file=sys.stderr)
status = 1
time.sleep(timeout)
return status
def move_window(app, timeout):
status = 0
# Start the process in a separate thread
app_thread = AppThread(app)
app_thread.start()
while app_thread.pid is None:
continue
pid = app_thread.pid
time.sleep(3)
window_list = check_output(['wmctrl', '-l'], universal_newlines=True)
window_id = ''
for line in window_list.split('\n'):
if app in line:
window_id = line.split()[0]
if window_id:
# Get the screen information from GDK
from gi.repository import Gdk
screen = Gdk.Screen.get_default()
geom = screen.get_monitor_geometry(screen.get_primary_monitor())
# Find out the window information from xwininfo
win_x = ''
win_y = ''
win_width = ''
win_height = ''
for line in check_output(['xwininfo', '-name', app],
universal_newlines=True).split('\n'):
if 'Absolute upper-left X' in line:
win_x = line.split(': ')[-1].strip()
elif 'Absolute upper-left Y' in line:
win_y = line.split(': ')[-1].strip()
elif 'Width' in line:
win_width = line.split(': ')[-1].strip()
elif 'Height' in line:
win_height = line.split(': ')[-1].strip()
move_line = ["0", win_x, win_y, win_width, win_height]
directions = {'RIGHT': geom.width,
'DOWN': geom.height,
'LEFT': win_x,
'UP': win_y,
'STOP': None}
current = 'RIGHT'
while current != 'STOP':
if current == 'RIGHT':
# Check if top right corner of window reached top right point
if int(move_line[1]) + int(win_width) != directions[current]:
new_x = int(move_line[1]) + 1
move_line[1] = str(new_x)
else:
current = 'DOWN'
elif current == 'DOWN':
if int(move_line[2]) + int(win_height) != directions[current]:
new_y = int(move_line[2]) + 1
move_line[2] = str(new_y)
else:
current = 'LEFT'
elif current == 'LEFT':
if int(move_line[1]) != int(directions[current]):
new_x = int(move_line[1]) - 1
move_line[1] = str(new_x)
else:
current = 'UP'
elif current == 'UP':
if int(move_line[2]) != int(directions[current]):
new_y = int(move_line[2]) - 1
move_line[2] = str(new_y)
else:
current = 'STOP'
check_call(['wmctrl', '-i', '-r', window_id,
'-e', ','.join(move_line)])
os.kill(pid, SIGTERM)
else:
print("Could not get window handle for %s" % app, file=sys.stderr)
status = 1
return status
def print_open_close(iterations, timeout, *args):
status = 0
print('Opening and closing a 3D window')
for it in range(iterations):
print('Iteration %d of %d:' % (it + 1, iterations))
exit_status = open_close_process('glxgears', timeout)
if exit_status != 0:
status = 1
print('')
return status
def print_suspend_resume(iterations, timeout, *args):
status = 0
print('Opening, suspending, resuming and closing a 3D window')
for it in range(iterations):
print('Iteration %d of %d:' % (it + 1, iterations))
exit_status = open_suspend_close_process('glxgears', timeout)
if exit_status != 0:
status = 1
print('')
return status
def print_open_close_multi(iterations, timeout, windows_number):
status = 0
print('Opening and closing %d 3D windows at the same time'
% windows_number)
for it in range(iterations):
print('Iteration %d of %d:' % (it + 1, iterations))
exit_status = open_close_multi_process('glxgears',
timeout,
windows_number)
if exit_status != 0:
status = 1
print('')
return status
def print_move_window(iterations, timeout, *args):
status = 0
print('Moving a 3D window across the screen')
for it in range(iterations):
print('Iteration %d of %d:' % (it + 1, iterations))
exit_status = move_window('glxgears',
timeout)
print('')
return status
def main():
tests = {'open-close': print_open_close,
'suspend-resume': print_suspend_resume,
'open-close-multi': print_open_close_multi,
'move': print_move_window}
parser = ArgumentParser(description='Script that performs window operation')
parser.add_argument('-t', '--test',
default='all',
help='The name of the test to run. \
Available tests: \
%s, all. \
Default is all' % (', '.join(tests)))
parser.add_argument('-i', '--iterations',
type=int,
default=1,
help='The number of times to run the test. \
Default is 1')
parser.add_argument('-a', '--application',
default='glxgears',
help='The 3D application to launch. \
Default is "glxgears"')
parser.add_argument('-to', '--timeout',
type=int,
default=3,
help='The time in seconds between each test. \
Default is 3')
parser.add_argument('-w', '--windows-number',
type=int,
default=4,
help='The number of windows to open.')
args = parser.parse_args()
status = 0
test = tests.get(args.test)
if test:
status = test(args.iterations, args.timeout, args.windows_number)
else:
if args.test == 'all':
for test in tests:
exit_status = tests[test](args.iterations, args.timeout,
args.windows_number)
if exit_status != 0:
status = exit_status
else:
parser.error('-t or --test can only be used with one '
'of the following tests: '
'%s, all' % (', '.join(tests)))
return status
if __name__ == '__main__':
exit(main())
plainbox-provider-checkbox-0.25/bin/wireless_ext 0000775 0001750 0001750 00000000351 12646152433 023306 0 ustar sylvain sylvain 0000000 0000000 #!/bin/sh
if lsmod | grep -q "80211"
then
echo "Driver is using MAC80211"
if iwconfig 2>&1 | grep -q "IEEE 802.11"
then
echo "Driver has loaded wireless extension"
exit 0
else
echo "No wireless module loaded"
exit 1
fi
fi
plainbox-provider-checkbox-0.25/bin/memory_test 0000775 0001750 0001750 00000020734 12646152433 023147 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
import re
from argparse import ArgumentParser
from subprocess import Popen, PIPE
class MemoryTest():
def __init__(self):
self.free_memory = 0
self.system_memory = 0
self.swap_memory = 0
self.process_memory = 0
self.is_process_limited = False
@property
def threaded_memtest_script(self):
directory = os.path.dirname(os.path.abspath(__file__))
return os.path.join(directory, "threaded_memtest")
def _get_memory(self):
mem_info = open("/proc/meminfo", "r")
try:
while True:
line = mem_info.readline()
if line:
tokens = line.split()
if len(tokens) == 3:
if "MemTotal:" == tokens[0].strip():
self.system_memory = \
int(tokens[1].strip()) // 1024
elif tokens[0].strip() in ["MemFree:",
"Cached:",
"Buffers:"]:
self.free_memory += \
int(tokens[1].strip()) // 1024
elif "SwapTotal:" == tokens[0].strip():
self.swap_memory = \
int(tokens[1].strip()) // 1024
else:
break
except Exception as e:
print("ERROR: Unable to get data from /proc/meminfo",
file=sys.stderr)
print(e, file=sys.stderr)
finally:
mem_info.close()
def _command(self, command, shell=True):
proc = Popen(command,
shell=shell,
stdout=PIPE,
stderr=PIPE)
return proc
def _command_out(self, command, shell=True):
proc = self._command(command, shell)
return proc.communicate()[0].strip()
def get_limits(self):
self._get_memory()
print("System Memory: %u MB" % self.system_memory)
print("Free Memory: %u MB" % self.free_memory)
print("Swap Memory: %u MB" % self.swap_memory)
if self.system_memory == 0:
print("ERROR: could not determine system RAM", file=sys.stderr)
return False
# Process Memory
self.process_memory = self.free_memory
try:
arch = self._command_out("arch").decode()
if (re.match(r"(i[0-9]86|s390|arm.*)", arch)
and self.free_memory > 1024):
self.is_process_limited = True
self.process_memory = 1024 # MB, due to 32-bit address space
print("%s arch, Limiting Process Memory: %u" % (
arch, self.process_memory))
# others? what about PAE kernel?
except Exception as e:
print("ERROR: could not determine system architecture via arch",
file=sys.stderr)
print(e, file=sys.stderr)
return False
return True
def run(self):
PASSED = 0
FAILED = 1
limits = self.get_limits()
if not limits:
return FAILED
# if process memory is limited, run multiple processes
if self.is_process_limited:
print("Running Multiple Process Memory Test")
if not self.run_multiple_process_test():
return FAILED
else:
print("Running Single Process Memory Test")
if not self.run_single_process_test():
return FAILED
# otherwised, passed
return PASSED
def run_single_process_test(self):
if not self.run_threaded_memory_test():
return False
return True
def run_multiple_process_test(self):
processes = self.free_memory // self.process_memory
# if not swap-less, add a process to hit swap
if not self.swap_memory == 0:
processes += 1
# check to make sure there's enough swap
required_memory = self.process_memory * processes
if required_memory > self.system_memory + self.swap_memory:
print("ERROR: this test requires a minimum of %u KB of swap "
"memory (%u configured)" % (
required_memory - self.system_memory,
self.swap_memory), file=sys.stderr)
print("Testing memory with %u processes" % processes)
print("Running threaded memory test:")
run_time = 60 # sec.
if not self.run_processes(processes, "%s -qv -m%um -t%u" % (
self.threaded_memtest_script, self.process_memory, run_time)):
print("Multi-process, threaded memory Test FAILED",
file=sys.stderr)
return False
return True
def run_threaded_memory_test(self):
# single-process threaded test
print("Starting Threaded Memory Test")
# run for Free Memory plus the lessor of 5% or 1GB
memory = (self.free_memory * 5) / 100
if memory > 1024: # MB
memory = 1024 # MB
memory = memory + self.free_memory
print("Running for %d MB total memory" % memory)
# run a test that will swap
if not self.swap_memory == 0:
# is there enough swap memory for the test?
if memory > self.system_memory + self.swap_memory:
print("ERROR: this test requires a minimum of %u KB of swap "
"memory (%u configured)"
% (memory - self.system_memory, self.swap_memory),
file=sys.stderr)
return False
# otherwise
run_time = 60 # sec.
print("Running for more than free memory at %u MB for %u sec." % (
memory, run_time))
command = "%s -qv -m%um -t%u" % (
self.threaded_memtest_script, memory, run_time)
print("Command is: %s" % command)
process = self._command(command)
process.communicate()
if process.returncode != 0:
print("%s returned code %s" % (self.threaded_memtest_script,
process.returncode), file=sys.stderr)
print("More Than Free Memory Test failed", file=sys.stderr)
return False
print("More than free memory test complete.")
# run again for 15 minutes
print("Running for free memory")
process = self._command("%s -qv" % self.threaded_memtest_script)
process.communicate()
if process.returncode != 0:
print("Free Memory Test failed", file=sys.stderr)
else:
print("Free Memory Test succeeded")
sys.stdout.flush()
return (process.returncode == 0)
def run_processes(self, number, command):
passed = True
pipe = []
for i in range(number):
pipe.append(self._command(command))
print("Started: process %u pid %u: %s" % (i, pipe[i].pid, command))
sys.stdout.flush()
waiting = True
while waiting:
waiting = False
for i in range(number):
if pipe[i]:
line = pipe[i].communicate()[0]
if line and len(line) > 1:
print("process %u pid %u: %s" % (i, pipe[i].pid, line))
sys.stdout.flush()
if pipe[i].poll() == -1:
waiting = True
else:
return_value = pipe[i].poll()
if return_value != 0:
print("ERROR: process %u pid %u retuned %u"
% (i, pipe[i].pid, return_value),
file=sys.stderr)
passed = False
print("process %u pid %u returned success"
% (i, pipe[i].pid))
pipe[i] = None
sys.stdout.flush()
return passed
def main(args):
parser = ArgumentParser()
parser.add_argument("-q", "--quiet", action="store_true",
help="Suppress output.")
args = parser.parse_args(args)
if args.quiet:
sys.stdout = open(os.devnull, 'a')
sys.stderr = open(os.devnull, 'a')
test = MemoryTest()
return test.run()
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/gst_pipeline_test 0000775 0001750 0001750 00000004373 12646152433 024322 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
from argparse import ArgumentParser
import logging
import re
import os
import sys
import time
from gi.repository import Gst
from gi.repository import GLib
from subprocess import check_output
def check_state(device):
"""Checks whether the sink is available for the given device.
"""
sink_info = check_output(['pacmd', 'list-sinks'],
universal_newlines=True)
data = sink_info.split("\n")
try:
device_name = re.findall(".*name:\s.*%s.*" % device, sink_info)[0].lstrip()
sink = re.findall(".*name:\s<(.*%s.*)>" % device, sink_info)[0].lstrip()
status = data[data.index("\t" + device_name) + 3]
except (IndexError, ValueError):
logging.error("Failed to find status for device: %s" % device)
return False
os.environ['PULSE_SINK'] = sink
logging.info("[ Pulse sink ]".center(80, '='))
logging.info("Device: %s %s" % (device_name.strip(), status.strip()))
return status
def main():
parser = ArgumentParser(description='Simple GStreamer pipeline player')
parser.add_argument('PIPELINE',
help='Quoted GStreamer pipeline to launch')
parser.add_argument('-t', '--timeout',
type=int, required=True,
help='Timeout for running the pipeline')
parser.add_argument('-d', '--device',
type=str,
help="Device to check for status")
args = parser.parse_args()
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO,
stream=sys.stdout)
exit_code = 0
if args.device:
if not check_state(args.device):
exit_code = 1
Gst.init(None)
try:
print("Attempting to initialize Gstreamer pipeline: {}".format(
args.PIPELINE))
element = Gst.parse_launch(args.PIPELINE)
except GLib.GError as error:
print("Specified pipeline couldn't be processed.")
print("Error when processing pipeline: {}".format(error))
#Exit harmlessly
return(2)
print("Pipeline initialized, now starting playback.")
element.set_state(Gst.State.PLAYING)
if args.timeout:
time.sleep(args.timeout)
element.set_state(Gst.State.NULL)
return exit_code
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/process_wait 0000775 0001750 0001750 00000003524 12646152433 023300 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
import time
from optparse import OptionParser
from subprocess import Popen, PIPE
COMMAND_FORMAT = "pgrep -f %(options)s %(process)s"
def process_pids(process, *options):
options_string = " ".join(options)
command = COMMAND_FORMAT % {"options": options_string, "process": process}
# Exclude this process and the pgrep process
subprocess = Popen(
command, stdout=PIPE, shell=True, universal_newlines=True)
exclude_pids = [os.getpid(), os.getppid(), subprocess.pid]
pids_string = subprocess.communicate()[0]
pids = [int(pid) for pid in pids_string.split()]
result = set(pids).difference(exclude_pids)
return list(result)
def process_count(*args):
return len(process_pids(*args))
def main(args):
default_sleep = 1
usage = "Usage: %prog PROCESS [PROCESS...]"
parser = OptionParser(usage=usage)
parser.add_option("-s", "--sleep",
type="int",
default=default_sleep,
help="Number of seconds to sleep between checks.")
parser.add_option("-t", "--timeout",
type="int",
help="Number of seconds to timeout from sleeping.")
parser.add_option("-u", "--uid",
help="Effective user name or id of the running processes")
(options, processes) = parser.parse_args(args)
process_args = []
if options.uid is not None:
process_args.extend(["-u", options.uid])
while True:
for process in processes:
if process_count(process, *process_args):
break
else:
break
if options.timeout is not None:
if options.timeout <= 0:
return 1
else:
options.timeout -= options.sleep
time.sleep(options.sleep)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/network_printer_test 0000775 0001750 0001750 00000002072 12646152433 025066 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
usage() {
cat < ] [ -s ]
-p -- specify a printer to use, by name
-s -- specify a network server to use
Note: this script expects printers over the IPP protocol only.
EOU
}
while [ $# -gt 0 ]
do
case "$1" in
-p)
if echo ${2} | grep -q -c '^-'; then
usage
exit 1
fi
printer=${2}
shift
;;
-s)
if echo ${2} | grep -q -c '^-'; then
usage
exit 1
fi
server=${2}
shift
;;
--usage)
usage
exit 1
;;
esac
shift
done
if [ -z $server ]; then
echo "Nothing to do with no server defined. (See $0 --usage)"
exit 0
fi
printer=${printer:-PDF}
lpadmin -E -v ipp://${server}/printers/${printer}
cupsenable ${printer}
cupsaccept ${printer}
lsb_release -a | lp -t "lsb_release" -d ${printer}
plainbox-provider-checkbox-0.25/bin/spindown 0000775 0001750 0001750 00000005224 12646152433 022436 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# Copyright (C) 2012 Canonical
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
get_load_cycle()
{
smartctl -A /dev/sda | grep Load_Cycle_Count | awk '{print $10}'
}
get_time_secs()
{
date "+%s"
}
if [ $EUID -ne 0 ]; then
echo "Need to run as root e.g. use sudo"
exit 1
fi
hdparm -B 127 /dev/sda
TEST_FILE=test
MAX_TIMEOUT=60
MAX_ITERATIONS=10
dirty_disk()
{
rm -f ${TEST_FILE}
touch ${TEST_FILE}
truncate -s 4K ${TEST_FILE}
}
drop_caches()
{
sync
(echo 1 | sudo tee /proc/sys/vm/drop_caches) > /dev/null
(echo 2 | sudo tee /proc/sys/vm/drop_caches) > /dev/null
(echo 3 | sudo tee /proc/sys/vm/drop_caches) > /dev/null
}
find_load_cycle_threshold()
{
lc1=0
lc2=0
count=0
TIMEOUT=1
echo Attempting to find Spin Down timeout for this HDD
while [ $lc1 -eq $lc2 -a $TIMEOUT -lt $MAX_TIMEOUT ]
do
lc1=$(get_load_cycle)
count=$((count + 1))
dirty_disk
drop_caches
sleep $TIMEOUT
lc2=$(get_load_cycle)
n=$((lc2 - lc1))
echo Checking with timeout: $TIMEOUT seconds, Load Cycles: $n
if [ $TIMEOUT -lt 15 ]; then
TIMEOUT=$((TIMEOUT + 1))
else
TIMEOUT=$((TIMEOUT + $TIMEOUT/5))
fi
done
}
exercise_load_cycle()
{
echo "Attempting to exercise load cycle on HDD"
i=0
t1=$(get_time_secs)
n1=$(get_load_cycle)
# bump timeout by 1 second just to make sure
# we can always catch the load cycle window
TIMEOUT=$((TIMEOUT + 1))
while [ $i -lt $MAX_ITERATIONS ]
do
i=$((i + 1))
echo "Load Cycle $i of $MAX_ITERATIONS"
dirty_disk
drop_caches
sleep $TIMEOUT
done
i=0
t2=$(get_time_secs)
n2=$(get_load_cycle)
t=$((t2 - t1))
n=$((n2 - n1))
echo "Managed to force $n Load Cycles in $t seconds."
life=$((1000000 * $t / $n))
days=$((life / (3600 * 24)))
echo "At this rate, the HDD will fail after $days days."
}
find_load_cycle_threshold
if [ $TIMEOUT -lt $MAX_TIMEOUT ]; then
echo "HDD seems to be spinning down aggressively."
exercise_load_cycle
exit 1
else
echo "Gave up looking for Load Cycle timeout threshold, HDD looks sane."
exit 0
fi
plainbox-provider-checkbox-0.25/bin/alsa_info 0000775 0001750 0001750 00000066211 12646152433 022533 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
SCRIPT_VERSION=0.4.61
CHANGELOG="http://www.alsa-project.org/alsa-info.sh.changelog"
#################################################################################
#Copyright (C) 2007 Free Software Foundation.
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
##################################################################################
#The script was written for 2 main reasons:
# 1. Remove the need for the devs/helpers to ask several questions before we can easily help the user.
# 2. Allow newer/inexperienced ALSA users to give us all the info we need to help them.
#Set the locale (this may or may not be a good idea.. let me know)
export LC_ALL=C
#Change the PATH variable, so we can run lspci (needed for some distros)
PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin
BGTITLE="ALSA-Info v $SCRIPT_VERSION"
PASTEBINKEY="C9cRIO8m/9y8Cs0nVs0FraRx7U0pHsuc"
#Define some simple functions
pbcheck(){
[[ $UPLOAD = "no" ]] && return
if [[ -z $PASTEBIN ]]; then
[[ $(ping -c1 www.alsa-project.org) ]] || KEEP_FILES="yes" UPLOAD="no" PBERROR="yes"
else
[[ $(ping -c1 www.pastebin.ca) ]] || KEEP_FILES="yes" UPLOAD="no" PBERROR="yes"
fi
}
update() {
SHFILE=`mktemp -t alsa-info.XXXXXXXXXX` || exit 1
wget -O $SHFILE "http://www.alsa-project.org/alsa-info.sh" >/dev/null 2>&1
REMOTE_VERSION=`grep SCRIPT_VERSION $SHFILE |head -n1 |sed 's/.*=//'`
if [ "$REMOTE_VERSION" != "$SCRIPT_VERSION" ]; then
if [[ -n $DIALOG ]]
then
OVERWRITE=
if [ -w $0 ]; then
dialog --yesno "Newer version of ALSA-Info has been found\n\nDo you wish to install it?\nNOTICE: The original file $0 will be overwritten!" 0 0
DIALOG_EXIT_CODE=$?
if [[ $DIALOG_EXIT_CODE = 0 ]]; then
OVERWRITE=yes
fi
fi
if [ -z "$OVERWRITE" ]; then
dialog --yesno "Newer version of ALSA-Info has been found\n\nDo you wish to download it?" 0 0
DIALOG_EXIT_CODE=$?
fi
if [[ $DIALOG_EXIT_CODE = 0 ]]
then
echo "Newer version detected: $REMOTE_VERSION"
echo "To view the ChangeLog, please visit $CHANGELOG"
if [ "$OVERWRITE" = "yes" ]; then
cp $SHFILE $0
echo "ALSA-Info script has been updated to v $REMOTE_VERSION"
echo "Please re-run the script"
rm $SHFILE 2>/dev/null
else
echo "ALSA-Info script has been downloaded as $SHFILE."
echo "Please re-run the script from new location."
fi
exit
else
rm $SHFILE 2>/dev/null
fi
else
echo "Newer version detected: $REMOTE_VERSION"
echo "To view the ChangeLog, please visit $CHANGELOG"
if [ -w $0 ]; then
echo "The original file $0 will be overwritten!"
echo -n "If you do not like to proceed, press Ctrl-C now.." ; read inp
cp $SHFILE $0
echo "ALSA-Info script has been updated. Please re-run it."
rm $SHFILE 2>/dev/null
else
echo "ALSA-Info script has been downloaded $SHFILE."
echo "Please, re-run it from new location."
fi
exit
fi
else
rm $SHFILE 2>/dev/null
fi
}
cleanup() {
if [ -n "$TEMPDIR" -a "$KEEP_FILES" != "yes" ]; then
rm -rf "$TEMPDIR" 2>/dev/null
fi
test -n "$KEEP_OUTPUT" || rm -f "$NFILE"
}
withaplay() {
echo "!!Aplay/Arecord output" >> $FILE
echo "!!--------------------" >> $FILE
echo "" >> $FILE
echo "APLAY" >> $FILE
echo "" >> $FILE
aplay -l >> $FILE 2>&1
echo "" >> $FILE
echo "ARECORD" >> $FILE
echo "" >> $FILE
arecord -l >> $FILE 2>&1
echo "" >> $FILE
}
withlsmod() {
echo "!!All Loaded Modules" >> $FILE
echo "!!------------------" >> $FILE
echo "" >> $FILE
lsmod |awk {'print $1'} >> $FILE
echo "" >> $FILE
echo "" >> $FILE
}
withamixer() {
echo "!!Amixer output" >> $FILE
echo "!!-------------" >> $FILE
echo "" >> $FILE
for i in `grep "]: " /proc/asound/cards | awk -F ' ' '{ print $1} '` ; do
CARD_NAME=`grep "^ *$i " $TEMPDIR/alsacards.tmp|awk {'print $2'}`
echo "!!-------Mixer controls for card $i $CARD_NAME]" >> $FILE
echo "" >>$FILE
amixer -c$i info>> $FILE 2>&1
amixer -c$i>> $FILE 2>&1
echo "" >> $FILE
done
echo "" >> $FILE
}
withalsactl() {
echo "!!Alsactl output" >> $FILE
echo "!!--------------" >> $FILE
echo "" >> $FILE
exe=""
if [ -x /usr/sbin/alsactl ]; then
exe="/usr/sbin/alsactl"
fi
if [ -x /usr/local/sbin/alsactl ]; then
exe="/usr/local/sbin/alsactl"
fi
if [ -z "$exe" ]; then
exe=`whereis alsactl | cut -d ' ' -f 2`
fi
$exe -f $TEMPDIR/alsactl.tmp store
echo "--startcollapse--" >> $FILE
cat $TEMPDIR/alsactl.tmp >> $FILE
echo "--endcollapse--" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
}
withdevices() {
echo "!!ALSA Device nodes" >> $FILE
echo "!!-----------------" >> $FILE
echo "" >> $FILE
ls -la /dev/snd/* >> $FILE
echo "" >> $FILE
echo "" >> $FILE
}
withconfigs() {
if [[ -e $HOME/.asoundrc ]] || [[ -e /etc/asound.conf ]] || [[ -e $HOME/.asoundrc.asoundconf ]]
then
echo "!!ALSA configuration files" >> $FILE
echo "!!------------------------" >> $FILE
echo "" >> $FILE
#Check for ~/.asoundrc
if [[ -e $HOME/.asoundrc ]]
then
echo "!!User specific config file (~/.asoundrc)" >> $FILE
echo "" >> $FILE
cat $HOME/.asoundrc >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
#Check for .asoundrc.asoundconf (seems to be Ubuntu specific)
if [[ -e $HOME/.asoundrc.asoundconf ]]
then
echo "!!asoundconf-generated config file" >> $FILE
echo "" >> $FILE
cat $HOME/.asoundrc.asoundconf >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
#Check for /etc/asound.conf
if [[ -e /etc/asound.conf ]]
then
echo "!!System wide config file (/etc/asound.conf)" >> $FILE
echo "" >> $FILE
cat /etc/asound.conf >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
fi
}
withsysfs() {
local i f
local printed=""
for i in /sys/class/sound/*; do
case "$i" in
*/hwC?D?)
if [ -f $i/init_pin_configs ]; then
if [ -z "$printed" ]; then
echo "!!Sysfs Files" >> $FILE
echo "!!-----------" >> $FILE
echo "" >> $FILE
fi
for f in init_pin_configs driver_pin_configs user_pin_configs init_verbs; do
echo "$i/$f:" >> $FILE
cat $i/$f >> $FILE
echo >> $FILE
done
printed=yes
fi
;;
esac
done
if [ -n "$printed" ]; then
echo "" >> $FILE
fi
}
withdmesg() {
echo "!!ALSA/HDA dmesg" >> $FILE
echo "!!--------------" >> $FILE
echo "" >> $FILE
dmesg | grep -C1 -E 'ALSA|HDA|HDMI|sound|hda.codec|hda.intel' >> $FILE
echo "" >> $FILE
echo "" >> $FILE
}
withall() {
withdevices
withconfigs
withaplay
withamixer
withalsactl
withlsmod
withsysfs
withdmesg
}
get_alsa_library_version() {
ALSA_LIB_VERSION=`grep VERSION_STR /usr/include/alsa/version.h 2>/dev/null|awk {'print $3'}|sed 's/"//g'`
if [ -z "$ALSA_LIB_VERSION" ]; then
if [ -f /etc/lsb-release ]; then
. /etc/lsb-release
case "$DISTRIB_ID" in
Ubuntu)
if which dpkg > /dev/null ; then
ALSA_LIB_VERSION=`dpkg -l libasound2 | tail -1 | awk '{print $3}' | cut -f 1 -d -`
fi
if [ "$ALSA_LIB_VERSION" = "" ]; then
ALSA_LIB_VERSION=""
fi
return
;;
*)
return
;;
esac
elif [ -f /etc/debian_version ]; then
if which dpkg > /dev/null ; then
ALSA_LIB_VERSION=`dpkg -l libasound2 | tail -1 | awk '{print $3}' | cut -f 1 -d -`
fi
if [ "$ALSA_LIB_VERSION" = "" ]; then
ALSA_LIB_VERSION=""
fi
return
fi
fi
}
#Run checks to make sure the programs we need are installed.
LSPCI=$(which lspci 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null);
TPUT=$(which tput 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null);
DIALOG=$(which dialog 2>/dev/null | sed 's|^[^/]*||' 2>/dev/null);
#Check to see if sysfs is enabled in the kernel. We'll need this later on
SYSFS=$(mount |grep sysfs|awk {'print $3'});
#Check modprobe config files for sound related options
SNDOPTIONS=$(modprobe -c|sed -n 's/^options \(snd[-_][^ ]*\)/\1:/p')
KEEP_OUTPUT=
NFILE=""
PASTEBIN=""
WWWSERVICE="www.alsa-project.org"
WELCOME="yes"
PROCEED="yes"
UPLOAD="ask"
REPEAT=""
while [ -z "$REPEAT" ]; do
REPEAT="no"
case "$1" in
--update|--help|--about)
WELCOME="no"
PROCEED="no"
;;
--upload)
UPLOAD="yes"
WELCOME="no"
;;
--no-upload)
UPLOAD="no"
WELCOME="no"
;;
--pastebin)
PASTEBIN="yes"
WWWSERVICE="pastebin"
;;
--no-dialog)
DIALOG=""
REPEAT=""
shift
;;
--stdout)
DIALOG=""
UPLOAD="no"
WELCOME="no"
TOSTDOUT="yes"
;;
esac
done
#Script header output.
if [ "$WELCOME" = "yes" ]; then
greeting_message="\
This script visits the following commands/files to collect diagnostic
information about your ALSA installation and sound related hardware.
dmesg
lspci
lsmod
aplay
amixer
alsactl
/proc/asound/
/sys/class/sound/
~/.asoundrc (etc.)
See '$0 --help' for command line options.
"
if [[ -n "$DIALOG" ]]; then
dialog --backtitle "$BGTITLE" \
--title "ALSA-Info script v $SCRIPT_VERSION" \
--msgbox "$greeting_message" 20 80
else
echo "ALSA Information Script v $SCRIPT_VERSION"
echo "--------------------------------"
echo "$greeting_message"
fi # dialog
fi # WELCOME
#Set the output file
TEMPDIR=`mktemp -t -d alsa-info.XXXXXXXXXX` || exit 1
FILE="$TEMPDIR/alsa-info.txt"
if [ -z "$NFILE" ]; then
NFILE=`mktemp -t alsa-info.txt.XXXXXXXXXX` || exit 1
fi
trap cleanup 0
if [ "$PROCEED" = "yes" ]; then
if [[ -z "$LSPCI" ]]
then
echo "This script requires lspci. Please install it, and re-run this script."
exit 0
fi
#Fetch the info and store in temp files/variables
DISTRO=`grep -ihs "buntu\|SUSE\|Fedora\|PCLinuxOS\|MEPIS\|Mandriva\|Debian\|Damn\|Sabayon\|Slackware\|KNOPPIX\|Gentoo\|Zenwalk\|Mint\|Kubuntu\|FreeBSD\|Puppy\|Freespire\|Vector\|Dreamlinux\|CentOS\|Arch\|Xandros\|Elive\|SLAX\|Red\|BSD\|KANOTIX\|Nexenta\|Foresight\|GeeXboX\|Frugalware\|64\|SystemRescue\|Novell\|Solaris\|BackTrack\|KateOS\|Pardus" /etc/{issue,*release,*version}`
KERNEL_VERSION=`uname -r`
KERNEL_PROCESSOR=`uname -p`
KERNEL_MACHINE=`uname -m`
KERNEL_OS=`uname -o`
[[ `uname -v |grep SMP` ]] && KERNEL_SMP="Yes" || KERNEL_SMP="No"
ALSA_DRIVER_VERSION=`cat /proc/asound/version |head -n1|awk {'print $7'} |sed 's/\.$//'`
get_alsa_library_version
ALSA_UTILS_VERSION=`amixer -v |awk {'print $3'}`
VENDOR_ID=`lspci -vn |grep 040[1-3] | awk -F':' '{print $3}'|awk {'print substr($0, 2);}' >$TEMPDIR/vendor_id.tmp`
DEVICE_ID=`lspci -vn |grep 040[1-3] | awk -F':' '{print $4}'|awk {'print $1'} >$TEMPDIR/device_id.tmp`
LAST_CARD=$((`grep "]: " /proc/asound/cards | wc -l` - 1 ))
ESDINST=$(which esd 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null)
PAINST=$(which pulseaudio 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null)
ARTSINST=$(which artsd 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null)
JACKINST=$(which jackd 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null)
ROARINST=$(which roard 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null)
DMIDECODE=$(which dmidecode 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null)
#Check for DMI data
if [ -d /sys/class/dmi/id ]; then
# No root privileges are required when using sysfs method
DMI_SYSTEM_MANUFACTURER=$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null)
DMI_SYSTEM_PRODUCT_NAME=$(cat /sys/class/dmi/id/product_name 2>/dev/null)
DMI_SYSTEM_PRODUCT_VERSION=$(cat /sys/class/dmi/id/product_version 2>/dev/null)
DMI_SYSTEM_FIRMWARE_VERSION=$(cat /sys/class/dmi/id/bios_version 2>/dev/null)
elif [ -x $DMIDECODE ]; then
DMI_SYSTEM_MANUFACTURER=$($DMIDECODE -s system-manufacturer 2>/dev/null)
DMI_SYSTEM_PRODUCT_NAME=$($DMIDECODE -s system-product-name 2>/dev/null)
DMI_SYSTEM_PRODUCT_VERSION=$($DMIDECODE -s system-version 2>/dev/null)
DMI_SYSTEM_FIRMWARE_VERSION=$($DMIDECODE -s bios-version 2>/dev/null)
fi
cat /proc/asound/modules 2>/dev/null|awk {'print $2'}>$TEMPDIR/alsamodules.tmp
cat /proc/asound/cards >$TEMPDIR/alsacards.tmp
lspci |grep -i "multi\|audio">$TEMPDIR/lspci.tmp
#Check for HDA-Intel cards codec#*
cat /proc/asound/card*/codec\#* > $TEMPDIR/alsa-hda-intel.tmp 2> /dev/null
#Check for AC97 cards codec
cat /proc/asound/card*/codec97\#0/ac97\#0-0 > $TEMPDIR/alsa-ac97.tmp 2> /dev/null
cat /proc/asound/card*/codec97\#0/ac97\#0-0+regs > $TEMPDIR/alsa-ac97-regs.tmp 2> /dev/null
#Check for USB mixer setup
cat /proc/asound/card*/usbmixer > $TEMPDIR/alsa-usbmixer.tmp 2> /dev/null
#Fetch the info, and put it in $FILE in a nice readable format.
if [[ -z $PASTEBIN ]]; then
echo "upload=true&script=true&cardinfo=" > $FILE
else
echo "name=$USER&type=33&description=/tmp/alsa-info.txt&expiry=&s=Submit+Post&content=" > $FILE
fi
echo "!!################################" >> $FILE
echo "!!ALSA Information Script v $SCRIPT_VERSION" >> $FILE
echo "!!################################" >> $FILE
echo "" >> $FILE
echo "!!Script ran on: `LANG=C TZ=UTC date`" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!Linux Distribution" >> $FILE
echo "!!------------------" >> $FILE
echo "" >> $FILE
echo $DISTRO >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!DMI Information" >> $FILE
echo "!!---------------" >> $FILE
echo "" >> $FILE
echo "Manufacturer: $DMI_SYSTEM_MANUFACTURER" >> $FILE
echo "Product Name: $DMI_SYSTEM_PRODUCT_NAME" >> $FILE
echo "Product Version: $DMI_SYSTEM_PRODUCT_VERSION" >> $FILE
echo "Firmware Version: $DMI_SYSTEM_FIRMWARE_VERSION" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!Kernel Information" >> $FILE
echo "!!------------------" >> $FILE
echo "" >> $FILE
echo "Kernel release: $KERNEL_VERSION" >> $FILE
echo "Operating System: $KERNEL_OS" >> $FILE
echo "Architecture: $KERNEL_MACHINE" >> $FILE
echo "Processor: $KERNEL_PROCESSOR" >> $FILE
echo "SMP Enabled: $KERNEL_SMP" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!ALSA Version" >> $FILE
echo "!!------------" >> $FILE
echo "" >> $FILE
echo "Driver version: $ALSA_DRIVER_VERSION" >> $FILE
echo "Library version: $ALSA_LIB_VERSION" >> $FILE
echo "Utilities version: $ALSA_UTILS_VERSION" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!Loaded ALSA modules" >> $FILE
echo "!!-------------------" >> $FILE
echo "" >> $FILE
cat $TEMPDIR/alsamodules.tmp >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!Sound Servers on this system" >> $FILE
echo "!!----------------------------" >> $FILE
echo "" >> $FILE
if [[ -n $PAINST ]];then
[[ `pgrep '^(.*/)?pulseaudio$'` ]] && PARUNNING="Yes" || PARUNNING="No"
echo "Pulseaudio:" >> $FILE
echo " Installed - Yes ($PAINST)" >> $FILE
echo " Running - $PARUNNING" >> $FILE
echo "" >> $FILE
fi
if [[ -n $ESDINST ]];then
[[ `pgrep '^(.*/)?esd$'` ]] && ESDRUNNING="Yes" || ESDRUNNING="No"
echo "ESound Daemon:" >> $FILE
echo " Installed - Yes ($ESDINST)" >> $FILE
echo " Running - $ESDRUNNING" >> $FILE
echo "" >> $FILE
fi
if [[ -n $ARTSINST ]];then
[[ `pgrep '^(.*/)?artsd$'` ]] && ARTSRUNNING="Yes" || ARTSRUNNING="No"
echo "aRts:" >> $FILE
echo " Installed - Yes ($ARTSINST)" >> $FILE
echo " Running - $ARTSRUNNING" >> $FILE
echo "" >> $FILE
fi
if [[ -n $JACKINST ]];then
[[ `pgrep '^(.*/)?jackd$'` ]] && JACKRUNNING="Yes" || JACKRUNNING="No"
echo "Jack:" >> $FILE
echo " Installed - Yes ($JACKINST)" >> $FILE
echo " Running - $JACKRUNNING" >> $FILE
echo "" >> $FILE
fi
if [[ -n $ROARINST ]];then
[[ `pgrep '^(.*/)?roard$'` ]] && ROARRUNNING="Yes" || ROARRUNNING="No"
echo "RoarAudio:" >> $FILE
echo " Installed - Yes ($ROARINST)" >> $FILE
echo " Running - $ROARRUNNING" >> $FILE
echo "" >> $FILE
fi
if [[ -z "$PAINST" && -z "$ESDINST" && -z "$ARTSINST" && -z "$JACKINST" && -z "$ROARINST" ]];then
echo "No sound servers found." >> $FILE
echo "" >> $FILE
fi
echo "" >> $FILE
echo "!!Soundcards recognised by ALSA" >> $FILE
echo "!!-----------------------------" >> $FILE
echo "" >> $FILE
cat $TEMPDIR/alsacards.tmp >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!PCI Soundcards installed in the system" >> $FILE
echo "!!--------------------------------------" >> $FILE
echo "" >> $FILE
cat $TEMPDIR/lspci.tmp >> $FILE
echo "" >> $FILE
echo "" >> $FILE
echo "!!Advanced information - PCI Vendor/Device/Subsystem ID's" >> $FILE
echo "!!-------------------------------------------------------" >> $FILE
echo "" >> $FILE
lspci -vvn |grep -A1 040[1-3] >> $FILE
echo "" >> $FILE
echo "" >> $FILE
if [ "$SNDOPTIONS" ]
then
echo "!!Modprobe options (Sound related)" >> $FILE
echo "!!--------------------------------" >> $FILE
echo "" >> $FILE
modprobe -c|sed -n 's/^options \(snd[-_][^ ]*\)/\1:/p' >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
if [ -d "$SYSFS" ]
then
echo "!!Loaded sound module options" >> $FILE
echo "!!---------------------------" >> $FILE
echo "" >> $FILE
for mod in `cat /proc/asound/modules|awk {'print $2'}`;do
echo "!!Module: $mod" >> $FILE
for params in `echo $SYSFS/module/$mod/parameters/*`; do
echo -ne "\t";
echo "$params : `cat $params`" | sed 's:.*/::';
done >> $FILE
echo "" >> $FILE
done
echo "" >> $FILE
fi
if [ -s "$TEMPDIR/alsa-hda-intel.tmp" ]
then
echo "!!HDA-Intel Codec information" >> $FILE
echo "!!---------------------------" >> $FILE
echo "--startcollapse--" >> $FILE
echo "" >> $FILE
cat $TEMPDIR/alsa-hda-intel.tmp >> $FILE
echo "--endcollapse--" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
if [ -s "$TEMPDIR/alsa-ac97.tmp" ]
then
echo "!!AC97 Codec information" >> $FILE
echo "!!----------------------" >> $FILE
echo "--startcollapse--" >> $FILE
echo "" >> $FILE
cat $TEMPDIR/alsa-ac97.tmp >> $FILE
echo "" >> $FILE
cat $TEMPDIR/alsa-ac97-regs.tmp >> $FILE
echo "--endcollapse--" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
if [ -s "$TEMPDIR/alsa-usbmixer.tmp" ]
then
echo "!!USB Mixer information" >> $FILE
echo "!!---------------------" >> $FILE
echo "--startcollapse--" >> $FILE
echo "" >> $FILE
cat $TEMPDIR/alsa-usbmixer.tmp >> $FILE
echo "--endcollapse--" >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
#If no command line options are specified, then run as though --with-all was specified
if [[ -z "$1" ]]
then
update
withall
pbcheck
fi
fi # proceed
#loop through command line arguments, until none are left.
if [[ -n "$1" ]]
then
until [ -z "$1" ]
do
case "$1" in
--pastebin)
update
withall
pbcheck
;;
--update)
update
exit
;;
--upload)
UPLOAD="yes"
withall
;;
--no-upload)
UPLOAD="no"
withall
;;
--output)
shift
NFILE="$1"
KEEP_OUTPUT="yes"
;;
--debug)
echo "Debugging enabled. $FILE and $TEMPDIR will not be deleted"
KEEP_FILES="yes"
echo ""
withall
;;
--with-all)
withall
;;
--with-aplay)
withaplay
;;
--with-amixer)
withamixer
;;
--with-alsactl)
withalsactl
;;
--with-devices)
withdevices
;;
--with-dmesg)
withdmesg
;;
--with-configs)
if [[ -e $HOME/.asoundrc ]] || [[ -e /etc/asound.conf ]]
then
echo "!!ALSA configuration files" >> $FILE
echo "!!------------------------" >> $FILE
echo "" >> $FILE
#Check for ~/.asoundrc
if [[ -e $HOME/.asoundrc ]]
then
echo "!!User specific config file ($HOME/.asoundrc)" >> $FILE
echo "" >> $FILE
cat $HOME/.asoundrc >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
#Check for /etc/asound.conf
if [[ -e /etc/asound.conf ]]
then
echo "!!System wide config file (/etc/asound.conf)" >> $FILE
echo "" >> $FILE
cat /etc/asound.conf >> $FILE
echo "" >> $FILE
echo "" >> $FILE
fi
fi
;;
--stdout)
UPLOAD="no"
withall
cat $FILE
rm $FILE
;;
--about)
echo "Written/Tested by the following users of #alsa on irc.freenode.net:"
echo ""
echo " wishie - Script author and developer / Testing"
echo " crimsun - Various script ideas / Testing"
echo " gnubien - Various script ideas / Testing"
echo " GrueMaster - HDA Intel specific items / Testing"
echo " olegfink - Script update function"
echo " TheMuso - display to stdout functionality"
exit 0
;;
*)
echo "alsa-info.sh version $SCRIPT_VERSION"
echo ""
echo "Available options:"
echo " --with-aplay (includes the output of aplay -l)"
echo " --with-amixer (includes the output of amixer)"
echo " --with-alsactl (includes the output of alsactl)"
echo " --with-configs (includes the output of ~/.asoundrc and"
echo " /etc/asound.conf if they exist)"
echo " --with-devices (shows the device nodes in /dev/snd/)"
echo " --with-dmesg (shows the ALSA/HDA kernel messages)"
echo ""
echo " --output FILE (specify the file to output for no-upload mode)"
echo " --update (check server for script updates)"
echo " --upload (upload contents to remote server)"
echo " --no-upload (do not upload contents to remote server)"
echo " --pastebin (use http://pastebin.ca) as remote server"
echo " instead www.alsa-project.org"
echo " --stdout (print alsa information to standard output"
echo " instead of a file)"
echo " --about (show some information about the script)"
echo " --debug (will run the script as normal, but will not"
echo " delete $FILE)"
exit 0
;;
esac
shift 1
done
fi
if [ "$PROCEED" = "no" ]; then
exit 1
fi
if [ "$UPLOAD" = "ask" ]; then
if [[ -n "$DIALOG" ]]; then
dialog --backtitle "$BGTITLE" --title "Information collected" --yes-label " UPLOAD / SHARE " --no-label " SAVE LOCALLY " --defaultno --yesno "\n\nAutomatically upload ALSA information to $WWWSERVICE?" 10 80
DIALOG_EXIT_CODE=$?
if [ $DIALOG_EXIT_CODE != 0 ]; then
UPLOAD="no"
else
UPLOAD="yes"
fi
else
echo -n "Automatically upload ALSA information to $WWWSERVICE? [y/N] : "
read -e CONFIRM
if [ "$CONFIRM" != "y" ]; then
UPLOAD="no"
else
UPLOAD="yes"
fi
fi
fi
if [ "$UPLOAD" = "no" ]; then
if [ -z "$TOSTDOUT" ]; then
mv -f $FILE $NFILE || exit 1
KEEP_OUTPUT="yes"
fi
if [[ -n $DIALOG ]]
then
if [[ -n $PBERROR ]]; then
dialog --backtitle "$BGTITLE" --title "Information collected" --msgbox "An error occurred while contacting the $WWWSERVICE.\n Your information was NOT automatically uploaded.\n\nYour ALSA information is in $NFILE" 10 100
else
dialog --backtitle "$BGTITLE" --title "Information collected" --msgbox "\n\nYour ALSA information is in $NFILE" 10 60
fi
else
echo
if [[ -n $PBERROR ]]; then
echo "An error occurred while contacting the $WWWSERVICE."
echo "Your information was NOT automatically uploaded."
echo ""
echo "Your ALSA information is in $NFILE"
echo ""
else
if [ -z "$TOSTDOUT" ]; then
echo ""
echo "Your ALSA information is in $NFILE"
echo ""
fi
fi
fi
exit
fi # UPLOAD
#Test that wget is installed, and supports --post-file. Upload $FILE if it does, and prompt user to upload file if it doesnt.
if
WGET=$(which wget 2>/dev/null| sed 's|^[^/]*||' 2>/dev/null); [[ -n "${WGET}" ]] && [[ -x "${WGET}" ]] && [[ `wget --help |grep post-file` ]]
then
if [[ -n $DIALOG ]]
then
if [[ -z $PASTEBIN ]]; then
wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://www.alsa-project.org/cardinfo-db/" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit"
{ for i in 10 20 30 40 50 60 70 80 90; do
echo $i
sleep 0.2
done
echo; } |dialog --backtitle "$BGTITLE" --guage "Uploading information to www.alsa-project.org ..." 6 70 0
else
wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY&encrypt=t&encryptpw=blahblah" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit"
{ for i in 10 20 30 40 50 60 70 80 90; do
echo $i
sleep 0.2
done
echo; } |dialog --backtitle "$BGTITLE" --guage "Uploading information to www.pastebin.ca ..." 6 70 0
fi
dialog --backtitle "$BGTITLE" --title "Information uploaded" --yesno "Would you like to see the uploaded information?" 5 100
DIALOG_EXIT_CODE=$?
if [ $DIALOG_EXIT_CODE = 0 ]; then
grep -v "alsa-info.txt" $FILE >$TEMPDIR/uploaded.txt
dialog --backtitle "$BGTITLE" --textbox $TEMPDIR/uploaded.txt 0 0
fi
clear
# no dialog
else
if [[ -z $PASTEBIN ]]; then
echo -n "Uploading information to www.alsa-project.org ... "
wget -O - --tries=5 --timeout=60 --post-file=$FILE http://www.alsa-project.org/cardinfo-db/ &>$TEMPDIR/wget.tmp &
else
echo -n "Uploading information to www.pastebin.ca ... "
wget -O - --tries=5 --timeout=60 --post-file=$FILE http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY &>$TEMPDIR/wget.tmp &
fi
#Progess spinner for wget transfer.
i=1
sp="/-\|"
echo -n ' '
while pgrep wget &>/dev/null
do
echo -en "\b${sp:i++%${#sp}:1}"
done
echo -e "\b Done!"
echo ""
fi #dialog
#See if tput is available, and use it if it is.
if [[ -n "$TPUT" ]]
then
if [[ -z $PASTEBIN ]]; then
FINAL_URL=`tput setaf 1; grep "SUCCESS:" $TEMPDIR/wget.tmp | cut -d ' ' -f 2 ; tput sgr0`
else
FINAL_URL=`tput setaf 1; grep "SUCCESS:" $TEMPDIR/wget.tmp |sed -n 's/.*\:\([0-9]\+\).*/http:\/\/pastebin.ca\/\1/p';tput sgr0`
fi
else
if [[ -z $PASTEBIN ]]; then
FINAL_URL=`grep "SUCCESS:" $TEMPDIR/wget.tmp | cut -d ' ' -f 2`
else
FINAL_URL=`grep "SUCCESS:" $TEMPDIR/wget.tmp |sed -n 's/.*\:\([0-9]\+\).*/http:\/\/pastebin.ca\/\1/p'`
fi
fi
#Output the URL of the uploaded file.
echo "Your ALSA information is located at $FINAL_URL"
echo "Please inform the person helping you."
echo ""
#We couldnt find a suitable wget, so tell the user to upload manually.
else
mv -f $FILE $NFILE || exit 1
KEEP_OUTPUT="yes"
if [[ -z $DIALOG ]]
then
if [[ -z $PASTEBIN ]]; then
echo ""
echo "Could not automatically upload output to http://www.alsa-project.org"
echo "Possible reasons are:"
echo " 1. Couldnt find 'wget' in your PATH"
echo " 2. Your version of wget is less than 1.8.2"
echo ""
echo "Please manually upload $NFILE to http://www.alsa-project.org/cardinfo-db/ and submit your post."
echo ""
else
echo ""
echo "Could not automatically upload output to http://www.pastebin.ca"
echo "Possible reasons are:"
echo " 1. Couldnt find 'wget' in your PATH"
echo " 2. Your version of wget is less than 1.8.2"
echo ""
echo "Please manually upload $NFILE to http://www.pastebin.ca/upload.php and submit your post."
echo ""
fi
else
if [[ -z $PASTEBIN ]]; then
dialog --backtitle "$BGTITLE" --msgbox "Could not automatically upload output to http://www.alsa-project.org.\nPossible reasons are:\n\n 1. Couldn't find 'wget' in your PATH\n 2. Your version of wget is less than 1.8.2\n\nPlease manually upload $NFILE to http://www.alsa-project,org/cardinfo-db/ and submit your post." 25 100
else
dialog --backtitle "$BGTITLE" --msgbox "Could not automatically upload output to http://www.pastebin.ca.\nPossible reasons are:\n\n 1. Couldn't find 'wget' in your PATH\n 2. Your version of wget is less than 1.8.2\n\nPlease manually upload $NFILE to http://www.pastebin.ca/upload.php and submit your post." 25 100
fi
fi
fi
plainbox-provider-checkbox-0.25/bin/optical_read_test 0000775 0001750 0001750 00000007464 12646152433 024272 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
import posixpath
import filecmp
import shutil
from argparse import ArgumentParser
from subprocess import Popen, PIPE
DEFAULT_DIR = '/tmp/checkbox.optical'
DEFAULT_DEVICE_DIR = 'device'
DEFAULT_IMAGE_DIR = 'image'
CDROM_ID = '/lib/udev/cdrom_id'
def _command(command, shell=True):
proc = Popen(command,
shell=shell,
stdout=PIPE,
stderr=PIPE
)
return proc
def _command_out(command, shell=True):
proc = _command(command, shell)
return proc.communicate()[0].strip()
def compare_tree(source, target):
for dirpath, dirnames, filenames in os.walk(source):
#if both tree are empty return false
if dirpath == source and dirnames == [] and filenames == []:
return False
for name in filenames:
file1 = os.path.join(dirpath, name)
file2 = file1.replace(source, target, 1)
if os.path.isfile(file1) and not os.path.islink(file1):
if filecmp.cmp(file1, file2):
continue
else:
return False
else:
continue
return True
def read_test(device):
passed = False
device_dir = os.path.join(DEFAULT_DIR, DEFAULT_DEVICE_DIR)
image_dir = os.path.join(DEFAULT_DIR, DEFAULT_IMAGE_DIR)
for dir in (device_dir, image_dir):
if posixpath.exists(dir):
shutil.rmtree(dir)
os.makedirs(device_dir)
try:
_command("umount %s" % device).communicate()
mount = _command("mount -o ro %s %s" % (device, device_dir))
mount.communicate()
if mount.returncode != 0:
print("Unable to mount %s to %s" %
(device, device_dir), file=sys.stderr)
return False
file_copy = _command("cp -dpR %s %s" % (device_dir, image_dir))
file_copy.communicate()
if file_copy.returncode != 0:
print("Failed to copy files from %s to %s" %
(device_dir, image_dir), file=sys.stderr)
return False
if compare_tree(device_dir, image_dir):
passed = True
except:
print("File Comparison failed while testing %s" % device,
file=sys.stderr)
passed = False
finally:
_command("umount %s" % device_dir).communicate(3)
for dir in (device_dir, image_dir):
if posixpath.exists(dir):
shutil.rmtree(dir)
if passed:
print("File Comparison passed (%s)" % device)
return passed
def get_capabilities(device):
cmd = "%s %s" % (CDROM_ID, device)
capabilities = _command_out(cmd)
return capabilities
def main():
tests = []
return_values = []
parser = ArgumentParser()
parser.add_argument("device", nargs='+',
help=('Specify an optical device or list of devices '
'such as /dev/cdrom'))
args = parser.parse_args()
if os.geteuid() != 0:
parser.error("ERROR: Must be root to run this script.")
for device in args.device:
capabilities = get_capabilities(device)
if not capabilities:
print("Unable to get capabilities of %s" % device, file=sys.stderr)
return 1
for capability in capabilities.decode().split('\n'):
if capability[:3] == 'ID_':
cap = capability[3:-2]
if cap == 'CDROM' or cap == 'CDROM_DVD':
tests.append('read')
for test in set(tests):
print("Testing %s on %s ... " % (test, device), file=sys.stdout)
tester = "%s_test" % test
return_values.append(globals()[tester](device))
return False in return_values
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/fwts_test 0000775 0001750 0001750 00000047322 12646152433 022624 0 ustar sylvain sylvain 0000000 0000000 #! /usr/bin/python3
import sys
import re
from time import time
from argparse import ArgumentParser, RawTextHelpFormatter, REMAINDER
from subprocess import Popen, PIPE
from syslog import *
from distutils.spawn import find_executable
import os
# These tests require user interaction and need either special handling
# or skipping altogether (right now, we skip them but they're kept here
# in case we figure out a way to present the interaction to the user).
INTERACTIVE_TESTS = ['ac_adapter',
'battery',
'hotkey',
'power_button',
'brightness',
'lid']
# These are performed on QA certification runs
QA_TESTS = ['acpitests',
'acpidump',
'acpitables',
'apicinstance',
'aspm',
'bios32',
'dmicheck',
'ebda',
'mpcheck',
'msr',
'nx',
'version']
# These are advanced tests that shouldn't affect certification status
NON_CERT_TESTS = ['bios_info',
'cmosdump',
'cpufreq',
'crs',
'crsdump',
'csm',
'ebdadump',
'fan',
'gpedump',
'hda_audio',
'maxfreq',
'maxreadreq',
'memmapdump',
'microcode',
'mpdump',
'os2gap',
'osilinux',
'pciirq',
'plddump',
'pnp',
'prsdump',
'romdump',
'securebootcert',
'syntaxcheck',
'uefidump',
'uefirtmisc',
'uefirttime',
'uefirtvariable',
'uefivarinfo',
'wakealarm'
]
# The following tests will record logs in a separate file for the HWE team
HWE_TESTS = ['mtrr',
'virt',
'apicedge',
'klog',
'oops',
'uefibootpath']
CERT_TESTS = sorted(QA_TESTS + HWE_TESTS)
TESTS = sorted(QA_TESTS + NON_CERT_TESTS + HWE_TESTS)
def get_sleep_times(start_marker, end_marker, sleep_time, resume_time):
logfile = '/var/log/syslog'
log_fh = open(logfile, 'r')
line = ''
run = 'FAIL'
sleep_start_time = 0.0
sleep_end_time = 0.0
resume_start_time = 0.0
resume_end_time = 0.0
while start_marker not in line:
try:
line = log_fh.readline()
except UnicodeDecodeError:
continue
if start_marker in line:
loglist = log_fh.readlines()
for idx in range(0, len(loglist)):
if 'PM: Syncing filesystems' in loglist[idx]:
sleep_start_time = re.split('[\[\]]', loglist[idx])[1].strip()
if 'ACPI: Low-level resume complete' in loglist[idx]:
sleep_end_time = re.split('[\[\]]', loglist[idx - 1])[1].strip()
resume_start_time = re.split('[\[\]]', loglist[idx])[1].strip()
idx += 1
if 'Restarting tasks' in loglist[idx]:
resume_end_time = re.split('[\[\]]', loglist[idx])[1].strip()
if end_marker in loglist[idx]:
run = 'PASS'
break
sleep_elapsed = float(sleep_end_time) - float(sleep_start_time)
resume_elapsed = float(resume_end_time) - float(resume_start_time)
return (run, sleep_elapsed, resume_elapsed)
def average_times(runs):
sleep_total = 0.0
resume_total = 0.0
run_count = 0
for run in runs.keys():
run_count += 1
sleep_total += runs[run][1]
resume_total += runs[run][2]
sleep_avg = sleep_total / run_count
resume_avg = resume_total / run_count
print('Average time to sleep: %0.5f' % sleep_avg)
print('Average time to resume: %0.5f' % resume_avg)
def fix_sleep_args(args):
new_args = []
for arg in args:
if "=" in arg:
new_args.extend(arg.split('='))
else:
new_args.append(arg)
return new_args
def detect_progress_indicator():
# Return a command suitable for piping progress information to its
# stdin (invoked via Popen), in list format.
# Return zenity if installed and DISPLAY (--auto-close)
# return dialog if installed and no DISPLAY (width height)
display = os.environ.get('DISPLAY')
if display and find_executable('zenity'):
return ["zenity", "--progress", "--text", "Progress", "--auto-close"]
if not display and find_executable('dialog'):
return ["dialog", "--gauge", "Progress", "20", "70"]
# Return None if no progress indicator is to be used
return None
def main():
description_text = 'Tests the system BIOS using the Firmware Test Suite'
epilog_text = ('To perform sleep testing, you will need at least some of '
'the following options: \n'
's3 or s4: tells fwts which type of sleep to perform.\n'
'--s3-delay-delta\n'
'--s3-device-check\n'
'--s3-device-check-delay\n'
'--s3-hybrid-sleep\n'
'--s3-max-delay\n'
'--s3-min-delay\n'
'--s3-multiple\n'
'--s3-quirks\n'
'--s3-sleep-delay\n'
'--s3power-sleep-delay\n\n'
'Example: fwts_test --sleep s3 --s3-min-delay 30 '
'--s3-multiple 10 --s3-device-check\n\n'
'For further help with sleep options:\n'
'fwts_test --fwts-help')
parser = ArgumentParser(description=description_text,
epilog=epilog_text,
formatter_class=RawTextHelpFormatter)
parser.add_argument('-l', '--log',
default='/tmp/fwts_results.log',
help=('Specify the location and name '
'of the log file.\n'
'[Default: %(default)s]'))
parser.add_argument('-f', '--fail-level',
default='high',
choices=['critical', 'high', 'medium',
'low', 'none', 'aborted'],
help=('Specify the FWTS failure level that will '
'trigger this script to return a failing exit '
'code. For example, if you chose "critical" as '
'the fail-level, this wrapper will NOT return '
'a failing exit code unless FWTS reports a '
'test as FAILED_CRITICAL. You will still be '
'notified of all FWTS test failures. '
'[Default level: %(default)s]'))
sleep_args = parser.add_argument_group('Sleep Options',
('The following arguments are to '
'only be used with the '
'--sleep test option'))
sleep_args.add_argument('--sleep-time',
dest='sleep_time',
action='store',
help=('The max time in seconds that a system '
'should take\nto completely enter sleep. '
'Anything more than this\ntime will cause '
'that test iteration to fail.\n'
'[Default: 10s]'))
sleep_args.add_argument('--resume-time',
dest='resume_time',
action='store',
help=('Same as --sleep-time, except this applies '
'to the\ntime it takes a system to fully '
'wake from sleep.\n[Default: 3s]'))
group = parser.add_mutually_exclusive_group()
group.add_argument('-t', '--test',
action='append',
help='Name of the test to run.')
group.add_argument('-a', '--all',
action='store_true',
help='Run ALL FWTS automated tests (assumes -w and -c)')
group.add_argument('-s', '--sleep',
nargs=REMAINDER,
action='store',
help=('Perform sleep test(s) using the additional\n'
'arguments provided after --sleep. Remaining\n'
'items on the command line will be passed \n'
'through to fwts for performing sleep tests. \n'
'For info on these extra fwts options, please \n'
'see the epilog below and \n'
'the --fwts-help option.'))
group.add_argument('--hwe',
action='store_true',
help='Run HWE concerned tests in fwts')
group.add_argument('--qa',
action='store_true',
help='Run QA concerned tests in fwts')
group.add_argument('--fwts-help',
dest='fwts_help',
action='store_true',
help='Display the help info for fwts itself (lengthy)')
group.add_argument('--list',
action='store_true',
help='List all tests in fwts.')
group.add_argument('--list-cert',
action='store_true',
help='List all certification tests in fwts.')
group.add_argument('--list-advanced',
action='store_true',
help='List all advanced tests in fwts.')
group.add_argument('--list-hwe',
action='store_true',
help='List all HWE concerned tests in fwts')
group.add_argument('--list-qa',
action='store_true',
help='List all QA concerned tests in fwts')
args = parser.parse_args()
tests = []
results = {}
critical_fails = []
high_fails = []
medium_fails = []
low_fails = []
passed = []
aborted = []
# Set correct fail level
if args.fail_level is not 'none':
args.fail_level = 'FAILED_%s' % args.fail_level.upper()
# Get our failure priority and create the priority values
fail_levels = {'FAILED_CRITICAL': 4,
'FAILED_HIGH': 3,
'FAILED_MEDIUM': 2,
'FAILED_LOW': 1,
'FAILED_NONE': 0,
'FAILED_ABORTED': -1}
fail_priority = fail_levels[args.fail_level]
# Enforce only using sleep opts with --sleep
if args.sleep_time or args.resume_time and not args.sleep:
parser.error('--sleep-time and --resume-time only apply to the '
'--sleep testing option.')
if args.fwts_help:
Popen('fwts -h', shell=True).communicate()[0]
return 0
elif args.list:
print('\n'.join(TESTS))
return 0
elif args.list_cert:
print('\n'.join(CERT_TESTS))
return 0
elif args.list_advanced:
print('\n'.join(NON_CERT_TESTS))
return 0
elif args.list_hwe:
print('\n'.join(HWE_TESTS))
return 0
elif args.list_qa:
print('\n'.join(QA_TESTS))
return 0
elif args.test:
tests.extend(args.test)
elif args.all:
tests.extend(TESTS)
elif args.hwe:
tests.extend(HWE_TESTS)
elif args.qa:
tests.extend(QA_TESTS)
elif args.sleep:
args.sleep = fix_sleep_args(args.sleep)
iterations = 1
# if multiple iterations are requested, we need to intercept
# that argument and keep it from being presented to fwts since
# we're handling the iterations directly.
s3 = '--s3-multiple'
s4 = '--s4-multiple'
if s3 in args.sleep:
iterations = int(args.sleep.pop(args.sleep.index(s3) + 1))
args.sleep.remove(s3)
if s4 in args.sleep:
iterations = int(args.sleep.pop(args.sleep.index(s4) + 1))
args.sleep.remove(s4)
# if we've passed our custom sleep arguments for resume or sleep
# time, we need to intercept those as well.
resume_time_arg = '--resume-time'
sleep_time_arg = '--sleep-time'
if resume_time_arg in args.sleep:
args.resume_time = int(args.sleep.pop(
args.sleep.index(resume_time_arg) + 1))
args.sleep.remove(resume_time_arg)
if sleep_time_arg in args.sleep:
args.sleep_time = int(args.sleep.pop(
args.sleep.index(sleep_time_arg) + 1))
args.sleep.remove(sleep_time_arg)
# if we still haven't set a sleep or resume time, use defauts.
if not args.sleep_time:
args.sleep_time = 10
if not args.resume_time:
args.resume_time = 3
tests.extend(args.sleep)
else:
tests.extend(CERT_TESTS)
# run the tests we want
if args.sleep:
iteration_results = {}
print('=' * 20 + ' Test Results ' + '=' * 20)
progress_indicator = None
if detect_progress_indicator():
progress_indicator = Popen(detect_progress_indicator(),
stdin=PIPE)
for iteration in range(0, iterations):
timestamp = int(time())
start_marker = 'CHECKBOX SLEEP TEST START %s' % timestamp
end_marker = 'CHECKBOX SLEEP TEST STOP %s' % timestamp
syslog(LOG_INFO, '---' + start_marker + '---' + str(time()))
command = ('fwts -q --stdout-summary -r %s %s'
% (args.log, ' '.join(tests)))
results['sleep'] = (Popen(command, stdout=PIPE, shell=True)
.communicate()[0].strip()).decode()
syslog(LOG_INFO, '---' + end_marker + '---' + str(time()))
if 's4' not in args.sleep:
sleep_times = get_sleep_times(start_marker,
end_marker,
args.sleep_time,
args.resume_time)
iteration_results[iteration] = sleep_times
progress_tuple = (iteration,
iteration_results[iteration][0],
iteration_results[iteration][1],
iteration_results[iteration][2])
progress_string = (' - Cycle %s: Status: %s '
'Sleep Elapsed: %0.5f '
'Resume Elapsed: '
' %0.5f' % progress_tuple)
progress_pct = "{}".format(int(100 * iteration / iterations))
if "zenity" in detect_progress_indicator():
progress_indicator.stdin.write("# {}\n".format(
progress_string).encode('utf-8'))
progress_indicator.stdin.write("{}\n".format(
progress_pct).encode('utf-8'))
progress_indicator.stdin.flush()
elif "dialog" in detect_progress_indicator():
progress_indicator.stdin.write("XXX\n".encode('utf-8'))
progress_indicator.stdin.write(
progress_pct.encode('utf-8'))
progress_indicator.stdin.write(
"\nTest progress\n".encode('utf-8'))
progress_indicator.stdin.write(
progress_string.encode('utf-8'))
progress_indicator.stdin.write(
"\nXXX\n".encode('utf-8'))
progress_indicator.stdin.flush()
else:
print(progress_string)
progress_indicator.terminate()
if 's4' not in args.sleep:
average_times(iteration_results)
for run in iteration_results.keys():
if 'FAIL' in iteration_results[run]:
results['sleep'] = 'FAILED_CRITICAL'
else:
for test in tests:
# ACPI tests can now be run with --acpitests (fwts >= 15.07.00)
log = args.log
# Split the log file for HWE (only if -t is not used)
if test == 'acpitests':
test = '--acpitests'
command = ('fwts -q --stdout-summary -r %s %s'
% (log, test))
results[test] = (Popen(command, stdout=PIPE, shell=True)
.communicate()[0].strip()).decode()
# parse the summaries
for test in results.keys():
if results[test] == 'FAILED_CRITICAL':
critical_fails.append(test)
elif results[test] == 'FAILED_HIGH':
high_fails.append(test)
elif results[test] == 'FAILED_MEDIUM':
medium_fails.append(test)
elif results[test] == 'FAILED_LOW':
low_fails.append(test)
elif results[test] == 'PASSED':
passed.append(test)
elif results[test] == 'ABORTED':
aborted.append(test)
else:
continue
if critical_fails:
print("Critical Failures: %d" % len(critical_fails))
print("WARNING: The following test cases were reported as critical\n"
"level failures by fwts. Please review the log at\n"
"%s for more information." % args.log)
for test in critical_fails:
print(" - " + test)
if high_fails:
print("High Failures: %d" % len(high_fails))
print("WARNING: The following test cases were reported as high\n"
"level failures by fwts. Please review the log at\n"
"%s for more information." % args.log)
for test in high_fails:
print(" - " + test)
if medium_fails:
print("Medium Failures: %d" % len(medium_fails))
print("WARNING: The following test cases were reported as medium\n"
"level failures by fwts. Please review the log at\n"
"%s for more information." % args.log)
for test in medium_fails:
print(" - " + test)
if low_fails:
print("Low Failures: %d" % len(low_fails))
print("WARNING: The following test cases were reported as low\n"
"level failures by fwts. Please review the log at\n"
"%s for more information." % args.log)
for test in low_fails:
print(" - " + test)
if passed:
print("Passed: %d" % len(passed))
for test in passed:
print(" - " + test)
if aborted:
print("Aborted Tests: %d" % len(aborted))
print("WARNING: The following test cases were aborted by fwts\n"
"Please review the log at %s for more information."
% args.log)
for test in aborted:
print(" - " + test)
if args.fail_level is not 'none':
if fail_priority == fail_levels['FAILED_CRITICAL']:
if critical_fails:
return 1
if fail_priority == fail_levels['FAILED_HIGH']:
if critical_fails or high_fails:
return 1
if fail_priority == fail_levels['FAILED_MEDIUM']:
if critical_fails or high_fails or medium_fails:
return 1
if fail_priority == fail_levels['FAILED_LOW']:
if critical_fails or high_fails or medium_fails or low_fails:
return 1
if fail_priority == fail_levels['FAILED_ABORTED']:
if aborted or critical_fails or high_fails:
return 1
return 0
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/mm-test 0000775 0001750 0001750 00000036471 12646152433 022173 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details:
#
# Copyright (C) 2008 Novell, Inc.
# Copyright (C) 2009 Red Hat, Inc.
#
import sys, dbus, time, os, string, subprocess, socket
DBUS_INTERFACE_PROPERTIES='org.freedesktop.DBus.Properties'
MM_DBUS_SERVICE='org.freedesktop.ModemManager'
MM_DBUS_PATH='/org/freedesktop/ModemManager'
MM_DBUS_INTERFACE='org.freedesktop.ModemManager'
MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
MM_DBUS_INTERFACE_MODEM_CDMA='org.freedesktop.ModemManager.Modem.Cdma'
MM_DBUS_INTERFACE_MODEM_GSM_CARD='org.freedesktop.ModemManager.Modem.Gsm.Card'
MM_DBUS_INTERFACE_MODEM_GSM_NETWORK='org.freedesktop.ModemManager.Modem.Gsm.Network'
MM_DBUS_INTERFACE_MODEM_SIMPLE='org.freedesktop.ModemManager.Modem.Simple'
def get_cdma_band_class(band_class):
if band_class == 1:
return "800MHz"
elif band_class == 2:
return "1900MHz"
else:
return "Unknown"
def get_reg_state(state):
if state == 1:
return "registered (roaming unknown)"
elif state == 2:
return "registered on home network"
elif state == 3:
return "registered on roaming network"
else:
return "unknown"
def cdma_inspect(proxy, dump_private):
cdma = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_CDMA)
esn = ""
if dump_private:
try:
esn = cdma.GetEsn()
except dbus.exceptions.DBusException:
esn = ""
print("")
print("ESN: %s" % esn)
try:
(cdma_1x_state, evdo_state) = cdma.GetRegistrationState()
print("1x State: %s" % get_reg_state (cdma_1x_state))
print("EVDO State: %s" % get_reg_state (evdo_state))
except dbus.exceptions.DBusException as e:
print("Error reading registration state: %s" % e)
try:
quality = cdma.GetSignalQuality()
print("Signal quality: %d" % quality)
except dbus.exceptions.DBusException as e:
print("Error reading signal quality: %s" % e)
try:
info = cdma.GetServingSystem()
print("Class: %s" % get_cdma_band_class(info[0]))
print("Band: %s" % info[1])
print("SID: %d" % info[2])
except dbus.exceptions.DBusException as e:
print("Error reading serving system: %s" % e)
def cdma_connect(proxy, user, password):
# Modem.Simple interface
simple = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_SIMPLE)
try:
simple.Connect({'number':"#777"}, timeout=92)
print("\nConnected!")
return True
except Exception as e:
print("Error connecting: %s" % e)
return False
def get_gsm_network_mode(modem):
mode = modem.GetNetworkMode()
if mode == 0x0:
mode = "Unknown"
elif mode == 0x1:
mode = "Any"
elif mode == 0x2:
mode = "GPRS"
elif mode == 0x4:
mode = "EDGE"
elif mode == 0x8:
mode = "UMTS"
elif mode == 0x10:
mode = "HSDPA"
elif mode == 0x20:
mode = "2G Preferred"
elif mode == 0x40:
mode = "3G Preferred"
elif mode == 0x80:
mode = "2G Only"
elif mode == 0x100:
mode = "3G Only"
elif mode == 0x200:
mode = "HSUPA"
elif mode == 0x400:
mode = "HSPA"
else:
mode = "(Unknown)"
print("Mode: %s" % mode)
def get_gsm_band(modem):
band = modem.GetBand()
if band == 0x0:
band = "Unknown"
elif band == 0x1:
band = "Any"
elif band == 0x2:
band = "EGSM (900 MHz)"
elif band == 0x4:
band = "DCS (1800 MHz)"
elif band == 0x8:
band = "PCS (1900 MHz)"
elif band == 0x10:
band = "G850 (850 MHz)"
elif band == 0x20:
band = "U2100 (WCSMA 2100 MHZ, Class I)"
elif band == 0x40:
band = "U1700 (WCDMA 3GPP UMTS1800 MHz, Class III)"
elif band == 0x80:
band = "17IV (WCDMA 3GPP AWS 1700/2100 MHz, Class IV)"
elif band == 0x100:
band = "U800 (WCDMA 3GPP UMTS800 MHz, Class VI)"
elif band == 0x200:
band = "U850 (WCDMA 3GPP UMT850 MHz, Class V)"
elif band == 0x400:
band = "U900 (WCDMA 3GPP UMTS900 MHz, Class VIII)"
elif band == 0x800:
band = "U17IX (WCDMA 3GPP UMTS MHz, Class IX)"
else:
band = "(invalid)"
print("Band: %s" % band)
def gsm_inspect(proxy, dump_private, do_scan):
# Gsm.Card interface
card = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_CARD)
imei = ""
imsi = ""
if dump_private:
try:
imei = card.GetImei()
except dbus.exceptions.DBusException:
imei = ""
try:
imsi = card.GetImsi()
except dbus.exceptions.DBusException:
imsi = ""
print("IMEI: %s" % imei)
print("IMSI: %s" % imsi)
# Gsm.Network interface
net = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_NETWORK)
try:
quality = net.GetSignalQuality()
print("Signal quality: %d" % quality)
except dbus.exceptions.DBusException as e:
print("Error reading signal quality: %s" % e)
if not do_scan:
return
print("Scanning...")
try:
results = net.Scan(timeout=120)
except dbus.exceptions.DBusException as e:
print("Error scanning: %s" % e)
results = {}
for r in results:
status = r['status']
if status == "1":
status = "available"
elif status == "2":
status = "current"
elif status == "3":
status = "forbidden"
else:
status = "(Unknown)"
access_tech = ""
try:
access_tech_num = r['access-tech']
if access_tech_num == "0":
access_tech = "(GSM)"
elif access_tech_num == "1":
access_tech = "(Compact GSM)"
elif access_tech_num == "2":
access_tech = "(UMTS)"
elif access_tech_num == "3":
access_tech = "(EDGE)"
elif access_tech_num == "4":
access_tech = "(HSDPA)"
elif access_tech_num == "5":
access_tech = "(HSUPA)"
elif access_tech_num == "6":
access_tech = "(HSPA)"
except KeyError:
pass
if 'operator-long' in r and len(r['operator-long']):
print("%s: %s %s" % (r['operator-long'], status, access_tech))
elif 'operator-short' in r and len(r['operator-short']):
print("%s: %s %s" % (r['operator-short'], status, access_tech))
else:
print("%s: %s %s" % (r['operator-num'], status, access_tech))
def gsm_connect(proxy, apn, user, password):
# Modem.Simple interface
simple = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_SIMPLE)
try:
opts = {'number':"*99#"}
if apn is not None:
opts['apn'] = apn
if user is not None:
opts['username'] = user
if password is not None:
opts['password'] = password
simple.Connect(opts, timeout=120)
print("\nConnected!")
return True
except Exception as e:
print("Error connecting: %s" % e)
return False
def pppd_find():
paths = ["/usr/local/sbin/pppd", "/usr/sbin/pppd", "/sbin/pppd"]
for p in paths:
if os.path.exists(p):
return p
return None
def ppp_start(device, user, password, tmpfile):
path = pppd_find()
if not path:
return None
args = [path]
args += ["nodetach"]
args += ["lock"]
args += ["nodefaultroute"]
args += ["debug"]
if user:
args += ["user"]
args += [user]
args += ["noipdefault"]
args += ["115200"]
args += ["noauth"]
args += ["crtscts"]
args += ["modem"]
args += ["usepeerdns"]
args += ["ipparam"]
ipparam = ""
if user:
ipparam += user
ipparam += "+"
if password:
ipparam += password
ipparam += "+"
ipparam += tmpfile
args += [ipparam]
args += ["plugin"]
args += ["mm-test-pppd-plugin.so"]
args += [device]
return subprocess.Popen(args, close_fds=True, cwd="/", env={})
def ppp_wait(p, tmpfile):
i = 0
while p.poll() == None and i < 30:
time.sleep(1)
if os.path.exists(tmpfile):
f = open(tmpfile, 'r')
stuff = f.read(500)
idx = string.find(stuff, "DONE")
f.close()
if idx >= 0:
return True
i += 1
return False
def ppp_stop(p):
import signal
p.send_signal(signal.SIGTERM)
p.wait()
def ntop_helper(ip):
ip = socket.ntohl(ip)
n1 = ip >> 24 & 0xFF
n2 = ip >> 16 & 0xFF
n3 = ip >> 8 & 0xFF
n4 = ip & 0xFF
a = "%c%c%c%c" % (n1, n2, n3, n4)
return socket.inet_ntop(socket.AF_INET, a)
def static_start(iface, modem):
(addr_num, dns1_num, dns2_num, dns3_num) = modem.GetIP4Config()
addr = ntop_helper(addr_num)
dns1 = ntop_helper(dns1_num)
dns2 = ntop_helper(dns2_num)
configure_iface(iface, addr, 0, dns1, dns2)
def down_iface(iface):
ip = ["ip", "addr", "flush", "dev", iface]
print(" ".join(ip))
subprocess.call(ip)
ip = ["ip", "link", "set", iface, "down"]
print(" ".join(ip))
subprocess.call(ip)
def configure_iface(iface, addr, gw, dns1, dns2):
print("\n\n******************************")
print("iface: %s" % iface)
print("addr: %s" % addr)
print("gw: %s" % gw)
print("dns1: %s" % dns1)
print("dns2: %s" % dns2)
ifconfig = ["ifconfig", iface, "%s/32" % addr]
if gw != 0:
ifconfig += ["pointopoint", gw]
print(" ".join(ifconfig))
print("\n******************************\n")
subprocess.call(ifconfig)
def file_configure_iface(tmpfile):
addr = None
gw = None
iface = None
dns1 = None
dns2 = None
f = open(tmpfile, 'r')
lines = f.readlines()
for l in lines:
if l.startswith("addr"):
addr = l[len("addr"):].strip()
if l.startswith("gateway"):
gw = l[len("gateway"):].strip()
if l.startswith("iface"):
iface = l[len("iface"):].strip()
if l.startswith("dns1"):
dns1 = l[len("dns1"):].strip()
if l.startswith("dns2"):
dns2 = l[len("dns2"):].strip()
f.close()
configure_iface(iface, addr, gw, dns1, dns2)
return iface
def try_ping(iface):
cmd = ["ping", "-I", iface, "-c", "4", "-i", "3", "-w", "20", "4.2.2.1"]
print(" ".join(cmd))
retcode = subprocess.call(cmd)
if retcode != 0:
print("PING: failed")
else:
print("PING: success")
dump_private = False
connect = False
apn = None
user = None
password = None
do_ip = False
do_scan = True
x = 1
while x < len(sys.argv):
if sys.argv[x] == "--private":
dump_private = True
elif sys.argv[x] == "--connect":
connect = True
elif (sys.argv[x] == "--user" or sys.argv[x] == "--username"):
x += 1
user = sys.argv[x]
elif sys.argv[x] == "--apn":
x += 1
apn = sys.argv[x]
elif sys.argv[x] == "--password":
x += 1
password = sys.argv[x]
elif sys.argv[x] == "--ip":
do_ip = True
if os.geteuid() != 0:
print("You probably want to be root to use --ip")
sys.exit(1)
elif sys.argv[x] == "--no-scan":
do_scan = False
x += 1
bus = dbus.SystemBus()
# Get available modems:
try:
manager_proxy = bus.get_object('org.freedesktop.ModemManager', '/org/freedesktop/ModemManager')
manager_iface = dbus.Interface(manager_proxy, dbus_interface='org.freedesktop.ModemManager')
modems = manager_iface.EnumerateDevices()
except dbus.exceptions.DBusException as excp:
if (excp.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown"):
print("ERROR: mm-test doesn't work on ModemManager 1.0 and newer: {}".format(
excp.get_dbus_message()))
else:
print("ERROR: {}".format(excp.get_dbus_message()))
sys.exit(1)
if not modems:
print("No modems found")
sys.exit(1)
for m in modems:
connect_success = False
data_device = None
proxy = bus.get_object(MM_DBUS_SERVICE, m)
# Properties
props_iface = dbus.Interface(proxy, dbus_interface='org.freedesktop.DBus.Properties')
type = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Type')
if type == 1:
print("GSM modem")
elif type == 2:
print("CDMA modem")
else:
print("Invalid modem type: %d" % type)
print("Driver: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Driver')))
print("Modem device: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'MasterDevice')))
data_device = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Device')
print("Data device: '%s'" % data_device)
# Modem interface
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
try:
modem.Enable(True)
except dbus.exceptions.DBusException as e:
print("Error enabling modem: %s" % e)
sys.exit(1)
info = modem.GetInfo()
print("Vendor: %s" % info[0])
print("Model: %s" % info[1])
print("Version: %s" % info[2])
if type == 1:
gsm_inspect(proxy, dump_private, do_scan)
if connect == True:
connect_success = gsm_connect(proxy, apn, user, password)
elif type == 2:
cdma_inspect(proxy, dump_private)
if connect == True:
connect_success = cdma_connect(proxy, user, password)
print()
if connect_success and do_ip:
tmpfile = "/tmp/mm-test-%d.tmp" % os.getpid()
success = False
try:
ip_method = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'IpMethod')
if ip_method == 0:
# ppp
p = ppp_start(data_device, user, password, tmpfile)
if ppp_wait(p, tmpfile):
data_device = file_configure_iface(tmpfile)
success = True
elif ip_method == 1:
# static
static_start(data_device, modem)
success = True
elif ip_method == 2:
# dhcp
pass
except Exception as e:
print("Error setting up IP: %s" % e)
if success:
try_ping(data_device)
print("Waiting for 30s...")
time.sleep(30)
print("Disconnecting...")
try:
if ip_method == 0:
ppp_stop(p)
try:
os.remove(tmpfile)
except:
pass
elif ip_method == 1:
# static
down_iface(data_device)
elif ip_method == 2:
# dhcp
down_iface(data_device)
modem.Disconnect()
except Exception as e:
print("Error tearing down IP: %s" % e)
time.sleep(5)
modem.Enable(False)
plainbox-provider-checkbox-0.25/bin/bluetooth_scan 0000775 0001750 0001750 00000000261 12646152433 023602 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
hciconfig hci0 reset
name=`zenity --title="Bluetooth Send" --entry --text="Bluetooth Send"`
address=`hcitool scan | grep "$name" | awk '{print $1}'`
echo $address
plainbox-provider-checkbox-0.25/bin/bmc_info 0000775 0001750 0001750 00000004054 12646152433 022351 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import sys
import shlex
from subprocess import check_output, CalledProcessError
def main():
# First, we need to get output
cmd = "ipmitool mc info"
try:
result = check_output(shlex.split(cmd), universal_newlines=True)
except FileNotFoundError:
print("ipmitool was not found! Please install it and try again.",
file=sys.stderr)
return 1
except CalledProcessError as e:
print("Problem running %s. Error was %s" % (cmd,e),file=sys.stderr)
return 1
result = result.split('\n')
# We need some bits that are formatted oddly so we need to do some parsing
data = {}
for line in result:
if ':' in line:
key = line.split(':')[0].strip()
value = line.split(':')[1].strip()
data[key] = value
last = (key, [value])
else:
# since the last line we matched had a ':', it's key is likely the
# key for the next few lines that don't have a ':'
# This should keep adding items to our last key's list until we hit
# another line with a :, and we start the cycle over again.
last[1].append(line.strip())
data[last[0]] = last[1]
# Now print out what we care about:
we_care_about = ['Manufacturer Name',
'Manufacturer ID',
'Product Name',
'Product ID',
'Firmware Revision',
'IPMI Version',
'Additional Device Support']
for field in we_care_about:
if type(data[field]) is list:
# Sometimes the first item in the list is ''. This will remove it
data[field].remove('')
print(field.ljust(30),':',data[field].pop(0))
for item in data[field]:
print(' '.ljust(32),item)
else:
print(field.ljust(30),":",data[field])
#print("{}:\t{}".format(field, data[field]))
return 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/audio_test 0000775 0001750 0001750 00000060740 12646152433 022741 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
from __future__ import division, print_function
import argparse
import collections
import json
import logging
import math
import re
import subprocess
import sys
import time
try:
import gi
gi.require_version('Gst','1.0')
from gi.repository import GObject
from gi.repository import Gst
from gi.repository import GLib
Gst.init(None) # This has to be done very early so it can find elements
except ImportError:
print("Can't import module: %s. it may not be available for this"
"version of Python, which is: " % sys.exc_info()[1], file=sys.stderr)
print((sys.version), file=sys.stderr)
sys.exit(127)
#Frequency bands for FFT
BINS = 256
#How often to take a sample and do FFT on it.
FFT_INTERVAL = 100000000 # In nanoseconds, so this is every 1/10th second
#Sampling frequency. The effective maximum frequency we can analyze is
#half of this (see Nyquist's theorem)
SAMPLING_FREQUENCY = 44100
#The default test frequency is in the middle of the band that contains 5000Hz
#This frequency was determined experimentally to be high enough but more
#reliable than others we tried.
DEFAULT_TEST_FREQUENCY = 5035
#only sample a signal when peak level is in this range (in dB attenuation,
#0 means no attenuation (and horrible clipping).
REC_LEVEL_RANGE = (-2.0, -12.0)
#For our test signal to be considered present, it has to be this much higher
#than the base level (minimum magnitude). This is in dB.
MAGNITUDE_THRESHOLD = 2.5
#Volume for the sample tone (in %)
PLAY_VOLUME = 70
class PIDController(object):
""" A Proportional-Integrative-Derivative controller (PID) controls a
process's output to try to maintain a desired output value (known as
'setpoint', by continually adjusting the process's input.
It does so by calculating the "error" (difference between output and
setpoint) and attempting to minimize it manipulating the input.
The desired change to the input is calculated based on error and three
constants (Kp, Ki and Kd). These values can be interpreted in terms of
time: P depends on the present error, I on the accumulation of past errors,
and D is a prediction of future errors, based on current rate of change.
The weighted sum of these three actions is used to adjust the process via a
control element.
In practice, Kp, Ki and Kd are process-dependent and usually have to
be tweaked by hand, but once reasonable constants are arrived at, they
can apply to a particular process without further modification.
"""
def __init__(self, Kp, Ki, Kd, setpoint=0):
""" Creates a PID controller with given constants and setpoint.
Arguments:
Kp, Ki, Kd: PID constants, see class description.
setpoint: desired output value; calls to input_change with
a process output reading will return a desired change
to the input to attempt matching output to this value.
"""
self.setpoint = setpoint
self.Kp = Kp
self.Ki = Ki
self.Kd = Kd
self._integral = 0
self._previous_error = 0
self._change_limit = 0
def input_change(self, process_feedback, dt):
""" Calculates desired input value change.
Based on process feedback and time interval (dt).
"""
error = self.setpoint - process_feedback
self._integral = self._integral + (error * dt)
derivative = (error - self._previous_error) / dt
self._previous_error = error
input_change = (self.Kp * error) + \
(self.Ki * self._integral) + \
(self.Kd * derivative)
if self._change_limit and abs(input_change) > abs(self._change_limit):
sign = input_change / abs(input_change)
input_change = sign * self._change_limit
return input_change
def set_change_limit(self, limit):
"""Ensures that input value changes are lower than limit.
Setting limit of zero disables this.
"""
self._change_limit = limit
class PAVolumeController(object):
pa_types = {'input': 'source', 'output': 'sink'}
def __init__(self, type, method=None, logger=None):
"""Initializes the volume controller.
Arguments:
type: either input or output
method: a method that will run a command and return pulseaudio
information in the described format, as a single string with
line breaks (to be processed with str.splitlines())
"""
self.type = type
self._volume = None
self.identifier = None
self.method = method
if not isinstance(method, collections.Callable):
self.method = self._pactl_output
self.logger = logger
def set_volume(self, volume):
if not 0 <= volume <= 100:
return False
if not self.identifier:
return False
command = ['pactl',
'set-%s-volume' % (self.pa_types[self.type]),
str(self.identifier[0]),
str(int(volume)) + "%"]
if False == self.method(command):
return False
self._volume = volume
return True
def get_volume(self):
if not self.identifier:
return None
return self._volume
def mute(self, mute):
mute = str(int(mute))
if not self.identifier:
return False
command = ['pactl',
'set-%s-mute' % (self.pa_types[self.type]),
str(self.identifier[0]),
mute]
if False == self.method(command):
return False
return True
def get_identifier(self):
if self.type:
self.identifier = self._get_identifier_for(self.type)
if self.identifier and self.logger:
message = "Using PulseAudio identifier %s (%s) for %s" %\
(self.identifier + (self.type,))
self.logger.info(message)
return self.identifier
def _get_identifier_for(self, type):
"""Gets default PulseAudio identifier for given type.
Arguments:
type: either input or output
Returns:
A tuple: (pa_id, pa_description)
"""
if type not in self.pa_types:
return None
command = ['pactl', 'list', self.pa_types[type] + "s", 'short']
#Expect lines of this form (field separator is tab):
#\t\t\t\t
#What we need to return is the ID for the first element on this list
#that does not contain auto_null or monitor.
pa_info = self.method(command)
valid_elements = None
if pa_info:
reject_regex = '.*(monitor|auto_null).*'
valid_elements = [element for element in pa_info.splitlines()
if not re.match(reject_regex, element)]
if not valid_elements:
if self.logger:
self.logger.error("No valid PulseAudio elements"
" for %s" % (self.type))
return None
#We only need the pulseaudio numeric ID and long name for each element
valid_elements = [(int(e.split()[0]), e.split()[1])
for e in valid_elements]
return valid_elements[0]
def _pactl_output(self, command):
#This method mainly calls pactl (hence the name). Since pactl may
#return a failure if the audio layer is not yet initialized, we will
#try running a few times in case of failure. All our invocations of
#pactl should be "idempotent" so repeating them should not have
#any bad effects.
for attempt in range(0, 3):
try:
return subprocess.check_output(command,
universal_newlines=True)
except (subprocess.CalledProcessError):
time.sleep(5)
return False
class FileDumper(object):
def write_to_file(self, filename, data):
try:
with open(filename, "w") as f:
for i in data:
print(i, file=f)
return_value = True
except (TypeError, IOError):
return_value = False
return return_value
class SpectrumAnalyzer(object):
def __init__(self, points, sampling_frequency=44100,
wanted_samples=50):
self.spectrum = [0] * points
self.number_of_samples = 0
self.wanted_samples = wanted_samples
self.sampling_frequency = sampling_frequency
#Frequencies should contain *real* frequency which is half of
#the sampling frequency
self.frequencies = [((sampling_frequency / 2.0) / points) * i
for i in range(points)]
def _average(self):
return sum(self.spectrum) / len(self.spectrum)
def sample(self, sample):
if len(sample) != len(self.spectrum):
return
self.spectrum = [((old * self.number_of_samples) + new) /
(self.number_of_samples + 1)
for old, new in zip(self.spectrum, sample)]
self.number_of_samples += 1
def frequencies_with_peak_magnitude(self, threshold=1.0):
#First establish the base level
per_magnitude_bins = collections.defaultdict(int)
for magnitude in self.spectrum:
per_magnitude_bins[magnitude] += 1
base_level = max(per_magnitude_bins,
key=lambda x: per_magnitude_bins[x])
#Now return all values that are higher (more positive)
#than base_level + threshold
peaks = []
for i in range(1, len(self.spectrum) - 1):
first_index = i - 1
last_index = i + 1
if self.spectrum[first_index] < self.spectrum[i] and \
self.spectrum[last_index] < self.spectrum[i] and \
self.spectrum[i] > base_level + threshold:
peaks.append(i)
return peaks
def frequency_band_for(self, frequency):
"""Convenience function to tell me which band
a frequency is contained in
"""
#Note that actual frequencies are half of what the sampling
#frequency would tell us. If SF is 44100 then maximum actual
#frequency is 22050, and if I have 10 frequency bins each will
#contain only 2205 Hz, not 4410 Hz.
max_frequency = self.sampling_frequency / 2
if frequency > max_frequency or frequency < 0:
return None
band = float(frequency) / (max_frequency / len(self.spectrum))
return int(math.ceil(band)) - 1
def frequencies_for_band(self, band):
"""Convenience function to tell me the delimiting frequencies
for a band
"""
if band >= len(self.spectrum) or band < 0:
return None
lower = self.frequencies[band]
upper = lower + ((self.sampling_frequency / 2.0) / len(self.spectrum))
return (lower, upper)
def sampling_complete(self):
return self.number_of_samples >= self.wanted_samples
class GStreamerMessageHandler(object):
def __init__(self, rec_level_range, logger, volumecontroller,
pidcontroller, spectrum_analyzer):
"""Initializes the message handler. It knows how to handle
spectrum and level gstreamer messages.
Arguments:
rec_level_range: tuple with acceptable recording level
ranges
logger: logging object with debug, info, error methods.
volumecontroller: an instance of VolumeController to use
to adjust RECORDING level
pidcontroller: a PID controller instance which helps control
volume
spectrum_analyzer: instance of SpectrumAnalyzer to collect
data from spectrum messages
"""
self.current_level = sys.maxsize
self.logger = logger
self.pid_controller = pidcontroller
self.rec_level_range = rec_level_range
self.spectrum_analyzer = spectrum_analyzer
self.volume_controller = volumecontroller
def set_quit_method(self, method):
""" Method that will be called when sampling is complete."""
self._quit_method = method
def bus_message_handler(self, bus, message):
if message.type == Gst.MessageType.ELEMENT:
message_name = message.get_structure().get_name()
if message_name == 'spectrum':
#TODO: Due to an upstream bug, a structure's get_value method
#doesn't work if the value in question is an array (as is the
#case with the magnitudes).
#https://bugzilla.gnome.org/show_bug.cgi?id=693168
#We have to resort to parsing the string representation of the
#structure. It's an ugly hack but it works.
#Ideally we'd be able to say this to get fft_magnitudes:
#message.get_structure.get_value('magnitude').
#If an upstream fix ever makes it into gstreamer,
#remember to remove this hack and the parse_spectrum
#method
struct_string = message.get_structure().to_string()
structure = parse_spectrum_message_structure(struct_string)
fft_magnitudes = structure['magnitude']
self.spectrum_method(self.spectrum_analyzer, fft_magnitudes)
if message_name == 'level':
#peak_value is our process feedback
#It's returned as an array, so I need the first (and only)
#element
peak_value = message.get_structure().get_value('peak')[0]
self.level_method(peak_value, self.pid_controller,
self.volume_controller)
#Adjust recording level
def level_method(self, level, pid_controller, volume_controller):
#If volume controller doesn't return a valid volume,
#we can't control it :(
current_volume = volume_controller.get_volume()
if current_volume is None:
self.logger.error("Unable to control recording volume."
"Test results may be wrong")
return
self.current_level = level
change = pid_controller.input_change(level, 0.10)
if self.logger:
self.logger.debug("Peak level: %(peak_level).2f, "
"volume: %(volume)d%%, Volume change: %(change)f%%" %
{'peak_level': level,
'change': change,
'volume': current_volume})
volume_controller.set_volume(current_volume + change)
#Only sample if level is within the threshold
def spectrum_method(self, analyzer, spectrum):
if self.rec_level_range[1] <= self.current_level \
or self.current_level <= self.rec_level_range[0]:
self.logger.debug("Sampling, recorded %d samples" %
analyzer.number_of_samples)
analyzer.sample(spectrum)
if analyzer.sampling_complete() and self._quit_method:
self.logger.info("Sampling complete, ending process")
self._quit_method()
class GstAudioObject(object):
def __init__(self):
self.class_name = self.__class__.__name__
def _set_state(self, state, description):
self.pipeline.set_state(state)
message = "%s: %s" % (self.class_name, description)
if self.logger:
self.logger.info(message)
def start(self):
self._set_state(Gst.State.PLAYING, "Starting")
def stop(self):
self._set_state(Gst.State.NULL, "Stopping")
class Player(GstAudioObject):
def __init__(self, frequency=DEFAULT_TEST_FREQUENCY, logger=None):
super(Player, self).__init__()
self.pipeline_description = ("audiotestsrc wave=sine freq=%s "
"! audioconvert "
"! audioresample "
"! autoaudiosink" % int(frequency))
self.logger = logger
if self.logger:
self.logger.debug(self.pipeline_description)
self.pipeline = Gst.parse_launch(self.pipeline_description)
class Recorder(GstAudioObject):
def __init__(self, output_file, bins=BINS,
sampling_frequency=SAMPLING_FREQUENCY,
fft_interval=FFT_INTERVAL, logger=None):
super(Recorder, self).__init__()
pipeline_description = ('''autoaudiosrc
! queue
! level message=true
! audioconvert
! audio/x-raw, channels=1, rate=(int)%(rate)s
! audioresample
! spectrum interval=%(fft_interval)s bands = %(bands)s
! wavenc
! filesink location=%(file)s''' %
{'bands': bins,
'rate': sampling_frequency,
'fft_interval': fft_interval,
'file': output_file})
self.logger = logger
if self.logger:
self.logger.debug(pipeline_description)
self.pipeline = Gst.parse_launch(pipeline_description)
def register_message_handler(self, handler_method):
if self.logger:
message = "Registering message handler: %s" % handler_method
self.logger.debug(message)
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message', handler_method)
def parse_spectrum_message_structure(struct_string):
#First let's jsonize this
#This is the message name, which we don't need
text = struct_string.replace("spectrum, ", "")
#name/value separator in json is : and not =
text = text.replace("=",": ")
#Mutate the {} array notation from the structure to
#[] notation for json.
text = text.replace("{","[")
text = text.replace("}","]")
#Remove a few stray semicolons that aren't needed
text = text.replace(";","")
#Remove the data type fields, as json doesn't need them
text = re.sub(r"\(.+?\)", "", text)
#double-quote the identifiers
text = re.sub(r"([\w-]+):", r'"\1":', text)
#Wrap the whole thing in brackets
text = ("{"+text+"}")
#Try to parse and return something sensible here, even if
#the data was unparsable.
try:
return json.loads(text)
except ValueError:
return None
def process_arguments():
description = """
Plays a single frequency through the default output, then records on
the default input device. Analyzes the recorded signal to test for
presence of the played frequency, if present it exits with success.
"""
parser = argparse.ArgumentParser(description=description)
parser.add_argument("-t", "--time",
dest='test_duration',
action='store',
default=30,
type=int,
help="""Maximum test duration, default %(default)s seconds.
It may exit sooner if it determines it has enough data.""")
parser.add_argument("-a", "--audio",
action='store',
default="/dev/null",
type=str,
help="File to save recorded audio in .wav format")
parser.add_argument("-q", "--quiet",
action='store_true',
default=False,
help="Be quiet, no output unless there's an error.")
parser.add_argument("-d", "--debug",
action='store_true',
default=False,
help="Debugging output")
parser.add_argument("-f", "--frequency",
action='store',
default=DEFAULT_TEST_FREQUENCY,
type=int,
help="Frequency for test signal, default %(default)s Hz")
parser.add_argument("-u", "--spectrum",
action='store',
type=str,
help="""File to save spectrum information for plotting
(one frequency/magnitude pair per line)""")
return parser.parse_args()
#
def main():
#Get arguments.
args = process_arguments()
#Setup logging
level = logging.INFO
if args.debug:
level = logging.DEBUG
if args.quiet:
level = logging.ERROR
logging.basicConfig(level=level)
try:
#Launches recording pipeline. I need to hook up into the gst
#messages.
recorder = Recorder(output_file=args.audio, logger=logging)
#Just launches the playing pipeline
player = Player(frequency=args.frequency, logger=logging)
except GObject.GError as excp:
logging.critical("Unable to initialize GStreamer pipelines: %s", excp)
sys.exit(127)
#This just receives a process feedback and tells me how much to change to
#achieve the setpoint
pidctrl = PIDController(Kp=0.7, Ki=.01, Kd=0.01,
setpoint=REC_LEVEL_RANGE[0])
pidctrl.set_change_limit(5)
#This gathers spectrum data.
analyzer = SpectrumAnalyzer(points=BINS,
sampling_frequency=SAMPLING_FREQUENCY)
#Volume controllers actually set volumes for their device types.
#we should at least issue a warning
recorder.volumecontroller = PAVolumeController(type='input',
logger=logging)
if not recorder.volumecontroller.get_identifier():
logging.warning("Unable to get input volume control identifier. "
"Test results will probably be invalid")
recorder.volumecontroller.set_volume(0)
recorder.volumecontroller.mute(False)
player.volumecontroller = PAVolumeController(type='output',
logger=logging)
if not player.volumecontroller.get_identifier():
logging.warning("Unable to get output volume control identifier. "
"Test results will probably be invalid")
player.volumecontroller.set_volume(PLAY_VOLUME)
player.volumecontroller.mute(False)
#This handles the messages from gstreamer and orchestrates
#the passed volume controllers, pid controller and spectrum analyzer
#accordingly.
gmh = GStreamerMessageHandler(rec_level_range=REC_LEVEL_RANGE,
logger=logging,
volumecontroller=recorder.volumecontroller,
pidcontroller=pidctrl,
spectrum_analyzer=analyzer)
#I need to tell the recorder which method will handle messages.
recorder.register_message_handler(gmh.bus_message_handler)
#Create the loop and add a few triggers
# GObject.threads_init() #Not needed?
loop = GLib.MainLoop()
GLib.timeout_add_seconds(0, player.start)
GLib.timeout_add_seconds(0, recorder.start)
GLib.timeout_add_seconds(args.test_duration, loop.quit)
# Tell the gmh which method to call when enough samples are collected
gmh.set_quit_method(loop.quit)
loop.run()
#When the loop ends, set things back to reasonable states
player.stop()
recorder.stop()
player.volumecontroller.set_volume(50)
recorder.volumecontroller.set_volume(10)
#See if data gathering was successful.
test_band = analyzer.frequency_band_for(args.frequency)
candidate_bands = analyzer.frequencies_with_peak_magnitude(MAGNITUDE_THRESHOLD)
for band in candidate_bands:
logging.debug("Band (%.2f,%.2f) contains a magnitude peak" %
analyzer.frequencies_for_band(band))
if test_band in candidate_bands:
freqs_for_band = analyzer.frequencies_for_band(test_band)
logging.info("PASS: Test frequency of %s in band (%.2f, %.2f) "
"which contains a magnitude peak" %
((args.frequency,) + freqs_for_band))
return_value = 0
else:
logging.info("FAIL: Test frequency of %s is not in one of the "
"bands with magnitude peaks" % args.frequency)
return_value = 1
#Is the microphone broken?
if len(set(analyzer.spectrum)) <= 1:
logging.info("WARNING: Microphone seems broken, didn't even "
"record ambient noise")
if args.spectrum:
logging.info("Saving spectrum data for plotting as %s" %
args.spectrum)
if not FileDumper().write_to_file(args.spectrum,
["%s,%s" % t for t in
zip(analyzer.frequencies,
analyzer.spectrum)]):
logging.error("Couldn't save spectrum data for plotting",
file=sys.stderr)
return return_value
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/filter_templates 0000775 0001750 0001750 00000006664 12646152433 024151 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import re
import sys
import posixpath
from optparse import OptionParser
from checkbox_support.lib.path import path_expand_recursive
from checkbox_support.lib.template import Template
class FilterError(Exception):
pass
def compile_filters(filters):
patterns = {}
for filter in filters:
if "=" not in filter:
raise FilterError("Missing assignment in filter: %s"
% filter)
name, value = filter.split("=", 1)
try:
pattern = re.compile(r"^%s$" % value)
except re.error:
raise FilterError("Invalid regular expression in filter: %s"
% value)
patterns.setdefault(name, [])
patterns[name].append(pattern)
return patterns
def match_patterns(patterns_table, element):
matches = []
for key, patterns in patterns_table.items():
if key not in element:
matches.append(False)
else:
value = element[key]
for pattern in patterns:
matches.append(True if pattern.match(value) else False)
return matches
def match_elements(elements, attributes=[], whitelist=[], blacklist=[]):
whitelist_patterns = compile_filters(whitelist)
blacklist_patterns = compile_filters(blacklist)
# Apply attributes
for element in elements:
for attribute in attributes:
name, value = attribute.split("=", 1)
element[name] = value
# Apply whitelist and blacklist
matches = []
for element in elements:
if whitelist_patterns \
and True not in match_patterns(whitelist_patterns, element):
continue
if blacklist_patterns \
and True in match_patterns(blacklist_patterns, element):
continue
matches.append(element)
return matches
def parse_file(file, *args, **kwargs):
template = Template()
matches = match_elements(template.load_file(file), *args, **kwargs)
template.dump_file(matches, sys.stdout)
def parse_path(path, *args, **kwargs):
for filename in path_expand_recursive(path):
print("# %s" % filename)
name = posixpath.basename(filename)
if name.startswith(".") or name.endswith("~"):
continue
file = open(filename, "r")
parse_file(file, *args, **kwargs)
def parse_paths(paths, *args, **kwargs):
for path in paths:
parse_path(path, *args, **kwargs)
def main(args):
usage = "Usage: %prog [OPTIONS] [FILE...]"
parser = OptionParser(usage=usage)
parser.add_option("-a", "--attribute",
action="append",
type="string",
default=[],
help="Set additional attributes by name and value.")
parser.add_option("-b", "--blacklist",
action="append",
type="string",
default=[],
help="Blacklist of elements by name and value.")
parser.add_option("-w", "--whitelist",
action="append",
type="string",
default=[],
help="Whitelist of elements by name and value.")
(options, args) = parser.parse_args(args)
if args:
parse_func = parse_paths
else:
parse_func = parse_file
args = sys.stdin
try:
parse_func(args, options.attribute,
options.whitelist, options.blacklist)
except FilterError as error:
parser.error(error.args[0])
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/sources_test 0000775 0001750 0001750 00000001237 12646152433 023317 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
result=0
sources_list=$1
repositories=$2
if [ -z "$sources_list" ]; then
echo "Must provide sources list location, e.g. /etc/apt/sources.list"
exit 1
fi
if [ -z "$repositories" ]; then
echo "Must provide list of repositories to check for, e.g. 'deb http://gb.archive.ubuntu.com/ubuntu/ precise multiverse, deb http://gb.archive.ubuntu.com/ubuntu/ precise-updates multiverse'"
exit 1
fi
IFS=$','
for repository in $repositories; do
if grep -q "$repository" "$sources_list"; then
echo "$repository found in $sources_list"
else
echo "$repository not found in $sources_list"
result=1
fi
done
exit $result
plainbox-provider-checkbox-0.25/bin/wifi_time2reconnect 0000775 0001750 0001750 00000003250 12646152433 024531 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import re
import sys
import time
import subprocess
from datetime import datetime
try:
from subprocess import DEVNULL # >= python3.3
except ImportError:
import os
DEVNULL = open(os.devnull, 'wb')
IFACE = None
TIMEOUT = 30
def main():
"""
Check the time needed to reconnect an active WIFI connection
"""
devices = subprocess.getoutput('nmcli dev')
match = re.search('(\w+)\s+(802-11-wireless|wifi)\s+connected', devices)
if match:
IFACE = match.group(1)
else:
print("No active wifi connection detected", file=sys.stderr)
return 1
try:
dev_status = subprocess.check_output(
['nmcli', '-t', '-f', 'devices,uuid', 'con', 'status'],
stderr=DEVNULL,
universal_newlines=True)
except subprocess.CalledProcessError:
dev_status = subprocess.check_output(
['nmcli', '-t', '-f', 'device,uuid', 'con', 'show'],
stderr=DEVNULL,
universal_newlines=True)
match = re.search(IFACE+':(.*)', dev_status)
uuid = None
if match:
uuid = match.group(1)
else:
return 1
subprocess.call(
'nmcli dev disconnect iface %s' %IFACE,
stdout=open(os.devnull, 'w'),
stderr=subprocess.STDOUT,
shell=True)
time.sleep(2)
start = datetime.now()
subprocess.call(
'nmcli con up uuid %s --timeout %s' %(uuid, TIMEOUT),
stdout=open(os.devnull, 'w'),
stderr=subprocess.STDOUT,
shell=True)
delta = datetime.now() - start
print('%.2f Seconds' %delta.total_seconds())
return 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/network_info 0000775 0001750 0001750 00000003416 12646152433 023302 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import sys
import subprocess
import socket
import fcntl
import struct
SYS_PATH = '/sys/class/net'
def _read_file(file):
source = open(file, 'r')
content = source.read()
source.close()
return content
def get_connected(interface):
STATUS = ('No', 'Yes')
carrier_file = os.path.join(SYS_PATH, interface, 'carrier')
carrier = 0
try:
carrier = int(_read_file(carrier_file))
except IOError:
pass
return STATUS[carrier]
def get_ip_address(interface):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', interface[:15].encode())
)[20:24])
def get_ipv6_address(interface):
cmd = ['/sbin/ip', '-6', 'addr', 'show', 'dev', interface]
proc = subprocess.check_output(cmd, universal_newlines=True)
ipaddr = proc.split()[8].strip()
return ipaddr
def get_mac_address(interface):
address_file = os.path.join(SYS_PATH, interface, 'address')
address = ''
try:
address = _read_file(address_file)
except IOError:
pass
return address
def main(args):
for interface in args:
connected = get_connected(interface)
print("Interface: %s" % interface)
print("Connected: %s" % connected)
try:
print("IPv4: %s" % get_ip_address(interface))
except IOError:
print("IPv4: n/a")
try:
print("IPv6: %s" % get_ipv6_address(interface))
except IOError:
print("IPv6: n/a")
except:
print("IPv6: n/a")
print("MAC: %s\n" % get_mac_address(interface))
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/network_device_info 0000775 0001750 0001750 00000021263 12646152433 024621 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
#
# This program 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Parts of this are based on the example python code that ships with
# NetworkManager
# http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python
#
# Copyright (C) 2012 Canonical, Ltd.
from subprocess import check_output, CalledProcessError, STDOUT
import sys
import dbus
from checkbox_support.parsers.modinfo import ModinfoParser
from checkbox_support.parsers.udevadm import UdevadmParser
# This example lists basic information about network interfaces known to NM
devtypes = {1: "Ethernet",
2: "WiFi",
5: "Bluetooth",
6: "OLPC",
7: "WiMAX",
8: "Modem"}
states = {0: "Unknown",
10: "Unmanaged",
20: "Unavailable",
30: "Disconnected",
40: "Prepare",
50: "Config",
60: "Need Auth",
70: "IP Config",
80: "IP Check",
90: "Secondaries",
100: "Activated",
110: "Deactivating",
120: "Failed"}
attributes = ("category", "interface", "product", "vendor", "driver", "path")
udev_devices = []
nm_devices = []
class UdevResult:
def addDevice(self, device):
if device.interface:
udev_devices.append(device)
class NetworkingDevice():
def __init__(self, devtype, props, dev_proxy, bus):
self._devtype = devtype
try:
self._interface = props['Interface']
except KeyError:
self._interface = "Unknown"
try:
self._ip = self._int_to_ip(props['Ip4Address'])
except KeyError:
self._ip = "Unknown"
try:
self._driver = props['Driver']
except KeyError:
self._driver = "Unknown"
self._driver_ver = "Unknown"
if self._driver != "Unknown":
self._modinfo = self._modinfo_parser(props['Driver'])
if self._modinfo:
self._driver_ver = self._find_driver_ver()
else:
self._driver_ver = "Unknown"
try:
self._firmware_missing = props['FirmwareMissing']
except KeyError:
self._firmware_missing = False
try:
self._state = states[props['State']]
except KeyError:
self._state = "Unknown"
def __str__(self):
ret = "Category: %s\n" % self._devtype
ret += "Interface: %s\n" % self._interface
ret += "IP: %s\n" % self._ip
ret += "Driver: %s (ver: %s)\n" % (self._driver, self._driver_ver)
if self._firmware_missing:
ret += "Warning: Required Firmware Missing for device\n"
ret += "State: %s\n" % self._state
return ret
def getstate(self):
return self._state
def gettype(self):
return self._devtype
def _bitrate_to_mbps(self, bitrate):
try:
intbr = int(bitrate)
return str(intbr / 1000)
except Exception:
return "NaN"
def _modinfo_parser(self, driver):
cmd = ['/sbin/modinfo', driver]
try:
stream = check_output(cmd, stderr=STDOUT, universal_newlines=True)
except CalledProcessError as err:
print("Error running %s:" % ' '.join(cmd), file=sys.stderr)
print(err.output, file=sys.stderr)
return None
if not stream:
print("Error: modinfo returned nothing", file=sys.stderr)
return None
else:
parser = ModinfoParser(stream)
modinfo = parser.get_all()
return modinfo
def _find_driver_ver(self):
# try the version field first, then vermagic second, some audio
# drivers don't report version if the driver is in-tree
if self._modinfo['version'] and self._modinfo['version'] != 'in-tree:':
return self._modinfo['version']
else:
# vermagic will look like this (below) and we only care about the
# first part:
# "3.2.0-29-generic SMP mod_unload modversions"
return self._modinfo['vermagic'].split()[0]
def _int_to_ip(self, int_ip):
ip = [0, 0, 0, 0]
ip[0] = int_ip & 0xff
ip[1] = (int_ip >> 8) & 0xff
ip[2] = (int_ip >> 16) & 0xff
ip[3] = (int_ip >> 24) & 0xff
return "%d.%d.%d.%d" % (ip[0], ip[1], ip[2], ip[3])
def get_nm_devices():
devices = []
bus = dbus.SystemBus()
# Get a proxy for the base NetworkManager object
proxy = bus.get_object("org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager")
manager = dbus.Interface(proxy, "org.freedesktop.NetworkManager")
# Get all devices known to NM and print their properties
nm_devices = manager.GetDevices()
for d in nm_devices:
dev_proxy = bus.get_object("org.freedesktop.NetworkManager", d)
prop_iface = dbus.Interface(dev_proxy,
"org.freedesktop.DBus.Properties")
props = prop_iface.GetAll("org.freedesktop.NetworkManager.Device")
try:
devtype = devtypes[props['DeviceType']]
except KeyError:
devtype = "Unknown"
# only return WiFi, Ethernet and Modem devices
if devtype in ("WiFi", "Ethernet", "Modem"):
devices.append(NetworkingDevice(devtype, props, dev_proxy, bus))
return devices
def match_counts(nm_devices, udev_devices, devtype):
"""
Ensures that the count of devices matching devtype is the same for the
two passed in lists, devices from Network Manager and devices from lspci.
"""
# now check that the count (by type) matches
nm_type_devices = [dev for dev in nm_devices if dev.gettype() in devtype]
udevtype = 'WIRELESS' if devtype == 'WiFi' else 'NETWORK'
udev_type_devices = [
udev
for udev in udev_devices
if udev.category == udevtype]
if len(nm_type_devices) != len(udev_type_devices):
print("ERROR: devices missing - udev showed %d %s devices, but "
"NetworkManager saw %d devices in %s" %
(len(udev_type_devices), udevtype,
len(nm_type_devices), devtype),
file=sys.stderr)
return False
else:
return True
def main(args):
try:
output = check_output(['udevadm', 'info', '--export-db'])
except CalledProcessError as err:
raise SystemExit(err)
try:
output = output.decode("UTF-8", errors='ignore')
except UnicodeDecodeError as err:
raise SystemExit("udevadm output is not valid UTF-8")
udev = UdevadmParser(output)
result = UdevResult()
udev.run(result)
if udev_devices:
print("[ Devices found by udev ]".center(80, '-'))
for device in udev_devices:
for attribute in attributes:
value = getattr(device, attribute)
if value is not None:
if attribute == 'driver':
props = {}
props['Driver'] = value
network_dev = NetworkingDevice(None, props, None, None)
print("%s: %s (ver: %s)" % (attribute.capitalize(),
value, network_dev._driver_ver))
else:
print("%s: %s" % (attribute.capitalize(), value))
print()
try:
nm_devices = get_nm_devices()
except dbus.exceptions.DBusException as e:
# server's don't have network manager installed
print("Warning: Exception while talking to Network Manager over dbus."
" Skipping the remainder of this test. If this is a server, this"
" is expected.", file=sys.stderr)
print("The Error Generated was:\n %s" % e, file=sys.stderr)
return 0
print("[ Devices found by Network Manager ]".center(80, '-'))
for nm_dev in nm_devices:
print(nm_dev)
if not match_counts(nm_devices, udev_devices, "WiFi"):
return 1
elif not match_counts(nm_devices, udev_devices, ("Ethernet", "Modem")):
return 1
else:
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
plainbox-provider-checkbox-0.25/bin/led_hdd_test 0000775 0001750 0001750 00000000563 12646152433 023220 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
TIMEOUT=3
TEMPFILE=`mktemp`
trap "rm $TEMPFILE" EXIT
for i in $(seq $TIMEOUT); do
#launch background writer
dd if=/dev/urandom of=$TEMPFILE bs=1024 oflag=direct &
WRITE_PID=$!
echo "Writing..."
sleep 1
kill $WRITE_PID
sync
echo "Reading..."
dd if=$TEMPFILE of=/dev/null bs=1024 iflag=direct
done
echo "OK, now exiting"
plainbox-provider-checkbox-0.25/bin/lock_screen_watcher 0000775 0001750 0001750 00000007746 12646152433 024614 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import argparse
import sys
import subprocess
import lsb_release
from gi.repository import GObject
from checkbox_support.dbus import connect_to_system_bus
import threading
import time
GObject.threads_init()
class SceenSaverStatusHelper(threading.Thread):
def __init__(self, loop):
super(SceenSaverStatusHelper, self).__init__()
self._loop = loop
self.quit = False
def query(self):
if (lsb_release.get_distro_information()["ID"] == "Ubuntu"):
if (lsb_release.get_distro_information()["CODENAME"] == "trusty"):
# trusty uses login screen as screen saver
process_ps = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE)
process_grep = subprocess.Popen(["grep",
"/usr/lib/unity/unity-panel-service --lockscreen-mode"],
stdin=process_ps.stdout,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
process_ps.stdout.close()
stdout = process_grep.communicate()[0]
if (len(stdout.decode().split("\n")) == 3):
print("the screensaver is active")
self._loop.quit()
p = subprocess.Popen(["gnome-screensaver-command", "-q"], stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
# parse the stdout string from the command "gnome-screensaver-command -q"
# the result should be "active" or "inactive"
if "active" == stdout.decode().split(" ")[-1].rstrip() :
print("the screensaver is active")
self._loop.quit()
def run(self):
while not self.quit:
GObject.idle_add(self.query)
time.sleep(1)
class HotkeyFunctionListener:
def __init__(self, system_bus, loop):
self._bus = system_bus
self._loop = loop
# Assume the test passes, this is changed when timeout expires
self._error = False
def _on_timeout_expired(self):
"""
Internal function called when the timer expires.
Basically it's just here to tell the user the test failed or that the
user was unable to pressed the hot key during the allowed time.
"""
print("You have failed to perform the required manipulation in time")
# Fail the test when the timeout was reached
self._error = True
# Stop the loop now
self._loop.quit()
def check(self, timeout):
"""
Run the configured test and return the result
The result is False if the test has failed. The timeout, when
non-zero, will make the test fail after the specified seconds have
elapsed without conclusive result.
"""
# Setup a timeout if requested
if timeout > 0:
GObject.timeout_add_seconds(timeout, self._on_timeout_expired)
# helper to listen the functionality is triggered or not
query_thread = SceenSaverStatusHelper(self._loop)
query_thread.start()
self._loop.run()
query_thread.quit = True
# Return the outcome of the test
return self._error
def main():
description = "Wait for the specified hotkey to be pressed."
parser = argparse.ArgumentParser(description=description)
parser.add_argument('--timeout', type=int, default=30)
args = parser.parse_args()
# Connect to the system bus, we also get the event
# loop as we need it to start listening for signals.
system_bus, loop = connect_to_system_bus()
listener = HotkeyFunctionListener(system_bus, loop)
# Run the actual listener and wait till it either times out or discovers
# the specific hot key pressed.
try:
return listener.check(args.timeout)
except KeyboardInterrupt:
return 1
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/gputest_benchmark 0000775 0001750 0001750 00000001503 12646152433 024276 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/python3
# This file is part of Checkbox.
#
# Copyright 2013 Canonical Ltd.
# Written by:
# Sylvain Pineau
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
import sys
from checkbox_support.scripts.gputest_benchmark import main
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/network_bandwidth_test 0000775 0001750 0001750 00000051016 12646152433 025351 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import os
import re
import sys
import random
import logging
import subprocess
from datetime import datetime, timedelta
from time import sleep
from logging import StreamHandler, FileHandler, Formatter
from optparse import OptionParser
from checkbox_support.lib.conversion import string_to_type
class CommandException(Exception):
pass
class CommandOutput(object):
def __init__(self, **attributes):
self._attributes = attributes
def __getattr__(self, name):
if name in self._attributes:
return self._attributes.get(name)
return None
class Command(object):
# Name of the command to run
name = None
# Number of command line arguments
argument_count = 0
# Option processing
option_strings = {}
option_defaults = {}
# Ouput processing
output_factory = CommandOutput
output_patterns = {}
# Convenient output patterns
non_space = r"[^ ]+"
def __init__(self, *arguments, **options):
if len(arguments) != self.argument_count:
raise TypeError("Invalid number of arguments: %d" % len(arguments))
self._arguments = arguments
self._options = self.option_defaults.copy()
for name, string in options.items():
if name not in self.option_strings:
raise TypeError("Unknown option: %s" % name)
self._options[name] = string
def get_command(self):
command = [self.name]
for name, string in self._options.items():
# Match option from string
if isinstance(string, bool):
option = self.option_strings[name]
else:
option = self.option_strings[name] % string
command.append(option)
command.extend(self._arguments)
return " ".join(command)
def parse_lines(self, lines):
attributes = {}
for line in lines:
# Match patterns from lines
for name, pattern in self.output_patterns.items():
match = re.search(pattern, line)
if match:
attributes[name] = string_to_type(match.group(1))
return self.output_factory(**attributes)
def parse_output(self, output):
lines = output.split("\n")
# Strip leading and trailing spaces
lines = [l.strip() for l in lines]
# Skip blank lines
lines = [l for l in lines if l]
return self.parse_lines(lines)
def run(self):
command = self.get_command()
logging.debug("Running command: %s" % command)
process = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
error = process.stderr.read()
if error:
raise CommandException(error.decode("utf-8"))
output = process.stdout.read()
return self.parse_output(output.decode("utf-8"))
class NetworkConfigOutput(CommandOutput):
@property
def speed(self):
if self.name == "lo":
return 10000
try:
wireless = WirelessConfig(self.name).run()
speed = wireless.bit_rate
except CommandException:
wired = WiredConfig(self.name).run()
speed = wired.speed
return speed / 1024 / 1024
class NetworkConfig(Command):
name = "ifconfig"
argument_count = 1
ipv4 = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
ipv6 = r"[\w:]+/\d+"
mac_address = r"\w\w:\w\w:\w\w:\w\w:\w\w:\w\w"
output_factory = NetworkConfigOutput
output_patterns = {
"name": r"(%s).*Link encap" % Command.non_space,
"broadcast": r"Bcast:(%s)" % ipv4,
"collisions": "collisions:(\d+)",
"hwaddr": r"HWaddr (%s)" % mac_address,
"inet_addr": r"inet addr:(%s)" % ipv4,
"link_encap": r"Link encap:(%s)" % Command.non_space,
"netmask": r"Mask:(%s)" % ipv4,
"metric": r"Metric:(\d+)",
"mtu": r"MTU:(\d+)",
"rx_bytes": "RX bytes:(\d+)",
"rx_dropped": "RX packets:.* dropped:(\d+)",
"rx_errors": "RX packets:.* errors:(\d+)",
"rx_frame": "RX packets:.* frame:(\d+)",
"rx_overruns": "RX packets:.* overruns:(\d+)",
"rx_packets": "RX packets:(\d+)",
"tx_bytes": "TX bytes:(\d+)",
"tx_carrier": "TX packets:.* carrier:(\d+)",
"tx_dropped": "TX packets:.* dropped:(\d+)",
"tx_errors": "TX packets:.* errors:(\d+)",
"tx_overruns": "TX packets:.* overruns:(\d+)",
"tx_packets": "TX packets:(\d+)",
"txqueuelen": "txqueuelen:(\d+)"}
class NetworkConfigs(Command):
name = "ifconfig -a"
def parse_output(self, output):
outputs = []
for paragraph in output.split("\n\n"):
if not paragraph:
continue
lines = paragraph.split("\n")
name = re.split(r"\s+", lines[0])[0]
config = NetworkConfig(name).parse_lines(lines)
outputs.append(config)
return outputs
class WiredConfig(Command):
name = "ethtool"
argument_count = 1
output_patterns = {
"advertised_auto_negotiation": r"Advertised auto-negotiation:\s+(.*)",
"advertised_link_modes": r"Advertised link modes:\s+(.*)",
"auto_negotiation": r"Auto-negotiation:\s+(.*)",
"current_message_level": r"Current message level:\s+(.*)",
"duplex": r"Duplex:\s+(.*)",
"link_detected": r"Link detected:\s+(.*)",
"phyad": r"PHYAD:\s+(.*)",
"port": r"Port:\s+(.*)",
"speed": r"Speed:\s+(.*)/s",
"supported_auto_negotiation": r"Supports auto-negotiation:\s+(.*)",
"supported_link_modes": r"Supported link modes:\s+(.*)",
"supported_ports": r"Supported ports:\s+(.*)",
"supports_wake_on": r"Supports Wake-on:\s+(.*)",
"transceiver": r"Transceiver:\s+(.*)",
"wake_on": r"Wake-on:\s+(.*)"}
def parse_lines(self, lines):
new_lines = []
# Skip header line
for line in lines[1:]:
if not re.search(r": ", line):
new_lines[-1] += " " + line
else:
new_lines.append(line)
return super(WiredConfig, self).parse_lines(new_lines)
class WirelessConfig(Command):
name = "iwconfig"
argument_count = 1
fraction = r"\d+(/\d+)?"
numeric = r"[\d\.]+"
numeric_with_unit = r"%s( %s)?" % (numeric, Command.non_space)
output_patterns = {
"access_point": r"Access Point: (.*)",
"bit_rate": r"Bit Rate[=:](%s)/s" % numeric_with_unit,
"channel": r"Channel=(%s)" % Command.non_space,
"essid": r"ESSID:\"?([^\"]+)\"?",
"fragment_thr": r"Fragment thr:(\w+)",
"frequency": r"Frequency:(%s)" % numeric_with_unit,
"invalid_misc": r"Invalid misc:(\d+)",
"link_quality": r"Link Quality[=:](%s)" % fraction,
"missed_beacon": r"Missed beacon:(\d+)",
"mode": r"Mode:(%s)" % Command.non_space,
"noise_level": r"Noise level[=:](%s)" % numeric_with_unit,
"power_management": r"Power Management:(.*)",
"retry_limit": r"Retry limit:(\w+)",
"rts_thr": r"RTS thr:(\w+)",
"rx_invalid_crypt": r"Rx invalid crypt:(\d+)",
"rx_invalid_frag": r"Rx invalid frag:(\d+)",
"rx_invalid_nwid": r"Rx invalid nwid:(\d+)",
"sensitivity": r"Sensitivity=(%s)" % fraction,
"signal_level": r"Signal level[=:](%s)" % numeric_with_unit,
"tx_excessive_retries": r"Tx excessive retries:(\d+)",
"tx_power": r"Tx-Power=(%s)" % numeric_with_unit}
class Ping(Command):
name = "ping"
argument_count = 1
option_strings = {
"count": "-c %d",
"flood": "-f",
"interface": "-I %s",
"quiet": "-q",
"size": "-s %d",
"ttl": "-t %d"}
option_defaults = {
"count": 1,
"quiet": True}
ms = r"\d+\.\d+"
rtt = (ms, ms, ms, ms)
output_patterns = {
"packet_loss": r"(\d+)% packet loss,",
"packets_received": r"(\d+) received,",
"packets_transmitted": r"(\d+) packets transmitted,",
"rtt_avg": r"rtt min/avg/max/mdev = %s/(%s)/%s/%s ms" % rtt,
"rtt_max": r"rtt min/avg/max/mdev = %s/%s/(%s)/%s ms" % rtt,
"rtt_mdev": r"rtt min/avg/max/mdev = %s/%s/%s/(%s) ms" % rtt,
"rtt_min": r"rtt min/avg/max/mdev = (%s)/%s/%s/%s ms" % rtt,
"time": r"time (\d+)ms"}
def parse_lines(self, lines):
# Skip ping lines
return super(Ping, self).parse_lines(lines[-2:])
class PingLarge(Ping):
# Some wired environments can handle the maximum ping packet
# size, (65507+28)=65535 bytes. With a count of 191 packets, 65535
# bytes/packet, 8 bits/byte, the sum payload is 100137480 bits ~
# 100Mb. This is preferred and will be tried first.
packet_size = 65507
packet_count = 191
option_defaults = {
"count": packet_count,
"flood": True,
"quiet": True,
"size": packet_size,
"ttl": 1}
class PingSmall(PingLarge):
# If the large packet test was too lossy, we fall back to a packet
# equal to the default MTU size of 1500, (1472+28)=1500 bytes.
# With a count of 8334 packets, 1500 bytes/packet, 8 bits/byte, the
# sum payload is 100008000 bits ~ 100Mb.
packet_size = 1472
packet_count = 8334
option_defaults = PingLarge.option_defaults.copy()
option_defaults.update({
"count": packet_count,
"size": packet_size})
class PingHost(Command):
output_patterns = {
"host": r"(?:Host|Nmap scan report for) (%s)" % NetworkConfig.ipv4,
"mac_address": r"MAC Address: (%s)" % NetworkConfig.mac_address}
class PingScan(Command):
name = "nmap -n -sP"
argument_count = 1
def parse_lines(self, lines):
hosts = []
host_lines = []
# Skip header lines
for line in lines[1:]:
host_lines.append(line)
if line.startswith("MAC Address"):
host = PingHost().parse_lines(host_lines)
hosts.append(host)
host_lines = []
return hosts
class Ip(object):
def __init__(self, address):
self.address = address
self.binary = self._address_to_binary(address)
def __str__(self):
return self.address
def _address_to_binary(self, address):
binary = 0
for position, part in enumerate(address.split(".")):
if position >= 4:
raise ValueError("Address contains more than four parts.")
try:
if not part:
part = 0
else:
part = int(part)
if not 0 <= part < 256:
raise ValueError
except ValueError:
raise ValueError("Address part out of range.")
binary <<= 8
binary += part
return binary
def count_1_bits(self):
ret = 0
num = self.binary
while num > 0:
num = num >> 1
ret += 1
return ret
def count_0_bits(self):
num = int(self.binary)
if num < 0:
raise ValueError("Only positive Numbers please: %s" % (num))
ret = 0
while num > 0:
if num & 1 == 1:
break
num = num >> 1
ret += 1
return ret
class IpRange(object):
def __init__(self, address, netmask):
self.address = Ip(address)
self.netmask = Ip(netmask)
self.prefix = self._netmask_to_prefix(self.netmask)
def __str__(self):
return "%s/%s" % (self.address, self.prefix)
def _check_netmask(self, masklen):
num = int(self.netmask.binary)
bits = masklen
# remove zero bits at the end
while (num & 1) == 0:
num = num >> 1
bits -= 1
if bits == 0:
break
# now check if the rest consists only of ones
while bits > 0:
if (num & 1) == 0:
raise ValueError("Netmask %s can't be expressed as an prefix."
% (hex(self.netmask.binary)))
num = num >> 1
bits -= 1
def _netmask_to_prefix(self, netmask):
netlen = netmask.count_0_bits()
masklen = netmask.count_1_bits()
self._check_netmask(masklen)
return masklen - netlen
def contains(self, address):
address = Ip(address)
if self.address.binary & self.netmask.binary \
== address.binary & self.netmask.binary:
return True
return False
def scan(self, max=None):
scan = PingScan(str(self)).run()
targets = [s.host for s in scan]
random.shuffle(targets)
if max is not None:
targets = targets[:max]
return targets
class NetworkManagerException(Exception):
pass
class NetworkManager(object):
NM_SERVICE = "org.freedesktop.NetworkManager"
NM_PATH = "/org/freedesktop/NetworkManager"
NM_INTERFACE = NM_SERVICE
NM_PATH_DEVICES = "/org/freedesktop/NetworkManager/Devices"
NM_INTERFACE_DEVICES = "org.freedesktop.NetworkManager.Devices"
NMI_SERVICE = "org.freedesktop.NetworkManagerInfo"
NMI_PATH = "/org/freedesktop/NetworkManagerInfo"
NMI_INTERFACE = NMI_SERVICE
HAL_SERVICE = "org.freedesktop.Hal"
HAL_PATH = "/org/freedesktop/Hal/Manager"
HAL_INTERFACE = "org.freedesktop.Hal.Manager"
HAL_INTERFACE_DEVICE = "org.freedesktop.Hal.Device"
#http://projects.gnome.org/NetworkManager/developers/
#NetworkManager D-Bus API Specifications, look for the
#NM_STATE enumeration to see which statuses indicate connection
#established and put them in this list. "3" works for NM 0.7
#and 0.8, while "60" and "70" work for NM 0.9.
STATES_CONNECTED = [3, 60, 70]
def __init__(self):
try:
import dbus
except ImportError:
raise NetworkManagerException("Python module not found: dbus")
try:
self._bus = dbus.SystemBus()
self.nm_object = self._bus.get_object(self.NM_SERVICE,
self.NM_PATH)
self.nm_service = dbus.Interface(self.nm_object, self.NM_INTERFACE)
except dbus.exceptions.DBusException:
raise NetworkManagerException("Failed to connect to dbus service")
def is_connected(self):
state = self.nm_service.state()
return state in self.STATES_CONNECTED
class Application(object):
def __init__(self, targets, interfaces, scan):
self.targets = targets
self.interfaces = interfaces
self.scan = scan
def test_interface(self, interface, targets):
logging.info("Testing %s at %s-Mbps", interface.name, interface.speed)
for target in targets:
ping = PingLarge(target, interface=interface.name)
result = ping.run()
if result.packet_loss:
ping = PingSmall(target, interface=interface.name)
result = ping.run()
if result.packet_loss:
logging.warning("SKIP: Non-zero packet loss (%s%%) "
"for [%s] [%s]->[%s]",
result.packet_loss, interface.name,
interface.inet_addr, target)
continue
mbps = (8 * (ping.packet_size + 28) * ping.packet_count
/ result.time / 1000)
percent = (100 * 8 * (ping.packet_size + 28) * ping.packet_count
/ result.time / 1000 / interface.speed)
if percent >= 10:
logging.info("PASS: Effective rate: %3.4f Mbps, "
"%3.2f%% of theoretical max (%5.2f Mbps)",
mbps, percent, interface.speed)
return True
else:
logging.warning("Unacceptable network effective rate found for [%s]" % interface.name)
logging.warning("Effective rate %3.4f Mbps, %3.2f%% of theoretical max (%5.2f Mbps)" %
(mbps, percent, interface.speed))
return False
def run(self):
logging.debug("Acquiring network Interfaces")
if self.interfaces:
interfaces = [NetworkConfig(i).run() for i in self.interfaces]
else:
interfaces = NetworkConfigs().run()
interfaces = [i for i in interfaces if i.inet_addr]
for interface in interfaces:
if not interface.inet_addr:
logging.debug("No network address for [%s]", interface.name)
continue
targets = []
ip_range = IpRange(interface.inet_addr, interface.netmask)
if self.targets:
for target in self.targets:
if ip_range.contains(target):
targets.append(target)
elif interface.name != "lo":
targets = ip_range.scan(self.scan)
logging.info("The following targets were found for %s:" % interface.name)
for target in targets:
logging.info("\t%s" % target)
if not targets:
logging.debug("No targets found for [%s]", interface.name)
continue
if not self.test_interface(interface, targets):
return False
return True
class ApplicationManager(object):
application_factory = Application
default_log_level = "critical"
default_scan = 1
default_timeout = 60
def get_parser(self, args):
usage = "Usage: %prog [TARGETS]"
parser = OptionParser(usage=usage)
parser.add_option("-i", "--interface",
dest="interfaces",
action="append",
type="string",
default=[],
help="Interface to test.")
parser.add_option("-s", "--scan",
default=self.default_scan,
type="int",
help="Number of targets to scan when not provided.")
parser.add_option("-t", "--timeout",
default=self.default_timeout,
type="int",
help="Time to wait for network manager to connect.")
parser.add_option("-l", "--log",
metavar="FILE",
help="The file to write the log to.")
parser.add_option("--log-level",
default=self.default_log_level,
help=("One of debug, info, warning, "
"error or critical."))
return parser
def check_uid(self):
return os.getuid() == 0
def check_network(self, timeout):
try:
nm = NetworkManager()
except NetworkManagerException:
return True
start = datetime.now()
while True:
if nm.is_connected():
return True
if datetime.now() - start > timedelta(seconds=timeout):
return False
sleep(5)
def create_application(self, args=sys.argv[1:]):
parser = self.get_parser(args)
(options, args) = parser.parse_args(args)
log_level = logging.getLevelName(options.log_level.upper())
log_handlers = []
if options.log:
log_filename = options.log
log_handlers.append(FileHandler(log_filename))
else:
log_handlers.append(StreamHandler())
# Logging setup
format = ("%(asctime)s %(levelname)-8s %(message)s")
date_format = '%Y-%m-%d %H:%M:%S'
if log_handlers:
for handler in log_handlers:
handler.setFormatter(Formatter(format, date_format))
logging.getLogger().addHandler(handler)
if log_level:
logging.getLogger().setLevel(log_level)
elif not logging.getLogger().handlers:
logging.disable(logging.CRITICAL)
if not self.check_uid():
parser.error("Must be run as root.")
if not self.check_network(options.timeout):
parser.error("Network devices must be configured and connected to a LAN segment before testing")
targets = args
return self.application_factory(targets,
options.interfaces, options.scan)
def main():
application_manager = ApplicationManager()
application = application_manager.create_application()
if not application.run():
return 1
return 0
if __name__ == "__main__":
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/pm_test 0000775 0001750 0001750 00000101074 12646152433 022250 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
import logging
import logging.handlers
import os
import pwd
import re
import shutil
import subprocess
import sys
import signal
from argparse import ArgumentParser, SUPPRESS
from calendar import timegm
from datetime import datetime, timedelta
from gi.repository import Gtk, GObject
from time import time, localtime
def main():
"""
Run power management operation as many times as needed
"""
args, extra_args = MyArgumentParser().parse()
# Verify that script is run as root
if os.getuid():
sys.stderr.write('This script needs superuser '
'permissions to run correctly\n')
sys.exit(1)
#Obtain name of the invoking user.
uid = os.getenv('SUDO_UID') or os.getenv('PKEXEC_UID')
if not uid:
sys.stderr.write('Unable to determine invoking user\n')
sys.exit(1)
username = pwd.getpwuid(int(uid)).pw_name
LoggingConfiguration.set(args.log_level, args.log_filename, args.append)
logging.debug('Invoking username: %s', username)
logging.debug('Arguments: {0!r}'.format(args))
logging.debug('Extra Arguments: {0!r}'.format(extra_args))
try:
operation = PowerManagementOperation(args, extra_args, user=username)
operation.setup()
operation.run()
except (TestCancelled, TestFailed) as exception:
if isinstance(exception, TestFailed):
logging.error(exception.args[0])
message = exception.MESSAGE.format(args.pm_operation.capitalize())
if args.silent:
logging.info(message)
else:
title = '{0} test'.format(args.pm_operation.capitalize())
MessageDialog(title, message, Gtk.MessageType.ERROR).run()
operation.teardown()
return exception.RETURN_CODE
return 0
class PowerManagementOperation(object):
SLEEP_TIME = 5
def __init__(self, args, extra_args, user=None):
self.args = args
self.extra_args = extra_args
self.user = user
def setup(self):
"""
Enable configuration file
"""
# Enable autologin and sudo on first cycle
if self.args.total == self.args.repetitions:
AutoLoginConfigurator(user=self.user).enable()
SudoersConfigurator(user=self.user).enable()
# Schedule this script to be automatically executed
# on startup to continue testing
autostart_file = AutoStartFile(self.args, user=self.user)
autostart_file.write()
def run(self):
"""
Run a power management iteration
"""
logging.info('{0} operations remaining: {1}'
.format(self.args.pm_operation, self.args.repetitions))
if self.args.pm_timestamp:
pm_timestamp = datetime.fromtimestamp(self.args.pm_timestamp)
now = datetime.now()
pm_time = now - pm_timestamp
logging.info('{0} time: {1}'
.format(self.args.pm_operation.capitalize(), pm_time))
if self.args.repetitions > 0:
self.run_suspend_cycles(self.args.suspends_before_reboot,
self.args.fwts)
self.run_pm_command()
else:
self.summary()
def run_pm_command(self):
"""
Run power managment command and check result if needed
"""
# Display information to user
# and make it possible to cancel the test
CountdownDialog(self.args.pm_operation,
self.args.pm_delay,
self.args.hardware_delay,
self.args.total - self.args.repetitions,
self.args.total).run()
# A small sleep time is added to reboot and poweroff
# so that script has time to return a value
# (useful when running it as an automated test)
command_str = ('sleep {0}; {1}'
.format(self.SLEEP_TIME, self.args.pm_operation))
if self.extra_args:
command_str += ' {0}'.format(' '.join(self.extra_args))
if self.args.pm_operation != 'reboot':
WakeUpAlarm.set(seconds=self.args.wakeup)
logging.info('Executing new {0!r} operation...'
.format(self.args.pm_operation))
logging.debug('Executing: {0!r}...'.format(command_str))
# The PM operation is performed asynchronously so let's just wait
# indefinitely until it happens and someone comes along to kill us.
# This addresses LP: #1413134
subprocess.check_call(command_str, shell=True)
signal.pause()
def run_suspend_cycles(self, cycles_count, fwts):
"""Run suspend and resume cycles."""
if cycles_count < 1:
return
if fwts:
script_name = 'fwts_test'
command_tpl = '{} -s s3 --s3-sleep-delay=30 --s3-multiple={}'
else:
script_name = 'sleep_test'
command_tpl = '{} -s mem -p -i {} -w 10'
script_path = os.path.join(
os.path.dirname(os.path.realpath(__file__)), script_name)
command_str = command_tpl.format(script_path, cycles_count)
logging.info('Running suspend/resume cycles')
logging.debug('Executing: {0!r}...'.format(command_str))
# We call sleep_test script and log its output as it contains
# average times we need to compute global average times later.
logging.info(subprocess.check_output(command_str,
universal_newlines=True, shell=True))
def summary(self):
"""
Gather hardware information for the last time,
log execution time and exit
"""
# Just gather hardware information one more time and exit
CountdownDialog(self.args.pm_operation,
self.args.pm_delay,
self.args.hardware_delay,
self.args.total - self.args.repetitions,
self.args.total).run()
self.teardown()
# Log some time information
start = datetime.fromtimestamp(self.args.start)
end = datetime.now()
if self.args.pm_operation == 'reboot':
sleep_time = timedelta(seconds=self.SLEEP_TIME)
else:
sleep_time = timedelta(seconds=self.args.wakeup)
wait_time = timedelta(seconds=(self.args.pm_delay
+ (self.args.hardware_delay)
* self.args.total))
average = (end - start - wait_time) / self.args.total - sleep_time
time_message = ('Total elapsed time: {total}\n'
'Average recovery time: {average}'
.format(total=end - start,
average=average))
logging.info(time_message)
message = ('{0} test complete'
.format(self.args.pm_operation.capitalize()))
if self.args.silent:
logging.info(message)
else:
title = '{0} test'.format(self.args.pm_operation.capitalize())
MessageDialog(title, message).run()
def teardown(self):
"""
Restore configuration
"""
# Don't execute this script again on next reboot
autostart_file = AutoStartFile(self.args, user=self.user)
autostart_file.remove()
# Restore previous configuration
SudoersConfigurator().disable()
AutoLoginConfigurator().disable()
class TestCancelled(Exception):
RETURN_CODE = 1
MESSAGE = '{0} test cancelled by user'
class TestFailed(Exception):
RETURN_CODE = 2
MESSAGE = '{0} test failed'
class WakeUpAlarm(object):
ALARM_FILENAME = '/sys/class/rtc/rtc0/wakealarm'
RTC_FILENAME = '/proc/driver/rtc'
@classmethod
def set(cls, minutes=0, seconds=0):
"""
Calculate wakeup time and write it to BIOS
"""
now = int(time())
timeout = minutes * 60 + seconds
wakeup_time_utc = now + timeout
wakeup_time_local = timegm(localtime()) + timeout
subprocess.check_call('echo 0 > %s' % cls.ALARM_FILENAME, shell=True)
subprocess.check_call('echo %d > %s'
% (wakeup_time_utc, cls.ALARM_FILENAME),
shell=True)
with open(cls.ALARM_FILENAME) as alarm_file:
wakeup_time_stored_str = alarm_file.read()
if not re.match('\d+', wakeup_time_stored_str):
subprocess.check_call('echo "+%d" > %s'
% (timeout, cls.ALARM_FILENAME),
shell=True)
with open(cls.ALARM_FILENAME) as alarm_file2:
wakeup_time_stored_str = alarm_file2.read()
if not re.match('\d+', wakeup_time_stored_str):
logging.error('Invalid wakeup time format: {0!r}'
.format(wakeup_time_stored_str))
sys.exit(1)
wakeup_time_stored = int(wakeup_time_stored_str)
try:
logging.debug('Wakeup timestamp: {0} ({1})'
.format(wakeup_time_stored,
datetime.fromtimestamp(
wakeup_time_stored).strftime('%c')))
except ValueError as e:
logging.error(e)
sys.exit(1)
if ((abs(wakeup_time_utc - wakeup_time_stored) > 1) and
(abs(wakeup_time_local - wakeup_time_stored) > 1)):
logging.error('Wakeup time not stored correctly')
sys.exit(1)
with open(cls.RTC_FILENAME) as rtc_file:
separator_regex = re.compile('\s+:\s+')
rtc_data = dict([separator_regex.split(line.rstrip())
for line in rtc_file])
logging.debug('RTC data:\n{0}'
.format('\n'.join(['- {0}: {1}'.format(*pair)
for pair in rtc_data.items()])))
# Verify wakeup time has been set properly
# by looking into the alarm_IRQ and alrm_date field
if rtc_data['alarm_IRQ'] != 'yes':
logging.error('alarm_IRQ not set properly: {0}'
.format(rtc_data['alarm_IRQ']))
sys.exit(1)
if '*' in rtc_data['alrm_date']:
logging.error('alrm_date not set properly: {0}'
.format(rtc_data['alrm_date']))
sys.exit(1)
class Command(object):
"""
Simple subprocess.Popen wrapper to run shell commands
and log their output
"""
def __init__(self, command_str, verbose=True):
self.command_str = command_str
self.verbose = verbose
self.process = None
self.stdout = None
self.stderr = None
self.time = None
def run(self):
"""
Execute shell command and return output and status
"""
logging.debug('Executing: {0!r}...'.format(self.command_str))
self.process = subprocess.Popen(self.command_str,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
start = datetime.now()
result = self.process.communicate()
end = datetime.now()
self.time = end - start
if self.verbose:
stdout, stderr = result
message = ['Output:\n'
'- returncode:\n{0}'.format(self.process.returncode)]
if stdout:
if type(stdout) is bytes:
stdout = stdout.decode('utf-8')
message.append('- stdout:\n{0}'.format(stdout))
if stderr:
if type(stderr) is bytes:
stderr = stderr.decode('utf-8')
message.append('- stderr:\n{0}'.format(stderr))
logging.debug('\n'.join(message))
self.stdout = stdout
self.stderr = stderr
return self
class CountdownDialog(Gtk.Dialog):
"""
Dialog that shows the amount of progress in the reboot test
and lets the user cancel it if needed
"""
def __init__(self, pm_operation, pm_delay, hardware_delay,
iterations, iterations_count):
self.pm_operation = pm_operation
title = '{0} test'.format(pm_operation.capitalize())
buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,)
super(CountdownDialog, self).__init__(title=title,
buttons=buttons)
self.set_default_response(Gtk.ResponseType.CANCEL)
self.set_resizable(False)
self.set_position(Gtk.WindowPosition.CENTER)
progress_bar = Gtk.ProgressBar()
progress_bar.set_fraction(iterations / float(iterations_count))
progress_bar.set_text('{0}/{1}'
.format(iterations, iterations_count))
progress_bar.set_show_text(True)
self.vbox.pack_start(progress_bar, True, True, 0)
operation_event = {'template': ('Next {0} in {{time}} seconds...'
.format(self.pm_operation)),
'timeout': pm_delay}
hardware_info_event = \
{'template': 'Gathering hardware information in {time} seconds...',
'timeout': hardware_delay,
'callback': self.on_hardware_info_timeout_cb}
if iterations == 0:
# In first iteration, gather hardware information directly
# and perform pm-operation
self.on_hardware_info_timeout_cb()
self.events = [operation_event]
elif iterations < iterations_count:
# In last iteration, wait before gathering hardware information
# and perform pm-operation
self.events = [operation_event,
hardware_info_event]
else:
# In last iteration, wait before gathering hardware information
# and finish the test
self.events = [hardware_info_event]
self.label = Gtk.Label()
self.vbox.pack_start(self.label, True, True, 0)
self.show_all()
def run(self):
"""
Set label text and run dialog
"""
self.schedule_next_event()
response = super(CountdownDialog, self).run()
self.destroy()
if response != Gtk.ResponseType.ACCEPT:
raise TestCancelled()
def schedule_next_event(self):
"""
Schedule next timed event
"""
if self.events:
self.event = self.events.pop()
self.timeout_counter = self.event.get('timeout', 0)
self.label.set_text(self.event['template']
.format(time=self.timeout_counter))
GObject.timeout_add_seconds(1, self.on_timeout_cb)
else:
# Return Accept response
# if there are no other events scheduled
self.response(Gtk.ResponseType.ACCEPT)
def on_timeout_cb(self):
"""
Set label properly and use callback method if needed
"""
if self.timeout_counter > 0:
self.label.set_text(self.event['template']
.format(time=self.timeout_counter))
self.timeout_counter -= 1
return True
# Call calback if defined
callback = self.event.get('callback')
if callback:
callback()
# Schedule next event if needed
self.schedule_next_event()
return False
def on_hardware_info_timeout_cb(self):
"""
Gather hardware information and print it to logs
"""
logging.info('Gathering hardware information...')
logging.debug('Networking:\n'
'{network}\n'
'{ethernet}\n'
'{ifconfig}\n'
'{iwconfig}'
.format(network=(Command('lspci | grep Network')
.run().stdout),
ethernet=(Command('lspci | grep Ethernet')
.run().stdout),
ifconfig=(Command("ifconfig -a | grep -A1 '^\w'")
.run().stdout),
iwconfig=(Command("iwconfig | grep -A1 '^\w'")
.run().stdout)))
logging.debug('Bluetooth Device:\n'
'{hciconfig}'
.format(hciconfig=(Command("hciconfig -a "
"| grep -A2 '^\w'")
.run().stdout)))
logging.debug('Video Card:\n'
'{lspci}'
.format(lspci=Command('lspci | grep VGA').run().stdout))
logging.debug('Touchpad and Keyboard:\n'
'{xinput}'
.format(xinput=Command(
'xinput list --name-only | sort').run().stdout))
logging.debug('Pulse Audio Sink:\n'
'{pactl_sink}'
.format(pactl_sink=(Command('pactl list | grep Sink')
.run().stdout)))
logging.debug('Pulse Audio Source:\n'
'{pactl_source}'
.format(pactl_source=(Command('pactl list | grep Source')
.run().stdout)))
# Check kernel logs using firmware test suite
command = Command('fwts -r stdout klog oops').run()
if command.process.returncode != 0:
# Don't abort the test loop,
# errors can be retrieved by pm_log_check
logging.error('Problem found in logs by fwts')
class MessageDialog(object):
"""
Simple wrapper aroung Gtk.MessageDialog
"""
def __init__(self, title, message, type=Gtk.MessageType.INFO):
self.title = title
self.message = message
self.type = type
def run(self):
dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.OK,
message_format=self.message,
type=self.type)
logging.info(self.message)
dialog.set_title(self.title)
dialog.run()
dialog.destroy()
class AutoLoginConfigurator(object):
"""
Enable/disable autologin configuration
to make sure that reboot test will work properly
"""
CONFIG_FILENAME = '/etc/lightdm/lightdm.conf'
TEMPLATE = """
[SeatDefaults]
greeter-session=unity-greeter
user-session=ubuntu
autologin-user={username}
autologin-user-timeout=0
"""
def __init__(self, user=None):
self.user = user
def enable(self):
"""
Make sure user will autologin in next reboot
"""
logging.debug('Enabling autologin for this user...')
if os.path.exists(self.CONFIG_FILENAME):
for backup_filename in self.generate_backup_filename():
if not os.path.exists(backup_filename):
shutil.copyfile(self.CONFIG_FILENAME, backup_filename)
shutil.copystat(self.CONFIG_FILENAME, backup_filename)
break
with open(self.CONFIG_FILENAME, 'w') as f:
f.write(self.TEMPLATE.format(username=self.user))
def disable(self):
"""
Remove latest configuration file
and use the same configuration that was in place
before running the test
"""
logging.debug('Restoring autologin configuration...')
backup_filename = None
for filename in self.generate_backup_filename():
if not os.path.exists(filename):
break
backup_filename = filename
if backup_filename:
shutil.copy(backup_filename, self.CONFIG_FILENAME)
os.remove(backup_filename)
else:
os.remove(self.CONFIG_FILENAME)
def generate_backup_filename(self):
backup_filename = self.CONFIG_FILENAME + '.bak'
yield backup_filename
index = 0
while True:
index += 1
backup_filename = (self.CONFIG_FILENAME
+ '.bak.{0}'.format(index))
yield backup_filename
class SudoersConfigurator(object):
"""
Enable/disable reboot test to be executed as root
to make sure that reboot test works properly
"""
MARK = '# Automatically added by pm.py'
SUDOERS = '/etc/sudoers'
def __init__(self, user=None):
self.user = user
def enable(self):
"""
Make sure that user will be allowed to execute reboot test as root
"""
logging.debug('Enabling user to execute test as root...')
command = ("sed -i -e '$a{mark}\\n"
"{user} ALL=NOPASSWD: /usr/bin/python3' "
"{filename}".format(mark=self.MARK,
user=self.user,
script=os.path.realpath(__file__),
filename=self.SUDOERS))
Command(command, verbose=False).run()
def disable(self):
"""
Revert sudoers configuration changes
"""
logging.debug('Restoring sudoers configuration...')
command = (("sed -i -e '/{mark}/,+1d' "
"{filename}")
.format(mark=self.MARK,
filename=self.SUDOERS))
Command(command, verbose=False).run()
class AutoStartFile(object):
"""
Generate autostart file contents and write it to proper location
"""
TEMPLATE = """
[Desktop Entry]
Name={pm_operation} test
Comment=Verify {pm_operation} works properly
Exec=sudo /usr/bin/python3 {script} -r {repetitions} -w {wakeup} --hardware-delay {hardware_delay} --pm-delay {pm_delay} --min-pm-time {min_pm_time} --max-pm-time {max_pm_time} --append --total {total} --start {start} --pm-timestamp {pm_timestamp} {silent} --log-level={log_level} --log-dir={log_dir} --suspends-before-reboot={suspend_cycles} {fwts} {pm_operation}
Type=Application
X-GNOME-Autostart-enabled=true
Hidden=false
"""
def __init__(self, args, user=None):
self.args = args
self.user = user
# Generate desktop filename
# based on environment variables
username = self.user
default_config_directory = os.path.expanduser('~{0}/.config'
.format(username))
config_directory = os.getenv('XDG_CONFIG_HOME',
default_config_directory)
autostart_directory = os.path.join(config_directory, 'autostart')
if not os.path.exists(autostart_directory):
os.makedirs(autostart_directory)
user_id = os.getenv('PKEXEC_UID') or os.getenv('SUDO_UID')
group_id = os.getenv('PKEXEC_UID') or os.getenv('SUDO_GID')
if user_id:
os.chown(config_directory, int(user_id), int(group_id))
os.chown(autostart_directory, int(user_id), int(group_id))
basename = '{0}.desktop'.format(os.path.basename(__file__))
self.desktop_filename = os.path.join(autostart_directory,
basename)
def write(self):
"""
Write autostart file to execute the script on startup
"""
logging.debug('Writing desktop file ({0!r})...'
.format(self.desktop_filename))
contents = (self.TEMPLATE
.format(script=os.path.realpath(__file__),
repetitions=self.args.repetitions - 1,
wakeup=self.args.wakeup,
hardware_delay=self.args.hardware_delay,
pm_delay=self.args.pm_delay,
min_pm_time=self.args.min_pm_time,
max_pm_time=self.args.max_pm_time,
total=self.args.total,
start=self.args.start,
pm_timestamp=int(time()),
silent='--silent' if self.args.silent else '',
log_level=self.args.log_level_str,
log_dir=self.args.log_dir,
fwts='--fwts' if self.args.fwts else '',
suspend_cycles=self.args.suspends_before_reboot,
pm_operation=self.args.pm_operation))
logging.debug(contents)
with open(self.desktop_filename, 'w') as f:
f.write(contents)
def remove(self):
"""
Remove autostart file to avoid executing the script on startup
"""
if os.path.exists(self.desktop_filename):
logging.debug('Removing desktop file ({0!r})...'
.format(self.desktop_filename))
os.remove(self.desktop_filename)
class LoggingConfiguration(object):
@classmethod
def set(cls, log_level, log_filename, append):
"""
Configure a rotating file logger
"""
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# Log to sys.stderr using log level passed through command line
if log_level != logging.NOTSET:
log_handler = logging.StreamHandler()
formatter = logging.Formatter('%(levelname)-8s %(message)s')
log_handler.setFormatter(formatter)
log_handler.setLevel(log_level)
logger.addHandler(log_handler)
# Log to rotating file using DEBUG log level
log_handler = logging.handlers.RotatingFileHandler(log_filename,
mode='a+',
backupCount=3)
formatter = logging.Formatter('%(asctime)s %(levelname)-8s '
'%(message)s')
log_handler.setFormatter(formatter)
log_handler.setLevel(logging.DEBUG)
logger.addHandler(log_handler)
if not append:
# Create a new log file on every new
# (i.e. not scheduled) invocation
log_handler.doRollover()
class MyArgumentParser(object):
"""
Command-line argument parser
"""
def __init__(self):
"""
Create parser object
"""
pm_operations = ('poweroff', 'reboot')
description = 'Run power management operation as many times as needed'
epilog = ('Unknown arguments will be passed '
'to the underlying command: poweroff or reboot.')
parser = ArgumentParser(description=description, epilog=epilog)
parser.add_argument('-r', '--repetitions', type=int, default=1,
help=('Number of times that the power management '
'operation has to be repeated '
'(%(default)s by default)'))
parser.add_argument('-w', '--wakeup', type=int, default=60,
help=('Timeout in seconds for the wakeup alarm '
'(%(default)s by default). '
"Note: wakeup alarm won't be scheduled "
'for reboot.'))
parser.add_argument('--min-pm-time', dest='min_pm_time',
type=int, default=0,
help=('Minimum time in seconds that '
'it should take the power management '
'operation each cycle (0 for reboot and '
'wakeup time minus two seconds '
'for the other power management operations '
'by default)'))
parser.add_argument('--max-pm-time', dest='max_pm_time',
type=int, default=300,
help=('Maximum time in seconds '
'that it should take '
'the power management operation each cycle '
'(%(default)s by default)'))
parser.add_argument('--pm-delay', dest='pm_delay',
type=int, default=5,
help=('Delay in seconds '
'after hardware information '
'has been gathered and before executing '
'the power management operation '
'(%(default)s by default)'))
parser.add_argument('--hardware-delay', dest='hardware_delay',
type=int, default=30,
help=('Delay in seconds before gathering hardware '
'information (%(default)s by default)'))
parser.add_argument('--silent', action='store_true',
help=("Don't display any dialog "
'when test is complete '
'to let the script be used '
'in automated tests'))
log_levels = ['notset', 'debug', 'info',
'warning', 'error', 'critical']
parser.add_argument('--log-level', dest='log_level_str',
default='info', choices=log_levels,
help=('Log level. '
'One of {0} or {1} (%(default)s by default)'
.format(', '.join(log_levels[:-1]),
log_levels[-1])))
parser.add_argument('--log-dir', dest='log_dir', default='/var/log',
help=('Path to the directory to store log files'))
parser.add_argument('pm_operation', choices=pm_operations,
help=('Power management operation to be performed '
'(one of {0} or {1!r})'
.format(', '.join(map(repr,
pm_operations[:-1])),
pm_operations[-1])))
# Test timestamps
parser.add_argument('--start', type=int, default=0, help=SUPPRESS)
parser.add_argument('--pm-timestamp', dest='pm_timestamp',
type=int, default=0, help=SUPPRESS)
# Append to log on subsequent startups
parser.add_argument('--append', action='store_true',
default=False, help=SUPPRESS)
# Total number of iterations initially passed through the command line
parser.add_argument('--total', type=int, default=0, help=SUPPRESS)
# suspend cycles before reboot
parser.add_argument('--suspends-before-reboot', type=int, default=0,
help=('How many cycles of suspend/resume to run'
'before each reboot or poweroff'))
# use fwts for suspend tests
parser.add_argument('--fwts', action='store_true', help=('Use fwts '
'when doing the suspend tests'))
self.parser = parser
def parse(self):
"""
Parse command-line arguments
"""
args, extra_args = self.parser.parse_known_args()
args.log_level = getattr(logging, args.log_level_str.upper())
# Total number of repetitions
# is the number of repetitions passed through the command line
# the first time the script is executed
if not args.total:
args.total = args.repetitions
# Test start time automatically set on first iteration
if not args.start:
args.start = int(time())
# Wakeup time set to 0 for 'reboot'
# since wakeup alarm won't be scheduled
if args.pm_operation == 'reboot':
args.wakeup = 0
args.min_pm_time = 0
# Minimum time for each power management operation
# is set to the wakeup time
if not args.min_pm_time:
min_pm_time = args.wakeup - 2
if min_pm_time < 0:
min_pm_time = 0
args.min_pm_time = min_pm_time
# Log filename shows clearly the type of test (pm_operation)
# and the times it was repeated (repetitions)
args.log_filename = os.path.join(args.log_dir,
('{0}.{1}.{2}.log'
.format(os.path.basename(__file__),
args.pm_operation,
args.total)))
return args, extra_args
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/xen_test 0000775 0001750 0001750 00000004141 12646152433 022423 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
## Xen Testing
## Script to make and fire off some pre-made VMs to test the hypervisor
## under a bit of simulated load
##
## USAGE: xentest.sh /path/to/ORIGINAL_IMAGE /path/to/ORIGINAL_CONFIG
##
## this is a kludge and a dirty, dirty hack and shoud die an ignomious
## death soon. A more elegant solution would be to modify the script
## /usr/share/checkbox/scripts/virtualization and add the missing Xen
## functionality. But this will do as a first pass.
ORIGINAL_VM=$1
ORIGINAL_VM_TEMPLATE=$2
VIRSH_CMD='virsh -c xen:///'
CLONE_CMD='virt-clone'
VM_NAME_BASE='xentest-vm'
# First, figure out how many CPUs we have:
#CPU_CORES=`xm dmesg | grep -c "(XEN) Processor #"`
CPU_CORES=1
# Verify our image and config file are present
if [ ! -e $ORIGINAL_VM ]; then
echo "Xen VM Image not found!" >&2
exit 1
fi
if [ ! -e $ORIGINAL_VM_TEMPLATE ]; then
echo "Xen VM Config File not found!" >&2
exit 1
fi
#Clone those suckers enough that we have 2 VMs per core and LAUNCH!
VM_TOTAL=$((CPU_CORES*2))
#Set up an assoticative array (this would translate much better into
#a simple python list later on, hint hint)
declare -A VM_NAMES
echo "Starting $VM_TOTAL VM clones" >&2
for vm in `seq 1 $VM_TOTAL`; do
VM_NAME="$VM_NAME_BASE$vm"
VM_NAMES[$vm]=$VM_NAME
echo "Cloning vm $vm" >&2
$CLONE_CMD --original-xml=$ORIGINAL_VM_TEMPLATE -n $VM_NAME -f /vms/$VM_NAME.img --force >&2
echo "Starting vm $vm" >&2
$VIRSH_CMD start $VM_NAME
done
#Lets wait a few minutes to let them do some work
echo "Sleeping for 5 miunutes to let VMs boot and start working" >&2
sleep 5m
echo "" >&2
#Now verify the VMs are still running
fail=false
echo "Checking domU state..." >&2
for vm in `seq 1 $VM_TOTAL`; do
state=`$VIRSH_CMD domstate ${VM_NAMES[$vm]}`
echo "${VM_NAMES[$vm]}: $state" >&2
if [ "$state" != "running" ]; then
fail=true
echo "VM $vm is not in running state!" >&2
fi
done
if $fail; then
echo "One or more guests is not in the running state after 5 minutes." >&2
echo "Test Fails" >&2
exit 1
else
echo "All guests seem to be running correctly"
fi
exit 0
plainbox-provider-checkbox-0.25/bin/udisks2_monitor 0000775 0001750 0001750 00000014321 12646152433 023726 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# Copyright 2012 Canonical Ltd.
# Written by:
# Zygmunt Krynicki
#
# This program 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
"""
Script that observes changes to various devices, as published by
UDisks2. Note: this script has no UDisks (one) equivalent.
"""
import errno
import logging
import sys
from checkbox_support.dbus import connect_to_system_bus, drop_dbus_type
from checkbox_support.dbus.udisks2 import UDisks2Observer
from dbus.exceptions import DBusException
def _print_interfaces_and_properties(interfaces_and_properties):
"""
Print a collection of interfaces and properties exported by some object
The argument is the value of the dictionary _values_, as returned from
GetManagedObjects() for example. See this for details:
http://dbus.freedesktop.org/doc/dbus-specification.html#
standard-interfaces-objectmanager
"""
for interface_name, properties in interfaces_and_properties.items():
print(" - Interface {}".format(interface_name))
for prop_name, prop_value in properties.items():
prop_value = drop_dbus_type(prop_value)
print(" * Property {}: {}".format(prop_name, prop_value))
def main():
# Connect to the system bus, we also get the event
# loop as we need it to start listening for signals.
system_bus, loop = connect_to_system_bus()
# Create an instance of the observer that we'll need for the model
observer = UDisks2Observer()
# Define all our callbacks in advance, there are three callbacks that we
# need, for interface insertion/removal (which roughly corresponds to
# objects/devices coming and going) and one extra signal that is only fired
# once, when we get the initial list of objects.
# Let's print everything we know about initially for the users to see
def print_initial_objects(managed_objects):
print("UDisks2 knows about the following objects:")
for object_path, interfaces_and_properties in managed_objects.items():
print(" * {}".format(object_path))
_print_interfaces_and_properties(interfaces_and_properties)
sys.stdout.flush()
observer.on_initial_objects.connect(print_initial_objects)
# Setup a callback for the InterfacesAdded signal. This way we will get
# notified of any interface changes in this collection. In practice this
# means that all objects that are added/removed will be advertised through
# this mechanism
def print_interfaces_added(object_path, interfaces_and_properties):
print("The object:")
print(" {}".format(object_path))
print("has gained the following interfaces and properties:")
_print_interfaces_and_properties(interfaces_and_properties)
sys.stdout.flush()
observer.on_interfaces_added.connect(print_interfaces_added)
# Setup a callback on PropertiesChanged signal. This way we will get
# notified on any changes to the values of properties exported by various
# objects on the bus.
def print_properties_changed(object_path, interface_name,
changed_properties, invalidated_properties):
print("The object")
print(" {}".format(object_path))
print("has changed the following properties")
print(" - Interface {}".format(interface_name))
for prop_name, prop_value in changed_properties.items():
prop_value = drop_dbus_type(prop_value)
print(" * Property {}: {}".format(prop_name, prop_value))
for prop_name in invalidated_properties:
print(" * Property {} (invalidated)".format(prop_name))
observer.on_properties_changed.connect(print_properties_changed)
# Again, a similar callback for interfaces that go away. It's not spelled
# out explicitly but it seems that objects with no interfaces left are
# simply gone. We'll treat them as such
def print_interfaces_removed(object_path, interfaces):
print("The object:")
print(" {}".format(object_path))
print("has lost the following interfaces:")
for interface in interfaces:
print(" * {}".format(interface))
sys.stdout.flush()
observer.on_interfaces_removed.connect(print_interfaces_removed)
# Now that all signal handlers are set, connect the observer to the system
# bus
try:
logging.debug("Connecting UDisks2 observer to DBus")
observer.connect_to_bus(system_bus)
except DBusException as exc:
# Manage the missing service error if needed to give sensible error
# message on precise where UDisks2 is not available
if exc.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
print("You need to have udisks2 installed to run this program")
print("It is only applicable to Ubuntu 12.10, or later")
raise SystemExit(1)
else:
raise # main_shield() will catch this one
# Now start the event loop and just display any device changes
print("=" * 80)
print("Waiting for device changes (press ctlr+c to exit)")
print("=" * 80)
logging.debug("Entering event loop")
sys.stdout.flush() # Explicitly flush to allow tee users to see things
try:
loop.run()
except KeyboardInterrupt:
loop.quit()
print("Exiting")
def main_shield():
"""
Helper for real main that manages exceptions we don't recover from
"""
try:
main()
except DBusException as exc:
logging.exception("Caught fatal DBus exception, aborting")
except IOError as exc:
# Ignore pipe errors as they are harmless
if exc.errno != errno.EPIPE:
raise
if __name__ == "__main__":
main_shield()
plainbox-provider-checkbox-0.25/bin/lamp_test 0000775 0001750 0001750 00000001263 12646152433 022564 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#
# Test LAMP by checking Apache, MySQL, and PHP
# Requires: apache2, php5-mysql, libapache2-mod-php5, mysql-server
#
# Check Apache is running; requires network connection so verify that
check=`ping -c 2 www.ubuntu.com |grep "2 received"`
if [ -n "$check" ]; then
run1=`w3m http://127.0.0.1/ | grep "404"`
if [ -n "$run1" ]; then
echo "FAIL: apache is not running."
exit 1
fi
fi
# Check if MySQL server is running
run2=`netstat -tap | grep mysql`
if [ -z "$run2" ]; then
echo "FAIL: mysql is not running."
exit 1
fi
# Check PHP
run3=`php -r 'phpinfo();' | grep 'PHP License'`
if [ -z "$run3" ]; then
echo "FAIL: php is not running."
exit 1
fi
exit 0
plainbox-provider-checkbox-0.25/bin/sleep_test_log_check 0000775 0001750 0001750 00000017350 12646152433 024745 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# This file is part of Checkbox.
#
# Copyright 2014 Canonical Ltd.
#
# Authors
# Jeff Lane
# Daniel Manrique
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see .
'''
This script is used to parse the log generated by fwts and check it for certain
errors detected during testing. It expects that this is a log file created by
fwts at runtime using the -l option.
It's written now specifically for checking ater the fwts s3 and s4 tests but
can be adapted to look for other tests, or all tests.
'''
import sys
import collections
import re
from argparse import ArgumentParser
import logging
# Definitions of when a level starts, how a failure looks,
# and when a level ends.
start_level_re = r'^(?P.+) failures: (?PNONE|\d+)$'
start_level_re = re.compile(start_level_re)
failure_re = re.compile(r'^ (?P(s3|s4)): (?P.+)$')
end_level_re = re.compile(r"$^")
def parse_summary(summary, results):
"""
Parses an entire "Test Failure Summary" section, which contains a short
summary of failures observed per level. Returns nothing, but adds the
results to the passed results dictionary.
:param summary:
A list of lines comprised in this summary section
:param results:
The results dictionary into which to put the end result. Should be a
dict with keys for each level, the values are dicts with keys for each
test (s3, s4) which in turn contain a list of all the failures observed
for that level and test.
"""
current_level = None
current_acum = []
for logline in summary:
level_matches = start_level_re.search(logline)
if level_matches:
logging.debug("Found a level: %s", level_matches.group('level'))
current_level = level_matches.group('level')
elif end_level_re.search(logline) and current_level:
if current_level:
logging.debug("Current level (%s) has %s",
current_level, current_acum)
# By passing results[current_level] a key in results will be
# created for every level we see, regardless of whether it
# reports failures or not. This is OK because we can later
# check results' keys to ensure we saw at least one level; if
# results has no keys, it could mean a malformed fwts log file.
parse_level(current_acum, results[current_level])
else:
logging.debug("Discarding junk")
current_acum = []
current_level = None
else:
current_acum.append(logline)
def parse_level(level_lines, level_results):
"""
Parses the level's lines, appending the failures to the level's results.
level_results is a dictionary with a key per test type (s3, s4, and so on).
Returns nothing, but adds the results to the passed results dictionary for
this level.
:param level_lines:
A list of lines comprised in this level's list of failures.
: param level_results:
A dictionary containing this level's results. Should be a dict with
keys for each test, to which the failures for the level will be
appended.
"""
for failureline in level_lines:
failure_matches = failure_re.search(failureline)
if failure_matches:
test = failure_matches.group('test')
details = failure_matches.group('details')
logging.debug("fail %s was %s", test, details)
level_results[test].append(details)
def main():
parser = ArgumentParser()
parser.add_argument('-d', '--debug',
action='store_const',
const=logging.DEBUG,
default=logging.INFO,
help="Show debugging information.")
parser.add_argument('-v', '--verbose',
action='store_true',
default=False,
help="Display each error discovered. May provide \
very long output. Also, this option will only \
provide a list of UNIQUE errors encountered in \
the log file. It will not display duplicates. \
Default is [%(default)s]")
parser.add_argument('test',
action='store',
choices=['s3', 's4'],
help='The test to check (s3 or s4)')
parser.add_argument('logfile',
action='store',
help='The log file to parse')
args = parser.parse_args()
logging.basicConfig(level=args.debug)
#Create a generator and get our lines
log = (line.rstrip() for line in open(args.logfile, 'rt', encoding="UTF-8"))
# End result will be a dictionary with a key per level, value is another
# dictionary with a key per test (s3, s4, ...) and a list of all failures
# for each test. Duplicates are possible, because we should also indicate
# the number of instances for each failure.
results = collections.defaultdict(lambda: collections.defaultdict(list))
sum_acum = []
summaries_found = 0
# Start parsing the fwts log. Gather each "Test Failure Summary" section
# and when it's complete, pass it to the parse_summary function to extract
# levels and tests.
for logline in log:
if "Test Failure Summary" in logline:
parse_summary(sum_acum, results)
summaries_found += 1
sum_acum = []
else:
sum_acum.append(logline)
# We reached the end, so add the last accumulated summary
if sum_acum:
parse_summary(sum_acum, results)
# Report what I found
for level in sorted(results.keys()):
if results[level]: # Yes, we can have an empty level. We may have
# seen the levelheader but had it report no
# failures.
print("{} failures:".format(level))
for test in results[level].keys():
print(" {}: {} failures".format(test,
len(results[level][test])))
if args.verbose:
print('='*40)
counts = collections.Counter(results[level][test])
for failure in counts:
print(" {} (x {})".format(failure, counts[failure]))
# Decide on the outcome based on the collected information
if not summaries_found:
logging.error("No fwts test summaries found, "
"possible malformed fwts log file")
return_code = 2
elif not results.keys(): # If it has no keys, means we didn't see any
# FWTS levels
logging.error("None of the summaries contained failure levels, "
"possible malformed fwts log file")
return_code = 2
elif any(results.values()): # If any of the results' levels has errors
return_code = 1
else:
print("No errors detected")
return_code = 0
return return_code
if __name__ == '__main__':
sys.exit(main())
plainbox-provider-checkbox-0.25/bin/broadband_info 0000775 0001750 0001750 00000000230 12646152433 023514 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
for i in $(mmcli --simple-status -L | \
awk '/freedesktop\/ModemManager1\/Modem/ {print $1;}'); do
mmcli -m $i
done
plainbox-provider-checkbox-0.25/bin/recovery_info 0000775 0001750 0001750 00000030660 12646152433 023450 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
# Copyright 2015 Canonical Ltd.
# Written by:
# Shawn Wang
#
# This program 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
"""Show the recovery partition information for the preinstalled OS."""
import os
import re
import subprocess
import sys
import tempfile
import unittest
import xml.dom.minidom as minidom
from guacamole import Command
try:
from unittest import mock
except ImportError:
from plainbox.vendor import mock
RECOVERY_PACKAGES = ["dell-recovery", "ubuntu-recovery"]
def get_recovery_package():
"""
Test with RECOVERY_PACKAGES.
to check recovery application is installed or not
:return:
string of package_version or None
"""
for pkg in RECOVERY_PACKAGES:
output = subprocess.check_output(["apt-cache", "policy", pkg],
universal_newlines=True)
for line in output.split("\n"):
if line.startswith(" Installed:"):
ver = line.split(": ")[1]
return "{}_{}".format(pkg, ver.strip())
return None
RECOVERY_LABELS = {"HP_TOOLS": "HP",
"PQSERVICE": "UBUNTU",
"BACKUP": "TEST",
"INSTALL": "DELL",
"OS": "DELL",
"RECOVERY": "DELL"}
_escape_pattern = re.compile(r'\\x([0-9a-fA-F][0-9a-fA-F])')
def lsblk_unescape(label):
"""Un-escape text escaping done by lsblk(8)."""
return _escape_pattern.sub(
lambda match: chr(int(match.group(1), 16)), label)
def get_recovery_partition():
"""
Get the type and location of the recovery partition.
:return:
(recovery_type, recovery_partition) or None
Use lsblk(8) to inspect available block devices looking
for a partition with FAT or NTFS and a well-known label.
"""
cmd = ['lsblk', '-o', 'TYPE,FSTYPE,NAME,LABEL', '--raw']
for line in subprocess.check_output(cmd).splitlines()[1:]:
type, fstype, name, label = line.split(b' ', 3)
# Skip everything but partitions
if type != b'part':
continue
# Skip everything but FAT and NTFS
if fstype != b'vfat' and fstype != b'ntfs':
continue
label = lsblk_unescape(label.decode('utf-8'))
recovery_type = RECOVERY_LABELS.get(label)
# Skip unknown labels
if recovery_type is None:
continue
recovery_partition = '/dev/{}'.format(name.decode('utf-8'))
return (recovery_type, recovery_partition)
class FunctionTests(unittest.TestCase):
"""Tests for several functions."""
@mock.patch('subprocess.check_output')
def test_get_recovery_package(self, mock_subprocess_check_output):
"""Smoke test for get_recovery_package()."""
mock_subprocess_check_output.return_value = """\
dell-recovery:
Installed: 1.11
Candidate: 1.11
Version table:
1.11
500 https://archive/cesg-mirror/ test/public amd64 Packages
"""
self.assertEqual(get_recovery_package(),
"dell-recovery_1.11")
@mock.patch('subprocess.check_output')
def test_get_recovery_partition(self, mock_subprocess_check_output):
"""Smoke test for get_recovery_partition()."""
mock_subprocess_check_output.return_value = (
b'TYPE FSTYPE NAME LABEL\n'
b'disk linux_raid_member sda fx:2x250GB\n'
b'raid1 bcache md127 \n'
b'disk ext4 bcache0 Ultra\n'
b'disk linux_raid_member sdb fx:2x250GB\n'
b'raid1 bcache md127 \n'
b'disk ext4 bcache0 Ultra\n'
b'disk sdc \n'
b'part btrfs sdc1 vol1\n'
b'disk sdd \n'
b'part ntfs sdd1 Windows\x208.1\n'
b'part sdd2 \n'
b'part ext4 sdd5 Utopic\n'
b'part swap sdd6 \n'
b'disk bcache sde \n'
b'disk ext4 bcache0 Ultra\n'
b'disk sdf \n'
b'part ntfs sda3 RECOVERY\n')
self.assertEqual(get_recovery_partition(), ("DELL", "/dev/sda3"))
def test_lsblk_unescape(self):
"""Smoke tests for lsblk_unescape()."""
self.assertEqual(lsblk_unescape('Windows\\x208.1'), 'Windows 8.1')
self.assertEqual(lsblk_unescape('Windows XP'), 'Windows XP')
class MountedPartition(object):
"""
Mount Manager to mount partition on tempdir.
e.g.
with MountedPartition("/dev/sda1") as tmp:
print("This is the mount point: {}".format(tmp))
do_stuff()
"""
def __init__(self, part):
"""
Prepare the mntdir point.
:param part: string of the partition device file, like /dev/sda2
"""
self.part = part
self.mntdir = tempfile.mkdtemp()
def __enter__(self):
"""
__enter__ method for python's with statement.
Mount the partition device to the mntdir.
"""
cmd = ["mount", self.part, self.mntdir]
subprocess.check_output(cmd, universal_newlines=True)
return self.mntdir
def __exit__(self, type, value, traceback):
"""
__exit__ method for python's with statement.
Unmount and remove the mntdir.
"""
subprocess.check_output(["umount", self.mntdir],
universal_newlines=True)
os.rmdir(self.mntdir)
class MountedPartitionTests(unittest.TestCase):
"""Unittest of MountedPartition."""
@mock.patch('subprocess.check_output')
def test_with_of_MountedPartition(self, mock_subprocess_check_output):
"""Test mount point."""
test_dir = ""
with MountedPartition("/dev/test") as tmp:
test_dir = tmp
self.assertTrue(os.path.exists(test_dir))
mock_subprocess_check_output.assert_has_calls(
[mock.call(['mount', '/dev/test', test_dir],
universal_newlines=True)])
self.assertFalse(os.path.exists(test_dir))
mock_subprocess_check_output.assert_has_calls(
[mock.call(['umount', test_dir],
universal_newlines=True)])
class RecoveryVersion(Command):
"""
print the version of recovery image.
@EPILOG@
This commands prints information such as:
image_version: xxx
bto_version: REV_xxx.iso (dell only)
"""
def invoked(self, ctx):
"""
Guacamole method called when the command is invoked.
/etc/buildstamp is a image information file,
it created by the oem image builder.
oilpalm Fri, 20 Jun 2014 04:02:07 +0000
somerville-trusty-amd64-20140620-0
If /etc/buildstamp exist, print out the second line (image iso name).
For Dell-recovery partition, /etc/buildstamp shows base image info.
If recovery_partition/bto.xml,
print out the bto_version (read from xml file).
"""
if os.path.isfile("/etc/buildstamp"):
with open('/etc/buildstamp', 'rt', encoding='UTF-8') as stream:
data = stream.readlines()
print("image_version: {}".format(data[1].strip()))
with MountedPartition(ctx.recovery_partition) as mntdir:
fname = "{}/bto.xml".format(mntdir)
if os.path.isfile(fname):
o = minidom.parse("{}/bto.xml".format(mntdir))
bto_version = o.getElementsByTagName("iso")[0].firstChild.data
print("bto_version: {}".format(bto_version))
class RecoveryFile(Command):
"""
display a single file from the recovery partition
This command can be used to ``cat`` any file from the recovery partition
"""
def register_arguments(self, parser):
"""
Guacamole method used by the argparse ingredient.
:param parser:
Argument parser (from :mod:`argparse`) specific to this command.
"""
parser.add_argument('file', help='name of the file to display')
def invoked(self, ctx):
"""
Guacamole method used by the command ingredient.
:param ctx:
The guacamole context object. Context provides access to all
features of guacamole. The argparse ingredient adds the ``args``
attribute to it. That attribute contains the result of parsing
command line arguments.
:returns:
The return code of the command. Guacamole translates ``None`` to a
successful exit status (return code zero).
"""
with MountedPartition(ctx.recovery_partition) as mnt:
return subprocess.call([
'cat', '--', os.path.join(mnt, ctx.args.file)])
class RecoveryCheckType(Command):
"""
test if the recovery partition is of the given type.
This command can be used for scripted tests, to see if the recovery
partition on the current system is of a concrete type or not (e.g.
DELL-specific)
@EPILOG@
The exit code is 0 if the recovery partition type matches and 1 otherwise.
"""
def register_arguments(self, parser):
"""
Guacamole method used by the argparse ingredient.
:param parser:
Argument parser (from :mod:`argparse`) specific to this command.
"""
parser.add_argument(
'type', help="expected type of the recovery partition")
def invoked(self, ctx):
"""
Guacamole method used by the command ingredient.
:param ctx:
The guacamole context object. Context provides access to all
features of guacamole. The argparse ingredient adds the ``args``
attribute to it. That attribute contains the result of parsing
command line arguments.
:returns:
The return code of the command. Guacamole translates ``None`` to a
successful exit status (return code zero).
"""
if ctx.recovery_type != ctx.args.type:
return 1
class RecoveryInfo(Command):
"""
Inspect the recovery partition.
This command can be used to inspect the recovery partition. It has several
sub-commands that do various tasks. If the system has no recovery
partition, the command exits with the error code 1.
"""
sub_commands = (
('version', RecoveryVersion),
('file', RecoveryFile),
('checktype', RecoveryCheckType),
)
def invoked(self, ctx):
"""
Guacamole method used by the command ingredient.
:param ctx:
The guacamole context object. Context provides access to all
features of guacamole. The argparse ingredient adds the ``args``
attribute to it. That attribute contains the result of parsing
command line arguments.
:returns:
The return code of the command. Guacamole translates ``None`` to a
successful exit status (return code zero).
"""
partition = get_recovery_partition()
if partition is None:
print("Recovery partition not found", file=sys.stderr)
return 1
(recovery_type, recovery_partition) = partition
ctx.recovery_partition = recovery_partition
ctx.recovery_type = recovery_type
class RecoveryInfoTests(unittest.TestCase):
"""Tests for RecoveryInfo."""
@mock.patch('__main__.get_recovery_package')
@mock.patch('__main__.get_recovery_partition')
def test_smoke(self, mock_get_recovery_partition,
mock_get_recovery_package):
"""Smoke tests for running recovery_info."""
mock_get_recovery_partition.return_value = ("DELL", "/dev/sda3")
mock_get_recovery_package.return_value = "dell-recovery_1.11"
self.assertEqual(RecoveryInfo().main(argv=[], exit=False), 0)
self.assertEqual(
RecoveryInfo().main(argv=["checktype", "HP"], exit=False), 1)
self.assertEqual(
RecoveryInfo().main(argv=["checktype", "DELL"], exit=False), 0)
if __name__ == '__main__':
if '--test' in sys.argv:
sys.argv.remove('--test')
unittest.main()
else:
RecoveryInfo().main()
plainbox-provider-checkbox-0.25/bin/disk_stats_test 0000775 0001750 0001750 00000003657 12646152433 024014 0 ustar sylvain sylvain 0000000 0000000 #!/bin/bash
#Simple script to gather some data about a disk to verify it's seen by the OS
#and is properly represented. Defaults to sda if not passed a disk at run time
DISK="sda"
check_return_code() {
if [ "${1}" -ne "0" ]; then
echo "ERROR: retval ${1} : ${2}" >&2
exit ${1}
fi
}
if [[ "$1" != '' ]]; then
DISK="$1"
fi
#Get some baseline stats for use later
echo "Getting baseline stats"
PROC_STAT_BEGIN=`grep -m 1 $DISK /proc/diskstats`
SYS_STAT_BEGIN=`cat /sys/block/$DISK/stat`
#Generate some disk activity using hdparm -t
echo "Generating some disk activity"
hdparm -t "/dev/$DISK" 2&> /dev/null
#Sleep 5 to let the stats files catch up
sleep 5
#Check /proc/partitions, exit with fail if disk isn't found
echo "Checking /proc/partitions"
grep -q $DISK /proc/partitions
check_return_code $? "Disk $DISK not found in /proc/partitions"
#Next, check /proc/diskstats
echo "Checking /proc/diskstats"
grep -q -m 1 $DISK /proc/diskstats
check_return_code $? "Disk $DISK not found in /proc/diskstats"
#Verify the disk shows up in /sys/block/
echo "Checking /sys/block"
ls /sys/block | grep -q $DISK
check_return_code $? "Disk $DISK not found in /sys/block"
#Verify there are stats in /sys/block/$DISK/stat
echo "Checking /sys/block/$DISK/stat"
[[ -s "/sys/block/$DISK/stat" ]]
check_return_code $? "stat is either empty or nonexistant in /sys/block/$DISK/"
#Sleep 5 to let the stats files catch up
sleep 5
#Make sure the stats have changed:
echo "Getting ending stats"
PROC_STAT_END=`grep -m 1 $DISK /proc/diskstats`
SYS_STAT_END=`cat /sys/block/$DISK/stat`
echo "Checking /proc/diskstats for changes"
[[ "$PROC_STAT_BEGIN" != "$PROC_STAT_END" ]]
check_return_code $? "Stats in /proc/diskstats did not change"
echo "Checking /sys/block/$DISK/stat for changes"
[[ "$SYS_STAT_BEGIN" != "$SYS_STAT_END" ]]
check_return_code $? "Stats in /sys/block/$DISK/stat did not change"
echo "PASS: Finished testing stats for $DISK"
exit 0
plainbox-provider-checkbox-0.25/bin/accelerometer_test 0000775 0001750 0001750 00000027455 12646152433 024460 0 ustar sylvain sylvain 0000000 0000000 #!/usr/bin/env python3
'''
script to test accerometer functionality
Copyright (C) 2012 Canonical Ltd.
Authors
Jeff Marcom
This program 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
The purpose of this script is to simply interact with an onboard
accelerometer, and check to be sure that the x, y, z axis respond
to physical movement of hardware.
'''
from argparse import ArgumentParser
from gi.repository import Gdk, GLib, Gtk
import logging
import os
import re
import sys
import threading
import time
from subprocess import Popen, PIPE, check_output, STDOUT, CalledProcessError
from checkbox_support.parsers.modinfo import ModinfoParser
handler = logging.StreamHandler()
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
class AccelerometerUI(Gtk.Window):
"""Builds UI Framework for axis threshold tests using Gtk"""
def __init__(self):
Gtk.Window.__init__(self, title="Accelerometer Test")
self.set_default_size(450, 100)
self.set_type_hint(Gdk.WindowType.TOPLEVEL)
self.enabled = False
# Create UI Grid
w_table = Gtk.Grid()
self.add(w_table)
# Create axis buttons
self.up_icon = Gtk.Image(stock=Gtk.STOCK_GO_UP)
self.up_icon.set_padding(10, 30)
self.down_icon = Gtk.Image(stock=Gtk.STOCK_GO_DOWN)
self.down_icon.set_padding(10, 30)
self.left_icon = Gtk.Image(stock=Gtk.STOCK_GO_BACK)
self.right_icon = Gtk.Image(stock=Gtk.STOCK_GO_FORWARD)
# Set debug
self.debug_label = Gtk.Label("Debug")
# Set Grid layout for UI
message = "Please tilt your hardware in the positions shown below:"
w_table.attach(Gtk.Label(message), 0, 0, 4, 1)
w_table.attach(self.up_icon, 2, 2, 1, 1)
w_table.attach_next_to(self.debug_label, self.up_icon,
Gtk.PositionType.BOTTOM, 1, 1)
w_table.attach_next_to(self.down_icon, self.debug_label,
Gtk.PositionType.BOTTOM, 1, 1)
w_table.attach_next_to(self.left_icon, self.debug_label,
Gtk.PositionType.LEFT, 1, 1)
w_table.attach_next_to(self.right_icon, self.debug_label,
Gtk.PositionType.RIGHT, 1, 1)
def update_axis_icon(self, direction):
"""Change desired directional icon to checkmark"""
exec('self.%s_icon.set_from_stock' % (direction) \
+ '(Gtk.STOCK_YES, size=Gtk.IconSize.BUTTON)')
def update_debug_label(self, text):
"""Update axis information in center of UI"""
self.debug_label.set_text(text)
def destroy(self):
Gtk.main_quit()
def enable(self):
self.enabled = True
self.connect("delete-event", Gtk.main_quit)
self.show_all()
# Enable GLib/Gdk threading so the UI won't lock main
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
class PermissionException(RuntimeError):
def __init__(self, error):
message = "Please re-run with root permissions: %s" % error.strip()
super(PermissionException, self).__init__(message)
class AxisData(threading.Thread):
"""Acquire information from kernel regarding the state of the
accelerometer axis positions. Gathered data will be compared to
a preset threshold reading. The default threshold (either - or + )
for any direction is 600. Return values for thread are SUCCESS:0
FAILURE:1. FAILURE is likely to exists when thread is unable to
obtain a valid reading from the hardware."""
def __init__(self, device_path, ui_control=None):
threading.Thread.__init__(self)
self.ui = ui_control
self.device_path = device_path.strip("/")
self.tilt_threshold = 600
self.x_test_pool = ["up", "down"]
self.y_test_pool = ["left", "right"]
if self.ui == None:
self.ui.enabled = False
def grab_current_readings(self):
"""Search device path and return axis tuple"""
time.sleep(0.5) # Sleep to accomodate slower processors
data_file = os.path.join("/sys", self.device_path,
"device", "position")
# Try and retrieve positional data from kernel
try:
position_tuple = open(data_file)
except (OSError, IOError):
logging.error("Failed to open: %s" % data_file)
return False
# Split data for x, y, z as it's easier to manage threshold tests.
axis_set = position_tuple.read().strip("\n()")
return axis_set.split(",")
def parse_reading(self, value, mapping):
"""Check for positive or negative threshold match"""
if abs(value) >= abs(self.tilt_threshold):
# And return test pool array position based on integer
if value < 0:
return 2
return 1
def direction_poll(self, x_axis, y_axis):
"""Poll for threshold being met per x, and y axis"""
direction_map = {"X": x_axis, "Y": y_axis}
for mapping, data in direction_map.items():
reading = self.parse_reading(int(data), mapping)
if type(reading) == int:
return reading, mapping
# Return nothing if threshold is not met
return False, None
def run(self):
rem_tests = self.y_test_pool + self.x_test_pool
while len(rem_tests) > 0:
axis_data_bundle = self.grab_current_readings()
if type(axis_data_bundle) != list:
logging.error("Failed to grab appropriate readings")
return 1
# Parse for current positional values
# Hdaps will only report X, and Y positional data
x_data = int(axis_data_bundle[0])
y_data = int(axis_data_bundle[1])
if len(axis_data_bundle) > 2:
z_data = int(axis_data_bundle[2])
else:
z_data = 0
debug_info = "X: %s Y: %s Z: %s" % (x_data, y_data, z_data)
if self.ui.enabled:
# Update positional values in UI
self.ui.update_debug_label(debug_info)
position, axis = self.direction_poll(x_data, y_data)
if position:
# Check axis set and delete test from pool
if axis == "X":
pool = self.x_test_pool
else:
pool = self.y_test_pool
if len(pool) >= position:
direction = pool[position - 1]
if direction in rem_tests:
# Remove direction from test pool
del rem_tests[rem_tests.index(direction)]
self.ui.update_axis_icon(direction)
else:
# Accept readings as successful test result
logging.debug("Latest Readings: %s" % debug_info)
break
if self.ui.enabled:
self.ui.destroy()
return 0
def insert_supported_module(oem_module):
"""Try and insert supported module to see if we get any init errors"""
try:
stream = check_output(['modinfo', oem_module], stderr=STDOUT,
universal_newlines=True)
except CalledProcessError as err:
print("Error accessing modinfo for %s: " % oem_module, file=sys.stderr)
print(err.output, file=sys.stderr)
return err.returncode
parser = ModinfoParser(stream)
module = os.path.basename(parser.get_field('filename'))
insmod_output = Popen(['insmod %s' % module], stderr=PIPE,
shell=True, universal_newlines=True)
error = insmod_output.stderr.read()
if "Permission denied" in error:
raise PermissionException(error)
return insmod_output.returncode
def check_module_status():
"""Looks to see if it can determine the hardware manufacturer
and report corresponding accelerometer driver status"""
oem_driver_pool = {"hewlett-packard": "hp_accel",
"toshiba": "hp_accel",
"ibm": "hdaps", "lenovo": "hdaps"}
oem_module = None
dmi_info = Popen(['dmidecode'], stdout=PIPE, stderr=PIPE,
universal_newlines=True)
output, error = dmi_info.communicate()
if "Permission denied" in error:
raise PermissionException(error)
vendor_data = re.findall("Vendor:\s.*", output)
try:
manufacturer = vendor_data[0].split(":")[1].strip()
except IndexError as exception:
logging.error("Failed to find Manufacturing data")
return
logging.debug(manufacturer)
# Now we look to see if there was any info during boot
# time that would help in debugging this failure
for vendor, module in oem_driver_pool.items():
if manufacturer.lower() == vendor:
oem_module = oem_driver_pool.get(vendor)
break # We've found our desired module to probe.
if oem_module != None:
if insert_supported_module(oem_module) != None:
logging.error("Failed module insertion")
# Check dmesg status for supported module
driver_status = Popen(['dmesg'], stdout=PIPE, universal_newlines=True)
module_regex = oem_module + ".*"
kernel_notes = re.findall(module_regex, driver_status.stdout.read())
# Report ALL findings, it's useful to note it the driver failed init
# more than once of actually passed despite a reading failure
logging.debug("\n".join((kernel_notes)))
else:
logging.error("No supported module")
def check_for_accelerometer():
"""Checks device list for existence of accelerometer and returns
name, manufacturer, and system path info."""
found = False
device_info = open("/proc/bus/input/devices").readlines()
for line in device_info:
if "accelerometer" in line.lower():
target = device_info.index(line)
name = device_info[target].split("=")[1]
path = device_info[target + 2].split("=")[1]
found = True
break
if found:
logger.debug("Name: %s\nPath: %s" % (name, path))
return path.strip()
else:
# Return False as it's expected
logger.error("Accelerometer hardware not found")
return False
def main():
parser = ArgumentParser(description="Tests accelerometer functionality")
parser.add_argument('-m', '--manual', default=False,
action='store_true',
help="For manual test with visual notification")
parser.add_argument('-a', '--automated', default=True,
action='store_true',
help="For automated test using defined parameters")
args = parser.parse_args()
sys_path = check_for_accelerometer()
if not sys_path:
try:
check_module_status()
except PermissionException as error:
print(error, file=sys.stderr)
sys.exit(1)
ui = AccelerometerUI()
grab_data = AxisData(sys_path, ui)
grab_data.setDaemon(True)
grab_data.start()
if args.manual:
ui.enable()
else:
# Sleep for enough time to retrieve a reading.
# Reading is not instant.
time.sleep(5)
if __name__ == '__main__':
main();
plainbox-provider-checkbox-0.25/src/ 0000775 0001750 0001750 00000000000 12646152434 020664 5 ustar sylvain sylvain 0000000 0000000 plainbox-provider-checkbox-0.25/src/clocktest.c 0000664 0001750 0001750 00000006157 12646152433 023033 0 ustar sylvain sylvain 0000000 0000000 /* clocktest.c - check for clock jitter on SMP machines */
#include
#include
#include
#include
#include
#define __USE_GNU 1
#include
#define NSEC_PER_SEC 1000000000
#define MAX_JITTER (double)0.2
#define ITERATIONS 10000
#define NSEC(ts) (ts.tv_sec*NSEC_PER_SEC + ts.tv_nsec)
#ifdef OLD_SCHED_SETAFFINITY
#define setaffinity(mask) sched_setaffinity(0,&mask)
#else
#define setaffinity(mask) sched_setaffinity(0,sizeof(mask),&mask)
#endif
int test_clock_jitter(){
cpu_set_t cpumask;
struct timespec *time;
unsigned long nsec;
unsigned slow_cpu, fast_cpu;
double jitter;
double largest_jitter = 0.0;
unsigned cpu, num_cpus, iter;
int failures = 0;
num_cpus = sysconf(_SC_NPROCESSORS_CONF);
if (num_cpus == 1) {
printf("Single CPU detected. No clock jitter testing necessary.\n");
return 0;
}
printf ("Testing for clock jitter on %u cpus\n", num_cpus);
time=malloc(num_cpus * sizeof(struct timespec));
for (iter=0; iter NSEC(time[fast_cpu])) { fast_cpu = cpu; }
}
jitter = ((double)(NSEC(time[fast_cpu]) - NSEC(time[slow_cpu]))
/ (double)NSEC_PER_SEC);
#ifdef DEBUG
printf("DEBUG: max jitter for pass %u was %f (cpu %u,%u)\n",
iter,jitter,slow_cpu,fast_cpu);
#endif
if (jitter > MAX_JITTER || jitter < -MAX_JITTER){
printf ("ERROR, jitter = %f\n",jitter);
printf ("iter = %u, cpus = %u,%u\n",iter,slow_cpu,fast_cpu);
failures++;
}
if (jitter > largest_jitter)
largest_jitter = jitter;
}
if (failures == 0)
printf ("PASSED, largest jitter seen was %lf\n",largest_jitter);
else
printf ("FAILED, %u iterations failed\n",failures);
return (failures > 0);
}
int test_clock_direction()
{
time_t starttime = 0;
time_t stoptime = 0;
int sleeptime = 60;
int delta = 0;
time(&starttime);
sleep(sleeptime);
time(&stoptime);
delta = (int)stoptime - (int)starttime - sleeptime;
printf("clock direction test: start time %d, stop time %d, sleeptime %u, delta %u\n",
(int)starttime, (int)stoptime, sleeptime, delta);
if (delta != 0)
{
printf("FAILED\n");
return 1;
}
/* otherwise */
printf("PASSED\n");
return 0;
}
int main()
{
int failures = test_clock_jitter();
if (failures == 0)
{
failures = test_clock_direction();
}
return failures;
}
plainbox-provider-checkbox-0.25/src/threaded_memtest.c 0000664 0001750 0001750 00000034616 12646152433 024357 0 ustar sylvain sylvain 0000000 0000000 /* $Id: threaded_memtest.c,v 1.7 2008/02/12 01:17:07 gnichols Exp $
*
* A scalable, threaded memory exerciser/tester.
*
* Author: Will Woods
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Notes:
* This program uses sched_setaffinity(), which is Linux-specific. This could
* probably be ported to other systems with a fairly simple #ifdef / #define
* of setaffinity(), below. You might also have to find a replacement for
* sysconf(), which (while a POSIX function) is not available on some other
* systems (e.g. OSX).
*/
#include
#include
#include
#include
#include
#ifdef __linux__
#include
#include
#include
#include
#define __USE_GNU 1
#include
#include
#ifdef OLD_SCHED_SETAFFINITY
#define setaffinity(mask) sched_setaffinity(0,&mask)
#else
#define setaffinity(mask) sched_setaffinity(0,sizeof(mask),&mask)
#endif
#define VERSION "$Revision: 1.7 $" /* CVS version info */
#define DEFAULT_THREADS 2
#define DEFAULT_RUNTIME 60*15
#define DEFAULT_MEMPCT 0.95
#define BARLEN 40
/* configurable values used by the threads */
int verbose = 0;
int quiet = 0;
int parallel = 0;
unsigned num_threads, default_threads = DEFAULT_THREADS;
unsigned runtime, default_runtime = DEFAULT_RUNTIME;
unsigned long memsize, default_memsize;
/* system info */
unsigned num_cpus;
unsigned long total_ram;
/* statistic gathering */
struct timeval start={0,0}, finish={0,0}, duration={0,0};
unsigned long *loop_counters = NULL;
/* pointers for threads and their memory regions */
pthread_t *threads;
char **mmap_regions = NULL;
/* Thread mutexes and conditions */
unsigned created_threads = 0;
pthread_mutex_t ct_mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned live_threads = 0;
pthread_mutex_t lt_mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned mmap_done = 0;
pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mmap_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t test_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t test_start = PTHREAD_COND_INITIALIZER;
pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER;
unsigned done = 0;
unsigned running_threads = 0;
/* short name of the program */
char *basename = NULL;
/* set the affinity for the current task to the given CPU */
int on_cpu(unsigned cpu){
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(cpu,&mask);
if (setaffinity(mask) < 0){
perror("sched_setaffinity");
return -1;
}
return 0;
}
/* Parse a memsize string like '34m' or '128k' into a long int */
long unsigned parse_memsize(const char *str) {
long unsigned size;
char okchars[] = "GgMmKk%";
char unit;
size=atoi(str); /* ignores trailing non-digit chars */
unit=str[strlen(str)-1];
if (index(okchars,unit)) {
switch (unit) {
case 'G':
case 'g':size *= 1024;
case 'M':
case 'm':size *= 1024;
case 'K':
case 'k':size *= 1024; break;
case '%':size = (size/100.0)*total_ram; break;
}
}
return size;
}
char memsize_str[22]; /* a 64-bit int is 20 digits long */
/* print a nice human-readable string for a large number of bytes */
char *human_memsize(long unsigned size) {
char unit=' ';
if (size > 10240) { unit='K'; size /= 1024; }
if (size > 10240) { unit='M'; size /= 1024; }
if (size > 10240) { unit='G'; size /= 1024; }
snprintf(memsize_str,22,"%ld%c",size,unit);
return memsize_str;
}
/* A cute little progress bar */
void progressbar(char *label, unsigned cur, unsigned total) {
unsigned pos;
char bar[BARLEN+1],spinner[]="-\\|/";
pos=(BARLEN*cur)/total;
memset(bar,'.',BARLEN);
memset(bar,'#',pos);
bar[BARLEN]='\0';
if ((pos < BARLEN) && (total >= BARLEN*2))
bar[pos]=spinner[cur%4];
printf("\r%18s [%s] %u/%u",label,bar,cur,total);
fflush(stdout);
}
/* This is the function that the threads run */
void *mem_twiddler(void *arg) {
unsigned long thread_id, pages, pagesize, i, p;
volatile long garbage;
long *lp;
int t,offset;
char *my_region;
unsigned long mapsize = *(unsigned long *)arg;
/* Make sure each thread gets a unique ID */
pthread_mutex_lock(&ct_mutex);
thread_id=created_threads++;
pthread_mutex_unlock(&ct_mutex);
if (parallel) {
/* let main() go as soon as the thread is created */
mmap_done=1;
pthread_cond_signal(&mmap_cond);
}
on_cpu(thread_id % num_cpus);
pagesize=getpagesize();
pages=mapsize/pagesize;
/* Map a chunk of memory */
if (verbose) printf("thread %ld: mapping %s RAM\n",
thread_id,human_memsize(mapsize));
my_region=mmap(NULL,mapsize,PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE,-1,0);
if (my_region == MAP_FAILED) { perror("mmap"); exit(1); }
mmap_regions[thread_id] = my_region;
/* Dirty each page of the mem region to fault them into existence */
for (i=0;i default_threads)
default_threads = num_cpus*2;
/* Get memory info */
if (sysinfo(&info) != 0) { perror("sysinfo"); return -1; }
free_mem=(info.freeram+info.bufferram)*info.mem_unit;
total_ram=info.totalram*info.mem_unit;
/* default to using most of free_mem */
default_memsize = free_mem * DEFAULT_MEMPCT;
/* Set configurable values to reasonable defaults */
runtime = default_runtime;
num_threads = default_threads;
memsize = default_memsize;
/* parse options */
while ((i = getopt(argc,argv,"hvqpt:n:m:")) != -1) {
switch (i) {
case 'h':
usage();
return 0;
case 'v':
verbose=1;
break;
case 'q':
quiet=1;
break;
case 'p':
parallel=1;
break;
case 't':
runtime=atoi(optarg);
if (!runtime) {
printf("%s: error: bad runtime \"%s\"\n",basename,optarg);
return 1;
}
break;
case 'n':
num_threads=atoi(optarg);
if (!num_threads) {
printf("%s: error: bad thread count \"%s\"\n",basename,optarg);
return 1;
}
break;
case 'm':
memsize=parse_memsize(optarg);
if (!memsize) {
printf("%s: error: bad memory size \"%s\"\n",basename,optarg);
return 1;
}
break;
}
}
/* calculate mapsize now that memsize/num_threads is set */
mapsize = memsize/num_threads;
/* sanity checks */
if (num_threads < num_cpus)
printf("Warning: num_threads < num_cpus. This isn't usually a good idea.\n");
if (memsize > free_mem)
printf("Warning: memsize > free_mem. You will probably hit swap.\n");
/* A little information */
if (verbose) {
printf("Detected %u processors.\n",num_cpus);
printf("RAM: %.1f%% free (%s/",
100.0*(double)free_mem/(double)total_ram,
human_memsize(free_mem));
printf("%s)\n",human_memsize(total_ram));
}
printf("Testing %s RAM for %u seconds using %u threads:\n",
human_memsize(memsize),runtime,num_threads);
/* Allocate room for thread info */
threads=(pthread_t *)malloc(num_threads*sizeof(pthread_t));
mmap_regions=(char **)malloc(num_threads*sizeof(char *));
loop_counters=(unsigned long *)malloc(num_threads*sizeof(unsigned long *));
/* Create all our threads! */
while (created_threads < num_threads) {
pthread_mutex_lock(&mmap_mutex);
mmap_done=0;
if (pthread_create(&threads[created_threads],NULL,
mem_twiddler,(void*)&mapsize) != 0) {
perror("pthread_create"); exit(1);
}
/* Wait for it to finish initializing */
while (!mmap_done) { pthread_cond_wait(&mmap_cond,&mmap_mutex); }
pthread_mutex_unlock(&mmap_mutex);
if (!verbose && !quiet)
progressbar("Starting threads",created_threads,num_threads);
}
if (parallel) {
/* Wait for the signal that everyone is finished initializing */
pthread_mutex_lock(&init_mutex);
while (live_threads < num_threads) { pthread_cond_wait(&init_cond,&init_mutex); }
pthread_mutex_unlock(&init_mutex);
}
/* Let the testing begin! */
if (!verbose && !quiet) printf("\n");
gettimeofday(&start,NULL);
pthread_cond_broadcast(&test_start);
/* catch ^C signal */
mysig.sa_handler=int_handler;
sigemptyset(&mysig.sa_mask);
mysig.sa_flags=0;
sigaction(SIGINT,&mysig,NULL);
/* Wait for the allotted time */
i=0;
while (!done && (i