Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.400
diff -u -p -r1.400 form.inc
--- includes/form.inc	16 Nov 2009 05:11:01 -0000	1.400
+++ includes/form.inc	16 Nov 2009 23:59:07 -0000
@@ -426,6 +426,10 @@ function drupal_form_submit($form_id, &$
   // Merge in default values.
   $form_state += form_state_defaults();
 
+  // Reset form validation.
+  $form_state['must_validate'] = TRUE;
+  form_clear_error();
+
   drupal_prepare_form($form_id, $form, $form_state);
   drupal_process_form($form_id, $form, $form_state);
 }
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.24
diff -u -p -r1.24 form.test
--- modules/simpletest/tests/form.test	15 Nov 2009 21:36:06 -0000	1.24
+++ modules/simpletest/tests/form.test	17 Nov 2009 00:00:15 -0000
@@ -354,6 +354,60 @@ class FormsElementsTableSelectFunctional
 }
 
 /**
+ * Test the programmatic form submit behavior.
+ */
+class FormsProgrammaticSubmitFunctionalTest extends DrupalWebTestCase {
+
+  function getInfo() {
+    return array(
+      'name' => t('Programmatically submitted forms test'),
+      'description' => t('Test the programmatic form submit behavior.'),
+      'group' => t('Form API'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('form_test');
+  }
+
+  /**
+   * Test multiple programmatic form submits.
+   */
+  function testMultipleSubmit() {
+    // Backup the current batch status and reset it to avoid conflicts while 
+    // processing the dummy form submit handler.
+    $current_batch = $batch =& batch_get();
+    $batch = array();
+
+    $this->submitDummyForm();
+    $this->submitDummyForm('test 1');
+    $this->submitDummyForm();
+    $this->submitDummyForm('test 2');
+
+    // Restore the current batch status.
+    $batch = $current_batch;
+  }
+
+  /**
+   * Helper function used to programmatically submit the dummy form defined in 
+   * form_test.module with the given value.
+   *
+   * @param string $value
+   *   The dummyfield submitted value.
+   */
+  private function submitDummyForm($value = NULL) {
+    $form_state = array('values' => array('dummyfield' => $value));
+    drupal_form_submit('_form_test_dummy_form', $form_state);
+    $errors = form_get_errors();
+    $valid_form = empty($errors);
+    $result = empty($value) ? !$valid_form : $valid_form;
+    $args = array('%value' => $value, '%errors' => $valid_form ? '' : implode(' ', $errors));
+    $this->assertTrue($result, t('Dummyfield value: %value<br/>Error: %errors', $args));
+    $this->assertTrue(!$valid_form || $form_state['dummy_submit'] == $value, t('Form correctly submitted'));
+  }
+}
+
+/**
  * Test using drupal_form_submit in a batch.
  */
 class FormAPITestCase extends DrupalWebTestCase {
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.14
diff -u -p -r1.14 form_test.module
--- modules/simpletest/tests/form_test.module	15 Nov 2009 21:36:06 -0000	1.14
+++ modules/simpletest/tests/form_test.module	16 Nov 2009 23:59:07 -0000
@@ -212,6 +212,34 @@ function _form_test_tableselect_js_selec
 }
 
 /**
+ * Dummy form used to test programmatic form submits.
+ */
+function _form_test_dummy_form($form_state) {
+  return array(
+    'dummyfield' => array(
+      '#title' => 'Dummyfield',
+      '#type' => 'textfield'
+    )
+  );
+}
+
+/**
+ * To test the validation handler the dummy value is explicitly required here.
+ */
+function _form_test_dummy_form_validate($form, &$form_state) {
+  if (empty($form_state['values']['dummyfield'])) {
+    form_set_error('dummyfield', t('This field is required although dummy.'));
+  }
+}
+
+/**
+ * Process the submitted dummy value.
+ */
+function _form_test_dummy_form_submit($form, &$form_state) {
+  $form_state['dummy_submit'] = $form_state['values']['dummyfield'];
+}
+
+/**
  * Page callback for the batch/drupal_form_submit interaction test.
  *
  * When called without any arguments we set up a batch that calls
