Commit 10244a9d authored by Dries's avatar Dries

- Patch #600836 by tim.cosgrove, dww, naxoc: batch API never terminates if you...

- Patch #600836 by tim.cosgrove, dww, naxoc: batch API never terminates if you set ['finished'] > 1.
parent f45d9a28
......@@ -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.
......
......@@ -27,7 +27,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
*/
function testBatchNoForm() {
// Displaying the page triggers batch 1.
$this->drupalGet('batch_test/no_form');
$this->drupalGet('batch-test/no-form');
$this->assertBatchMessages($this->_resultMessages(1), t('Batch for step 2 performed successfully.'));
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), t('Execution order was correct.'));
$this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
......@@ -39,34 +39,34 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
function testBatchForm() {
// Batch 0: no operation.
$edit = array('batch' => 'batch_0');
$this->drupalPost('batch_test/simple', $edit, 'Submit');
$this->drupalPost('batch-test/simple', $edit, 'Submit');
$this->assertBatchMessages($this->_resultMessages('batch_0'), t('Batch with no operation performed successfully.'));
$this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
// Batch 1: several simple operations.
$edit = array('batch' => 'batch_1');
$this->drupalPost('batch_test/simple', $edit, 'Submit');
$this->drupalPost('batch-test/simple', $edit, 'Submit');
$this->assertBatchMessages($this->_resultMessages('batch_1'), t('Batch with simple operations performed successfully.'));
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), t('Execution order was correct.'));
$this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
// Batch 2: one multistep operation.
$edit = array('batch' => 'batch_2');
$this->drupalPost('batch_test/simple', $edit, 'Submit');
$this->drupalPost('batch-test/simple', $edit, 'Submit');
$this->assertBatchMessages($this->_resultMessages('batch_2'), t('Batch with multistep operation performed successfully.'));
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), t('Execution order was correct.'));
$this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
// Batch 3: simple + multistep combined.
$edit = array('batch' => 'batch_3');
$this->drupalPost('batch_test/simple', $edit, 'Submit');
$this->drupalPost('batch-test/simple', $edit, 'Submit');
$this->assertBatchMessages($this->_resultMessages('batch_3'), t('Batch with simple and multistep operations performed successfully.'));
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_3'), t('Execution order was correct.'));
$this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
// Batch 4: nested batch.
$edit = array('batch' => 'batch_4');
$this->drupalPost('batch_test/simple', $edit, 'Submit');
$this->drupalPost('batch-test/simple', $edit, 'Submit');
$this->assertBatchMessages($this->_resultMessages('batch_4'), t('Nested batch performed successfully.'));
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_4'), t('Execution order was correct.'));
$this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
......@@ -76,7 +76,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
* Test batches defined in a multistep form.
*/
function testBatchFormMultistep() {
$this->drupalGet('batch_test/multistep');
$this->drupalGet('batch-test/multistep');
$this->assertText('step 1', t('Form is displayed in step 1.'));
// First step triggers batch 1.
......@@ -100,7 +100,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
// handlers. Each submit handler modify the submitted 'value'.
$value = rand(0, 255);
$edit = array('value' => $value);
$this->drupalPost('batch_test/chained', $edit, 'Submit');
$this->drupalPost('batch-test/chained', $edit, 'Submit');
// Check that result messages are present and in the correct order.
$this->assertBatchMessages($this->_resultMessages('chained'), t('Batches defined in separate submit handlers performed successfully.'));
// The stack contains execution order of batch callbacks and submit
......@@ -118,7 +118,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
// Batches 1, 2 and 3 are triggered in sequence by different submit
// handlers. Each submit handler modify the submitted 'value'.
$value = rand(0, 255);
$this->drupalGet('batch_test/programmatic/' . $value);
$this->drupalGet('batch-test/programmatic/' . $value);
// Check that result messages are present and in the correct order.
$this->assertBatchMessages($this->_resultMessages('chained'), t('Batches defined in separate submit handlers performed successfully.'));
// The stack contains execution order of batch callbacks and submit
......@@ -134,10 +134,23 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
// Displaying the page triggers a batch that programmatically submits a
// form.
$value = rand(0, 255);
$this->drupalGet('batch_test/nested_programmatic/' . $value);
$this->drupalGet('batch-test/nested-programmatic/' . $value);
$this->assertEqual(batch_test_stack(), array('mock form submitted with value = ' . $value), t('drupal_form_submit() ran successfully within a batch operation.'));
}
/**
* 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.
*
......@@ -197,6 +210,12 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
$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';
$stack[] = 'value = ' . $value;
......@@ -242,6 +261,10 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
$messages = array_merge($messages, $this->_resultMessages('batch_2'));
break;
case 'batch_5':
$messages[] = 'results for batch 5<br />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'));
$messages = array_merge($messages, $this->_resultMessages('batch_2'));
......@@ -280,7 +303,7 @@ class BatchPageTestCase extends DrupalWebTestCase {
// theme that was used during batch execution (which the batch callback
// function saved as a variable) matches the theme used on the
// administrative page.
$this->drupalGet('admin/batch_test/test_theme');
$this->drupalGet('admin/batch-test/test-theme');
// The stack should contain the name of the the used on the progress page.
$this->assertEqual(batch_test_stack(), array('seven'), t('A progressive batch correctly uses the theme of the page that started the batch.'));
}
......
......@@ -12,6 +12,7 @@
*/
function _batch_test_callback_1($id, $sleep, &$context) {
// No-op, but ensure the batch take a couple iterations.
// Batch needs time to run for the test, so sleep a bit.
usleep($sleep);
// Track execution, and store some result for post-processing in the
// 'finished' callback.
......@@ -33,6 +34,7 @@ function _batch_test_callback_2($start, $total, $sleep, &$context) {
$limit = 5;
for ($i = 0; $i < $limit && $context['sandbox']['count'] < $total; $i++) {
// No-op, but ensure the batch take a couple iterations.
// Batch needs time to run for the test, so sleep a bit.
usleep($sleep);
// Track execution, and store some result for post-processing in the
// 'finished' callback.
......@@ -51,6 +53,21 @@ function _batch_test_callback_2($start, $total, $sleep, &$context) {
}
}
/**
* Simple batch operation.
*/
function _batch_test_callback_5($id, $sleep, &$context) {
// No-op, but ensure the batch take a couple iterations.
// Batch needs time to run for the test, so sleep a bit.
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.
*/
......@@ -116,3 +133,10 @@ function _batch_test_finished_3($success, $results, $operations) {
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);
}
......@@ -12,20 +12,20 @@
function batch_test_menu() {
$items = array();
$items['batch_test'] = array(
$items['batch-test'] = array(
'title' => 'Batch test',
'page callback' => 'drupal_get_form',
'page arguments' => array('batch_test_simple_form'),
'access callback' => TRUE,
);
// Simple form: one submit handler, setting a batch.
$items['batch_test/simple'] = array(
$items['batch-test/simple'] = array(
'title' => 'Simple',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
);
// Multistep form: two steps, each setting a batch.
$items['batch_test/multistep'] = array(
$items['batch-test/multistep'] = array(
'title' => 'Multistep',
'page callback' => 'drupal_get_form',
'page arguments' => array('batch_test_multistep_form'),
......@@ -34,7 +34,7 @@ function batch_test_menu() {
'weight' => 1,
);
// Chained form: four submit handlers, several of which set a batch.
$items['batch_test/chained'] = array(
$items['batch-test/chained'] = array(
'title' => 'Chained',
'page callback' => 'drupal_get_form',
'page arguments' => array('batch_test_chained_form'),
......@@ -44,7 +44,7 @@ function batch_test_menu() {
);
// Programmatic form: the page submits the 'Chained' form through
// drupal_form_submit().
$items['batch_test/programmatic'] = array(
$items['batch-test/programmatic'] = array(
'title' => 'Programmatic',
'page callback' => 'batch_test_programmatic',
'access callback' => TRUE,
......@@ -52,32 +52,39 @@ function batch_test_menu() {
'weight' => 3,
);
// No form: fire a batch simply by accessing a page.
$items['batch_test/no_form'] = array(
$items['batch-test/no-form'] = array(
'title' => 'Simple page',
'page callback' => 'batch_test_no_form',
'access callback' => TRUE,
'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(
$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(
$items['batch-test/redirect'] = array(
'title' => 'Redirect',
'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.
$items['admin/batch_test/test_theme'] = array(
$items['admin/batch-test/test-theme'] = array(
'page callback' => 'batch_test_theme_batch',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
......@@ -118,7 +125,7 @@ function batch_test_simple_form_submit($form, &$form_state) {
$function = '_batch_test_' . $form_state['values']['batch'];
batch_set($function());
$form_state['redirect'] = 'batch_test/redirect';
$form_state['redirect'] = 'batch-test/redirect';
}
......@@ -162,7 +169,7 @@ function batch_test_multistep_form_submit($form, &$form_state) {
}
// This will only be effective on the last step.
$form_state['redirect'] = 'batch_test/redirect';
$form_state['redirect'] = 'batch-test/redirect';
}
/**
......@@ -244,7 +251,7 @@ function batch_test_chained_form_submit_4($form, &$form_state) {
batch_set(_batch_test_batch_3());
// This is the redirect that should prevail.
$form_state['redirect'] = 'batch_test/redirect';
$form_state['redirect'] = 'batch-test/redirect';
}
/**
......@@ -267,7 +274,7 @@ function batch_test_nested_drupal_form_submit($value = 1) {
array('_batch_test_nested_drupal_form_submit_callback', array($value)),
);
batch_set($batch);
batch_process('batch_test/redirect');
batch_process('batch-test/redirect');
}
/**
......@@ -307,7 +314,17 @@ function batch_test_no_form() {
batch_test_stack(NULL, TRUE);
batch_set(_batch_test_batch_1());
batch_process('batch_test/redirect');
batch_process('batch-test/redirect');
}
/**
* 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');
}
/**
......@@ -432,6 +449,28 @@ function _batch_test_batch_4() {
return $batch;
}
/**
* 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.
*/
......@@ -443,7 +482,7 @@ function batch_test_theme_batch() {
),
);
batch_set($batch);
batch_process('batch_test/redirect');
batch_process('batch-test/redirect');
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment