Index: includes/batch.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/batch.inc,v retrieving revision 1.50 diff -u -p -r1.50 batch.inc --- includes/batch.inc 17 Feb 2010 22:44:51 -0000 1.50 +++ includes/batch.inc 22 Apr 2010 21:06:14 -0000 @@ -203,7 +203,7 @@ function _batch_progress_page_nojs() { // Perform actual processing. list($percentage, $message) = _batch_process($batch); - if ($percentage == 100) { + if ($percentage >= 100) { $new_op = 'finished'; } @@ -285,7 +285,7 @@ function _batch_process() { ); call_user_func_array($function, array_merge($args, array(&$batch_context))); - if ($finished == 1) { + if ($finished >= 1) { // Make sure this step is not counted twice when computing $current. $finished = 0; // Remove the processed operation and clear the sandbox. Index: modules/simpletest/tests/batch.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/batch.test,v retrieving revision 1.8 diff -u -p -r1.8 batch.test --- modules/simpletest/tests/batch.test 8 Jan 2010 06:36:34 -0000 1.8 +++ modules/simpletest/tests/batch.test 22 Apr 2010 21:06:14 -0000 @@ -139,6 +139,19 @@ class BatchProcessingTestCase extends Dr } /** + * Test batches that return $context['finished'] > 1 do in fact complete. + * see http://drupal.org/node/600836 + */ + function testBatchLargePercentage() { + // Displaying the page triggers batch 5. + $this->drupalGet('batch_test/large_percentage'); + $this->assertBatchMessages($this->_resultMessages(1), t('Batch for step 2 performed successfully.')); + $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_5'), t('Execution order was correct.')); + $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.')); + } + + + /** * Will trigger a pass if the texts were found in order in the raw content. * * @param $texts @@ -196,6 +209,12 @@ class BatchProcessingTestCase extends Dr } $stack = array_merge($stack, $this->_resultStack('batch_2')); break; + + case 'batch_5': + for ($i = 1; $i <= 10; $i++) { + $stack[] = "op 5 id $i"; + } + break; case 'chained': $stack[] = 'submit handler 1'; @@ -241,6 +260,10 @@ class BatchProcessingTestCase extends Dr $messages[] = 'results for batch 4
op 1: processed 10 elements'; $messages = array_merge($messages, $this->_resultMessages('batch_2')); break; + + case 'batch_5': + $messages[] = 'results for batch 5
op 1: processed 10 elements. $context[\'finished\'] > 1 returned from batch process, with success.'; + break; case 'chained': $messages = array_merge($messages, $this->_resultMessages('batch_1')); Index: modules/simpletest/tests/batch_test.callbacks.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/batch_test.callbacks.inc,v retrieving revision 1.1 diff -u -p -r1.1 batch_test.callbacks.inc --- modules/simpletest/tests/batch_test.callbacks.inc 8 Jan 2010 06:36:34 -0000 1.1 +++ modules/simpletest/tests/batch_test.callbacks.inc 22 Apr 2010 21:06:14 -0000 @@ -52,6 +52,20 @@ function _batch_test_callback_2($start, } /** + * Simple batch operation. + */ +function _batch_test_callback_5($id, $sleep, &$context) { + // No-op, but ensure the batch take a couple iterations. + usleep($sleep); + // Track execution, and store some result for post-processing in the + // 'finished' callback. + batch_test_stack("op 5 id $id"); + $context['results'][5][] = $id; + // this test is to test finished > 1 + $context['finished'] = 3.14; +} + +/** * Batch operation setting up its own batch. */ function _batch_test_nested_batch_callback() { @@ -116,3 +130,10 @@ function _batch_test_finished_3($success function _batch_test_finished_4($success, $results, $operations) { _batch_test_finished_helper(4, $success, $results, $operations); } + +/** + * 'finished' callback for batch 5. + */ +function _batch_test_finished_5($success, $results, $operations) { + _batch_test_finished_helper(5, $success, $results, $operations); +} Index: modules/simpletest/tests/batch_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/batch_test.module,v retrieving revision 1.1 diff -u -p -r1.1 batch_test.module --- modules/simpletest/tests/batch_test.module 8 Jan 2010 06:36:34 -0000 1.1 +++ modules/simpletest/tests/batch_test.module 22 Apr 2010 21:06:14 -0000 @@ -59,13 +59,21 @@ function batch_test_menu() { 'type' => MENU_LOCAL_TASK, 'weight' => 4, ); + // No form: fire a batch; return > 100% complete + $items['batch_test/large_percentage'] = array( + 'title' => 'Simple page with batch over 100% complete', + 'page callback' => 'batch_test_large_percentage', + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + 'weight' => 5, + ); // Tests programmatic form submission within a batch operation. $items['batch_test/nested_programmatic'] = array( 'title' => 'Nested programmatic', 'page callback' => 'batch_test_nested_drupal_form_submit', 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, - 'weight' => 5, + 'weight' => 6, ); // Landing page to test redirects. $items['batch_test/redirect'] = array( @@ -73,7 +81,7 @@ function batch_test_menu() { 'page callback' => 'batch_test_redirect_page', 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, - 'weight' => 6, + 'weight' => 7, ); // // This item lives under 'admin' so that the page uses the admin theme. @@ -311,6 +319,16 @@ function batch_test_no_form() { } /** + * Menu callback: fire a batch process without a form submission. + */ +function batch_test_large_percentage() { + batch_test_stack(NULL, TRUE); + + batch_set(_batch_test_batch_5()); + batch_process('batch_test/redirect'); +} + +/** * Menu callback: successful redirection. */ function batch_test_redirect_page() { @@ -433,6 +451,28 @@ function _batch_test_batch_4() { } /** + * Batch 5: repeats a simple operation. + * + * Operations: op 1 from 1 to 10. + */ +function _batch_test_batch_5() { + // Ensure the batch takes at least two iterations. + $total = 10; + $sleep = (1000000 / $total) * 2; + + $operations = array(); + for ($i = 1; $i <= $total; $i++) { + $operations[] = array('_batch_test_callback_5', array($i, $sleep)); + } + $batch = array( + 'operations' => $operations, + 'finished' => '_batch_test_finished_5', + 'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc', + ); + return $batch; +} + +/** * Menu callback: run a batch for testing theme used on the progress page. */ function batch_test_theme_batch() {