commit 6d75122d5386f5dffe476e7ac307af6de9b818c5
Author: Francesco Placella <plach.git@psegno.it>
Date:   Fri Jul 3 19:28:05 2015 +0100

    Added test coverage.

diff --git a/core/modules/system/src/Tests/Entity/EntityFormTest.php b/core/modules/system/src/Tests/Entity/EntityFormTest.php
index f268dd7..0851035 100644
--- a/core/modules/system/src/Tests/Entity/EntityFormTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFormTest.php
@@ -149,4 +149,25 @@ protected function loadEntityByName($entity_type, $name) {
     $entities = $entity_storage->loadByProperties(array('name' => $name));
     return $entities ? current($entities) : NULL;
   }
+
+  /**
+   * Checks that validation handlers works as expected.
+   */
+  public function testValidationHandlers() {
+    /** @var \Drupal\Core\State\StateInterface $state */
+    $state = $this->container->get('state');
+
+    // Check that from-level validation handlers can be defined and can alter
+    // the form array.
+    $state->set('entity_test.form.validate.test', 'form-level');
+    $this->drupalPostForm('entity_test/add', [], 'Save');
+    $this->assertTrue($state->get('entity_test.form.validate.result'), 'Form-level validation handlers behave correctly.');
+
+    // Check that defining a button-level validation handler causes an exception
+    // to be thrown.
+    $state->set('entity_test.form.validate.test', 'button-level');
+    $this->drupalPostForm('entity_test/add', [], 'Save');
+    $this->assertEqual($state->get('entity_test.form.save.exception'), 'LogicException: Entity validation was skipped.', 'Button-level validation handlers behave correctly.');
+  }
+
 }
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index dd44c1f..90afa9a 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -260,6 +260,37 @@ function entity_test_entity_extra_field_info() {
 /**
  * Implements hook_form_BASE_FORM_ID_alter().
  */
+function entity_test_form_entity_test_form_alter(&$form) {
+  switch (\Drupal::state()->get('entity_test.form.validate.test')) {
+    case 'form-level':
+      $form['#validate'][] = 'entity_test_form_entity_test_form_validate';
+      $form['#validate'][] = 'entity_test_form_entity_test_form_validate_check';
+      break;
+
+    case 'button-level':
+      $form['actions']['submit']['#validate'][] = 'entity_test_form_entity_test_form_validate';
+  }
+}
+
+/**
+ * Validation handler for the entity_test entity form.
+ */
+function entity_test_form_entity_test_form_validate(array &$form, FormStateInterface $form_state) {
+  $form['#entity_test_form_validate'] = TRUE;
+}
+
+/**
+ * Validation handler for the entity_test entity form.
+ */
+function entity_test_form_entity_test_form_validate_check(array &$form, FormStateInterface $form_state) {
+  if (!empty($form['#entity_test_form_validate'])) {
+    \Drupal::state()->set('entity_test.form.validate.result', TRUE);
+  }
+}
+
+/**
+ * Implements hook_form_BASE_FORM_ID_alter().
+ */
 function entity_test_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
   $langcode = $form_state->getFormObject()->getFormLangcode($form_state);
   \Drupal::state()->set('entity_test.form_langcode', $langcode);
diff --git a/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php b/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php
index e679585..f1c99bc 100644
--- a/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php
+++ b/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php
@@ -51,37 +51,42 @@ public function form(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function save(array $form, FormStateInterface $form_state) {
-    $entity = $this->entity;
+    try {
+      $entity = $this->entity;
 
-    // Save as a new revision if requested to do so.
-    if (!$form_state->isValueEmpty('revision')) {
-      $entity->setNewRevision();
-    }
+      // Save as a new revision if requested to do so.
+      if (!$form_state->isValueEmpty('revision')) {
+        $entity->setNewRevision();
+      }
 
-    $is_new = $entity->isNew();
+      $is_new = $entity->isNew();
 
-    // Make sure we do not skip the parent's entity save logic.
-    parent::save($form, $form_state);
+      // Make sure we do not skip the parent's entity save logic.
+      parent::save($form, $form_state);
 
-    if ($is_new) {
-     $message = t('%entity_type @id has been created.', array('@id' => $entity->id(), '%entity_type' => $entity->getEntityTypeId()));
-    }
-    else {
-      $message = t('%entity_type @id has been updated.', array('@id' => $entity->id(), '%entity_type' => $entity->getEntityTypeId()));
-    }
-    drupal_set_message($message);
+      if ($is_new) {
+        $message = t('%entity_type @id has been created.', array('@id' => $entity->id(), '%entity_type' => $entity->getEntityTypeId()));
+      }
+      else {
+        $message = t('%entity_type @id has been updated.', array('@id' => $entity->id(), '%entity_type' => $entity->getEntityTypeId()));
+      }
+      drupal_set_message($message);
 
-    if ($entity->id()) {
-      $entity_type = $entity->getEntityTypeId();
-      $form_state->setRedirect(
-        "entity.$entity_type.edit_form",
-        array($entity_type => $entity->id())
-      );
+      if ($entity->id()) {
+        $entity_type = $entity->getEntityTypeId();
+        $form_state->setRedirect(
+          "entity.$entity_type.edit_form",
+          array($entity_type => $entity->id())
+        );
+      }
+      else {
+        // Error on save.
+        drupal_set_message(t('The entity could not be saved.'), 'error');
+        $form_state->setRebuild();
+      }
     }
-    else {
-      // Error on save.
-      drupal_set_message(t('The entity could not be saved.'), 'error');
-      $form_state->setRebuild();
+    catch (\Exception $e) {
+      \Drupal::state()->set('entity_test.form.save.exception', get_class($e) . ': ' . $e->getMessage());
     }
   }
 
