Przeglądaj źródła

Fix #64, do it via modularity as specified in #66

George S. Baugh 10 lat temu
rodzic
commit
22cbe3e237

+ 2 - 1
Changes

@@ -3,12 +3,13 @@ Revision history for Perl module TestRail::API
 0.029 2015-07-11 TEODESIAN
     - Add bulkAddResults function to TestRail::API
     - Add new script testrail-bulk-mark-results
-    - Add new script testrail-lock
+    - Add new script testrail-lock and it's backend TestRail::Utils::Lock
     - Re-factor part of the scripts into TestRail::Utils::interrogateUser
     - Modify all bin/ scripts to use POD as their help output, move help() to TestRail::Utils
     - Modify all bin/ scripts to parse all the ~/.testrailrc options
     - Fix an issue where statusNamesToIDs would return status IDs in the wrong order.
     - Re-factor to use Type::Tiny parameter checking.
+    - Fix getCaseTypeByName, it's apparently been broken/noncovered this whole time
 
 0.028 2015-06-16 TEODESIAN
     - Hotfix: forgot to include a module in the prove plugin.  How did this pass compile.t? A mystery.

+ 15 - 3
bin/testrail-lock

@@ -45,9 +45,17 @@ All mandatory options not passed with the above switches, or in your ~/.testrail
 
 =over 4
 
--p --plan     : desired plan name.  Required if the run passed is a child of a plan.
+-p --plan       : desired plan name.  Required if the run passed is a child of a plan.
 
--e --encoding : Character encoding of arguments.  Defaults to UTF-8. See L<Encode::Supported> for supported encodings.
+-m --match      : attempt to find filenames matching the test names in the provided dir.
+
+--no-match      : attempt to find filenames that do not match test names in the provided dir.
+
+-n --no-recurse : if match (or no-match) passed, do not recurse subdirectories.
+
+-t --case-type  : Only attempt to lock cases of the specified type.  May be passed multiple times.
+
+-e --encoding   : Character encoding of arguments.  Defaults to UTF-8. See L<Encode::Supported> for supported encodings.
 
 =back
 
@@ -104,12 +112,16 @@ GetOptions(
     'p|plan=s'        => \$opts->{'plan'},
     'r|run=s'         => \$opts->{'run'},
     'c|config=s@'     => \$opts->{'configs'},
+    'm|match=s'       => \$opts->{'match'},
+    'no-match=s'      => \$opts->{'no-match'},
+    'n|no-recurse'    => \$opts->{'no-recurse'},
+    't|case-type=s@'  => \$opts->{'case-types'},
     'mock'            => \$opts->{'mock'},
     'e|encoding=s'    => \$opts->{'encoding'},
     'h|help'          => \$opts->{'help'}
 );
 
-if ($opts->{help}) { help(); }
+if ($opts->{help}) { TestRail::Utils::help(); }
 $opts->{'hostname'} = hostname;
 
 TestRail::Utils::interrogateUser($opts,qw{apiurl user password project run lockname});

+ 3 - 24
bin/testrail-tests

@@ -86,9 +86,6 @@ use TestRail::Utils;
 
 use Getopt::Long;
 use File::HomeDir qw{my_home};
-use File::Find;
-use Cwd qw{abs_path};
-use File::Basename qw{basename};
 
 my $opts ={};
 
