Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.427
diff -u -p -r1.427 form.inc
--- includes/form.inc	25 Jan 2010 10:38:34 -0000	1.427
+++ includes/form.inc	27 Jan 2010 21:29:40 -0000
@@ -1130,10 +1130,15 @@ function form_set_error($name = NULL, $m
       }
     }
     if ($record) {
-      $form[$name] = $message;
       if ($message) {
         drupal_set_message($message, 'error');
       }
+      else {
+        // If the message is empty, save a default message. This is needed for
+        // _form_set_class() which tests whether the returned value is empty.
+        $message = t('Error in @name field.', array('@name' => $name));
+      }
+      $form[$name] = $message;
     }
   }
 
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.33
diff -u -p -r1.33 form.test
--- modules/simpletest/tests/form.test	8 Jan 2010 06:36:34 -0000	1.33
+++ modules/simpletest/tests/form.test	27 Jan 2010 21:30:05 -0000
@@ -784,3 +784,49 @@ class FormsRebuildTestCase extends Drupa
     $this->assertFieldById('edit-text-2', 'DEFAULT 2', t('A newly added textfield was initialized with its default value.'));
   }
 }
+
+/**
+ * Test error class handling.
+ */
+class FormsErrorClassTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Form element error class',
+      'description' => 'Tests that form elements get an error class when form_set_error() is called with an empty message.',
+      'group' => 'Form API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('form_test');
+  }
+
+  /**
+   * Tests if the error class is applied to all three texfields on a form.
+   */
+  function testErrorClasses() {
+    $edit = array();
+    $this->drupalPost('form-test/error-classes', $edit, t('Submit'));
+    $this->assertFieldByXPath('//input[@name="title1" and contains(@class,"error")]', "DEFAULT", 'Error class added to title1.');
+    $this->assertFieldByXPath('//input[@name="title2" and contains(@class,"error")]', "DEFAULT", 'Error class added to title2.');
+    $this->assertFieldByXPath('//input[@name="title3" and contains(@class,"error")]', "DEFAULT", 'Error class added to title3.');
+    $this->assertFieldByXPath('//input[@name="tree[trunk]" and contains(@class,"error")]', "", 'Error class added to tree[trunk].');
+    $this->assertNoText('form_test_error_class success.', t('The form failed validation.'));
+
+    $edit['title3'] = $edit['title2'] = $edit['title1'] = $edit['tree[trunk]'] = $this->randomName();
+    $this->drupalPost('form-test/error-classes', $edit, t('Submit'));
+    $this->assertFieldByXPath('//input[@name="title1" and contains(@class,"error")]', $edit['title1'], 'Error class added to title1.');
+    $this->assertFieldByXPath('//input[@name="title2" and contains(@class,"error")]', $edit['title2'], 'Error class added to title2.');
+    $this->assertFieldByXPath('//input[@name="title3" and contains(@class,"error")]', $edit['title3'], 'Error class added to title3.');
+    $this->assertNoText('form_test_error_class success.', t('The form failed validation.'));
+
+    $edit['title2'] = $edit['title1'] . $this->randomName();
+    $edit['title3'] = $edit['title2'] . $this->randomName();
+    $this->drupalPost('form-test/error-classes', $edit, t('Submit'));
+    $this->assertNoFieldByXPath('//input[@name="title1" and contains(@class,"error")]', $edit['title1'], 'Error class not added to title1.');
+    $this->assertNoFieldByXPath('//input[@name="title2" and contains(@class,"error")]', $edit['title2'], 'Error class not added to title2.');
+    $this->assertNoFieldByXPath('//input[@name="title3" and contains(@class,"error")]', $edit['title3'], 'Error class not added to title3.');
+    $this->assertNoFieldByXPath('//input[@name="tree[trunk]" and contains(@class,"error")]', $edit['tree[trunk]'], 'Error class not added to tree[trunk].');
+    $this->assertText('form_test_error_class success.', t('The form passed validation.'));
+  }
+}
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.26
diff -u -p -r1.26 form_test.module
--- modules/simpletest/tests/form_test.module	8 Jan 2010 06:36:34 -0000	1.26
+++ modules/simpletest/tests/form_test.module	27 Jan 2010 21:30:07 -0000
@@ -118,6 +118,14 @@ function form_test_menu() {
     'type' => MENU_CALLBACK,
   );
 
+  $items['form-test/error-classes'] = array(
+    'title' => 'Form error class test',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('form_test_error_class'),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
+
   return $items;
 }
 
@@ -889,3 +897,73 @@ function form_test_form_form_test_state_
     $form_state['cache'] = TRUE;
   }
 }
+
+/**
+ * Form constructor for testing error classes.
+ */
+function form_test_error_class($form, &$form_state) {
+  // Three textfeilds with the same default value.
+  $form['title1'] = array(
+    '#type' => 'textfield',
+    '#title' => 'title1',
+    '#default_value' => 'DEFAULT',
+    '#required' => TRUE,
+  );
+  $form['title2'] = array(
+    '#type' => 'textfield',
+    '#title' => 'title2',
+    '#default_value' => 'DEFAULT',
+    '#required' => TRUE,
+  );
+  $form['title3'] = array(
+    '#type' => 'textfield',
+    '#title' => 'title3',
+    '#default_value' => 'DEFAULT',
+    '#required' => TRUE,
+  );
+  $form['tree'] = array(
+    '#tree' => TRUE,
+  );
+  $form['tree']['trunk'] = array(
+    '#type' => 'textfield',
+    '#title' => 'trunk',
+    '#default_value' => '',
+    '#element_validate' => array('form_test_error_class_tree_validate'),
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+  );
+  return $form;
+}
+
+/**
+ * Form validation handler which requires all title values to be unique.
+ */
+function form_test_error_class_validate($form, &$form_state) {
+  $values[] = $form_state['values']['title1'];
+  $values[] = $form_state['values']['title3'];
+  $values[] = $form_state['values']['title2'];
+  $unique = array_unique($values);
+  if (count($unique) < count($values)) {
+    form_set_error('title1', 'Fields must have unique values');
+    form_set_error('title2');
+    form_set_error('title3');
+  }
+}
+
+/**
+ * Element validation handler which requires the element value to be not empty.
+ */
+function form_test_error_class_tree_validate($element, &$form_state) {
+  if (empty($element['#value'])) {
+    form_error($element);
+  }
+}
+
+/**
+ * Form submit handler that just sets a message.
+ */
+function form_test_error_class_submit($form, &$form_state) {
+  drupal_set_message('form_test_error_class success.');
+}
