diff --git a/1508.patch b/1508.patch new file mode 100644 index 0000000..442744b --- /dev/null +++ b/1508.patch @@ -0,0 +1,374 @@ +From 6442f889a3e45e782ad4c2e4c737442e09f895f5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luk=C3=A1=C5=A1=20R=C5=AF=C5=BEi=C4=8Dka?= + +Date: Mon, 17 Aug 2020 13:35:10 +0200 +Subject: [PATCH 1/3] Add `mouse_drag` subroutine to support click and drag in + tests + +1. This PR adds the `mouse_drag` subroutine that enables the mouse and drag +support for OpenQA tests. To use the subroutine, it is possible to either +provide a "starting" and "ending" needle from which the starting and finishing +points will be calculated (using the centres of the needle tag), or +coordinates might be provided directly. If both needles and coordinates are +provided at the same time, then the coordinates precede over the needles. +Combinations are possible, too, which means that one of the points can +be passed as a needle and the other as coordinates. + +2. In order not to repete code, the part responsible for calculating the +center of needle was removed from the `click_lastmatch` subroutine and moved +into a standalone non-exported subroutine called `calculate_clickpoint` to be +also used by the `mouse_drag` subroutine, as well as by the original +`click_lastmatch`. + +3. This PR solves action #39335 +--- + testapi.pm | 109 +++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 93 insertions(+), 16 deletions(-) + +diff --git a/testapi.pm b/testapi.pm +index ed94bd5875..22a062e873 100755 +--- a/testapi.pm ++++ b/testapi.pm +@@ -48,7 +48,7 @@ our @EXPORT = qw($realname $username $password $serialdev %cmd %vars + + assert_screen check_screen assert_and_dclick save_screenshot + assert_and_click mouse_hide mouse_set mouse_click +- mouse_dclick mouse_tclick match_has_tag click_lastmatch ++ mouse_dclick mouse_tclick match_has_tag click_lastmatch mouse_drag + + assert_script_run script_run assert_script_sudo script_sudo + script_output validate_script_output +@@ -108,6 +108,36 @@ os-autoinst is used in the openQA project. + + =head1 internal + ++=head2 _calculate_clickpoint ++ ++This subroutine is used to by several subroutines dealing with mouse clicks to calculate ++a clickpoint, when only the needle area is available. It takes the area coordinates and ++returns the center of that area. It is meant to be a helper subroutine not available ++to be used in tests. ++ ++=cut ++ ++sub _calculate_clickpoint { ++ my ($needle_to_use, $needle_area, $click_point) = @_; ++ # If there is no needle area defined, take it from the needle itself. ++ if (!$needle_area) { ++ $needle_area = $needle_to_use->{area}->[-1]; ++ } ++ # If there is no clickpoint defined, or if it has been specifically defined as "center" ++ # then calculate the click point as a central point of the specified area. ++ if (!$click_point || $click_point eq 'center') { ++ $click_point = { ++ xpos => $needle_area->{w} / 2, ++ ypos => $needle_area->{h} / 2, ++ }; ++ } ++ # Use the click point coordinates (which are relative numbers inside of the area) ++ # to calculate the absolute click point position. ++ my $x = int($needle_area->{x} + $click_point->{xpos}); ++ my $y = int($needle_area->{y} + $click_point->{ypos}); ++ return $x, $y; ++} ++ + =for stopwords xen hvc0 xvc0 ipmi ttyS + + =head2 init +@@ -522,25 +552,12 @@ sub click_lastmatch { + my $relative_click_point; + for my $area (reverse @{$last_matched_needle->{area}}) { + next unless ($relative_click_point = $area->{click_point}); +- + $relevant_area = $area; + last; + } + +- # use center of the last area if no area contains click coordinates +- if (!$relevant_area) { +- $relevant_area = $last_matched_needle->{area}->[-1]; +- } +- if (!$relative_click_point || $relative_click_point eq 'center') { +- $relative_click_point = { +- xpos => $relevant_area->{w} / 2, +- ypos => $relevant_area->{h} / 2, +- }; +- } +- +- # calculate absolute click position and click +- my $x = int($relevant_area->{x} + $relative_click_point->{xpos}); +- my $y = int($relevant_area->{y} + $relative_click_point->{ypos}); ++ # Calculate the absolute click point. ++ my ($x, $y) = _calculate_clickpoint($last_matched_needle, $relevant_area, $relative_click_point); + bmwqemu::diag("clicking at $x/$y"); + mouse_set($x, $y); + if ($args{dclick}) { +@@ -1549,6 +1566,66 @@ sub mouse_hide(;$) { + query_isotovideo('backend_mouse_hide', {offset => $border_offset}); + } + ++=head2 mouse_drag ++ mouse_drag([$startpoint, $endpoint, $startx, $starty, $endx, $endy, $button, $timeout]); ++ ++Click mouse C<$button>, C<'left'> or C<'right'>, at a given location, hold the button and drag ++the mouse to another location where the button is released. You can set the C<$startpoint> ++and C<$endpoint> by passing the name of the needle tag, i.e. the mouse drag happens between ++the two needle areas. Alternatively, you can set all the coordinates explicitly with C<$startx>, ++C<$starty>, C<$endx>, and C<$endy>. You can also set one point using a needle and another one ++using coordinates. If both the coordinates and the needle are provided, the coordinates ++will be used to set up the locations and the needle location will be overridden. ++ ++=cut ++ ++sub mouse_drag { ++ my %args = @_; ++ my ($startx, $starty, $endx, $endy); ++ # If full coordinates are provided, work with them as a priority, ++ if (defined $args{startx} and defined $args{starty}) { ++ $startx = $args{startx}; ++ $starty = $args{starty}; ++ } ++ # If the coordinates were not complete, use the needle as a fallback solution. ++ elsif (defined $args{startpoint}) { ++ my $startmatch = $args{startpoint}; ++ # Check that the needle exists. ++ my $start_matched_needle = assert_screen($startmatch, $args{timeout}); ++ # Calculate the click point from the area defined by the needle (take the center of it) ++ ($startx, $starty) = _calculate_clickpoint($start_matched_needle); ++ } ++ # If neither coordinates nor a needle is provided, report an error and quit. ++ else { ++ die "The starting point of the drag was not correctly provided. Either provide the 'startx' and 'starty' coordinates, or a needle marking the starting point."; ++ } ++ ++ # Repeat the same for endpoint coordinates or needles. ++ if (defined $args{endx} and defined $args{endy}) { ++ $endx = $args{endx}; ++ $endy = $args{endy}; ++ } ++ elsif (defined $args{endpoint}) { ++ my $endmatch = $args{endpoint}; ++ my $end_matched_needle = assert_screen($endmatch, $args{timeout}); ++ ($endx, $endy) = _calculate_clickpoint($end_matched_needle); ++ } ++ else { ++ die "The ending point of the drag was not correctly provided. Either provide the 'endx' and 'endy' coordinates, or a needle marking the end point."; ++ } ++ # Get the button variable. If no button has been provided, assume the "left" button. ++ my $button = $args{button} // "left"; ++ bmwqemu::log_call("mouse dragged", button => $button); ++ ++ # Now, perform the actual mouse drag. Navigate to the startpoint location, ++ # press and hold the mouse button, then navigate to the endpoint location ++ # and release the mouse button. ++ mouse_set($startx, $starty); ++ query_isotovideo('backend_mouse_button', {button => $button, bstate => 1}); ++ mouse_set($endx, $endy); ++ query_isotovideo('backend_mouse_button', {button => $button, bstate => 0}); ++} ++ + =head1 multi console support + + All C commands that interact with the system under test do that + +From 5e6d7d1f868430de25cbd1ae6f1168d74d29bed6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luk=C3=A1=C5=A1=20R=C5=AF=C5=BEi=C4=8Dka?= + +Date: Tue, 25 Aug 2020 10:04:01 +0200 +Subject: [PATCH 2/3] Write tests for _calculate_clickpoint + +--- + t/03-testapi.t | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/t/03-testapi.t b/t/03-testapi.t +index d53aa12590..edca0eb418 100755 +--- a/t/03-testapi.t ++++ b/t/03-testapi.t +@@ -683,4 +683,32 @@ subtest 'autoinst_url' => sub { + is(autoinst_url('foo'), 'http://localhost:1/foo', 'we can configure the hostname that autoinst_url returns'); + }; + ++subtest '_calculate_clickpoint' => sub { ++ my %fake_needle = ( ++ area => [{x => 10, y => 10, w => 20, h => 30}], ++ ); ++ my %fake_needle_area = (x => 100, y => 100, w => 50, h => 40); ++ my %fake_click_point = (xpos => 20, ypos => 10); ++ ++ # Everything is provided. ++ my ($x, $y) = testapi::_calculate_clickpoint(\%fake_needle, \%fake_needle_area, \%fake_click_point); ++ is($x, 120); ++ is($y, 110); ++ ++ # Everything is provided but the click point is 'center' ++ ($x, $y) = testapi::_calculate_clickpoint(\%fake_needle, \%fake_needle_area, "center"); ++ is($x, 125); ++ is($y, 120); ++ ++ # Just the area is provided and no click point. ++ ($x, $y) = testapi::_calculate_clickpoint(\%fake_needle, \%fake_needle_area); ++ is($x, 125); ++ is($y, 120); ++ ++ # Just the needle is provided and no area and click point. ++ ($x, $y) = testapi::_calculate_clickpoint(\%fake_needle); ++ is($x, 20); ++ is($y, 25); ++}; ++ + done_testing; + +From 168d4437c7de938c50609331ffb26a6241a343a1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luk=C3=A1=C5=A1=20R=C5=AF=C5=BEi=C4=8Dka?= + +Date: Wed, 26 Aug 2020 10:32:02 +0200 +Subject: [PATCH 3/3] Write tests for mouse_drag + +--- + t/03-testapi.t | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ + testapi.pm | 2 +- + 2 files changed, 114 insertions(+), 1 deletion(-) + +diff --git a/t/03-testapi.t b/t/03-testapi.t +index edca0eb418..e25b831765 100755 +--- a/t/03-testapi.t ++++ b/t/03-testapi.t +@@ -711,4 +711,117 @@ subtest '_calculate_clickpoint' => sub { + is($y, 25); + }; + ++subtest 'mouse_drag' => sub { ++ my $mock_testapi = Test::MockModule->new('testapi'); ++ my @area = ({x => 100, y => 100, w => 20, h => 20}); ++ $mock_testapi->redefine(assert_screen => {area => \@area}); ++ ++ my ($startx, $starty) = (0, 0); ++ my ($endx, $endy) = (200, 200); ++ my $button = "left"; ++ $cmds = []; ++ # Startpoint from a needle. Endpoint coordinates. ++ mouse_drag(startpoint => 'foo', endx => $endx, endy => $endy, button => $button, timeout => 30); ++ is_deeply($cmds, [ ++ { ++ cmd => 'backend_mouse_set', ++ x => 110, ++ y => 110 ++ }, ++ { ++ bstate => 1, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ { ++ cmd => 'backend_mouse_set', ++ x => 200, ++ y => 200 ++ }, ++ { ++ bstate => 0, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ ], 'mouse drag (startpoint defined by a needle)') or diag explain $cmds; ++ ++ # Startpoint from coordinates, endpoint from a needle. ++ $cmds = []; ++ mouse_drag(endpoint => 'foo', startx => $startx, starty => $starty, button => $button, timeout => 30); ++ is_deeply($cmds, [ ++ { ++ cmd => 'backend_mouse_set', ++ x => 0, ++ y => 0 ++ }, ++ { ++ bstate => 1, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ { ++ cmd => 'backend_mouse_set', ++ x => 110, ++ y => 110 ++ }, ++ { ++ bstate => 0, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ ], 'mouse drag (endpoint defined by a needle)') or diag explain $cmds; ++ ++ # Using coordinates only. ++ $cmds = []; ++ mouse_drag(endx => $endx, endy => $endy, startx => $startx, starty => $starty, button => $button, timeout => 30); ++ is_deeply($cmds, [ ++ { ++ cmd => 'backend_mouse_set', ++ x => 0, ++ y => 0 ++ }, ++ { ++ bstate => 1, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ { ++ cmd => 'backend_mouse_set', ++ x => 200, ++ y => 200 ++ }, ++ { ++ bstate => 0, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ ], 'mouse drag (start and endpoints defined by coordinates)') or diag explain $cmds; ++ ++ # Both needle and coordinates provided for startpoint (coordinates should win). ++ $cmds = []; ++ mouse_drag(startpoint => "foo", endx => $endx, endy => $endy, startx => $startx, starty => $starty, button => $button, timeout => 30); ++ is_deeply($cmds, [ ++ { ++ cmd => 'backend_mouse_set', ++ x => 0, ++ y => 0 ++ }, ++ { ++ bstate => 1, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ { ++ cmd => 'backend_mouse_set', ++ x => 200, ++ y => 200 ++ }, ++ { ++ bstate => 0, ++ button => 'left', ++ cmd => 'backend_mouse_button' ++ }, ++ ], 'mouse drag (redundant definiton by a needle)') or diag explain $cmds; ++}; ++ + done_testing; +diff --git a/testapi.pm b/testapi.pm +index 22a062e873..fe16c29b07 100755 +--- a/testapi.pm ++++ b/testapi.pm +@@ -1615,7 +1615,6 @@ sub mouse_drag { + } + # Get the button variable. If no button has been provided, assume the "left" button. + my $button = $args{button} // "left"; +- bmwqemu::log_call("mouse dragged", button => $button); + + # Now, perform the actual mouse drag. Navigate to the startpoint location, + # press and hold the mouse button, then navigate to the endpoint location +@@ -1624,6 +1623,7 @@ sub mouse_drag { + query_isotovideo('backend_mouse_button', {button => $button, bstate => 1}); + mouse_set($endx, $endy); + query_isotovideo('backend_mouse_button', {button => $button, bstate => 0}); ++ bmwqemu::log_call(message => "Mouse dragged from $startx,$starty to $endx, $endy", button => $button); + } + + =head1 multi console support diff --git a/os-autoinst.spec b/os-autoinst.spec index 1260d83..a50efdf 100644 --- a/os-autoinst.spec +++ b/os-autoinst.spec @@ -38,7 +38,7 @@ Name: os-autoinst Version: %{github_version} -Release: 26%{?github_date:.%{github_date}git%{shortcommit}}%{?dist} +Release: 27%{?github_date:.%{github_date}git%{shortcommit}}%{?dist} Summary: OS-level test automation License: GPLv2+ URL: https://os-autoinst.github.io/openQA/ @@ -47,6 +47,9 @@ Source0: https://github.com/%{github_owner}/%{github_name}/archive/%{gith # https://github.com/os-autoinst/os-autoinst/commit/c2a1e23ce3347359a868d287379710e603cff523 # https://bugzilla.redhat.com/show_bug.cgi?id=1873028 Patch0: 0001-t-Fix-regex-for-warning-multiline.patch +# Add click-and-drag support to testapi (from lruzicka) +# https://github.com/os-autoinst/os-autoinst/pull/1508 +Patch1: 1508.patch # on SUSE this is conditional, for us it doesn't have to be but we # still use a macro just to keep build_requires similar for ease of @@ -225,6 +228,9 @@ rm tools/lib/perlcritic/Perl/Critic/Policy/*.pm %files devel %changelog +* Fri Aug 28 2020 Adam Williamson - 4.6-27.20200804gitb781299 +- Backport click-and-drag support by lruzicka + * Thu Aug 27 2020 Adam Williamson - 4.6-26.20200804gitb781299 - Backport fix for a test regex with recent qemu