@@ -118,11 +115,6 @@ GetOptions(
 
 if ($opts->{help}) { TestRail::Utils::help(); }
 
-if ($opts->{'match'} && $opts->{'no-match'}) {
-    print "Error! match and no-match options are mutually exclusive.\n";
-    exit 255;
-}
-
 TestRail::Utils::interrogateUser($opts,qw{apiurl user password project run});
 
 if ($opts->{mock}) {
@@ -186,24 +178,11 @@ if (!$cases) {
     exit 3;
 }
 
-my @tests =  map {$_->{'title'}} @$cases;
-my @realtests;
-
-if ($opts->{'match'} || $opts->{'no-match'}) {
-    my $dir = $opts->{'match'} ? $opts->{'match'} : $opts->{'no-match'};
-    if (!$opts->{'no-recurse'}) {
-        File::Find::find( sub { push(@realtests,$File::Find::name) if -f }, $dir );
-        @tests = grep {my $real = $_; grep { basename($real) eq $_ } @tests} @realtests; #XXX if you have dups in your tree, be-ware
-    } else {
-        #Handle special windows case -- glob doesn't prepend abspath
-        @realtests = glob("$dir/*");
-        @tests = map {$^O eq 'MSWin32' ? "$dir/$_" : $_ } grep {my $fname = $_; grep { basename($_) eq $fname} @realtests } @tests;
-    }
-    @tests = grep {my $otest = basename($_); scalar(grep {basename($_) eq $otest} @tests) == 0} @realtests if $opts->{'no-match'}; #invert the list in this case.
-}
+$opts->{'names-only'} = 1;
+my @tests = TestRail::Utils::findTests($opts,@$cases);
 
-@tests = map { abs_path($_) } @tests if $opts->{'match'};
 print join("\n",@tests)."\n" if scalar(@tests);
+
 exit 0;
 
 __END__

+ 727 - 9
lib/Test/LWP/UserAgent/TestRailMock.pm

@@ -11,6 +11,8 @@ use HTTP::Response;
 use HTTP::Request;
 use HTTP::Headers;
 
+use Clone qw{clone};
+
 =head1 DESCRIPTION
 
 Provides a Test::LWP::UserAgent with mappings defined for all the requests made by this module's main test.
@@ -605,7 +607,7 @@ $VAR4 = bless( {
 $VAR5 = '[
     {"id":1,"suite_id":9,"name":"TestingSuite","description":"ACQUIRE CLOTHES, BOOTS AND MOTORCYCLE","milestone_id":null,"assignedto_id":null,"include_all":true,"is_completed":false,"completed_on":null,"config":null,"config_ids":[],"passed_count":0,"blocked_count":0,"untested_count":1,"retest_count":0,"failed_count":0,"custom_status1_count":0,"custom_status2_count":0,"custom_status3_count":0,"custom_status4_count":0,"custom_status5_count":0,"custom_status6_count":0,"custom_status7_count":0,"project_id":9,"plan_id":null,"created_on":1419364929,"created_by":1,"url":"http:\\/\\/testrail.local\\/\\/index.php?\\/runs\\/view\\/22"},
     {"id":2,"suite_id":9,"name":"OtherOtherSuite","description":"bah","completed_on":null},
-    {"id":3,"suite_id":9,"name":"FinalRun","description":"Tests finality","milestone_id":null,"assignedto_id":null,"include_all":true,"is_completed":false,"completed_on":null,"config":null,"config_ids":[],"passed_count":0,"blocked_count":0,"untested_count":0,"retest_count":0,"failed_count":0,"custom_status1_count":1,"custom_status2_count":0,"custom_status3_count":0,"custom_status4_count":0,"custom_status5_count":0,"custom_status6_count":0,"custom_status7_count":0,"project_id":9,"plan_id":null,"created_on":1419364929,"created_by":1,"url":"http:\\/\\/testrail.local\\/\\/index.php?\\/runs\\/view\\/22"}
+    {"id":3,"suite_id":9,"name":"FinalRun","description":"Tests finality","milestone_id":null,"assignedto_id":null,"include_all":true,"is_completed":false,"completed_on":null,"config":null,"config_ids":[],"passed_count":0,"blocked_count":0,"untested_count":0,"retest_count":0,"failed_count":0,"custom_status1_count":1,"custom_status2_count":0,"custom_status3_count":0,"custom_status4_count":0,"custom_status5_count":0,"custom_status6_count":0,"custom_status7_count":0,"project_id":9,"plan_id":null,"created_on":1419364929,"created_by":1,"url":"http:\\/\\/testrail.local\\/\\/index.php?\\/runs\\/view\\/22"},{"id":1099,"suite_id":5,"name":"lockRun","description":"Locky tests","milestone_id":null,"assignedto_id":null,"include_all":true,"is_completed":false,"completed_on":null,"config":null,"config_ids":[],"passed_count":0,"blocked_count":0,"untested_count":0,"retest_count":5,"failed_count":0,"custom_status1_count":0,"custom_status2_count":0,"custom_status3_count":0,"custom_status4_count":1,"custom_status5_count":0,"custom_status6_count":0,"custom_status7_count":0,"project_id":2,"plan_id":null,"created_on":1437073290,"created_by":1,"url":"http:\\/\\/testrail.local\\/index.php?\\/runs\\/view\\/1099"}
 ]';
 $mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
 
@@ -1236,7 +1238,7 @@ $VAR4 = bless( {
                  'server' => 'Apache/2.4.7 (Ubuntu)'
                }, 'HTTP::Headers' );
 $VAR5 = '[{"id":15,"case_id":8,"status_id":3,"assignedto_id":null,"run_id":22,"title":"STORAGE TANKS SEARED","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":15,"case_id":8,"status_id":3,"assignedto_id":null,"run_id":22,"title":"NOT SO SEARED AFTER ARR"},{"id":15,"case_id":8,"status_id":3,"assignedto_id":1,"run_id":22,"title":"skipall.test"} ]';
-$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
 
 }
 
@@ -1263,7 +1265,7 @@ $VAR4 = bless( {
                  'server' => 'Apache/2.4.7 (Ubuntu)'
                }, 'HTTP::Headers' );
 $VAR5 = '[{"id":15,"case_id":8,"status_id":3,"assignedto_id":null,"run_id":22,"title":"STORAGE TANKS SEARED","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":15,"case_id":8,"status_id":3,"assignedto_id":null,"run_id":22,"title":"NOT SO SEARED AFTER ARR"},{"id":15,"case_id":8,"status_id":3,"assignedto_id":1,"run_id":22,"title":"skipall.test"} ]';
-$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
 
 }
 
@@ -1291,7 +1293,7 @@ $VAR4 = bless( {
                  'server' => 'Apache/2.4.7 (Ubuntu)'
                }, 'HTTP::Headers' );
 $VAR5 = '[{"id":15,"case_id":8,"status_id":3,"assignedto_id":null,"run_id":22,"title":"STORAGE TANKS SEARED","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":15,"case_id":8,"status_id":3,"assignedto_id":null,"run_id":22,"title":"NOT SO SEARED AFTER ARR"},{"id":15,"case_id":8,"status_id":3,"assignedto_id":null,"run_id":22,"title":"skipall.test"},{"id":16,"case_id":9,"status_id":3,"assignedto_id":null,"run_id":22,"title":"notests.test"},{"id":17,"case_id":10,"status_id":1,"assignedto_id":null,"run_id":22,"title":"pass.test"},{"id":18,"case_id":10,"status_id":1,"assignedto_id":null,"run_id":22,"title":"todo_pass.test"}]';
-$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
 
 }
 
@@ -1356,22 +1358,22 @@ $VAR2 = '200';
 $VAR3 = 'OK';
 $VAR4 = bless( {
                  'connection' => 'close',
-                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.5',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
                  'client-response-num' => 1,
-                 'date' => 'Tue, 23 Dec 2014 20:02:11 GMT',
+                 'date' => 'Thu, 16 Jul 2015 23:05:53 GMT',
                  'client-peer' => '192.168.122.217:80',
-                 'content-length' => '830',
+                 'content-length' => '1489',
                  '::std_case' => {
                                    'client-date' => 'Client-Date',
                                    'x-powered-by' => 'X-Powered-By',
                                    'client-response-num' => 'Client-Response-Num',
                                    'client-peer' => 'Client-Peer'
                                  },
-                 'client-date' => 'Tue, 23 Dec 2014 20:02:11 GMT',
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:53 GMT',
                  'content-type' => 'application/json; charset=utf-8',
                  'server' => 'Apache/2.4.7 (Ubuntu)'
                }, 'HTTP::Headers' );
-$VAR5 = '[{"id":1,"name":"passed","label":"Passed","color_dark":6667107,"color_medium":9820525,"color_bright":12709313,"is_system":true,"is_untested":false,"is_final":true},{"id":2,"name":"blocked","label":"Blocked","color_dark":9474192,"color_medium":13684944,"color_bright":14737632,"is_system":true,"is_untested":false,"is_final":true},{"id":3,"name":"untested","label":"Untested","color_dark":11579568,"color_medium":15395562,"color_bright":15790320,"is_system":true,"is_untested":true,"is_final":false},{"id":4,"name":"retest","label":"Retest","color_dark":13026868,"color_medium":15593088,"color_bright":16448182,"is_system":true,"is_untested":false,"is_final":false},{"id":5,"name":"failed","label":"Failed","color_dark":14250867,"color_medium":15829135,"color_bright":16631751,"is_system":true,"is_untested":false,"is_final":true},{"id":6,"name":"skip","label":"Skipped"},{"id":7,"name":"todo_fail","label":"TODO (failed)"},{"id":8,"name":"todo_pass","label":"TODO (passed)"}]';
+$VAR5 = '[{"id":1,"name":"passed","label":"Passed","color_dark":6667107,"color_medium":9820525,"color_bright":12709313,"is_system":true,"is_untested":false,"is_final":true},{"id":2,"name":"blocked","label":"Blocked","color_dark":9474192,"color_medium":13684944,"color_bright":14737632,"is_system":true,"is_untested":false,"is_final":true},{"id":3,"name":"untested","label":"Untested","color_dark":11579568,"color_medium":15395562,"color_bright":15790320,"is_system":true,"is_untested":true,"is_final":false},{"id":4,"name":"retest","label":"Retest","color_dark":13026868,"color_medium":15593088,"color_bright":16448182,"is_system":true,"is_untested":false,"is_final":false},{"id":5,"name":"failed","label":"Failed","color_dark":14250867,"color_medium":15829135,"color_bright":16631751,"is_system":true,"is_untested":false,"is_final":true},{"id":6,"name":"skip","label":"Skipped","color_dark":0,"color_medium":10526880,"color_bright":13684944,"is_system":false,"is_untested":false,"is_final":true},{"id":7,"name":"todo_fail","label":"Todo Failed","color_dark":0,"color_medium":10526880,"color_bright":13684944,"is_system":false,"is_untested":false,"is_final":true},{"id":8,"name":"todo_pass","label":"Todo Passed","color_dark":0,"color_medium":10526880,"color_bright":13684944,"is_system":false,"is_untested":false,"is_final":true},{"id":9,"name":"locked","label":"Locked","color_dark":14730013,"color_medium":16772121,"color_bright":16110712,"is_system":false,"is_untested":false,"is_final":false}]';
 $mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
 
 }
@@ -2278,4 +2280,720 @@ $VAR5 = '[{"id":515,"test_id":286,"status_id":1,"created_by":1,"created_on":1436
 $mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
 }
 
+{
+
+$VAR1 = 'index.php?/api/v2/get_case_types';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 20:59:52 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '285',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 20:59:52 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":1,"name":"Automated","is_default":false},{"id":2,"name":"Functionality","is_default":false},{"id":6,"name":"Other","is_default":true},{"id":3,"name":"Performance","is_default":false},{"id":4,"name":"Regression","is_default":false},{"id":5,"name":"Usability","is_default":false}]';
+$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+#Lock Mocks
+
+{
+
+$VAR1 = 'index.php?/api/v2/add_result/590';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '353',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:54 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":635,"test_id":590,"status_id":9,"created_by":1,"created_on":1437087955,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/get_results/590&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '895',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":635,"test_id":590,"status_id":9,"created_by":1,"created_on":1437087955,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":631,"test_id":590,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":622,"test_id":590,"status_id":9,"created_by":1,"created_on":1437087447,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/add_result/588';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:57 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '353',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:56 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":637,"test_id":588,"status_id":9,"created_by":1,"created_on":1437087957,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/get_results/588&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:57 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '895',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:57 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":637,"test_id":588,"status_id":9,"created_by":1,"created_on":1437087957,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":630,"test_id":588,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":624,"test_id":588,"status_id":9,"created_by":1,"created_on":1437087449,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/add_result/590';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '353',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:54 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":635,"test_id":590,"status_id":9,"created_by":1,"created_on":1437087955,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/get_results/590&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '895',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":635,"test_id":590,"status_id":9,"created_by":1,"created_on":1437087955,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":631,"test_id":590,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":622,"test_id":590,"status_id":9,"created_by":1,"created_on":1437087447,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/add_result/591';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:59 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '353',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:59 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":639,"test_id":591,"status_id":9,"created_by":1,"created_on":1437087959,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/get_results/591&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:59 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '895',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:59 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":639,"test_id":591,"status_id":9,"created_by":1,"created_on":1437087959,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":632,"test_id":591,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":626,"test_id":591,"status_id":9,"created_by":1,"created_on":1437087452,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/add_result/593';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:06:00 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '353',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:06:00 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":640,"test_id":593,"status_id":9,"created_by":1,"created_on":1437087960,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/get_results/593&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:06:00 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '895',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:06:00 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":640,"test_id":593,"status_id":9,"created_by":1,"created_on":1437087960,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":634,"test_id":593,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":627,"test_id":593,"status_id":9,"created_by":1,"created_on":1437087453,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/add_result/592';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:06:02 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '353',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:06:01 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":641,"test_id":592,"status_id":9,"created_by":1,"created_on":1437087962,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
+$VAR1 = 'index.php?/api/v2/get_results/592&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:06:02 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '895',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:06:02 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":641,"test_id":592,"status_id":9,"created_by":1,"created_on":1437087962,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":633,"test_id":592,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":628,"test_id":592,"status_id":9,"created_by":1,"created_on":1437087454,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+$mockObject->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+sub lockMockStep0 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:54 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:54 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
+sub lockMockStep1 {
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+$VAR1 = 'index.php?/api/v2/add_result/587';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:56 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '353',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:55 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":636,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087956,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+$VAR1 = 'index.php?/api/v2/get_results/587&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:56 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1250',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:56 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":636,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087956,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":629,"test_id":587,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":625,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087451,"assignedto_id":null,"comment":"Test Locked by race.bannon.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":623,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087448,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+return $cloned;
+
+}
+
+sub lockMockStep2 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:56 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:56 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
+sub lockMockStep3 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:57 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:57 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
+sub lockMockStep4 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:58 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:58 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+$VAR1 = 'index.php?/api/v2/add_result/587';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:58 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '354',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:58 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '{"id":638,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087958,"assignedto_id":null,"comment":"Test Locked by race.bannon.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}';
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+$VAR1 = 'index.php?/api/v2/get_results/587&limit=100';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:58 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1605',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:58 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":638,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087958,"assignedto_id":null,"comment":"Test Locked by race.bannon.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":636,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087956,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":629,"test_id":587,"status_id":4,"created_by":1,"created_on":1437087814,"assignedto_id":null,"comment":null,"version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":625,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087451,"assignedto_id":null,"comment":"Test Locked by race.bannon.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null},{"id":623,"test_id":587,"status_id":9,"created_by":1,"created_on":1437087448,"assignedto_id":null,"comment":"Test Locked by drs-laptop.\\n\\n        If this result is preceded immediately by another lock statement like this, please disregard it;\\n        a lock collision occurred.","version":null,"elapsed":null,"defects":null,"custom_step_results":null}]';
+
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
+sub lockMockStep5 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:05:59 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:05:59 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
+sub lockMockStep6 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:06:00 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:06:00 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
+sub lockMockStep7 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:06:01 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:06:01 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":4,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
+sub lockMockStep8 {
+
+$VAR1 = 'index.php?/api/v2/get_tests/1099';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.9',
+                 'client-response-num' => 1,
+                 'date' => 'Thu, 16 Jul 2015 23:06:02 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '1613',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Thu, 16 Jul 2015 23:06:02 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":587,"case_id":14,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockme.test","type_id":1,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":588,"case_id":15,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmetoo.test","type_id":1,"priority_id":2,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":590,"case_id":16,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"lockmealso.test","type_id":1,"priority_id":5,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":591,"case_id":17,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"sortalockme.test","type_id":6,"priority_id":4,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":592,"case_id":18,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"dontlockme_nothere.test","type_id":1,"priority_id":3,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null},{"id":593,"case_id":19,"status_id":9,"assignedto_id":null,"run_id":1099,"title":"dontlockme_alsonothere.test","type_id":6,"priority_id":1,"estimate":null,"estimate_forecast":null,"refs":null,"milestone_id":null,"custom_preconds":null,"custom_steps":null,"custom_expected":null}]';
+
+my $cloned = clone $mockObject;
+$cloned->map_response(qr/\Q$VAR1\E$/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+return $cloned;
+
+}
+
 1;

+ 12 - 5
lib/TestRail/API.pm

@@ -89,7 +89,6 @@ sub new {
         testtree         => [],
         flattree         => [],
         user_cache       => [],
-        type_cache       => [],
         configurations   => {},
         tr_fields        => undef,
         default_request  => undef,
@@ -175,7 +174,12 @@ sub _doRequest {
 
     #Uncomment to generate mocks
     #use Data::Dumper;
-    #print Dumper($path,'200','OK',$response->headers,$response->content);
+    #open(my $fh, '>>', 'mock.out');
+    #print $fh "{\n\n";
+    #print $fh Dumper($path,'200','OK',$response->headers,$response->content);
+    #print $fh '$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));';
+    #print $fh "\n\n}\n\n";
+    #close $fh;
 
     return $response if !defined($response); #worst case
     if ($response->code == 403) {
@@ -790,11 +794,13 @@ Returns ARRAYREF of case type definition HASHREFs.
 sub getCaseTypes {
     state $check = compile(Object);
     my ($self) = $check->(@_);
+    return $self->{'type_cache'} if defined($self->{'type_cache'});
 
     my $types = $self->_doRequest("index.php?/api/v2/get_case_types");
     return -500 if !$types || (reftype($types) || 'undef') ne 'ARRAY';
-    $self->{'type_cache'} = $types if !$self->{'type_cache'}; #We can't change this with API, so assume it is static
-    return $self->{'type_cache'};
+    $self->{'type_cache'} = $types;
+
+    return $types;
 }
 
 =head2 B<getCaseTypeByName (name)>
@@ -808,6 +814,7 @@ Gets case type by name.
 =back
 
 Returns case type definition HASHREF.
+Dies if named case type does not exist.
 
     $tr->getCaseTypeByName();
 
@@ -822,7 +829,7 @@ sub getCaseTypeByName {
     foreach my $type (@$types) {
         return $type if $type->{'name'} eq $name;
     }
-    return 0;
+    confess("No such case type '$name'!");
 }
 
 =head2 B<createCase(section_id,title,type_id,options,extra_options)>

+ 65 - 0
lib/TestRail/Utils.pm

@@ -9,6 +9,11 @@ use warnings;
 use Carp qw{confess cluck};
 use Pod::Perldoc 3.10;
 
+use Scalar::Util qw{blessed};
+use File::Find;
+use Cwd qw{abs_path};
+use File::Basename qw{basename};
+
 =head1 SCRIPT HELPER FUNCTIONS
 
 =head2 help
@@ -160,6 +165,66 @@ sub getRunInformation {
     return ($project,$plan,$run);
 }
 
+=head2 findTests(opts,case1,...,caseN)
+
+Given an ARRAY of tests, find tests meeting your criteria (or not) in the specified directory.
+
+=over 4
+
+=item HASHREF C<OPTS> - Options for finding tests:
+
+=over 4
+
+=item STRING C<MATCH> - Only return tests which exist in the path provided.  Mutually exclusive with no-match.
+
+=item STRING C<NO-MATCH> - Only return tests which aren't in the path provided (orphan tests).  Mutually exclusive with match.
+
+=item BOOL C<NO-RECURSE> - Do not do a recursive scan for files.
+
+=item BOOL C<NAMES-ONLY> - Only return the names of the tests rather than the entire test objects.
+
+=back
+
+=item ARRAY C<CASES> - Array of cases to translate to pathnames based on above options.
+
+=back
+
+Returns tests found that meet the criteria laid out in the options.
+Provides absolute path to tests if match is passed; this is the 'full_title' key if names-only is false/undef.
+Dies if mutually exclusive options are passed.
+
+=cut
+
+sub findTests {
+    my ($opts,@cases) = @_;
+
+    confess "Error! match and no-match options are mutually exclusive.\n" if ($opts->{'match'} && $opts->{'no-match'});
+    my @tests = @cases;
+    my (@realtests);
+
+    if ($opts->{'match'} || $opts->{'no-match'}) {
+        my $dir = $opts->{'match'} ? $opts->{'match'} : $opts->{'no-match'};
+        if (!$opts->{'no-recurse'}) {
+            File::Find::find( sub { push(@realtests,$File::Find::name) if -f }, $dir );
+            @tests = grep {my $real = $_->{'title'}; grep { $real eq basename($_) } @realtests} @cases; #XXX if you have dups in your tree, be-ware
+        } else {
+            #Handle special windows case -- glob doesn't prepend abspath
+            @realtests = glob("$dir/*");
+            @tests = map {
+                $_->{'title'} = "$dir/".$_->{'title'} if( $^O eq 'MSWin32' );
+                $_
+            } grep {my $fname = $_->{'title'}; grep { basename($_) eq $fname} @realtests } @cases;
+        }
+        @tests = map {{'title' => $_}} grep {my $otest = basename($_); scalar(grep {basename($_->{'title'}) eq $otest} @tests) == 0} @realtests if $opts->{'no-match'}; #invert the list in this case.
+    }
+
+    @tests = map { abs_path($_->{'title'}) } @tests if $opts->{'match'} && $opts->{'names-only'};
+    @tests = map { $_->{'full_title'} = abs_path($_->{'title'}); $_ } @tests if $opts->{'match'} && !$opts->{'names-only'};
+    @tests = map { $_->{'title'} } @tests if !$opts->{'match'} && $opts->{'names-only'};
+
+    return @tests;
+}
+
 1;
 
 __END__

+ 30 - 21
lib/TestRail/Utils/Lock.pm

@@ -3,6 +3,8 @@
 
 package TestRail::Utils::Lock;
 
+use 5.010;
+
 use strict;
 use warnings;
 
@@ -36,16 +38,18 @@ testrail-lock's primary routine.
 
 =item TestRail::API C<HANDLE> - Instance of TestRail::API, in the case where the caller already has a valid object.
 
-There are two special keys, 'mock' and 'simulate_race_condition' in the HASHREF that are used for testing.
+There is a special key, 'mock' in the HASHREF that is used for testing.
+The 'hostname' key must also be passed in the options, as it is required by lockTest, which this calls.
 
 =back
 
 =cut
 
 sub pickAndLockTest {
-    my ($opts, $tr) = @_;
+    state $check = compile(HashRef, Optional[Maybe[Object]]);
+    my ($opts, $tr) = $check->(@_);
 
-    if ($opts->{mock}) {
+    if ($opts->{mock} && !$tr) {
         require Test::LWP::UserAgent::TestRailMock; #LazyLoad
         $opts->{browser} = $Test::LWP::UserAgent::TestRailMock::mockObject;
         $opts->{debug} = 1;
@@ -64,31 +68,34 @@ sub pickAndLockTest {
     my ($lock_status_id,$untested_id,$retest_id) = @$status_ids;
 
     my $cases = $tr->getTests($run->{'id'});
-    my @statuses_to_check_for = ($untested_id,$retest_id);
-    @statuses_to_check_for = ($lock_status_id) if $opts->{'simulate_race_condition'}; #Unit test stuff
 
-    # Limit to only non-locked and open cases
-    @$cases = grep { my $tstatus = $_->{'status_id'}; scalar(grep { $tstatus eq $_ } @statuses_to_check_for) } @$cases;
-    @$cases = sort { $a->{'priority_id'} <=> $b->{'priority_id'} } @$cases; #Sort by priority
+    #Filter by case types
+    if ($opts->{'case-types'}) {
+        my @case_types = map { my $cdef = $tr->getCaseTypeByName($_); $cdef->{'id'} } @{ $opts->{'case-types'} };
+        @$cases = grep { my $case_type_id = $_->{'type_id'}; grep {$_ eq $case_type_id} @case_types } @$cases;
+    }
 
-    my $test = shift @$cases;
+    # Limit to only non-locked and open cases
+    @$cases = grep { my $tstatus = $_->{'status_id'}; scalar(grep { $tstatus eq $_ } ($untested_id,$retest_id) ) } @$cases;
+    @$cases = sort { $b->{'priority_id'} <=> $a->{'priority_id'} } @$cases; #Sort by priority DESC
 
-    confess "No outstanding cases in the provided run.\n" if !$test;
+    # Filter by match options
+    @$cases = TestRail::Utils::findTests($opts,@$cases);
 
     my $title;
     foreach my $test (@$cases) {
-        $title = lockTest($test,$lock_status_id,$tr);
+        $title = lockTest($test,$lock_status_id,$opts->{'hostname'},$tr);
         last if $title;
     }
 
-    confess "Failed to lock case!" if !$title;
+    warn "Failed to lock case!  This probably means you don't have any cases left to lock." if !$title;
 
     return $title;
 }
 
 =head2 lockTest(test,lock_status_id,handle)
 
-Lock the specified test.
+Lock the specified test, and return it's title (or full_title if it exists).
 
 =over 4
 
@@ -100,24 +107,24 @@ Lock the specified test.
 
 =back
 
-Returns undef in the event a lock could not occur, and warns on lock collisions.
+Returns undef in the event a lock could not occur, and warns & returns 0 on lock collisions.
 
 =cut
 
 sub lockTest {
-    state $check = compile(HashRef, Int, Object);
-    my ($test,$lock_status_id,$handle) = $check->(@_);
+    state $check = compile(HashRef, Int, Str, Object);
+    my ($test,$lock_status_id,$hostname,$handle) = $check->(@_);
 
-    my $res = $tr->createTestResults(
+    my $res = $handle->createTestResults(
         $test->{id},
         $lock_status_id,
-        "Test Locked by $opts->{hostname}.\n
+        "Test Locked by $hostname.\n
         If this result is preceded immediately by another lock statement like this, please disregard it;
         a lock collision occurred."
     );
 
     #If we've got more than 100 lock conflicts, we have big-time problems
-    my $results = $tr->getTestResults($test->{id},100);
+    my $results = $handle->getTestResults($test->{id},100);
 
     #Remember, we're returned results from newest to oldest...
     my $next_one = 0;
@@ -137,10 +144,12 @@ sub lockTest {
         if ($next_one) {
             #If we got this far, a lock conflict occurred. Try the next one.
             warn "Lock conflict detected.  Try again...\n";
-            return undef;
+            return 0;
         }
     }
-    return $test->{'title'} if $next_one;
+
+    #Prefer full titles (match mode)
+    return defined($test->{'full_title'}) ? $test->{'full_title'} : $test->{'title'} if $next_one;
     return undef;
 }
 

+ 5 - 1
t/TestRail-API-mockOnly.t

@@ -3,7 +3,7 @@ use warnings;
 
 #Test things we can only mock, because the API doesn't support them.
 
-use Test::More 'tests' => 13;
+use Test::More 'tests' => 14;
 use TestRail::API;
 use Test::LWP::UserAgent::TestRailMock;
 use Scalar::Util qw{reftype};
@@ -40,3 +40,7 @@ is(reftype($tr->closeRun(666)),'HASH',"Can close run that exists");
 is($tr->closeRun(90210),-404,"Can't close run that doesn't exist");
 is(reftype($tr->closePlan(23)),'HASH',"Can close plan that exists");
 is($tr->closePlan(75020),-404,"Can't close plan that doesn't exist");
+
+# Test case type method
+my $ct = $tr->getCaseTypeByName("Automated");
+is($ct->{'id'},1,"Can get case type by name");

+ 5 - 1
t/TestRail-API.t

@@ -4,7 +4,7 @@ use warnings;
 use TestRail::API;
 use Test::LWP::UserAgent::TestRailMock;
 
-use Test::More tests => 74;
+use Test::More tests => 75;
 use Test::Fatal;
 use Test::Deep;
 use Scalar::Util ();
@@ -56,6 +56,10 @@ my @cuser_ids = $tr->userNamesToIds(@user_names);
 cmp_deeply(\@cuser_ids,\@user_ids,"userNamesToIds functions correctly");
 isnt(exception {$tr->userNamesToIds(@user_names,'potzrebie'); }, undef, "Passing invalid user name throws exception");
 
+#Test CASE TYPE method
+my $caseTypes = $tr->getCaseTypes();
+is(ref($caseTypes),'ARRAY',"getCaseTypes returns ARRAY of case types");
+
 #Test PROJECT methods
 my $project_name = 'CRUSH ALL HUMANS';
 

+ 70 - 0
t/TestRail-Utils-Lock.t

@@ -0,0 +1,70 @@
+use strict;
+use warnings;
+
+use Test::More 'tests' => 11;
+use Test::Fatal;
+use File::Basename qw{dirname};
+
+use TestRail::Utils;
+use TestRail::Utils::Lock;
+use Test::LWP::UserAgent::TestRailMock;
+use Sys::Hostname qw{hostname};
+use File::Basename qw{basename};
+
+my $opts = {
+    'project'    => 'TestProject',
+    'run'        => 'lockRun',
+    'case-types' => ['Automated'],
+    'lockname'   => 'locked',
+    'match'      => 't',
+    'no-recurse' => 1,
+    'hostname'   => hostname(),
+    'mock'       => 1
+};
+
+my ($apiurl,$login,$pw) = ('http://hokum.bogus','bogus','bogus');
+
+my $tr = new TestRail::API($apiurl,$login,$pw,undef,1);
+
+#Mock if necesary
+$tr->{'debug'} = 0;
+
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep0();
+is(TestRail::Utils::Lock::pickAndLockTest($opts,$tr),undef,"Verify that no tests are locked in match mode, as they all are in a subdir, and recurse is off");
+delete $opts->{'no-recurse'};
+
+is(basename( TestRail::Utils::Lock::pickAndLockTest($opts,$tr) ), 'lockmealso.test' , "Verify the highest priority test is chosen first");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep1();
+
+is(basename( TestRail::Utils::Lock::pickAndLockTest($opts,$tr) ), 'lockme.test'     , "Verify the highest priority test of type automated is chosen");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep2();
+
+is(basename( TestRail::Utils::Lock::pickAndLockTest($opts,$tr) ), 'lockmetoo.test'  , "Verify that the highest priority test that exists in the tree is chosen");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep3();
+
+is(TestRail::Utils::Lock::pickAndLockTest($opts,$tr),undef,"Verify that no tests are locked, as they either are of the wrong type or do not exist in the match tree");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep4();
+
+#Simulate lock collision
+my ($lockStatusID) = $tr->statusNamesToIds('locked');
+my ($project,$plan,$run) = TestRail::Utils::getRunInformation($tr,$opts);
+is(TestRail::Utils::Lock::lockTest($tr->getTestByName($run->{'id'},'lockme.test'),$lockStatusID,'race.bannon',$tr),0,"False returned when race condition is simulated");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep5();
+
+#Test with a second set of options, verify that no-match and type filtering works
+delete $opts->{'match'};
+$opts->{'case-types'} = ['Other'];
+is(TestRail::Utils::Lock::pickAndLockTest($opts,$tr),'sortalockme.test',"Test which is here but the other type is locked when ommitting match");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep6();
+
+is(TestRail::Utils::Lock::pickAndLockTest($opts,$tr),'dontlockme_alsonothere.test',"Test which is not here but the other type is locked when omitting match");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep7();
+
+is(TestRail::Utils::Lock::pickAndLockTest($opts,$tr),undef,"No tests are locked, as they are not the right type");
+
+#Make sure we only grab retest/untested
+delete $opts->{'case-types'};
+is(TestRail::Utils::Lock::pickAndLockTest($opts,$tr),'dontlockme_nothere.test',"Wrong type test which is not here gets locked after we remove all restrictions");
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep8();
+
+is(TestRail::Utils::Lock::pickAndLockTest($opts,$tr),undef,"No tests are locked, as none are untested or retest");

+ 0 - 0
t/lock_data/lockme.test


+ 0 - 0
t/lock_data/lockmealso.test


+ 0 - 0
t/lock_data/lockmetoo.test


+ 0 - 0
t/lock_data/sortalockme.test


+ 12 - 0
t/testrail-lock.t

@@ -0,0 +1,12 @@
+use strict;
+use warnings;
+
+use Test::More "tests" => 2;
+
+#VERY rudimentray checking
+my @args = ($^X,qw{bin/testrail-lock --help});
+my $out = `@args`;
+is($? >> 8, 0, "Can get help output OK");
+chomp $out;
+like($out,qr/useful to lock the test/,"Help Output looks as expected");
+

+ 2 - 2
t/testrail-tests.t

@@ -63,7 +63,7 @@ like($out,qr/skipall\.test$/,"Gets test correctly when filtering by assignment")
 
 @args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" --mock --config "testConfig" --assignedto billy});
 $out = `@args`;
-is($? >> 8, 0, "Exit code OK when filtering by assignement");
+is($? >> 8, 0, "Exit code OK when filtering by assignment");
 chomp $out;
 is($out,"","Gets no tests correctly when filtering by wrong assignment");
 
@@ -93,7 +93,7 @@ is($? >> 8, 0, "Exit code OK asking for help");
 like($out,qr/encoding of arguments/i,"Help output OK");
 
 #Verify no-match and match are mutually exclusive
-@args = ($^X,qw{bin/testrail-tests --no-match t/ --match t/qa });
+@args = ($^X,qw{bin/testrail-tests --no-match t/ --match t/qa --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -r "TestingSuite" --mock});
 $out = `@args`;
 isnt($? >> 8, 0, "Exit code not OK asking for mutually exclusive match options");
 like($out,qr/mutually exclusive/i,"Death message OK");