diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 82e5241..e31bb87 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -129,6 +129,13 @@
   protected $isDefaultRevision = TRUE;
 
   /**
+   * Indicates whether the revision id should be kept on new revisions.
+   *
+   * @var bool
+   */
+  protected $keepNewRevisionId = FALSE;
+
+  /**
    * Overrides Entity::__construct().
    */
   public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = array()) {
@@ -189,6 +196,17 @@ public function isDefaultRevision($new_value = NULL) {
   /**
    * {@inheritdoc}
    */
+  public function keepNewRevisionId($new_value = NULL) {
+    $return = $this->keepNewRevisionId;
+    if (isset($new_value)) {
+      $this->keepNewRevisionId = $new_value;
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getRevisionId() {
     return NULL;
   }
diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
index eaa4951..d189669 100644
--- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
@@ -736,7 +736,7 @@ protected function saveRevision(EntityInterface $entity) {
 
     // When saving a new revision, set any existing revision ID to NULL so as to
     // ensure that a new revision will actually be created.
-    if ($entity->isNewRevision() && isset($record->{$this->revisionKey})) {
+    if ($entity->isNewRevision() && isset($record->{$this->revisionKey}) && !$entity->keepNewRevisionId()) {
       $record->{$this->revisionKey} = NULL;
     }
 
diff --git a/core/lib/Drupal/Core/Entity/RevisionableInterface.php b/core/lib/Drupal/Core/Entity/RevisionableInterface.php
index d246d24..2f41023 100644
--- a/core/lib/Drupal/Core/Entity/RevisionableInterface.php
+++ b/core/lib/Drupal/Core/Entity/RevisionableInterface.php
@@ -54,6 +54,21 @@ public function getRevisionId();
   public function isDefaultRevision($new_value = NULL);
 
   /**
+   * Checks if this revision is editable.
+   *
+   * Editing revisions is very strongly discouraged.
+   *
+   * @param bool $new_value
+   *   (optional) A Boolean to (re)set the editable flag. DO NOT USE. This is
+   *   solely for migrate to use.
+   *
+   * @return bool
+   *   TRUE if the revision is editable, FALSE otherwise. Defaults to FALSE.
+   *   If $new_value was passed, the previous value is returned.
+   */
+  public function keepNewRevisionId($new_value = NULL);
+
+  /**
    * Acts on a revision before it gets saved.
    *
    * @param EntityStorageControllerInterface $storage_controller
diff --git a/core/modules/migrate/lib/Drupal/migrate/Annotation/MigrateDestination.php b/core/modules/migrate/lib/Drupal/migrate/Annotation/MigrateDestination.php
new file mode 100644
index 0000000..bfeff62
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Annotation/MigrateDestination.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Annotation\MigrateDestination.
+ */
+
+namespace Drupal\migrate\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a migration destination plugin annotation object.
+ *
+ * @Annotation
+ */
+class MigrateDestination extends Plugin {
+
+  /**
+   * A unique identifier for the process plugin.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * Whether requirements are met.
+   *
+   * If TRUE and a 'provider' key is present in the annotation then the
+   * default destination plugin manager will set this to FALSE if the
+   * provider (module/theme) doesn't exist.
+   *
+   * @var bool
+   */
+  public $requirements_met = TRUE;
+
+  /**
+   * A class to make the plugin derivative aware.
+   *
+   * @var string
+   *
+   * @see \Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator
+   */
+  public $derivative;
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Annotation/MigrateSource.php b/core/modules/migrate/lib/Drupal/migrate/Annotation/MigrateSource.php
new file mode 100644
index 0000000..86dd857
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Annotation/MigrateSource.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Annotation\MigrateDestination.
+ */
+
+namespace Drupal\migrate\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a migration destination plugin annotation object.
+ *
+ * @Annotation
+ */
+class MigrateSource extends Plugin {
+
+  /**
+   * A unique identifier for the process plugin.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * Whether requirements are met.
+   *
+   * @var bool
+   */
+  public $requirements_met = TRUE;
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Entity/Migration.php b/core/modules/migrate/lib/Drupal/migrate/Entity/Migration.php
index 3967aec..75c2cc6 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Entity/Migration.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Entity/Migration.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
+use Drupal\migrate\Plugin\RequirementsInterface;
 
 /**
  * Defines the Migration entity.
@@ -22,12 +23,7 @@
  *   label = @Translation("Migration"),
  *   module = "migrate",
  *   controllers = {
- *     "list" = "Drupal\Core\Config\Entity\DraggableListController",
- *     "form" = {
- *       "add" = "Drupal\Core\Entity\EntityFormController",
- *       "edit" = "Drupal\Core\Entity\EntityFormController",
- *       "delete" = "Drupal\Core\Entity\EntityFormController"
- *     }
+ *     "storage" = "Drupal\migrate\MigrationStorageController"
  *   },
  *   entity_keys = {
  *     "id" = "id",
@@ -36,7 +32,7 @@
  *   }
  * )
  */
-class Migration extends ConfigEntityBase implements MigrationInterface {
+class Migration extends ConfigEntityBase implements MigrationInterface, RequirementsInterface {
 
   /**
    * The migration ID (machine name).
@@ -141,7 +137,7 @@ class Migration extends ConfigEntityBase implements MigrationInterface {
    *
    * @var array
    */
-  public $destinationIds = array();
+  public $destinationIds = FALSE;
 
   /**
    * Information on the highwater mark.
@@ -171,16 +167,6 @@ class Migration extends ConfigEntityBase implements MigrationInterface {
   public $sourceRowStatus = MigrateIdMapInterface::STATUS_IMPORTED;
 
   /**
-   * The ratio of the memory limit at which an operation will be interrupted.
-   *
-   * Can be overridden by a Migration subclass if one would like to push the
-   * envelope. Defaults to 0.85.
-   *
-   * @var float
-   */
-  protected $memoryThreshold = 0.85;
-
-  /**
    * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
    */
   protected $highwaterStorage;
@@ -191,21 +177,18 @@ class Migration extends ConfigEntityBase implements MigrationInterface {
   public $trackLastImported = FALSE;
 
   /**
-   * The ratio of the time limit at which an operation will be interrupted.
-   *
-   * Can be overridden by a Migration subclass if one would like to push the
-   * envelope. Defaults to 0.9.
-   *
-   * @var float
-   */
-  public $timeThreshold = 0.90;
-
-  /**
-   * The time limit when executing the migration.
+   * These migrations must be already executed before this migration can run.
    *
    * @var array
    */
-  public $limit = array();
+  protected $requirements = array();
+
+  /**
+   * These migrations, if ran at all, must be executed before this migration.
+   *
+   *@var array
+   */
+  public $dependencies = array();
 
   /**
    * {@inheritdoc}
@@ -301,11 +284,56 @@ protected function getHighWaterStorage() {
     return $this->highwaterStorage;
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function getHighwater() {
     return $this->getHighWaterStorage()->get($this->id());
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function saveHighwater($highwater) {
     $this->getHighWaterStorage()->set($this->id(), $highwater);
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkRequirements() {
+    // Check whether the current migration source and destination plugin
+    // requirements are met or not.
+    try {
+      if ($this->getSourcePlugin() instanceof RequirementsInterface && !$this->getSourcePlugin()->checkRequirements()) {
+        return FALSE;
+      }
+      if ($this->getDestinationPlugin() instanceof RequirementsInterface && !$this->getDestinationPlugin()->checkRequirements()) {
+        return FALSE;
+      }
+
+      /** @var \Drupal\migrate\Entity\MigrationInterface[] $required_migrations */
+      $required_migrations = entity_load_multiple('migration', $this->requirements);
+      // Check if the dependencies are in good shape.
+      foreach ($required_migrations as $required_migration) {
+        // If the dependent source migration has no IDs then no mappings can
+        // be recorded thus it is impossible to see whether the migration ran.
+        if (!$required_migration->getSourcePlugin()->getIds()) {
+          return FALSE;
+        }
+
+        // If the dependent migration has not processed any record, it means the
+        // dependency requirements are not met.
+        if (!$required_migration->getIdMap()->processedCount()) {
+          return FALSE;
+        }
+      }
+    }
+    catch (\Exception $e) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Entity/MigrationInterface.php b/core/modules/migrate/lib/Drupal/migrate/Entity/MigrationInterface.php
index 4999cdf..732291f 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Entity/MigrationInterface.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Entity/MigrationInterface.php
@@ -84,10 +84,17 @@ public function getDestinationPlugin();
   public function getIdMap();
 
   /**
+   * The current value of the highwater mark.
+   *
    * @return int
    */
   public function getHighwater();
 
+  /**
+   * Save the highwater mark.
+   *
+   * @return int
+   */
   public function saveHighwater($highwater);
 
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrateBuildDependencyInterface.php b/core/modules/migrate/lib/Drupal/migrate/MigrateBuildDependencyInterface.php
new file mode 100644
index 0000000..e06c95c
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrateBuildDependencyInterface.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\migrate\MigrateBuildDependencyInterface.
+ */
+
+namespace Drupal\migrate;
+
+
+interface MigrateBuildDependencyInterface {
+
+  /**
+   * Builds a dependency tree for the migrations and set their order.
+   *
+   * @param \Drupal\migrate\Entity\MigrationInterface[] $migrations
+   *   Array of loaded migrations with their declared dependencies.
+   * @param array $dynamic_ids
+   *   Keys are dynamic ids (for example node:*) values are a list of loaded
+   *   migration ids (for example node:page, node:article).
+   *
+   * @return array
+   */
+  public function buildDependencyMigration(array $migrations, array $dynamic_ids);
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrateException.php b/core/modules/migrate/lib/Drupal/migrate/MigrateException.php
index d07c04f..48334bf 100644
--- a/core/modules/migrate/lib/Drupal/migrate/MigrateException.php
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrateException.php
@@ -48,7 +48,7 @@ class MigrateException extends \Exception {
    *   The status of the item for the map table, a MigrateMap::STATUS_*
    *   constant.
    */
-  public function __construct($message = null, $code = 0, \Exception $previous = null, $level = MigrationInterface::MESSAGE_ERROR, $status = MigrateIdMapInterface::STATUS_FAILED) {
+  public function __construct($message = NULL, $code = 0, \Exception $previous = NULL, $level = MigrationInterface::MESSAGE_ERROR, $status = MigrateIdMapInterface::STATUS_FAILED) {
     $this->level = $level;
     $this->status = $status;
     parent::__construct($message);
@@ -58,6 +58,7 @@ public function __construct($message = null, $code = 0, \Exception $previous = n
    * Gets the level.
    *
    * @return int
+   *   An integer status code. @see Migration::MESSAGE_*
    */
   public function getLevel() {
     return $this->level;
@@ -67,6 +68,7 @@ public function getLevel() {
    * Gets the status of the current item.
    *
    * @return int
+   *   An integer status code. @see MigrateMap::STATUS_*
    */
   public function getStatus() {
     return $this->status;
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrateExecutable.php b/core/modules/migrate/lib/Drupal/migrate/MigrateExecutable.php
index 104f187..73974d7 100644
--- a/core/modules/migrate/lib/Drupal/migrate/MigrateExecutable.php
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrateExecutable.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\migrate;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Utility\Error;
 use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
@@ -85,6 +86,33 @@ class MigrateExecutable {
   protected $maxExecTime;
 
   /**
+   * The ratio of the memory limit at which an operation will be interrupted.
+   *
+   * Can be overridden by a Migration subclass if one would like to push the
+   * envelope. Defaults to 0.85.
+   *
+   * @var float
+   */
+  protected $memoryThreshold = 0.85;
+
+  /**
+   * The ratio of the time limit at which an operation will be interrupted.
+   *
+   * Can be overridden by a Migration subclass if one would like to push the
+   * envelope. Defaults to 0.9.
+   *
+   * @var float
+   */
+  public $timeThreshold = 0.90;
+
+  /**
+   * The time limit when executing the migration.
+   *
+   * @var array
+   */
+  public $limit = array();
+
+  /**
    * The configuration values of the source.
    *
    * @var array
@@ -216,9 +244,14 @@ public function getSource() {
    * Performs an import operation - migrate items from source to destination.
    */
   public function import() {
+    // Knock off migration if the requirements haven't been met.
+    if (!$this->migration->checkRequirements()) {
+      $this->message->display(
+        $this->t('Migration @id did not meet the requirements', array('@id' => $this->migration->id())), 'error');
+      return MigrationInterface::RESULT_FAILED;
+    }
     $return = MigrationInterface::RESULT_COMPLETED;
     $source = $this->getSource();
-    $destination = $this->migration->getDestinationPlugin();
     $id_map = $this->migration->getIdMap();
 
     try {
@@ -227,10 +260,12 @@ public function import() {
     catch (\Exception $e) {
       $this->message->display(
         $this->t('Migration failed with source plugin exception: !e',
-          array('!e' => $e->getMessage())));
+          array('!e' => $e->getMessage())), 'error');
       return MigrationInterface::RESULT_FAILED;
     }
 
+    $destination = $this->migration->getDestinationPlugin();
+
     while ($source->valid()) {
       $row = $source->current();
       if ($this->sourceIdValues = $row->getSourceIdValues()) {
@@ -250,11 +285,12 @@ public function import() {
 
       if ($save) {
         try {
-          $destination_id_values = $destination->import($row);
-          // @todo Handle the successful but no ID case like config,
-          //   https://drupal.org/node/2160835.
+          $destination_id_values = $destination->import($row, $id_map->lookupDestinationId($this->sourceIdValues));
           if ($destination_id_values) {
-            $id_map->saveIdMapping($row, $destination_id_values, $this->sourceRowStatus, $this->rollbackAction);
+            // We do not save an idMap entry for config.
+            if ($destination_id_values !== TRUE) {
+              $id_map->saveIdMapping($row, $destination_id_values, $this->sourceRowStatus, $this->rollbackAction);
+            }
             $this->successesSinceFeedback++;
             $this->totalSuccesses++;
           }
@@ -270,7 +306,7 @@ public function import() {
         catch (MigrateException $e) {
           $this->migration->getIdMap()->saveIdMapping($row, array(), $e->getStatus(), $this->rollbackAction);
           $this->saveMessage($e->getMessage(), $e->getLevel());
-          $this->message->display($e->getMessage());
+          $this->message->display($e->getMessage(), 'error');
         }
         catch (\Exception $e) {
           $this->migration->getIdMap()->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_FAILED, $this->rollbackAction);
@@ -299,7 +335,7 @@ public function import() {
       catch (\Exception $e) {
         $this->message->display(
           $this->t('Migration failed with source plugin exception: !e',
-            array('!e' => $e->getMessage())));
+            array('!e' => $e->getMessage())), 'error');
         return MigrationInterface::RESULT_FAILED;
       }
     }
@@ -345,13 +381,27 @@ public function processRow(Row $row, array $process = NULL, $value = NULL) {
           if (!is_array($value)) {
             throw new MigrateException(sprintf('Pipeline failed for destination %s: %s got instead of an array,', $destination, $value));
           }
+          $break = FALSE;
           foreach ($value as $scalar_value) {
-            $new_value[] = $plugin->transform($scalar_value, $this, $row, $destination);
+            try {
+              $new_value[] = $plugin->transform($scalar_value, $this, $row, $destination);
+            }
+            catch (MigrateSkipProcessException $e) {
+              $break = TRUE;
+            }
           }
           $value = $new_value;
+          if ($break) {
+            break;
+          }
         }
         else {
-          $value = $plugin->transform($value, $this, $row, $destination);
+          try {
+            $value = $plugin->transform($value, $this, $row, $destination);
+          }
+          catch (MigrateSkipProcessException $e) {
+            break;
+          }
           $multiple = $multiple || $plugin->multiple();
         }
       }
@@ -402,7 +452,7 @@ protected function timeOptionExceeded() {
    *   The time limit, NULL if no limit or if the units were not in seconds.
    */
   public function getTimeLimit() {
-    $limit = $this->migration->get('limit');
+    $limit = $this->limit;
     if (isset($limit['unit']) && isset($limit['value']) && ($limit['unit'] == 'seconds' || $limit['unit'] == 'second')) {
       return $limit['value'];
     }
@@ -488,7 +538,7 @@ protected function checkStatus() {
   protected function memoryExceeded() {
     $usage = $this->getMemoryUsage();
     $pct_memory = $usage / $this->memoryLimit;
-    if (!$threshold = $this->migration->get('memoryThreshold')) {
+    if (!$threshold = $this->memoryThreshold) {
       return FALSE;
     }
     if ($pct_memory > $threshold) {
@@ -570,7 +620,7 @@ protected function formatSize($size) {
    *   TRUE if the threshold is exceeded, FALSE if not.
    */
   protected function maxExecTimeExceeded() {
-    return $this->maxExecTime && (($this->getTimeElapsed() / $this->maxExecTime) > $this->migration->get('timeThreshold'));
+    return $this->maxExecTime && (($this->getTimeElapsed() / $this->maxExecTime) > $this->timeThreshold);
   }
 
   /**
@@ -599,7 +649,7 @@ public function handleException(\Exception $exception, $save = TRUE) {
     if ($save) {
       $this->saveMessage($message);
     }
-    $this->message->display($message);
+    $this->message->display($message, 'error');
   }
 
   /**
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrateMessage.php b/core/modules/migrate/lib/Drupal/migrate/MigrateMessage.php
index d90297e..a9c8916 100644
--- a/core/modules/migrate/lib/Drupal/migrate/MigrateMessage.php
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrateMessage.php
@@ -13,15 +13,20 @@
 class MigrateMessage implements MigrateMessageInterface {
 
   /**
-   * Displays a migrate message.
+   * The map between migrate status and watchdog severity.
    *
-   * @param string $message
-   *   The message to display.
-   * @param string $type
-   *   The type of message, for example: status or warning.
+   * @var array
    */
-  function display($message, $type = 'status') {
-    drupal_set_message($message, $type);
+  protected $map = array(
+    'status' => WATCHDOG_INFO,
+    'error' => WATCHDOG_ERROR,
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public function display($message, $type = 'status') {
+    watchdog('migrate', $message, array(), isset($this->map[$type]) ? $this->map[$type] : WATCHDOG_NOTICE);
   }
 
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrateMessageInterface.php b/core/modules/migrate/lib/Drupal/migrate/MigrateMessageInterface.php
index bcf3753..42d6e95 100644
--- a/core/modules/migrate/lib/Drupal/migrate/MigrateMessageInterface.php
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrateMessageInterface.php
@@ -10,10 +10,12 @@
 interface MigrateMessageInterface {
 
   /**
-   * @param $message
-   * @param string $type
+   * Displays a migrate message.
    *
-   * @return mixed
+   * @param string $message
+   *   The message to display.
+   * @param string $type
+   *   The type of message, for example: status or warning.
    */
-  function display($message, $type = 'status');
+  public function display($message, $type = 'status');
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigratePassword.php b/core/modules/migrate/lib/Drupal/migrate/MigratePassword.php
new file mode 100644
index 0000000..fc8ed1c
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/MigratePassword.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\MigratePassword.
+ */
+
+namespace Drupal\migrate;
+
+use Drupal\Core\Password\PasswordInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * Replaces the original 'password' service in order to prefix the MD5 re-hashed
+ * passwords with the 'U' flag. The new salted hash is recreated on first login
+ * similarly to the D6->D7 upgrade path.
+ */
+class MigratePassword implements PasswordInterface {
+
+  /**
+   * The original password service.
+   *
+   * @var \Drupal\Core\Password\PasswordInterface
+   */
+  protected $originalPassword;
+
+  /**
+   * Indicates if MD5 password prefixing is enabled.
+   */
+  protected $enabled = FALSE;
+
+  /**
+   * Builds the replacement password service class.
+   *
+   * @param PasswordInterface $original_password
+   */
+  public function __construct(PasswordInterface $original_password) {
+    $this->originalPassword = $original_password;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function check($password, UserInterface $account) {
+    return $this->originalPassword->check($password, $account);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function userNeedsNewHash(UserInterface $account) {
+    return $this->originalPassword->userNeedsNewHash($account);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hash($password) {
+    $hash = $this->originalPassword->hash($password);
+
+    // Allow prefixing only if the service was asked to prefix. Check also if
+    // the $password pattern is conforming to a MD5 result.
+    if ($this->enabled && preg_match('/^[0-9a-f]{32}$/', $password)) {
+      $hash = 'U' . $hash;
+    }
+
+    return $hash;
+  }
+
+  /**
+   * Enables the MD5 password prefixing.
+   */
+  public function enableMd5Prefixing() {
+    $this->enabled = TRUE;
+  }
+
+  /**
+   * Disables the MD5 password prefixing.
+   */
+  public function disableMd5Prefixing() {
+    $this->enabled = FALSE;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrateServiceProvider.php b/core/modules/migrate/lib/Drupal/migrate/MigrateServiceProvider.php
new file mode 100644
index 0000000..78a60bb
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrateServiceProvider.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\MigrateServiceProvider.
+ */
+
+namespace Drupal\migrate;
+
+use Drupal\Core\DependencyInjection\ServiceModifierInterface;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+
+/**
+ * Swaps the original 'password' service in order to handle password hashing for
+ * user migrations that have passwords hashed to MD5.
+ *
+ * @see \Drupal\migrate\MigratePassword
+ * @see \Drupal\Core\Password\PhpassHashedPassword
+ */
+class MigrateServiceProvider implements ServiceModifierInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function alter(ContainerBuilder $container) {
+    $container->setDefinition('password_original', $container->getDefinition('password'));
+    $container->setDefinition('password', $container->getDefinition('password_migrate'));
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrateSkipProcessException.php b/core/modules/migrate/lib/Drupal/migrate/MigrateSkipProcessException.php
new file mode 100644
index 0000000..0e64292
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrateSkipProcessException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\MigrateSkipProcessException.
+ */
+
+namespace Drupal\migrate;
+
+/**
+ * This exception is thrown when the rest of the process should be skipped.
+ */
+class MigrateSkipProcessException extends \Exception {
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/MigrationStorageController.php b/core/modules/migrate/lib/Drupal/migrate/MigrationStorageController.php
new file mode 100644
index 0000000..1fd07f7
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/MigrationStorageController.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\MigrateStorageController.
+ */
+
+namespace Drupal\migrate;
+
+use Drupal\Component\Graph\Graph;
+use Drupal\Core\Config\Entity\ConfigStorageController;
+
+/**
+ * Storage controller for migration entities.
+ */
+class MigrationStorageController extends ConfigStorageController implements MigrateBuildDependencyInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildDependencyMigration(array $migrations, array $dynamic_ids) {
+    // Dependencies defined in the migration storage controller can be soft
+    // dependencies: if a soft dependency does not run, the current migration
+    // is still OK to go. This is indicated by adding ": false" (without
+    // quotes) after the name of the dependency. Hard dependencies (default)
+    // are called requirements. Both hard and soft dependencies (if run at
+    // all) must run before the current one.
+    $dependency_graph = array();
+    $requirement_graph = array();
+    $different = FALSE;
+    /** @var \Drupal\migrate\Entity\MigrationInterface $migration */
+    foreach ($migrations as $migration) {
+      $id = $migration->id();
+      $requirements[$id] = array();
+      $dependency_graph[$id]['edges'] = array();
+      if (isset($migration->dependencies) && is_array($migration->dependencies)) {
+        foreach ($migration->dependencies as $dependency) {
+          if (is_string($dependency) && !isset($dynamic_ids[$dependency])) {
+            $this->addDependency($requirement_graph, $id, $dependency, $dynamic_ids);
+          }
+          if (is_array($dependency)) {
+            list($dependency_string, $required) = each($dependency);
+            $dependency = $dependency_string;
+            if ($required) {
+              $this->addDependency($requirement_graph, $id, $dependency, $dynamic_ids);
+            }
+            else {
+              $different = TRUE;
+            }
+          }
+          $this->addDependency($dependency_graph, $id, $dependency, $dynamic_ids);
+        }
+      }
+    }
+    $graph_object = new Graph($dependency_graph);
+    $dependency_graph = $graph_object->searchAndSort();
+    if ($different) {
+      $graph_object = new Graph($requirement_graph);
+      $requirement_graph = $graph_object->searchAndSort();
+    }
+    else {
+      $requirement_graph = $dependency_graph;
+    }
+    $weights = array();
+    foreach ($migrations as $migration_id => $migration) {
+      // Populate a weights array to use with array_multisort later.
+      $weights[] = $dependency_graph[$migration_id]['weight'];
+      if (!empty($requirement_graph[$migration_id]['paths'])) {
+        $migration->set('requirements', $requirement_graph[$migration_id]['paths']);
+      }
+    }
+    array_multisort($weights, SORT_DESC, SORT_NUMERIC, $migrations);
+
+    return $migrations;
+  }
+
+  /**
+   * Add one or more dependencies to a graph.
+   *
+   * @param array $graph
+   *   The graph so far.
+   * @param int $id
+   *   The migration id.
+   * @param string $dependency
+   *   The dependency string.
+   * @param array $dynamic_ids
+   *   The dynamic id mapping.
+   */
+  protected function addDependency(array &$graph, $id, $dependency, $dynamic_ids) {
+    $dependencies = isset($dynamic_ids[$dependency]) ? $dynamic_ids[$dependency] : array($dependency);
+    if (!isset($graph[$id]['edges'])) {
+      $graph[$id]['edges'] = array();
+    }
+    $graph[$id]['edges'] += array_combine($dependencies, $dependencies);
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/Derivative/MigrateEntity.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/Derivative/MigrateEntity.php
new file mode 100644
index 0000000..df2c142
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/Derivative/MigrateEntity.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\Derivative\MigrateEntity.
+ */
+
+namespace Drupal\migrate\Plugin\Derivative;
+
+use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+class MigrateEntity implements ContainerDerivativeInterface {
+
+  /**
+   * List of derivative definitions.
+   *
+   * @var array
+   */
+  protected $derivatives = array();
+
+  /**
+   * The entity definitions
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface[]
+   */
+  protected $entityDefinitions;
+
+  /**
+   * Constructs a MigrateEntity object.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_definitions
+   *   A list of entity definition objects.
+   */
+  public function __construct(array $entity_definitions) {
+    $this->entityDefinitions = $entity_definitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $container->get('entity.manager')->getDefinitions()
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinition($derivative_id, array $base_plugin_definition) {
+    if (!empty($this->derivatives) && !empty($this->derivatives[$derivative_id])) {
+      return $this->derivatives[$derivative_id];
+    }
+    $this->getDerivativeDefinitions($base_plugin_definition);
+    return $this->derivatives[$derivative_id];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions(array $base_plugin_definition) {
+    foreach ($this->entityDefinitions as $entity_type => $entity_info) {
+      $class = is_subclass_of($entity_info->getClass(), 'Drupal\Core\Config\Entity\ConfigEntityInterface') ?
+        'Drupal\migrate\Plugin\migrate\destination\EntityConfigBase' :
+        'Drupal\migrate\Plugin\migrate\destination\EntityContentBase';
+      $this->derivatives[$entity_type] = array(
+        'id' => "entity:$entity_type",
+        'class' => $class,
+        'requirements_met' => 1,
+      );
+    }
+    return $this->derivatives;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/Derivative/MigrateEntityRevision.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/Derivative/MigrateEntityRevision.php
new file mode 100644
index 0000000..ae6395d
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/Derivative/MigrateEntityRevision.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\Derivative\MigrateEntityDerivative.
+ */
+
+namespace Drupal\migrate\Plugin\Derivative;
+
+use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+class MigrateEntityRevision implements ContainerDerivativeInterface {
+
+  /**
+   * List of derivative definitions.
+   *
+   * @var array
+   */
+  protected $derivatives = array();
+
+  /**
+   * The entity definitions
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface[]
+   */
+  protected $entityDefinitions;
+
+  /**
+   * Constructs a MigrateEntity object.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_definitions
+   *   A list of entity definition objects.
+   */
+  public function __construct(array $entity_definitions) {
+    $this->entityDefinitions = $entity_definitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $container->get('entity.manager')->getDefinitions()
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinition($derivative_id, array $base_plugin_definition) {
+    if (!empty($this->derivatives) && !empty($this->derivatives[$derivative_id])) {
+      return $this->derivatives[$derivative_id];
+    }
+    $this->getDerivativeDefinitions($base_plugin_definition);
+    return $this->derivatives[$derivative_id];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions(array $base_plugin_definition) {
+    foreach ($this->entityDefinitions as $entity_type => $entity_info) {
+      if ($entity_info->getKey('revision')) {
+        $this->derivatives[$entity_type] = array(
+          'id' => "entity_revision:$entity_type",
+          'class' => 'Drupal\migrate\Plugin\migrate\destination\EntityRevision',
+          'requirements_met' => 1,
+        );
+      }
+    }
+    return $this->derivatives;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateDestinationInterface.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateDestinationInterface.php
index 97ede97..a2c33f7 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateDestinationInterface.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateDestinationInterface.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\migrate\Entity\Migration;
+use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\migrate\Row;
 
 /**
@@ -18,46 +19,85 @@
 interface MigrateDestinationInterface extends PluginInspectionInterface {
 
   /**
+   * Get the destination ids.
+   *
    * To support MigrateIdMap maps, derived destination classes should return
-   * schema field definition(s) corresponding to the primary key of the destination
-   * being implemented. These are used to construct the destination key fields
-   * of the map table for a migration using this destination.
+   * schema field definition(s) corresponding to the primary key of the
+   * destination being implemented. These are used to construct the destination
+   * key fields of the map table for a migration using this destination.
+   *
+   * @return array
+   *   An array of ids.
    */
-  public function getIdsSchema();
+  public function getIds();
 
   /**
+   * Returns an array of destination fields.
+   *
    * Derived classes must implement fields(), returning a list of available
    * destination fields.
    *
-   * @todo Review the cases where we need the Migration parameter, can we avoid that?
+   * @todo Review the cases where we need the Migration parameter,
+   * can we avoid that?
+   *
+   * @param \Drupal\migrate\Entity\MigrationInterface $migration
+   *   (optional) the migration containing this destination.
    *
-   * @param Migration $migration
-   *   Optionally, the migration containing this destination.
    * @return array
-   *  - Keys: machine names of the fields
-   *  - Values: Human-friendly descriptions of the fields.
+   *   - Keys: machine names of the fields
+   *   - Values: Human-friendly descriptions of the fields.
    */
-  public function fields(Migration $migration = NULL);
+  public function fields(MigrationInterface $migration = NULL);
+
 
   /**
-   * Derived classes may implement preImport() and/or postImport(), to do any
-   * processing they need done before or after looping over all source rows.
-   * Similarly, preRollback() or postRollback() may be implemented.
+   * Allows pre-processing of an import.
+   *
+   * Derived classes may implement preImport() to do any processing they need
+   * done before over all source rows.
    */
   public function preImport();
+
+  /**
+   * Allows pre-processing of a rollback.
+   */
   public function preRollback();
+
+  /**
+   * Allows post-processing of an import.
+   *
+   * Derived classes may implement postImport(), to do any processing they need
+   * done after looping over all source rows.
+   */
   public function postImport();
+
+  /**
+   * Allows post-processing of a rollback.
+   */
   public function postRollback();
 
   /**
-   * Derived classes must implement import(), to construct one new object (pre-populated
-   * using ID mappings in the Migration).
+   * Import the row.
+   *
+   * Derived classes must implement import(), to construct one new object
+   * (pre-populated) using ID mappings in the Migration).
+   *
+   * @param \Drupal\migrate\Row $row
+   *   The row object.
+   * @param array $old_destination_id_values
+   *   The old destination ids.
+   *
+   * @return mixed
+   *   The entity id or an indication of success.
    */
-  public function import(Row $row);
+  public function import(Row $row, array $old_destination_id_values = array());
 
   /**
    * Delete the specified IDs from the target Drupal.
+   *
    * @param array $destination_identifiers
+   *   The destination ids to delete.
    */
   public function rollbackMultiple(array $destination_identifiers);
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateDestinationPluginManager.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateDestinationPluginManager.php
new file mode 100644
index 0000000..d4d581b
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateDestinationPluginManager.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\MigrateDestinationPluginManager.
+ */
+
+
+namespace Drupal\migrate\Plugin;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
+use Drupal\Core\Language\LanguageManager;
+
+class MigrateDestinationPluginManager extends MigratePluginManager {
+
+  /**
+   * The theme handler
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
+   * An associative array where the keys are the enabled modules and themes.
+   *
+   * @var array
+   */
+  protected $providers;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, EntityManagerInterface $entity_manager, $annotation = 'Drupal\migrate\Annotation\MigrateDestination') {
+    parent::__construct($type, $namespaces, $cache_backend, $language_manager, $module_handler, $annotation);
+    $this->themeHandler = $theme_handler;
+    $this->entityManager = $entity_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function processDefinition(&$definition, $plugin_id) {
+    // By setting requirements_met to something in the annotation, this
+    // handling can be skipped.
+    parent::processDefinition($definition, $plugin_id);
+    if ($definition['requirements_met'] === TRUE) {
+      if (substr($plugin_id, 0, 7) == 'entity:' && !$this->entityManager->getDefinition(substr($plugin_id, 7))) {
+        $definition['requirements_met'] = FALSE;
+      }
+      elseif (isset($definition['destination_provider'])) {
+        if (!isset($this->providers)) {
+          $this->providers = $this->moduleHandler->getModuleList();
+          foreach ($this->themeHandler->listInfo() as $theme => $info) {
+            if ($info->status) {
+              $this->providers[$theme] = TRUE;
+            }
+          }
+        }
+        $definition['requirements_met'] = isset($this->providers[$definition['destination_provider']]);
+      }
+    }
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateEntityDestinationFieldInterface.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateEntityDestinationFieldInterface.php
new file mode 100644
index 0000000..6082a21
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateEntityDestinationFieldInterface.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * @file
+ * Contains
+ */
+
+namespace Drupal\migrate\Plugin;
+use Drupal\field\Entity\FieldInstance;
+
+/**
+ * Handle the importing of a specific configurable field type.
+ */
+interface MigrateEntityDestinationFieldInterface {
+
+  /**
+   * Convert an array of values into an array structure fit for entity_create.
+   *
+   * @param \Drupal\field\Entity\FieldInstance $instance
+   *   The field instance. For example, this can be used to check for required.
+   * @param array $values
+   *   The array of values.
+   * @return array|NULL
+   *   This will be set in the $values array passed to entity_create() as the
+   *   value of a configurable field of the type this class handles.
+   */
+  public function import(FieldInstance $instance, array $values = NULL);
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateIdMapInterface.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateIdMapInterface.php
index 4848b99..df392f0 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateIdMapInterface.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateIdMapInterface.php
@@ -18,7 +18,7 @@
  * Migrate ID mappings maintain a relation between source ID and destination ID
  * for audit and rollback purposes.
  */
-interface MigrateIdMapInterface extends PluginInspectionInterface {
+interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
 
   /**
    * Codes reflecting the current status of a map row.
@@ -201,7 +201,7 @@ public function lookupSourceID(array $destination_id_values);
    * Given a (possibly multi-field) source identifier value, return the
    * (possibly multi-field) destination identifier value it is mapped to.
    *
-   * @param array $destination_id_values
+   * @param array $source_id_values
    *   The source identifier values of the record.
    *
    * @return array
@@ -234,8 +234,9 @@ public function setMessage(MigrateMessageInterface $message);
   /**
    * Sets a specified record to be updated, if it exists.
    *
-   * @param $source_id_values
+   * @param array $source_id_values
    *   The source identifier values of the record.
    */
   public function setUpdate(array $source_id_values);
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigratePluginManager.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigratePluginManager.php
index 2fa236d..69b2d4f 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigratePluginManager.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigratePluginManager.php
@@ -8,11 +8,13 @@
 namespace Drupal\migrate\Plugin;
 
 use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Component\Utility\String;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\LanguageManager;
 use Drupal\Core\Plugin\DefaultPluginManager;
 use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateException;
 
 /**
  * Manages migrate plugins.
@@ -54,9 +56,12 @@ public function createInstance($plugin_id, array $configuration = array(), Migra
     $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
     // If the plugin provides a factory method, pass the container to it.
     if (is_subclass_of($plugin_class, 'Drupal\Core\Plugin\ContainerFactoryPluginInterface')) {
-      return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition, $migration);
+      $plugin = $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition, $migration);
     }
-    return new $plugin_class($configuration, $plugin_id, $plugin_definition, $migration);
+    else {
+      $plugin = new $plugin_class($configuration, $plugin_id, $plugin_definition, $migration);
+    }
+    return $plugin;
   }
 
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateProcessPluginManager.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateProcessPluginManager.php
new file mode 100644
index 0000000..aecb5f4
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateProcessPluginManager.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\MigrateProcessPluginManager.
+ */
+
+namespace Drupal\migrate\Plugin;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Language\LanguageManager;
+use Drupal\migrate\Entity\MigrationInterface;
+
+class MigrateProcessPluginManager extends MigratePluginManager {
+
+  /**
+   * Plugin storage.
+   *
+   * @var array
+   */
+  protected $storage;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ModuleHandlerInterface $module_handler, $annotation = 'Drupal\migrate\Annotation\MigrateProcessPlugin') {
+    parent::__construct($type, $namespaces, $cache_backend, $language_manager, $module_handler, $annotation);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createInstance($plugin_id, array $configuration = array(), MigrationInterface $migration = NULL) {
+    $index = serialize($configuration);
+    if (!isset($this->storage[$migration->id()][$plugin_id][$index])) {
+      $this->storage[$migration->id()][$plugin_id][$index] = parent::createInstance($plugin_id, $configuration, $migration);
+    }
+    return $this->storage[$migration->id()][$plugin_id][$index];
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateSourceInterface.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateSourceInterface.php
index 60b59cf..da11d0b 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateSourceInterface.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/MigrateSourceInterface.php
@@ -23,7 +23,6 @@
    */
   public function fields();
 
-
   /**
    * Returns the iterator that will yield the row arrays to be processed.
    *
@@ -38,6 +37,7 @@ public function getIterator();
    * Add additional data to the row.
    *
    * @param \Drupal\Migrate\Row $row
+   *   The row object.
    *
    * @return bool
    *   FALSE if this row needs to be skipped.
@@ -45,4 +45,13 @@ public function getIterator();
   public function prepareRow(Row $row);
 
   public function __toString();
+
+  /**
+   * Get the source ids.
+   *
+   * @return array
+   *   The source ids.
+   */
+  public function getIds();
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/RequirementsInterface.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/RequirementsInterface.php
index ad45be5..8a5d816 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/RequirementsInterface.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/RequirementsInterface.php
@@ -15,7 +15,7 @@
   /**
    * Checks if requirements for this plugin are OK.
    *
-   * @return boolean
+   * @return bool
    *   TRUE if it is possible to use the plugin, FALSE if not.
    */
   public function checkRequirements();
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/SourceEntityInterface.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/SourceEntityInterface.php
new file mode 100644
index 0000000..982ba3d
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/SourceEntityInterface.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @file
+ * Contains
+ */
+
+namespace Drupal\migrate\Plugin;
+
+/**
+ * Interface for sources providing an entity.
+ */
+interface SourceEntityInterface {
+
+  /**
+   * Whether this migration has a bundle migration.
+   *
+   * @return bool
+   *   TRUE when the bundle_migration key is required.
+   */
+  public function bundleMigrationRequired();
+
+  /**
+   * The entity type id (user, node etc).
+   *
+   * This function is used when bundleMigrationRequired() is FALSE.
+   *
+   * @return string
+   *   The entity type id.
+   */
+  public function entityTypeId();
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/ComponentEntityDisplayBase.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/ComponentEntityDisplayBase.php
new file mode 100644
index 0000000..a3bd8d0
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/ComponentEntityDisplayBase.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\ComponentEntityDisplayBase.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Row;
+
+abstract class ComponentEntityDisplayBase extends DestinationBase {
+
+  const MODE_NAME = '';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function import(Row $row, array $old_destination_id_values = array()) {
+    $values = array();
+    // array_intersect_key() won't work because the order is important because
+    // this is also the return value.
+    foreach (array_keys($this->getIds()) as $id) {
+      $values[$id] = $row->getDestinationProperty($id);
+    }
+    $entity = $this->getEntity($values['entity_type'], $values['bundle'], $values[static::MODE_NAME]);
+    if (!$row->getDestinationProperty('hidden')) {
+      $entity
+        ->setComponent($values['field_name'], $row->getDestinationProperty('options') ?: array())
+        ->save();
+    }
+    else {
+      $entity->removeComponent($values['field_name']);
+    }
+    return array_values($values);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['entity_type']['type'] = 'string';
+    $ids['bundle']['type'] = 'string';
+    $ids[static::MODE_NAME]['type'] = 'string';
+    $ids['field_name']['type'] = 'string';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields(MigrationInterface $migration = NULL) {
+    // TODO: Implement fields() method.
+  }
+
+  /**
+   * Get the entity.
+   *
+   * @param string $entity_type
+   *   The entity type to retrieve.
+   * @param string $bundle
+   *   The entity bundle.
+   * @param string $mode
+   *   The display mode.
+   *
+   * @return \Drupal\Core\Entity\Display\EntityDisplayInterface
+   *   The entity display object.
+   */
+  protected abstract function getEntity($entity_type, $bundle, $mode);
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Config.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Config.php
index 36ead84..7f69b31 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Config.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Config.php
@@ -1,13 +1,13 @@
 <?php
 /**
  * @file
- *   Provides Configuration Management destination plugin.
+ * Provides Configuration Management destination plugin.
  */
 
 namespace Drupal\migrate\Plugin\migrate\destination;
 
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\migrate\Entity\Migration;
+use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\Row;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -16,7 +16,9 @@
 /**
  * Persist data to the config system.
  *
- * @PluginID("d8_config")
+ * @MigrateDestination(
+ *   id = "config"
+ * )
  */
 class Config extends DestinationBase implements ContainerFactoryPluginInterface {
 
@@ -28,21 +30,33 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface
   protected $config;
 
   /**
+   * Constructs a Config destination object.
+   *
    * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
    * @param string $plugin_id
+   *   The plugin ID for the plugin instance.
    * @param array $plugin_definition
-   * @param ConfigObject $config
+   *   The plugin implementation definition.
+   * @param \Drupal\migrate\Entity\MigrationInterface $migration
+   *   The migration entity.
+   * @param \Drupal\Core\Config\Config $config
+   *   The configuration object.
    */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, ConfigObject $config) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, ConfigObject $config) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
     $this->config = $config;
   }
 
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
     return new static(
       $configuration,
       $plugin_id,
       $plugin_definition,
+      $migration,
       $container->get('config.factory')->get($configuration['config_name'])
     );
   }
@@ -50,14 +64,19 @@ public static function create(ContainerInterface $container, array $configuratio
   /**
    * {@inheritdoc}
    */
-  public function import(Row $row) {
-    $this->config
-      ->setData($row->getDestination())
-      ->save();
+  public function import(Row $row, array $old_destination_id_values = array()) {
+    foreach ($row->getRawDestination() as $key => $value) {
+      $this->config->set($key, $value);
+    }
+    $this->config->save();
+    return TRUE;
   }
 
   /**
+   * Throw an exception because config can not be rolled back.
+   *
    * @param array $destination_keys
+   *   The array of destination ids to roll back.
    *
    * @throws \Drupal\migrate\MigrateException
    */
@@ -66,22 +85,17 @@ public function rollbackMultiple(array $destination_keys) {
   }
 
   /**
-   * Derived classes must implement fields(), returning a list of available
-   * destination fields.
-   *
-   * @todo Review the cases where we need the Migration parameter, can we avoid that?
-   *
-   * @param Migration $migration
-   *   Optionally, the migration containing this destination.
-   * @return array
-   *  - Keys: machine names of the fields
-   *  - Values: Human-friendly descriptions of the fields.
+   * {@inheritdoc}
    */
-  public function fields(Migration $migration = NULL) {
+  public function fields(MigrationInterface $migration = NULL) {
     // @todo Dynamically fetch fields using Config Schema API.
   }
 
-  public function getIdsSchema() {
-    return array($this->config->getName() => array());
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return array();
   }
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/DestinationBase.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/DestinationBase.php
index 7cdf11b..45e1df4 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/DestinationBase.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/DestinationBase.php
@@ -9,9 +9,42 @@
 namespace Drupal\migrate\Plugin\migrate\destination;
 
 use Drupal\Core\Plugin\PluginBase;
+use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\migrate\Plugin\MigrateDestinationInterface;
+use Drupal\migrate\Plugin\RequirementsInterface;
 
-abstract class DestinationBase extends PluginBase implements MigrateDestinationInterface {
+abstract class DestinationBase extends PluginBase implements MigrateDestinationInterface, RequirementsInterface {
+
+  /**
+   * The migration.
+   *
+   * @var \Drupal\migrate\Entity\MigrationInterface
+   */
+  protected $migration;
+
+  /**
+   * Constructs an entity destination plugin.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param MigrationInterface $migration
+   *   The migration.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->migration = $migration;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkRequirements() {
+    return $this->pluginDefinition['requirements_met'];
+  }
 
   /**
    * Modify the Row before it is imported.
@@ -27,27 +60,46 @@ public function preRollback() {
     // TODO: Implement preRollback() method.
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function postImport() {
     // TODO: Implement postImport() method.
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function postRollback() {
     // TODO: Implement postRollback() method.
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function rollbackMultiple(array $destination_identifiers) {
     // TODO: Implement rollbackMultiple() method.
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function getCreated() {
     // TODO: Implement getCreated() method.
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function getUpdated() {
     // TODO: Implement getUpdated() method.
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function resetStats() {
     // TODO: Implement resetStats() method.
   }
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Entity.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Entity.php
index 97e4121..5e63ef9 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Entity.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/Entity.php
@@ -9,16 +9,17 @@
 
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\field\FieldInfo;
-use Drupal\migrate\Entity\Migration;
-use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\migrate\Row;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * @PluginId("entity")
+ * @MigrateDestination(
+ *   id = "entity",
+ *   derivative = "Drupal\migrate\Plugin\Derivative\MigrateEntity"
+ * )
  */
-class Entity extends DestinationBase implements ContainerFactoryPluginInterface {
+abstract class Entity extends DestinationBase implements ContainerFactoryPluginInterface {
 
   /**
    * The entity storage controller.
@@ -28,57 +29,111 @@ class Entity extends DestinationBase implements ContainerFactoryPluginInterface
   protected $storageController;
 
   /**
-   * Constructs an entity destination plugin.
+   * The list of the bundles of this entity type.
    *
+   * @var array
+   */
+  protected $bundles;
+
+  /**
    * @param array $configuration
    *   A configuration array containing information about the plugin instance.
    * @param string $plugin_id
    *   The plugin_id for the plugin instance.
    * @param array $plugin_definition
    *   The plugin implementation definition.
+   * @param MigrationInterface $migration
+   *   The migration.
    * @param EntityStorageControllerInterface $storage_controller
    *   The storage controller for this entity type.
+   * @param array $bundles
+   *   The list of bundles this entity type has.
    */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityStorageControllerInterface $storage_controller) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageControllerInterface $storage_controller, array $bundles) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
     $this->storageController = $storage_controller;
+    $this->bundles = $bundles;
   }
 
   /**
    * {@inheritdoc}
    */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    $entity_type = static::getEntityType($plugin_id);
     return new static(
       $configuration,
       $plugin_id,
       $plugin_definition,
-      $container->get('entity.manager')->getStorageController($configuration['entity_type'])
+      $migration,
+      $container->get('entity.manager')->getStorageController($entity_type),
+      array_keys($container->get('entity.manager')->getBundleInfo($entity_type))
     );
   }
 
   /**
-   * {@inheritdoc}
+   * Finds the entity type from configuration or plugin id.
+   *
+   * @param $configuration
+   *   The plugin configuration.
+   * @param $plugin_id
+   *   The plugin id.
+   *
+   * @return string
+   *   The entity type.
+   * @throws \Drupal\migrate\MigrateException
    */
-  public function import(Row $row) {
-    // @TODO: add field handling. https://drupal.org/node/2164451
-    // @TODO: add validation https://drupal.org/node/2164457
-    $entity = $this->storageController->create($row->getDestination());
-    $entity->save();
-    return array($entity->id());
+  protected static function getEntityType($plugin_id) {
+    // Remove entity:
+    return substr($plugin_id, 7);
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getIdsSchema() {
-    // TODO: Implement getIdsSchema() method.
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function fields(Migration $migration = NULL) {
+  public function fields(MigrationInterface $migration = NULL) {
     // TODO: Implement fields() method.
   }
 
+  /**
+   * Creates or loads an entity.
+   *
+   * @param Row $row
+   * @param array $old_destination_id_values
+   * @return \Drupal\Core\Entity\EntityInterface
+   */
+  protected function getEntity(Row $row, array $old_destination_id_values) {
+    $entity_id = $old_destination_id_values ? reset($old_destination_id_values) : $row->getDestinationProperty($this->getKey('id'));
+    if (!empty($entity_id) && ($entity = $this->storageController->load($entity_id))) {
+      $this->updateEntity($entity, $row);
+    }
+    else {
+      $values = $row->getDestination();
+      // Stubs might not have the bundle specified.
+      if ($row->stub()) {
+        $bundle_key = $this->getKey('bundle');
+        if ($bundle_key && !isset($values[$bundle_key])) {
+          $values[$bundle_key] = reset($this->bundles);
+        }
+      }
+      $entity = $this->storageController->create($values);
+      $entity->enforceIsNew();
+    }
+    return $entity;
+  }
+
+  /**
+   * Returns a specific entity key.
+   *
+   * @param string $key
+   *   The name of the entity key to return.
+   *
+   * @return string|bool
+   *   The entity key, or FALSE if it does not exist.
+   *
+   * @see \Drupal\Core\Entity\EntityTypeInterface::getKeys()
+   */
+  protected function getKey($key) {
+    return $this->storageController->getEntityType()->getKey($key);
+  }
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityComment.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityComment.php
new file mode 100644
index 0000000..36601d9
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityComment.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityComment.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\KeyValueStore\StateInterface;
+use Drupal\field\FieldInfo;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:comment"
+ * )
+ */
+class EntityComment extends EntityContentBase {
+
+  /**
+   * The state storage object.
+   *
+   * @var \Drupal\Core\KeyValueStore\StateInterface
+   */
+  protected $state;
+
+  /**
+   * Builds an comment entity destination.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param MigrationInterface $migration
+   *   The migration.
+   * @param EntityStorageControllerInterface $storage_controller
+   *   The storage controller for this entity type.
+   * @param array $bundles
+   *   The list of bundles this entity type has.
+   * @param \Drupal\migrate\Plugin\MigratePluginManager $plugin_manager
+   *   The migrate plugin manager.
+   * @param \Drupal\field\FieldInfo $field_info
+   *   The field and instance definitions service.
+   * @param \Drupal\Core\KeyValueStore\StateInterface $state
+   *   The state storage object.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageControllerInterface $storage_controller, array $bundles, MigratePluginManager $plugin_manager, FieldInfo $field_info, StateInterface $state) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage_controller, $bundles, $plugin_manager, $field_info);
+    $this->state = $state;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    $entity_type = static::getEntityType($plugin_id);
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('entity.manager')->getStorageController($entity_type),
+      array_keys($container->get('entity.manager')->getBundleInfo($entity_type)),
+      $container->get('plugin.manager.migrate.entity_field'),
+      $container->get('field.info'),
+      $container->get('state')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function import(Row $row, array $old_destination_id_values = array()) {
+    if (($stub = !$row->getSourceProperty('entity_type')) && ($state = $this->state->get('comment.maintain_entity_statistics', 0))) {
+      $this->state->set('comment.maintain_entity_statistics', 0);
+    }
+    $return = parent::import($row, $old_destination_id_values);
+    if ($stub && $state) {
+      $this->state->set('comment.maintain_entity_statistics', $state);
+    }
+    return $return;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityConfigBase.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityConfigBase.php
new file mode 100644
index 0000000..479e735
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityConfigBase.php
@@ -0,0 +1,117 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityConfigBase.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\migrate\Row;
+
+/**
+ * Class for importing configuration entities.
+ *
+ * This class serves as the import class for most configuration entities.
+ * It can be necessary to provide a specific entity class if the configuration
+ * entity has a compound id (see EntityFieldEntity) or it has specific setter
+ * methods (see EntityDateFormat). When implementing an entity destination for
+ * the latter case, make sure to add a test not only for importing but also
+ * for re-importing (if that is supported).
+ */
+class EntityConfigBase extends Entity {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function import(Row $row, array $old_destination_id_values = array()) {
+    $ids = $this->getIds();
+    $id_key = $this->getKey('id');
+    if (count($ids) > 1) {
+      $id_keys = array_keys($ids);
+      if (!$row->getDestinationProperty($id_key)) {
+        $row->setDestinationProperty($id_key, $this->generateId($row, $id_keys));
+      }
+    }
+    $entity = $this->getEntity($row, $old_destination_id_values);
+    $entity->save();
+    if (count($ids) > 1) {
+      // This can only be a config entity, content entities have their id key
+      // and that's it.
+      $return = array();
+      foreach ($id_keys as $id_key) {
+        $return[] = $entity->get($id_key);
+      }
+      return $return;
+    }
+    return array($entity->id());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $id_key = $this->getKey('id');
+    $ids[$id_key]['type'] = 'string';
+    return $ids;
+  }
+
+
+  /**
+   * Updates an entity with the contents of a row.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity to update.
+   * @param \Drupal\migrate\Row $row
+   *   The row object to update from.
+   */
+  protected function updateEntity(EntityInterface $entity, Row $row) {
+    foreach ($row->getRawDestination() as $property => $value) {
+      $this->updateEntityProperty($entity, explode('.', $property), $value);
+    }
+  }
+
+  /**
+   * Updates a (possible nested) entity property with a value.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The config entity.
+   * @param array $parents
+   *   The array of parents.
+   * @param string|object $value
+   *   The value to update to.
+   */
+  protected function updateEntityProperty(EntityInterface $entity, array $parents, $value) {
+    $top_key = array_shift($parents);
+    $entity_value = $entity->get($top_key);
+    if (is_array($entity_value)) {
+      NestedArray::setValue($entity_value, $parents, $value);
+    }
+    else {
+      $entity_value = $value;
+    }
+    $entity->set($top_key, $entity_value);
+  }
+
+  /**
+   * Generate an entity id.
+   *
+   * @param Row $row
+   *   The current row.
+   * @param array $ids
+   *   The destination ids.
+   *
+   * @return string
+   *   The generated entity id.
+   */
+  protected function generateId(Row $row, array $ids) {
+    $id_values = array();
+    foreach ($ids as $id) {
+      $id_values[] = $row->getDestinationProperty($id);
+    }
+    return implode('.', $id_values);
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityContentBase.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityContentBase.php
new file mode 100644
index 0000000..8e4d14b
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityContentBase.php
@@ -0,0 +1,143 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityBaseContent.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\field\FieldInfo;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * The destination class for all content entities lacking a specific class.
+ */
+class EntityContentBase extends Entity {
+
+  /**
+   * @var \Drupal\field\FieldInfo
+   */
+  protected $fieldInfo;
+
+  /**
+   * Constructs a content entity.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin ID for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\migrate\Entity\MigrationInterface $migration
+   *   The migration entity.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
+   *   The storage controller for this entity type.
+   * @param array $bundles
+   *   The list of bundles this entity type has.
+   * @param \Drupal\migrate\Plugin\MigratePluginManager $plugin_manager
+   *   The plugin manager.
+   * @param \Drupal\Field\FieldInfo $field_info
+   *   The field info.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageControllerInterface $storage_controller, array $bundles, MigratePluginManager $plugin_manager, FieldInfo $field_info) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage_controller, $bundles);
+    $this->migrateEntityFieldPluginManager = $plugin_manager;
+    $this->fieldInfo = $field_info;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    $entity_type = static::getEntityType($plugin_id);
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('entity.manager')->getStorageController($entity_type),
+      array_keys($container->get('entity.manager')->getBundleInfo($entity_type)),
+      $container->get('plugin.manager.migrate.entity_field'),
+      $container->get('field.info')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function import(Row $row, array $old_destination_id_values = array()) {
+    if ($all_instances = $this->fieldInfo->getInstances($this->storageController->getEntityTypeId())) {
+      /** @var \Drupal\Field\Entity\FieldInstanceConfig [] $instances */
+      $instances = array();
+      if ($bundle_key = $this->getKey('bundle')) {
+        $bundle = $row->getDestinationProperty($bundle_key);
+        if (isset($all_instances[$bundle])) {
+          $instances = $all_instances[$bundle];
+        }
+      }
+      foreach ($instances as $field_name => $instance) {
+        $field_type = $instance->getType();
+        if ($this->migrateEntityFieldPluginManager->getDefinition($field_type)) {
+          $destination_value = $this->migrateEntityFieldPluginManager->createInstance($field_type)->import($instance, $row->getDestinationProperty($field_name));
+          // @TODO: check for NULL return? Add an unset to $row? Maybe needed in
+          // exception handling? Propagate exception?
+          $row->setDestinationProperty($field_name, $destination_value);
+        }
+      }
+    }
+    $entity = $this->getEntity($row, $old_destination_id_values);
+    return $this->save($entity, $old_destination_id_values);
+  }
+
+  /**
+   * Save the entity.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+   *   The content entity.
+   * @param array $old_destination_id_values
+   *   An array of destination id values.
+   *
+   * @return array
+   *   An array containing the entity id.
+   */
+  protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) {
+    $entity->keepNewRevisionId(TRUE);
+    $entity->save();
+    return array($entity->id());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $id_key = $this->getKey('id');
+    $ids[$id_key]['type'] = 'integer';
+    return $ids;
+  }
+
+  /**
+   * Update an entity with the new values from row.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity to update.
+   * @param \Drupal\migrate\Row $row
+   *   The row object to update from.
+   */
+  protected function updateEntity(EntityInterface $entity, Row $row) {
+    foreach ($row->getDestination() as $field_name => $values) {
+      $field = $entity->$field_name;
+      if ($field instanceof TypedDataInterface) {
+        $field->setValue($values);
+      }
+    }
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityDateFormat.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityDateFormat.php
new file mode 100644
index 0000000..5124ab0
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityDateFormat.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityDateFormat.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:date_format"
+ * )
+ */
+class EntityDateFormat extends EntityConfigBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param \Drupal\system\DateFormatInterface $entity
+   *   The date entity.
+   */
+  protected function updateEntityProperty(EntityInterface $entity, array $parents, $value) {
+    if ($parents[0] == 'pattern') {
+      $entity->setPattern($value, $parents[1]);
+    }
+    else {
+      parent::updateEntityProperty($entity, $parents, $value);
+    }
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFieldConfig.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFieldConfig.php
new file mode 100644
index 0000000..8d2c312
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFieldConfig.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityFieldEntity.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:field_config"
+ * )
+ */
+class EntityFieldConfig extends EntityConfigBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['entity_type']['type'] = 'string';
+    $ids['name']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFieldInstance.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFieldInstance.php
new file mode 100644
index 0000000..c02fef5
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFieldInstance.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityFieldInstance.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:field_instance_config"
+ * )
+ */
+class EntityFieldInstance extends EntityConfigBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['entity_type']['type'] = 'string';
+    $ids['bundle']['type'] = 'string';
+    $ids['field_name']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFile.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFile.php
new file mode 100644
index 0000000..4c8a1f1
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityFile.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityFile.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\field\FieldInfo;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:file"
+ * )
+ */
+class EntityFile extends EntityContentBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageControllerInterface $storage_controller, array $bundles, MigratePluginManager $plugin_manager, FieldInfo $field_info) {
+    $configuration += array(
+      'source_base_path' => '',
+      'source_path_property' => 'filepath',
+      'destination_path_property' => 'uri',
+      'move' => FALSE,
+    );
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage_controller, $bundles, $plugin_manager, $field_info);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function import(Row $row, array $old_destination_id_values = array()) {
+    $source = $this->configuration['source_base_path'] . $row->getSourceProperty($this->configuration['source_path_property']);
+    $destination = $row->getDestinationProperty($this->configuration['destination_path_property']);
+    $replace = FILE_EXISTS_REPLACE;
+    if (!empty($this->configuration['rename'])) {
+      $entity_id = $row->getDestinationProperty($this->getKey('id'));
+      if (!empty($entity_id) && ($entity = $this->storageController->load($entity_id))) {
+        $replace = FILE_EXISTS_RENAME;
+      }
+    }
+    $dirname = drupal_dirname($destination);
+    file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);
+    if ($this->configuration['move']) {
+      file_unmanaged_move($source, $destination, $replace);
+    }
+    else {
+      file_unmanaged_copy($source, $destination, $replace);
+    }
+    return parent::import($row, $old_destination_id_values);
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityRevision.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityRevision.php
new file mode 100644
index 0000000..1efef0f
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityRevision.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityRevision.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity_revision",
+ *   derivative = "Drupal\migrate\Plugin\Derivative\MigrateEntityRevision"
+ * )
+ */
+class EntityRevision extends EntityContentBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static function getEntityType($plugin_id) {
+    // Remove entity_revision:
+    return substr($plugin_id, 16);
+  }
+
+  /**
+   * Get the entity.
+   *
+   * @param \Drupal\migrate\Row $row
+   *   The row object.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface|false
+   *   The entity or false if it can not be created.
+   */
+  protected function getEntity(Row $row, array $old_destination_id_values) {
+    $revision_id = $old_destination_id_values ? reset($old_destination_id_values) : $row->getDestinationProperty($this->getKey('revision'));
+    if (!empty($revision_id) && ($entity = $this->storageController->loadRevision($revision_id))) {
+      $entity->setNewRevision(FALSE);
+    }
+    else {
+      $entity_id = $row->getDestinationProperty($this->getKey('id'));
+      $entity = $this->storageController->load($entity_id);
+      $entity->enforceIsNew(FALSE);
+      $entity->setNewRevision(TRUE);
+      $entity->keepNewRevisionId(TRUE);
+    }
+    $this->updateEntity($entity, $row);
+    $entity->isDefaultRevision(FALSE);
+    return $entity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) {
+    $entity->save();
+    return array($entity->getRevisionId());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    if ($key = $this->getKey('revision')) {
+      $ids[$key]['type'] = 'integer';
+      return $ids;
+    }
+    throw new MigrateException('This entity type does not support revisions.');
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntitySearchPage.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntitySearchPage.php
new file mode 100644
index 0000000..0e623ef
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntitySearchPage.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntitySearchPage.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:search_page"
+ * )
+ */
+class EntitySearchPage extends EntityConfigBase {
+
+  /**
+   * Updates the entity with the contents of a row.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The search page entity.
+   * @param \Drupal\migrate\Row $row
+   *   The row object to update from.
+   */
+  protected function updateEntity(EntityInterface $entity, Row $row) {
+    $entity->setPlugin($row->getDestinationProperty('plugin'));
+    $entity->getPlugin()->setConfiguration($row->getDestinationProperty('configuration'));
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityUser.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityUser.php
new file mode 100644
index 0000000..3b3c5b1
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityUser.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityUser.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Password\PasswordInterface;
+use Drupal\field\FieldInfo;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigratePassword;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:user"
+ * )
+ */
+class EntityUser extends EntityContentBase {
+
+  /**
+   * The password service class.
+   *
+   * @var \Drupal\Core\Password\PasswordInterface
+   */
+  protected $password;
+
+  /**
+   * Builds an user entity destination.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param MigrationInterface $migration
+   *   The migration.
+   * @param EntityStorageControllerInterface $storage_controller
+   *   The storage controller for this entity type.
+   * @param array $bundles
+   *   The list of bundles this entity type has.
+   * @param \Drupal\migrate\Plugin\MigratePluginManager $plugin_manager
+   *   The migrate plugin manager.
+   * @param \Drupal\field\FieldInfo $field_info
+   *   The field and instance definitions service.
+   * @param \Drupal\Core\Password\PasswordInterface $password
+   *   The password service.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageControllerInterface $storage_controller, array $bundles, MigratePluginManager $plugin_manager, FieldInfo $field_info, PasswordInterface $password) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage_controller, $bundles, $plugin_manager, $field_info);
+    if (isset($configuration['md5_passwords'])) {
+      $this->password = $password;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    $entity_type = static::getEntityType($plugin_id);
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('entity.manager')->getStorageController($entity_type),
+      array_keys($container->get('entity.manager')->getBundleInfo($entity_type)),
+      $container->get('plugin.manager.migrate.entity_field'),
+      $container->get('field.info'),
+      $container->get('password')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   * @throws \Drupal\migrate\MigrateException
+   */
+  public function import(Row $row, array $old_destination_id_values = array()) {
+    if ($this->password) {
+      if ($this->password instanceof MigratePassword) {
+        $this->password->enableMd5Prefixing();
+      }
+      else {
+        throw new MigrateException('Password service has been altered by another module, aborting.');
+      }
+    }
+    $ids = parent::import($row, $old_destination_id_values);
+    if ($this->password) {
+      $this->password->disableMd5Prefixing();
+    }
+
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityViewMode.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityViewMode.php
new file mode 100644
index 0000000..0887d30
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityViewMode.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\EntityViewMode.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+/**
+ * @MigrateDestination(
+ *   id = "entity:view_mode"
+ * )
+ */
+class EntityViewMode extends EntityConfigBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['targetEntityType']['type'] = 'string';
+    $ids['mode']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/PerComponentEntityDisplay.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/PerComponentEntityDisplay.php
new file mode 100644
index 0000000..953d5ff
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/PerComponentEntityDisplay.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\PerComponentEntityDisplay.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+/**
+ * This class imports one component of an entity display.
+ *
+ * @MigrateDestination(
+ *   id = "component_entity_display"
+ * )
+ */
+class PerComponentEntityDisplay extends ComponentEntityDisplayBase {
+
+  const MODE_NAME = 'view_mode';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntity($entity_type, $bundle, $view_mode) {
+    return entity_get_display($entity_type, $bundle, $view_mode);
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/PerComponentEntityFormDisplay.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/PerComponentEntityFormDisplay.php
new file mode 100644
index 0000000..7ae9d46
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/PerComponentEntityFormDisplay.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\PerComponentEntityFormDisplay.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+/**
+ * This class imports one component of an entity form display.
+ *
+ * @MigrateDestination(
+ *   id = "component_entity_form_display"
+ * )
+ */
+class PerComponentEntityFormDisplay extends ComponentEntityDisplayBase {
+
+  const MODE_NAME = 'form_mode';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntity($entity_type, $bundle, $form_mode) {
+    return entity_get_form_display($entity_type, $bundle, $form_mode);
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/UrlAlias.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/UrlAlias.php
new file mode 100644
index 0000000..e2c1403
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/UrlAlias.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\destination\UrlAlias.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Row;
+use Drupal\Core\Path\Path;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+
+/**
+ * @MigrateDestination(
+ *   id = "url_alias"
+ * )
+ */
+class UrlAlias extends DestinationBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The path crud service.
+   *
+   * @var Path $path
+   */
+  protected $path;
+
+  /**
+   * Constructs an entity destination plugin.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param MigrationInterface $migration
+   *   The migration.
+   * @param \Drupal\Core\Path\Path $path
+   *   The path crud service.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, Path $path) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
+    $this->path = $path;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('path.crud')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function import(Row $row, array $old_destination_id_values = array()) {
+
+    $path = $this->path->save(
+      $row->getDestinationProperty('source'),
+      $row->getDestinationProperty('alias'),
+      $row->getDestinationProperty('langcode'),
+      $old_destination_id_values ? $old_destination_id_values[0] : NULL
+    );
+
+    return array($path['pid']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['pid']['type'] = 'integer';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields(MigrationInterface $migration = NULL) {
+    // TODO: Implement fields() method.
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/id_map/Sql.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/id_map/Sql.php
index fa731ff..b9988e9 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/id_map/Sql.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/id_map/Sql.php
@@ -8,11 +8,12 @@
 namespace Drupal\migrate\Plugin\migrate\id_map;
 
 use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Plugin\PluginBase;
 use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\MigrateMessageInterface;
-use Drupal\migrate\Plugin\migrate\source\SqlBase;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
 use Drupal\migrate\Row;
 
@@ -74,13 +75,11 @@ class Sql extends PluginBase implements MigrateIdMapInterface {
   protected $destinationIdFields;
 
   /**
-   * Stores whether the the tables (map/message) already exist.
-   *
-   * This is determined just once per request/instance of the class.
+   * Whether the plugin is already initialized.
    *
    * @var boolean
    */
-  protected $ensured;
+  protected $initialized;
 
   /**
    * The result.
@@ -90,6 +89,20 @@ class Sql extends PluginBase implements MigrateIdMapInterface {
   protected $result = NULL;
 
   /**
+   * The source identifiers.
+   *
+   * @var array
+   */
+  protected $sourceIds = array();
+
+  /**
+   * The destination identifiers.
+   *
+   * @var array
+   */
+  protected $destinationIds = array();
+
+  /**
    * The current row.
    *
    * @var null
@@ -121,29 +134,41 @@ public function __construct(array $configuration, $plugin_id, array $plugin_defi
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
     $this->migration = $migration;
-    $machine_name = $migration->id();
+  }
 
-    // Default generated table names, limited to 63 characters.
-    $prefixLength = strlen($this->getDatabase()->tablePrefix()) ;
-    $this->mapTableName = 'migrate_map_' . Unicode::strtolower($machine_name);
-    $this->mapTableName = Unicode::substr($this->mapTableName, 0, 63 - $prefixLength);
-    $this->messageTableName = 'migrate_message_' . Unicode::strtolower($machine_name);
-    $this->messageTableName = Unicode::substr($this->messageTableName, 0, 63 - $prefixLength);
-    $this->sourceIds = $migration->get('sourceIds');
-    $this->destinationIds = $migration->get('destinationIds');
+  /**
+   * The source ID fields.
+   *
+   * @return array
+   *   The source ID fields.
+   */
+  protected function sourceIdFields() {
+    if (!isset($this->sourceIdFields)) {
+      // Build the source and destination identifier maps.
+      $this->sourceIdFields = array();
+      $count = 1;
+      foreach ($this->migration->getSourcePlugin()->getIds() as $field => $schema) {
+        $this->sourceIdFields[$field] = 'sourceid' . $count++;
+      }
+    }
+    return $this->sourceIdFields;
+  }
 
-    // Build the source and destination identifier maps.
-    $this->sourceIdFields = array();
-    $count = 1;
-    foreach ($this->sourceIds as $field => $schema) {
-      $this->sourceIdFields[$field] = 'sourceid' . $count++;
+  /**
+   * The destination ID fields.
+   *
+   * @return array
+   *   The destination ID fields.
+   */
+  protected function destinationIdFields() {
+    if (!isset($this->destinationIdFields)) {
+      $this->destinationIdFields = array();
+      $count = 1;
+      foreach ($this->migration->getDestinationPlugin()->getIds() as $field => $schema) {
+        $this->destinationIdFields[$field] = 'destid' . $count++;
+      }
     }
-    $this->destinationIdFields = array();
-    $count = 1;
-    foreach ($this->destinationIds as $field => $schema) {
-      $this->destinationIdFields[$field] = 'destid' . $count++;
-    }
-    $this->ensureTables();
+    return $this->destinationIdFields;
   }
 
   /**
@@ -151,7 +176,8 @@ public function __construct(array $configuration, $plugin_id, array $plugin_defi
    *
    * @return string
    */
-  public function getMapTableName() {
+  public function mapTableName() {
+    $this->init();
     return $this->mapTableName;
   }
 
@@ -160,29 +186,19 @@ public function getMapTableName() {
    *
    * @return string
    */
-  public function getMessageTableName() {
+  public function messageTableName() {
+    $this->init();
     return $this->messageTableName;
   }
 
   /**
-   * Qualifying the map table name with the database name makes cross-db joins
-   * possible. Note that, because prefixes are applied after we do this (i.e.,
-   * it will prefix the string we return), we do not qualify the table if it has
-   * a prefix. This will work fine when the source data is in the default
-   * (prefixed) database (in particular, for simpletest), but not if the primary
-   * query is in an external database.
-   *
    * @return string
    */
   public function getQualifiedMapTableName() {
-    $options = $this->getDatabase()->getConnectionOptions();
-    $prefix = $this->getDatabase()->tablePrefix($this->mapTableName);
-    if ($prefix) {
-      return $this->mapTableName;
-    }
-    else {
-      return $options['database'] . '.' . $this->mapTableName;
-    }
+    $database = $this->getDatabase();
+    $options = $database->getConnectionOptions();
+    $prefix = $database->tablePrefix($this->mapTableName);
+    return $options['database'] . '.' . $prefix . $this->mapTableName;
   }
 
   /**
@@ -192,12 +208,30 @@ public function getQualifiedMapTableName() {
    */
   protected function getDatabase() {
     if (!isset($this->database)) {
-      $this->database = SqlBase::getDatabaseConnection($this->migration->id(), $this->configuration);
+      $this->database = \Drupal::database();
     }
+    $this->init();
     return $this->database;
   }
 
   /**
+   * Initialize the plugin.
+   */
+  protected function init() {
+    if (!$this->initialized) {
+      $this->initialized = TRUE;
+      // Default generated table names, limited to 63 characters.
+      $machine_name = str_replace(':', '__', $this->migration->id());
+      $prefixLength = strlen($this->getDatabase()->tablePrefix()) ;
+      $this->mapTableName = 'migrate_map_' . Unicode::strtolower($machine_name);
+      $this->mapTableName = Unicode::substr($this->mapTableName, 0, 63 - $prefixLength);
+      $this->messageTableName = 'migrate_message_' . Unicode::strtolower($machine_name);
+      $this->messageTableName = Unicode::substr($this->messageTableName, 0, 63 - $prefixLength);
+      $this->ensureTables();
+    }
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function setMessage(MigrateMessageInterface $message) {
@@ -208,133 +242,148 @@ public function setMessage(MigrateMessageInterface $message) {
    * Create the map and message tables if they don't already exist.
    */
   protected function ensureTables() {
-    if (!$this->ensured) {
-      if (!$this->getDatabase()->schema()->tableExists($this->mapTableName)) {
-        // Generate appropriate schema info for the map and message tables,
-        // and map from the source field names to the map/msg field names.
-        $count = 1;
-        $source_id_schema = array();
-        $pks = array();
-        foreach ($this->sourceIds as $field_schema) {
-          $mapkey = 'sourceid' . $count++;
-          $source_id_schema[$mapkey] = $field_schema;
-          $pks[] = $mapkey;
-        }
+    if (!$this->getDatabase()->schema()->tableExists($this->mapTableName)) {
+      // Generate appropriate schema info for the map and message tables,
+      // and map from the source field names to the map/msg field names.
+      $count = 1;
+      $source_id_schema = array();
+      $pks = array();
+      foreach ($this->migration->getSourcePlugin()->getIds() as $id_definition) {
+        $mapkey = 'sourceid' . $count++;
+        $source_id_schema[$mapkey] = $this->getFieldSchema($id_definition);
+        $pks[] = $mapkey;
+      }
 
-        $fields = $source_id_schema;
+      $fields = $source_id_schema;
 
-        // Add destination identifiers to map table.
-        // TODO: How do we discover the destination schema?
-        $count = 1;
-        foreach ($this->destinationIds as $field_schema) {
-          // Allow dest identifier fields to be NULL (for IGNORED/FAILED
-          // cases).
-          $field_schema['not null'] = FALSE;
-          $mapkey = 'destid' . $count++;
-          $fields[$mapkey] = $field_schema;
-        }
-        $fields['source_row_status'] = array(
+      // Add destination identifiers to map table.
+      // TODO: How do we discover the destination schema?
+      $count = 1;
+      foreach ($this->migration->getDestinationPlugin()->getIds() as $id_definition) {
+        // Allow dest identifier fields to be NULL (for IGNORED/FAILED
+        // cases).
+        $mapkey = 'destid' . $count++;
+        $fields[$mapkey] = $this->getFieldSchema($id_definition);
+        $fields[$mapkey]['not null'] = FALSE;
+      }
+      $fields['source_row_status'] = array(
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => MigrateIdMapInterface::STATUS_IMPORTED,
+        'description' => 'Indicates current status of the source row',
+      );
+      $fields['rollback_action'] = array(
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => MigrateIdMapInterface::ROLLBACK_DELETE,
+        'description' => 'Flag indicating what to do for this item on rollback',
+      );
+      $fields['last_imported'] = array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'UNIX timestamp of the last time this row was imported',
+      );
+      $fields['hash'] = array(
+        'type' => 'varchar',
+        'length' => '64',
+        'not null' => FALSE,
+        'description' => 'Hash of source row data, for detecting changes',
+      );
+      $schema = array(
+        'description' => 'Mappings from source identifier value(s) to destination identifier value(s).',
+        'fields' => $fields,
+      );
+      if ($pks) {
+        $schema['primary key'] = $pks;
+      }
+      $this->getDatabase()->schema()->createTable($this->mapTableName, $schema);
+
+      // Now do the message table.
+      $fields = array();
+      $fields['msgid'] = array(
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      );
+      $fields += $source_id_schema;
+
+      $fields['level'] = array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 1,
+      );
+      $fields['message'] = array(
+        'type' => 'text',
+        'size' => 'medium',
+        'not null' => TRUE,
+      );
+      $schema = array(
+        'description' => 'Messages generated during a migration process',
+        'fields' => $fields,
+        'primary key' => array('msgid'),
+      );
+      if ($pks) {
+        $schema['indexes']['sourcekey'] = $pks;
+      }
+      $this->getDatabase()->schema()->createTable($this->messageTableName(), $schema);
+    }
+    else {
+      // Add any missing columns to the map table.
+      if (!$this->getDatabase()->schema()->fieldExists($this->mapTableName,
+                                                    'rollback_action')) {
+        $this->getDatabase()->schema()->addField($this->mapTableName,
+                                              'rollback_action', array(
           'type' => 'int',
           'size' => 'tiny',
           'unsigned' => TRUE,
           'not null' => TRUE,
-          'default' => MigrateIdMapInterface::STATUS_IMPORTED,
-          'description' => 'Indicates current status of the source row',
-        );
-        $fields['rollback_action'] = array(
-          'type' => 'int',
-          'size' => 'tiny',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'default' => MigrateIdMapInterface::ROLLBACK_DELETE,
-          'description' => 'Flag indicating what to do for this item on rollback',
-        );
-        $fields['last_imported'] = array(
-          'type' => 'int',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
           'default' => 0,
-          'description' => 'UNIX timestamp of the last time this row was imported',
-        );
-        $fields['hash'] = array(
+          'description' => 'Flag indicating what to do for this item on rollback',
+        ));
+      }
+      if (!$this->getDatabase()->schema()->fieldExists($this->mapTableName, 'hash')) {
+        $this->getDatabase()->schema()->addField($this->mapTableName, 'hash', array(
           'type' => 'varchar',
           'length' => '64',
           'not null' => FALSE,
           'description' => 'Hash of source row data, for detecting changes',
-        );
-        $schema = array(
-          'description' => 'Mappings from source identifier value(s) to destination identifier value(s).',
-          'fields' => $fields,
-        );
-        if ($pks) {
-          $schema['primary key'] = $pks;
-        }
-        $this->getDatabase()->schema()->createTable($this->mapTableName, $schema);
-
-        // Now do the message table.
-        $fields = array();
-        $fields['msgid'] = array(
-          'type' => 'serial',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-        );
-        $fields += $source_id_schema;
-
-        $fields['level'] = array(
-          'type' => 'int',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'default' => 1,
-        );
-        $fields['message'] = array(
-          'type' => 'text',
-          'size' => 'medium',
-          'not null' => TRUE,
-        );
-        $schema = array(
-          'description' => 'Messages generated during a migration process',
-          'fields' => $fields,
-          'primary key' => array('msgid'),
-        );
-        if ($pks) {
-          $schema['indexes']['sourcekey'] = $pks;
-        }
-        $this->getDatabase()->schema()->createTable($this->messageTableName, $schema);
+        ));
       }
-      else {
-        // Add any missing columns to the map table.
-        if (!$this->getDatabase()->schema()->fieldExists($this->mapTableName,
-                                                      'rollback_action')) {
-          $this->getDatabase()->schema()->addField($this->mapTableName,
-                                                'rollback_action', array(
-            'type' => 'int',
-            'size' => 'tiny',
-            'unsigned' => TRUE,
-            'not null' => TRUE,
-            'default' => 0,
-            'description' => 'Flag indicating what to do for this item on rollback',
-          ));
-        }
-        if (!$this->getDatabase()->schema()->fieldExists($this->mapTableName, 'hash')) {
-          $this->getDatabase()->schema()->addField($this->mapTableName, 'hash', array(
-            'type' => 'varchar',
-            'length' => '64',
-            'not null' => FALSE,
-            'description' => 'Hash of source row data, for detecting changes',
-          ));
-        }
-      }
-      $this->ensured = TRUE;
     }
   }
 
   /**
+   * Create schema from an id definition.
+   *
+   * @param array $id_definition
+   *   A field schema definition. Can be SQL schema or a type data
+   *   based schema. In the latter case, the value of type needs to be
+   *   $typed_data_type.$column
+   * @return array
+   */
+  protected function getFieldSchema(array $id_definition) {
+    $type_parts = explode('.', $id_definition['type']);
+    if (count($type_parts) == 1) {
+      $type_parts[] = 'value';
+    }
+    $schema = FieldDefinition::create($type_parts[0])->getColumns();
+    return $schema[$type_parts[1]];
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function getRowBySource(array $source_id_values) {
-    $query = $this->getDatabase()->select($this->mapTableName, 'map')
+    $query = $this->getDatabase()->select($this->mapTableName(), 'map')
               ->fields('map');
-    foreach ($this->sourceIdFields as $source_id) {
+    foreach ($this->sourceIdFields() as $source_id) {
       $query = $query->condition("map.$source_id", array_shift($source_id_values), '=');
     }
     $result = $query->execute();
@@ -345,9 +394,9 @@ public function getRowBySource(array $source_id_values) {
    * {@inheritdoc}
    */
   public function getRowByDestination(array $destination_id_values) {
-    $query = $this->getDatabase()->select($this->mapTableName, 'map')
+    $query = $this->getDatabase()->select($this->mapTableName(), 'map')
               ->fields('map');
-    foreach ($this->destinationIdFields as $destination_id) {
+    foreach ($this->destinationIdFields() as $destination_id) {
       $query = $query->condition("map.$destination_id", array_shift($destination_id_values), '=');
     }
     $result = $query->execute();
@@ -359,7 +408,7 @@ public function getRowByDestination(array $destination_id_values) {
    */
   public function getRowsNeedingUpdate($count) {
     $rows = array();
-    $result = $this->getDatabase()->select($this->mapTableName, 'map')
+    $result = $this->getDatabase()->select($this->mapTableName(), 'map')
                       ->fields('map')
                       ->condition('source_row_status', MigrateIdMapInterface::STATUS_NEEDS_UPDATE)
                       ->range(0, $count)
@@ -374,9 +423,9 @@ public function getRowsNeedingUpdate($count) {
    * {@inheritdoc}
    */
   public function lookupSourceID(array $destination_id) {
-    $query = $this->getDatabase()->select($this->mapTableName, 'map')
-              ->fields('map', $this->sourceIdFields);
-    foreach ($this->destinationIdFields as $key_name) {
+    $query = $this->getDatabase()->select($this->mapTableName(), 'map')
+              ->fields('map', $this->sourceIdFields());
+    foreach ($this->destinationIdFields() as $key_name) {
       $query = $query->condition("map.$key_name", array_shift($destination_id), '=');
     }
     $result = $query->execute();
@@ -388,9 +437,12 @@ public function lookupSourceID(array $destination_id) {
    * {@inheritdoc}
    */
   public function lookupDestinationId(array $source_id) {
-    $query = $this->getDatabase()->select($this->mapTableName, 'map')
-              ->fields('map', $this->destinationIdFields);
-    foreach ($this->sourceIdFields as $key_name) {
+    if (empty($source_id)) {
+      return array();
+    }
+    $query = $this->getDatabase()->select($this->mapTableName(), 'map')
+              ->fields('map', $this->destinationIdFields());
+    foreach ($this->sourceIdFields() as $key_name) {
       $query = $query->condition("map.$key_name", array_shift($source_id), '=');
     }
     $result = $query->execute();
@@ -406,12 +458,12 @@ public function saveIdMapping(Row $row, array $destination_id_values, $source_ro
     $source_id_values = $row->getSourceIdValues();
     // Construct the source key and initialize to empty variable keys.
     $keys = array();
-    foreach ($this->sourceIdFields as $field_name => $key_name) {
+    foreach ($this->sourceIdFields() as $field_name => $key_name) {
       // A NULL key value will fail.
       if (!isset($source_id_values[$field_name])) {
         $this->message->display(t(
           'Could not save to map table due to NULL value for key field !field',
-          array('!field' => $field_name)));
+          array('!field' => $field_name)), 'error');
         return;
       }
       $keys[$key_name] = $source_id_values[$field_name];
@@ -422,16 +474,20 @@ public function saveIdMapping(Row $row, array $destination_id_values, $source_ro
       'rollback_action' => (int) $rollback_action,
       'hash' => $row->getHash(),
     );
-    $count = 1;
+    $count = 0;
     foreach ($destination_id_values as $dest_id) {
-      $fields['destid' . $count++] = $dest_id;
+      $fields['destid' . ++$count] = $dest_id;
+    }
+    if ($count && $count != count($this->destinationIdFields())) {
+      $this->message->display(t('Could not save to map table due to missing destination id values'), 'error');
+      return;
     }
     if ($this->migration->get('trackLastImported')) {
       $fields['last_imported'] = time();
     }
     if ($keys) {
-      $this->getDatabase()->merge($this->mapTableName)
-        ->keys($keys)
+      $this->getDatabase()->merge($this->mapTableName())
+        ->key($keys)
         ->fields($fields)
         ->execute();
     }
@@ -451,7 +507,7 @@ public function saveMessage(array $source_id_values, $message, $level = Migratio
     }
     $fields['level'] = $level;
     $fields['message'] = $message;
-    $this->getDatabase()->insert($this->messageTableName)
+    $this->getDatabase()->insert($this->messageTableName())
       ->fields($fields)
       ->execute();
   }
@@ -460,7 +516,7 @@ public function saveMessage(array $source_id_values, $message, $level = Migratio
    * {@inheritdoc}
    */
   public function prepareUpdate() {
-    $this->getDatabase()->update($this->mapTableName)
+    $this->getDatabase()->update($this->mapTableName())
     ->fields(array('source_row_status' => MigrateIdMapInterface::STATUS_NEEDS_UPDATE))
     ->execute();
   }
@@ -469,7 +525,7 @@ public function prepareUpdate() {
    * {@inheritdoc}
    */
   public function processedCount() {
-    return $this->getDatabase()->select($this->mapTableName)
+    return $this->getDatabase()->select($this->mapTableName())
       ->countQuery()
       ->execute()
       ->fetchField();
@@ -479,7 +535,7 @@ public function processedCount() {
    * {@inheritdoc}
    */
   public function importedCount() {
-    return $this->getDatabase()->select($this->mapTableName)
+    return $this->getDatabase()->select($this->mapTableName())
       ->condition('source_row_status', array(MigrateIdMapInterface::STATUS_IMPORTED, MigrateIdMapInterface::STATUS_NEEDS_UPDATE), 'IN')
       ->countQuery()
       ->execute()
@@ -504,7 +560,7 @@ public function errorCount() {
    * {@inheritdoc}
    */
   public function messageCount() {
-    return $this->countHelper(NULL, $this->messageTableName);
+    return $this->countHelper(NULL, $this->messageTableName());
   }
 
   /**
@@ -518,7 +574,7 @@ public function messageCount() {
    *   The number of records.
    */
   protected function countHelper($status, $table = NULL) {
-    $query = $this->getDatabase()->select($table ?: $this->mapTableName);
+    $query = $this->getDatabase()->select($table ?: $this->mapTableName());
     if (isset($status)) {
       $query->condition('source_row_status', $status);
     }
@@ -533,9 +589,9 @@ public function delete(array $source_id_values, $messages_only = FALSE) {
       throw new MigrateException('Without source identifier values it is impossible to find the row to delete.');
     }
     if (!$messages_only) {
-      $map_query = $this->getDatabase()->delete($this->mapTableName);
+      $map_query = $this->getDatabase()->delete($this->mapTableName());
     }
-    $message_query = $this->getDatabase()->delete($this->messageTableName);
+    $message_query = $this->getDatabase()->delete($this->messageTableName());
     $count = 1;
     foreach ($source_id_values as $id_value) {
       if (!$messages_only) {
@@ -555,8 +611,8 @@ public function delete(array $source_id_values, $messages_only = FALSE) {
    * {@inheritdoc}
    */
   public function deleteDestination(array $destination_id) {
-    $map_query = $this->getDatabase()->delete($this->mapTableName);
-    $message_query = $this->getDatabase()->delete($this->messageTableName);
+    $map_query = $this->getDatabase()->delete($this->mapTableName());
+    $message_query = $this->getDatabase()->delete($this->messageTableName());
     $source_id = $this->lookupSourceID($destination_id);
     if (!empty($source_id)) {
       $count = 1;
@@ -582,7 +638,7 @@ public function setUpdate(array $source_id) {
       throw new MigrateException('No source identifiers provided to update.');
     }
     $query = $this->getDatabase()
-      ->update($this->mapTableName)
+      ->update($this->mapTableName())
       ->fields(array('source_row_status' => MigrateIdMapInterface::STATUS_NEEDS_UPDATE));
     $count = 1;
     foreach ($source_id as $key_value) {
@@ -596,22 +652,22 @@ public function setUpdate(array $source_id) {
    */
   public function deleteBulk(array $source_id_values) {
     // If we have a single-column key, we can shortcut it.
-    if (count($this->sourceIds) == 1) {
+    if (count($this->migration->getSourcePlugin()->getIds()) == 1) {
       $sourceids = array();
       foreach ($source_id_values as $source_id) {
         $sourceids[] = $source_id;
       }
-      $this->getDatabase()->delete($this->mapTableName)
+      $this->getDatabase()->delete($this->mapTableName())
         ->condition('sourceid1', $sourceids, 'IN')
         ->execute();
-      $this->getDatabase()->delete($this->messageTableName)
+      $this->getDatabase()->delete($this->messageTableName())
         ->condition('sourceid1', $sourceids, 'IN')
         ->execute();
     }
     else {
       foreach ($source_id_values as $source_id) {
-        $map_query = $this->getDatabase()->delete($this->mapTableName);
-        $message_query = $this->getDatabase()->delete($this->messageTableName);
+        $map_query = $this->getDatabase()->delete($this->mapTableName());
+        $message_query = $this->getDatabase()->delete($this->messageTableName());
         $count = 1;
         foreach ($source_id as $key_value) {
           $map_query->condition('sourceid' . $count, $key_value);
@@ -627,15 +683,15 @@ public function deleteBulk(array $source_id_values) {
    * {@inheritdoc}
    */
   public function clearMessages() {
-    $this->getDatabase()->truncate($this->messageTableName)->execute();
+    $this->getDatabase()->truncate($this->messageTableName())->execute();
   }
 
   /**
    * {@inheritdoc}
    */
   public function destroy() {
-    $this->getDatabase()->schema()->dropTable($this->mapTableName);
-    $this->getDatabase()->schema()->dropTable($this->messageTableName);
+    $this->getDatabase()->schema()->dropTable($this->mapTableName());
+    $this->getDatabase()->schema()->dropTable($this->messageTableName());
   }
 
   /**
@@ -648,10 +704,10 @@ public function destroy() {
   public function rewind() {
     $this->currentRow = NULL;
     $fields = array();
-    foreach ($this->sourceIdFields as $field) {
+    foreach ($this->sourceIdFields() as $field) {
       $fields[] = $field;
     }
-    foreach ($this->destinationIdFields as $field) {
+    foreach ($this->destinationIdFields() as $field) {
       $fields[] = $field;
     }
 
@@ -661,7 +717,7 @@ public function rewind() {
       $query = $query->range(0, $this->options['itemlimit']);
     }
     */
-    $this->result = $this->getDatabase()->select($this->mapTableName, 'map')
+    $this->result = $this->getDatabase()->select($this->mapTableName(), 'map')
       ->fields('map', $fields)
       ->execute();
     $this->next();
@@ -697,7 +753,7 @@ public function next() {
     $this->currentRow = $this->result->fetchAssoc();
     $this->currentKey = array();
     if ($this->currentRow) {
-      foreach ($this->sourceIdFields as $map_field) {
+      foreach ($this->sourceIdFields() as $map_field) {
         $this->currentKey[$map_field] = $this->currentRow[$map_field];
         // Leave only destination fields.
         unset($this->currentRow[$map_field]);
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Callback.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Callback.php
new file mode 100644
index 0000000..b1ecd2d
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Callback.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\process\Callback.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * This plugin allows source value to be passed to a callback.
+ *
+ * The current value is passed to a callable that returns the processed value.
+ * This plugin allows simple processing of the value, such as strtolower(). The
+ * callable takes the value as the single mandatory argument. No additional
+ * arguments can be passed to the callback as this would make the migration YAML
+ * file too complex.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "callback"
+ * )
+ */
+class Callback extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (is_callable($this->configuration['callable'])) {
+      $value = call_user_func($this->configuration['callable'], $value);
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Concat.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Concat.php
new file mode 100644
index 0000000..4296057
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Concat.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\process\Concat.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\process;
+
+use Drupal\Component\Utility\String;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Concatenates the strings in the current value.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "concat",
+ *   handle_multiples = TRUE
+ * )
+ */
+class Concat extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Concatenates the strings in the current value.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value)) {
+      $delimiter = isset($this->configuration['delimiter']) ? $this->configuration['delimiter'] : '';
+      return implode($delimiter, $value);
+    }
+    else {
+      throw new MigrateException(sprintf('%s is not an array', String::checkPlain(var_export($value, TRUE))));
+    }
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/DefaultValue.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/DefaultValue.php
index fb4aea0..d129bd9 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/DefaultValue.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/DefaultValue.php
@@ -25,6 +25,9 @@ class DefaultValue extends ProcessPluginBase {
    * {@inheritdoc}
    */
   public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
-    return isset($value) ? $value : $this->configuration['default_value'];
+    if (!empty($this->configuration['strict'])) {
+      return isset($value) ? $value : $this->configuration['default_value'];
+    }
+    return $value ?: $this->configuration['default_value'];
   }
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Migration.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Migration.php
new file mode 100644
index 0000000..0a8e352
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/Migration.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\process\Migration.
+ */
+
+
+namespace Drupal\migrate\Plugin\migrate\process;
+
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Calculates the value of a property based on a previous migration.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "migration"
+ * )
+ */
+class Migration extends ProcessPluginBase implements  ContainerFactoryPluginInterface {
+
+  /**
+   * @var \Drupal\migrate\Plugin\MigratePluginManager
+   */
+  protected $processPluginManager;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $migrationStorageController;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageControllerInterface $storage_controller, MigratePluginManager $process_plugin_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->migrationStorageController = $storage_controller;
+    $this->migration = $migration;
+    $this->processPluginManager = $process_plugin_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('entity.manager')->getStorageController('migration'),
+      $container->get('plugin.manager.migrate.process')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    $migration_ids = $this->configuration['migration'];
+    if (!is_array($migration_ids)) {
+      $migration_ids = array($migration_ids);
+    }
+    $scalar = FALSE;
+    if (!is_array($value)) {
+      $scalar = TRUE;
+      $value = array($value);
+    }
+    $self = FALSE;
+    /** @var \Drupal\migrate\Entity\MigrationInterface[] $migrations */
+    $migrations = $this->migrationStorageController->loadMultiple($migration_ids);
+    $destination_ids = NULL;
+    $source_id_values = array();
+    foreach ($migrations as $migration_id => $migration) {
+      if ($migration_id == $this->migration->id()) {
+        $self = TRUE;
+      }
+      if (isset($this->configuration['source_ids'][$migration_id])) {
+        $configuration = array('source' => $this->configuration['source_ids'][$migration_id]);
+        $source_id_values[$migration_id] = $this->processPluginManager
+          ->createInstance('get', $configuration, $this->migration)
+          ->transform(NULL, $migrate_executable, $row, $destination_property);
+      }
+      else {
+        $source_id_values[$migration_id] = $value;
+      }
+      // Break out of the loop as soon as a destination ID is found.
+      if ($destination_ids = $migration->getIdMap()->lookupDestinationID($source_id_values[$migration_id])) {
+        break;
+      }
+    }
+    if (!$destination_ids && (($self && empty($this->configuration['no stub'])) || isset($this->configuration['stub_id']) || count($migrations) == 1))  {
+      // If the lookup didn't succeed, figure out which migration will do the
+      // stubbing.
+      if ($self) {
+        $migration = $this->migration;
+      }
+      elseif (isset($this->configuration['stub_id'])) {
+        $migration = $migrations[$this->configuration['stub_id']];
+      }
+      else {
+        $migration = reset($migrations);
+      }
+      $destination_plugin = $migration->getDestinationPlugin();
+      // Only keep the process necessary to produce the destination ID.
+      $process = array_intersect_key($migration->get('process'), $destination_plugin->getIds());
+      // We already have the source id values but need to key them for the Row
+      // constructor.
+      $source_ids = $migration->getSourcePlugin()->getIds();
+      $values = array();
+      foreach (array_keys($source_ids) as $index => $source_id) {
+        $values[$source_id] = $source_id_values[$migration->id()][$index];
+      }
+      $stub_row = new Row($values, $source_ids);
+      $stub_row->stub(TRUE);
+      // Do a normal migration with the stub row.
+      $migrate_executable->processRow($stub_row, $process);
+      $destination_ids = $destination_plugin->import($stub_row);
+    }
+    if ($scalar) {
+      if (count($destination_ids) == 1) {
+        return reset($destination_ids);
+      }
+      throw new MigrateException('Migration process plugin failed.');
+    }
+    return $destination_ids;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/SkipProcessOnEmpty.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/SkipProcessOnEmpty.php
new file mode 100644
index 0000000..bb24bf2
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/SkipProcessOnEmpty.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\Process\d6\FlagSkipProcess.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateSkipProcessException;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * If the value evaluates to false, skip further processing.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "skip_process_on_empty"
+ * )
+ */
+class SkipProcessOnEmpty extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Skip the rest of the processing on 0.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (!$value) {
+      throw new MigrateSkipProcessException();
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/SkipRowOnEmpty.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/SkipRowOnEmpty.php
new file mode 100644
index 0000000..156dd33
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/SkipRowOnEmpty.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\process\d6\FlagSkippingRow.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\process;
+
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+use Drupal\migrate\MigrateSkipRowException;
+
+/**
+ * If the source evaluates to empty, we skip the current row.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "skip_row_on_empty"
+ * )
+ */
+class SkipRowOnEmpty extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (!$value) {
+      throw new MigrateSkipRowException();
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/StaticMap.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/StaticMap.php
index e0f2d95..455cb51 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/StaticMap.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/process/StaticMap.php
@@ -39,8 +39,14 @@ public function transform($value, MigrateExecutable $migrate_executable, Row $ro
     }
     $new_value = NestedArray::getValue($this->configuration['map'], $new_value, $key_exists);
     if (!$key_exists) {
+      if (isset($this->configuration['default_value'])) {
+        if (!empty($this->configuration['bypass'])) {
+          throw new MigrateException('Setting both default_value and bypass is invalid.');
+        }
+        return $this->configuration['default_value'];
+      }
       if (empty($this->configuration['bypass'])) {
-        throw new MigrateException('Lookup failed.');
+        throw new MigrateException(sprintf('Lookup of %s failed.', var_export($value, TRUE)));
       }
       else {
         return $value;
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/EmptySource.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/EmptySource.php
new file mode 100644
index 0000000..acd2067
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/EmptySource.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\Constants.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\source;
+
+/**
+ * Source returning an empty row.
+ *
+ * This is generally useful when needing to create a field using a migration..
+ *
+ * @MigrateSource(
+ *   id = "empty"
+ * )
+ */
+class EmptySource extends SourcePluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'id' => t('ID'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIterator() {
+    return new \ArrayIterator(array(array('id' => '')));
+  }
+
+  public function __toString() {
+    return '';
+  }
+
+  public function getIds() {
+    $ids['id']['type'] = 'string';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function count() {
+    return 1;
+  }
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SourcePluginBase.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SourcePluginBase.php
index 0efc013..7b1c92f 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SourcePluginBase.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SourcePluginBase.php
@@ -12,6 +12,9 @@
 use Drupal\migrate\Plugin\MigrateSourceInterface;
 use Drupal\migrate\Row;
 
+/**
+ * The base class for all source plugins.
+ */
 abstract class SourcePluginBase extends PluginBase implements MigrateSourceInterface  {
 
   /**
@@ -27,7 +30,7 @@
   /**
    * {@inheritdoc}
    */
-  function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->migration = $migration;
   }
@@ -46,9 +49,12 @@ protected function getModuleHandler() {
    * {@inheritdoc}
    */
   public function prepareRow(Row $row) {
-    $this->getModuleHandler()->invokeAll('migrate_prepare_row', array($row, $this, $this->migration));
-    $this->getModuleHandler()->invokeAll('migrate_ '. $this->migration->id() . '_prepare_row', array($row, $this, $this->migration));
-    return TRUE;
+    $resultHook = $this->getModuleHandler()->invokeAll('migrate_prepare_row', array($row, $this, $this->migration));
+    $resultNamedHook = $this->getModuleHandler()->invokeAll('migrate_'. $this->migration->id() . '_prepare_row', array($row, $this, $this->migration));
+    // If any of the hooks returned false, we want to skip the row.
+    if (($resultHook && in_array(FALSE, $resultHook)) || ($resultNamedHook && in_array(FALSE, $resultNamedHook))) {
+      return FALSE;
+    }
   }
 
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SqlBase.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SqlBase.php
index 8740f11..d6d2b97 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SqlBase.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/SqlBase.php
@@ -34,15 +34,14 @@
   /**
    * {@inheritdoc}
    */
-  function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
     parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
-    $this->mapJoinable = TRUE;
   }
 
   /**
    * @return \Drupal\Core\Database\Connection
    */
-  function __toString() {
+  public function __toString() {
     return (string) $this->query;
   }
 
@@ -50,50 +49,48 @@ function __toString() {
    * @return \Drupal\Core\Database\Connection
    */
   public function getDatabase() {
-    if  (!isset($this->database)) {
-      $this->database = static::getDatabaseConnection($this->migration->id(), $this->configuration);
+    if (!isset($this->database)) {
+      $this->database = Database::getConnection('default', 'migrate');
     }
     return $this->database;
   }
 
-  public static function getDatabaseConnection($id, array $configuration) {
-    if (isset($configuration['database'])) {
-      $key = 'migrate_' . $id;
-      Database::addConnectionInfo($key, 'default', $configuration['database']);
-    }
-    else {
-      $key = 'default';
-    }
-    return Database::getConnection('default', $key);
-  }
-
+  /**
+   * Wrapper for database select.
+   */
   protected function select($table, $alias = NULL, array $options = array()) {
     $options['fetch'] = \PDO::FETCH_ASSOC;
     return $this->getDatabase()->select($table, $alias, $options);
   }
 
   /**
+   * A helper for adding tags and metadata to the query.
+   *
+   * @return \Drupal\Core\Database\Query\SelectInterface
+   *   The query with additional tags and metadata.
+   */
+  protected function prepareQuery() {
+    $this->query = clone $this->query();
+    $this->query->addTag('migrate');
+    $this->query->addTag('migrate_' . $this->migration->id());
+    $this->query->addMetaData('migration', $this->migration);
+
+    return $this->query;
+  }
+
+  /**
    * Implementation of MigrateSource::performRewind().
    *
    * We could simply execute the query and be functionally correct, but
    * we will take advantage of the PDO-based API to optimize the query up-front.
    */
   protected function runQuery() {
-    $this->query = clone $this->query();
-    $this->query->addTag('migrate');
-    $this->query->addTag('migrate_' . $this->migration->id());
-    $this->query->addMetaData('migration', $this->migration);
+    $this->prepareQuery();
     $highwaterProperty = $this->migration->get('highwaterProperty');
 
     // Get the key values, for potential use in joining to the map table, or
     // enforcing idlist.
     $keys = array();
-    foreach ($this->migration->get('sourceIds') as $field_name => $field_schema) {
-      if (isset($field_schema['alias'])) {
-        $field_name = $field_schema['alias'] . '.' . $field_name;
-      }
-      $keys[] = $field_name;
-    }
 
     // The rules for determining what conditions to add to the query are as
     // follows (applying first applicable rule)
@@ -113,13 +110,13 @@ protected function runQuery() {
       //      OR above highwater).
       $conditions = $this->query->orConditionGroup();
       $condition_added = FALSE;
-      if ($this->mapJoinable) {
+      if ($this->getIds() && ($this->migration->getIdMap() instanceof \Drupal\migrate\Plugin\migrate\id_map\Sql)) {
         // Build the join to the map table. Because the source key could have
         // multiple fields, we need to build things up.
         $count = 1;
         $map_join = '';
         $delimiter = '';
-        foreach ($this->migration->get('sourceIds') as $field_name => $field_schema) {
+        foreach ($this->getIds() as $field_name => $field_schema) {
           if (isset($field_schema['alias'])) {
             $field_name = $field_schema['alias'] . '.' . $field_name;
           }
@@ -133,7 +130,7 @@ protected function runQuery() {
         $condition_added = TRUE;
 
         // And as long as we have the map table, add its data to the row.
-        $n = count($this->migration->get('sourceIds'));
+        $n = count($this->getIds());
         for ($count = 1; $count <= $n; $count++) {
           $map_key = 'sourceid' . $count;
           $this->query->addField($alias, $map_key, "migrate_map_$map_key");
@@ -168,7 +165,7 @@ protected function runQuery() {
   /**
    * @return \Drupal\Core\Database\Query\SelectInterface
    */
-  abstract function query();
+  abstract public function query();
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/d7/Node.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/d7/Node.php
new file mode 100644
index 0000000..9791f61
--- /dev/null
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/source/d7/Node.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d7\Node.
+ */
+
+namespace Drupal\migrate\Plugin\migrate\source\d7;
+
+use Drupal\migrate\Plugin\migrate\source\SqlBase;
+
+/**
+ * Drupal 7 node source.
+ *
+ * @PluginID("drupal7_node")
+ */
+class Node extends SqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->database->select('node', 'n')
+     ->fields('n', array('nid', 'vid', 'language', 'title', 'uid',
+       'status', 'created', 'changed', 'comment', 'promote', 'sticky',
+       'tnid', 'translate'))
+     ->condition('n.type', $this->sourceType)
+     ->orderBy('n.changed');
+
+  }
+
+  public function getCurrentKey() {
+    // TODO: Implement getCurrentKey() method.
+  }
+
+  public function fields() {
+    // TODO: Implement fields() method.
+  }
+
+  public function getIgnored() {
+    // TODO: Implement getIgnored() method.
+  }
+
+  public function getProcessed() {
+    // TODO: Implement getProcessed() method.
+  }
+
+  public function resetStats() {
+    // TODO: Implement resetStats() method.
+  }
+
+  /**
+   * (PHP 5 &gt;= 5.1.0)<br/>
+   * Count elements of an object
+   * @link http://php.net/manual/en/countable.count.php
+   * @return int The custom count as an integer.
+   * </p>
+   * <p>
+   * The return value is cast to an integer.
+   */
+  public function count() {
+    // TODO: Implement count() method.
+  }
+
+
+}
diff --git a/core/modules/migrate/lib/Drupal/migrate/Row.php b/core/modules/migrate/lib/Drupal/migrate/Row.php
index 2a29f61..342b706 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Row.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Row.php
@@ -57,6 +57,27 @@ class Row {
   protected $frozen = FALSE;
 
   /**
+   * The raw destination properties.
+   *
+   * Unlike $destination which is set by using
+   * \Drupal\Component\Utility\NestedArray::setValue() this array contains
+   * the destination as setDestinationProperty was called.
+   *
+   * @var array
+   *   The raw destination.
+   *
+   * @see getRawDestination()
+   */
+  protected $rawDestination;
+
+  /**
+   * TRUE when this row is a stub.
+   *
+   * @var bool
+   */
+  protected $stub = FALSE;
+
+  /**
    * Constructs a \Drupal\Migrate\Row object.
    *
    * @param array $values
@@ -98,7 +119,7 @@ public function getSourceIdValues() {
    *   TRUE if the source has property; FALSE otherwise.
    */
   public function hasSourceProperty($property) {
-    return isset($this->source[$property]) || array_key_exists($property, $this->source);
+    return NestedArray::keyExists($this->source, explode('.', $property));
   }
 
   /**
@@ -111,8 +132,9 @@ public function hasSourceProperty($property) {
    *   The found returned property or NULL if not found.
    */
   public function getSourceProperty($property) {
-    if (isset($this->source[$property])) {
-      return $this->source[$property];
+    $return = NestedArray::getValue($this->source, explode('.', $property), $key_exists);
+    if ($key_exists) {
+      return $return;
     }
   }
 
@@ -143,7 +165,7 @@ public function setSourceProperty($property, $data) {
       throw new \Exception("The source is frozen and can't be changed any more");
     }
     else {
-      $this->source[$property] = $data;
+      NestedArray::setValue($this->source, explode('.', $property), $data, TRUE);
     }
   }
 
@@ -164,7 +186,7 @@ public function freezeSource() {
    *   TRUE if the destination property exists.
    */
   public function hasDestinationProperty($property) {
-    return NestedArray::keyExists($this->destination, explode(':', $property));
+    return NestedArray::keyExists($this->destination, explode('.', $property));
   }
 
   /**
@@ -176,7 +198,8 @@ public function hasDestinationProperty($property) {
    *   The property value to set on the destination.
    */
   public function setDestinationProperty($property, $value) {
-    NestedArray::setValue($this->destination, explode(':', $property), $value, TRUE);
+    $this->rawDestination[$property] = $value;
+    NestedArray::setValue($this->destination, explode('.', $property), $value, TRUE);
   }
 
   /**
@@ -190,16 +213,31 @@ public function getDestination() {
   }
 
   /**
+   * Returns the raw destination. Rarely necessary.
+   *
+   * For example calling setDestination('foo:bar', 'baz') results in
+   * @code
+   * $this->destination['foo']['bar'] = 'baz';
+   * $this->rawDestination['foo.bar'] = 'baz';
+   *
+   * @return array
+   *   The raw destination values.
+   */
+  public function getRawDestination() {
+    return $this->rawDestination;
+  }
+
+  /**
    * Returns the value of a destination property.
    *
-   * @param array|string $property
-   *   An array of properties on the destination.
+   * @param string $property
+   *   The name of a property on the destination.
    *
    * @return mixed
    *  The destination value.
    */
   public function getDestinationProperty($property) {
-    return NestedArray::getValue($this->destination, explode(':', $property));
+    return NestedArray::getValue($this->destination, explode('.', $property));
   }
 
   /**
@@ -261,4 +299,20 @@ public function getHash() {
     return $this->idMap['hash'];
   }
 
+  /**
+   * Flags and reports this row as a stub.
+   *
+   * @param bool|null $new_value
+   *   TRUE when the row is a stub. Omit to determine whether the row is a
+   *   stub.
+   *
+   * @return mixed
+   *   The current stub value.
+   */
+  public function stub($new_value = NULL) {
+    if (isset($new_value)) {
+      $this->stub = $new_value;
+    }
+    return $this->stub;
+  }
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Source.php b/core/modules/migrate/lib/Drupal/migrate/Source.php
index ebec104..629873f 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Source.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Source.php
@@ -121,14 +121,23 @@ class Source implements \Iterator, \Countable {
    */
   protected $highwaterProperty;
 
+  /**
+   * Getter for currentIds data member.
+   */
   public function getCurrentIds() {
     return $this->currentIds;
   }
 
+  /**
+   * Getter for numIgnored data member.
+   */
   public function getIgnored() {
     return $this->numIgnored;
   }
 
+  /**
+   * Getter for numProcessed data member.
+   */
   public function getProcessed() {
     return $this->numProcessed;
   }
@@ -141,11 +150,16 @@ public function resetStats() {
   }
 
   /**
+   * Get the source count.
+   *
    * Return a count of available source records, from the cache if appropriate.
    * Returns -1 if the source is not countable.
    *
-   * @param boolean $refresh
+   * @param bool $refresh
+   *   Whether or not to refresh the count.
+   *
    * @return int
+   *   The count.
    */
   public function count($refresh = FALSE) {
     if ($this->skipCount) {
@@ -167,12 +181,12 @@ public function count($refresh = FALSE) {
       // Caching is in play, first try to retrieve a cached count.
       $cache_object = $this->cache->get($this->cacheKey, 'cache');
       if (is_object($cache_object)) {
-        // Success
+        // Success.
         $count = $cache_object->data;
       }
       else {
         // No cached count, ask the derived class to count 'em up, and cache
-        // the result
+        // the result.
         $count = $source->count();
         $this->cache->set($this->cacheKey, $count, 'cache');
       }
@@ -184,9 +198,11 @@ public function count($refresh = FALSE) {
    * Class constructor.
    *
    * @param \Drupal\migrate\Entity\MigrationInterface $migration
+   *   The migration entity.
    * @param \Drupal\migrate\MigrateExecutable $migrate_executable
+   *   The migration executable.
    */
-  function __construct(MigrationInterface $migration, MigrateExecutable $migrate_executable) {
+  public function __construct(MigrationInterface $migration, MigrateExecutable $migrate_executable) {
     $this->migration = $migration;
     $this->migrateExecutable = $migrate_executable;
     $configuration = $migration->get('source');
@@ -205,7 +221,10 @@ function __construct(MigrationInterface $migration, MigrateExecutable $migrate_e
   }
 
   /**
+   * Get the cache object.
+   *
    * @return \Drupal\Core\Cache\CacheBackendInterface
+   *   The cache object.
    */
   protected function getCache() {
     if (!isset($this->cache)) {
@@ -215,7 +234,10 @@ protected function getCache() {
   }
 
   /**
+   * Get the source iterator.
+   *
    * @return \Iterator
+   *   The source iterator.
    */
   protected function getIterator() {
     if (!isset($this->iterator)) {
@@ -232,23 +254,30 @@ public function current() {
   }
 
   /**
-   * Implementation of Iterator::key - called when entering a loop iteration, returning
-   * the key of the current row. It must be a scalar - we will serialize
-   * to fulfill the requirement, but using getCurrentIds() is preferable.
+   * Get the iterator key.
+   *
+   * Implementation of Iterator::key - called when entering a loop iteration,
+   * returning the key of the current row. It must be a scalar - we will
+   * serialize to fulfill the requirement, but using getCurrentIds() is
+   * preferable.
    */
   public function key() {
     return serialize($this->currentIds);
   }
 
   /**
-   * Implementation of Iterator::valid() - called at the top of the loop, returning
-   * TRUE to process the loop and FALSE to terminate it
+   * Whether the iterator is currently valid.
+   *
+   * Implementation of Iterator::valid() - called at the top of the loop,
+   * returning TRUE to process the loop and FALSE to terminate it
    */
   public function valid() {
     return isset($this->currentRow);
   }
 
   /**
+   * Rewind the iterator.
+   *
    * Implementation of Iterator::rewind() - subclasses of MigrateSource should
    * implement performRewind() to do any class-specific setup for iterating
    * source records.
@@ -272,13 +301,14 @@ public function rewind() {
   public function next() {
     $this->currentIds = NULL;
     $this->currentRow = NULL;
+    $source_configuration = $this->migration->get('source');
 
     while ($this->getIterator()->valid()) {
-      $row_data = $this->getIterator()->current();
+      $row_data = $this->getIterator()->current() + $source_configuration;
       $this->getIterator()->next();
-      $row = new Row($row_data, $this->migration->get('sourceIds'), $this->migration->get('destinationIds'));
+      $row = new Row($row_data, $this->migration->getSourcePlugin()->getIds(), $this->migration->get('destinationIds'));
 
-      // Populate the source key for this row
+      // Populate the source key for this row.
       $this->currentIds = $row->getSourceIdValues();
 
       // Pick up the existing map row, if any, unless getNextRow() did it.
@@ -307,7 +337,7 @@ public function next() {
       }
       // 3. If the row is marked as needing update, pass it.
       elseif ($row->needsUpdate()) {
-        // Fall through
+        // Fall through.
       }
       // 4. At this point, we have a row which has previously been imported and
       //    not marked for update. If we're not using highwater marks, then we
@@ -346,22 +376,22 @@ public function next() {
       // 6. So, we are using highwater marks. Take the row if its highwater
       //    field value is greater than the saved mark, otherwise skip it.
       else {
-        // Call prepareRow() here, in case the highwaterField needs preparation
+        // Call prepareRow() here, in case the highwaterField needs preparation.
         if ($this->prepareRow($row) !== FALSE) {
           if ($row->getSourceProperty($this->highwaterProperty['name']) > $this->originalHighwater) {
             $this->currentRow = $row;
             break;
           }
           else {
-            // Skip
+            // Skip.
             continue;
           }
         }
         $prepared = TRUE;
       }
 
-      // Allow the Migration to prepare this row. prepareRow() can return boolean
-      // FALSE to ignore this row.
+      // Allow the Migration to prepare this row. prepareRow() can return
+      // boolean FALSE to ignore this row.
       if (!$prepared) {
         if ($this->prepareRow($row) !== FALSE) {
           // Finally, we've got a keeper.
@@ -385,10 +415,14 @@ public function next() {
    * Source classes should override this as necessary and manipulate $keep.
    *
    * @param \Drupal\migrate\Row $row
+   *   The row object.
+   *
+   * @return bool
+   *   TRUE if we're to process the row otherwise FALSE.
    */
   protected function prepareRow(Row $row) {
-    // We're explicitly skipping this row - keep track in the map table
-    if ($this->migration->getSourcePlugin()->prepareRow($row) === FALSE) {
+    // We're explicitly skipping this row - keep track in the map table.
+    if (($result = $this->migration->getSourcePlugin()->prepareRow($row)) === FALSE) {
       // Make sure we replace any previous messages for this item with any
       // new ones.
       $id_map = $this->migration->getIdMap();
@@ -409,5 +443,7 @@ protected function prepareRow(Row $row) {
       }
     }
     $this->numProcessed++;
+    return $result;
   }
+
 }
diff --git a/core/modules/migrate/lib/Drupal/migrate/Tests/MigrateTestBase.php b/core/modules/migrate/lib/Drupal/migrate/Tests/MigrateTestBase.php
index b8a5e52..f10320b 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Tests/MigrateTestBase.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Tests/MigrateTestBase.php
@@ -9,10 +9,11 @@
 
 use Drupal\Core\Database\Database;
 use Drupal\migrate\Entity\MigrationInterface;
-use Drupal\migrate\Plugin\migrate\source\SqlBase;
+use Drupal\migrate\MigrateMessageInterface;
+use Drupal\migrate\Row;
 use Drupal\simpletest\WebTestBase;
 
-class MigrateTestBase extends WebTestBase {
+class MigrateTestBase extends WebTestBase implements MigrateMessageInterface {
 
   /**
    * The file path(s) to the dumped database(s) to load into the child site.
@@ -21,29 +22,67 @@ class MigrateTestBase extends WebTestBase {
    */
   public $databaseDumpFiles = array();
 
+
+  /**
+   * TRUE to collect messages instead of displaying them.
+   *
+   * @var bool
+   */
+  protected $collectMessages = FALSE;
+
+  /**
+   * A two dimensional array of messages.
+   *
+   * The first key is the type of message, the second is just numeric. Values
+   * are the messages.
+   *
+   * @var array
+   */
+  protected $migrateMessages;
+
   public static $modules = array('migrate');
 
   /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $connection_info = Database::getConnectionInfo('default');
+    foreach ($connection_info as $target => $value) {
+      $connection_info[$target]['prefix'] = array(
+        // Simpletest uses 7 character prefixes at most so this can't cause
+        // collisions.
+        'default' => $value['prefix']['default'] .'0',
+      );
+    }
+    Database::addConnectionInfo('migrate', 'default', $connection_info['default']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function tearDown() {
+    Database::removeConnection('migrate');
+    parent::tearDown();
+  }
+
+  /**
    * @param MigrationInterface $migration
    * @param array $files
    *
    * @return \Drupal\Core\Database\Connection
    */
   protected function prepare(MigrationInterface $migration, array $files = array()) {
-    $databasePrefix = 'm_';
-    $connection_info = Database::getConnectionInfo('default');
-    foreach ($connection_info as $target => $value) {
-      $connection_info[$target]['prefix'] = array(
-        'default' => $value['prefix']['default'] . $databasePrefix,
-      );
-    }
-    $database = SqlBase::getDatabaseConnection($migration->id(), array('database' => $connection_info['default']));
-    foreach (array('source', 'destination', 'idMap') as $key) {
-      $configuration = $migration->get($key);
-      $configuration['database'] = $database;
-      $migration->set($key, $configuration);
-    }
+    $this->loadDumps($files);
+  }
 
+  /**
+   * Load Drupal 6 database dumps to be used.
+   *
+   * @param string $method
+   *   The name of the method in the dump class to use. Defaults to load.
+   */
+  protected function loadDumps($files, $method = 'load') {
     // Load the database from the portable PHP dump.
     // The files may be gzipped.
     foreach ($files as $file) {
@@ -53,8 +92,56 @@ protected function prepare(MigrationInterface $migration, array $files = array()
       }
       preg_match('/^namespace (.*);$/m', file_get_contents($file), $matches);
       $class = $matches[1] . '\\' . basename($file, '.php');
-      $class::load($database);
+      (new $class(Database::getConnection('default', 'migrate')))->$method();
     }
-    return $database;
   }
+
+  /**
+   * @param array $id_mappings
+   *   A list of id mappings keyed by migration ids. Each id mapping is a list
+   *   of two arrays, the first are source ids and the second are destination
+   *   ids.
+   */
+  protected function prepareIdMappings(array $id_mappings) {
+    /** @var \Drupal\migrate\Entity\MigrationInterface[] $migrations */
+    $migrations = entity_load_multiple('migration', array_keys($id_mappings));
+    foreach ($id_mappings as $migration_id => $data) {
+      $migration = $migrations[$migration_id];
+      $id_map = $migration->getIdMap();
+      $id_map->setMessage($this);
+      $source_ids = $migration->getSourcePlugin()->getIds();
+      foreach ($data as $id_mapping) {
+        $row = new Row(array_combine(array_keys($source_ids), $id_mapping[0]), $source_ids);
+        $id_map->saveIdMapping($row, $id_mapping[1]);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function display($message, $type = 'status') {
+    if ($this->collectMessages) {
+      $this->migrateMessages[$type][] = $message;
+    }
+    else {
+      $this->assert($type == 'status', $message, 'migrate');
+    }
+  }
+
+  /**
+   * Start collecting messages and erase previous messages.
+   */
+  public function startCollectingMessages() {
+    $this->collectMessages = TRUE;
+    $this->migrateMessages = array();
+  }
+
+  /**
+   * Stop collecting messages.
+   */
+  public function stopCollectingMessages() {
+    $this->collectMessages = FALSE;
+  }
+
 }
diff --git a/core/modules/migrate/migrate.api.php b/core/modules/migrate/migrate.api.php
index a2d2cb5..c89614e 100644
--- a/core/modules/migrate/migrate.api.php
+++ b/core/modules/migrate/migrate.api.php
@@ -24,7 +24,7 @@
  * hook_migrate_MIGRATION_ID_prepare_row is also available.
  */
 function hook_migrate_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) {
-  if ($migration->id() == 'drupal6_filter_formats') {
+  if ($migration->id() == 'd6_filter_formats') {
     $value = $source->getDatabase()->query('SELECT value FROM {variable} WHERE name = :name', array(':name' => 'mymodule_filter_foo_' . $row->getSourceProperty('format')))->fetchField();
     if ($value) {
       $row->setSourceProperty('settings:mymodule:foo', unserialize($value));
diff --git a/core/modules/migrate/migrate.services.yml b/core/modules/migrate/migrate.services.yml
index 11bead4..86aabe1 100644
--- a/core/modules/migrate/migrate.services.yml
+++ b/core/modules/migrate/migrate.services.yml
@@ -8,16 +8,19 @@ services:
     arguments: [migrate]
   plugin.manager.migrate.source:
     class: Drupal\migrate\Plugin\MigratePluginManager
-    arguments: [source, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
+    arguments: [source, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler', 'Drupal\migrate\Annotation\MigrateSource']
   plugin.manager.migrate.process:
-    class: Drupal\migrate\Plugin\MigratePluginManager
-    arguments: [process, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler', 'Drupal\migrate\Annotation\MigrateProcessPlugin']
+    class: Drupal\migrate\Plugin\MigrateProcessPluginManager
+    arguments: [process, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
   plugin.manager.migrate.destination:
-    class: Drupal\migrate\Plugin\MigratePluginManager
-    arguments: [destination, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
+    class: Drupal\migrate\Plugin\MigrateDestinationPluginManager
+    arguments: [destination, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler', '@theme_handler', '@entity.manager']
   plugin.manager.migrate.id_map:
     class: Drupal\migrate\Plugin\MigratePluginManager
     arguments: [id_map, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
   plugin.manager.migrate.entity_field:
     class: Drupal\migrate\Plugin\MigratePluginManager
     arguments: [entity_field, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
+  password_migrate:
+    class: Drupal\migrate\MigratePassword
+    arguments: ['@password_original']
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/FakeDatabaseSchema.php b/core/modules/migrate/tests/Drupal/migrate/Tests/FakeDatabaseSchema.php
index 5c1424d..5ec9bc5 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/FakeDatabaseSchema.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/FakeDatabaseSchema.php
@@ -32,74 +32,128 @@ public function __construct(array &$database_contents) {
     $this->databaseContents = &$database_contents;
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function tableExists($table) {
     return in_array($table, array_keys($this->databaseContents));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function prefixNonTable($table) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   protected function getPrefixInfo($table = 'default', $add_prefix = TRUE) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function addField($table, $field, $spec, $keys_new = array()) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function addIndex($table, $name, $fields) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function addPrimaryKey($table, $fields) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function addUniqueKey($table, $name, $fields) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * PHP magic __clone() method.
+   */
   public function __clone() {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function copyTable($source, $destination) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function createTable($name, $table) {
     #throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function dropField($table, $field) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function dropIndex($table, $name) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function dropPrimaryKey($table) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function dropTable($table) {
     unset($this->databaseContents[$table]);
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function dropUniqueKey($table, $name) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function fieldExists($table, $column) {
     if (!empty($this->databaseContents[$table])) {
       $row = reset($this->databaseContents[$table]);
@@ -110,42 +164,72 @@ public function fieldExists($table, $column) {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function fieldNames($fields) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function fieldSetDefault($table, $field, $default) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function fieldSetNoDefault($table, $field) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function findTables($table_expression) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function getFieldTypeMap() {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function indexExists($table, $name) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function nextPlaceholder() {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function prepareComment($comment, $length = NULL) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function renameTable($table, $new_name) {
     throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function uniqueIdentifier() {
     return $this->uniqueIdentifier;
   }
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/FakeMerge.php b/core/modules/migrate/tests/Drupal/migrate/Tests/FakeMerge.php
index 09d9e77..709e0db 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/FakeMerge.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/FakeMerge.php
@@ -25,7 +25,7 @@ class FakeMerge extends Merge {
    * @param string $table
    *   The database table to merge into.
    */
-  function __construct(array &$database_contents, $table) {
+  public function __construct(array &$database_contents, $table) {
     $this->databaseContents = &$database_contents;
     $this->table = $table;
     $this->conditionTable = $table;
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/FakeSelect.php b/core/modules/migrate/tests/Drupal/migrate/Tests/FakeSelect.php
index bf49714..de2f546 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/FakeSelect.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/FakeSelect.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\migrate\Tests;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Database\Query\Condition;
 use Drupal\Core\Database\Query\PlaceholderInterface;
@@ -87,7 +88,17 @@ public function addJoin($type, $table, $alias = NULL, $condition = NULL, $argume
       if ($type != 'INNER' && $type != 'LEFT') {
         throw new \Exception(sprintf('%s type not supported, only INNER and LEFT.', $type));
       }
-      if (!preg_match('/(\w+)\.(\w+)\s*=\s*(\w+)\.(\w+)/', $condition, $matches)) {
+      if (!preg_match('/^(\w+\.)?(\w+)\s*=\s*(\w+)\.(\w+)$/', $condition, $matches)) {
+        throw new \Exception('Only x.field1 = y.field2 conditions are supported.' . $condition);
+      }
+      if (!$matches[1] && count($this->tables) == 2) {
+        $aliases = array_keys($this->tables);
+        $matches[1] = $aliases[0];
+      }
+      else {
+        $matches[1] = substr($matches[1], 0, -1);
+      }
+      if (!$matches[1]) {
         throw new \Exception('Only x.field1 = y.field2 conditions are supported.' . $condition);
       }
       if ($matches[1] == $alias) {
@@ -518,7 +529,7 @@ public function fields($table_alias, array $fields = array()) {
         $fields = array_keys(reset($this->databaseContents[$table]));
       }
       else {
-        throw new \Exception('All fields on empty table is not supported.');
+        throw new \Exception(String::format('All fields on empty table @table is not supported.', array('@table' => $table)));
       }
     }
     return parent::fields($table_alias, $fields);
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecutableTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecutableTest.php
index cd54fd9..e837e09 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecutableTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecutableTest.php
@@ -43,12 +43,8 @@ class MigrateExecutableTest extends MigrateTestCase {
    */
   protected $executable;
 
-  protected $mapJoinable = FALSE;
-
   protected $migrationConfiguration = array(
     'id' => 'test',
-    'limit' => array('unit' => 'second', 'value' => 1),
-    'timeThreshold' => 0.9,
   );
 
   /**
@@ -72,6 +68,8 @@ protected function setUp() {
 
     $this->executable = new TestMigrateExecutable($this->migration, $this->message);
     $this->executable->setTranslationManager($this->getStringTranslationStub());
+    $this->executable->setTimeThreshold(0.1);
+    $this->executable->limit = array('unit' => 'second', 'value' => 1);
   }
 
   /**
@@ -111,6 +109,15 @@ public function testImportWithValidRow() {
       ->disableOriginalConstructor()
       ->getMock();
 
+    $row->expects($this->once())
+      ->method('getSourceIdValues')
+      ->will($this->returnValue(array('id' => 'test')));
+
+    $this->idMap->expects($this->once())
+      ->method('lookupDestinationId')
+      ->with(array('id' => 'test'))
+      ->will($this->returnValue(array('test')));
+
     $source->expects($this->once())
       ->method('current')
       ->will($this->returnValue($row));
@@ -124,7 +131,7 @@ public function testImportWithValidRow() {
     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
     $destination->expects($this->once())
       ->method('import')
-      ->with($row)
+      ->with($row, array('test'))
       ->will($this->returnValue(array('id' => 'test')));
 
     $this->migration->expects($this->once())
@@ -142,6 +149,56 @@ public function testImportWithValidRow() {
   /**
    * Tests the import method with a valid row.
    */
+  public function testImportWithValidRowWithoutDestinationId() {
+    $source = $this->getMockSource();
+
+    $row = $this->getMockBuilder('Drupal\migrate\Row')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $row->expects($this->once())
+      ->method('getSourceIdValues')
+      ->will($this->returnValue(array('id' => 'test')));
+
+    $this->idMap->expects($this->once())
+      ->method('lookupDestinationId')
+      ->with(array('id' => 'test'))
+      ->will($this->returnValue(array('test')));
+
+    $source->expects($this->once())
+      ->method('current')
+      ->will($this->returnValue($row));
+
+    $this->executable->setSource($source);
+
+    $this->migration->expects($this->once())
+      ->method('getProcessPlugins')
+      ->will($this->returnValue(array()));
+
+    $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
+    $destination->expects($this->once())
+      ->method('import')
+      ->with($row, array('test'))
+      ->will($this->returnValue(TRUE));
+
+    $this->migration->expects($this->once())
+      ->method('getDestinationPlugin')
+      ->will($this->returnValue($destination));
+
+    $this->idMap->expects($this->never())
+      ->method('saveIdMapping');
+
+    $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
+
+    $this->assertSame(1, $this->executable->getSuccessesSinceFeedback());
+    $this->assertSame(1, $this->executable->getTotalSuccesses());
+    $this->assertSame(1, $this->executable->getTotalProcessed());
+    $this->assertSame(1, $this->executable->getProcessedSinceFeedback());
+  }
+
+  /**
+   * Tests the import method with a valid row.
+   */
   public function testImportWithValidRowNoDestinationValues() {
     $source = $this->getMockSource();
 
@@ -166,7 +223,7 @@ public function testImportWithValidRowNoDestinationValues() {
     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
     $destination->expects($this->once())
       ->method('import')
-      ->with($row)
+      ->with($row, array('test'))
       ->will($this->returnValue(array()));
 
     $this->migration->expects($this->once())
@@ -188,6 +245,11 @@ public function testImportWithValidRowNoDestinationValues() {
     $this->idMap->expects($this->once())
       ->method('saveMessage');
 
+    $this->idMap->expects($this->once())
+      ->method('lookupDestinationId')
+      ->with(array('id' => 'test'))
+      ->will($this->returnValue(array('test')));
+
     $this->message->expects($this->once())
       ->method('display')
       ->with('New object was not saved, no error provided');
@@ -223,7 +285,7 @@ public function testImportWithValidRowWithMigrateException() {
     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
     $destination->expects($this->once())
       ->method('import')
-      ->with($row)
+      ->with($row, array('test'))
       ->will($this->throwException(new MigrateException($exception_message)));
 
     $this->migration->expects($this->once())
@@ -241,6 +303,11 @@ public function testImportWithValidRowWithMigrateException() {
       ->method('display')
       ->with($exception_message);
 
+    $this->idMap->expects($this->once())
+      ->method('lookupDestinationId')
+      ->with(array('id' => 'test'))
+      ->will($this->returnValue(array('test')));
+
     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
   }
 
@@ -272,7 +339,7 @@ public function testImportWithValidRowWithException() {
     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
     $destination->expects($this->once())
       ->method('import')
-      ->with($row)
+      ->with($row, array('test'))
       ->will($this->throwException(new \Exception($exception_message)));
 
     $this->migration->expects($this->once())
@@ -286,6 +353,11 @@ public function testImportWithValidRowWithException() {
     $this->idMap->expects($this->once())
       ->method('saveMessage');
 
+    $this->idMap->expects($this->once())
+      ->method('lookupDestinationId')
+      ->with(array('id' => 'test'))
+      ->will($this->returnValue(array('test')));
+
     $this->message->expects($this->once())
       ->method('display')
       ->with($exception_message);
@@ -301,10 +373,10 @@ public function testTimeOptionExceeded() {
     $this->executable->setTimeElapsed(1);
     $this->assertTrue($this->executable->timeOptionExceeded());
     // Assert time limit not exceeded.
-    $this->migration->set('limit', array('unit' => 'seconds', 'value' => (REQUEST_TIME - 3600)));
+    $this->executable->limit = array('unit' => 'seconds', 'value' => (REQUEST_TIME - 3600));
     $this->assertFalse($this->executable->timeOptionExceeded());
     // Assert no time limit.
-    $this->migration->set('limit', array());
+    $this->executable->limit = array();
     $this->assertFalse($this->executable->timeOptionExceeded());
   }
 
@@ -313,19 +385,19 @@ public function testTimeOptionExceeded() {
    */
   public function testGetTimeLimit() {
     // Assert time limit has a unit of one second (test configuration default).
-    $limit = $this->migration->get('limit');
+    $limit = $this->executable->limit;
     $this->assertArrayHasKey('unit', $limit);
     $this->assertSame('second', $limit['unit']);
     $this->assertSame($limit['value'], $this->executable->getTimeLimit());
     // Assert time limit has a unit of multiple seconds.
-    $this->migration->set('limit', array('unit' => 'seconds', 'value' => 30));
-    $limit = $this->migration->get('limit');
+    $this->executable->limit = array('unit' => 'seconds', 'value' => 30);
+    $limit = $this->executable->limit;
     $this->assertArrayHasKey('unit', $limit);
     $this->assertSame('seconds', $limit['unit']);
     $this->assertSame($limit['value'], $this->executable->getTimeLimit());
     // Assert no time limit.
-    $this->migration->set('limit', array());
-    $limit = $this->migration->get('limit');
+    $this->executable->limit = array();
+    $limit = $this->executable->limit;
     $this->assertArrayNotHasKey('unit', $limit);
     $this->assertArrayNotHasKey('value', $limit);
     $this->assertNull($this->executable->getTimeLimit());
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecuteableMemoryExceededTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecuteableMemoryExceededTest.php
index d69873f..133402e 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecuteableMemoryExceededTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateExecuteableMemoryExceededTest.php
@@ -37,13 +37,6 @@ class MigrateExecuteableMemoryExceededTest extends MigrateTestCase {
   protected $executable;
 
   /**
-   * Whether the map is joinable, initialized to FALSE.
-   *
-   * @var bool
-   */
-  protected $mapJoinable = FALSE;
-
-  /**
    * The migration configuration, initialized to set the ID to test.
    *
    * @var array
@@ -97,7 +90,7 @@ protected function setUp() {
   protected function runMemoryExceededTest($message, $memory_exceeded, $memory_usage_first = NULL, $memory_usage_second = NULL, $memory_limit = NULL) {
     $this->executable->setMemoryLimit($memory_limit ?: $this->memoryLimit);
     $this->executable->setMemoryUsage($memory_usage_first ?: $this->memoryLimit, $memory_usage_second ?: $this->memoryLimit);
-    $this->migration->set('memoryThreshold', 0.85);
+    $this->executable->setMemoryThreshold(0.85);
     if ($message) {
       $this->executable->message->expects($this->at(0))
         ->method('display')
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapEnsureTablesTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapEnsureTablesTest.php
index d63caa4..6727aab 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapEnsureTablesTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapEnsureTablesTest.php
@@ -18,30 +18,12 @@
 class MigrateSqlIdMapEnsureTablesTest extends MigrateTestCase {
 
   /**
-   * Whether the map is joinable, initialized to FALSE.
-   *
-   * @var bool
-   */
-  protected $mapJoinable = FALSE;
-
-  /**
    * The migration configuration, initialized to set the ID and destination IDs.
    *
    * @var array
    */
   protected $migrationConfiguration = array(
     'id' => 'sql_idmap_test',
-    'sourceIds' => array(
-      'source_id_property' => array(
-        'type' => 'int',
-      ),
-    ),
-    'destinationIds' => array(
-      'destination_id_property' => array(
-        'type' => 'varchar',
-        'length' => 255,
-      ),
-    ),
   );
 
   /**
@@ -88,9 +70,15 @@ public function testEnsureTablesNotExist() {
       'not null' => FALSE,
       'description' => 'Hash of source row data, for detecting changes',
     );
-    $fields['sourceid1'] = $this->migrationConfiguration['sourceIds']['source_id_property'];
-    $fields['destid1'] = $this->migrationConfiguration['destinationIds']['destination_id_property'];
-    $fields['destid1']['not null'] = FALSE;
+    $fields['sourceid1'] = array(
+      'type' => 'int',
+      'not null' => TRUE,
+    );
+    $fields['destid1'] = array(
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => FALSE,
+    );
     $map_table_schema = array(
       'description' => 'Mappings from source identifier value(s) to destination identifier value(s).',
       'fields' => $fields,
@@ -113,7 +101,10 @@ public function testEnsureTablesNotExist() {
       'unsigned' => TRUE,
       'not null' => TRUE,
     );
-    $fields['sourceid1'] = $this->migrationConfiguration['sourceIds']['source_id_property'];
+    $fields['sourceid1'] = array(
+      'type' => 'int',
+      'not null' => TRUE,
+    );
     $fields['level'] = array(
       'type' => 'int',
       'unsigned' => TRUE,
@@ -199,7 +190,31 @@ protected function runEnsureTablesTest($schema) {
     $database->expects($this->any())
       ->method('schema')
       ->will($this->returnValue($schema));
-    new TestSqlIdMap($database, array(), 'sql', array(), $this->getMigration());
+    $migration = $this->getMigration();
+    $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
+    $plugin->expects($this->any())
+      ->method('getIds')
+      ->will($this->returnValue(array(
+      'source_id_property' => array(
+        'type' => 'integer',
+      ),
+    )));
+    $migration->expects($this->any())
+      ->method('getSourcePlugin')
+      ->will($this->returnValue($plugin));
+    $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
+    $plugin->expects($this->any())
+      ->method('getIds')
+      ->will($this->returnValue(array(
+      'destination_id_property' => array(
+        'type' => 'string',
+      ),
+    )));
+    $migration->expects($this->any())
+      ->method('getDestinationPlugin')
+      ->will($this->returnValue($plugin));
+    $map = new TestSqlIdMap($database, array(), 'sql', array(), $migration);
+    $map->getDatabase();
   }
 
 }
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapTest.php
index 9bce172..1500618 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlIdMapTest.php
@@ -21,25 +21,20 @@
 class MigrateSqlIdMapTest extends MigrateTestCase {
 
   /**
-   * Whether the map is joinable, initialized to FALSE.
-   *
-   * @var bool
-   */
-  protected $mapJoinable = FALSE;
-
-  /**
    * The migration configuration, initialized to set the ID and destination IDs.
    *
    * @var array
    */
   protected $migrationConfiguration = array(
     'id' => 'sql_idmap_test',
-    'sourceIds' => array(
-      'source_id_property' => array(),
-    ),
-    'destinationIds' => array(
-      'destination_id_property' => array(),
-    ),
+  );
+
+  protected $sourceIds = array(
+    'source_id_property' => array(),
+  );
+
+  protected $destinationIds = array(
+    'destination_id_property' => array(),
   );
 
   /**
@@ -76,6 +71,20 @@ public static function getInfo() {
    */
   protected function getIdMap($database_contents = array(), $connection_options = array(), $prefix = '') {
     $migration = $this->getMigration();
+    $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
+    $plugin->expects($this->any())
+      ->method('getIds')
+      ->will($this->returnValue($this->sourceIds));
+    $migration->expects($this->any())
+      ->method('getSourcePlugin')
+      ->will($this->returnValue($plugin));
+    $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
+    $plugin->expects($this->any())
+      ->method('getIds')
+      ->will($this->returnValue($this->destinationIds));
+    $migration->expects($this->any())
+      ->method('getDestinationPlugin')
+      ->will($this->returnValue($plugin));
     $this->database = $this->getDatabase($database_contents, $connection_options, $prefix);
     $id_map = new TestSqlIdMap($this->database, array(), 'sql', array(), $migration);
     $migration->expects($this->any())
@@ -246,7 +255,7 @@ public function testMessageSave() {
 
     foreach ($expected_results as $key => $expected_result) {
       $id_map->saveMessage(array($key), $message, $expected_result['level']);
-      $message_row = $this->database->select($id_map->getMessageTableName(), 'message')
+      $message_row = $this->database->select($id_map->messageTableName(), 'message')
                        ->fields('message')
                        ->condition('level',$expected_result['level'])
                        ->condition('message',$expected_result['message'])
@@ -258,7 +267,7 @@ public function testMessageSave() {
     // Insert with default level.
     $message_default = 'Hello world default.';
     $id_map->saveMessage(array(5), $message_default);
-    $message_row = $this->database->select($id_map->getMessageTableName(), 'message')
+    $message_row = $this->database->select($id_map->messageTableName(), 'message')
                      ->fields('message')
                      ->condition('level', MigrationInterface::MESSAGE_ERROR)
                      ->condition('message', $message_default)
@@ -319,8 +328,8 @@ public function testLookupDestinationIdMapping() {
   protected function performLookupDestinationIdTest($num_source_fields, $num_destination_fields) {
     // Adjust the migration configuration according to the number of source and
     // destination fields.
-    $this->migrationConfiguration['sourceIds'] = array();
-    $this->migrationConfiguration['destinationIds'] = array();
+    $this->sourceIds = array();
+    $this->destinationIds = array();
     $source_id_values = array();
     $nonexistent_id_values = array();
     $row = $this->idMapDefaults();
@@ -328,13 +337,13 @@ protected function performLookupDestinationIdTest($num_source_fields, $num_desti
       $row["sourceid$i"] = "source_id_value_$i";
       $source_id_values[] = "source_id_value_$i";
       $nonexistent_id_values[] = "nonexistent_source_id_value_$i";
-      $this->migrationConfiguration['sourceIds']["source_id_property_$i"] = array();
+      $this->sourceIds["source_id_property_$i"] = array();
     }
     $expected_result = array();
     for ($i = 1; $i <= $num_destination_fields; $i++) {
       $row["destid$i"] = "destination_id_value_$i";
       $expected_result[] = "destination_id_value_$i";
-      $this->migrationConfiguration['destinationIds']["destination_id_property_$i"] = array();
+      $this->destinationIds["destination_id_property_$i"] = array();
     }
     $database_contents['migrate_map_sql_idmap_test'][] = $row;
     $id_map = $this->getIdMap($database_contents);
@@ -400,14 +409,14 @@ public function testLookupSourceIDMapping() {
   protected function performLookupSourceIdTest($num_source_fields, $num_destination_fields) {
     // Adjust the migration configuration according to the number of source and
     // destination fields.
-    $this->migrationConfiguration['sourceIds'] = array();
-    $this->migrationConfiguration['destinationIds'] = array();
+    $this->sourceIds = array();
+    $this->destinationIds = array();
     $row = $this->idMapDefaults();
     $expected_result = array();
     for ($i = 1; $i <= $num_source_fields; $i++) {
       $row["sourceid$i"] = "source_id_value_$i";
       $expected_result[] = "source_id_value_$i";
-      $this->migrationConfiguration['sourceIds']["source_id_property_$i"] = array();
+      $this->sourceIds["source_id_property_$i"] = array();
     }
     $destination_id_values = array();
     $nonexistent_id_values = array();
@@ -415,7 +424,7 @@ protected function performLookupSourceIdTest($num_source_fields, $num_destinatio
       $row["destid$i"] = "destination_id_value_$i";
       $destination_id_values[] = "destination_id_value_$i";
       $nonexistent_id_values[] = "nonexistent_destination_id_value_$i";
-      $this->migrationConfiguration['destinationIds']["destination_id_property_$i"] = array();
+      $this->destinationIds["destination_id_property_$i"] = array();
     }
     $database_contents['migrate_map_sql_idmap_test'][] = $row;
     $id_map = $this->getIdMap($database_contents);
@@ -679,8 +688,10 @@ public function testPrepareUpdate() {
    */
   public function testDestroy() {
     $id_map = $this->getIdMap();
-    $map_table_name = $id_map->getMapTableName();
-    $message_table_name = $id_map->getMessageTableName();
+    // Initialize the id map.
+    $id_map->getDatabase();
+    $map_table_name = $id_map->mapTableName();
+    $message_table_name = $id_map->messageTableName();
     $row = new Row(array('source_id_property' => 'source_value'), array('source_id_property' => array()));
     $id_map->saveIdMapping($row, array('destination_id_property' => 2));
     $id_map->saveMessage(array('source_value'), 'A message');
@@ -710,7 +721,7 @@ public function testGetQualifiedMapTableNoPrefix() {
   public function testGetQualifiedMapTablePrefix() {
     $id_map = $this->getIdMap(array(), array('database' => 'source_database'), 'prefix');
     $qualified_map_table = $id_map->getQualifiedMapTableName();
-    $this->assertEquals('migrate_map_sql_idmap_test', $qualified_map_table);
+    $this->assertEquals('source_database.prefixmigrate_map_sql_idmap_test', $qualified_map_table);
   }
 
   /**
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlSourceTestCase.php b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlSourceTestCase.php
index a8111c8..598db2c 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlSourceTestCase.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateSqlSourceTestCase.php
@@ -6,6 +6,8 @@
  */
 
 namespace Drupal\migrate\Tests;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\migrate\Source;
 
 /**
  * Provides setup and helper methods for Migrate module source tests.
@@ -15,7 +17,7 @@
   /**
    * The tested source plugin.
    *
-   * @var \Drupal\migrate\Plugin\migrate\source\d6\Drupal6SqlBase.
+   * @var \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase.
    */
   protected $source;
 
@@ -69,9 +71,7 @@
    * {@inheritdoc}
    */
   protected function setUp() {
-    $module_handler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
 
     $migration = $this->getMigration();
     $migration->expects($this->any())
@@ -82,6 +82,7 @@ protected function setUp() {
     $plugin = new $plugin_class($this->migrationConfiguration['source'], $this->migrationConfiguration['source']['plugin'], array(), $migration);
     $plugin->setDatabase($this->getDatabase($this->databaseContents + array('test_map' => array())));
     $plugin->setModuleHandler($module_handler);
+    $plugin->setTranslationManager($this->getStringTranslationStub());
     $migration->expects($this->any())
       ->method('getSourcePlugin')
       ->will($this->returnValue($plugin));
@@ -94,6 +95,9 @@ protected function setUp() {
     $this->source->setCache($cache);
   }
 
+  /**
+   * Test the source returns the same rows as expected.
+   */
   public function testRetrieval() {
     $this->queryResultTest($this->source, $this->expectedResults);
   }
@@ -119,3 +123,9 @@ public static function getInfo() {
   }
 
 }
+
+class TestSource extends Source {
+  public function setCache(CacheBackendInterface $cache) {
+    $this->cache = $cache;
+  }
+}
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateTestCase.php b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateTestCase.php
index ef94410..91e9fb0 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateTestCase.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/MigrateTestCase.php
@@ -14,13 +14,6 @@
  */
 abstract class MigrateTestCase extends UnitTestCase {
 
-  /**
-   * @TODO: does this need to be derived from the source/destination plugin?
-   *
-   * @var bool
-   */
-  protected $mapJoinable = TRUE;
-
   protected $migrationConfiguration = array();
 
   /**
@@ -32,13 +25,16 @@
   protected function getMigration() {
     $this->idMap = $this->getMock('Drupal\migrate\Plugin\MigrateIdMapInterface');
 
-    if ($this->mapJoinable) {
-      $this->idMap->expects($this->once())
-        ->method('getQualifiedMapTableName')
-        ->will($this->returnValue('test_map'));
-    }
+    $this->idMap->expects($this->any())
+      ->method('getQualifiedMapTableName')
+      ->will($this->returnValue('test_map'));
 
-    $migration = $this->getMock('Drupal\migrate\Entity\MigrationInterface');
+    $migration = $this->getMockBuilder('Drupal\migrate\Entity\Migration')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $migration->expects($this->any())
+      ->method('checkRequirements')
+      ->will($this->returnValue(TRUE));
     $migration->expects($this->any())
       ->method('getIdMap')
       ->will($this->returnValue($this->idMap));
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/RowTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/RowTest.php
index b337cdf..c30375c 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/RowTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/RowTest.php
@@ -248,8 +248,8 @@ public function testDestination() {
   public function testMultipleDestination() {
     $row = new Row($this->testValues, $this->testSourceIds);
     // Set some deep nested values.
-    $row->setDestinationProperty('image:alt', 'alt text');
-    $row->setDestinationProperty('image:fid', 3);
+    $row->setDestinationProperty('image.alt', 'alt text');
+    $row->setDestinationProperty('image.fid', 3);
 
     $this->assertTrue($row->hasDestinationProperty('image'));
     $this->assertFalse($row->hasDestinationProperty('alt'));
@@ -258,8 +258,8 @@ public function testMultipleDestination() {
     $destination = $row->getDestination();
     $this->assertEquals('alt text', $destination['image']['alt']);
     $this->assertEquals(3, $destination['image']['fid']);
-    $this->assertEquals('alt text', $row->getDestinationProperty('image:alt'));
-    $this->assertEquals(3, $row->getDestinationProperty('image:fid'));
+    $this->assertEquals('alt text', $row->getDestinationProperty('image.alt'));
+    $this->assertEquals(3, $row->getDestinationProperty('image.fid'));
   }
 
 }
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/TestMigrateExecutable.php b/core/modules/migrate/tests/Drupal/migrate/Tests/TestMigrateExecutable.php
index 1a222c7..1ddfebf 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/TestMigrateExecutable.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/TestMigrateExecutable.php
@@ -222,6 +222,26 @@ public function setMemoryLimit($memory_limit) {
   }
 
   /**
+   * Sets the memory threshold.
+   *
+   * @param float $threshold
+   *   The new threshold.
+   */
+  public function setMemoryThreshold($threshold) {
+    $this->memoryThreshold = $threshold;
+  }
+
+  /**
+   * Sets the time threshold.
+   *
+   * @param float $threshold
+   *   The new threshold.
+   */
+  public function setTimeThreshold($threshold) {
+    $this->timeThreshold = $threshold;
+  }
+
+  /**
    * {@inheritdoc}
    */
   protected function formatSize($size) {
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/TestSource.php b/core/modules/migrate/tests/Drupal/migrate/Tests/TestSource.php
deleted file mode 100644
index 99988d6..0000000
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/TestSource.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\migrate\Tests\TestSource.
- */
-
-
-namespace Drupal\migrate\Tests;
-
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\migrate\Source;
-
-class TestSource extends Source {
-  function setCache(CacheBackendInterface $cache) {
-    $this->cache = $cache;
-  }
-}
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/TestSqlIdMap.php b/core/modules/migrate/tests/Drupal/migrate/Tests/TestSqlIdMap.php
index 76f59db..2914a7f 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/TestSqlIdMap.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/TestSqlIdMap.php
@@ -7,8 +7,10 @@
 
 namespace Drupal\migrate\Tests;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Database\Connection;
 use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateException;
 use Drupal\migrate\Plugin\migrate\id_map\Sql;
 
 /**
@@ -30,7 +32,7 @@ class TestSqlIdMap extends Sql implements \Iterator {
    * @param \Drupal\migrate\Entity\MigrationInterface $migration
    *   The migration to do.
    */
-  function __construct(Connection $database, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
+  public function __construct(Connection $database, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
     $this->database = $database;
     parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
   }
@@ -42,4 +44,24 @@ public function getDatabase() {
     return parent::getDatabase();
   }
 
+  protected function getFieldSchema(array $id_definition) {
+    if (!isset($id_definition['type'])) {
+      return array();
+    }
+    switch ($id_definition['type']) {
+      case 'integer':
+        return array(
+          'type' => 'int',
+          'not null' => TRUE,
+        );
+      case 'string':
+        return array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => FALSE,
+        );
+      default:
+        throw new MigrateException(String::format('@type not supported', array('@type' => $id_definition['type'])));
+    }
+  }
 }
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/destination/PerComponentEntityDisplayTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/destination/PerComponentEntityDisplayTest.php
new file mode 100644
index 0000000..d36acb4
--- /dev/null
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/destination/PerComponentEntityDisplayTest.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\destination\EntityDisplayTest.
+ */
+
+namespace Drupal\migrate\Tests\destination;
+
+use Drupal\migrate\Plugin\migrate\destination\ComponentEntityDisplayBase;
+use Drupal\migrate\Row;
+use Drupal\migrate\Tests\MigrateTestCase;
+
+/**
+ * Tests the entity display destination plugin.
+ *
+ * @group Drupal
+ * @group migrate
+ */
+class PerComponentEntityDisplayTest extends MigrateTestCase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Entity display destination plugin',
+      'description' => 'Tests the entity display destination plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+  /**
+   * Tests the entity display import method.
+   */
+  public function testImport() {
+    $values = array(
+      'entity_type' => 'entity_type_test',
+      'bundle' => 'bundle_test',
+      'view_mode' => 'view_mode_test',
+      'field_name' => 'field_name_test',
+      'options' => array('test setting'),
+    );
+    $row = new Row(array(), array());
+    foreach ($values as $key => $value) {
+      $row->setDestinationProperty($key, $value);
+    }
+    $entity = $this->getMockBuilder('Drupal\entity\Entity\EntityViewDisplay')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $entity->expects($this->once())
+      ->method('setComponent')
+      ->with('field_name_test', array('test setting'))
+      ->will($this->returnSelf());
+    $entity->expects($this->once())
+      ->method('save')
+      ->with();
+    $plugin = new TestPerComponentEntityDisplay($entity);
+    $this->assertSame($plugin->import($row), array('entity_type_test', 'bundle_test', 'view_mode_test', 'field_name_test'));
+    $this->assertSame($plugin->getTestValues(), array('entity_type_test', 'bundle_test', 'view_mode_test'));
+  }
+
+}
+
+class TestPerComponentEntityDisplay extends ComponentEntityDisplayBase {
+  const MODE_NAME = 'view_mode';
+  protected $testValues;
+  public function __construct($entity) {
+    $this->entity = $entity;
+  }
+  protected function getEntity($entity_type, $bundle, $view_mode) {
+    $this->testValues = func_get_args();
+    return $this->entity;
+  }
+  public function getTestValues() {
+    return $this->testValues;
+  }
+}
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/destination/PerComponentEntityFormDisplayTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/destination/PerComponentEntityFormDisplayTest.php
new file mode 100644
index 0000000..8d24988
--- /dev/null
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/destination/PerComponentEntityFormDisplayTest.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\destination\EntityFormDisplayTest.
+ */
+
+namespace Drupal\migrate\Tests\destination;
+
+use Drupal\migrate\Plugin\migrate\destination\PerComponentEntityFormDisplay;
+use Drupal\migrate\Row;
+use Drupal\migrate\Tests\MigrateTestCase;
+
+/**
+ * Tests the entity display destination plugin.
+ *
+ * @group Drupal
+ * @group migrate
+ */
+class PerComponentEntityFormDisplayTest extends MigrateTestCase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Entity display destination plugin',
+      'description' => 'Tests the entity display destination plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+  /**
+   * Tests the entity display import method.
+   */
+  public function testImport() {
+    $values = array(
+      'entity_type' => 'entity_type_test',
+      'bundle' => 'bundle_test',
+      'form_mode' => 'form_mode_test',
+      'field_name' => 'field_name_test',
+      'options' => array('test setting'),
+    );
+    $row = new Row(array(), array());
+    foreach ($values as $key => $value) {
+      $row->setDestinationProperty($key, $value);
+    }
+    $entity = $this->getMockBuilder('Drupal\entity\Entity\EntityFormDisplay')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $entity->expects($this->once())
+      ->method('setComponent')
+      ->with('field_name_test', array('test setting'))
+      ->will($this->returnSelf());
+    $entity->expects($this->once())
+      ->method('save')
+      ->with();
+    $plugin = new TestPerComponentEntityFormDisplay($entity);
+    $this->assertSame($plugin->import($row), array('entity_type_test', 'bundle_test', 'form_mode_test', 'field_name_test'));
+    $this->assertSame($plugin->getTestValues(), array('entity_type_test', 'bundle_test', 'form_mode_test'));
+  }
+
+}
+
+class TestPerComponentEntityFormDisplay extends PerComponentEntityFormDisplay {
+  const MODE_NAME = 'form_mode';
+  protected $testValues;
+  public function __construct($entity) {
+    $this->entity = $entity;
+  }
+  protected function getEntity($entity_type, $bundle, $form_mode) {
+    $this->testValues = func_get_args();
+    return $this->entity;
+  }
+  public function getTestValues() {
+    return $this->testValues;
+  }
+}
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/CallbackTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/CallbackTest.php
new file mode 100644
index 0000000..c4ace45
--- /dev/null
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/CallbackTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\process\CallbackTest.
+ */
+
+namespace Drupal\migrate\Tests\process;
+
+use Drupal\migrate\Plugin\migrate\process\Callback;
+
+/**
+ * @group migrate
+ * @group Drupal
+ */
+class CallbackTest extends MigrateProcessTestCase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Callback process plugin',
+      'description' => 'Tests the callback process plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->plugin = new TestCallback();
+    parent::setUp();
+  }
+
+  /**
+   * Test callback with a function as callable.
+   */
+  public function testCallbackWithFunction() {
+    $this->plugin->setCallable('strtolower');
+    $value = $this->plugin->transform('FooBar', $this->migrateExecutable, $this->row, 'destinationproperty');
+    $this->assertSame($value, 'foobar');
+  }
+
+  /**
+   * Test callback with a class method as callable.
+   */
+  public function testCallbackWithClassMethod() {
+    $this->plugin->setCallable(array('\Drupal\Component\Utility\Unicode', 'strtolower'));
+    $value = $this->plugin->transform('FooBar', $this->migrateExecutable, $this->row, 'destinationproperty');
+    $this->assertSame($value, 'foobar');
+  }
+
+}
+
+class TestCallback extends Callback {
+  public function __construct() {
+  }
+
+  public function setCallable($callable) {
+    $this->configuration['callable'] = $callable;
+  }
+
+}
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/ConcatTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/ConcatTest.php
new file mode 100644
index 0000000..4c01ab7
--- /dev/null
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/ConcatTest.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\process\ConcatTest.
+ */
+
+namespace Drupal\migrate\Tests\process;
+
+use Drupal\migrate\Plugin\migrate\process\Concat;
+
+/**
+ * @group migrate
+ * @group Drupal
+ */
+class ConcatTest extends MigrateProcessTestCase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Concat process plugin',
+      'description' => 'Tests the concat process plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->plugin = new TestConcat();
+    parent::setUp();
+  }
+
+  /**
+   * Test concat works without a delimiter.
+   */
+  public function testConcatWithoutDelimiter() {
+    $value = $this->plugin->transform(array('foo', 'bar'), $this->migrateExecutable, $this->row, 'destinationproperty');
+    $this->assertSame($value, 'foobar');
+  }
+
+  /**
+   * Test concat fails properly on non-arrays.
+   *
+   * @expectedException \Drupal\migrate\MigrateException
+   */
+  public function testConcatWithNonArray() {
+    $this->plugin->transform('foo', $this->migrateExecutable, $this->row, 'destinationproperty');
+  }
+
+  /**
+   * Test concat works without a delimiter.
+   */
+  public function testConcatWithDelimiter() {
+    $this->plugin->setDelimiter('_');
+    $value = $this->plugin->transform(array('foo', 'bar'), $this->migrateExecutable, $this->row, 'destinationproperty');
+    $this->assertSame($value, 'foo_bar');
+  }
+}
+
+class TestConcat extends Concat {
+  public function __construct() {
+  }
+
+  public function setDelimiter($delimiter) {
+    $this->configuration['delimiter'] = $delimiter;
+  }
+
+}
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/DedupeEntityTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/DedupeEntityTest.php
index 4948dab..1060acd 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/process/DedupeEntityTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/DedupeEntityTest.php
@@ -40,7 +40,7 @@ public static function getInfo() {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  protected function setUp() {
     $this->entityQuery = $this->getMockBuilder('Drupal\Core\Entity\Query\QueryInterface')
       ->disableOriginalConstructor()
       ->getMock();
@@ -107,7 +107,7 @@ protected function entityQueryExpects($count) {
 }
 
 class TestDedupeEntity extends DedupeEntity {
-  function setEntityQuery(QueryInterface $entity_query) {
+  public function setEntityQuery(QueryInterface $entity_query) {
     $this->entityQuery = $entity_query;
   }
 }
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/ExtractTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/ExtractTest.php
index 5e1e7d9..5266abf 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/process/ExtractTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/ExtractTest.php
@@ -31,7 +31,7 @@ public static function getInfo() {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  protected function setUp() {
     $configuration['index'] = array('foo');
     $this->plugin = new Extract($configuration, 'map', array());
     parent::setUp();
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/GetTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/GetTest.php
index 60e66a7..a268e13 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/process/GetTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/GetTest.php
@@ -7,6 +7,7 @@
 namespace Drupal\migrate\Tests\process;
 
 use Drupal\migrate\Plugin\migrate\process\TestGet;
+use Drupal\migrate\Row;
 
 /**
  * @group migrate
@@ -28,7 +29,7 @@ public static function getInfo() {
   /**
    * {@inheritdoc}
    */
-  function setUp() {
+  protected function setUp() {
     $this->plugin = new TestGet();
     parent::setUp();
   }
@@ -36,7 +37,7 @@ function setUp() {
   /**
    * Tests the Get plugin when source is a string.
    */
-  function testTransformSourceString() {
+  public function testTransformSourceString() {
     $this->row->expects($this->once())
       ->method('getSourceProperty')
       ->with('test')
@@ -49,7 +50,7 @@ function testTransformSourceString() {
   /**
    * Tests the Get plugin when source is an array.
    */
-  function testTransformSourceArray() {
+  public function testTransformSourceArray() {
     $map = array(
       'test1' => 'source_value1',
       'test2' => 'source_value2',
@@ -65,7 +66,7 @@ function testTransformSourceArray() {
   /**
    * Tests the Get plugin when source is a string pointing to destination.
    */
-  function testTransformSourceStringAt() {
+  public function testTransformSourceStringAt() {
     $this->row->expects($this->once())
       ->method('getSourceProperty')
       ->with('@test')
@@ -78,7 +79,7 @@ function testTransformSourceStringAt() {
   /**
    * Tests the Get plugin when source is an array pointing to destination.
    */
-  function testTransformSourceArrayAt() {
+  public function testTransformSourceArrayAt() {
     $map = array(
       'test1' => 'source_value1',
       '@test2' => 'source_value2',
@@ -97,9 +98,9 @@ function testTransformSourceArrayAt() {
 namespace Drupal\migrate\Plugin\migrate\process;
 
 class TestGet extends Get {
-  function __construct() {
+  public function __construct() {
   }
-  function setSource($source) {
+  public function setSource($source) {
     $this->configuration['source'] = $source;
   }
 }
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/IteratorTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/IteratorTest.php
index 454206f..9ca2f62 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/process/IteratorTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/IteratorTest.php
@@ -36,11 +36,6 @@ class IteratorTest extends MigrateTestCase {
   );
 
   /**
-   * @var bool
-   */
-  protected $mapJoinable = FALSE;
-
-  /**
    * {@inheritdoc}
    */
   public static function getInfo() {
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/MachineNameTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/MachineNameTest.php
index 0c7b24b..c1c41c6 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/process/MachineNameTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/MachineNameTest.php
@@ -24,11 +24,6 @@ class MachineNameTest extends MigrateProcessTestCase {
   protected $transliteration;
 
   /**
-   * @var bool
-   */
-  protected $mapJoinable = FALSE;
-
-  /**
    * {@inheritdoc}
    */
   public static function getInfo() {
@@ -42,7 +37,7 @@ public static function getInfo() {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  protected function setUp() {
     $this->transliteration = $this->getMockBuilder('Drupal\Component\Transliteration\TransliterationInterface')
       ->disableOriginalConstructor()
       ->getMock();
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/MigrateProcessTestCase.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/MigrateProcessTestCase.php
index 923ca97..4b45f35 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/process/MigrateProcessTestCase.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/MigrateProcessTestCase.php
@@ -26,7 +26,10 @@
    */
   protected $migrateExecutable;
 
-  function setUp() {
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
     $this->row = $this->getMockBuilder('Drupal\migrate\Row')
       ->disableOriginalConstructor()
       ->getMock();
diff --git a/core/modules/migrate/tests/Drupal/migrate/Tests/process/StaticMapTest.php b/core/modules/migrate/tests/Drupal/migrate/Tests/process/StaticMapTest.php
index 5bd66cb..f7cf5a3 100644
--- a/core/modules/migrate/tests/Drupal/migrate/Tests/process/StaticMapTest.php
+++ b/core/modules/migrate/tests/Drupal/migrate/Tests/process/StaticMapTest.php
@@ -28,7 +28,7 @@ public static function getInfo() {
   /**
    * {@inheritdoc}
    */
-  function setUp() {
+  protected function setUp() {
     $this->row = $this->getMockBuilder('Drupal\migrate\Row')
       ->disableOriginalConstructor()
       ->getMock();
@@ -43,7 +43,7 @@ function setUp() {
   /**
    * Tests map when the source is a string.
    */
-  function testMapWithSourceString() {
+  public function testMapWithSourceString() {
     $value = $this->plugin->transform('foo', $this->migrateExecutable, $this->row, 'destinationproperty');
     $this->assertSame($value, array('bar' => 'baz'));
   }
@@ -51,7 +51,7 @@ function testMapWithSourceString() {
   /**
    * Tests map when the source is a list.
    */
-  function testMapWithSourceList() {
+  public function testMapWithSourceList() {
     $value = $this->plugin->transform(array('foo', 'bar'), $this->migrateExecutable, $this->row, 'destinationproperty');
     $this->assertSame($value, 'baz');
   }
@@ -61,7 +61,7 @@ function testMapWithSourceList() {
    *
    * @expectedException \Drupal\migrate\MigrateException
    */
-  function testMapwithEmptySource() {
+  public function testMapwithEmptySource() {
     $this->plugin->transform(array(), $this->migrateExecutable, $this->row, 'destinationproperty');
   }
 
@@ -70,7 +70,32 @@ function testMapwithEmptySource() {
    *
    * @expectedException \Drupal\migrate\MigrateException
    */
-  function testMapwithInvalidSource() {
+  public function testMapwithInvalidSource() {
+    $this->plugin->transform(array('bar'), $this->migrateExecutable, $this->row, 'destinationproperty');
+  }
+
+  /**
+   * Tests when the source is invalid but there's a default.
+   */
+  public function testMapWithInvalidSourceWithADefaultValue() {
+    $configuration['map']['foo']['bar'] = 'baz';
+    $configuration['default_value'] = 'test';
+    $this->plugin = new StaticMap($configuration, 'map', array());
+    $value = $this->plugin->transform(array('bar'), $this->migrateExecutable, $this->row, 'destinationproperty');
+    $this->assertSame($value, 'test');
+  }
+
+  /**
+   * Tests when the source is invalid and bypass is enabled.
+   *
+   * @expectedException \Drupal\migrate\MigrateException
+   * @expectedExceptionMessage Setting both default_value and bypass is invalid.
+   */
+  public function testMapWithInvalidSourceAndBypass() {
+    $configuration['map']['foo']['bar'] = 'baz';
+    $configuration['default_value'] = 'test';
+    $configuration['bypass'] = TRUE;
+    $this->plugin = new StaticMap($configuration, 'map', array());
     $this->plugin->transform(array('bar'), $this->migrateExecutable, $this->row, 'destinationproperty');
   }
 
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_action_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_action_settings.yml
index 2da277f..d9da486 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_action_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_action_settings.yml
@@ -1,10 +1,10 @@
 id: d6_action_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - actions_max_stack
 process:
   recursion_limit: actions_max_stack
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: action.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_feed.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_feed.yml
new file mode 100644
index 0000000..bb06fcd
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_feed.yml
@@ -0,0 +1,19 @@
+id: d6_aggregator_feed
+
+source:
+  plugin: d6_aggregator_feed
+
+process:
+  fid: fid
+  title: title
+  url: url
+  refresh: refresh
+  checked: checked
+  link: link
+  description: description
+  image: image
+  etag: etag
+  modified: modified
+
+destination:
+  plugin: entity:aggregator_feed
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_item.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_item.yml
new file mode 100644
index 0000000..c5c7ae1
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_item.yml
@@ -0,0 +1,20 @@
+id: d6_aggregator_item
+source:
+  plugin: d6_aggregator_item
+process:
+  iid: iid
+  fid:
+    plugin: migration
+    migration: d6_aggregator_feed
+    source:
+      - fid
+  title: title
+  link: link
+  author: author
+  description: description
+  timestamp: timestamp
+  guid: guid
+destination:
+  plugin: entity:aggregator_item
+dependencies:
+  - d6_aggregator_feed
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_settings.yml
index a6ec30c..a5f99be 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_aggregator_settings.yml
@@ -1,6 +1,6 @@
 id: d6_aggregator_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - aggregator_fetcher
     - aggregator_parser
@@ -14,11 +14,11 @@ process:
   fetcher: aggregator_fetcher
   parser: aggregator_parser
   processors: aggregator_processors
-  'items:allowed_html': aggregator_allowed_html_tags
-  'items:teaser_length': aggregator_teaser_length
-  'items:expire': aggregator_clear
-  'source:list_max': aggregator_summary_items
-  'source:category_selector': aggregator_category_selector
+  'items.allowed_html': aggregator_allowed_html_tags
+  'items.teaser_length': aggregator_teaser_length
+  'items.expire': aggregator_clear
+  'source.list_max': aggregator_summary_items
+  'source.category_selector': aggregator_category_selector
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: aggregator.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_block.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_block.yml
new file mode 100644
index 0000000..2c9469c
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_block.yml
@@ -0,0 +1,60 @@
+id: d6_block
+source:
+  plugin: d6_block
+process:
+  id:
+    # We need something unique, so aggregator, aggregator_1 etc will do.
+    plugin: dedupe_entity
+    entity_type: block
+    field: id
+    postfix: _
+    source: module
+  plugin:
+    -
+      plugin: static_map
+      bypass: true
+      source:
+        - module
+        - delta
+      map:
+        book:
+          0: book_navigation
+        comment:
+          0: views_block:comments_recent-block_1
+        forum:
+          0: forum_active_block
+          1: forum_new_block
+        locale:
+          0: language_block
+        node:
+          0: node_syndicate_block
+        search:
+          0: search_form_block
+        statistics:
+          0: statistics_popular_block
+        system:
+          0: system_powered_by_block
+        user:
+          0: user_login_block
+          1: system_menu_block:tools
+          2: views_block:who_s_new-block_1
+          3: views_block:who_s_online-who_s_online_block
+    -
+      plugin: d6_block_plugin_id
+  region: region
+  theme: theme
+  label: title
+  'visibility.path.visibility': visibility
+  'visibility.path.pages': pages
+  'visibility.role.roles': roles
+  weight: weight
+  settings:
+    plugin: d6_block_settings
+    source:
+      - @plugin
+      - delta
+      - settings
+destination:
+  plugin: entity:block
+dependencies:
+  - d6_menu: false
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_book_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_book_settings.yml
index 77da0ce..9e1097f 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_book_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_book_settings.yml
@@ -1,14 +1,14 @@
 id: d6_book_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - book_child_type
     - book_block_mode
     - book_allowed_types
 process:
   child_type: book_child_type
-  'block:navigation:mode': book_block_mode
+  'block.navigation.mode': book_block_mode
   allowed_types: book_allowed_types
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: book.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_cck_field_revision.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_cck_field_revision.yml
new file mode 100644
index 0000000..7480201
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_cck_field_revision.yml
@@ -0,0 +1,13 @@
+id: d6_cck_field_revision
+load:
+  plugin: drupal_entity
+  bundle_migration: d6_node_type
+source:
+  plugin: d6_cck_field_revision
+process:
+  vid: vid
+destination:
+  plugin: entity_revision:node
+dependencies:
+  - d6_cck_field_values
+  - d6_node_revision
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_cck_field_values.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_cck_field_values.yml
new file mode 100644
index 0000000..5d1ad8e
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_cck_field_values.yml
@@ -0,0 +1,17 @@
+id: d6_cck_field_values
+load:
+  plugin: drupal_entity
+  bundle_migration: d6_node_type
+source:
+  plugin: d6_cck_field_values
+process:
+  nid:
+    plugin: migration
+    migration: d6_node
+    source: nid
+destination:
+  plugin: entity:node
+dependencies:
+  - d6_node
+  - d6_field_formatter_settings
+  - d6_field_instance_widget_settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_comment.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_comment.yml
new file mode 100644
index 0000000..a297286
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_comment.yml
@@ -0,0 +1,48 @@
+id: d6_comment
+source:
+  plugin: d6_comment
+  constants:
+    field_id: node__comment
+    entity_type: node
+process:
+  cid: cid
+  pid:
+    -
+      plugin: skip_process_on_empty
+      source: pid
+    -
+      plugin: migration
+      migration: d6_comment
+  entity_id:
+    plugin: migration
+    migration: d6_node
+    source: nid
+  entity_type: constants.entity_type
+  field_id: constants.field_id
+  subject: subject
+  uid:
+    -
+      plugin: skip_process_on_empty
+      source: uid
+    -
+      plugin: migration
+      migration: d6_user
+  name: name
+  mail: mail
+  homepage: homepage
+  hostname: hostname
+  created: timestamp
+  changed: timestamp
+  status: status #In D6, published=0. We reverse the value in prepareRow.
+  thread: thread
+  'comment_body.value': comment
+  'comment_body.format':
+    plugin: migration
+    migration: d6_filter_format
+    source: format
+destination:
+  plugin: entity:comment
+dependencies:
+  - d6_node
+  - d6_user
+  - d6_filter_format
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_comment_entity_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_entity_display.yml
new file mode 100644
index 0000000..3286e9d
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_entity_display.yml
@@ -0,0 +1,20 @@
+id: d6_comment_entity_display
+source:
+  plugin: d6_comment_variable
+  constants:
+    entity_type: node
+    field_name: comment
+    view_mode: default
+    options:
+      label: hidden
+      type: comment_default
+      weight: 20
+process:
+  entity_type: constants.entity_type
+  field_name: constants.field_name
+  view_mode: constants.view_mode
+  options: constants.options
+
+  bundle: node_type
+destination:
+  plugin: component_entity_display
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_comment_entity_form_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_entity_form_display.yml
new file mode 100644
index 0000000..cb255de
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_entity_form_display.yml
@@ -0,0 +1,19 @@
+id: d6_comment_entity_form_display
+source:
+  plugin: d6_comment_variable
+  constants:
+    entity_type: node
+    field_name: comment
+    form_mode: default
+    options:
+      type: comment_default
+      weight: 20
+process:
+  entity_type: constants.entity_type
+  field_name: constants.field_name
+  form_mode: constants.form_mode
+  options: constants.options
+
+  bundle: node_type
+destination:
+  plugin: component_entity_form_display
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_comment_field.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_field.yml
new file mode 100644
index 0000000..29b4a39
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_field.yml
@@ -0,0 +1,15 @@
+id: d6_comment_field
+source:
+  plugin: d6_comment_variable
+  constants:
+    entity_type: node
+    type: comment
+    id: node.comment
+    name: comment
+process:
+  entity_type: constants.entity_type
+  id: constants.id
+  name: constants.name
+  type: constants.type
+destination:
+  plugin: entity:field_config
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_comment_field_instance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_field_instance.yml
new file mode 100644
index 0000000..208adef
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_comment_field_instance.yml
@@ -0,0 +1,26 @@
+id: d6_comment_field_instance
+source:
+  plugin: d6_comment_variable
+  constants:
+    entity_type: node
+    field_name: comment
+    label: Comment settings
+    required: true
+process:
+  entity_type: constants.entity_type
+  field_name: constants.field_name
+  label: constants.label
+  required: constants.required
+
+  bundle: node_type
+  'default_value.0.status': comment
+  'settings.default_mode': comment_default_mode
+  'settings.per_page': comment_default_per_page
+  'settings.anonymous': comment_anonymous
+  'settings.subject': comment_subject_field
+  'settings.form_location': comment_form_location
+  'settings.preview': comment_preview
+destination:
+  plugin: entity:field_instance_config
+dependencies:
+  - d6_comment_field
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_contact_category.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_contact_category.yml
new file mode 100644
index 0000000..e9898d9
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_contact_category.yml
@@ -0,0 +1,21 @@
+id: d6_contact_category
+
+source:
+  plugin: d6_contact_category
+
+process:
+  id:
+    -
+      plugin: machine_name
+      source: category
+    -
+      plugin: dedupe_entity
+      entity_type: user_role
+      field: cid
+  label: category
+  recipients: recipients
+  reply: reply
+  weight: weight
+
+destination:
+  plugin: entity:contact_category
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_contact_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_contact_settings.yml
index 46470f8..823944d 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_contact_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_contact_settings.yml
@@ -1,12 +1,12 @@
 id: d6_contact_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - contact_default_status
     - contact_hourly_threshold
 process:
   user_default_enabled: contact_default_status
-  'flood:limit': contact_hourly_threshold
+  'flood.limit': contact_hourly_threshold
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: contact.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_custom_block.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_custom_block.yml
new file mode 100644
index 0000000..425ac84
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_custom_block.yml
@@ -0,0 +1,18 @@
+id: d6_custom_block
+source:
+  plugin: d6_box
+  constants:
+    type: basic
+process:
+  id: bid
+  type: constants.type
+  info: info
+  'body.format':
+    plugin: migration
+    migration: d6_filter_format
+    source: format
+  'body.value': body
+destination:
+  plugin: entity:custom_block
+dependencies:
+  - d6_filter_format
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_date_formats.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_date_formats.yml
new file mode 100644
index 0000000..d7ac1e1
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_date_formats.yml
@@ -0,0 +1,18 @@
+id: d6_date_formats
+source:
+  plugin: variable_multirow
+  variables:
+    - date_format_long
+    - date_format_medium
+    - date_format_short
+process:
+  id:
+    plugin: static_map
+    source: name
+    map:
+      date_format_long: long
+      date_format_short: short
+      date_format_medium: medium
+  'pattern.php': value
+destination:
+  plugin: entity:date_format
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_dblog_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_dblog_settings.yml
index cea039f..b998cd6 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_dblog_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_dblog_settings.yml
@@ -1,10 +1,10 @@
 id: d6_dblog_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - dblog_row_limit
 process:
   row_limit: dblog_row_limit
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: dblog.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_field.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_field.yml
new file mode 100644
index 0000000..59f28e9
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_field.yml
@@ -0,0 +1,83 @@
+id: d6_field
+
+source:
+  plugin: d6_field
+  constants:
+    entity_type: node
+    langocde: und
+process:
+  entity_type: constants.entity_type
+  status: active
+  langcode: constants.langcode
+  name: field_name
+  type:
+    -
+      plugin: static_map
+      bypass: true
+      source:
+        - type
+      map:
+        number_integer: number_integer
+        number_decimal: number_float
+        number_float: number_float
+        text: text
+        email: email
+        link: link
+        date: datetime
+        datestamp: datetime
+        datetime: datetime
+        fr_phone: telephone
+        be_phone: telephone
+        it_phone: telephone
+        el_phone: telephone
+        ch_phone: telephone
+        ca_phone: telephone
+        cr_phone: telephone
+        pa_phone: telephone
+        gb_phone: telephone
+        ru_phone: telephone
+        ua_phone: telephone
+        es_phone: telephone
+        au_phone: telephone
+        cs_phone: telephone
+        hu_phone: telephone
+        pl_phone: telephone
+        nl_phone: telephone
+        se_phone: telephone
+        za_phone: telephone
+        il_phone: telephone
+        nz_phone: telephone
+        br_phone: telephone
+        cl_phone: telephone
+        cn_phone: telephone
+        hk_phone: telephone
+        mo_phone: telephone
+        ph_phone: telephone
+        sg_phone: telephone
+        jo_phone: telephone
+        eg_phone: telephone
+        pk_phone: telephone
+        int_phone: telephone
+    -
+      plugin: file_image_handler
+  cardinality:
+    plugin: static_map
+    bypass: true
+    source: multiple
+    map:
+      0: 1
+      1: -1
+  settings:
+    plugin: field_settings
+    source:
+      - @type
+      - global_settings
+      - widget_settings
+
+destination:
+  plugin: entity:field_config
+dependencies:
+  # It is not possible to make this a requirement as d6_field_settings has no
+  # source id. However it also has no requirements so it will always run so a
+  # dependency is enough.
+  - d6_field_settings: false
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_field_formatter_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_field_formatter_settings.yml
new file mode 100644
index 0000000..70db67c
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_field_formatter_settings.yml
@@ -0,0 +1,284 @@
+id: d6_field_formatter_settings
+
+source:
+  plugin: d6_field_instance_per_view_mode
+  constants:
+    entity_type: node
+
+process:
+  entity_type: constants.entity_type
+  bundle: type_name
+  view_mode:
+    -
+      plugin: migration
+      migration: d6_view_modes
+      source:
+        - view_mode
+    -
+      plugin: extract
+      index:
+        - 1
+  field_name: field_name
+  "options.label": label
+  "options.weight": weight
+  "options.type":
+      -
+        plugin: static_map
+        bypass: true
+        source:
+          - type
+          - "display_settings.format"
+        map:
+          text:
+            default: text_default
+            trimmed: text_trimmed
+          number_integer:
+            default: number_integer
+            us_0: number_integer
+            be_0: number_integer
+            fr_0: number_integer
+            unformatted: number_unformatted
+          number_float:
+            default: number_decimal
+            us_0: number_decimal
+            us_1: number_decimal
+            us_2: number_decimal
+            be_0: number_decimal
+            be_1: number_decimal
+            be_2: number_decimal
+            fr_0: number_decimal
+            fr_1: number_decimal
+            fr_2: number_decimal
+            unformatted: number_unformatted
+          number_decimal:
+            default: number_decimal
+            us_0: number_decimal
+            us_1: number_decimal
+            us_2: number_decimal
+            be_0: number_decimal
+            be_1: number_decimal
+            be_2: number_decimal
+            fr_0: number_decimal
+            fr_1: number_decimal
+            fr_2: number_decimal
+            unformatted: number_unformatted
+          email:
+            default: email_mailto
+            spamspan: email_mailto
+            contact: email_mailto
+            plain: text_plain
+          link:
+            default: link
+            plain: link
+            absolute: link
+            title_plain: link
+            url: link
+            short: link
+            label: link
+            separate: link_separate
+          filefield:
+            default: file_default
+            url_plain: file_url_plain
+            path_plain: file_url_plan #unsure about this?
+            image_plain: image
+            image_nodelink: image
+            image_imagelink: image
+          fr_phone:
+            default: text_plain
+          be_phone:
+            default: text_plain
+          it_phone:
+            default: text_plain
+          el_phone:
+            default: text_plain
+          ch_phone:
+            default: text_plain
+          ca_phone:
+            default: text_plain
+          cr_phone:
+            default: text_plain
+          pa_phone:
+            default: text_plain
+          gb_phone:
+            default: text_plain
+          ru_phone:
+            default: text_plain
+          ua_phone:
+            default: text_plain
+          es_phone:
+            default: text_plain
+          au_phone:
+            default: text_plain
+          cs_phone:
+            default: text_plain
+          hu_phone:
+            default: text_plain
+          pl_phone:
+            default: text_plain
+          nl_phone:
+            default: text_plain
+          se_phone:
+            default: text_plain
+          za_phone:
+            default: text_plain
+          il_phone:
+            default: text_plain
+          nz_phone:
+            default: text_plain
+          br_phone:
+            default: text_plain
+          cl_phone:
+            default: text_plain
+          cn_phone:
+            default: text_plain
+          hk_phone:
+            default: text_plain
+          mo_phone:
+            default: text_plain
+          ph_phone:
+            default: text_plain
+          sg_phone:
+            default: text_plain
+          jo_phone:
+            default: text_plain
+          eg_phone:
+            default: text_plain
+          pk_phone:
+            default: text_plain
+          int_phone:
+            default: text_plain
+      -
+        plugin: field_type_defaults
+  "options.settings":
+    -
+      plugin: static_map
+      bypass: true
+      source:
+        - module
+        - "display_settings.format"
+      map:
+        number:
+          us_0:
+            scale: 0
+            decimal_separator: .
+            thousand_separator: ','
+            prefix_suffix: true
+          us_1:
+            scale: 1
+            decimal_separator: .
+            thousand_separator: ','
+            prefix_suffix: true
+          us_2:
+            scale: 2
+            decimal_separator: .
+            thousand_separator: ','
+            prefix_suffix: true
+          be_0:
+            scale: 0
+            decimal_separator: ','
+            thousand_separator: .
+            prefix_suffix: true
+          be_1:
+            scale: 1
+            decimal_separator: ','
+            thousand_separator: .
+            prefix_suffix: true
+          be_2:
+            scale: 2
+            decimal_separator: ','
+            thousand_separator: .
+            prefix_suffix: true
+          fr_0:
+            scale: 0
+            decimal_separator: ','
+            thousand_separator: ' '
+            prefix_suffix: true
+          fr_1:
+            scale: 1
+            decimal_separator: ','
+            thousand_separator: ' '
+            prefix_suffix: true
+          fr_2:
+            scale: 2
+            decimal_separator: ','
+            thousand_separator: ' '
+            prefix_suffix: true
+        link:
+          default:
+            trim_length: '80'
+            url_only: 0
+            url_plain: 0
+            rel: 0
+            target: 0
+          plain:
+            trim_length: '80'
+            url_only: 1
+            url_plain: 1
+            rel: 0
+            target: 0
+          absolute:
+            trim_length: '80'
+            url_only: 1
+            url_plain: 1
+            rel: 0
+            target: 0
+          title_plain: #can't support title as plain text.
+            trim_length: '80'
+            url_only: 1
+            url_plain: 1
+            rel: 0
+            target: 0
+          url:
+            trim_length: '80'
+            url_only: 1
+            url_plain: 0
+            rel: 0
+            target: 0
+          short: #can't support hardcoded link text?
+            trim_length: '80'
+            url_only: 0
+            url_plain: 0
+            rel: 0
+            target: 0
+          label: # can't support label as link text?
+            trim_length: '80'
+            url_only: 0
+            url_plain: 0
+            rel: 0
+            target: 0
+          separate:
+            trim_length: '80'
+            rel: 0
+            target: 0
+        filefield:
+          image_plain:
+            image_style: ''
+            image_link: ''
+          image_nodelink:
+            image_style: ''
+            image_link: content
+          image_imagelink:
+            image_style: ''
+            image_link: file
+        date:
+          default:
+            format: fallback
+          format_interval:
+            format: fallback
+          long:
+            format: long
+          medium:
+            format: medium
+          short:
+            format: short
+        text:
+          trimmed:
+            trim_length: 600
+    -
+      plugin: field_formatter_settings_defaults
+
+destination:
+  plugin: component_entity_display
+dependencies:
+  - d6_field_instance
+  - d6_view_modes
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_field_instance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_field_instance.yml
new file mode 100644
index 0000000..c87a537
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_field_instance.yml
@@ -0,0 +1,34 @@
+id: d6_field_instance
+
+source:
+  plugin: d6_field_instance
+  constants:
+    entity_type: node
+
+process:
+  entity_type: constants.entity_type
+  field_name: field_name
+  bundle: type_name
+  label: label
+  description: description
+  required: required
+  status: active
+  settings:
+    plugin: d6_field_instance_settings
+    source:
+      - widget_type
+      - widget_settings
+      - global_settings
+
+  default_value_function: ''
+  default_value:
+    plugin: d6_field_instance_defaults
+    source:
+      - widget_type
+      - widget_settings
+
+destination:
+  plugin: entity:field_instance_config
+dependencies:
+  - d6_node_type
+  - d6_field
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_field_instance_widget_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_field_instance_widget_settings.yml
new file mode 100644
index 0000000..f3bec42
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_field_instance_widget_settings.yml
@@ -0,0 +1,43 @@
+id: d6_field_instance_widget_settings
+
+source:
+  plugin: d6_field_instance_per_form_display
+  constants:
+    entity_type: node
+    form_mode: default
+
+process:
+  bundle: type_name
+  form_mode: constants.form_mode
+  field_name: field_name
+  entity_type: constants.entity_type
+  "options.weight": weight
+  "options.type":
+    type:
+      plugin: static_map
+      bypass: true
+      source: widget_type
+      map:
+        text_textfield: text_textfield
+        number: number
+        link: link_default
+        email_textfield: email_default
+        date_select: datetime_default
+        date_text: datetime_default
+        filefield_widget: file_generic
+        imagefield_widget: image_image
+        phone_textfield: telephone_default
+        optionwidgets_onoff: options_onoff
+        optionwidgets_buttons: options_buttons
+        optionwidgets_select: options_select
+  "options.settings":
+    -
+      plugin: field_instance_widget_settings
+      source:
+        - widget_type
+        - widget_settings
+
+destination:
+  plugin: component_entity_form_display
+dependencies:
+  - d6_field_instance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_field_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_field_settings.yml
index 45d6c34..902e155 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_field_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_field_settings.yml
@@ -1,10 +1,10 @@
 id: d6_field_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - field_language_fallback
 process:
   language_fallback: field_language_fallback
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: field.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_file.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_file.yml
new file mode 100644
index 0000000..5412e1e
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_file.yml
@@ -0,0 +1,18 @@
+id: d6_file
+source:
+  plugin: d6_file
+process:
+  fid: fid
+  filename: filename
+  uri:
+    plugin: file_uri
+    source:
+      - filepath
+      - file_directory_path
+      - is_public
+  filemime: filemime
+  filesize: filesize
+  status: status
+  changed: timestamp
+destination:
+  plugin: entity:file
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_file_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_file_settings.yml
index 35e077b..a088b6c 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_file_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_file_settings.yml
@@ -1,14 +1,14 @@
 id: d6_file_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - file_description_type
     - file_description_length
     - file_icon_directory
 process:
-  'description:type': file_description_type
-  'description:length': file_description_length
-  'icon:directory': file_icon_directory
+  'description.type': file_description_type
+  'description.length': file_description_length
+  'icon.directory': file_icon_directory
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: file.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_filter_format.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_filter_format.yml
new file mode 100644
index 0000000..99653b7
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_filter_format.yml
@@ -0,0 +1,40 @@
+id: d6_filter_format
+source:
+  plugin: d6_filter_format
+process:
+  format:
+    -
+      plugin: machine_name
+      source: name
+    -
+      plugin: dedupe_entity
+      entity_type: filter_format
+      field: format
+  name: name
+  cache: cache
+  filters:
+    plugin: iterator
+    source: filters
+    key: @id
+    process:
+      id:
+        plugin: static_map
+        default_value: filter_null
+        source:
+          - module
+          - delta
+        map:
+          filter:
+            - filter_html_escape
+            - filter_autop
+            - filter_url
+            - filter_htmlcorrector
+            - filter_html_escape
+          php:
+            - php_code
+      settings: settings
+      status:
+        plugin: default_value
+        default_value: true
+destination:
+  plugin: entity:filter_format
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_forum_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_forum_settings.yml
index 5bb0a1f..8ed1bd2 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_forum_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_forum_settings.yml
@@ -1,6 +1,6 @@
 id: d6_forum_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - forum_hot_topic
     - forum_per_page
@@ -8,11 +8,11 @@ source:
     - forum_block_num_0
     - forum_block_num_1
 process:
-  'block:active:limit': forum_block_num_0
-  'block:new:limit': forum_block_num_1
-  'topics:hot_threshold': forum_hot_topic
-  'topics:page_limit': forum_per_page
-  'topics:order': forum_order
+  'block.active.limit': forum_block_num_0
+  'block.new.limit': forum_block_num_1
+  'topics.hot_threshold': forum_hot_topic
+  'topics.page_limit': forum_per_page
+  'topics.order': forum_order
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: forum.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_locale_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_locale_settings.yml
index 1183b5e..972aaff 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_locale_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_locale_settings.yml
@@ -1,12 +1,12 @@
 id: d6_locale_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - locale_cache_strings
     - locale_js_directory
 process:
   cache_string: locale_cache_strings
-  'javascript:directory': locale_js_directory
+  'javascript.directory': locale_js_directory
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: locale.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_menu.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_menu.yml
new file mode 100644
index 0000000..35aaa2f
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_menu.yml
@@ -0,0 +1,9 @@
+id: d6_menu
+source:
+  plugin: d6_menu
+process:
+  id: menu_name
+  label: title
+  description: description
+destination:
+  plugin: entity:menu
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_menu_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_menu_settings.yml
index b57bd3e..5c56ea4 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_menu_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_menu_settings.yml
@@ -1,6 +1,6 @@
 id: d6_menu_settings
 source:
-    plugin: drupal6_variable
+    plugin: variable
     variables:
         - menu_primary_links_source
         - menu_secondary_links_source
@@ -10,5 +10,5 @@ process:
     secondary_links: menu_secondary_links_source
     override_parent_selector: menu_override_parent_selector
 destination:
-    plugin: d8_config
+    plugin: config
     config_name: menu.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_node.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_node.yml
new file mode 100644
index 0000000..8304f00
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_node.yml
@@ -0,0 +1,35 @@
+id: d6_node
+source:
+  plugin: d6_node
+process:
+  nid: nid
+  vid: vid
+  type: type
+  langcode: language
+  title: title
+  uid: uid
+  status: status
+  created: created
+  changed: changed
+  promote: promote
+  sticky: sticky
+  body.format:
+    plugin: migration
+    migration: d6_filter_format
+    source: format
+  body.value: body
+
+#  unmapped d6 fields.
+#  tnid
+#  translate
+#  moderate
+#  comment
+
+destination:
+  plugin: entity:node
+dependencies:
+  - d6_node_type
+  - d6_filter_format
+  - d6_field_instance_widget_settings: false
+  - d6_field_formatter_settings: false
+  - d6_node_settings: false
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_node_revision.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_node_revision.yml
new file mode 100644
index 0000000..87b4f93
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_node_revision.yml
@@ -0,0 +1,31 @@
+id: d6_node_revision
+source:
+  plugin: d6_node_revision
+process:
+  nid: nid
+  vid: vid
+  type: type
+  langcode: language
+  title: title
+  uid: uid
+  status: status
+  created: created
+  changed: changed
+  promote: promote
+  sticky: sticky
+  body.format:
+    plugin: migration
+    migration: d6_filter_format
+    source: format
+  body.value: body
+
+#  unmapped d6 fields.
+#  tnid
+#  translate
+#  moderate
+#  comment
+
+destination:
+  plugin: entity_revision:node
+dependencies:
+  - d6_node
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_node_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_node_settings.yml
index ab37378..27e89b1 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_node_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_node_settings.yml
@@ -1,10 +1,12 @@
 id: d6_node_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - node_admin_theme
 process:
   use_admin_theme: node_admin_theme
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: node.settings
+dependencies:
+  - d6_node_type
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_node_type.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_node_type.yml
new file mode 100644
index 0000000..530abe0
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_node_type.yml
@@ -0,0 +1,20 @@
+id: d6_node_type
+source:
+  plugin: d6_node_type
+  constants:
+    preview: 1 # DRUPAL_OPTIONAL
+    create_body: false
+process:
+  type: type
+  name: name
+  module: module
+  description: description
+  help: help
+  has_title: has_title
+  title_label: title_label
+  preview: constants.preview
+  submitted: submitted
+  options: options
+  create_body: has_body
+destination:
+  plugin: entity:node_type
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_profile_values.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_profile_values.yml
new file mode 100644
index 0000000..53a5086
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_profile_values.yml
@@ -0,0 +1,17 @@
+id: d6_profile_values
+source:
+  plugin: d6_profile_field_values
+load:
+  plugin: drupal_entity
+process:
+  uid:
+    plugin: migration
+    migration: d6_user
+    source: uid
+destination:
+  plugin: entity:user
+dependencies:
+  - d6_user
+  - d6_user_profile_field_instance
+  - d6_user_profile_entity_display
+  - d6_user_profile_entity_form_display
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_search_page.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_search_page.yml
new file mode 100644
index 0000000..d766126
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_search_page.yml
@@ -0,0 +1,22 @@
+id: d6_search_page
+source:
+  plugin: variable
+  variables:
+    - node_rank_comments
+    - node_rank_promote
+    - node_rank_recent
+    - node_rank_relevance
+    - node_rank_sticky
+    - node_rank_views
+  constants:
+    id: node_search
+    path: node
+    plugin: node_search
+process:
+  id: constants.id
+  path: constants.path
+  plugin: constants.plugin
+  configuration.rankings:
+    plugin: d6_search_configuration_rankings
+destination:
+  plugin: entity:search_page
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_search_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_search_settings.yml
index 7ea5c20..b5c94b4 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_search_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_search_settings.yml
@@ -1,6 +1,6 @@
 id: d6_search_settings
 source:
-    plugin: drupal6_variable
+    plugin: variable
     variables:
         - minimum_word_size
         - overlap_cjk
@@ -8,9 +8,9 @@ source:
         - search_tag_weights
         - search_and_or_limit
 process:
-    'index:minimum_word_size': minimum_word_size
-    'index:overlap_cjk': overlap_cjk
-    'index:cron_limit': search_cron_limit
+    'index.minimum_word_size': minimum_word_size
+    'index.overlap_cjk': overlap_cjk
+    'index.cron_limit': search_cron_limit
 destination:
-    plugin: d8_config
+    plugin: config
     config_name: search.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_simpletest_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_simpletest_settings.yml
index 8a6f06c..f9cd2bb 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_simpletest_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_simpletest_settings.yml
@@ -1,6 +1,6 @@
 id: d6_simpletest_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - simpletest_clear_results
     - simpletest_httpauth_method
@@ -9,10 +9,10 @@ source:
     - simpletest_verbose
 process:
   clear_results: simpletest_clear_results
-  'httpauth:method': simpletest_httpauth_method
-  'httpauth:password': simpletest_httpauth_password
-  'httpauth:username': simpletest_httpauth_username
+  'httpauth.method': simpletest_httpauth_method
+  'httpauth.password': simpletest_httpauth_password
+  'httpauth.username': simpletest_httpauth_username
   verbose: simpletest_verbose
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: simpletest.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_statistics_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_statistics_settings.yml
index 24a1baf..e20849b 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_statistics_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_statistics_settings.yml
@@ -1,6 +1,6 @@
 id: d6_statistics_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - statistics_enable_access_log
     - statistics_flush_accesslog_timer
@@ -9,12 +9,12 @@ source:
     - statistics_block_top_all_num
     - statistics_block_top_last_num
 process:
-  'access_log:enable': statistics_enable_access_log
-  'access_log:max_lifetime': statistics_flush_accesslog_timer
+  'access_log.enable': statistics_enable_access_log
+  'access_log.max_lifetime': statistics_flush_accesslog_timer
   'count_content_views': statistics_count_content_views
-  'block:popular:top_day_limit': statistics_block_top_day_num
-  'block:popular:top_all_limit': statistics_block_top_all_num
-  'block:popular:top_recent_limit': statistics_block_top_last_num
+  'block.popular.top_day_limit': statistics_block_top_day_num
+  'block.popular.top_all_limit': statistics_block_top_all_num
+  'block.popular.top_recent_limit': statistics_block_top_last_num
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: statistics.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_syslog_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_syslog_settings.yml
index 8be7bf2..47c3072 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_syslog_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_syslog_settings.yml
@@ -1,6 +1,6 @@
 id: d6_syslog_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - syslog_identity
     - syslog_facility
@@ -8,5 +8,5 @@ process:
   identity: syslog_identity
   facility: syslog_facility
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: syslog.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_cron.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_cron.yml
index 1e0e452..73a8b34 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_cron.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_cron.yml
@@ -1,13 +1,13 @@
 id: d6_system_cron
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - cron_threshold_warning
     - cron_threshold_error
     - cron_last
 process:
-  'threshold:warning': cron_threshold_warning
-  'threshold:error': cron_threshold_error
+  'threshold.warning': cron_threshold_warning
+  'threshold.error': cron_threshold_error
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.cron
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_file.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_file.yml
index df0797d..3c7cd3a 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_file.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_file.yml
@@ -1,12 +1,12 @@
 id: d6_system_file
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - file_directory_path
     - file_directory_temp
 process:
-  'path:private': file_directory_path
-  'path:temporary': file_directory_temp
+  'path.private': file_directory_path
+  'path.temporary': file_directory_temp
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.file
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_filter.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_filter.yml
index 0a2690e..2ca5770 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_filter.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_filter.yml
@@ -1,10 +1,10 @@
 id: d6_system_filter
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - filter_allowed_protocols
 process:
   protocols: filter_allowed_protocols
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.filter
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_image.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_image.yml
index 6d98bfc..d7caf6a 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_image.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_image.yml
@@ -1,10 +1,10 @@
 id: d6_system_image
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - image_toolkit
 process:
   toolkit: image_toolkit
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.image
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_image_gd.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_image_gd.yml
index 29aacba..f5bebe5 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_image_gd.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_image_gd.yml
@@ -1,10 +1,10 @@
 id: d6_system_image_gd
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - image_jpeg_quality
 process:
   jpeg_quality: image_jpeg_quality
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.image.gd
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_maintenance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_maintenance.yml
index a711614..46e7708 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_maintenance.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_maintenance.yml
@@ -1,6 +1,6 @@
 id: d6_system_maintenance
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - site_offline
     - site_offline_message
@@ -8,5 +8,5 @@ process:
   enable: site_offline
   message: site_offline_message
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.maintenance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_performance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_performance.yml
index 6498d9e..fa83c7f 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_performance.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_performance.yml
@@ -1,14 +1,14 @@
 id: d6_system_performance
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - preprocess_css
     - preprocess_js
     - cache_lifetime
 process:
-  'css:preprocess': preprocess_css
-  'js:preprocess': preprocess_js
-  'cache:page:max_age': cache_lifetime
+  'css.preprocess': preprocess_css
+  'js.preprocess': preprocess_js
+  'cache.page.max_age': cache_lifetime
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.performance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_rss.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_rss.yml
index ca8498f..ced4769 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_rss.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_rss.yml
@@ -1,10 +1,10 @@
 id: d6_system_rss
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - feed_default_items
 process:
-  'items:limit': feed_default_items
+  'items.limit': feed_default_items
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.rss
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_site.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_site.yml
index de88ed4..0bfe4e6 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_site.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_site.yml
@@ -1,6 +1,6 @@
 id: d6_system_site
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - site_name
     - site_mail
@@ -14,11 +14,11 @@ process:
   name: site_name
   mail: site_mail
   slogan: site_slogan
-  'page:front': site_frontpage
-  'page:403': site_403
-  'page:404': site_404
+  'page.front': site_frontpage
+  'page.403': site_403
+  'page.404': site_404
   weight_select_max: drupal_weight_select_max
   admin_compact_mode: admin_compact_mode
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.site
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_system_theme.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_system_theme.yml
index ba78e8c..8c1ffd8 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_system_theme.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_system_theme.yml
@@ -1,6 +1,6 @@
 id: d6_system_theme
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - admin_theme
     - theme_default
@@ -8,5 +8,5 @@ process:
   admin: admin_theme
   default: theme_default
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: system.theme
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_settings.yml
index a6bbaf7..78caf05 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_settings.yml
@@ -1,6 +1,6 @@
 id: d6_taxonomy_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - taxonomy_override_selector
     - taxonomy_terms_per_page_admin
@@ -8,5 +8,5 @@ process:
   override_selector: taxonomy_override_selector
   terms_per_page_admin: taxonomy_terms_per_page_admin
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: taxonomy.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_term.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_term.yml
new file mode 100644
index 0000000..76928b4
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_term.yml
@@ -0,0 +1,24 @@
+id: d6_taxonomy_term
+source:
+  plugin: d6_taxonomy_term
+process:
+  tid: tid
+  vid:
+    plugin: migration
+    migration: d6_taxonomy_vocabulary
+    source: vid
+  name: name
+  description: description
+  weight: weight
+  parent:
+    -
+      plugin: skip_process_on_empty
+      source: parent
+    -
+      plugin: migration
+      migration: d6_taxonomy_term
+  changed: timestamp
+destination:
+  plugin: entity:taxonomy_term
+dependencies:
+  - d6_taxonomy_vocabulary
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_vocabulary.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_vocabulary.yml
new file mode 100644
index 0000000..df237fb
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_taxonomy_vocabulary.yml
@@ -0,0 +1,19 @@
+id: d6_taxonomy_vocabulary
+source:
+  plugin: d6_taxonomy_vocabulary
+process:
+  vid:
+    -
+      plugin: machine_name
+      source: name
+    -
+      plugin: dedupe_entity
+      entity_type: taxonomy_vocabulary
+      field: vid
+  label: name
+  name: name
+  description: description
+  hierarchy: hierarchy
+  weight: weight
+destination:
+  plugin: entity:taxonomy_vocabulary
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_term_node.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_term_node.yml
new file mode 100644
index 0000000..0126925
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_term_node.yml
@@ -0,0 +1,18 @@
+id: d6_term_node
+load:
+  plugin: d6_term_node
+
+source:
+  plugin: d6_term_node
+
+process:
+  nid: nid
+  type: type
+  # The actual field name is dynamic and will be added by the load plugin.
+
+destination:
+  plugin: entity:node
+dependencies:
+  - d6_vocabulary_entity_display
+  - d6_vocabulary_entity_form_display
+  - d6_node
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_term_node_revision.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_term_node_revision.yml
new file mode 100644
index 0000000..8457615
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_term_node_revision.yml
@@ -0,0 +1,17 @@
+id: d6_term_node_revision
+load:
+  plugin: d6_term_node
+  bundle_migration: d6_vocabulary_field
+
+source:
+  plugin: d6_term_node_revision
+
+process:
+  vid: vid
+  # The actual field name is dynamic and will be added by the load plugin.
+
+destination:
+  plugin: entity_revision:node
+dependencies:
+  - d6_term_node
+  - d6_node_revision
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_text_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_text_settings.yml
index fb5dea5..e2e5fbd 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_text_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_text_settings.yml
@@ -1,10 +1,10 @@
 id: d6_text_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - teaser_length
 process:
   default_summary_length: teaser_length
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: text.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_update_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_update_settings.yml
index a3ab12a..6004b36 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_update_settings.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_update_settings.yml
@@ -1,16 +1,16 @@
 id: d6_update_settings
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - update_max_fetch_attempts
     - update_fetch_url
     - update_notification_threshold
     - update_notify_emails
 process:
-  'fetch:max_attempts': update_max_fetch_attempts
-  'fetch:url': update_fetch_url
-  'notification:threshold': update_notification_threshold
-  'notification:mails': update_notify_emails
+  'fetch.max_attempts': update_max_fetch_attempts
+  'fetch.url': update_fetch_url
+  'notification.threshold': update_notification_threshold
+  'notification.mails': update_notify_emails
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: update.settings
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_upload.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_upload.yml
new file mode 100644
index 0000000..9e381eb
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_upload.yml
@@ -0,0 +1,23 @@
+id: d6_upload
+
+source:
+  plugin: d6_upload
+
+process:
+  nid: nid
+  vid: vid
+  upload:
+    plugin: iterator
+    source: upload
+    process:
+      target_id:
+        plugin: migration
+        migration: d6_file
+        source: fid
+      display: list
+      description: description
+destination:
+  plugin: entity:node
+dependencies:
+  - d6_file
+  - d6_node
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_upload_entity_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_entity_display.yml
new file mode 100644
index 0000000..ccc26e4
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_entity_display.yml
@@ -0,0 +1,23 @@
+id: d6_upload_entity_display
+source:
+  plugin: d6_upload_instance
+  constants:
+    entity_type: node
+    view_mode: default
+    name: upload
+    type: file_default
+    options:
+      label: hidden
+      settings: {}
+process:
+  entity_type: constants.entity_type
+  bundle: node_type
+  view_mode: constants.view_mode
+  field_name: constants.name
+  type: constants.type
+  options: constants.options
+  'options.type': @type
+destination:
+  plugin: component_entity_display
+dependencies:
+  - d6_upload_field_instance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_upload_entity_form_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_entity_form_display.yml
new file mode 100644
index 0000000..01c78c6
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_entity_form_display.yml
@@ -0,0 +1,25 @@
+id: d6_upload_entity_form_display
+source:
+  plugin: d6_upload_instance
+  constants:
+    empty: {}
+    entity_type: node
+    form_mode: default
+    name: upload
+    type: file_generic
+    options:
+      label: hidden
+      settings:
+        progress_indicator: throbber
+process:
+  entity_type: constants.entity_type
+  bundle: node_type
+  field_name: constants.name
+  form_mode: constants.form_mode
+  type: constants.type
+  options: constants.options
+  'options.type': @type
+destination:
+  plugin: component_entity_form_display
+dependencies:
+  - d6_upload_field_instance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_upload_field.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_field.yml
new file mode 100644
index 0000000..f8d846d
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_field.yml
@@ -0,0 +1,20 @@
+id: d6_upload_field
+source:
+  # We do an empty source and a proper destination to have an idmap for
+  # dependencies.
+  plugin: empty
+  provider: upload
+  constants:
+    entity_type: node
+    type: file
+    name: upload
+    cardinality: -1
+    display_field: true
+process:
+  entity_type: constants.entity_type
+  name: constants.name
+  type: constants.type
+  cardinality: constants.cardinality
+  settings.display_field: constants.display_field
+destination:
+  plugin: entity:field_config
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_upload_field_instance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_field_instance.yml
new file mode 100644
index 0000000..0063db6
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_upload_field_instance.yml
@@ -0,0 +1,19 @@
+id: d6_upload_field_instance
+source:
+  plugin: d6_upload_instance
+  constants:
+    entity_type: node
+    name: upload
+    settings:
+      description_field: 1
+process:
+  entity_type: constants.entity_type
+  bundle: node_type
+  field_name: constants.name
+  settings: constants.settings
+  'settings.file_extensions': file_extensions
+  'settings.max_filesize': max_filesize
+destination:
+  plugin: entity:field_instance_config
+dependencies:
+  - d6_upload_field
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_url_alias.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_url_alias.yml
new file mode 100644
index 0000000..14a4a47
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_url_alias.yml
@@ -0,0 +1,11 @@
+id: d6_url_alias
+source:
+  plugin: d6_url_alias
+
+process:
+  source: src
+  alias: dst
+  langcode: language
+
+destination:
+  plugin: url_alias
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user.yml
new file mode 100644
index 0000000..ce0f8b8
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user.yml
@@ -0,0 +1,38 @@
+id: d6_user
+source:
+  plugin: d6_user
+process:
+  uid: uid
+  name: name
+  pass: pass
+  mail: mail
+  created: created
+  access: access
+  login: login
+  status: status
+  timezone:
+    plugin: user_update_7002
+    source: timezone
+  preferred_langcode: language
+  init: init
+  roles:
+    plugin: migration
+    migration: d6_user_role
+    source: roles
+  signature: signature
+  signature_format:
+    plugin: migration
+    migration: d6_filter_format
+    source: signature_format
+  user_picture:
+    plugin: d6_user_picture
+    source: uid
+destination:
+  plugin: entity:user
+  md5_passwords: true
+dependencies:
+  - d6_filter_format
+  - d6_user_role
+  - d6_user_picture_entity_display
+  - d6_user_picture_entity_form_display
+  - d6_user_picture_file: false
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_mail.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_mail.yml
index 1450402..75dee05 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_user_mail.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_mail.yml
@@ -1,6 +1,6 @@
 id: d6_user_mail
 source:
-  plugin: drupal6_variable
+  plugin: variable
   variables:
     - user_mail_status_activated_subject
     - user_mail_status_activated_body
@@ -17,20 +17,20 @@ source:
     - user_mail_status_blocked_subject
     - user_mail_status_blocked_body
 process:
-  'status_activated:subject': user_mail_status_activated_subject
-  'status_activated:body': user_mail_status_activated_body
-  'password_reset:subject': user_mail_password_reset_subject
-  'password_reset:body': user_mail_password_reset_body
-  'cancel_confirm:subject': user_mail_status_deleted_subject
-  'cancel_confirm:body': user_mail_status_deleted_body
-  'register_admin_created:subject': user_mail_register_admin_created_subject
-  'register_admin_created:body': user_mail_register_admin_created_body
-  'register_no_approval_required:subject': user_mail_register_no_approval_required_subject
-  'register_no_approval_required:body': user_mail_register_no_approval_required_body
-  'register_pending_approval:subject': user_mail_user_mail_register_pending_approval_subject
-  'register_pending_approval:body': user_mail_user_mail_register_pending_approval_body
-  'status_blocked:subject': user_mail_status_blocked_subject
-  'status_blocked:body': user_mail_status_blocked_body
+  'status_activated.subject': user_mail_status_activated_subject
+  'status_activated.body': user_mail_status_activated_body
+  'password_reset.subject': user_mail_password_reset_subject
+  'password_reset.body': user_mail_password_reset_body
+  'cancel_confirm.subject': user_mail_status_deleted_subject
+  'cancel_confirm.body': user_mail_status_deleted_body
+  'register_admin_created.subject': user_mail_register_admin_created_subject
+  'register_admin_created.body': user_mail_register_admin_created_body
+  'register_no_approval_required.subject': user_mail_register_no_approval_required_subject
+  'register_no_approval_required.body': user_mail_register_no_approval_required_body
+  'register_pending_approval.subject': user_mail_user_mail_register_pending_approval_subject
+  'register_pending_approval.body': user_mail_user_mail_register_pending_approval_body
+  'status_blocked.subject': user_mail_status_blocked_subject
+  'status_blocked.body': user_mail_status_blocked_body
 destination:
-  plugin: d8_config
+  plugin: config
   config_name: user.mail
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_entity_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_entity_display.yml
new file mode 100644
index 0000000..bb8dcd1
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_entity_display.yml
@@ -0,0 +1,26 @@
+id: d6_user_picture_entity_display
+source:
+  plugin: d6_user_picture_instance
+  constants:
+    entity_type: user
+    bundle: user
+    view_mode: default
+    name: user_picture
+    type: image
+    options:
+      label: hidden
+      settings:
+        image_style: ''
+        image_link: content
+process:
+  entity_type: constants.entity_type
+  bundle: constants.bundle
+  view_mode: constants.view_mode
+  field_name: constants.name
+  type: constants.type
+  options: constants.options
+  options.type: @type
+destination:
+  plugin: component_entity_display
+dependencies:
+  - d6_user_picture_field_instance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_entity_form_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_entity_form_display.yml
new file mode 100644
index 0000000..85a3f54
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_entity_form_display.yml
@@ -0,0 +1,26 @@
+id: d6_user_picture_entity_form_display
+source:
+  plugin: d6_user_picture_instance
+  constants:
+    entity_type: user
+    bundle: user
+    form_mode: default
+    name: user_picture
+    type: image_image
+    options:
+      label: hidden
+      settings:
+        progress_indicator: throbber
+        preview_image_style: thumbnail
+process:
+  entity_type: constants.entity_type
+  bundle: constants.bundle
+  field_name: constants.name
+  form_mode: constants.form_mode
+  type: constants.type
+  options: constants.options
+  options.type: @type
+destination:
+  plugin: component_entity_form_display
+dependencies:
+  - d6_user_picture_field_instance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_field.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_field.yml
new file mode 100644
index 0000000..a4629f3
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_field.yml
@@ -0,0 +1,17 @@
+id: d6_user_picture_field
+source:
+  # We do an empty source and a proper destination to have an idmap for
+  # dependencies.
+  plugin: empty
+  constants:
+    entity_type: user
+    type: image
+    name: user_picture
+    cardinality: 1
+process:
+  entity_type: constants.entity_type
+  name: constants.name
+  type: constants.type
+  cardinality: constants.cardinality
+destination:
+  plugin: entity:field_config
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_field_instance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_field_instance.yml
new file mode 100644
index 0000000..785fbe6
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_field_instance.yml
@@ -0,0 +1,26 @@
+id: d6_user_picture_field_instance
+source:
+  plugin: d6_user_picture_instance
+  constants:
+    entity_type: user
+    bundle: user
+    name: user_picture
+    settings:
+      file_extensions: 'png gif jpg jpeg'
+      alt_field: false
+      title_field: false
+      min_resolution: ''
+      alt_field_required: false
+      title_field_required: false
+process:
+  entity_type: constants.entity_type
+  bundle: constants.bundle
+  field_name: constants.name
+  settings: constants.settings
+  'settings.file_directory': file_directory
+  'settings.max_filesize': max_filesize
+  'settings.max_resolution': max_resolution
+destination:
+  plugin: entity:field_instance_config
+dependencies:
+  - d6_user_picture_field
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_file.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_file.yml
new file mode 100644
index 0000000..515d96b
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_picture_file.yml
@@ -0,0 +1,18 @@
+id: d6_user_picture_file
+source:
+  plugin: d6_user_picture_file
+  constants:
+    is_public: true
+process:
+  filename: filename
+  uri:
+    plugin: file_uri
+    source:
+      - picture
+      - file_directory_path
+      - constants.is_public
+destination:
+  plugin: entity:file
+  source_path_property: picture
+dependencies:
+  - d6_file: false
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_entity_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_entity_display.yml
new file mode 100644
index 0000000..975106a
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_entity_display.yml
@@ -0,0 +1,37 @@
+id: d6_user_profile_entity_display
+source:
+  plugin: d6_profile_field
+  constants:
+    entity_type: user
+    bundle: user
+    view_mode: default
+    options:
+      label: hidden
+      settings: {}
+process:
+  entity_type: constants.entity_type
+  bundle: constants.bundle
+  view_mode: constants.view_mode
+  field_name: name
+  type:
+    plugin: static_map
+    source: type
+    map:
+      checkbox: list_default
+      date: datetime_default
+      list: text_default
+      selection: list_default
+      textfield: text_default
+      textarea: text_default
+      url: link_default
+  options: constants.options
+  'options.type': @type
+  hidden:
+    plugin: static_map
+    source: visibility
+    default_value: false
+    map:
+      1: true # PROFILE_PRIVATE
+      4: true # PROFILE_HIDDEN
+destination:
+  plugin: component_entity_display
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_entity_form_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_entity_form_display.yml
new file mode 100644
index 0000000..bd813e4
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_entity_form_display.yml
@@ -0,0 +1,42 @@
+id: d6_user_profile_entity_form_display
+source:
+  plugin: d6_profile_field
+  constants:
+    empty: {}
+    entity_type: user
+    bundle: user
+    form_mode: default
+    options:
+      label: hidden
+process:
+  entity_type: constants.entity_type
+  bundle: constants.bundle
+  field_name: name
+  form_mode: constants.form_mode
+  type:
+    plugin: static_map
+    source: type
+    map:
+      checkbox: options_select
+      date: datetime_default
+      list: text_textfield
+      selection: options_select
+      textfield: text_textfield
+      textarea: text_textarea
+      url: link_default
+  options: constants.options
+  'options.type': @type
+  'options.settings':
+    plugin: field_instance_widget_settings
+    source:
+      - @type
+      - constants.empty # we don't have any settings.
+  hidden:
+    plugin: static_map
+    source: visibility
+    default_value: false
+    map:
+      1: true # PROFILE_PRIVATE
+      4: true # PROFILE_HIDDEN
+destination:
+  plugin: component_entity_form_display
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_field.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_field.yml
new file mode 100644
index 0000000..e1154c1
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_field.yml
@@ -0,0 +1,27 @@
+id: d6_user_profile_field
+source:
+  plugin: d6_profile_field
+  constants:
+    entity_type: user
+process:
+  entity_type: constants.entity_type
+  name: name
+  type:
+    plugin: static_map
+    source: type
+    map:
+      checkbox: list_integer
+      date: datetime
+      list: text
+      selection: list_text
+      textfield: text
+      textarea: text_long
+      url: link
+  cardinality:
+    plugin: static_map
+    default_value: 1
+    source: type
+    map:
+      list: -1
+destination:
+  plugin: entity:field_config
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_field_instance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_field_instance.yml
new file mode 100644
index 0000000..ddf69cb
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_profile_field_instance.yml
@@ -0,0 +1,17 @@
+id: d6_user_profile_field_instance
+source:
+  plugin: d6_profile_field
+  constants:
+    entity_type: user
+    bundle: user
+process:
+  entity_type: constants.entity_type
+  bundle: constants.bundle
+  label: title
+  description: explanation
+  field_name: name
+  required: required
+destination:
+  plugin: entity:field_instance_config
+dependencies:
+  - d6_user_profile_field
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_user_role.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_user_role.yml
index 3ee7334..b2372b5 100644
--- a/core/modules/migrate_drupal/config/migrate.migration.d6_user_role.yml
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_user_role.yml
@@ -1,15 +1,6 @@
 id: d6_user_role
-sourceIds:
-  rid:
-    type: int
-    "not null": true
-    default: 0
-destinationIds:
-  id:
-    type: varchar
-    length: 255
 source:
-  plugin: drupal6_user_role
+  plugin: d6_user_role
 process:
   id:
     -
@@ -19,20 +10,13 @@ process:
       plugin: dedupe_entity
       entity_type: user_role
       field: id
-  label: name
-# permissions start as array(array('perm' => array('perm1', 'perm2'))), array('perm' => array('perm3', 'perm4')))
-  permissions:
-    # extract gets array('perm' => array('perm1', 'perm2')) first
     -
-      plugin: extract
-      source: permissions
-      index:
-        - perm
-    # the pipeline is now array(array('perm1', 'perm2'))
-    - plugin: flatten
-    # the pipeline is now array('perm1', 'perm2')
+      plugin: user_update_8002
+  label: name
+  permissions:
     -
       plugin: static_map
+      source: permissions
       bypass: true
       map:
         'use PHP for block visibility': 'use PHP for settings'
@@ -50,6 +34,6 @@ process:
     - plugin: system_update_7000
     - plugin: node_update_7008
     - plugin: flatten
+    - plugin: filter_format_permission
 destination:
-  plugin: entity
-  entity_type: user_role
+  plugin: entity:user_role
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_view_modes.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_view_modes.yml
new file mode 100644
index 0000000..a0b39f0
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_view_modes.yml
@@ -0,0 +1,37 @@
+id: d6_view_modes
+source:
+  plugin: d6_view_mode
+  constants:
+    targetEntityType: node
+    status: true
+
+process:
+  mode:
+    plugin: static_map
+    source: view_mode
+    map:
+      0: normal
+      1: preview
+      2: search_index
+      3: search_result
+      4: rss
+      5: print
+      teaser: teaser
+      full: full
+  label:
+    plugin: static_map
+    source: view_mode
+    map:
+      0: "Normal"
+      1: "Preview"
+      2: "Search index"
+      3: "Search result"
+      4: "RSS"
+      5: "Print"
+      teaser: "Teaser"
+      full: "Full"
+  targetEntityType: constants.targetEntityType
+  status: constants.status
+
+destination:
+  plugin: entity:view_mode
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_entity_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_entity_display.yml
new file mode 100644
index 0000000..9256831
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_entity_display.yml
@@ -0,0 +1,24 @@
+id: d6_vocabulary_entity_display
+source:
+  plugin: d6_taxonomy_vocabulary_per_type
+  constants:
+    entity_type: node
+    view_mode: default
+    options:
+      label: hidden
+      type: taxonomy_term_reference
+      weight: 20
+
+process:
+  entity_type: constants.entity_type
+  view_mode: constants.view_mode
+  options: constants.options
+  bundle: type
+  field_name:
+    plugin: migration
+    migration: d6_taxonomy_vocabulary
+    source: vid
+destination:
+  plugin: component_entity_display
+dependencies:
+  - d6_vocabulary_field_instance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_entity_form_display.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_entity_form_display.yml
new file mode 100644
index 0000000..56b0e5c
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_entity_form_display.yml
@@ -0,0 +1,22 @@
+id: d6_vocabulary_entity_form_display
+source:
+  plugin: d6_taxonomy_vocabulary_per_type
+  constants:
+    entity_type: node
+    form_mode: default
+    options:
+      type: taxonomy_term_reference
+      weight: 20
+process:
+  entity_type: constants.entity_type
+  form_mode: constants.form_mode
+  options: constants.options
+  bundle: type
+  field_name:
+    plugin: migration
+    migration: d6_taxonomy_vocabulary
+    source: vid
+destination:
+  plugin: component_entity_form_display
+dependencies:
+  - d6_vocabulary_field_instance
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_field.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_field.yml
new file mode 100644
index 0000000..b4b244f
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_field.yml
@@ -0,0 +1,22 @@
+id: d6_vocabulary_field
+source:
+  plugin: d6_taxonomy_vocabulary
+  constants:
+    entity_type: node
+    type: taxonomy_term_reference
+    parent: 0
+    cardinality: -1
+process:
+  entity_type: constants.entity_type
+  type: constants.type
+  name:
+    plugin: migration
+    migration: d6_taxonomy_vocabulary
+    source: vid
+  'settings.allowed_values.0.vocabulary': @name
+  'settings.allowed_values.0.parent': constants.parent
+  cardinality: constants.cardinality
+destination:
+  plugin: entity:field_config
+dependencies:
+  - d6_taxonomy_vocabulary
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_field_instance.yml b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_field_instance.yml
new file mode 100644
index 0000000..7127ba2
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d6_vocabulary_field_instance.yml
@@ -0,0 +1,19 @@
+id: d6_vocabulary_field_instance
+source:
+  plugin: d6_taxonomy_vocabulary_per_type
+  constants:
+    entity_type: node
+    parent: 0
+process:
+  entity_type: constants.entity_type
+  bundle: type
+  field_name:
+    plugin: migration
+    migration: d6_taxonomy_vocabulary
+    source: vid
+  'settings.allowed_values.0.vocabulary': @field_name
+  'settings.allowed_values.0.parent': constants.parent
+destination:
+  plugin: entity:field_instance_config
+dependencies:
+  - d6_vocabulary_field
diff --git a/core/modules/migrate_drupal/config/migrate.migration.d7_tracker_settings.yml b/core/modules/migrate_drupal/config/migrate.migration.d7_tracker_settings.yml
new file mode 100644
index 0000000..3c355e7
--- /dev/null
+++ b/core/modules/migrate_drupal/config/migrate.migration.d7_tracker_settings.yml
@@ -0,0 +1,10 @@
+id: d7_tracker_settings
+source:
+  plugin: variable
+  variables:
+    - cron_index_limit
+process:
+  cron_index_limit: cron_index_limit
+destination:
+  plugin: config
+  config_name: tracker.settings
diff --git a/core/modules/migrate_drupal/drushmigratemessage.inc b/core/modules/migrate_drupal/drushmigratemessage.inc
new file mode 100644
index 0000000..09c832e
--- /dev/null
+++ b/core/modules/migrate_drupal/drushmigratemessage.inc
@@ -0,0 +1,9 @@
+<?php
+
+use Drupal\migrate\MigrateMessageInterface;
+
+class DrushMigrateMessage implements MigrateMessageInterface {
+  public function display($message, $type = 'status') {
+    drush_log($message, $type);
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Entity/Migration.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Entity/Migration.php
new file mode 100644
index 0000000..7875ddf
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Entity/Migration.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Entity\Migration.
+ */
+
+namespace Drupal\migrate_drupal\Entity;
+
+use Drupal\migrate\Entity\Migration as BaseMigration;
+
+class Migration extends BaseMigration implements MigrationInterface {
+
+  /**
+   * The load plugin configuration, if any.
+   *
+   * @var array
+   */
+  public $load = array();
+
+  /**
+   * The load plugin.
+   *
+   * @var \Drupal\migrate_drupal\Plugin\MigrateLoadInterface|false
+   */
+  protected $loadPlugin = FALSE;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLoadPlugin() {
+    if ($this->load && !$this->loadPlugin) {
+      $this->loadPlugin = \Drupal::service('plugin.manager.migrate.load')->createInstance($this->load['plugin'], $this->load, $this);
+    }
+    return $this->loadPlugin;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Entity/MigrationInterface.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Entity/MigrationInterface.php
new file mode 100644
index 0000000..e59631e
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Entity/MigrationInterface.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * @file
+ * Contains
+ */
+
+namespace Drupal\migrate_drupal\Entity;
+
+use Drupal\migrate\Entity\MigrationInterface as BaseMigrationInterface;
+
+interface MigrationInterface extends BaseMigrationInterface {
+
+  /**
+   * Returns the initialized load plugin if there's one.
+   *
+   * @return \Drupal\migrate_drupal\Plugin\MigrateLoadInterface|false
+   */
+  public function getLoadPlugin();
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalRunForm.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalRunForm.php
new file mode 100644
index 0000000..709bb96
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalRunForm.php
@@ -0,0 +1,142 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Form\MigrateDrupalRun.
+ */
+
+namespace Drupal\migrate_drupal\Form;
+
+use Drupal\Component\Utility\MapArray;
+use Drupal\Core\Database\Database;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Form\FormBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+class MigrateDrupalRunForm extends FormBase {
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $storageController;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'migrate_drupal_run_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    // The multistep is for testing only. The final version will run a fixed
+    // set of migrations.
+    if (isset($form_state['database'])) {
+      Database::addConnectionInfo('migrate', 'default', $form_state['database']);
+      $migrations = $this->storageController()->loadMultiple();
+      $form['migrations'] = array(
+        '#type' => 'checkboxes',
+        '#options' => MapArray::copyValuesToKeys(array_keys($migrations)),
+      );
+    }
+    else {
+      $form['db_url'] = array(
+        '#type' => 'textfield',
+        '#title' => $this->t('Database URL from D6'),
+        '#size' => 40,
+      );
+    }
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+    );
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    if (isset($form_state['values']['db_url'])) {
+      $form_state['rebuild'] = TRUE;
+      $form_state['database'] = $this->convertDbUrl($form_state['values']['db_url']);
+    }
+    else {
+      $migration_ids = array_keys(array_filter($form_state['values']['migrations']));
+      $batch = array(
+        'title' => t('Running migrations'),
+        'operations' => array(
+          array(array('Drupal\migrate_drupal\MigrateDrupalRunBatch', 'run'), array($migration_ids, $form_state['database'])),
+        ),
+        'finished' => array('Drupal\migrate_drupal\MigrateDrupalRunBatch', 'finished'),
+        'progress_message' => '',
+        'init_message' => t('Processing migration @num of @max.', array('@num' => '1', '@max' => count($migration_ids))),
+      );
+      $this->batchSet($batch);
+    }
+  }
+
+  /**
+   * Converts a D6 database URL to a new style DB configuration array.
+   *
+   * @param $db_url
+   *  The D6 database url.
+   * @return array
+   *   The new style database array.
+   */
+  protected function convertDbUrl($db_url) {
+    $url = parse_url($db_url);
+    // Fill in defaults to prevent notices.
+    $url += array(
+      'driver' => NULL,
+      'user' => NULL,
+      'pass' => NULL,
+      'host' => NULL,
+      'port' => NULL,
+      'path' => NULL,
+      'database' => NULL,
+    );
+    $url = (object) array_map('urldecode', $url);
+    return array(
+      'driver' => $url->scheme == 'mysqli' ? 'mysql' : $url->scheme,
+      'username' => $url->user,
+      'password' => $url->pass,
+      'port' => $url->port,
+      'host' => $url->host,
+
+      'database' => substr($url->path, 1),
+    );
+  }
+
+  /**
+   * Set a batch.
+   *
+   * @param $batch
+   */
+  protected function batchSet($batch) {
+    batch_set($batch);
+  }
+
+  /**
+   * @return EntityStorageControllerInterface
+   */
+  protected function storageController() {
+    if (!isset($this->storageController)) {
+      $this->storageController = \Drupal::entityManager()->getStorageController('migration');
+    }
+    return $this->storageController;
+  }
+
+  /**
+   * Returns the properties to be serialized
+   *
+   * @return array
+   */
+  public function __sleep() {
+    // This apparently contains a PDOStatement somewhere.
+    unset($this->storageController);
+    return parent::__sleep();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/MigrateDrupalRunBatch.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/MigrateDrupalRunBatch.php
new file mode 100644
index 0000000..7578161
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/MigrateDrupalRunBatch.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\MigrateDrupalRunBatch.
+ */
+
+namespace Drupal\migrate_drupal;
+
+use Drupal\Core\Database\Database;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateMessage;
+
+class MigrateDrupalRunBatch {
+
+  /**
+   * @param $initial_ids
+   *   The initial migration IDs.
+   * @param $db_spec
+   *   The database specification pointing to the old Drupal database.
+   * @param $context
+   *   The batch context.
+   */
+  public static function run($initial_ids, $db_spec, &$context) {
+    Database::addConnectionInfo('migrate', 'default', $db_spec);
+    if (!isset($context['sandbox']['migration_ids'])) {
+      $context['sandbox']['max'] = count($initial_ids);
+      $context['sandbox']['migration_ids'] = $initial_ids;
+    }
+    $migration_id = reset($context['sandbox']['migration_ids']);
+    $migration = entity_load('migration', $migration_id);
+    // @TODO: if there are no source IDs then remove php.ini time limit.
+    // @TODO: move time limit back into MigrateExecutable so we can set it here.
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    if ($executable->import() == MigrationInterface::RESULT_COMPLETED) {
+      array_shift($context['sandbox']['migration_ids']);
+    }
+    $context['finished'] = 1 - count($context['sandbox']['migration_ids']) / $context['sandbox']['max'];
+  }
+
+  /**
+   * @param $success
+   * @param $results
+   * @param $operations
+   * @param $elapsed
+   */
+  public static function finished($success, $results, $operations, $elapsed) {
+
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/MigrationStorageController.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/MigrationStorageController.php
new file mode 100644
index 0000000..08e5d63
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/MigrationStorageController.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\MigrateStorageController.
+ */
+
+namespace Drupal\migrate_drupal;
+
+use Drupal\Component\Utility\String;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageException;
+use Drupal\migrate\MigrationStorageController as BaseMigrationStorageController;
+
+/**
+ * Storage controller for migration entities.
+ */
+class MigrationStorageController extends BaseMigrationStorageController {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function loadMultiple(array $ids = NULL) {
+    $ids_to_load = array();
+    $dynamic_ids = array();
+    if (isset($ids)) {
+      foreach ($ids as $id) {
+        // Evaluate whether or not this migration is dynamic in the form of
+        // migration_id:* to load all the additional migrations.
+        if (($n = strpos($id, ':')) !== FALSE) {
+          $base_id = substr($id, 0, $n);
+          $ids_to_load[] = $base_id;
+          // Get the ids of the additional migrations.
+          $sub_id = substr($id, $n + 1);
+          if ($sub_id == '*') {
+            // If the id of the additional migration is '*', get all of them.
+            $dynamic_ids[$base_id] = NULL;
+          }
+          elseif (!isset($dynamic_ids[$base_id]) || is_array($dynamic_ids[$base_id])) {
+            $dynamic_ids[$base_id][] = $sub_id;
+          }
+        }
+        else {
+          $ids_to_load[] = $id;
+        }
+      }
+      $ids = array_flip($ids);
+    }
+    else {
+      $ids_to_load = NULL;
+    }
+
+    /** @var \Drupal\migrate_drupal\Entity\MigrationInterface[] $entities */
+    $entities = parent::loadMultiple($ids_to_load);
+    if (!isset($ids)) {
+      // Changing the array being foreach()'d is not a good idea.
+      $return = array();
+      foreach ($entities as $entity_id => $entity) {
+        if ($plugin = $entity->getLoadPlugin()) {
+          $new_entities = $plugin->loadMultiple($this);
+          $this->getDynamicIds($dynamic_ids, $new_entities);
+          $return += $new_entities;
+        }
+        else {
+          $return[$entity_id] = $entity;
+        }
+      }
+      $entities = $return;
+    }
+    else {
+      foreach ($dynamic_ids as $base_id => $sub_ids) {
+        $entity = $entities[$base_id];
+        if ($plugin = $entity->getLoadPlugin()) {
+          unset($entities[$base_id]);
+          $new_entities = $plugin->loadMultiple($this, $sub_ids);
+          if (!isset($sub_ids)) {
+            unset($dynamic_ids[$base_id]);
+            $this->getDynamicIds($dynamic_ids, $new_entities);
+          }
+          $entities += $new_entities;
+        }
+      }
+    }
+
+    // Build an array of dependencies and set the order of the migrations.
+    return $this->buildDependencyMigration($entities, $dynamic_ids);
+  }
+
+  /**
+   * Extract the dynamic id mapping from entities loaded by plugin.
+   *
+   * @param array $dynamic_ids
+   *   Get the dynamic migration ids.
+   * @param array $entities
+   *   An array of entities.
+   */
+  protected function getDynamicIds(array &$dynamic_ids, array $entities) {
+    foreach (array_keys($entities) as $new_id) {
+      list($base_id, $sub_id) = explode(':', $new_id, 2);
+      $dynamic_ids[$base_id][] = $sub_id;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(EntityInterface $entity) {
+    if (strpos($entity->id(), ':') !== FALSE) {
+      throw new EntityStorageException(String::format("Dynamic migration %id can't be saved", array('$%id' => $entity->id())));
+    }
+    return parent::save($entity);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/MigrateLoadInterface.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/MigrateLoadInterface.php
new file mode 100644
index 0000000..ee40c6d
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/MigrateLoadInterface.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\migrate\Plugin\MigrateLoadInterface
+ */
+
+namespace Drupal\migrate_drupal\Plugin;
+
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+
+interface MigrateLoadInterface {
+
+  /**
+   * Load an additional migration.
+   *
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
+   *   The migration storage controller.
+   * @param string $sub_id
+   *   For example, when loading d6_node:article, this will be article.
+   * @return \Drupal\migrate\Entity\MigrationInterface
+   */
+  public function load(EntityStorageControllerInterface $storage_controller, $sub_id);
+
+  /**
+   * Load additional migrations.
+   *
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
+   *   The migration storage controller.
+   * @param array $sub_ids
+   *   For example, when loading d6_node:article, sub_id will be article.
+   *   If NULL then load all sub-migrations.
+   * @return \Drupal\migrate\Entity\MigrationInterface[]
+   */
+  public function loadMultiple(EntityStorageControllerInterface $storage_controller, array $sub_ids = NULL);
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/load/LoadEntity.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/load/LoadEntity.php
new file mode 100644
index 0000000..d0d7389
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/load/LoadEntity.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\load\LoadEntity.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\load;
+
+use Drupal\Component\Utility\String;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Plugin\PluginBase;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\Plugin\SourceEntityInterface;
+use Drupal\migrate_drupal\Plugin\MigrateLoadInterface;
+
+/**
+ * Base class for entity load plugins.
+ *
+ * @PluginID("drupal_entity")
+ */
+class LoadEntity extends PluginBase implements MigrateLoadInterface {
+
+  /**
+   * The list of bundles being loaded.
+   *
+   * @var array
+   */
+  protected $bundles;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
+    $this->migration = $migration;
+    $source_plugin = $this->migration->getSourcePlugin();
+    if (!$source_plugin instanceof SourceEntityInterface) {
+      throw new MigrateException('Migrations with a load plugin using LoadEntity should have an entity as source.');
+    }
+    if ($source_plugin->bundleMigrationRequired() && empty($configuration['bundle_migration'])) {
+      throw new MigrateException(String::format('Source plugin @plugin requires the bundle_migration key to be set.', array('@plugin' => $source_plugin->getPluginId())));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load(EntityStorageControllerInterface $storage_controller, $sub_id) {
+    $entities = $this->loadMultiple($storage_controller, array($sub_id));
+    return isset($entities[$sub_id]) ? $entities[$sub_id] : FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function loadMultiple(EntityStorageControllerInterface $storage_controller, array $sub_ids = NULL) {
+    // This entity type has no bundles ('user', 'feed', etc).
+    if (isset($this->configuration['bundle_migration'])) {
+      /** @var \Drupal\migrate\Entity\MigrationInterface $bundle_migration */
+      $bundle_migration = $storage_controller->load($this->configuration['bundle_migration']);
+      $source_id = array_keys($bundle_migration->getSourcePlugin()->getIds())[0];
+      $this->bundles = array();
+      foreach ($bundle_migration->getSourcePlugin()->getIterator() as $row) {
+        $this->bundles[] = $row[$source_id];
+      }
+    }
+    else {
+      $this->bundles = array($this->migration->getSourcePlugin()->entityTypeId());
+    }
+    $sub_ids_to_load = isset($sub_ids) ? array_intersect($this->bundles, $sub_ids) : $this->bundles;
+    $migrations = array();
+    foreach ($sub_ids_to_load as $id) {
+      $values = $this->migration->getExportProperties();
+      $values['id'] = $this->migration->id() . ':' . $id;
+      $values['source']['bundle'] = $id;
+      /** @var \Drupal\migrate\Entity\MigrationInterface $migration */
+      $migration = $storage_controller->create($values);
+      $fields = array_keys($migration->getSourcePlugin()->fields());
+      $migration->process += array_combine($fields, $fields);
+      $migrations[$migration->id()] = $migration;
+    }
+
+    return $migrations;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/load/d6/LoadTermNode.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/load/d6/LoadTermNode.php
new file mode 100644
index 0000000..a5b9ce7
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/load/d6/LoadTermNode.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\load\d6\TermNode.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\load\d6;
+
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\load\LoadEntity;
+
+/**
+ * @PluginID("d6_term_node")
+ */
+class LoadTermNode extends LoadEntity {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
+    $configuration['bundle_migration'] = 'd6_taxonomy_vocabulary';
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function loadMultiple(EntityStorageControllerInterface $storage_controller, array $sub_ids = NULL) {
+    /** @var \Drupal\migrate\Entity\MigrationInterface $bundle_migration */
+    $bundle_migration = $storage_controller->load('d6_taxonomy_vocabulary');
+    $migrate_executable = new MigrateExecutable($bundle_migration, new MigrateMessage());
+    $process = array_intersect_key($bundle_migration->get('process'), $bundle_migration->getDestinationPlugin()->getIds());
+    $migrations = array();
+    foreach ($bundle_migration->getSourcePlugin()->getIterator() as $source_row) {
+      $row = new Row($source_row, $source_row);
+      $migrate_executable->processRow($row, $process);
+      $new_vid = $row->getDestinationProperty('vid');
+      $old_vid = $source_row['vid'];
+      $values = $this->migration->getExportProperties();
+      $migration_id = $this->migration->id() . ':' . $old_vid;
+      $values['id'] = $migration_id;
+      $values['source']['vid'] = $old_vid;
+      $values['process'][$new_vid] = 'tid';
+      $migrations[$migration_id] = $storage_controller->create($values);;
+    }
+
+    return $migrations;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockPluginId.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockPluginId.php
new file mode 100644
index 0000000..e571819
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockPluginId.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\BlockAggregator.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_block_plugin_id"
+ * )
+ */
+class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * @var \Drupal\migrate\Plugin\MigratePluginManager
+   */
+  protected $processPluginManager;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $customBlockStorageController;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageControllerInterface $storage_controller, MigratePluginManager $process_plugin_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->customBlockStorageController = $storage_controller;
+    $this->migration = $migration;
+    $this->processPluginManager = $process_plugin_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('entity.manager')->getStorageController('custom_block'),
+      $container->get('plugin.manager.migrate.process')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the block plugin id.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value)) {
+      list($module, $delta) = $value;
+      switch ($module) {
+        case 'aggregator':
+          list($type, $id) = explode('-', $delta);
+          if ($type == 'category') {
+            // @TODO skip row.
+            // throw new MigrateSkipRowException();
+          }
+          $value = 'aggregator_feed_block';
+          break;
+        case 'menu':
+          $value = "system_menu_block:$delta";
+          break;
+        case 'block':
+          $block_ids = $this->processPluginManager
+            ->createInstance('migration', array('migration' => 'd6_custom_block'), $this->migration)
+            ->transform($delta, $migrate_executable, $row, $destination_property);
+          $value = 'custom_block:' . $this->customBlockStorageController->load($block_ids[0])->uuid();
+          break;
+        default:
+          // @TODO skip row.
+          // throw new MigrateSkipRowException();
+      }
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockSettings.php
new file mode 100644
index 0000000..c039d68
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockSettings.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @file
+ * Contains
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_block_settings"
+ * )
+ */
+class BlockSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the block configuration.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($plugin, $delta, $old_settings) = $value;
+    $settings = array();
+    switch ($plugin) {
+      case 'aggregator_feed_block':
+        list(, $id) = explode('-', $delta);
+        $settings['block_count'] = $old_settings['aggregator']['item_count'];
+        $settings['feed'] = $id;
+        break;
+      case 'book_navigation':
+        $settings['block_mode'] = $old_settings['book']['block_mode'];
+        break;
+      case 'forum_active_block':
+      case 'forum_new_block':
+        $settings['block_count'] = $old_settings['forum']['block_num'];
+        break;
+      case 'statistics_popular_block':
+        $settings['top_day_num'] = $old_settings['statistics']['statistics_block_top_day_num'];
+        $settings['top_all_num'] = $old_settings['statistics']['statistics_block_top_all_num'];
+        $settings['top_last_num'] = $old_settings['statistics']['statistics_block_top_last_num'];
+        break;
+      case 'views_block:who_s_new-block_1':
+        $settings['items_per_page'] = $old_settings['user']['block_whois_new_count'];
+        break;
+      case 'views_block:who_s_online-who_s_online_block':
+        $settings['items_per_page'] = $old_settings['user']['max_list_count'];
+        break;
+    }
+    return $settings;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldFormatterSettingsDefaults.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldFormatterSettingsDefaults.php
new file mode 100644
index 0000000..6d45c61
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldFormatterSettingsDefaults.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\process\d6\FieldSettingsDefaults.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+
+/**
+ * Set the default field settings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_formatter_settings_defaults"
+ * )
+ */
+class FieldFormatterSettingsDefaults extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set field formatter settings when the map didn't map: for date
+   * formatters, the fallback format, for everything else, empty array.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    // If the 1 index is set then the map missed.
+    if (isset($value[1])) {
+      $value = $row->getSourceProperty('module') == 'date' ? array('format' => 'fallback') : array();
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldIdGenerator.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldIdGenerator.php
new file mode 100644
index 0000000..039562b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldIdGenerator.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FieldIdGenerator.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Generate the file name for field config entities.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_id_generator"
+ * )
+ */
+class FieldIdGenerator extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    return $value[0] . "." . $value[1];
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceDefaults.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceDefaults.php
new file mode 100644
index 0000000..141eb28
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceDefaults.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\migrate_drupal\Plugin\migrate\d6\FieldInstanceDefaults
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_field_instance_defaults"
+ * )
+ */
+class FieldInstanceDefaults extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the field instance defaults.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($widget_type, $widget_settings) = $value;
+    $default = array();
+
+    switch ($widget_type) {
+      case 'text_textfield':
+      case 'number':
+      case 'phone_textfield':
+        $default['value'] = $widget_settings['default_value'][0]['value'];
+        break;
+
+      case 'imagefield_widget':
+        // @todo, load the image and populate the defaults.
+        // $default['default_image'] = $widget_settings['default_image'];
+        break;
+
+      case 'date_select':
+        $default['value'] = $widget_settings['default_value'];
+        break;
+
+      case 'email_textfield':
+        $default['value'] = $widget_settings['default_value'][0]['email'];
+        break;
+
+      case 'link':
+        $default['title'] = $widget_settings['default_value'][0]['title'];
+        $default['url'] = $widget_settings['default_value'][0]['url'];
+        break;
+    }
+    return array($default);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceSettings.php
new file mode 100644
index 0000000..7f16cef
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceSettings.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\migrate_drupal\Plugin\migrate\d6\FieldInstanceSettings
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_field_instance_settings"
+ * )
+ */
+class FieldInstanceSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the field instance defaults.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($widget_type, $widget_settings, $field_settings) = $value;
+    $settings = array();
+    switch ($widget_type) {
+      case 'text_textfield':
+        $settings['text_processing'] = $field_settings['text_processing'];
+        break;
+
+      case 'number':
+        $settings['min'] = $field_settings['min'];
+        $settings['max'] = $field_settings['max'];
+        $settings['prefix'] = $field_settings['prefix'];
+        $settings['suffix'] = $field_settings['suffix'];
+        break;
+
+      case 'link':
+        // $settings['url'] = $widget_settings['default_value'][0]['url'];
+        // D6 has optional, required, value and none. D8 only has disabled (0)
+        // optional (1) and required (2).
+        $map = array('disabled' => 0, 'optional' => 1, 'required' => 2);
+        $settings['title'] = $map[$field_settings['title']];
+        break;
+
+      case 'filefield_widget':
+        $settings['file_extensions'] = $widget_settings['file_extensions'];
+        $settings['file_directory'] = $widget_settings['file_path'];
+        $settings['description_field'] = $field_settings['description_field'];
+        $settings['max_filesize'] = $this->convertSizeUnit($widget_settings['max_filesize_per_file']);
+        break;
+
+      case 'imagefield_widget':
+        $settings['file_extensions'] = $widget_settings['file_extensions'];
+        $settings['file_directory'] = 'public://';
+        $settings['max_filesize'] = $this->convertSizeUnit($widget_settings['max_filesize_per_file']);
+        $settings['alt_field'] = $widget_settings['alt'];
+        $settings['alt_field_required'] = $widget_settings['custom_alt'];
+        $settings['title_field'] = $widget_settings['title'];
+        $settings['title_field_required'] = $widget_settings['custom_title'];
+        $settings['max_resolution'] = $widget_settings['max_resolution'];
+        $settings['min_resolution'] = $widget_settings['min_resolution'];
+        break;
+
+    }
+    return $settings;
+  }
+
+  /**
+   * Convert file size strings into their D8 format.
+   *
+   * D6 stores file size using a "K" for kilobytes and "M" for megabytes where
+   * as D8 uses "KB" and "MB" respectively.
+   *
+   * @param string $size_string
+   *   The size string, eg 10M
+   *
+   * @return string
+   *   The D8 version of the size string.
+   */
+  protected function convertSizeUnit($size_string) {
+    $size_unit = substr($size_string, strlen($size_string) - 1);
+    if ($size_unit == "M" || $size_unit == "K") {
+      return $size_string . "B";
+    }
+    return $size_string;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceWidgetSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceWidgetSettings.php
new file mode 100644
index 0000000..4352483
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceWidgetSettings.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FieldInstanceWidgetSettings
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Get the field instance widget settings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_instance_widget_settings"
+ * )
+ */
+class FieldInstanceWidgetSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Get the field instance default/mapped widget settings.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($widget_type, $widget_settings) = $value;
+    return $this->getSettings($widget_type, $widget_settings);
+  }
+
+  /**
+   * Merge the default D8 and specified D6 settings for a widget type.
+   *
+   * @param string $widget_type
+   *   The widget type.
+   * @param array $widget_settings
+   *   The widget settings from D6 for this widget.
+   *
+   * @return array
+   *   A valid array of settings.
+   */
+  public function getSettings($widget_type, $widget_settings) {
+    $progress = isset($widget_settings['progress_indicator']) ? $widget_settings['progress_indicator'] : 'throbber';
+    $size = isset($widget_settings['size']) ? $widget_settings['size'] : 60;
+    $rows = isset($widget_settings['rows']) ? $widget_settings['rows'] : 5;
+
+    $settings = array(
+      'text_textfield' => array(
+        'size' => $size,
+        'placeholder' => '',
+      ),
+      'text_textarea' => array(
+        'rows' => $rows,
+        'placeholder' => '',
+      ),
+      'number' => array(
+        'placeholder' => '',
+      ),
+      'email_textfield' => array(
+        'placeholder' => '',
+      ),
+      'link' => array(
+        'placeholder_uri' => '',
+        'placeholder_title' => '',
+      ),
+      'filefield_widget' => array(
+        'progress_indicator' => $progress,
+      ),
+      'imagefield_widget' => array(
+        'progress_indicator' => $progress,
+        'preview_image_style' => 'thumbnail',
+      ),
+      'optionwidgets_onoff' => array(
+        'display_label' => FALSE,
+      ),
+      'phone_textfield' => array(
+        'placeholder' => '',
+      ),
+    );
+
+    return isset($settings[$widget_type]) ? $settings[$widget_type] : array();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldSettings.php
new file mode 100644
index 0000000..e73bab0
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldSettings.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FieldSettings
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Get the field settings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_settings"
+ * )
+ */
+class FieldSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Get the field default/mapped settings.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($field_type, $global_settings, $widget_settings) = $value;
+    return $this->getSettings($field_type, $global_settings, $widget_settings);
+  }
+
+  /**
+   * Merge the default D8 and specified D6 settings.
+   *
+   * @param string $field_type
+   *   The field type.
+   * @param array $global_settings
+   *   The field settings.
+   * @param array $widget_settings
+   *   The widget settings needed for some settings.
+   *
+   * @return array
+   *   A valid array of settings.
+   */
+  public function getSettings($field_type, $global_settings, $widget_settings) {
+    $image_label = isset($widget_settings['alt']) ? $widget_settings['alt'] : '';
+    $title_label = isset($widget_settings['title']) ? $widget_settings['title'] : '';
+    $max_length = isset($global_settings['max_length']) ? $global_settings['max_length'] : '';
+    $max_length = empty($max_length) ? 255 : $max_length;
+
+    $settings = array(
+      'text' => array(
+        'max_length' => $max_length,
+      ),
+      'image' => array(
+        'column_groups' => array(
+          'alt' => array('label' => $image_label),
+          'title' => array('label' => $title_label),
+        ),
+      ),
+      'datetime' => array('datetime_type' => 'datetime'),
+    );
+
+
+    return isset($settings[$field_type]) ? $settings[$field_type] : array();
+  }
+}
\ No newline at end of file
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldTypeDefaults.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldTypeDefaults.php
new file mode 100644
index 0000000..085eda9
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldTypeDefaults.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\process\d6\FieldTypeDefaults.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+
+/**
+ * Gives us a change to set per field defaults.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_type_defaults"
+ * )
+ */
+class FieldTypeDefaults extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value)) {
+      if ($row->getSourceProperty('module') == 'date') {
+        $value = 'date_default';
+      }
+      else {
+        throw new MigrateException(sprintf('Lookup failed for %s', var_export($value, TRUE)));
+      }
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileImageHandler.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileImageHandler.php
new file mode 100644
index 0000000..752fb4e
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileImageHandler.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\system_update_7000.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Decide if it's an image or a file when coming from a D6 filefield.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "file_image_handler"
+ * )
+ */
+class FileImageHandler extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+
+    // If it's an array then the map missed.
+    if (is_array($value)) {
+
+      // Filefields in D6 have no way to tell if it's an image or file so we
+      // have to look at the widget type as well.
+      if ($row->getSourceProperty('module') == 'filefield') {
+        $widget_type = $row->getSourceProperty('widget_type');
+        $value = $widget_type == "imagefield_widget" ? "image" : "file";
+      }
+      else {
+        throw new MigrateException(sprintf('Lookup failed for %s', $value));
+      }
+    }
+
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileUri.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileUri.php
new file mode 100644
index 0000000..5383d56
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileUri.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FileUri.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Process the file url into a D8 compatible URL.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "file_uri"
+ * )
+ */
+class FileUri extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+
+    list($filepath, $file_directory_path, $is_public) = $value;
+
+    // Strip the files path from the uri instead of using basename
+    // so any additional folders in the path are preserved.
+    $uri = preg_replace('/^' . preg_quote($file_directory_path, '/') . '/', '', $filepath);
+
+    return $is_public ? "public://$uri" : "private://$uri";
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FilterFormatPermission.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FilterFormatPermission.php
new file mode 100644
index 0000000..d83044f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FilterFormatPermission.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FilterFormatRole.
+ */
+
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Plugin\MigrateProcessInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Migrate filter format serial to string id in permission name.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "filter_format_permission",
+ *   handle_multiples = TRUE
+ * )
+ */
+class FilterFormatPermission extends ProcessPluginBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The migration plugin.
+   *
+   * @var \Drupal\migrate\Plugin\MigrateProcessInterface
+   */
+  protected $migrationPlugin;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, MigrateProcessInterface $migration_plugin) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->migration = $migration;
+    $this->migrationPlugin = $migration_plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('plugin.manager.migrate.process')->createInstance('migration', array('migration' => 'd6_filter_format'), $migration)
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Migrate filter format serial to string id in permission name.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    $rid = $row->getSourceProperty('rid');
+    if ($formats = $row->getSourceProperty("filter_permissions:$rid")) {
+      foreach ($formats as $format) {
+        $new_id = $this->migrationPlugin->transform(array($format), $migrate_executable, $row, $destination_property);
+        if ($new_id) {
+          $value[] = 'use text format ' . $new_id[0];
+        }
+      }
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/SearchConfigurationRankings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/SearchConfigurationRankings.php
new file mode 100644
index 0000000..1fdb59f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/SearchConfigurationRankings.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\SearchPage.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+
+/**
+ * Generate configuration rankings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "d6_search_configuration_rankings"
+ * )
+ */
+class SearchConfigurationRankings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Generate the configuration rankings.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    $return = array();
+    foreach ($row->getSource() as $name => $rank) {
+      if (substr($name, 0, 10) == 'node_rank_' && $rank) {
+        $return[substr($name, 10)] = $rank;
+      }
+    }
+    return $return;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserPicture.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserPicture.php
new file mode 100644
index 0000000..b73ef56
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserPicture.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\UserPicture.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Plugin\MigrateProcessInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Split the 'administer nodes' permission from 'access content overview'.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "d6_user_picture"
+ * )
+ */
+class UserPicture extends ProcessPluginBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The migration plugin.
+   *
+   * @var \Drupal\migrate\Plugin\MigrateProcessInterface
+   */
+  protected $migrationPlugin;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, MigrateProcessInterface $migration_plugin) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->migration = $migration;
+    $this->migrationPlugin = $migration_plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('plugin.manager.migrate.process')->createInstance('migration', array('migration' => 'd6_user_picture_file'), $migration)
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Split the 'administer nodes' permission from 'access content overview'.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    return $row->getSourceProperty('picture') ? $this->migrationPlugin->transform($value, $migrate_executable, $row, $destination_property) : NULL;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate7002.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate7002.php
new file mode 100644
index 0000000..5deb1fe
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate7002.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\UserUpdate7002.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Converts user time zones from time zone offsets to time zone names.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "user_update_7002"
+ * )
+ */
+class UserUpdate7002 extends ProcessPluginBase {
+
+  /**
+   * System timezones.
+   *
+   * @var array
+   */
+  protected static $timezones;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    if (!isset(static::$timezones)) {
+      static::$timezones = system_time_zones();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    $timezone = NULL;
+
+    if ($row->hasSourceProperty('timezone_name')) {
+      if (isset(static::$timezones[$row->getSourceProperty('timezone_name')])) {
+        $timezone = $row->getSourceProperty('timezone_name');
+      }
+    }
+    if (!$timezone && $row->hasSourceProperty('event_timezone')) {
+      if (isset(static::$timezones[$row->getSourceProperty('event_timezone')])) {
+        $timezone = $row->getSourceProperty('event_timezone');
+      }
+    }
+
+    return $timezone;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate8002.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate8002.php
new file mode 100644
index 0000000..cce55ed
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate8002.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\UserUpdate8002.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Keep the predefined roles for rid 1 and 2.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "user_update_8002"
+ * )
+ */
+class UserUpdate8002 extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Keep the predefined roles for rid 1 and 2.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    $rid = $row->getSourceProperty('rid');
+    $map = array(
+      1 => 'anonymous',
+      2 => 'authenticated',
+    );
+    return isset($map[$rid]) ? $map[$rid] : $value;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/DrupalSqlBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/DrupalSqlBase.php
new file mode 100644
index 0000000..e4ca7f1
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/DrupalSqlBase.php
@@ -0,0 +1,151 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Drupal6SqlBase.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Plugin\migrate\source\SqlBase;
+use Drupal\migrate\Plugin\RequirementsInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * A base source class for Drupal migrate sources.
+ *
+ * Mainly to let children retrieve information from the origin system in an
+ * easier way.
+ */
+abstract class DrupalSqlBase extends SqlBase implements ContainerFactoryPluginInterface, RequirementsInterface {
+
+   /**
+   * The contents of the system table.
+   *
+   * @var array
+   */
+  protected $systemData;
+
+  /**
+   * If the source provider is missing.
+   *
+   * @var bool
+   */
+  protected $requirements = TRUE;
+
+  /**
+    * Retrieves all system data information from origin system.
+    *
+    * @return array
+    *   List of system table information keyed by type and name.
+    */
+   public function getSystemData() {
+    if (!isset($this->systemData)) {
+      $this->systemData = array();
+      try {
+        $results = $this->select('system', 's')
+          ->fields('s')
+          ->execute();
+        foreach ($results as $result) {
+          $this->systemData[$result['type']][$result['name']] = $result;
+        }
+      }
+      catch (\Exception $e) {
+        // The table might not exist for example in tests.
+      }
+    }
+    return $this->systemData;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration = NULL) {
+    $plugin = new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration
+    );
+    /** @var \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase $plugin */
+    if ($plugin_definition['requirements_met'] === TRUE) {
+      if (isset($plugin_definition['source_provider'])) {
+        if ($plugin->moduleExists($plugin_definition['source_provider'])) {
+          if (isset($plugin_definition['minimum_schema_version']) && !$plugin->getModuleSchemaVersion($plugin_definition['source_provider']) < $plugin_definition['minimum_schema_version']) {
+            $plugin->checkRequirements(FALSE);
+          }
+        }
+        else {
+          $plugin->checkRequirements(FALSE);
+        }
+      }
+    }
+    return $plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkRequirements($new_value = NULL) {
+    if (isset($new_value)) {
+      $this->requirements = $new_value;
+    }
+    return $this->requirements;
+  }
+
+  /**
+   * Get a module schema_version value in the source installation.
+   *
+   * @param string $module
+   *   Name of module.
+   *
+   * @return mixed
+   *   The current module schema version on the origin system table or FALSE if
+   *   not found.
+   */
+  protected function getModuleSchemaVersion($module) {
+    $system_data = $this->getSystemData();
+    return isset($system_data['module'][$module]['schema_version']) ? $system_data['module'][$module]['schema_version'] : FALSE;
+  }
+
+  /**
+   * Check to see if a given module is enabled in the source installation.
+   *
+   * @param string $module
+   *   Name of module to check.
+   *
+   * @return bool
+   *   TRUE if module is enabled on the origin system, FALSE if not.
+   */
+  protected function moduleExists($module) {
+    $system_data = $this->getSystemData();
+    return !empty($system_data['module'][$module]['status']);
+  }
+
+  /**
+   * Read a variable from a Drupal database.
+   *
+   * @param $name
+   *   Name of the variable.
+   * @param $default
+   *   The default value.
+   * @return mixed
+   */
+  protected function variableGet($name, $default) {
+    try {
+      $result = $this->select('variable', 'v')
+        ->fields('v', array('value'))
+        ->condition('name', $name)
+        ->execute()
+        ->fetchField();
+    }
+    // The table might not exist.
+    catch (\Exception $e) {
+      $result = FALSE;
+    }
+    return $result !== FALSE ? unserialize($result) : $default;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/Variable.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/Variable.php
new file mode 100644
index 0000000..0c3e8dc
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/Variable.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Variable.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source;
+
+use Drupal\migrate\Entity\MigrationInterface;
+
+/**
+ * Drupal 6 variable source from database.
+ *
+ * This source class always returns a single row and as such is not a good
+ * example for any normal source class returning multiple rows.
+ *
+ * @MigrateSource(
+ *   id = "variable"
+ * )
+ */
+class Variable extends DrupalSqlBase {
+
+  /**
+   * The variable names to fetch.
+   *
+   * @var array
+   */
+  protected $variables;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
+    $this->variables = $this->configuration['variables'];
+  }
+
+  protected function runQuery() {
+    return new \ArrayIterator(array(array_map('unserialize', $this->prepareQuery()->execute()->fetchAllKeyed())));
+  }
+
+  public function count() {
+    return intval($this->query()->countQuery()->execute()->fetchField() > 0);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array_combine($this->variables, $this->variables);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->getDatabase()
+      ->select('variable', 'v')
+      ->fields('v', array('name', 'value'))
+      ->condition('name', $this->variables, 'IN');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return array();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/VariableMultiRow.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/VariableMultiRow.php
new file mode 100644
index 0000000..3069fbe
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/VariableMultiRow.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source;
+
+use Drupal\migrate\Row;
+
+/**
+ * Drupal 6 multiple variables source from database.
+ *
+ * Unlike the d6_variable source plugin, this one returns one row per
+ * variable.
+ *
+ * @MigrateSource(
+ *   id = "variable_multirow"
+ * )
+ */
+class VariableMultiRow extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('variable', 'v')
+      ->fields('v', array('name', 'value'))
+      ->condition('name', $this->configuration['variables']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'name' => $this->t('Name'),
+      'value' => $this->t('Value'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    if ($value = $row->getSourceProperty('value')) {
+      $row->setSourceProperty('value', unserialize($value));
+    }
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['name']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Action.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Action.php
new file mode 100644
index 0000000..86048dc
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Action.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Action.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 action source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_action"
+ * )
+ */
+class Action extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->database
+      ->select('actions', 'a')
+      ->fields('a', array(
+        'aid',
+        'type',
+        'callback',
+        'parameters',
+        'description',
+      )
+    );
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'aid' => $this->t('Action ID'),
+      'type' => $this->t('Module'),
+      'callback' => $this->t('Callback function'),
+      'parameters' => $this->t('Action configuration'),
+      'description' => $this->t('Action description'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['aid']['type'] = 'string';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/AggregatorFeed.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/AggregatorFeed.php
new file mode 100644
index 0000000..d4da74b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/AggregatorFeed.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\AggregatorFeed.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 feed source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_aggregator_feed",
+ *   source_provider = "aggregator"
+ * )
+ */
+class AggregatorFeed extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('aggregator_feed', 'af')
+      ->fields('af', array(
+        'fid',
+        'title',
+        'url',
+        'refresh',
+        'checked',
+        'link',
+        'description',
+        'image',
+        'etag',
+        'modified',
+        'block',
+      ));
+
+    $query->orderBy('fid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'fid' => $this->t('The feed ID.'),
+      'title' => $this->t('Title of the feed.'),
+      'url' => $this->t('URL to the feed.'),
+      'refresh' => $this->t('Refresh frequency in seconds.'),
+      'checked' => $this->t('Last-checked unix timestamp.'),
+      'link' => $this->t('Parent website of feed.'),
+      'description' => $this->t('Parent website\'s description fo the feed.'),
+      'image' => $this->t('An image representing the feed.'),
+      'etag' => $this->t('Entity tag HTTP response header.'),
+      'modified' => $this->t('When the feed was last modified.'),
+      'block' => $this->t("Number of items to display in the feed's block."),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['fid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/AggregatorItem.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/AggregatorItem.php
new file mode 100644
index 0000000..0e7646b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/AggregatorItem.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\AggregatorItem.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+
+/**
+ * Drupal 6 aggregator item source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_aggregator_item",
+ *   source_provider = "aggregator"
+ * )
+ */
+class AggregatorItem extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('aggregator_item', 'ai')
+      ->fields('ai', array('iid', 'fid', 'title', 'link', 'author',
+        'description', 'timestamp', 'guid'))
+      ->orderBy('iid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'iid' => $this->t('Primary Key: Unique ID for feed item.'),
+      'fid' => $this->t('The {aggregator_feed}.fid to which this item belongs.'),
+      'title' => $this->t('Title of the feed item.'),
+      'link' => $this->t('Link to the feed item.'),
+      'author' => $this->t('Author of the feed item.'),
+      'description' => $this->t('Body of the feed item.'),
+      'timestamp' => $this->t('Post date of feed item, as a Unix timestamp.'),
+      'guid' => $this->t('Unique identifier for the feed item.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['iid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Block.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Block.php
new file mode 100644
index 0000000..4bafad2
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Block.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\source\d6\Block.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 block source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_block"
+ * )
+ */
+class Block extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('blocks', 'b')
+      ->fields('b', array('bid', 'module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'title', 'cache'))
+      ->orderBy('bid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'bid' => $this->t('The block numeric identifier.'),
+      'module' => $this->t('The module providing the block.'),
+      'delta' => $this->t('The block\'s delta.'),
+      'theme' => $this->t('Which theme the block is placed in.'),
+      'status' => $this->t('Whether or not the block is enabled.'),
+      'weight' => $this->t('Weight of the block for ordering within regions.'),
+      'region' => $this->t('Region the block is placed in.'),
+      'visibility' => $this->t('Visibility expression.'),
+      'pages' => $this->t('Pages list.'),
+      'title' => $this->t('Block title.'),
+      'cache' => $this->t('Cache rule.'),
+
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $module = $row->getSourceProperty('module');
+    $delta = $row->getSourceProperty('delta');
+    $roles = $this->select('blocks_roles', 'br')
+      ->fields('br', array('rid'))
+      ->condition('module', $module)
+      ->condition('delta', $delta)
+      ->execute()
+      ->fetchCol();
+    $row->setSourceProperty('permissions', $roles);
+    $settings = array();
+    // Contrib can use hook_migration_d6_block_prepare_row() to add similar variables
+    // via $migration->getSource()->variableGet().
+    switch ($module) {
+      case 'aggregator':
+        list($type, $id) = explode('-', $delta);
+        if ($type == 'feed') {
+          $item_count = $this->database->query('SELECT block FROM {aggregator_feed} WHERE fid = :fid', array(':fid' => $id))->fetchField();
+        }
+        else {
+          $item_count = $this->database->query('SELECT block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchField();
+        }
+        $settings['aggregator']['item_count'] = $item_count;
+        break;
+      case 'book':
+        $settings['book']['block_mode'] = $this->variableGet('book_block_mode', 'all pages');
+        break;
+      case 'forum':
+        $settings['forum']['block_num'] = $this->variableGet('forum_block_num_'. $delta, 5);
+        break;
+      case 'statistics':
+        foreach (array('statistics_block_top_day_num', 'statistics_block_top_all_num', 'statistics_block_top_last_num') as $name) {
+          $settings['statistics'][$name] = $this->variableGet($name, 0);
+        }
+        break;
+      case 'user':
+        switch ($delta) {
+          case 2:
+            $settings['user']['block_whois_new_count'] = $this->variableGet('user_block_whois_new_count', 5);
+            break;
+          case 3:
+            $settings['user']['block_seconds_online'] = $this->variableGet('user_block_seconds_online', 900);
+            $settings['user']['max_list_count'] = $this->variableGet('user_block_max_list_count', 10);
+            break;
+        }
+        break;
+    }
+    $row->setSourceProperty('settings', $settings);
+    return parent::prepareRow($row);
+  }
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['module']['type'] = 'string';
+    $ids['delta']['type'] = 'string';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Box.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Box.php
new file mode 100644
index 0000000..3873c36
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Box.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Boxes.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 block source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_box"
+ * )
+ */
+class Box extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('boxes', 'b')
+      ->fields('b', array('bid', 'body', 'info', 'format'));
+    $query->orderBy('bid');
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'bid' => $this->t('The numeric identifier of the block/box'),
+      'body' => $this->t('The block/box content'),
+      'info' => $this->t('Admin title of the block/box.'),
+      'format' => $this->t('Input format of the custom block/box content.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['bid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CckFieldRevision.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CckFieldRevision.php
new file mode 100644
index 0000000..0ac4921
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CckFieldRevision.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\CckFieldRevision.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+/**
+ * Drupal 6 cck field revision source.
+ *
+ * @MigrateSource(
+ *   id = "d6_cck_field_revision"
+ * )
+ */
+class CckFieldRevision extends CckFieldValues {
+
+  /**
+   * The join options between the node and the node_revisions_table.
+   */
+  const JOIN = 'n.nid = nr.nid AND n.vid <> nr.vid';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    // Use all the node fields plus the vid that identifies the version.
+    return parent::fields() + array('vid' => t('The primary identifier for this version.'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['vid']['type'] = 'integer';
+    $ids['vid']['alias'] = 'nr';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CckFieldValues.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CckFieldValues.php
new file mode 100644
index 0000000..7877921
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CckFieldValues.php
@@ -0,0 +1,271 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\CckFieldValues.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Plugin\SourceEntityInterface;
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+
+/**
+ * Drupal 6 cck field source.
+ *
+ * @MigrateSource(
+ *   id = "d6_cck_field_values"
+ * )
+ */
+class CckFieldValues extends DrupalSqlBase implements SourceEntityInterface {
+
+  /**
+   * The join options between the node and the node_revisions table.
+   */
+  const JOIN = 'n.vid = nr.vid';
+
+  /**
+   * The source field information for complex node fields.
+   *
+   * @var array
+   */
+  protected $sourceFieldInfo;
+
+  /**
+   * Information on which tables exist.
+   *
+   * @var array
+   */
+  protected $tables;
+
+  /**
+   * TRUE when CCK is enabled and the schema is correct.
+   *
+   * @var bool
+   */
+  protected $cckSchemaCorrect;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    // Select node in its last revision.
+    $query = $this->select('node_revisions', 'nr')
+      ->fields('n', array(
+        'nid',
+        'type',
+      ))
+      ->fields('nr', array(
+        'vid',
+      ))
+      ->condition('type', $this->configuration['bundle']);
+    $query->innerJoin('node', 'n', static::JOIN);
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $bundle = $row->getSourceProperty('type');
+    // Pick up simple CCK fields.
+    $cck_table = "content_type_$bundle";
+    if ($this->tableExists($cck_table)) {
+      $query = $this->select($cck_table, 'f')->condition('vid', $row->getSourceProperty('vid'));
+      // The main column for the field should be rendered with the field name,
+      // not the column name (e.g., field_foo rather than field_foo_value).
+      $field_info = $this->getSourceFieldInfo($bundle);
+      foreach ($field_info as $field_name => $info) {
+        if (isset($info['columns']) && !$info['multiple'] && $info['db_storage']) {
+          $i = 0;
+          $data = FALSE;
+          foreach ($info['columns'] as $display_name => $column_name) {
+            if ($i++ == 0) {
+              $query->addField('f', $column_name, $field_name);
+            }
+            else {
+              // The database API won't allow colons in column aliases, so we
+              // will accept the default alias, and fix up the field names later.
+              // Remember how to translate the field names.
+              $clean_name = str_replace(':', '_', $display_name);
+              //$this->fixFieldNames[$clean_name] = $display_name;
+              if ($info['type'] == 'filefield' &&
+                (strpos($display_name, ':list') || strpos($display_name, ':description'))) {
+                if (!$data) {
+                  //$this->fileDataFields[] = $field_name . '_data';
+                  $query->addField('f', $field_name . '_data');
+                  $data = TRUE;
+                }
+              }
+              else {
+                $query->addField('f', $column_name);
+              }
+            }
+          }
+        }
+      }
+      if ($results = $query->execute()->fetchAssoc()) {
+        $source = $row->getSource();
+        // We diff the results because the extra will be all the field columns.
+        $new_fields = array_diff($results, $source);
+        foreach ($new_fields as $key => $value) {
+          $row->setSourceProperty($key, $value);
+        }
+      }
+    }
+
+    // Handle fields that have their own table.
+    foreach ($this->getSourceFieldInfo($bundle) as $field_name => $field_info) {
+      if ($field_info['multiple'] && !$field_info['db_storage']) {
+        // Select the data.
+        $table = "content_$field_name";
+        $field_index = $field_name . '_value';
+        $data = $this
+          ->select($table, 't')
+          ->fields('t', array('delta', $field_index))
+          ->condition('vid', $row->getSourceProperty('vid'))
+          ->execute()
+          ->fetchAllKeyed();
+
+        // Set it on the row.
+        $row->setSourceProperty($field_name, $data);
+      }
+    }
+    parent::prepareRow($row);
+  }
+
+  /**
+   * Get all the complex field info.
+   *
+   * @param string $bundle
+   *   The bundle for which fields we want.
+   *
+   * @return array
+   *   An array of field info keyed by field name.
+   */
+  protected function getSourceFieldInfo($bundle) {
+    if (!isset($this->sourceFieldInfo)) {
+      $this->sourceFieldInfo = array();
+      if ($this->tableExists('content_node_field_instance')) {
+        // Get each field attached to this type.
+        $query = $this->select('content_node_field_instance', 'i')
+          ->fields('i', array(
+            'label',
+            'widget_settings',
+            'field_name',
+          ))
+          ->condition('type_name', $bundle);
+
+        $query->innerJoin('content_node_field', 'f', 'i.field_name = f.field_name');
+        $query->fields('f', array(
+            'field_name',
+            'type',
+            'db_columns',
+            'global_settings',
+            'multiple',
+            'db_storage')
+        );
+
+        $results = $query->execute();
+        foreach ($results as $row) {
+          $field_name = trim($row['field_name']);
+          $db_columns = $db_columns = !empty($row['db_columns']) ? unserialize($row['db_columns']) : array();
+          $columns = array();
+          foreach ($db_columns as $column_name => $column_info) {
+            // Special handling for the stuff packed into filefield's "data"
+            if ($row['type'] == 'filefield' && $column_name == 'data') {
+              $widget_settings = unserialize($row['widget_settings']);
+              $global_settings = unserialize($row['global_settings']);
+
+              if (!empty($widget_settings['custom_alt'])) {
+                $columns[$field_name . ':alt'] = $field_name . '_alt';
+              }
+              if (!empty($widget_settings['custom_title'])) {
+                $columns[$field_name . ':title'] = $field_name . '_title';
+              }
+              if (!empty($global_settings['description_field'])) {
+                $columns[$field_name . ':description'] = $field_name . '_description';
+              }
+            }
+            else {
+              $display_name = $field_name . ':' . $column_name;
+              $column_name = $field_name . '_' . $column_name;
+              $columns[$display_name] = $column_name;
+            }
+          }
+          $this->sourceFieldInfo[$field_name] = array(
+            'label' => $row['label'],
+            'type' => $row['type'],
+            'columns' => $columns,
+            'multiple' => $row['multiple'],
+            'db_storage' => $row['db_storage'],
+            'bundle' => $bundle,
+          );
+        }
+      }
+    }
+
+    return $this->sourceFieldInfo;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    $fields = array(
+      'nid' => $this->t('Node ID'),
+      'type' => $this->t('Type'),
+    );
+    foreach ($this->getSourceFieldInfo($this->configuration['bundle']) as $field_name => $field_data) {
+      $fields[$field_name] = $field_data['label'];
+    }
+    return $fields;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['nid']['type'] = 'integer';
+    $ids['nid']['alias'] = 'n';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function bundleMigrationRequired() {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function entityTypeId() {
+    return 'node';
+  }
+
+  /**
+   * Determines whether a specific CCK table exists.
+   */
+  protected function tableExists($table) {
+    if (!isset($this->tables[$table])) {
+      $this->tables[$table] = $this->cckSchemaCorrect() && $this->getDatabase()->schema()->tableExists($table);
+    }
+    return $this->tables[$table];
+  }
+
+  /**
+   * Determines whether CCK is enabled and is using the right schema.
+   */
+  protected function cckSchemaCorrect() {
+    if (!isset($this->cckSchemaCorrect)) {
+      $this->cckSchemaCorrect = $this->moduleExists('content') && $this->getModuleSchemaVersion('content') >= 6001;
+    }
+    return $this->cckSchemaCorrect;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Comment.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Comment.php
new file mode 100644
index 0000000..2eddf72
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Comment.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Comment.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 comment source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_comment",
+ *   source_provider = "comment"
+ * )
+ */
+class Comment extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('comments', 'c')
+      ->fields('c', array('cid', 'pid', 'nid', 'uid', 'subject',
+        'comment', 'hostname', 'timestamp', 'status', 'thread', 'name',
+        'mail', 'homepage', 'format'));
+    $query->orderBy('timestamp');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row, $keep = TRUE) {
+    // In D6, status=0 means published, while in D8 means the opposite.
+    // See https://drupal.org/node/237636
+    $row->setSourceProperty('status', !$row->getSourceProperty('status'));
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'cid' => $this->t('Comment ID.'),
+      'pid' => $this->t('Parent comment ID. If set to 0, this comment is not a reply to an existing comment.'),
+      'nid' => $this->t('The {node}.nid to which this comment is a reply.'),
+      'uid' => $this->t('The {users}.uid who authored the comment. If set to 0, this comment was created by an anonymous user.'),
+      'subject' => $this->t('The comment title.'),
+      'comment' => $this->t('The comment body.'),
+      'hostname' => $this->t("The author's host name."),
+      'timestamp' => $this->t('The time that the comment was created, or last edited by its author, as a Unix timestamp.'),
+      'status' => $this->t('The published status of a comment. (0 = Published, 1 = Not Published)'),
+      'format' => $this->t('The {filter_formats}.format of the comment body.'),
+      'thread' => $this->t("The vancode representation of the comment's place in a thread."),
+      'name' => $this->t("The comment author's name. Uses {users}.name if the user is logged in, otherwise uses the value typed into the comment form."),
+      'mail' => $this->t("The comment author's e-mail address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."),
+      'homepage' => $this->t("The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."),
+      'type' => $this->t("The {node}.type to which this comment is a reply.")
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['cid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CommentVariable.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CommentVariable.php
new file mode 100644
index 0000000..629accf
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CommentVariable.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\source\d6\CommentVariable.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * @MigrateSource(
+ *   id = "d6_comment_variable"
+ * )
+ */
+class CommentVariable extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function runQuery() {
+    return new \ArrayIterator($this->getCommentVariables());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function count() {
+    return count($this->getCommentVariables());
+  }
+
+  /**
+   * Retrieves the values of the comment variables grouped by node type.
+   *
+   * @return array
+   */
+  protected function getCommentVariables() {
+    $comment_prefixes = array_keys($this->commentPrefixes());
+    $variables = array();
+    $node_types = $this->getDatabase()->query('SELECT type FROM {node_type}')->fetchCol();
+    foreach ($node_types as $node_type) {
+      foreach ($comment_prefixes as $prefix) {
+        $variables[] = $prefix . '_' . $node_type;
+      }
+    }
+    $return = array();
+    $values = $this->getDatabase()->query('SELECT name, value FROM {variable} WHERE name IN (:name)', array(':name' => $variables))->fetchAllKeyed();
+    foreach ($node_types as $node_type) {
+      foreach ($comment_prefixes as $prefix) {
+        $name = $prefix . '_' . $node_type;
+        if (isset($values[$name])) {
+          $return[$node_type][$prefix] = unserialize($values[$name]);
+        }
+      }
+    }
+    // The return key will not be used so move it inside the row. This could
+    // not be done sooner because otherwise empty rows would be created with
+    // just the node type in it.
+    foreach ($return as $node_type => $data) {
+      $return[$node_type]['node_type'] = $node_type;
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return $this->commentPrefixes() + array(
+      'node_type' => $this->t('The node type'),
+    );
+  }
+
+  /**
+   * Comment related data for fields.
+   */
+  protected function commentPrefixes() {
+    return array(
+      'comment' => $this->t('Default comment setting'),
+      'comment_default_mode' => $this->t('Default display mode'),
+      'comment_default_order' => $this->t('Default display order'),
+      'comment_default_per_page' => $this->t('Default comments per page'),
+      'comment_controls' => $this->t('Comment controls'),
+      'comment_anonymous' => $this->t('Anonymous commenting'),
+      'comment_subject_field' => $this->t('Comment subject field'),
+      'comment_preview' => $this->t('Preview comment'),
+      'comment_form_location' => $this->t('Location of comment submission form'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    // Nothing to do here.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['node_type']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ContactCategory.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ContactCategory.php
new file mode 100644
index 0000000..067c63d
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ContactCategory.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\ContactCategory.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 contact category source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_contact_category",
+ *   source_provider = "contact"
+ * )
+ */
+class ContactCategory extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('contact', 'c')
+      ->fields('c', array(
+        'cid',
+        'category',
+        'recipients',
+        'reply',
+        'weight',
+        'selected',
+      )
+    );
+    $query->orderBy('cid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'cid' => $this->t('Primary Key: Unique category ID.'),
+      'category' => $this->t('Category name.'),
+      'recipients' => $this->t('Comma-separated list of recipient e-mail addresses.'),
+      'reply' => $this->t('Text of the auto-reply message.'),
+      'weight' => $this->t("The category's weight."),
+      'selected' => $this->t('Flag to indicate whether or not category is selected by default. (1 = Yes, 0 = No)'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['cid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Drupal6SqlBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Drupal6SqlBase.php
deleted file mode 100644
index f83f669..0000000
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Drupal6SqlBase.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\migrate\Plugin\migrate\source\d6\Drupal6SqlBase.
- */
-
-namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
-
-use Drupal\migrate\Plugin\migrate\source\SqlBase;
-
-/**
- * A base source class for Drupal 6 migrate sources.
- *
- * Mainly to let children retrieve information from the origin system in an
- * easier way.
- */
-abstract class Drupal6SqlBase extends SqlBase {
-
-  /**
-   * Retrieves all system data information from origin system.
-   *
-   * @return array
-   *   List of system table information keyed by type and name.
-   */
-  public function getSystemData() {
-    static $system_data;
-    if (isset($system_data)) {
-      return $system_data;
-    }
-    $results = $this->database
-      ->select('system', 's')
-      ->fields('s')
-      ->execute();
-    foreach ($results as $result) {
-      $system_data[$result['type']][$result['name']] = $result;
-    }
-    return $system_data;
-  }
-
-  /**
-   * Get a module schema_version value in the source installation.
-   *
-   * @param string $module
-   *   Name of module.
-   *
-   * @return mixed
-   *   The current module schema version on the origin system table or FALSE if
-   *   not found.
-   */
-  protected function getModuleSchemaVersion($module) {
-    $system_data = $this->getSystemData();
-    return isset($system_data['module'][$module]['schema_version']) ? $system_data['module'][$module]['schema_version'] : FALSE;
-  }
-
-  /**
-   * Check to see if a given module is enabled in the source installation.
-   *
-   * @param string $module
-   *   Name of module to check.
-   *
-   * @return bool
-   *   TRUE if module is enabled on the origin system, FALSE if not.
-   */
-  protected function moduleExists($module) {
-    return isset($system_data['module'][$module]['status']) ? (bool) $system_data['module'][$module]['status'] : FALSE;
-  }
-
-  protected function variableGet($name, $default) {
-    try {
-      $result = $this->database
-        ->query('SELECT value FROM {variable} WHERE name = :name', array(':name' => $name))
-        ->fetchField();
-    }
-    // The table might not exist.
-    catch (\Exception $e) {
-      $result = FALSE;
-    }
-    return $result !== FALSE ? unserialize($result) : $default;
-  }
-
-}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Field.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Field.php
new file mode 100644
index 0000000..96ce07a
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Field.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Field.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 field source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_field",
+ *   source_provider = "content"
+ * )
+ */
+class Field extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('content_node_field', 'cnf')
+      ->fields('cnf', array(
+        'field_name',
+        'type',
+        'global_settings',
+        'required',
+        'multiple',
+        'db_storage',
+        'module',
+        'db_columns',
+        'active',
+        'locked',
+      ))
+      ->fields('cnfi', array(
+        'widget_type',
+        'widget_settings',
+      ));
+    $query->join('content_node_field_instance', 'cnfi', 'cnfi.field_name = cnf.field_name');
+    $query->orderBy('field_name');
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'field_name' => $this->t('Field name'),
+      'type' => $this->t('Type (text, integer, ....)'),
+      'global_settings' => $this->t('Global settings. Shared with every field instance.'),
+      'required' => $this->t('Required'),
+      'multiple' => $this->t('Multiple'),
+      'db_storage' => $this->t('DB storage'),
+      'module' => $this->t('Module'),
+      'db_columns' => $this->t('DB Columns'),
+      'active' => $this->t('Active'),
+      'locked' => $this->t('Locked'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row, $keep = TRUE) {
+    // Unserialize data.
+    $global_settings = unserialize($row->getSourceProperty('global_settings'));
+    $widget_settings = unserialize($row->getSourceProperty('widget_settings'));
+    $db_columns = unserialize($row->getSourceProperty('db_columns'));
+    $row->setSourceProperty('global_settings', $global_settings);
+    $row->setSourceProperty('widget_settings', $widget_settings);
+    $row->setSourceProperty('db_columns', $db_columns);
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['field_name'] = array(
+      'type' => 'string',
+      'alias' => 'cnf',
+    );
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstance.php
new file mode 100644
index 0000000..66049fd
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstance.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\FieldInstance.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 field instances source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_field_instance",
+ *   source_provider = "content"
+ * )
+ */
+class FieldInstance extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('content_node_field_instance', 'cnfi')
+      ->fields('cnfi', array(
+        'field_name',
+        'type_name',
+        'weight',
+        'label',
+        'widget_type',
+        'widget_settings',
+        'display_settings',
+        'description',
+        'widget_module',
+        'widget_active',
+        'description',
+      ))
+      ->fields('cnf', array(
+        'required',
+        'active',
+        'global_settings',
+      ));
+
+    $query->join('content_node_field', 'cnf', 'cnf.field_name = cnfi.field_name');
+    $query->orderBy('type_name');
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'field_name' => $this->t('The machine name of field.'),
+      'type_name' => $this->t('Content type where is used this field.'),
+      'weight' => $this->t('Weight.'),
+      'label' => $this->t('A name to show.'),
+      'widget_type' => $this->t('Widget type.'),
+      'widget_settings' => $this->t('Serialize data with widget settings.'),
+      'display_settings' => $this->t('Serialize data with display settings.'),
+      'description' => $this->t('A description of field.'),
+      'widget_module' => $this->t('Module that implements widget.'),
+      'widget_active' => $this->t('Status of widget'),
+      'module' => $this->t('The module that provides the field.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row, $keep = TRUE) {
+    // Unserialize data.
+    $widget_settings = unserialize($row->getSourceProperty('widget_settings'));
+    $display_settings = unserialize($row->getSourceProperty('display_settings'));
+    $global_settings = unserialize($row->getSourceProperty('global_settings'));
+    $row->setSourceProperty('widget_settings', $widget_settings);
+    $row->setSourceProperty('display_settings', $display_settings);
+    $row->setSourceProperty('global_settings', $global_settings);
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids = array(
+      'field_name' => array(
+        'type' => 'string',
+        'alias' => 'cnfi',
+      ),
+      'type_name' => array(
+        'type' => 'string',
+      ),
+    );
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstancePerFormDisplay.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstancePerFormDisplay.php
new file mode 100644
index 0000000..bc7fc39
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstancePerFormDisplay.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\FieldInstancePerViewMode.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * A base class for field instances which all require the same data and fields.
+ *
+ * @MigrateSource(
+ *   id = "d6_field_instance_per_form_display"
+ * )
+ */
+class FieldInstancePerFormDisplay extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function runQuery() {
+    $rows = array();
+    $result = $this->prepareQuery()->execute();
+    while ($field_row = $result->fetchAssoc()) {
+      $field_row['display_settings'] = unserialize($field_row['display_settings']);
+      $field_row['widget_settings'] = unserialize($field_row['widget_settings']);
+      $bundle = $field_row['type_name'];
+      $field_name = $field_row['field_name'];
+
+      $index = "$bundle.$field_name";
+      $rows[$index]['type_name'] = $bundle;
+      $rows[$index]['widget_active'] = (bool) $field_row['widget_active'];
+      $rows[$index]['field_name'] = $field_name;
+      $rows[$index]['type'] = $field_row['type'];
+      $rows[$index]['module'] = $field_row['module'];
+      $rows[$index]['weight'] = $field_row['display_settings']['weight'];
+      $rows[$index]['widget_type'] = $field_row['widget_type'];
+      $rows[$index]['widget_settings'] = $field_row['widget_settings'];
+    }
+
+    return new \ArrayIterator($rows);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('content_node_field_instance', 'cnfi')
+      ->fields('cnfi', array(
+        'field_name',
+        'type_name',
+        'weight',
+        'label',
+        'widget_type',
+        'widget_settings',
+        'display_settings',
+        'description',
+        'widget_module',
+        'widget_active',
+      ))
+      ->fields('cnf', array(
+        'type',
+        'module',
+      ));
+    $query->join('content_node_field', 'cnf', 'cnfi.field_name = cnf.field_name');
+    $query->orderBy('type_name');
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'field_name' => $this->t('The machine name of field.'),
+      'type_name' => $this->t('Content type where this field is used.'),
+      'weight' => $this->t('Weight.'),
+      'label' => $this->t('A name to show.'),
+      'widget_type' => $this->t('Widget type.'),
+      'widget_settings' => $this->t('Serialize data with widget settings.'),
+      'display_settings' => $this->t('Serialize data with display settings.'),
+      'description' => $this->t('A description of field.'),
+      'widget_module' => $this->t('Module that implements widget.'),
+      'widget_active' => $this->t('Status of widget'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['type_name']['type'] = 'string';
+    $ids['field_name']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstancePerViewMode.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstancePerViewMode.php
new file mode 100644
index 0000000..c45469b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FieldInstancePerViewMode.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\FieldInstancePerViewMode.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Entity\MigrationInterface;
+
+/**
+ * A base class for field instances which all require the same data and fields.
+ *
+ * @MigrateSource(
+ *   id = "d6_field_instance_per_view_mode"
+ * )
+ */
+class FieldInstancePerViewMode extends ViewModeBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function runQuery() {
+    $rows = array();
+    $result = $this->prepareQuery()->execute();
+    while ($field_row = $result->fetchAssoc()) {
+      // These are added to every view mode row.
+      $field_row['display_settings'] = unserialize($field_row['display_settings']);
+      $field_row['widget_settings'] = unserialize($field_row['widget_settings']);
+      $bundle = $field_row['type_name'];
+      $field_name = $field_row['field_name'];
+
+      foreach ($this->getViewModes() as $view_mode) {
+        if (isset($field_row['display_settings'][$view_mode]) && !$field_row['display_settings'][$view_mode]['exclude']) {
+          $index = $view_mode . "." . $bundle . "." . $field_name;
+          $rows[$index]['entity_type'] = 'node';
+          $rows[$index]['view_mode'] = $view_mode;
+          $rows[$index]['type_name'] = $bundle;
+          $rows[$index]['field_name'] = $field_name;
+          $rows[$index]['type'] = $field_row['type'];
+          $rows[$index]['module'] = $field_row['module'];
+          $rows[$index]['weight'] = $field_row['display_settings']['weight'];
+          $rows[$index]['label'] = $field_row['display_settings']['label']['format'];
+          $rows[$index]['display_settings'] = $field_row['display_settings'][$view_mode];
+          $rows[$index]['widget_settings'] = $field_row['widget_settings'];
+        }
+      }
+    }
+
+    return new \ArrayIterator($rows);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('content_node_field_instance', 'cnfi')
+      ->fields('cnfi', array(
+        'field_name',
+        'type_name',
+        'weight',
+        'label',
+        'display_settings',
+        'widget_settings',
+    ))
+    ->fields('cnf', array(
+        'type',
+        'module',
+    ));
+    $query->join('content_node_field', 'cnf', 'cnfi.field_name = cnf.field_name');
+    $query->orderBy('type_name');
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'field_name' => $this->t('The machine name of field.'),
+      'type_name' => $this->t('Content type where this field is used.'),
+      'weight' => $this->t('Weight.'),
+      'label' => $this->t('A name to show.'),
+      'widget_type' => $this->t('Widget type.'),
+      'widget_settings' => $this->t('Serialize data with widget settings.'),
+      'display_settings' => $this->t('Serialize data with display settings.'),
+      'description' => $this->t('A description of field.'),
+      'widget_module' => $this->t('Module that implements widget.'),
+      'widget_active' => $this->t('Status of widget'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['type_name']['type'] = 'string';
+    $ids['view_mode']['type'] = 'string';
+    $ids['entity_type']['type'] = 'string';
+    $ids['field_name']['type'] = 'string';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/File.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/File.php
new file mode 100644
index 0000000..ba946a7
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/File.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\File.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 file source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_file"
+ * )
+ */
+class File extends DrupalSqlBase {
+
+  /**
+   * The file directory path.
+   *
+   * @var string
+   */
+  protected $filePath;
+
+  /**
+   * Flag for private or public file storage.
+   *
+   * @var boolean
+   */
+  protected $isPublic;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('files', 'f')->fields('f', array(
+      'fid',
+      'uid',
+      'filename',
+      'filepath',
+      'filemime',
+      'filesize',
+      'status',
+      'timestamp',
+    ));
+    $query->orderBy('timestamp');
+    return $query;
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function runQuery() {
+    $conf_path = isset($this->configuration['conf_path']) ? $this->configuration['conf_path'] : 'sites/default';
+    $this->filePath = $this->variableGet('file_directory_path', $conf_path . '/files') . '/';
+
+    // FILE_DOWNLOADS_PUBLIC == 1 and FILE_DOWNLOADS_PRIVATE == 2.
+    $this->isPublic = $this->variableGet('file_downloads', 1) == 1;
+    return parent::runQuery();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $row->setSourceProperty('file_directory_path', $this->filePath);
+    $row->setSourceProperty('is_public', $this->isPublic);
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'fid' => $this->t('File ID'),
+      'uid' => $this->t('The {users}.uid who added the file. If set to 0, this file was added by an anonymous user.'),
+      'filename' => $this->t('File name'),
+      'filepath' => $this->t('File path'),
+      'filemime' => $this->t('File Mime Type'),
+      'status' => $this->t('The published status of a file.'),
+      'timestamp' => $this->t('The time that the file was added.'),
+      'file_directory_path' => $this->t('The Drupal files path.'),
+      'is_public' => $this->t('TRUE if the files directory is public otherwise FALSE.'),
+    );
+  }
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['fid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FilterFormat.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FilterFormat.php
new file mode 100644
index 0000000..9088d04
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/FilterFormat.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\FilterFormats.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+use Drupal\migrate\Row;
+
+/**
+ * Drupal 6 role source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_filter_format"
+ * )
+ */
+class FilterFormat extends \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('filter_formats', 'f')
+      ->fields('f', array('format', 'name', 'roles', 'cache'))
+      ->orderBy('format');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'format' => $this->t('Format ID.'),
+      'name' => $this->t('The name of the filter format.'),
+      'roles' => $this->t('The user roles that can use the format.'),
+      'cache' => $this->t('Flag to indicate whether format is cachable. (1 = cachable, 0 = not cachable).'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $filters = array();
+    $roles = $row->getSourceProperty('roles');
+    $row->setSourceProperty('roles', array_values(array_filter(explode(',', $roles))));
+    $format = $row->getSourceProperty('format');
+    // Find filters for this row.
+    $results = $this->database
+      ->select('filters', 'f', array('fetch' => \PDO::FETCH_ASSOC))
+      ->fields('f', array('module', 'delta', 'weight'))
+      ->condition('format', $format)
+      ->execute();
+    foreach ($results as $raw_filter) {
+      $module = $raw_filter['module'];
+      $delta = $raw_filter['delta'];
+      $filter = array(
+        'module' => $module,
+        'delta' => $delta,
+        'weight' => $raw_filter['weight'],
+        'settings' => array(),
+      );
+      // Load the filter settings for the filter module, modules can use
+      // hook_migration_d6_filter_formats_prepare_row() to add theirs.
+      if ($raw_filter['module'] == 'filter') {
+        if (!$delta) {
+          if ($setting = $this->variableGet("allowed_html_$format", NULL)) {
+            $filter['settings']['allowed_html'] = $setting;
+          }
+          if ($setting = $this->variableGet("filter_html_help_$format", NULL)) {
+            $filter['settings']['filter_html_help'] = $setting;
+          }
+          if ($setting = $this->variableGet("filter_html_nofollow_$format", NULL)) {
+            $filter['settings']['filter_html_nofollow'] = $setting;
+          }
+        }
+        elseif ($delta == 2 && ($setting = $this->variableGet("filter_url_length_$format", NULL))) {
+          $filter['settings']['filter_url_length'] = $setting;
+        }
+      }
+      $filters[] = $filter;
+    }
+
+    $row->setSourceProperty('filters', $filters);
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['format']['type'] = 'integer';
+    return $ids;
+  }
+}
+
+
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Menu.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Menu.php
new file mode 100644
index 0000000..4f9d7e5
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Menu.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Menu.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 menu source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_menu",
+ *   source_provider = "menu"
+ * )
+ */
+class Menu extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('menu_custom', 'm')
+      ->fields('m', array('menu_name', 'title', 'description'));
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'menu_name' => $this->t('The menu name. Primary key.'),
+      'title' => $this->t('The human-readable name of the menu.'),
+      'description' => $this->t('A description of the menu'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['menu_name']['type'] = 'string';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Node.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Node.php
new file mode 100644
index 0000000..752976e
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Node.php
@@ -0,0 +1,110 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Node.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Plugin\SourceEntityInterface;
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+
+/**
+ * Drupal 6 node source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_node"
+ * )
+ */
+class Node extends DrupalSqlBase implements SourceEntityInterface {
+
+  /**
+   * The join options between the node and the node_revisions table.
+   */
+  const JOIN = 'n.vid = nr.vid';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    // Select node in its last revision.
+    $query = $this->select('node_revisions', 'nr')
+      ->fields('n', array(
+        'nid',
+        'type',
+        'language',
+        'status',
+        'created',
+        'changed',
+        'comment',
+        'promote',
+        'moderate',
+        'sticky',
+        'tnid',
+        'translate',
+      ))
+      ->fields('nr', array(
+        'vid',
+        'uid',
+        'title',
+        'body',
+        'teaser',
+        'format',
+      ));
+    $query->innerJoin('node', 'n', static::JOIN);
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    $fields = array(
+      'nid' => $this->t('Node ID'),
+      'type' => $this->t('Type'),
+      'title' => $this->t('Title'),
+      'body' => $this->t('Body'),
+      'format' => $this->t('Format'),
+      'teaser' => $this->t('Teaser'),
+      'uid' => $this->t('Authored by (uid)'),
+      'created' => $this->t('Created timestamp'),
+      'changed' => $this->t('Modified timestamp'),
+      'status' => $this->t('Published'),
+      'promote' => $this->t('Promoted to front page'),
+      'sticky' => $this->t('Sticky at top of lists'),
+      'revision' => $this->t('Create new revision'),
+      'log' => $this->t('Revision Log message'),
+      'language' => $this->t('Language (fr, en, ...)'),
+      'tnid' => $this->t('The translation set id for this node'),
+    );
+    return $fields;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['nid']['type'] = 'integer';
+    $ids['nid']['alias'] = 'n';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function bundleMigrationRequired() {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function entityTypeId() {
+    return 'node';
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/NodeRevision.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/NodeRevision.php
new file mode 100644
index 0000000..87683e4
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/NodeRevision.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+* @file
+* Contains \Drupal\migrate\Plugin\migrate\source\d6\NodeRevision.
+*/
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+/**
+ * Drupal 6 node revision source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_node_revision"
+ * )
+ */
+class NodeRevision extends Node {
+
+  /**
+   * The join options between the node and the node_revisions_table.
+   */
+  const JOIN = 'n.nid = nr.nid AND n.vid <> nr.vid';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    // Use all the node fields plus the vid that identifies the version.
+    return parent::fields() + array('vid' => t('The primary identifier for this version.'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['vid']['type'] = 'integer';
+    $ids['vid']['alias'] = 'nr';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/NodeType.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/NodeType.php
new file mode 100644
index 0000000..94abb9c
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/NodeType.php
@@ -0,0 +1,127 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\NodeType.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 Node types source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_node_type"
+ * )
+ */
+class NodeType extends DrupalSqlBase {
+
+  /**
+   * The teaser length
+   *
+   * @var int
+   */
+  protected $teaserLength;
+
+  /**
+   * Node preview optional / required.
+   *
+   * @var int
+   */
+  protected $nodePreview;
+
+  /**
+   * An array of theme settings.
+   *
+   * @var array
+   */
+  protected $themeSettings;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('node_type', 't')
+      ->fields('t', array(
+        'type',
+        'name',
+        'module',
+        'description',
+        'help',
+        'has_title',
+        'title_label',
+        'has_body',
+        'body_label',
+        'min_word_count',
+        'custom',
+        'modified',
+        'locked',
+        'orig_type',
+      ))
+      ->orderBy('t.type');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'type' => $this->t('Machine name of the node type.'),
+      'name' => $this->t('Human name of the node type.'),
+      'module' => $this->t('The module providing the node type.'),
+      'description' => $this->t('Description of the node type.'),
+      'help' => $this->t('Help text for the node type.'),
+      'has_title' => $this->t('Flag indicating the node type has a title.'),
+      'title_label' => $this->t('Title label.'),
+      'has_body' => $this->t('Flag indicating the node type has a body field.'),
+      'body_label' => $this->t('Body label.'),
+      'min_word_count' => $this->t('Minimum word count for the body field.'),
+      'custom' => $this->t('Flag.'),
+      'modified' => $this->t('Flag.'),
+      'locked' => $this->t('Flag.'),
+      'orig_type' => $this->t('The original type.'),
+      'teaser_length' => $this->t('Teaser length'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function runQuery() {
+    $this->teaserLength = $this->variableGet('teaser_length', 600);
+    $this->nodePreview = $this->variableGet('node_preview', 0);
+    $this->themeSettings = $this->variableGet('theme_settings', array());
+    return parent::runQuery();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $row->setSourceProperty('teaser_length', $this->teaserLength);
+    $row->setSourceProperty('node_preview', $this->nodePreview);
+
+    $type = $row->getSourceProperty('type');
+    $options = $this->variableGet('node_options_' . $type, array('promote', 'sticky'));
+    foreach (array('promote', 'sticky', 'status', 'revision') as $item) {
+      $options[$item] = isset($options[$item]);
+    }
+    $row->setSourceProperty('options', $options);
+    $submitted = isset($this->themeSettings['toggle_node_info_' . $type]) ? $this->themeSettings['toggle_node_info_' . $type] : FALSE;
+    $row->setSourceProperty('submitted', $submitted);
+
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['type']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ProfileField.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ProfileField.php
new file mode 100644
index 0000000..e75989f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ProfileField.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\ProfileField.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 profile fields source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_profile_field",
+ *   source_provider = "profile"
+ * )
+ */
+class ProfileField extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('profile_fields', 'pf')
+      ->fields('pf', array(
+        'fid',
+        'title',
+        'name',
+        'explanation',
+        'category',
+        'page',
+        'type',
+        'weight',
+        'required',
+        'register',
+        'visibility',
+        'autocomplete',
+        'options',
+      ));
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'fid' => $this->t('Primary Key: Unique profile field ID.'),
+      'title' => $this->t('Title of the field shown to the end user.'),
+      'name' => $this->t('Internal name of the field used in the form HTML and URLs.'),
+      'explanation' => $this->t('Explanation of the field to end users.'),
+      'category' => $this->t('Profile category that the field will be grouped under.'),
+      'page' => $this->t("Title of page used for browsing by the field's value"),
+      'type' => $this->t('Type of form field.'),
+      'weight' => $this->t('Weight of field in relation to other profile fields.'),
+      'required' => $this->t('Whether the user is required to enter a value. (0 = no, 1 = yes)'),
+      'register' => $this->t('Whether the field is visible in the user registration form. (1 = yes, 0 = no)'),
+      'visibility' => $this->t('The level of visibility for the field. (0 = hidden, 1 = private, 2 = public on profile but not member list pages, 3 = public on profile and list pages)'),
+      'autocomplete' => $this->t('Whether form auto-completion is enabled. (0 = disabled, 1 = enabled)'),
+      'options' => $this->t('List of options to be used in a list selection field.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['fid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ProfileFieldValues.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ProfileFieldValues.php
new file mode 100644
index 0000000..41d735f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ProfileFieldValues.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\ProfileFieldValues.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Plugin\SourceEntityInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+use Drupal\migrate\Row;
+
+
+/**
+ * Drupal 6 profile fields values source.
+ *
+ * @MigrateSource(
+ *   id = "d6_profile_field_values",
+ *   source_provider = "profile"
+ * )
+ */
+class ProfileFieldValues extends DrupalSqlBase implements SourceEntityInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('profile_values', 'pv')
+      ->distinct()
+      ->fields('pv', array('fid', 'uid'));
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    // Find profile values for this row.
+    $query = $this->select('profile_values', 'pv')
+      ->fields('pv', array('fid', 'value'));
+    $query->leftJoin('profile_fields', 'pf', 'pf.fid=pv.fid');
+    $query->fields('pf', array('name', 'type'));
+    $query->condition('uid', $row->getSourceProperty('uid'));
+    $results = $query->execute();
+
+    foreach ($results as $profile_value) {
+      // Check special case for date. We need unserialize.
+      if ($profile_value['type'] == 'date') {
+        $date = unserialize($profile_value['value']);
+        $date = date('Y-m-d', mktime(0, 0, 0, $date['month'], $date['day'], $date['year']));
+        $row->setSourceProperty($profile_value['name'], array('value' => $date));
+      }
+      elseif ($profile_value['type'] == 'list') {
+        $row->setSourceProperty($profile_value['name'], explode("\n", $profile_value['value']));
+      }
+      else {
+        $row->setSourceProperty($profile_value['name'], array($profile_value['value']));
+      }
+    }
+
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    $fields = array(
+      'fid' => $this->t('Unique profile field ID.'),
+      'uid' => $this->t('The user Id.'),
+      'value' => $this->t('The value for this field..'),
+    );
+
+    $query = $this->select('profile_values', 'pv')
+      ->fields('pv', array('fid', 'value'));
+    $query->leftJoin('profile_fields', 'pf', 'pf.fid=pv.fid');
+    $query->fields('pf', array('name', 'title'));
+    $results = $query->execute();
+    foreach ($results as $profile) {
+      $fields[$profile['name']] = $this->t($profile['title']);
+    }
+
+    return $fields;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return array(
+      'uid' => array(
+        'type' => 'integer',
+        'alias' => 'pv',
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function bundleMigrationRequired() {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function entityTypeId() {
+    return 'user';
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Role.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Role.php
index b22765b..1677e33 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Role.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Role.php
@@ -9,13 +9,23 @@
 
 
 use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
 
 /**
  * Drupal 6 role source from database.
  *
- * @PluginId("drupal6_user_role")
+ * @MigrateSource(
+ *   id = "d6_user_role"
+ * )
  */
-class Role extends Drupal6SqlBase {
+class Role extends DrupalSqlBase {
+
+  /**
+   * List of filter IDs per role IDs.
+   *
+   * @var array
+   */
+  protected $filterPermissions = array();
 
   /**
    * {@inheritdoc}
@@ -32,31 +42,51 @@ public function query() {
    */
   public function fields() {
     return array(
-      'rid' => t('Role ID.'),
-      'name' => t('The name of the user role.'),
+      'rid' => $this->t('Role ID.'),
+      'name' => $this->t('The name of the user role.'),
     );
   }
 
   /**
    * {@inheritdoc}
    */
-  function prepareRow(Row $row, $keep = TRUE) {
-    $permissions = array();
-    $results = $this->database
-      ->select('permission', 'p', array('fetch' => \PDO::FETCH_ASSOC))
-      ->fields('p', array('pid', 'rid', 'perm', 'tid'))
-      ->condition('rid', $row->getSourceProperty('rid'))
-      ->execute();
-    foreach ($results as $perm) {
-      $permissions[] = array(
-        'pid' => $perm['pid'],
-        'rid' => $perm['rid'],
-        'perm' => array_map('trim', explode(',', $perm['perm'])),
-        'tid' => $perm['tid'],
-      );
+  protected function runQuery() {
+    $filter_roles = $this->select('filter_formats', 'f')
+      ->fields('f', array('format', 'roles'))
+      ->execute()
+      ->fetchAllKeyed();
+    foreach ($filter_roles as $format => $roles) {
+      // Drupal 6 code: $roles = ','. implode(',', $roles) .',';
+      // Remove the beginning and ending comma.
+      foreach (explode(',', trim($roles, ',')) as $rid) {
+        $this->filterPermissions[$rid][] = $format;
+      }
+    }
+    return parent::runQuery();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row, $keep = TRUE) {
+    $rid = $row->getSourceProperty('rid');
+    $permissions = $this->select('permission', 'p')
+      ->fields('p', array('perm'))
+      ->condition('rid', $rid)
+      ->execute()
+      ->fetchField();
+    $row->setSourceProperty('permissions', explode(', ', $permissions));
+    if (isset($this->filterPermissions[$rid])) {
+      $row->setSourceProperty("filter_permissions:$rid", $this->filterPermissions[$rid]);
     }
-    $row->setSourceProperty('permissions', $permissions);
     return parent::prepareRow($row);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['rid']['type'] = 'integer';
+    return $ids;
+  }
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Term.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Term.php
new file mode 100644
index 0000000..ffaf9ee
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Term.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Term.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 taxonomy terms source from database.
+ *
+ * @todo Support term_relation, term_synonym table if possible.
+ *
+ * @MigrateSource(
+ *   id = "d6_taxonomy_term",
+ *   source_provider = "taxonomy"
+ * )
+ */
+class Term extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    // Note the explode - this supports the (admittedly unusual) case of
+    // consolidating multiple vocabularies into one.
+    $query = $this->select('term_data', 'td')
+      ->fields('td', array('tid', 'vid', 'name', 'description', 'weight'))
+      // @todo: working, but not is there support for distinct() in FakeSelect?
+      ->distinct();
+    if (isset($this->configuration['vocabulary'])) {
+      $query->condition('vid', $this->configuration['vocabulary'], 'IN');
+    }
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'tid' => $this->t('The term ID.'),
+      'vid' => $this->t('Existing term VID'),
+      'name' => $this->t('The name of the term.'),
+      'description' => $this->t('The term description.'),
+      'weight' => $this->t('Weight'),
+      'parent' => $this->t("The Drupal term IDs of the term's parents."),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    // Find parents for this row.
+    $parents = $this->select('term_hierarchy', 'th')
+      ->fields('th', array('parent', 'tid'))
+      ->condition('tid', $row->getSourceProperty('tid'))
+      ->execute()
+      ->fetchCol();
+    $row->setSourceProperty('parent', $parents);
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['tid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/TermNode.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/TermNode.php
new file mode 100644
index 0000000..fea7808
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/TermNode.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\source\d6\TermNode.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Plugin\SourceEntityInterface;
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Source returning tids from the term_node table for the current revision.
+ *
+ * @MigrateSource(
+ *   id = "d6_term_node",
+ *   source_provider = "taxonomy"
+ * )
+ */
+class TermNode extends DrupalSqlBase implements SourceEntityInterface {
+
+    /**
+   * The join options between the node and the term node table.
+   */
+  const JOIN = 'tn.vid = n.vid';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('term_node', 'tn')
+      // @todo: working, but not is there support for distinct() in FakeSelect?
+      ->distinct()
+      ->fields('tn', array('nid', 'vid'))
+      ->fields('n', array('type'));
+    // Because this is an inner join it enforces the current revision.
+    $query->innerJoin('term_data', 'td', 'td.tid = tn.tid AND td.vid = :vid', array(':vid' => $this->configuration['vid']));
+    $query->innerJoin('node', 'n', static::JOIN);
+    return $query;
+
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'nid' => $this->t('The node revision ID.'),
+      'vid' => $this->t('The node revision ID.'),
+      'tid' => $this->t('The term ID.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    // Select the terms belonging to the revision selected.
+    $query = $this->select('term_node', 'tn')
+      ->fields('tn', array('tid'))
+      ->condition('n.nid', $row->getSourceProperty('nid'));
+    $query->join('node', 'n', static::JOIN);
+    $query->innerJoin('term_data', 'td', 'td.tid = tn.tid AND td.vid = :vid', array(':vid' => $this->configuration['vid']));
+    $row->setSourceProperty('tid', $query->execute()->fetchCol());
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['vid']['type'] = 'integer';
+    $ids['vid']['alias'] = 'tn';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function bundleMigrationRequired() {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function entityTypeId() {
+    return 'taxonomy_term';
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/TermNodeRevision.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/TermNodeRevision.php
new file mode 100644
index 0000000..99acd0e
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/TermNodeRevision.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\source\d6\TermNodeRevision.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+/**
+ * Source returning tids from the term_node table for the non-current revision.
+ *
+ * @MigrateSource(
+ *   id = "d6_term_node_revision"
+ * )
+ */
+class TermNodeRevision extends TermNode {
+
+  /**
+   * {@inheritdoc}
+   */
+  const JOIN = 'tn.nid = n.nid AND tn.vid != n.vid';
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Upload.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Upload.php
new file mode 100644
index 0000000..2640c6b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Upload.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Upload.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 upload source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_upload",
+ *   source_provider = "upload"
+ * )
+ */
+class Upload extends DrupalSqlBase {
+
+  /**
+   * The join options between the node and the upload table.
+   */
+  const JOIN = 'n.nid = u.nid AND n.vid = u.vid';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('upload', 'u')
+      ->distinct()
+      ->fields('u', array('nid', 'vid'));
+    $query->innerJoin('node', 'n', static::JOIN);
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $query = $this->select('upload', 'u')
+      ->fields('u', array('fid', 'description', 'list'))
+      ->condition('u.nid', $row->getSourceProperty('nid'))
+      ->orderBy('u.weight');
+    $query->innerJoin('node', 'n', static::JOIN);
+    $row->setSourceProperty('upload', $query->execute()->fetchAll());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'fid' => $this->t('The file Id.'),
+      'nid' => $this->t('The node Id.'),
+      'vid' => $this->t('The version Id.'),
+      'description' => $this->t('The file description.'),
+      'list' => $this->t('Whether the list should be visible on the node page.'),
+      'weight' => $this->t('The file weight.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['vid']['type'] = 'integer';
+    $ids['vid']['alias'] = 'u';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UploadInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UploadInstance.php
new file mode 100644
index 0000000..0f9c60b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UploadInstance.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\UploadInstance.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 upload instance source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_upload_instance"
+ * )
+ */
+class UploadInstance extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function runQuery() {
+    $prefix = 'upload';
+    $node_types = $this->getDatabase()->query('SELECT type FROM {node_type}')->fetchCol();
+    foreach ($node_types as $node_type) {
+      $variables[] = $prefix . '_' . $node_type;
+    }
+
+    $max_filesize = $this->variableGet('upload_uploadsize_default', 1);
+    $max_filesize = $max_filesize ? $max_filesize . 'MB' : '';
+    $file_extensions = $this->variableGet('upload_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp');
+    $return = array();
+    $values = $this->getDatabase()->query('SELECT name, value FROM {variable} WHERE name IN (:name)', array(':name' => $variables))->fetchAllKeyed();
+    foreach ($node_types as $node_type) {
+      $name = $prefix . '_' . $node_type;
+      if (isset($values[$name])) {
+        $enabled = unserialize($values[$name]);
+        if ($enabled) {
+          $return[$node_type]['node_type'] = $node_type;
+          $return[$node_type]['max_filesize'] = $max_filesize;
+          $return[$node_type]['file_extensions'] = $file_extensions;
+        }
+      }
+    }
+
+    return new \ArrayIterator($return);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return array(
+      'node_type' => array(
+        'type' => 'string',
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    // Nothing needed here.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkRequirements() {
+    return $this->moduleExists('upload');
+  }
+
+  /**
+   * {@inheritdoc
+   */
+  public function fields() {
+    $fields = array(
+      'node_type' => $this->t('Node type'),
+      'max_filesize' => $this->t('Max filesize'),
+      'file_extensions' => $this->t('File extensions'),
+    );
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UrlAlias.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UrlAlias.php
new file mode 100644
index 0000000..c2e48db
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UrlAlias.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\UrlAlias.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 url aliases source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_url_alias"
+ * )
+ */
+class UrlAlias extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('url_alias', 'ua')
+      ->fields('ua', array('pid', 'src', 'dst', 'language'));
+    $query->orderBy('pid');
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'pid' => $this->t('The numeric identifier of the path alias.'),
+      'src' => $this->t('The internal path.'),
+      'dst' => $this->t('The user set path alias.'),
+      'language' => $this->t('The language code of the url alias.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['pid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/User.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/User.php
new file mode 100644
index 0000000..410ad47
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/User.php
@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\User.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Plugin\SourceEntityInterface;
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 user source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_user"
+ * )
+ */
+class User extends DrupalSqlBase implements SourceEntityInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('users', 'u')
+      ->fields('u', array_keys($this->baseFields()))
+      ->condition('uid', 1, '>');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    $fields = $this->baseFields();
+
+    // Add roles field.
+    $fields['roles'] = $this->t('Roles');
+
+    // Profile fields.
+    if ($this->moduleExists('profile')) {
+      $fields += $this->select('profile_fields', 'pf')
+        ->fields('pf', array('name', 'title'))
+        ->execute()
+        ->fetchAllKeyed();
+    }
+
+    return $fields;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row, $keep = TRUE) {
+    // User roles.
+    $roles = $this->select('users_roles', 'ur')
+      ->fields('ur', array('rid'))
+      ->condition('ur.uid', $row->getSourceProperty('uid'))
+      ->execute()
+      ->fetchCol();
+    $row->setSourceProperty('roles', $roles);
+
+    // We are adding here the Event contributed module column.
+    // @see https://api.drupal.org/api/drupal/modules%21user%21user.install/function/user_update_7002/7
+    if ($row->hasSourceProperty('timezone_id') && $row->getSourceProperty('timezone_id')) {
+      if ($this->getDatabase()->schema()->tableExists('event_timezones')) {
+        $event_timezone = $this->select('event_timezones', 'e')
+          ->fields('e', array('name'))
+          ->condition('e.timezone', $row->getSourceProperty('timezone_id'))
+          ->execute()
+          ->fetchField();
+        if ($event_timezone) {
+          $row->setSourceProperty('event_timezone', $event_timezone);
+        }
+      }
+    }
+
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return array(
+      'uid' => array(
+        'type' => 'integer',
+        'alias' => 'u',
+      ),
+    );
+  }
+
+  /**
+   * Returns the user base fields to be migrated.
+   *
+   * @return array
+   *   Associative array having field name as key and description as value.
+   */
+  protected function baseFields() {
+    $fields = array(
+      'uid' => $this->t('User ID'),
+      'name' => $this->t('Username'),
+      'pass' => $this->t('Password'),
+      'mail' => $this->t('Email address'),
+      'signature' => $this->t('Signature'),
+      'signature_format' => $this->t('Signature format'),
+      'created' => $this->t('Registered timestamp'),
+      'access' => $this->t('Last access timestamp'),
+      'login' => $this->t('Last login timestamp'),
+      'status' => $this->t('Status'),
+      'timezone' => $this->t('Timezone'),
+      'language' => $this->t('Language'),
+      'picture' => $this->t('Picture'),
+      'init' => $this->t('Init'),
+    );
+
+    // Possible field added by Date contributed module.
+    // @see https://api.drupal.org/api/drupal/modules%21user%21user.install/function/user_update_7002/7
+    if ($this->getDatabase()->schema()->fieldExists('users', 'timezone_name')) {
+      $fields['timezone_name'] = $this->t('Timezone (Date)');
+    }
+
+    // Possible field added by Event contributed module.
+    // @see https://api.drupal.org/api/drupal/modules%21user%21user.install/function/user_update_7002/7
+    if ($this->getDatabase()->schema()->fieldExists('users', 'timezone_id')) {
+      $fields['timezone_id'] = $this->t('Timezone (Event)');
+    }
+
+    return $fields;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function bundleMigrationRequired() {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function entityTypeId() {
+    return 'user';
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPicture.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPicture.php
new file mode 100644
index 0000000..ae7b6ab
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPicture.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\UserPicture.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+
+/**
+ * Drupal 6 user picture source from database.
+ *
+ * @todo Support default picture?
+ *
+ * @MigrateSource(
+ *   id = "d6_user_picture"
+ * )
+ */
+class UserPicture extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->getDatabase()
+      ->select('users', 'u')
+      ->condition('picture', '', '<>')
+      ->fields('u', array('uid', 'access', 'picture'))
+      ->orderBy('access');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'uid' => 'Primary Key: Unique user ID.',
+      'access' => 'Timestamp for previous time user accessed the site.',
+      'picture' => "Path to the user's uploaded picture.",
+    );
+  }
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['uid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPictureFile.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPictureFile.php
new file mode 100644
index 0000000..e08cfe0
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPictureFile.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\UserPictureFile.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+use Drupal\migrate\Row;
+
+/**
+ * Drupal 6 user picture source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_user_picture_file"
+ * )
+ */
+class UserPictureFile extends DrupalSqlBase {
+
+  /**
+   * The file directory path.
+   *
+   * @var string
+   */
+  protected $filePath;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('users', 'u')
+      ->condition('picture', '', '<>')
+      ->fields('u', array('uid', 'picture'));
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function runQuery() {
+    $conf_path = isset($this->configuration['conf_path']) ? $this->configuration['conf_path'] : 'sites/default';
+    $this->filePath = $this->variableGet('file_directory_path', $conf_path . '/files') . '/';
+    return parent::runQuery();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $row->setSourceProperty('filename', basename($row->getSourceProperty('picture')));
+    $row->setSourceProperty('file_directory_path', $this->filePath);
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'picture' => "Path to the user's uploaded picture.",
+      'filename' => 'The picture filename.',
+    );
+  }
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['uid']['type'] = 'integer';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPictureInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPictureInstance.php
new file mode 100644
index 0000000..b239a16
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/UserPictureInstance.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\UserPictureInstance.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+
+/**
+ * Drupal 6 user picture field instance source.
+ *
+ * @todo Support default picture?
+ *
+ * @MigrateSource(
+ *   id = "d6_user_picture_instance"
+ * )
+ */
+class UserPictureInstance extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function runQuery() {
+    return new \ArrayIterator(array(
+      array(
+        'id' => '',
+        'file_directory' => $this->variableGet('user_picture_path', 'pictures'),
+        'max_filesize' => $this->variableGet('user_picture_file_size', '30') . 'KB',
+        'max_resolution' => $this->variableGet('user_picture_dimensions', '85x85'),
+      )));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'file_directory' => 'The directory to store images..',
+      'max_filesize' => 'The maximum allowed file size in KBs.',
+      'max_resolution' => "The maximum resolution.",
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['id']['type'] = 'string';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    // Nothing to do here.
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Variable.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Variable.php
deleted file mode 100644
index e9a24b5..0000000
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Variable.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\migrate\Plugin\migrate\source\d6\Variable.
- */
-
-namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
-
-use Drupal\migrate\Entity\MigrationInterface;
-
-/**
- * Drupal 6 variable source from database.
- *
- * This source class always returns a single row and as such is not a good
- * example for any normal source class returning multiple rows.
- *
- * @PluginID("drupal6_variable")
- */
-class Variable extends Drupal6SqlBase {
-
-  /**
-   * The variable names to fetch.
-   *
-   * @var array
-   */
-  protected $variables;
-
-  /**
-   * {@inheritdoc}
-   */
-  function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
-    $this->variables = $this->configuration['variables'];
-  }
-
-  protected function runQuery() {
-    return new \ArrayIterator(array(array_map('unserialize', $this->query()->execute()->fetchAllKeyed())));
-  }
-
-  public function count() {
-    return intval($this->query()->countQuery()->execute()->fetchField() > 0);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function fields() {
-    return array_combine($this->variables, $this->variables);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  function query() {
-    return $this->getDatabase()
-      ->select('variable', 'v')
-      ->fields('v', array('name', 'value'))
-      ->condition('name', $this->variables, 'IN');
-  }
-}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ViewMode.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ViewMode.php
new file mode 100644
index 0000000..75cafc3
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ViewMode.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\ViewMode.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Row;
+
+/**
+ * A base class for field instances which all require the same data and fields.
+ *
+ * @MigrateSource(
+ *   id = "d6_view_mode"
+ * )
+ */
+class ViewMode extends ViewModeBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function runQuery() {
+    $rows = array();
+    $result = $this->prepareQuery()->execute();
+    while ($field_row = $result->fetchAssoc()) {
+      $field_row['display_settings'] = unserialize($field_row['display_settings']);
+      foreach ($this->getViewModes() as $view_mode) {
+        if (isset($field_row['display_settings'][$view_mode]) && !$field_row['display_settings'][$view_mode]['exclude']) {
+          if (!isset($rows[$view_mode])) {
+            $rows[$view_mode]['entity_type'] = 'node';
+            $rows[$view_mode]['view_mode'] = $view_mode;
+          }
+        }
+      }
+    }
+
+    return new \ArrayIterator($rows);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('content_node_field_instance', 'cnfi')
+      ->fields('cnfi', array(
+        'display_settings',
+      ));
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'display_settings' => $this->t('Serialize data with display settings.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['view_mode']['type'] = 'string';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ViewModeBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ViewModeBase.php
new file mode 100644
index 0000000..e364032
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/ViewModeBase.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\ViewModeBase.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * A base class for migrations that require view mode info.
+ */
+abstract class ViewModeBase extends DrupalSqlBase {
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function count() {
+    return count($this->runQuery());
+  }
+
+  /**
+   * Get a list of D6 view modes.
+   *
+   * Drupal 6 supported the following view modes.
+   * NODE_BUILD_NORMAL = 0
+   * NODE_BUILD_PREVIEW = 1
+   * NODE_BUILD_SEARCH_INDEX = 2
+   * NODE_BUILD_SEARCH_RESULT = 3
+   * NODE_BUILD_RSS = 4
+   * NODE_BUILD_PRINT = 5
+   * teaser
+   * full
+   *
+   * @return array
+   *   The view mode names.
+   */
+  public function getViewModes() {
+    return array(
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      'teaser',
+      'full',
+    );
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Vocabulary.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Vocabulary.php
new file mode 100644
index 0000000..211e8a9
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Vocabulary.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Vocabulary.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+
+/**
+ * Drupal 6 vocabularies source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_taxonomy_vocabulary",
+ *   source_provider = "taxonomy"
+ * )
+ */
+class Vocabulary extends VocabularyBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    // Find node types for this row.
+    $node_types = $this->select('vocabulary_node_types', 'nt')
+      ->fields('nt', array('type', 'vid'))
+      ->condition('vid', $row->getSourceProperty('vid'))
+      ->execute()
+      ->fetchCol();
+    $row->setSourceProperty('node_types', $node_types);
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['vid']['type'] = 'integer';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/VocabularyBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/VocabularyBase.php
new file mode 100644
index 0000000..885aebe
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/VocabularyBase.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\VocabularyBase.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 vocabularies source base.
+ */
+abstract class VocabularyBase extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('vocabulary', 'v')
+      ->fields('v', array(
+        'vid',
+        'name',
+        'description',
+        'help',
+        'relations',
+        'hierarchy',
+        'multiple',
+        'required',
+        'tags',
+        'module',
+        'weight',
+      ));
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'vid' => $this->t('The vocabulary ID.'),
+      'name' => $this->t('The name of the vocabulary.'),
+      'description' => $this->t('The description of the vocabulary.'),
+      'help' => $this->t('Help text to display for the vocabulary.'),
+      'relations' => $this->t('Whether or not related terms are enabled within the vocabulary. (0 = disabled, 1 = enabled)'),
+      'hierarchy' => $this->t('The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)'),
+      'multiple' => $this->t('Whether or not multiple terms from this vocabulary may be assigned to a node. (0 = disabled, 1 = enabled)'),
+      'required' => $this->t('Whether or not terms are required for nodes using this vocabulary. (0 = disabled, 1 = enabled)'),
+      'tags' => $this->t('Whether or not free tagging is enabled for the vocabulary. (0 = disabled, 1 = enabled)'),
+      'weight' => $this->t('The weight of the vocabulary in relation to other vocabularies.'),
+      'parents' => $this->t("The Drupal term IDs of the term's parents."),
+      'node_types' => $this->t('The names of the node types the vocabulary may be used with.'),
+    );
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/VocabularyPerType.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/VocabularyPerType.php
new file mode 100644
index 0000000..f03cb25
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/VocabularyPerType.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Vocabulary.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate\Row;
+
+/**
+ * Drupal 6 vocabularies source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_taxonomy_vocabulary_per_type",
+ *   source_provider = "taxonomy"
+ * )
+ */
+class VocabularyPerType extends Vocabulary {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = parent::query();
+    $query->fields('nt', array(
+        'type',
+      ));
+    $query->join('vocabulary_node_types', 'nt', 'v.vid = nt.vid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['vid']['type'] = 'integer';
+    $ids['vid']['alias'] = 'nt';
+    $ids['type']['type'] = 'string';
+    return $ids;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ActionSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ActionSettings.php
index 245d19e..587a84f 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ActionSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ActionSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing action.settings.yml migration.
  */
-class Drupal6ActionSettings {
+class Drupal6ActionSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorFeed.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorFeed.php
new file mode 100644
index 0000000..8710662
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorFeed.php
@@ -0,0 +1,129 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\Dump\Drupal6Feed.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing feed migration.
+ */
+class Drupal6AggregatorFeed extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('aggregator_feed', array(
+      'description' => 'Stores feeds to be parsed by the aggregator.',
+      'fields' => array(
+        'fid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+          'description' => 'Primary Key: Unique feed ID.',
+        ),
+        'title' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Title of the feed.',
+        ),
+        'url' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'URL to the feed.',
+        ),
+        'refresh' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'How often to check for new feed items, in seconds.',
+        ),
+        'checked' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'Last time feed was checked for new items, as Unix timestamp.',
+        ),
+        'link' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'The parent website of the feed; comes from the &lt;link&gt; element in the feed.',
+        ),
+        'description' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+          'description' => "The parent website's description; comes from the &lt;description&gt; element in the feed.",
+        ),
+        'image' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+          'description' => 'An image representing the feed.',
+        ),
+        'etag' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Entity tag HTTP response header, used for validating cache.',
+        ),
+        'modified' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'When the feed was last modified, as a Unix timestamp.',
+        ),
+        'block' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => "Number of items to display in the feed's block.",
+        )
+      ),
+      'primary key' => array('fid'),
+      'unique keys' => array(
+        'url'  => array('url'),
+        'title' => array('title'),
+      ),
+    ));
+
+    $this->database->insert('aggregator_feed')->fields(array(
+      'fid',
+      'title',
+      'url',
+      'refresh',
+      'checked',
+      'link',
+      'description',
+      'image',
+      'etag',
+      'modified',
+      'block',
+    ))
+    ->values(array(
+      'fid' => 5,
+      'title' => 'Know Your Meme',
+      'url' => 'http://knowyourmeme.com/newsfeed.rss',
+      'refresh' => 900,
+      'checked' => 1387659487,
+      'link' => 'http://knowyourmeme.com',
+      'description' => 'New items added to the News Feed',
+      'image' => 'http://b.thumbs.redditmedia.com/harEHsUUZVajabtC.png',
+      'etag' => '"213cc1365b96c310e92053c5551f0504"',
+      'modified' => 0,
+      'block' => 5,
+    ))
+    ->execute();
+    $this->setModuleVersion('aggregator', 6001);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorItem.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorItem.php
new file mode 100644
index 0000000..c866631
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorItem.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\Dump\Drupal6AggregatorItem.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing aggregator item migration.
+ */
+class Drupal6AggregatorItem extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('aggregator_item', array(
+      'description' => 'Stores the individual items imported from feeds.',
+      'fields' => array(
+        'iid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+          'description' => 'Primary Key: Unique ID for feed item.',
+        ),
+        'fid' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'The {aggregator_feed}.fid to which this item belongs.',
+        ),
+        'title' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Title of the feed item.',
+        ),
+        'link' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Link to the feed item.',
+        ),
+        'author' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Author of the feed item.',
+        ),
+        'description' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+          'description' => 'Body of the feed item.',
+        ),
+        'timestamp' => array(
+          'type' => 'int',
+          'not null' => FALSE,
+          'description' => 'Post date of feed item, as a Unix timestamp.',
+        ),
+        'guid' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => FALSE,
+          'description' => 'Unique identifier for the feed item.',
+        ),
+      ),
+      'primary key' => array('iid'),
+      'indexes' => array('fid' => array('fid')),
+    ));
+
+    $this->database->insert('aggregator_item')->fields(array(
+      'iid',
+      'fid',
+      'title',
+      'link',
+      'author',
+      'description',
+      'timestamp',
+      'guid',
+    ))
+    ->values(array(
+      'iid' => 1,
+      'fid' => 5,
+      'title' => 'This (three) weeks in Drupal Core - January 10th 2014',
+      'link' => 'https://groups.drupal.org/node/395218',
+      'author' => 'larowlan',
+      'description' => "<h2 id='new'>What's new with Drupal 8?</h2>",
+      'timestamp' => 1389297196,
+      'guid' => '395218 at https://groups.drupal.org',
+    ))
+    ->execute();
+
+    $this->setModuleVersion('aggregator', '6001');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorSettings.php
index 7d0de49..51bfb9f 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing aggregator.settings.yml migration.
  */
-class Drupal6AggregatorSettings {
+class Drupal6AggregatorSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Block.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Block.php
new file mode 100644
index 0000000..3144fb7
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Block.php
@@ -0,0 +1,311 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Block.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+class Drupal6Block extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('blocks', array(
+      'fields' => array(
+        'bid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+        ),
+        'module' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'delta' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '0',
+        ),
+        'theme' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'status' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'region' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'custom' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'throttle' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'visibility' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'pages' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+        ),
+        'title' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'cache' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 1,
+          'size' => 'tiny',
+        ),
+      ),
+      'primary key' => array(
+        'bid',
+      ),
+      'unique keys' => array(
+        'tmd' => array(
+          'theme',
+          'module',
+          'delta',
+        ),
+      ),
+      'indexes' => array(
+        'list' => array(
+          'theme',
+          'status',
+          'region',
+          'weight',
+          'module',
+        ),
+      ),
+    ));
+    $this->createTable('blocks_roles', array(
+      'fields' => array(
+        'module' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+        ),
+        'delta' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+        ),
+        'rid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+      ),
+      'primary key' => array(
+        'module',
+        'delta',
+        'rid',
+      ),
+      'indexes' => array(
+        'rid' => array(
+          'rid',
+        ),
+      ),
+      'module' => 'block',
+      'name' => 'blocks_roles',
+    ));
+    $this->database->insert('blocks')->fields(array(
+      'bid',
+      'module',
+      'delta',
+      'theme',
+      'status',
+      'weight',
+      'region',
+      'custom',
+      'throttle',
+      'visibility',
+      'pages',
+      'title',
+      'cache',
+    ))
+    ->values(array(
+      'bid' => '1',
+      'module' => 'user',
+      'delta' => '0',
+      'theme' => 'garland',
+      'status' => '1',
+      'weight' => '0',
+      'region' => 'left',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '-1'
+     ))
+    ->values(array(
+      'bid' => '2',
+      'module' => 'user',
+      'delta' => '1',
+      'theme' => 'garland',
+      'status' => '1',
+      'weight' => '0',
+      'region' => 'left',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '-1'
+    ))
+    ->values(array(
+      'bid' => '3',
+      'module' => 'system',
+      'delta' => '0',
+      'theme' => 'garland',
+      'status' => '1',
+      'weight' => '-5',
+      'region' => 'footer',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '-1'
+    ))
+    ->values(array(
+      'bid' => '4',
+      'module' => 'comment',
+      'delta' => '0',
+      'theme' => 'garland',
+      'status' => '0',
+      'weight' => '-6',
+      'region' => '',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '1'
+    ))
+    ->values(array(
+      'bid' => '5',
+      'module' => 'menu',
+      'delta' => 'primary-links',
+      'theme' => 'garland',
+      'status' => '1',
+      'weight' => '-5',
+      'region' => 'header',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '-1'
+    ))
+    ->values(array(
+      'bid' => '6',
+      'module' => 'menu',
+      'delta' => 'secondary-links',
+      'theme' => 'garland',
+      'status' => '0',
+      'weight' => '-5',
+      'region' => '',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '-1'
+    ))
+    ->values(array(
+      'bid' => '7',
+      'module' => 'node',
+      'delta' => '0',
+      'theme' => 'garland',
+      'status' => '0',
+      'weight' => '-4',
+      'region' => '',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '-1'
+    ))
+    ->values(array(
+      'bid' => '8',
+      'module' => 'user',
+      'delta' => '2',
+      'theme' => 'garland',
+      'status' => '0',
+      'weight' => '-3',
+      'region' => '',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '1'
+    ))
+    ->values(array(
+      'bid' => '9',
+      'module' => 'user',
+      'delta' => '3',
+      'theme' => 'garland',
+      'status' => '0',
+      'weight' => '-1',
+      'region' => '',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '0',
+      'pages' => '',
+      'title' => '',
+      'cache' => '-1'
+    ))
+    ->values(array(
+      'bid' => '10',
+      'module' => 'block',
+      'delta' => '1',
+      'theme' => 'garland',
+      'status' => '1',
+      'weight' => '0',
+      'region' => 'content',
+      'custom' => '0',
+      'throttle' => '0',
+      'visibility' => '1',
+      'pages' => '<front>',
+      'title' => 'Static Block',
+      'cache' => '-1'
+    ))
+    ->execute();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6BookSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6BookSettings.php
index 104fb7b..0bf6a57 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6BookSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6BookSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing book.settings.yml migration.
  */
-class Drupal6BookSettings {
+class Drupal6BookSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Box.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Box.php
new file mode 100644
index 0000000..d042f72
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Box.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Box.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+class Drupal6Box extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('boxes', array(
+      'description' => 'Stores contents of custom-made blocks.',
+      'fields' => array(
+        'bid' => array(
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'description' => "The block's {blocks}.bid.",
+        ),
+        'body' => array(
+          'type' => 'text',
+          'not null' => FALSE,
+          'size' => 'big',
+          'description' => 'Block contents.',
+        ),
+        'info' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Block description.',
+        ),
+        'format' => array(
+          'type' => 'int',
+          'size' => 'small',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => "Block body's {filter_formats}.format; for example, 1 = Filtered HTML.",
+        ),
+      ),
+      'unique keys' => array('info' => array('info')),
+      'primary key' => array('bid'),
+    ));
+
+    $this->database->insert('boxes')->fields(array(
+      'bid',
+      'body',
+      'info',
+      'format',
+    ))
+    ->values(array(
+      'bid' => '1',
+      'body' => '<h3>My custom block body</h3>',
+      'info' => 'My block 1',
+      'format' => 2,
+    ))
+    ->execute();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Comment.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Comment.php
new file mode 100644
index 0000000..0a938a0
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Comment.php
@@ -0,0 +1,189 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Comment.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+class Drupal6Comment extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('comments', array(
+      'description' => 'Stores comments and associated data.',
+      'fields' => array(
+        'cid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+          'description' => 'Primary Key: Unique comment ID.',
+        ),
+        'pid' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'The {comments}.cid to which this comment is a reply. If set to 0, this comment is not a reply to an existing comment.',
+        ),
+        'nid' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'The {node}.nid to which this comment is a reply.',
+        ),
+        'uid' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'The {users}.uid who authored the comment. If set to 0, this comment was created by an anonymous user.',
+        ),
+        'subject' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'The comment title.',
+        ),
+        'comment' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+          'description' => 'The comment body.',
+        ),
+        'hostname' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => "The author's host name.",
+        ),
+        'timestamp' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'The time that the comment was created, or last edited by its author, as a Unix timestamp.',
+        ),
+        'status' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'The published status of a comment. (0 = Published, 1 = Not Published)',
+        ),
+        'format' => array(
+          'type' => 'int',
+          'size' => 'small',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'The {filter_formats}.format of the comment body.',
+        ),
+        'thread' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'description' => "The vancode representation of the comment's place in a thread.",
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 60,
+          'not null' => FALSE,
+          'description' => "The comment author's name. Uses {users}.name if the user is logged in, otherwise uses the value typed into the comment form.",
+        ),
+        'mail' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => FALSE,
+          'description' => "The comment author's e-mail address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on.",
+        ),
+        'homepage' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => FALSE,
+          'description' => "The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on.",
+        ),
+      ),
+      'indexes' => array(
+        'pid'    => array('pid'),
+        'nid'    => array('nid'),
+        'comment_uid'    => array('uid'),
+        'status' => array('status'), // This index is probably unused
+      ),
+      'primary key' => array('cid'),
+    ));
+    $this->database->insert('comments')->fields(array(
+      'cid',
+      'pid',
+      'nid',
+      'uid',
+      'subject',
+      'comment',
+      'hostname',
+      'timestamp',
+      'status',
+      'format',
+      'thread',
+      'name',
+      'mail',
+      'homepage',
+    ))
+    // The comment structure is:
+    // -1
+    // -3
+    // --2
+    ->values(array(
+      'cid' => 1,
+      'pid' => 0,
+      'nid' => 1,
+      'uid' => 0,
+      'subject' => 'The first comment.',
+      'comment' => 'The first comment body.',
+      'hostname' => '127.0.0.1',
+      'timestamp' => 1390264918,
+      'status' => 0,
+      'format' => 1,
+      'thread' => '01/',
+      'name' => '1st comment author name',
+      'mail' => 'comment1@example.com',
+      'homepage' => 'http://drupal.org',
+    ))
+    ->values(array(
+      'cid' => 2,
+      'pid' => 3,
+      'nid' => 1,
+      'uid' => 0,
+      'subject' => 'The response to the second comment.',
+      'comment' => 'The second comment response body.',
+      'hostname' => '127.0.0.1',
+      'timestamp' => 1390264938,
+      'status' => 0,
+      'format' => 1,
+      'thread' => '02/01',
+      'name' => '3rd comment author name',
+      'mail' => 'comment3@example.com',
+      'homepage' => 'http://drupal.org',
+    ))
+    ->values(array(
+      'cid' => 3,
+      'pid' => 0,
+      'nid' => 1,
+      'uid' => 0,
+      'subject' => 'The second comment.',
+      'comment' => 'The second comment body.',
+      'hostname' => '127.0.0.1',
+      'timestamp' => 1390264948,
+      // This comment is unpublished.
+      'status' => 1,
+      'format' => 1,
+      'thread' => '02/',
+      'name' => '3rd comment author name',
+      'mail' => 'comment3@example.com',
+      'homepage' => 'http://drupal.org',
+    ))
+    ->execute();
+    $this->setModuleVersion('comment', '6001');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php
new file mode 100644
index 0000000..9d150f2
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php
@@ -0,0 +1,238 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6CommentVariable.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing comment variables migration.
+ */
+class Drupal6CommentVariable extends Drupal6DumpBase {
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('variable');
+    $this->createTable('node_type', array(
+      'fields' => array(
+        'type' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'module' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+        ),
+        'description' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'medium',
+        ),
+        'help' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'medium',
+        ),
+        'has_title' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'size' => 'tiny',
+        ),
+        'title_label' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'has_body' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'size' => 'tiny',
+        ),
+        'body_label' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'min_word_count' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'size' => 'small',
+        ),
+        'custom' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'modified' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'locked' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'orig_type' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+      ),
+      'primary key' => array(
+        'type',
+      ),
+      'module' => 'node',
+      'name' => 'node_type',
+    ));
+    $this->database->insert('node_type')->fields(array(
+      'type',
+      'name',
+      'module',
+      'description',
+      'help',
+      'has_title',
+      'title_label',
+      'has_body',
+      'body_label',
+      'min_word_count',
+      'custom',
+      'modified',
+      'locked',
+      'orig_type',
+    ))
+    ->values(array(
+      'type' => 'page',
+      'name' => 'Page',
+      'module' => 'node',
+      'description' => "A <em>page</em>, similar in form to a <em>story</em>, is a simple method for creating and displaying information that rarely changes, such as an \"About us\" section of a website. By default, a <em>page</em> entry does not allow visitor comments and is not featured on the site's initial home page.",
+      'help' => '',
+      'has_title' => '1',
+      'title_label' => 'Title',
+      'has_body' => '1',
+      'body_label' => 'Body',
+      'min_word_count' => '0',
+      'custom' => '1',
+      'modified' => '1',
+      'locked' => '0',
+      'orig_type' => 'page',
+    ))
+    ->values(array(
+      'type' => 'story',
+      'name' => 'Story',
+      'module' => 'node',
+      'description' => "A <em>story</em>, similar in form to a <em>page</em>, is ideal for creating and displaying content that informs or engages website visitors. Press releases, site announcements, and informal blog-like entries may all be created with a <em>story</em> entry. By default, a <em>story</em> entry is automatically featured on the site's initial home page, and provides the ability to post comments.",
+      'help' => '',
+      'has_title' => '1',
+      'title_label' => 'Title',
+      'has_body' => '1',
+      'body_label' => 'Body',
+      'min_word_count' => '0',
+      'custom' => '1',
+      'modified' => '1',
+      'locked' => '0',
+      'orig_type' => 'story',
+    ))
+    ->execute();
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'comment_anonymous_page',
+      'value' => 'i:0;',
+    ))
+    ->values(array(
+      'name' => 'comment_anonymous_story',
+      'value' => 'i:1;',
+    ))
+    ->values(array(
+      'name' => 'comment_controls_page',
+      'value' => 's:1:"3";',
+    ))
+    ->values(array(
+      'name' => 'comment_controls_story',
+      'value' => 's:1:"3";',
+    ))
+    ->values(array(
+      'name' => 'comment_default_mode_page',
+      'value' => 's:1:"4";',
+    ))
+    ->values(array(
+      'name' => 'comment_default_mode_story',
+      'value' => 's:1:"2";',
+    ))
+    ->values(array(
+      'name' => 'comment_default_order_page',
+      'value' => 's:1:"1";',
+    ))
+    ->values(array(
+      'name' => 'comment_default_order_story',
+      'value' => 's:1:"1";',
+    ))
+    ->values(array(
+      'name' => 'comment_default_per_page_page',
+      'value' => 's:2:"50";',
+    ))
+    ->values(array(
+      'name' => 'comment_default_per_page_story',
+      'value' => 's:2:"70";',
+    ))
+    ->values(array(
+      'name' => 'comment_form_location_page',
+      'value' => 's:1:"0";',
+    ))
+    ->values(array(
+      'name' => 'comment_form_location_story',
+      'value' => 's:1:"0";',
+    ))
+    ->values(array(
+      'name' => 'comment_page',
+      'value' => 's:1:"0";',
+    ))
+    ->values(array(
+      'name' => 'comment_preview_page',
+      'value' => 's:1:"1";',
+    ))
+    ->values(array(
+      'name' => 'comment_preview_story',
+      'value' => 's:1:"0";',
+    ))
+    ->values(array(
+      'name' => 'comment_story',
+      'value' => 's:1:"2";',
+    ))
+    ->values(array(
+      'name' => 'comment_subject_field_page',
+      'value' => 's:1:"1";',
+    ))
+    ->values(array(
+      'name' => 'comment_subject_field_story',
+      'value' => 's:1:"0";',
+    ))
+    ->execute();
+    $this->setModuleVersion('comment', '6001');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactCategory.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactCategory.php
new file mode 100644
index 0000000..541b6d2
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactCategory.php
@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6ContactCategories.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing contact category migration.
+ */
+class Drupal6ContactCategory extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('contact', array(
+      'description' => 'Contact form category settings.',
+      'fields' => array(
+        'cid' => array(
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'description' => 'Primary Key: Unique category ID.',
+        ),
+        'category' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Category name.',
+          'translatable' => TRUE,
+        ),
+        'recipients' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+          'description' => 'Comma-separated list of recipient e-mail addresses.',
+        ),
+        'reply' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+          'description' => 'Text of the auto-reply message.',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => "The category's weight.",
+        ),
+        'selected' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Flag to indicate whether or not category is selected by default. (1 = Yes, 0 = No)',
+        ),
+      ),
+      'primary key' => array('cid'),
+      'unique keys' => array(
+        'category' => array('category'),
+      ),
+      'indexes' => array(
+        'list' => array('weight', 'category'),
+      ),
+    ));
+    $this->database->insert('contact')->fields(array('cid', 'category', 'recipients', 'reply', 'weight', 'selected'))
+      ->values(array(
+        'cid' => '1',
+        'category' => 'Website feedback',
+        'recipients' => 'admin@example.com',
+        'reply' => '',
+        'weight' => '0',
+        'selected' => '1',
+      ))
+      ->execute();
+    $this->setModuleVersion('contact', '6001');
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactSettings.php
index 4c16b44..56fddf5 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing contact.settings.yml migration.
  */
-class Drupal6ContactSettings {
+class Drupal6ContactSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DateFormat.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DateFormat.php
new file mode 100644
index 0000000..c126fee
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DateFormat.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing date formats migration.
+ */
+class Drupal6DateFormat extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+      ->values(array(
+        'name' => 'date_format_long',
+        'value' => 's:24:"\\L\\O\\N\\G l, F j, Y - H:i";',
+      ))
+      ->values(array(
+        'name' => 'date_format_medium',
+        'value' => 's:27:"\\M\\E\\D\\I\\U\\M D, m/d/Y - H:i";',
+      ))
+      ->values(array(
+        'name' => 'date_format_short',
+        'value' => 's:22:"\\S\\H\\O\\R\\T m/d/Y - H:i";',
+      ))
+      ->execute();
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DblogSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DblogSettings.php
index 676dab9..2b04e9b 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DblogSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DblogSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing dblog.settings.yml migration.
  */
-class Drupal6DblogSettings {
+class Drupal6DblogSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DumpBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DumpBase.php
new file mode 100644
index 0000000..c340f4c
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DumpBase.php
@@ -0,0 +1,251 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6DumpBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+use Drupal\Core\Database\Connection;
+
+/**
+ * Base class for the dump classes.
+ */
+class Drupal6DumpBase {
+
+  /**
+   * The database connection.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $database;
+
+  /**
+   * Sample database schema and values.
+   *
+   * @param \Drupal\Core\Database\Connection $database
+   *   The database connection.
+   */
+  public function __construct(Connection $database) {
+    $this->database = $database;
+  }
+
+  /**
+   * Create a new table from a Drupal table definition if it doesn't exist.
+   *
+   * @param $name
+   *   The name of the table to create.
+   * @param $table
+   *   A Schema API table definition array.
+   */
+  protected function createTable($name, $table = NULL) {
+    // This must be on the database connection to be shared among classes.
+    if (empty($this->database->migrateTables[$name])) {
+      $this->database->migrateTables[$name] = TRUE;
+      $this->database->schema()->createTable($name, $table ?: $this->tableDefinitions()[$name]);
+    }
+  }
+
+  /**
+   * Table definitions.
+   */
+  protected function tableDefinitions() {
+    return array(
+      'node_type' => array(
+        'description' => 'Stores information about all defined {node} types.',
+        'fields' => array(
+          'type' => array(
+            'description' => 'The machine-readable name of this type.',
+            'type' => 'varchar',
+            'length' => 32,
+            'not null' => TRUE),
+          'name' => array(
+            'description' => 'The human-readable name of this type.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => ''),
+          'module' => array(
+            'description' => 'The base string used to construct callbacks corresponding to this node type.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE),
+          'description'    => array(
+            'description' => 'A brief description of this type.',
+            'type' => 'text',
+            'not null' => TRUE,
+            'size' => 'medium'),
+          'help' => array(
+            'description' => 'Help information shown to the user when creating a {node} of this type.',
+            'type' => 'text',
+            'not null' => TRUE,
+            'size' => 'medium'),
+          'has_title' => array(
+            'description' => 'Boolean indicating whether this type uses the {node}.title field.',
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'size' => 'tiny'),
+          'title_label' => array(
+            'description' => 'The label displayed for the title field on the edit form.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => ''),
+          'has_body' => array(
+            'description' => 'Boolean indicating whether this type uses the {node_revisions}.body field.',
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'size' => 'tiny'),
+          'body_label' => array(
+            'description' => 'The label displayed for the body field on the edit form.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => ''),
+          'min_word_count' => array(
+            'description' => 'The minimum number of words the body must contain.',
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'size' => 'small'),
+          'custom' => array(
+            'description' => 'A boolean indicating whether this type is defined by a module (FALSE) or by a user via a module like the Content Construction Kit (TRUE).',
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'size' => 'tiny'),
+          'modified' => array(
+            'description' => 'A boolean indicating whether this type has been modified by an administrator; currently not used in any way.',
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'size' => 'tiny'),
+          'locked' => array(
+            'description' => 'A boolean indicating whether the administrator can change the machine name of this type.',
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'size' => 'tiny'),
+          'orig_type' => array(
+            'description' => 'The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => '',
+          ),
+        ),
+        'primary key' => array('type'),
+      ),
+      'variable' => array(
+        'fields' => array(
+          'name' => array(
+            'type' => 'varchar',
+            'length' => 128,
+            'not null' => TRUE,
+            'default' => '',
+          ),
+          'value' => array(
+            'type' => 'blob',
+            'not null' => TRUE,
+            'size' => 'big',
+            'translatable' => TRUE,
+          ),
+        ),
+        'primary key' => array(
+          'name',
+        ),
+        'module' => 'book',
+        'name' => 'variable',
+      ),
+      'system' => array(
+        'description' => "A list of all modules, themes, and theme engines that are or have been installed in Drupal's file system.",
+        'fields' => array(
+          'filename' => array(
+            'description' => 'The path of the primary file for this item, relative to the Drupal root; e.g. modules/node/node.module.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => ''),
+          'name' => array(
+            'description' => 'The name of the item; e.g. node.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => ''),
+          'type' => array(
+            'description' => 'The type of the item, either module, theme, or theme_engine.',
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => ''),
+          'owner' => array(
+            'description' => "A theme's 'parent'. Can be either a theme or an engine.",
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => ''),
+          'status' => array(
+            'description' => 'Boolean indicating whether or not this item is enabled.',
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0),
+          'throttle' => array(
+            'description' => 'Boolean indicating whether this item is disabled when the throttle.module disables throttleable items.',
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'size' => 'tiny'),
+          'bootstrap' => array(
+            'description' => "Boolean indicating whether this module is loaded during Drupal's early bootstrapping phase (e.g. even before the page cache is consulted).",
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0),
+          'schema_version' => array(
+            'description' => "The module's database schema version number. -1 if the module is not installed (its tables do not exist); 0 or the largest N of the module's hook_update_N() function that has either been run
+   or existed when the module was first installed.",
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => -1,
+            'size' => 'small'),
+          'weight' => array(
+            'description' => "The order in which this module's hooks should be invoked relative to other modules. Equal-weighted modules are ordered by name.",
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0),
+          'info' => array(
+            'description' => "A serialized array containing information from the module's .info file; keys can include name, description, package, version, core, dependencies, dependents, and php.",
+            'type' => 'text',
+            'not null' => FALSE,
+          )),
+        'primary key' => array('filename'),
+        'indexes' => array(
+          'modules' => array(array('type', 12), 'status', 'weight', 'filename'),
+          'bootstrap' => array(array('type', 12), 'status', 'bootstrap', 'weight', 'filename'),
+          'type_name' => array(array('type', 12), 'name'),
+        ),
+      ),
+    );
+  }
+
+  /**
+   * Sets a module version and status.
+   *
+   * @param $module
+   * @param $version
+   * @param int $status
+   */
+  public function setModuleVersion($module, $version, $status = 1) {
+    $this->createTable('system');
+    $this->database->merge('system')
+      ->key(array('filename' => "modules/$module"))
+      ->fields(array(
+        'type' => 'module',
+        'name' => $module,
+        'schema_version' => $version,
+        'status' => $status,
+      ))
+      ->execute();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DumpCommon.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DumpCommon.php
deleted file mode 100644
index f56f3d0..0000000
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DumpCommon.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6DumpBase.
- */
-
-namespace Drupal\migrate_drupal\Tests\Dump;
-
-use Drupal\Core\Database\Connection;
-
-class Drupal6DumpCommon {
-
-  public static function createVariable(Connection $database) {
-    $database->schema()->createTable('variable', array(
-      'fields' => array(
-        'name' => array(
-          'type' => 'varchar',
-          'length' => 128,
-          'not null' => TRUE,
-          'default' => '',
-        ),
-        'value' => array(
-          'type' => 'blob',
-          'not null' => TRUE,
-          'size' => 'big',
-          'translatable' => TRUE,
-        ),
-      ),
-      'primary key' => array(
-        'name',
-      ),
-      'module' => 'book',
-      'name' => 'variable',
-    ));
-  }
-
-}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php
new file mode 100644
index 0000000..77500e2
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php
@@ -0,0 +1,853 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\Dump\Drupal6FieldInstance.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing entity display migration.
+ */
+class Drupal6FieldInstance extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('content_node_field_instance', array(
+      'description' => 'Table that contains field instance settings.',
+      'fields' => array(
+        'field_name' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'type_name' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'label' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'widget_type' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'widget_settings' => array(
+          'type' => 'text',
+          'size' => 'medium',
+          'not null' => TRUE,
+          'serialize' => TRUE,
+        ),
+        'display_settings' => array(
+          'type' => 'text',
+          'size' => 'medium',
+          'not null' => TRUE,
+          'serialize' => TRUE,
+        ),
+        'description' => array(
+          'type' => 'text',
+          'size' => 'medium',
+          'not null' => TRUE,
+        ),
+        'widget_module' => array(
+          'type' => 'varchar',
+          'length' => 127,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'widget_active' => array(
+          'type' => 'int',
+          'size' => 'tiny',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'primary key' => array('field_name', 'type_name'),
+    ));
+
+    $this->database->insert('content_node_field_instance')->fields(array(
+      'field_name',
+      'type_name',
+      'weight',
+      'label',
+      'widget_type',
+      'widget_settings',
+      'display_settings',
+      'description',
+    ))
+    ->values(array(
+      'field_name' => 'field_test',
+      'type_name' => 'story',
+      'weight' => 1,
+      'label' => 'Text Field',
+      'widget_type' => 'text_textfield',
+      'widget_settings' => serialize(array(
+        'rows' => 5,
+        'size' => '60',
+        'default_value' => array(
+          0 => array(
+            'value' => 'text for default value',
+            '_error_element' => 'default_value_widget][field_test][0][value',
+          ),
+        ),
+        'default_value_php' => NULL,
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 1,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        1 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        'teaser' => array(
+          'format' => 'trimmed',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'trimmed',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example text field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test',
+      'type_name' => 'article',
+      'weight' => 1,
+      'label' => 'Text Field',
+      'widget_type' => 'text_textfield',
+      'widget_settings' => serialize(array(
+        'rows' => 5,
+        'size' => '60',
+        'default_value' => array(
+          0 => array(
+            'value' => 'text for default value',
+            '_error_element' => 'default_value_widget][field_test][0][value',
+          ),
+        ),
+        'default_value_php' => NULL,
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 1,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'trimmed',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'trimmed',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example textfield.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_two',
+      'type_name' => 'story',
+      'weight' => 2,
+      'label' => 'Integer Field',
+      'widget_type' => 'number',
+      'widget_settings' => 'a:2:{s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:0:"";s:14:"_error_element";s:41:"default_value_widget][field_int][0][value";}}s:17:"default_value_php";N;}',
+      'display_settings' => serialize(array(
+        'weight' => 2,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'unformatted',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'us_0',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'unformatted',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example integer field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_three',
+      'type_name' => 'story',
+      'weight' => 3,
+      'label' => 'Float Field',
+      'widget_type' => 'number',
+      'widget_settings' => serialize(array(
+        'default_value' => array(
+          0 => array(
+            'value' => '101',
+            '_error_element' => 'default_value_widget][field_float][0][value',
+          ),
+        ),
+        'default_value_php' => NULL,
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 3,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'unformatted',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'us_2',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'unformatted',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example float field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_email',
+      'type_name' => 'story',
+      'weight' => 4,
+      'label' => 'Email Field',
+      'widget_type' => 'email_textfield',
+      'widget_settings' => serialize(array(
+        'size' => '60',
+        'default_value' => array(
+          0 => array(
+            'email' => 'benjy@example.com',
+          ),
+        ),
+        'default_value_php' => NULL,
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 4,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example email field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_link',
+      'type_name' => 'story',
+      'weight' => 5,
+      'label' => 'Link Field',
+      'widget_type' => 'link',
+      'widget_settings' => serialize(array(
+        'default_value' => array(
+          0 => array(
+            'title' => 'default link title',
+            'url' => 'http://drupal.org',
+          ),
+        ),
+        'default_value_php' => NULL,
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 5,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'absolute',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example link field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_filefield',
+      'type_name' => 'story',
+      'weight' => 7,
+      'label' => 'File Field',
+      'widget_type' => 'filefield_widget',
+      'widget_settings' => serialize(array(
+        'file_extensions' => 'txt pdf doc',
+        'file_path' => 'images',
+        'progress_indicator' => 'bar',
+        'max_filesize_per_file' => '200K',
+        'max_filesize_per_node' => '20M',
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 7,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'url_plain',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example image field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_imagefield',
+      'type_name' => 'story',
+      'weight' => 8,
+      'label' => 'Image Field',
+      'widget_type' => 'imagefield_widget',
+      'widget_settings' => serialize(array(
+        'file_extensions' => 'png gif jpg jpeg',
+        'file_path' => '',
+        'progress_indicator' => 'bar',
+        'max_filesize_per_file' => '',
+        'max_filesize_per_node' => '',
+        'max_resolution' => '0',
+        'min_resolution' => '0',
+        'alt' => 'Test alt',
+        'custom_alt' => 0,
+        'title' => 'Test title',
+        'custom_title' => 0,
+        'title_type' => 'textfield',
+        'default_image' => NULL,
+        'use_default_image' => 0,
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 8,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'image_imagelink',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'image_plain',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example image field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_phone',
+      'type_name' => 'story',
+      'weight' => 9,
+      'label' => 'Phone Field',
+      'widget_type' => 'phone_textfield',
+      'widget_settings' => serialize(array(
+        'size' => '60',
+        'default_value' => array(
+          0 => array(
+            'value' => '',
+            '_error_element' => 'default_value_widget][field_phone][0][value',
+          ),
+        ),
+        'default_value_php' => NULL,
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 9,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example phone field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_date',
+      'type_name' => 'story',
+      'weight' => 10,
+      'label' => 'Date Field',
+      'widget_type' => 'date_select',
+      'widget_settings' => serialize(array(
+        'default_value' => 'blank',
+        'default_value_code' => '',
+        'default_value2' => 'same',
+        'default_value_code2' => '',
+        'input_format' => 'm/d/Y - H:i:s',
+        'input_format_custom' => '',
+        'increment' => '1',
+        'text_parts' => array(),
+        'year_range' => '-3:+3',
+        'label_position' => 'above',
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 10,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'long',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example date field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_datestamp',
+      'type_name' => 'story',
+      'weight' => 11,
+      'label' => 'Date Stamp Field',
+      'widget_type' => 'date_select',
+      'widget_settings' => serialize(array(
+        'default_value' => 'blank',
+        'default_value_code' => '',
+        'default_value2' => 'same',
+        'default_value_code2' => '',
+        'input_format' => 'm/d/Y - H:i:s',
+        'input_format_custom' => '',
+        'increment' => '1',
+        'text_parts' => array(),
+        'year_range' => '-3:+3',
+        'label_position' => 'above',
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 11,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'medium',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example date stamp field.',
+    ))
+    ->values(array(
+      'field_name' => 'field_test_datetime',
+      'type_name' => 'story',
+      'weight' => 12,
+      'label' => 'Datetime Field',
+      'widget_type' => 'date_select',
+      'widget_settings' => serialize(array(
+        'default_value' => 'blank',
+        'default_value_code' => '',
+        'default_value2' => 'same',
+        'default_value_code2' => '',
+        'input_format' => 'm/d/Y - H:i:s',
+        'input_format_custom' => '',
+        'increment' => '1',
+        'text_parts' => array(),
+        'year_range' => '-3:+3',
+        'label_position' => 'above',
+      )),
+      'display_settings' => serialize(array(
+        'weight' => 12,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'short',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        5 => array(
+          'format' => 'default',
+          'exclude' => 1,
+        ),
+      )),
+      'description' => 'An example datetime field.',
+    ))
+    ->execute();
+
+    // Create the field table.
+    $this->createTable('content_node_field', array(
+      'description' => 'Table that contains field instance settings.',
+      'fields' => array(
+        'field_name' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'type' => array(
+          'type' => 'varchar',
+          'length' => 127,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'global_settings' => array(
+          'type' => 'text',
+          'size' => 'medium',
+          'not null' => TRUE,
+          'serialize' => TRUE,
+        ),
+        'required' => array(
+          'type' => 'int',
+          'size' => 'tiny',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'multiple' => array(
+          'type' => 'int',
+          'size' => 'tiny',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'db_storage' => array(
+          'type' => 'int',
+          'size' => 'tiny',
+          'not null' => TRUE,
+          'default' => 1,
+        ),
+        'module' => array(
+          'type' => 'varchar',
+          'length' => 127,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'db_columns' => array(
+          'type' => 'text',
+          'size' => 'medium',
+          'not null' => TRUE,
+          'serialize' => TRUE,
+        ),
+        'active' => array(
+          'type' => 'int',
+          'size' => 'tiny',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'locked' => array(
+          'type' => 'int',
+          'size' => 'tiny',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'primary key' => array('field_name'),
+    ));
+
+    $this->database->insert('content_node_field')->fields(array(
+      'field_name',
+      'module',
+      'type',
+      'global_settings',
+      'multiple',
+      'db_storage',
+      'db_columns',
+      'active',
+    ))
+    ->values(array(
+      'field_name' => 'field_test',
+      'module' => 'text',
+      'type' => 'text',
+      'global_settings' => 'a:4:{s:15:"text_processing";s:1:"1";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => serialize(array(
+        'value' => array(
+          'type' => 'text',
+          'size' => 'big',
+          'not null' => FALSE,
+          'sortable' => TRUE,
+          'views' => TRUE,
+        ),
+      )),
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_two',
+      'module' => 'number',
+      'type' => 'number_integer',
+      'global_settings' => 'a:6:{s:6:"prefix";s:4:"pref";s:6:"suffix";s:3:"suf";s:3:"min";i:10;s:3:"max";i:100;s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+      'multiple' => 1,
+      'db_storage' => 0,
+      'db_columns' => 'a:2:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}s:6:"format";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:0;s:5:"views";b:0;}}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_three',
+      'module' => 'number',
+      'type' => 'number_decimal',
+      'global_settings' => '',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_email',
+      'module' => 'email',
+      'type' => 'email',
+      'global_settings' => 'a:0:{}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_link',
+      'module' => 'link',
+      'type' => 'link',
+      'global_settings' => 'a:7:{s:10:"attributes";a:4:{s:6:"target";s:7:"default";s:3:"rel";s:8:"nofollow";s:5:"class";s:0:"";s:5:"title";s:10:"Link Title";}s:7:"display";a:1:{s:10:"url_cutoff";s:2:"80";}s:3:"url";i:0;s:5:"title";s:8:"required";s:11:"title_value";s:0:"";s:13:"enable_tokens";s:0:"";s:12:"validate_url";i:1;}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_filefield',
+      'module' => 'filefield',
+      'type' => 'filefield',
+      'global_settings' => 'a:3:{s:10:"list_field";s:1:"0";s:12:"list_default";i:1;s:17:"description_field";s:1:"1";}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_imagefield',
+      'module' => 'filefield',
+      'type' => 'filefield',
+      'global_settings' => 'a:3:{s:10:"list_field";s:1:"0";s:12:"list_default";i:1;s:17:"description_field";s:1:"0";}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_phone',
+      'module' => 'phone',
+      'type' => 'au_phone',
+      'global_settings' => 'a:1:{s:5:"value";a:3:{s:4:"type";s:7:"varchar";s:6:"length";i:255;s:8:"not null";b:0;}}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_date',
+      'module' => 'date',
+      'type' => 'date',
+      'global_settings' => 'a:0:{}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_datestamp',
+      'module' => 'date',
+      'type' => 'datestamp',
+      'global_settings' => 'a:0:{}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 1,
+    ))
+    ->values(array(
+      'field_name' => 'field_test_datetime',
+      'module' => 'date',
+      'type' => 'datetime',
+      'global_settings' => 'a:0:{}',
+      'multiple' => 0,
+      'db_storage' => 1,
+      'db_columns' => 'a:0:{}',
+      'active' => 0,
+    ))
+    ->execute();
+
+    $this->createTable('content_field_test_two', array(
+      'description' => 'Table for field_test_two',
+      'fields' => array(
+        'vid' => array(
+          'description' => 'The primary identifier for this version.',
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'nid' => array(
+          'description' => 'The {node} this version belongs to.',
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'field_test_two_value' => array(
+          'description' => 'Test field column.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'delta' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'field_test_two_format' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'primary key' => array('vid', 'delta'),
+    ));
+    $this->database->insert('content_field_test_two')->fields(array(
+      'vid',
+      'nid',
+      'field_test_two_value',
+      'delta',
+      'field_test_two_format',
+    ))
+    ->values(array(
+      'vid' => 1,
+      'nid' => 1,
+      'field_test_two_value' => 10,
+      'delta' => 0,
+      'field_test_two_format' => 1,
+    ))
+    ->values(array(
+      'vid' => 1,
+      'nid' => 1,
+      'field_test_two_value' => 20,
+      'delta' => 1,
+      'field_test_two_format' => 1,
+    ))
+    ->execute();
+    $this->setModuleVersion('content', '6001');
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldSettings.php
index 4425d5c..44e899f 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldSettings.php
@@ -7,28 +7,23 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing field.settings.yml migration.
  */
-class Drupal6FieldSettings {
+class Drupal6FieldSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
     ->values(array(
       'name' => 'field_language_fallback',
-        'value' => 'b:1;',
+      'value' => 'b:1;',
     ))
     ->execute();
   }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6File.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6File.php
new file mode 100644
index 0000000..23f0dc6
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6File.php
@@ -0,0 +1,129 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6File.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing file migrations.
+ */
+class Drupal6File extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+
+    $this->createTable('files', array(
+      'fields' => array(
+        'fid' => array(
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'uid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'filename' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'filepath' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'filemime' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'filesize' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'status' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'timestamp' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'indexes' => array(
+        'uid' => array(
+          'uid',
+        ),
+        'status' => array(
+          'status',
+        ),
+        'timestamp' => array(
+          'timestamp',
+        ),
+      ),
+      'primary key' => array(
+        'fid',
+      ),
+      'module' => 'system',
+      'name' => 'files',
+    ));
+    $this->database->insert('files')->fields(array(
+      'fid',
+      'uid',
+      'filename',
+      'filepath',
+      'filemime',
+      'filesize',
+      'status',
+      'timestamp',
+    ))
+    ->values(array(
+      'fid' => '1',
+      'uid' => '1',
+      'filename' => 'Image1.png',
+      'filepath' => 'core/modules/simpletest/files/image-1.png',
+      'filemime' => 'image/png',
+      'filesize' => '39325',
+      'status' => '1',
+      'timestamp' => '1388880660',
+    ))
+    ->values(array(
+      'fid' => '2',
+      'uid' => '1',
+      'filename' => 'Image2.jpg',
+      'filepath' => 'core/modules/simpletest/files/image-2.jpg',
+      'filemime' => 'image/jpeg',
+      'filesize' => '1831',
+      'status' => '1',
+      'timestamp' => '1388880664',
+    ))
+    ->values(array(
+      'fid' => '3',
+      'uid' => '1',
+      'filename' => 'Image-test.gif',
+      'filepath' => 'core/modules/simpletest/files/image-test.gif',
+      'filemime' => 'image/jpeg',
+      'filesize' => '183',
+      'status' => '1',
+      'timestamp' => '1388880668',
+    ))
+    ->execute();
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FileSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FileSettings.php
index 61a1209..b00c541 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FileSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FileSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing file.settings.yml migration.
  */
-class Drupal6FileSettings {
+class Drupal6FileSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FilterFormat.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FilterFormat.php
new file mode 100644
index 0000000..002e6b8
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FilterFormat.php
@@ -0,0 +1,204 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\Dump\Drupal6FilterFormats.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing filter format migration.
+ */
+class Drupal6FilterFormat extends Drupal6DumpBase {
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('filters', array(
+      'description' => 'Table that maps filters (HTML corrector) to input formats (Filtered HTML).',
+      'fields' => array(
+        'fid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+          'description' => 'Primary Key: Auto-incrementing filter ID.',
+        ),
+        'format' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'Foreign key: The {filter_formats}.format to which this filter is assigned.',
+        ),
+        'module' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'The origin module of the filter.',
+        ),
+        'delta' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'ID to identify which filter within module is being referenced.',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Weight of filter within format.',
+        ),
+      ),
+      'primary key' => array('fid'),
+      'unique keys' => array(
+        'fmd' => array('format', 'module', 'delta'),
+      ),
+      'indexes' => array(
+        'list' => array('format', 'weight', 'module', 'delta'),
+      ),
+    ));
+    $this->createTable('filter_formats', array(
+      'description' => 'Stores input formats: custom groupings of filters, such as Filtered HTML.',
+      'fields' => array(
+        'format' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+          'description' => 'Primary Key: Unique ID for format.',
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Name of the input format (Filtered HTML).',
+        ),
+        'roles' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          // This is bad since you can't use joins, nor index.
+          'description' => 'A comma-separated string of roles; references {role}.rid.',
+        ),
+        'cache' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Flag to indicate whether format is cachable. (1 = cachable, 0 = not cachable)',
+        ),
+      ),
+      'primary key' => array('format'),
+      'unique keys' => array('name' => array('name')),
+    ));
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'allowed_html_1',
+      'value' => 's:61:"<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>";',
+    ))
+    ->values(array(
+      'name' => 'filter_html_help_1',
+      'value' => 'i:1;',
+    ))
+    ->values(array(
+      'name' => 'filter_html_nofollow_1',
+      'value' => 'i:0;',
+    ))
+    ->values(array(
+      'name' => 'filter_url_length_1',
+      'value' => 's:2:"72";',
+    ))
+    ->execute();
+    $this->database->insert('filter_formats')->fields(array(
+      'format',
+      'name',
+      'roles',
+      'cache',
+    ))
+    ->values(array(
+      'format' => '1',
+      'name' => 'Filtered HTML',
+      'roles' => ',1,2,',
+      'cache' => '1',
+    ))
+    ->values(array(
+      'format' => '2',
+      'name' => 'Full HTML',
+      'roles' => '3',
+      'cache' => '1',
+    ))
+    ->values(array(
+      'format' => '3',
+      'name' => 'Escape HTML Filter',
+      'roles' => '',
+      'cache' => '1',
+    ))
+    ->execute();
+
+    $this->database->insert('filters')->fields(array(
+      'fid',
+      'format',
+      'module',
+      'delta',
+      'weight',
+    ))
+    ->values(array(
+      'fid' => '1',
+      'format' => '1',
+      'module' => 'filter',
+      'delta' => '2',
+      'weight' => '0',
+    ))
+    ->values(array(
+      'fid' => '2',
+      'format' => '1',
+      'module' => 'filter',
+      'delta' => '0',
+      'weight' => '1',
+    ))
+    ->values(array(
+      'fid' => '3',
+      'format' => '1',
+      'module' => 'filter',
+      'delta' => '1',
+      'weight' => '2',
+    ))
+    ->values(array(
+      'fid' => '4',
+      'format' => '1',
+      'module' => 'filter',
+      'delta' => '3',
+      'weight' => '10',
+    ))
+    ->values(array(
+      'fid' => '5',
+      'format' => '2',
+      'module' => 'filter',
+      'delta' => '2',
+      'weight' => '0',
+    ))
+    ->values(array(
+      'fid' => '6',
+      'format' => '2',
+      'module' => 'filter',
+      'delta' => '1',
+      'weight' => '1',
+    ))
+    ->values(array(
+      'fid' => '7',
+      'format' => '2',
+      'module' => 'filter',
+      'delta' => '3',
+      'weight' => '10',
+    ))
+    ->execute();
+
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ForumSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ForumSettings.php
index d75700e..8ae739e 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ForumSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ForumSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing forum.site.yml migration.
  */
-class Drupal6ForumSettings {
+class Drupal6ForumSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6LocaleSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6LocaleSettings.php
index c32dedb..7dc6e5c 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6LocaleSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6LocaleSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing locale.settings.yml migration.
  */
-class Drupal6LocaleSettings {
+class Drupal6LocaleSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Menu.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Menu.php
new file mode 100644
index 0000000..01ef84d
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Menu.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Menu.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing menu migration.
+ */
+class Drupal6Menu extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('menu_custom', array(
+      'fields' => array(
+        'menu_name' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'title' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'description' => array(
+          'type' => 'text',
+          'not null' => FALSE,
+        ),
+      ),
+      'primary key' => array(
+        'menu_name',
+      ),
+      'module' => 'menu',
+      'name' => 'menu_custom',
+    ));
+    $this->database->insert('menu_custom')->fields(array('menu_name', 'title', 'description'))
+      ->values(array(
+        'menu_name' => 'navigation',
+        'title' => 'Navigation',
+        'description' => 'The navigation menu is provided by Drupal and is the main interactive menu for any site. It is usually the only menu that contains personalized links for authenticated users, and is often not even visible to anonymous users.',
+      ))
+      ->values(array(
+        'menu_name' => 'primary-links',
+        'title' => 'Primary links',
+        'description' => 'Primary links are often used at the theme layer to show the major sections of a site. A typical representation for primary links would be tabs along the top.',
+      ))
+      ->values(array(
+        'menu_name' => 'secondary-links',
+        'title' => 'Secondary links',
+        'description' => 'Secondary links are often used for pages like legal notices, contact details, and other secondary navigation items that play a lesser role than primary links',
+      ))
+      ->execute();
+    $this->setModuleVersion('menu', '6001');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6MenuSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6MenuSettings.php
index dc6fe2d..298b499 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6MenuSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6MenuSettings.php
@@ -7,21 +7,18 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing menu.settings.yml migration.
  */
-class Drupal6MenuSettings {
+class Drupal6MenuSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->setModuleVersion('menu', 6000);
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php
new file mode 100644
index 0000000..cd31852
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php
@@ -0,0 +1,331 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Node.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing the node migration.
+ */
+class Drupal6Node extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('node', array(
+      'description' => 'The base table for nodes.',
+      'fields' => array(
+        'nid' => array(
+          'description' => 'The primary identifier for a node.',
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'vid' => array(
+          'description' => 'The current {node_revisions}.vid version identifier.',
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'type' => array(
+          'description' => 'The {node_type}.type of this node.',
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'language' => array(
+          'description' => 'The {languages}.language of this node.',
+          'type' => 'varchar',
+          'length' => 12,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'title' => array(
+          'description' => 'The title of this node, always treated as non-markup plain text.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'uid' => array(
+          'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'status' => array(
+          'description' => 'Boolean indicating whether the node is published (visible to non-administrators).',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 1,
+        ),
+        'created' => array(
+          'description' => 'The Unix timestamp when the node was created.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'changed' => array(
+          'description' => 'The Unix timestamp when the node was most recently saved.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'comment' => array(
+          'description' => 'Whether comments are allowed on this node: 0 = no, 1 = read only, 2 = read/write.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'promote' => array(
+          'description' => 'Boolean indicating whether the node should be displayed on the front page.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'moderate' => array(
+          'description' => 'Previously, a boolean indicating whether the node was "in moderation"; mostly no longer used.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'sticky' => array(
+          'description' => 'Boolean indicating whether the node should be displayed at the top of lists in which it appears.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'tnid' => array(
+          'description' => 'The translation set id for this node, which equals the node id of the source post in each set.',
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'translate' => array(
+          'description' => 'A boolean indicating whether this translation page needs to be updated.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'indexes' => array(
+        'node_changed' => array('changed'),
+        'node_created' => array('created'),
+        'node_moderate' => array('moderate'),
+        'node_promote_status' => array('promote', 'status'),
+        'node_status_type' => array('status', 'type', 'nid'),
+        'node_title_type' => array('title', array('type', 4)),
+        'node_type' => array(array('type', 4)),
+        'uid' => array('uid'),
+        'tnid' => array('tnid'),
+        'translate' => array('translate'),
+      ),
+      'unique keys' => array(
+        'vid' => array('vid'),
+      ),
+      'primary key' => array('nid'),
+    ));
+    $this->database->insert('node')->fields(array(
+        'nid',
+        'vid',
+        'type',
+        'language',
+        'title',
+        'uid',
+        'status',
+        'created',
+        'changed',
+        'comment',
+        'promote',
+        'moderate',
+        'sticky',
+        'tnid',
+        'translate',
+      ))
+      ->values(array(
+        'nid' => 1,
+        'vid' => 1,
+        'type' => 'story',
+        'language' => '',
+        'title' => 'Test title',
+        'uid' => 1,
+        'status' => 1,
+        'created' => 1388271197,
+        'changed' => 1390095701,
+        'comment' => 0,
+        'promote' => 0,
+        'moderate' => 0,
+        'sticky' => 0,
+        'tnid' => 0,
+        'translate' => 0,
+      ))
+      ->values(array(
+        'nid' => 2,
+        'vid' => 3,
+        'type' => 'story',
+        'language' => '',
+        'title' => 'Test title 2',
+        'uid' => 1,
+        'status' => 1,
+        'created' => 1388271197,
+        'changed' => 1390095701,
+        'comment' => 0,
+        'promote' => 0,
+        'moderate' => 0,
+        'sticky' => 0,
+        'tnid' => 0,
+        'translate' => 0,
+      ))
+      ->execute();
+    $this->createTable('node_revisions', array(
+      'description' => 'Stores information about each saved version of a {node}.',
+      'fields' => array(
+        'nid' => array(
+          'description' => 'The {node} this version belongs to.',
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'vid' => array(
+          'description' => 'The primary identifier for this version.',
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'uid' => array(
+          'description' => 'The {users}.uid that created this version.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'title' => array(
+          'description' => 'The title of this version.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'body' => array(
+          'description' => 'The body of this version.',
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+        ),
+        'teaser' => array(
+          'description' => 'The teaser of this version.',
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+        ),
+        'log' => array(
+          'description' => 'The log entry explaining the changes in this version.',
+          'type' => 'text',
+          'not null' => TRUE,
+          'size' => 'big',
+        ),
+        'timestamp' => array(
+          'description' => 'A Unix timestamp indicating when this version was created.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'format' => array(
+          'description' => "The input format used by this version's body.",
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'indexes' => array(
+        'nid' => array('nid'),
+        'uid' => array('uid'),
+      ),
+      'primary key' => array('vid'),
+    ));
+
+    $this->database->insert('node_revisions')->fields(
+      array(
+        'nid',
+        'vid',
+        'uid',
+        'title',
+        'body',
+        'teaser',
+        'log',
+        'timestamp',
+        'format',
+      ))
+      ->values(array(
+        'nid' => 1,
+        'vid' => 1,
+        'uid' => 1,
+        'title' => 'Test title',
+        'body' => 'test',
+        'teaser' => 'test',
+        'log' => '',
+        'timestamp' => 1390095701,
+        'format' => 1,
+      ))
+      ->values(array(
+        'nid' => 2,
+        'vid' => 3,
+        'uid' => 1,
+        'title' => 'Test title rev 3',
+        'body' => 'test rev 3',
+        'teaser' => 'test rev 3',
+        'log' => '',
+        'timestamp' => 1390095701,
+        'format' => 1,
+      ))
+      ->execute();
+
+    $this->createTable('content_type_story', array(
+      'description' => 'The content type join table.',
+      'fields' => array(
+        'nid' => array(
+          'description' => 'The {node} this version belongs to.',
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'vid' => array(
+          'description' => 'The primary identifier for this version.',
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'field_test_value' => array(
+          'description' => 'Test field column.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+      ),
+      'primary key' => array('vid'),
+    ));
+
+    $this->database->insert('content_type_story')->fields(
+      array(
+        'nid',
+        'vid',
+        'field_test_value',
+      ))
+      ->values(array(
+        'nid' => 1,
+        'vid' => 1,
+        'field_test_value' => 'This is a text field',
+      ))
+      ->execute();
+    $this->setModuleVersion('content', 6001);
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeBodyInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeBodyInstance.php
new file mode 100644
index 0000000..8ec82b5
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeBodyInstance.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6NodeBodyInstance.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing field.instance.node.*.body.yml migration.
+ */
+class Drupal6NodeBodyInstance extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('variable');
+    $this->createTable('node_type');
+    $this->database->insert('node_type')->fields(array(
+      'type',
+      'name',
+      'module',
+      'description',
+      'help',
+      'has_title',
+      'title_label',
+      'has_body',
+      'body_label',
+      'min_word_count',
+      'custom',
+      'modified',
+      'locked',
+      'orig_type'
+    ))
+    ->values(array(
+      'type' => 'company',
+      'name' => 'Company',
+      'module' => 'node',
+      'description' => 'Company node type',
+      'help' => '',
+      'has_title' => 1,
+      'title_label' => 'Name',
+      'has_body' => 1,
+      'body_label' => 'Description',
+      'min_word_count' => 20,
+      'custom' => 0,
+      'modified' => 0,
+      'locked' => 0,
+      'orig_type' => 'company',
+    ))
+    ->values(array(
+      'type' => 'employee',
+      'name' => 'Employee',
+      'module' => 'node',
+      'description' => 'Employee node type',
+      'help' => '',
+      'has_title' => 1,
+      'title_label' => 'Name',
+      'has_body' => 1,
+      'body_label' => 'Bio',
+      'min_word_count' => 20,
+      'custom' => 0,
+      'modified' => 0,
+      'locked' => 0,
+      'orig_type' => 'employee',
+    ))
+    ->values(array(
+      'type' => 'sponsor',
+      'name' => 'Sponsor',
+      'module' => 'node',
+      'description' => 'Sponsor node type',
+      'help' => '',
+      'has_title' => 1,
+      'title_label' => 'Name',
+      'has_body' => 0,
+      'body_label' => 'Body',
+      'min_word_count' => 0,
+      'custom' => 0,
+      'modified' => 0,
+      'locked' => 0,
+      'orig_type' => '',
+    ))
+    ->execute();
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'teaser_length',
+      'value' => 'i:456;',
+    ))
+    ->values(array(
+      'name' => 'node_preview',
+      'value' => 'i:0;',
+    ))
+    ->execute();
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeRevision.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeRevision.php
new file mode 100644
index 0000000..04a4ad5
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeRevision.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6NodeRevision.
+ */
+
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+class Drupal6NodeRevision extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->database->insert('node_revisions')->fields(
+      array(
+        'nid',
+        'vid',
+        'uid',
+        'title',
+        'body',
+        'teaser',
+        'log',
+        'timestamp',
+        'format',
+      ))
+      ->values(array(
+        'nid' => 1,
+        'vid' => 2,
+        'uid' => 1,
+        'title' => 'Test title rev 2',
+        'body' => 'test rev 2',
+        'teaser' => 'test rev 2',
+        'log' => '',
+        'timestamp' => 1390095701,
+        'format' => 1,
+      ))
+      ->execute();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeSettings.php
index d0af31a..4fb67b9 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing node.settings.yml migration.
  */
-class Drupal6NodeSettings {
+class Drupal6NodeSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeType.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeType.php
new file mode 100644
index 0000000..87db257
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeType.php
@@ -0,0 +1,136 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6NodeType.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing node type migration.
+ */
+class Drupal6NodeType extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('node_type');
+    $this->database->insert('node_type')->fields(
+      array(
+        'type',
+        'name',
+        'module',
+        'description',
+        'help',
+        'has_title',
+        'title_label',
+        'has_body',
+        'body_label',
+        'min_word_count',
+        'custom',
+        'modified',
+        'locked',
+        'orig_type',
+      ))
+      ->values(array(
+        'type' => 'test_page',
+        'name' => 'Migrate test page',
+        'module' => 'node',
+        'description' => "A <em>page</em>, similar in form to a <em>story</em>, is a simple method for creating and displaying information that rarely changes, such as an \"About us\" section of a website. By default, a <em>page</em> entry does not allow visitor comments and is not featured on the site's initial home page.",
+        'help' => '',
+        'has_title' => 1,
+        'title_label' => 'Title',
+        'has_body' => 1,
+        'body_label' => 'Body',
+        'min_word_count' => 0,
+        'custom' => 1,
+        'modified' => 1,
+        'locked' => 0,
+        'orig_type' => 'page',
+      ))
+      ->values(array(
+        'type' => 'test_story',
+        'name' => 'Migrate test story',
+        'module' => 'node',
+        'description' => "A <em>story</em>, similar in form to a <em>page</em>, is ideal for creating and displaying content that informs or engages website visitors. Press releases, site announcements, and informal blog-like entries may all be created with a <em>story</em> entry. By default, a <em>story</em> entry is automatically featured on the site's initial home page, and provides the ability to post comments.",
+        'help' => '',
+        'has_title' => 1,
+        'title_label' => 'Title',
+        'has_body' => 0,
+        'body_label' => 'Body',
+        'min_word_count' => 0,
+        'custom' => 1,
+        'modified' => 1,
+        'locked' => 0,
+        'orig_type' => 'story',
+      ))
+      ->execute();
+
+    $this->database->merge('node_type')
+      ->key(array('type' => 'story'))
+      ->fields(array(
+        'name' => 'Story',
+        'module' => 'node',
+        'description' => "A <em>story</em>, similar in form to a <em>page</em>, is ideal for creating and displaying content that informs or engages website visitors. Press releases, site announcements, and informal blog-like entries may all be created with a <em>story</em> entry. By default, a <em>story</em> entry is automatically featured on the site's initial home page, and provides the ability to post comments.",
+        'help' => '',
+        'has_title' => '1',
+        'title_label' => 'Title',
+        'has_body' => '1',
+        'body_label' => 'Body',
+        'min_word_count' => '0',
+        'custom' => '1',
+        'modified' => '1',
+        'locked' => '0',
+        'orig_type' => 'story',
+      ))
+      ->execute();
+
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'node_options_migrate_test_page',
+      'value' => serialize(array(
+        0 => 'status',
+        1 => 'promote',
+        2 => 'sticky',
+      )),
+    ))
+    ->values(array(
+      'name' => 'node_options_migrate_test_story',
+      'value' => serialize(array(
+        0 => 'status',
+        1 => 'promote',
+      )),
+    ))
+    ->values(array(
+      'name' => 'theme_settings',
+      'value' => serialize(array(
+        'toggle_logo' => 1,
+        'toggle_name' => 1,
+        'toggle_slogan' => 0,
+        'toggle_mission' => 1,
+        'toggle_node_user_picture' => 0,
+        'toggle_comment_user_picture' => 0,
+        'toggle_search' => 0,
+        'toggle_favicon' => 1,
+        'toggle_primary_links' => 1,
+        'toggle_secondary_links' => 1,
+        'toggle_node_info_test' => 1,
+        'toggle_node_info_something' => 1,
+        'default_logo' => 1,
+        'logo_path' => '',
+        'logo_upload' => '',
+        'default_favicon' => 1,
+        'favicon_path' => '',
+        'favicon_upload' => '',
+        'toggle_node_info_migrate_test_page' => 1,
+        'toggle_node_info_migrate_test_story' => 1,
+      )),
+    ))
+    ->execute();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchPage.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchPage.php
new file mode 100644
index 0000000..c0c7298
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchPage.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6SearchPage.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing search page migration.
+ */
+class Drupal6SearchPage extends Drupal6DumpBase {
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'node_rank_comments',
+      'value' => 's:1:"5";',
+    ))
+    ->values(array(
+      'name' => 'node_rank_promote',
+      'value' => 's:1:"0";',
+    ))
+    ->values(array(
+      'name' => 'node_rank_recent',
+      'value' => 's:1:"0";',
+    ))
+    ->values(array(
+      'name' => 'node_rank_relevance',
+      'value' => 's:1:"2";',
+    ))
+    ->values(array(
+      'name' => 'node_rank_sticky',
+      'value' => 's:1:"8";',
+    ))
+    ->values(array(
+      'name' => 'node_rank_views',
+      'value' => 's:1:"1";',
+    ))
+    ->execute();
+
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchSettings.php
index 0b9d5af..fffc6c7 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing forum.site.yml migration.
  */
-class Drupal6SearchSettings {
+class Drupal6SearchSettings extends Drupal6DumpBase {
 
   /**
-   * Mock the database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The mocked database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SimpletestSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SimpletestSettings.php
index 77f7c51..4469f8d 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SimpletestSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SimpletestSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing simpletest.settings.yml migration.
  */
-class Drupal6SimpletestSettings {
+class Drupal6SimpletestSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6StatisticsSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6StatisticsSettings.php
index 573a5b4..1bec9c6 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6StatisticsSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6StatisticsSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing statistics.settings.yml migration.
  */
-class Drupal6StatisticsSettings {
+class Drupal6StatisticsSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SyslogSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SyslogSettings.php
index ac0016b..4155820 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SyslogSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SyslogSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing syslog.settings.yml migration.
  */
-class Drupal6SyslogSettings {
+class Drupal6SyslogSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemCron.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemCron.php
index b08e904..44ee90b 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemCron.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemCron.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.cron.yml migration.
  */
-class Drupal6SystemCron {
+class Drupal6SystemCron extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php
index 14b8ee0..a3937a1 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php
@@ -7,28 +7,24 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.file.yml migration.
  */
-class Drupal6SystemFile {
+class Drupal6SystemFile extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
     ->values(array(
       'name' => 'file_directory_path',
-      'value' => 's:10:"files/test";',
+      // This sets up MigrateDrupal6Test to pass. Do not change.
+      'value' => 's:29:"core/modules/simpletest/files";',
     ))
     ->values(array(
       'name' => 'file_directory_temp',
@@ -37,4 +33,20 @@ public static function load(Connection $database) {
     ->execute();
   }
 
+  /**
+   * Dump for the standalone test in MigrateFileTest.
+   */
+  public function loadMigrateFileStandalone() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'file_directory_path',
+      'value' => 's:10:"files/test";',
+    ))
+    ->execute();
+  }
+
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFilter.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFilter.php
index 22f0813..fe34217 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFilter.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFilter.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.filter.yml migration.
  */
-class Drupal6SystemFilter {
+class Drupal6SystemFilter extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImage.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImage.php
index 90fd2f8..a5f0be9 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImage.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImage.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.image.yml migration.
  */
-class Drupal6SystemImage {
+class Drupal6SystemImage extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImageGd.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImageGd.php
index a5b0875..f5798f1 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImageGd.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImageGd.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.image.gd.yml migration.
  */
-class Drupal6SystemImageGd {
+class Drupal6SystemImageGd extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemMaintenance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemMaintenance.php
index 8521f39..e98b741 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemMaintenance.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemMaintenance.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.maintenance.yml migration.
  */
-class Drupal6SystemMaintenance {
+class Drupal6SystemMaintenance extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemPerformance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemPerformance.php
index 0fd8153..b8bbf63 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemPerformance.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemPerformance.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.performance.yml migration.
  */
-class Drupal6SystemPerformance {
+class Drupal6SystemPerformance extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemRss.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemRss.php
index 2090030..ecf7488 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemRss.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemRss.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.settings.yml migration.
  */
-class Drupal6SystemRss {
+class Drupal6SystemRss extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemSite.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemSite.php
index 2310fb5..e6ebe16 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemSite.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemSite.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.site.yml migration.
  */
-class Drupal6SystemSite {
+class Drupal6SystemSite extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
@@ -36,7 +31,7 @@ public static function load(Connection $database) {
     ))
     ->values(array(
       'name' => 'site_slogan',
-      'value' => 's:13:"Migrate rocks";',
+      'value' => serialize('Migrate rocks'),
     ))
     ->values(array(
       'name' => 'site_frontpage',
@@ -44,7 +39,7 @@ public static function load(Connection $database) {
     ))
     ->values(array(
       'name' => 'site_403',
-      'value' => 's:4:"user";',
+      'value' => serialize('user'),
     ))
     ->values(array(
       'name' => 'site_404',
@@ -52,7 +47,7 @@ public static function load(Connection $database) {
     ))
     ->values(array(
       'name' => 'admin_compact_mode',
-      'value' => 'b:0;',
+      'value' => serialize(FALSE),
     ))
     ->execute();
   }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemTheme.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemTheme.php
index 4b015b5..9b9ceb3 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemTheme.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemTheme.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing system.theme.yml migration.
  */
-class Drupal6SystemTheme {
+class Drupal6SystemTheme extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomySettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomySettings.php
index 9fc9d1a..25f45c0 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomySettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomySettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing taxonomy.settings.yml migration.
  */
-class Drupal6TaxonomySettings {
+class Drupal6TaxonomySettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyTerm.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyTerm.php
new file mode 100644
index 0000000..2f96140
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyTerm.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6TaxonomyTerm.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing taxonomy term migration.
+ */
+class Drupal6TaxonomyTerm extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->setModuleVersion('taxonomy', 6000);
+
+    $this->createTable('term_data', array(
+      'fields' => array(
+        'tid' => array(
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'vid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'description' => array(
+          'type' => 'text',
+          'not null' => FALSE,
+          'size' => 'big',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+      ),
+      'primary key' => array(
+        'tid',
+      ),
+      'indexes' => array(
+        'taxonomy_tree' => array(
+          'vid',
+          'weight',
+          'name',
+        ),
+        'vid_name' => array(
+          'vid',
+          'name',
+        ),
+      ),
+      'module' => 'taxonomy',
+      'name' => 'term_data',
+    ));
+
+    $this->createTable('term_hierarchy', array(
+      'fields' => array(
+        'tid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'parent' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'indexes' => array(
+        'parent' => array(
+          'parent',
+        ),
+      ),
+      'primary key' => array(
+        'tid',
+        'parent',
+      ),
+      'module' => 'taxonomy',
+      'name' => 'term_hierarchy',
+    ));
+
+    $this->database->insert('term_data')->fields(array(
+      'tid',
+      'vid',
+      'name',
+      'description',
+      'weight',
+    ))
+      ->values(array(
+        'tid' => '1',
+        'vid' => '1',
+        'name' => 'term 1 of vocabulary 1',
+        'description' => 'description of term 1 of vocabulary 1',
+        'weight' => '0',
+      ))
+      ->values(array(
+        'tid' => '2',
+        'vid' => '2',
+        'name' => 'term 2 of vocabulary 2',
+        'description' => 'description of term 2 of vocabulary 2',
+        'weight' => '3',
+      ))
+      ->values(array(
+        'tid' => '3',
+        'vid' => '2',
+        'name' => 'term 3 of vocabulary 2',
+        'description' => 'description of term 3 of vocabulary 2',
+        'weight' => '4',
+      ))
+      ->values(array(
+        'tid' => '4',
+        'vid' => '3',
+        'name' => 'term 4 of vocabulary 3',
+        'description' => 'description of term 4 of vocabulary 3',
+        'weight' => '6',
+      ))
+      ->values(array(
+        'tid' => '5',
+        'vid' => '3',
+        'name' => 'term 5 of vocabulary 3',
+        'description' => 'description of term 5 of vocabulary 3',
+        'weight' => '7',
+      ))
+      ->values(array(
+        'tid' => '6',
+        'vid' => '3',
+        'name' => 'term 6 of vocabulary 3',
+        'description' => 'description of term 6 of vocabulary 3',
+        'weight' => '8',
+      ))
+      ->execute();
+
+    $this->database->insert('term_hierarchy')->fields(array(
+      'tid',
+      'parent',
+    ))
+      ->values(array(
+        'tid' => '1',
+        'parent' => '0',
+      ))
+      ->values(array(
+        'tid' => '2',
+        'parent' => '0',
+      ))
+      ->values(array(
+        'tid' => '4',
+        'parent' => '0',
+      ))
+      ->values(array(
+        'tid' => '3',
+        'parent' => '2',
+      ))
+      ->values(array(
+        'tid' => '5',
+        'parent' => '4',
+      ))
+      ->values(array(
+        'tid' => '6',
+        'parent' => '4',
+      ))
+      ->values(array(
+        'tid' => '6',
+        'parent' => '5',
+      ))
+      ->execute();
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php
new file mode 100644
index 0000000..70b2429
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php
@@ -0,0 +1,186 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6TaxonomyVocabulary.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+/**
+ * Database dump for testing taxonomy vocabulary migration.
+ */
+class Drupal6TaxonomyVocabulary extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('vocabulary', array(
+      'description' => 'Stores vocabulary information.',
+      'fields' => array(
+        'vid' => array(
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'description' => 'Primary Key: Unique vocabulary ID.',
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Name of the vocabulary.',
+        ),
+        'description' => array(
+          'type' => 'text',
+          'not null' => FALSE,
+          'size' => 'big',
+          'description' => 'Description of the vocabulary.',
+        ),
+        'help' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Help text to display for the vocabulary.',
+        ),
+        'relations' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Whether or not related terms are enabled within the vocabulary. (0 = disabled, 1 = enabled)',
+        ),
+        'hierarchy' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)',
+        ),
+        'multiple' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Whether or not multiple terms from this vocabulary may be assigned to a node. (0 = disabled, 1 = enabled)',
+        ),
+        'required' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Whether or not terms are required for nodes using this vocabulary. (0 = disabled, 1 = enabled)',
+        ),
+        'tags' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Whether or not free tagging is enabled for the vocabulary. (0 = disabled, 1 = enabled)',
+        ),
+        'module' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'The module which created the vocabulary.',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'The weight of the vocabulary in relation to other vocabularies.',
+        ),
+      ),
+      'primary key' => array('vid'),
+      'indexes' => array(
+        'list' => array('weight', 'name'),
+      ),
+    ));
+    $this->createTable('vocabulary_node_types', array(
+      'description' => 'Stores which node types vocabularies may be used with.',
+      'fields' => array(
+        'vid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'Primary Key: the {vocabulary}.vid of the vocabulary.',
+        ),
+        'type' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'The {node}.type of the node type for which the vocabulary may be used.',
+        ),
+      ),
+      'primary key' => array('type', 'vid'),
+      'indexes' => array(
+        'vid' => array('vid'),
+      ),
+    ));
+    $this->database->insert('vocabulary')->fields(array(
+      'vid',
+      'name',
+      'description',
+      'help',
+      'relations',
+      'hierarchy',
+      'multiple',
+      'required',
+      'tags',
+      'module',
+      'weight',
+    ))
+    ->values(array(
+      'vid' => '1',
+      'name' => 'vocabulary 1 (i=0)',
+      'description' => 'description of vocabulary 1 (i=0)',
+      'help' => '',
+      'relations' => '1',
+      'hierarchy' => '0',
+      'multiple' => '0',
+      'required' => '0',
+      'tags' => '0',
+      'module' => 'taxonomy',
+      'weight' => '4',
+    ))
+    ->values(array(
+      'vid' => '2',
+      'name' => 'vocabulary 2 (i=1)',
+      'description' => 'description of vocabulary 2 (i=1)',
+      'help' => '',
+      'relations' => '1',
+      'hierarchy' => '1',
+      'multiple' => '1',
+      'required' => '0',
+      'tags' => '0',
+      'module' => 'taxonomy',
+      'weight' => '5',
+    ))
+    ->values(array(
+      'vid' => '3',
+      'name' => 'vocabulary 3 (i=2)',
+      'description' => 'description of vocabulary 3 (i=2)',
+      'help' => '',
+      'relations' => '1',
+      'hierarchy' => '2',
+      'multiple' => '0',
+      'required' => '0',
+      'tags' => '0',
+      'module' => 'taxonomy',
+      'weight' => '6',
+    ))
+    ->execute();
+    $this->setModuleVersion('taxonomy', 6001);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TermNode.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TermNode.php
new file mode 100644
index 0000000..8df32d7
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TermNode.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6TermNode.
+ */
+
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+
+class Drupal6TermNode extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->setModuleVersion('taxonomy', 6000);
+    $this->createTable('term_node', array(
+      'fields' => array(
+        'nid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'vid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'tid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'indexes' => array(
+        'vid' => array(
+          'vid',
+        ),
+        'nid' => array(
+          'nid',
+        ),
+      ),
+      'primary key' => array(
+        'tid',
+        'vid',
+      ),
+      'module' => 'taxonomy',
+      'name' => 'term_node',
+    ));
+    $this->database->insert('term_node')->fields(array(
+      'nid',
+      'vid',
+      'tid',
+    ))
+    ->values(array(
+      'nid' => 1,
+      'vid' => 1,
+      'tid' => 1,
+    ))
+    ->values(array(
+      'nid' => 1,
+      'vid' => 2,
+      'tid' => 5,
+    ))
+    ->values(array(
+      'nid' => 1,
+      'vid' => 2,
+      'tid' => 4,
+    ))
+    ->values(array(
+      'nid' => 2,
+      'vid' => 3,
+      'tid' => 2,
+    ))
+    ->values(array(
+      'nid' => 2,
+      'vid' => 3,
+      'tid' => 3,
+    ))
+    ->execute();
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TextSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TextSettings.php
index 02ba13a..59c7680 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TextSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TextSettings.php
@@ -7,29 +7,20 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing text.settings.yml migration.
  */
-class Drupal6TextSettings {
+class Drupal6TextSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
-      'name',
-      'value',
-    ))
-    ->values(array(
-      'name' => 'teaser_length',
-      'value' => 'i:600;',
-    ))
-    ->execute();
+  public function load() {
+    $this->createTable('variable');
+    // This needs to be a merge to avoid conflicts with Drupal6NodeBodyInstance.
+    $this->database->merge('variable')
+      ->key(array('name' => 'teaser_length'))
+      ->fields(array('value' => 'i:456;'))
+      ->execute();
   }
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UpdateSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UpdateSettings.php
index 8198802..638b618 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UpdateSettings.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UpdateSettings.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing update.settings.yml migration.
  */
-class Drupal6UpdateSettings {
+class Drupal6UpdateSettings extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Upload.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Upload.php
new file mode 100644
index 0000000..6fd53d3
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Upload.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Upload.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+class Drupal6Upload extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->setModuleVersion('upload', 6000);
+    $this->createTable('upload', array(
+      'fields' => array(
+        'fid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'Primary Key: The {files}.fid.',
+        ),
+        'nid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'The {node}.nid associated with the uploaded file.',
+        ),
+        'vid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'Primary Key: The {node}.vid associated with the uploaded file.',
+        ),
+        'description' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'Description of the uploaded file.',
+        ),
+        'list' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Whether the file should be visibly listed on the node: yes(1) or no(0).',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+          'description' => 'Weight of this upload in relation to other uploads in this node.',
+        ),
+      ),
+      'primary key' => array('vid', 'fid'),
+      'indexes' => array(
+        'fid' => array('fid'),
+        'nid' => array('nid'),
+      ),
+    ));
+    $this->database->insert('upload')->fields(array(
+      'nid',
+      'vid',
+      'fid',
+      'description',
+      'list',
+      'weight',
+    ))
+    ->values(array(
+      'nid' => 1,
+      'vid' => 1,
+      'fid' => 1,
+      'description' => 'file 1-1-1',
+      'list' => 0,
+      'weight' => 5,
+    ))
+    ->values(array(
+      'nid' => 1,
+      'vid' => 2,
+      'fid' => 2,
+      'description' => 'file 1-2-2',
+      'list' => 1,
+      'weight' => 4,
+    ))
+    ->values(array(
+      'nid' => 1,
+      'vid' => 2,
+      'fid' => 3,
+      'description' => 'file 1-2-3',
+      'list' => 0,
+      'weight' => 3,
+    ))
+    ->values(array(
+      'nid' => 2,
+      'vid' => 3,
+      'fid' => 2,
+      'description' => 'file 2-3-2',
+      'list' => 1,
+      'weight' => 2,
+    ))
+    ->values(array(
+      'nid' => 2,
+      'vid' => 3,
+      'fid' => 3,
+      'description' => 'file 2-3-3',
+      'list' => 0,
+      'weight' => 1,
+    ))
+    ->execute();
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadField.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadField.php
new file mode 100644
index 0000000..6df410d
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadField.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Upload.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+class Drupal6UploadField extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->setModuleVersion('upload', 6000);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadInstance.php
new file mode 100644
index 0000000..c3721ba
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadInstance.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6User.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing the upload migration.
+ */
+class Drupal6UploadInstance extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->setModuleVersion('upload', 6000);
+    $this->createTable('node_type');
+    $this->database->merge('node_type')
+      ->key(array('type' => 'page'))
+      ->fields(array(
+        'name' => 'Page',
+        'module' => 'node',
+        'description' => "A <em>page</em>, similar in form to a <em>story</em>, is a simple method for creating and displaying information that rarely changes, such as an \"About us\" section of a website. By default, a <em>page</em> entry does not allow visitor comments and is not featured on the site's initial home page.",
+        'help' => '',
+        'has_title' => '1',
+        'title_label' => 'Title',
+        'has_body' => '1',
+        'body_label' => 'Body',
+        'min_word_count' => '0',
+        'custom' => '1',
+        'modified' => '1',
+        'locked' => '0',
+        'orig_type' => 'page',
+      ))
+    ->execute();
+  $this->database->merge('node_type')
+    ->key(array('type' => 'story'))
+    ->fields(array(
+      'name' => 'Story',
+      'module' => 'node',
+      'description' => "A <em>story</em>, similar in form to a <em>page</em>, is ideal for creating and displaying content that informs or engages website visitors. Press releases, site announcements, and informal blog-like entries may all be created with a <em>story</em> entry. By default, a <em>story</em> entry is automatically featured on the site's initial home page, and provides the ability to post comments.",
+      'help' => '',
+      'has_title' => '1',
+      'title_label' => 'Title',
+      'has_body' => '1',
+      'body_label' => 'Body',
+      'min_word_count' => '0',
+      'custom' => '1',
+      'modified' => '1',
+      'locked' => '0',
+      'orig_type' => 'story',
+    ))
+    ->execute();
+  $this->database->merge('node_type')
+    ->key(array('type' => 'article'))
+    ->fields(array(
+      'name' => 'Article',
+      'module' => 'node',
+      'description' => "An <em>article</em>, content type.",
+      'help' => '',
+      'has_title' => '1',
+      'title_label' => 'Title',
+      'has_body' => '1',
+      'body_label' => 'Body',
+      'min_word_count' => '0',
+      'custom' => '1',
+      'modified' => '1',
+      'locked' => '0',
+      'orig_type' => 'story',
+    ))
+    ->execute();
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'upload_page',
+      'value' => 'b:1;',
+    ))
+    ->values(array(
+      'name' => 'upload_story',
+      'value' => 'b:1;',
+    ))
+    ->values(array(
+      'name' => 'upload_article',
+      'value' => 'b:0;',
+    ))
+    ->execute();
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UrlAlias.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UrlAlias.php
new file mode 100644
index 0000000..2af66ef
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UrlAlias.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6UrlAlias.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing url alias migrations.
+ */
+class Drupal6UrlAlias extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('url_alias', array(
+      'description' => 'A list of URL aliases for Drupal paths; a user may visit either the source or destination path.',
+      'fields' => array(
+        'pid' => array(
+          'description' => 'A unique path alias identifier.',
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'src' => array(
+          'description' => 'The Drupal path this alias is for; e.g. node/12.',
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'dst' => array(
+          'description' => 'The alias for this path; e.g. title-of-the-story.',
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'language' => array(
+          'description' => 'The language this alias is for; if blank, the alias will be used for unknown languages. Each Drupal path can have an alias for each supported language.',
+          'type' => 'varchar',
+          'length' => 12,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+      ),
+      'unique keys' => array(
+        'dst_language_pid' => array(
+          'dst',
+          'language',
+          'pid',
+        ),
+      ),
+      'primary key' => array('pid'),
+      'indexes' => array('src_language_pid' => array('src', 'language', 'pid')),
+    ));
+
+    $this->database->insert('url_alias')->fields(array(
+      'pid',
+      'src',
+      'dst',
+      'language',
+    ))
+    ->values(array(
+      'pid' => 1,
+      'src' => 'node/1',
+      'dst' => 'alias-one',
+      'language' => 'en',
+    ))
+    ->values(array(
+      'pid' => 2,
+      'src' => 'node/2',
+      'dst' => 'alias-two',
+      'language' => 'en',
+    ))
+    ->execute();
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6User.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6User.php
new file mode 100644
index 0000000..2b662e8
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6User.php
@@ -0,0 +1,423 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6User.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing the users migration.
+ */
+class Drupal6User extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+
+    foreach (static::getSchema() as $table => $schema) {
+      // Create tables.
+      $this->createTable($table, $schema);
+
+      // Insert data.
+      $data = static::getData($table);
+      if ($data) {
+        $query = $this->database->insert($table)->fields(array_keys($data[0]));
+        foreach ($data as $record) {
+          $query->values($record);
+        }
+        $query->execute();
+      }
+    }
+  }
+
+  /**
+   * Defines schema for this database dump.
+   *
+   * @return array
+   *   Associative array having the structure as is returned by hook_schema().
+   */
+  protected static function getSchema() {
+    return array(
+      'users' => array(
+        'description' => 'Stores user data.',
+        'fields' => array(
+          'uid' => array(
+            'type' => 'serial',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'description' => 'Primary Key: Unique user ID.',
+          ),
+          'name' => array(
+            'type' => 'varchar',
+            'length' => 60,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => 'Unique user name.',
+          ),
+          'pass' => array(
+            'type' => 'varchar',
+            'length' => 32,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => "User's password (md5 hash).",
+          ),
+          'mail' => array(
+            'type' => 'varchar',
+            'length' => 64,
+            'not null' => FALSE,
+            'default' => '',
+            'description' => "User's email address.",
+          ),
+          'mode' => array(
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'size' => 'tiny',
+            'description' => 'Per-user comment display mode (threaded vs. flat), used by the {comment} module.',
+          ),
+          'sort' => array(
+            'type' => 'int',
+            'not null' => FALSE,
+            'default' => 0,
+            'size' => 'tiny',
+            'description' => 'Per-user comment sort order (newest vs. oldest first), used by the {comment} module.',
+          ),
+          'threshold' => array(
+            'type' => 'int',
+            'not null' => FALSE,
+            'default' => 0,
+            'size' => 'tiny',
+            'description' => 'Previously used by the {comment} module for per-user preferences; no longer used.',
+          ),
+          'theme' => array(
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => "User's default theme.",
+          ),
+          'signature' => array(
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => "User's signature.",
+          ),
+          'signature_format' => array(
+            'type' => 'int',
+            'size' => 'small',
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'The {filter_formats}.format of the signature.',
+          ),
+          'created' => array(
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'Timestamp for when user was created.',
+          ),
+          'access' => array(
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'Timestamp for previous time user accessed the site.',
+          ),
+          'login' => array(
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => "Timestamp for user's last login.",
+          ),
+          'status' => array(
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'size' => 'tiny',
+            'description' => 'Whether the user is active(1) or blocked(0).',
+          ),
+          'timezone' => array(
+            'type' => 'varchar',
+            'length' => 8,
+            'not null' => FALSE,
+            'description' => "User's timezone.",
+          ),
+          'language' => array(
+            'type' => 'varchar',
+            'length' => 12,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => "User's default language.",
+          ),
+          'picture' => array(
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => "Path to the user's uploaded picture.",
+          ),
+          'init' => array(
+            'type' => 'varchar',
+            'length' => 64,
+            'not null' => FALSE,
+            'default' => '',
+            'description' => 'Email address used for initial account creation.',
+          ),
+          'data' => array(
+            'type' => 'text',
+            'not null' => FALSE,
+            'size' => 'big',
+            'description' => 'A serialized array of name value pairs that are related to the user. Any form values posted during user edit are stored and are loaded into the $user object during user_load(). Use of this field is discouraged and it will likely disappear in a future version of Drupal.',
+          ),
+          // Field not part of Drupal 6 schema. Added by Date contributed module.
+          'timezone_name' => array(
+            'type' => 'varchar',
+            'length' => 50,
+            'not null' => FALSE,
+            'default' => '',
+            'description' => 'Field added by Date contributed module.',
+          ),
+          // Field not part of Drupal 6 schema. Added by Event contributed module.
+          'timezone_id' => array(
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'Field added by Event contributed module.',
+          ),
+          // Field not part of Drupal 6 schema. Needed to test password rehashing.
+          'pass_plain' => array(
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => "User's password (plain).",
+          ),
+          // Field not part of Drupal 6 schema. Needed to test user_update_7002.
+          'expected_timezone' => array(
+            'type' => 'varchar',
+            'length' => 50,
+            'not null' => FALSE,
+          ),
+        ),
+        'indexes' => array(
+          'access' => array('access'),
+          'created' => array('created'),
+          'mail' => array('mail'),
+        ),
+        'unique keys' => array(
+          'name' => array('name'),
+        ),
+        'primary key' => array('uid'),
+      ),
+      'users_roles' => array(
+        'description' => 'Maps users to roles.',
+        'fields' => array(
+          'uid' => array(
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'Primary Key: {users}.uid for user.',
+          ),
+          'rid' => array(
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'Primary Key: {role}.rid for role.',
+          ),
+        ),
+        'primary key' => array('uid', 'rid'),
+        'indexes' => array(
+          'rid' => array('rid'),
+        ),
+      ),
+      'event_timezones' => array(
+        'fields' => array(
+          'timezone' => array(
+            'type' => 'int',
+            'not null' => TRUE,
+            'default' => 0,
+          ),
+          'name' => array(
+            'type' => 'varchar',
+            'length' => 255,
+            'not null' => TRUE,
+            'default' => '',
+          ),
+        )
+      ),
+      'profile_values' => array(
+        'description' => 'Stores values for profile fields.',
+        'fields' => array(
+          'fid' => array(
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'The {profile_field}.fid of the field.',
+          ),
+          'uid' => array(
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'The {users}.uid of the profile user.',
+          ),
+          'value' => array(
+            'type' => 'text',
+            'not null' => FALSE,
+            'description' => 'The value for the field.',
+          ),
+        ),
+        'primary key' => array('uid', 'fid'),
+        'indexes' => array(
+          'fid' => array('fid'),
+        ),
+        'foreign keys' => array(
+          'profile_field' => array(
+            'table' => 'profile_field',
+            'columns' => array('fid' => 'fid'),
+          ),
+          'profile_user' => array(
+            'table' => 'users',
+            'columns' => array('uid' => 'uid'),
+          ),
+        ),
+      ),
+    );
+  }
+
+  /**
+   * Returns dump data from a specific table.
+   *
+   * @param string $table
+   *   The table name.
+   *
+   * @return array
+   *   Array of associative arrays each one having fields as keys.
+   */
+  public static function getData($table) {
+    $data = array(
+      'users' => array(
+        array(
+          'uid' => 2,
+          'name' => 'john.doe',
+          'pass' => md5('john.doe_pass'),
+          'mail' => 'john.doe@example.com',
+          'picture' => 'core/modules/simpletest/files/image-test.jpg',
+          'mode' => 0,
+          'sort' => 0,
+          'threshold' => 0,
+          'theme' => '',
+          'signature' => 'John Doe | john.doe@example.com',
+          'signature_format' => 1,
+          'created' => 1391150052,
+          'access' => 1391259672,
+          'login' => 1391152253,
+          'status' => 1,
+          'timezone' => '3600',
+          'language' => 'fr',
+          'init' => 'doe@example.com',
+          'data' => serialize(array()),
+          'timezone_name' => NULL,
+          'timezone_id' => 1,
+          'pass_plain' => 'john.doe_pass',
+          'expected_timezone' => 'Europe/Berlin',
+        ),
+        array(
+          'uid' => 8,
+          'name' => 'joe.roe',
+          'pass' => md5('joe.roe_pass'),
+          'mail' => 'joe.roe@example.com',
+          'picture' => 'core/modules/simpletest/files/image-test.png',
+          'mode' => 0,
+          'sort' => 0,
+          'threshold' => 0,
+          'theme' => '',
+          'signature' => 'JR',
+          'signature_format' => 2,
+          'created' => 1391150053,
+          'access' => 1391259673,
+          'login' => 1391152254,
+          'status' => 1,
+          'timezone' => '7200',
+          'language' => 'ro',
+          'init' => 'roe@example.com',
+          'data' => serialize(array()),
+          'timezone_name' => 'Europe/Helsinki',
+          'timezone_id' => 0,
+          'pass_plain' => 'joe.roe_pass',
+          'expected_timezone' => 'Europe/Helsinki',
+        ),
+        array(
+          'uid' => 15,
+          'name' => 'joe.bloggs',
+          'pass' => md5('joe.bloggs_pass'),
+          'mail' => 'joe.bloggs@example.com',
+          'picture' => '',
+          'mode' => 0,
+          'sort' => 0,
+          'threshold' => 0,
+          'theme' => '',
+          'signature' => 'bloggs',
+          'signature_format' => 1,
+          'created' => 1391150054,
+          'access' => 1391259674,
+          'login' => 1391152255,
+          'status' => 1,
+          'timezone' => '3600',
+          'language' => 'en',
+          'init' => 'bloggs@example.com',
+          'data' => serialize(array()),
+          'timezone_name' => NULL,
+          'timezone_id' => 0,
+          'pass_plain' => 'joe.bloggs_pass',
+          'expected_timezone' => NULL,
+        ),
+      ),
+      'users_roles' => array(
+        array('uid' => 2, 'rid' => 3),
+        array('uid' => 8, 'rid' => 4),
+        array('uid' => 8, 'rid' => 5),
+        array('uid' => 15, 'rid' => 3),
+        array('uid' => 15, 'rid' => 4),
+        array('uid' => 15, 'rid' => 5),
+      ),
+      'event_timezones' => array(
+        array(
+          'timezone' => 1,
+          'name' => 'Europe/Berlin',
+        )
+      ),
+      'profile_values' => array(
+        array('fid' => 8, 'uid' => 2, 'value' => 'red'),
+        array('fid' => 9, 'uid' => 2, 'value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nulla sapien, congue nec risus ut, adipiscing aliquet felis. Maecenas quis justo vel nulla varius euismod. Quisque metus metus, cursus sit amet sem non, bibendum vehicula elit. Cras dui nisl, eleifend at iaculis vitae, lacinia ut felis. Nullam aliquam ligula volutpat nulla consectetur accumsan. Maecenas tincidunt molestie diam, a accumsan enim fringilla sit amet. Morbi a tincidunt tellus. Donec imperdiet scelerisque porta. Sed quis sem bibendum eros congue sodales. Vivamus vel fermentum est, at rutrum orci. Nunc consectetur purus ut dolor pulvinar, ut volutpat felis congue. Cras tincidunt odio sed neque sollicitudin, vehicula tempor metus scelerisque.'),
+        array('fid' => 10, 'uid' => 2, 'value' => '1'),
+        array('fid' => 11, 'uid' => 2, 'value' => 'Fitness spammers'),
+        array('fid' => 12, 'uid' => 2, 'value' => "AC/DC\nEagles"),
+        array('fid' => 13, 'uid' => 2, 'value' => "http://example.com/blog"),
+        array('fid' => 14, 'uid' => 2, 'value' => 'a:3:{s:5:"month";s:1:"6";s:3:"day";s:1:"2";s:4:"year";s:4:"1974";}'),
+        array('fid' => 8, 'uid' => 8, 'value' => 'brown'),
+        array('fid' => 9, 'uid' => 8, 'value' => 'Nunc condimentum ligula felis, eget lacinia purus accumsan at. Pellentesque eu lobortis felis. Duis at accumsan nisl, vel pulvinar risus. Nullam venenatis, tellus non eleifend hendrerit, augue nulla rhoncus leo, eget convallis enim sem ut velit. Mauris tincidunt enim ut eros volutpat dapibus. Curabitur augue libero, imperdiet eget orci sed, malesuada dapibus tellus. Nam lacus sapien, convallis vitae quam vel, bibendum commodo odio.'),
+        array('fid' => 10, 'uid' => 8, 'value' => '0'),
+        array('fid' => 11, 'uid' => 8, 'value' => ''),
+        array('fid' => 12, 'uid' => 8, 'value' => "Deep Purple\nWho\nThe Beatles"),
+        array('fid' => 13, 'uid' => 8, 'value' => "http://blog.example.com"),
+        array('fid' => 14, 'uid' => 8, 'value' => 'a:3:{s:5:"month";s:1:"9";s:3:"day";s:1:"9";s:4:"year";s:4:"1980";}'),
+        array('fid' => 8, 'uid' => 15, 'value' => 'orange'),
+        array('fid' => 9, 'uid' => 15, 'value' => 'Donec a diam volutpat augue fringilla fringilla. Mauris ultricies turpis ut lacus tempus, vitae pharetra lacus mattis. Nulla semper dui euismod sem bibendum, in eleifend nisi malesuada. Vivamus orci mauris, volutpat vitae enim ac, aliquam tempus lectus.'),
+        array('fid' => 10, 'uid' => 15, 'value' => '1'),
+        array('fid' => 11, 'uid' => 15, 'value' => 'Pill spammers'),
+        array('fid' => 12, 'uid' => 15, 'value' => "ABBA\nBoney M"),
+        array('fid' => 13, 'uid' => 15, 'value' => "http://example.com/journal"),
+        array('fid' => 14, 'uid' => 15, 'value' => 'a:3:{s:5:"month";s:2:"11";s:3:"day";s:2:"25";s:4:"year";s:4:"1982";}'),
+      ),
+    );
+
+    return isset($data[$table]) ? $data[$table] : FALSE;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserMail.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserMail.php
index 7784e74..114b482 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserMail.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserMail.php
@@ -7,22 +7,17 @@
 
 namespace Drupal\migrate_drupal\Tests\Dump;
 
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing user.mail.yml migration.
  */
-class Drupal6UserMail {
+class Drupal6UserMail extends Drupal6DumpBase {
 
   /**
-   * Sample database schema and values.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    Drupal6DumpCommon::createVariable($database);
-    $database->insert('variable')->fields(array(
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
       'name',
       'value',
     ))
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php
new file mode 100644
index 0000000..60e90df
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php
@@ -0,0 +1,245 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\Dump\Drupal6UserProfileFields.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing profile fields.
+ */
+class Drupal6UserProfileFields extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('profile_fields', array(
+      'fields' => array(
+        'fid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+        ),
+        'title' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => FALSE,
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'explanation' => array(
+          'type' => 'text',
+          'not null' => FALSE,
+        ),
+        'category' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => FALSE,
+        ),
+        'page' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => FALSE,
+        ),
+        'type' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => FALSE,
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'required' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'register' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'visibility' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'autocomplete' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'options' => array(
+          'type' => 'text',
+          'not null' => FALSE,
+        ),
+      ),
+      'indexes' => array(
+        'category' => array(
+          'category',
+        ),
+      ),
+      'unique keys' => array(
+        'name' => array(
+          'name',
+        ),
+      ),
+      'primary key' => array(
+        'fid',
+      ),
+      'module' => 'profile',
+      'name' => 'profile_fields',
+    ));
+
+    // Insert data.
+    $data = static::getData('profile_fields');
+    if ($data) {
+      $query = $this->database->insert('profile_fields')->fields(array_keys($data[0]));
+      foreach ($data as $record) {
+        $query->values($record);
+      }
+      $query->execute();
+    }
+    $this->setModuleVersion('profile', 6001);
+  }
+
+  /**
+   * Returns dump data from a specific table.
+   *
+   * @param string $table
+   *   The table name.
+   *
+   * @return array
+   *   Array of associative arrays each one having fields as keys.
+   */
+  public static function getData($table) {
+    $data = array(
+      'profile_fields' => array(
+        array(
+          'fid' => '8',
+          'title' => 'Favorite color',
+          'name' => 'profile_color',
+          'explanation' => 'List your favorite color',
+          'category' => 'Personal information',
+          'page' => 'Peole whose favorite color is %value',
+          'type' => 'textfield',
+          'weight' => '-10',
+          'required' => '0',
+          'register' => '1',
+          'visibility' => '2',
+          'autocomplete' => '1',
+          'options' => '',
+        ),
+        array(
+          'fid' => '9',
+          'title' => 'Biography',
+          'name' => 'profile_biography',
+          'explanation' => 'Tell people a little bit about yourself',
+          'category' => 'Personal information',
+          'page' => '',
+          'type' => 'textarea',
+          'weight' => '-8',
+          'required' => '0',
+          'register' => '0',
+          'visibility' => '2',
+          'autocomplete' => '0',
+          'options' => '',
+        ),
+        array(
+          'fid' => '10',
+          'title' => 'Sell your e-mail address?',
+          'name' => 'profile_sell_address',
+          'explanation' => "If you check this box, we'll sell your address to spammers to help line the pockets of our shareholders. Thanks!",
+          'category' => 'Communication preferences',
+          'page' => 'People who want us to sell their address',
+          'type' => 'checkbox',
+          'weight' => '-10',
+          'required' => '0',
+          'register' => '1',
+          'visibility' => '1',
+          'autocomplete' => '0',
+          'options' => '',
+        ),
+        array(
+          'fid' => '11',
+          'title' => 'Sales Category',
+          'name' => 'profile_sold_to',
+          'explanation' => "Select the sales categories to which this user's address was sold.",
+          'category' => 'Administrative data',
+          'page' => 'People whose address was sold to %value',
+          'type' => 'selection',
+          'weight' => '-10',
+          'required' => '0',
+          'register' => '0',
+          'visibility' => '4',
+          'autocomplete' => '0',
+          'options' => "Pill spammers\r\nFitness spammers",
+        ),
+        array(
+          'fid' => '12',
+          'title' => 'Favorite bands',
+          'name' => 'profile_bands',
+          'explanation' => "Enter your favorite bands. When you've saved your profile, you'll be able to find other people with the same favorites.",
+          'category' => 'Personal information',
+          'page' => '',
+          'type' => 'list',
+          'weight' => '-6',
+          'required' => '0',
+          'register' => '1',
+          'visibility' => '3',
+          'autocomplete' => '1',
+          'options' => '',
+        ),
+/*
+        array(
+          'fid' => '13',
+          'title' => 'Your blog',
+          'name' => 'profile_blog',
+          'explanation' => 'Paste the full URL, including http://, of your personal blog.',
+          'category' => 'Personal information',
+          'page' => '',
+          'type' => 'url',
+          'weight' => '0',
+          'required' => '0',
+          'register' => '0',
+          'visibility' => '2',
+          'autocomplete' => '0',
+          'options' => '',
+        ),
+*/
+        array(
+          'fid' => '14',
+          'title' => 'Birthdate',
+          'name' => 'profile_birthdate',
+          'explanation' => "Enter your birth date and we'll send you a coupon.",
+          'category' => 'Personal information',
+          'page' => '',
+          'type' => 'date',
+          'weight' => '4',
+          'required' => '0',
+          'register' => '0',
+          'visibility' => '2',
+          'autocomplete' => '0',
+          'options' => '',
+        ),
+      ),
+    );
+
+    return isset($data[$table]) ? $data[$table] : FALSE;
+  }
+
+}
+
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php
index 934141e..12283bb 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php
@@ -6,118 +6,121 @@
  */
 
 namespace Drupal\migrate_drupal\Tests\Dump;
-use Drupal\Core\Database\Connection;
-
 /**
  * Database dump for testing user role migration.
  */
-class Drupal6UserRole {
+class Drupal6UserRole extends Drupal6DumpBase {
 
   /**
-   * @param \Drupal\Core\Database\Connection $database
+   * {@inheritdoc}
    */
-  public static function load(Connection $database) {
-    $database->schema()->createTable('permission', array(
-      'description' => 'Stores permissions for users.',
-      'fields' => array(
-        'pid' => array(
-          'type' => 'serial',
-          'not null' => TRUE,
-          'description' => 'Primary Key: Unique permission ID.',
-        ),
-        'rid' => array(
-          'type' => 'int',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'default' => 0,
-          'description' => 'The {role}.rid to which the permissions are assigned.',
-        ),
-        'perm' => array(
-          'type' => 'text',
-          'not null' => FALSE,
-          'size' => 'big',
-          'description' => 'List of permissions being assigned.',
-        ),
-        'tid' => array(
-          'type' => 'int',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'default' => 0,
-          'description' => 'Originally intended for taxonomy-based permissions, but never used.',
+  public function load() {
+    foreach (static::getSchema() as $table => $schema) {
+      // Create tables.
+      $this->createTable($table, $schema);
+
+      // Insert data.
+      $data = static::getData($table);
+      if ($data) {
+        $query = $this->database->insert($table)->fields(array_keys($data[0]));
+        foreach ($data as $record) {
+          $query->values($record);
+        }
+        $query->execute();
+      }
+    }
+  }
+
+  /**
+   * Defines schema for this database dump.
+   *
+   * @return array
+   *   Associative array having the structure as is returned by hook_schema().
+   */
+  protected static function getSchema() {
+    return array(
+      'permission' => array(
+        'description' => 'Stores permissions for users.',
+        'fields' => array(
+          'pid' => array(
+            'type' => 'serial',
+            'not null' => TRUE,
+            'description' => 'Primary Key: Unique permission ID.',
+          ),
+          'rid' => array(
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'The {role}.rid to which the permissions are assigned.',
+          ),
+          'perm' => array(
+            'type' => 'text',
+            'not null' => FALSE,
+            'size' => 'big',
+            'description' => 'List of permissions being assigned.',
+          ),
+          'tid' => array(
+            'type' => 'int',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'default' => 0,
+            'description' => 'Originally intended for taxonomy-based permissions, but never used.',
+          ),
         ),
+        'primary key' => array('pid'),
+        'indexes' => array('rid' => array('rid')),
       ),
-      'primary key' => array('pid'),
-      'indexes' => array('rid' => array('rid')),
-    ));
-    $database->schema()->createTable('role', array(
-      'description' => 'Stores user roles.',
-      'fields' => array(
-        'rid' => array(
-          'type' => 'serial',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'description' => 'Primary Key: Unique role id.',
-        ),
-        'name' => array(
-          'type' => 'varchar',
-          'length' => 64,
-          'not null' => TRUE,
-          'default' => '',
-          'description' => 'Unique role name.',
+      'role' => array(
+        'description' => 'Stores user roles.',
+        'fields' => array(
+          'rid' => array(
+            'type' => 'serial',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+            'description' => 'Primary Key: Unique role id.',
+          ),
+          'name' => array(
+            'type' => 'varchar',
+            'length' => 64,
+            'not null' => TRUE,
+            'default' => '',
+            'description' => 'Unique role name.',
+          ),
         ),
+        'unique keys' => array('name' => array('name')),
+        'primary key' => array('rid'),
       ),
-      'unique keys' => array('name' => array('name')),
-      'primary key' => array('rid'),
-    ));
-    $database->schema()->createTable('users_roles', array(
-      'description' => 'Maps users to roles.',
-      'fields' => array(
-        'uid' => array(
-          'type' => 'int',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'default' => 0,
-          'description' => 'Primary Key: {users}.uid for user.',
-        ),
-        'rid' => array(
-          'type' => 'int',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'default' => 0,
-          'description' => 'Primary Key: {role}.rid for role.',
-        ),
+    );
+  }
+
+  /**
+   * Returns dump data from a specific table.
+   *
+   * @param string $table
+   *   The table name.
+   *
+   * @return array
+   *   Array of associative arrays each one having fields as keys.
+   */
+  public static function getData($table) {
+    $data = array(
+      'permission' => array(
+        array('pid' => 1, 'rid' => 1, 'perm' => 'migrate test anonymous permission'),
+        array('pid' => 2, 'rid' => 2, 'perm' => 'migrate test authenticated permission'),
+        array('pid' => 3, 'rid' => 3, 'perm' => 'migrate test role 1 test permission'),
+        array('pid' => 4, 'rid' => 4, 'perm' => 'migrate test role 2 test permission, use PHP for settings, administer contact forms, skip comment approval, edit own blog content, edit any blog content, delete own blog content, delete any blog content, create forum content, delete any forum content, delete own forum content, edit any forum content, edit own forum content, administer nodes'),
       ),
-      'primary key' => array('uid', 'rid'),
-      'indexes' => array(
-        'rid' => array('rid'),
+      'role' => array(
+        array('rid' => 1, 'name' => 'anonymous user'),
+        array('rid' => 2, 'name' => 'authenticated user'),
+        array('rid' => 3, 'name' => 'migrate test role 1'),
+        array('rid' => 4, 'name' => 'migrate test role 2'),
+        array('rid' => 5, 'name' => 'migrate test role 3'),
       ),
-    ));
-    $database->insert('permission')->fields(array('pid', 'rid', 'perm'))
-      ->values(array('pid' => 3, 'rid' => 3, 'perm' => 'migrate test role 1 test permission'))
-      ->values(array('pid' => 4, 'rid' => 4, 'perm' => 'migrate test role 2 test permission'))
-      ->values(array('pid' => 5, 'rid' => 4, 'perm' => 'use PHP for settings'))
-      ->values(array('pid' => 6, 'rid' => 4, 'perm' => 'administer contact forms'))
-      ->values(array('pid' => 7, 'rid' => 4, 'perm' => 'skip comment approval'))
-      ->values(array('pid' => 8, 'rid' => 4, 'perm' => 'edit own blog content'))
-      ->values(array('pid' => 9, 'rid' => 4, 'perm' => 'edit any blog content'))
-      ->values(array('pid' => 10, 'rid' => 4, 'perm' => 'delete own blog content'))
-      ->values(array('pid' => 11, 'rid' => 4, 'perm' => 'delete any blog content'))
-      ->values(array('pid' => 12, 'rid' => 4, 'perm' => 'create forum content'))
-      ->values(array('pid' => 13, 'rid' => 4, 'perm' => 'delete any forum content'))
-      ->values(array('pid' => 14, 'rid' => 4, 'perm' => 'delete own forum content'))
-      ->values(array('pid' => 15, 'rid' => 4, 'perm' => 'edit any forum content'))
-      ->values(array('pid' => 16, 'rid' => 4, 'perm' => 'edit own forum content'))
-      ->values(array('pid' => 17, 'rid' => 4, 'perm' => 'administer nodes'))
-      ->execute();
-    $database->insert('role')->fields(array('rid', 'name'))
-      ->values(array('rid' => 3, 'name' => 'migrate test role 1'))
-      ->values(array('rid' => 4, 'name' => 'migrate test role 2'))
-      ->values(array('rid' => 5, 'name' => 'migrate test role 3'))
-      ->execute();
-    $database->insert('users_roles')->fields(array('uid', 'rid'))
-      ->values(array('uid' => 1, 'rid' => 3))
-      ->values(array('uid' => 1, 'rid' => 4))
-      ->execute();
+    );
+
+    return isset($data[$table]) ? $data[$table] : FALSE;
   }
 
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php
new file mode 100644
index 0000000..1330cb5
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php
@@ -0,0 +1,173 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6VocabularyField.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing vocabulary to field migration.
+ */
+class Drupal6VocabularyField extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+
+    $this->createTable('vocabulary', array(
+      'fields' => array(
+        'vid' => array(
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'description' => array(
+          'type' => 'text',
+          'not null' => FALSE,
+          'size' => 'big',
+        ),
+        'help' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'relations' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'hierarchy' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'multiple' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'required' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'tags' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+        'module' => array(
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+          'size' => 'tiny',
+        ),
+      ),
+      'primary key' => array(
+        'vid',
+      ),
+      'indexes' => array(
+        'list' => array(
+          'weight',
+          'name',
+        ),
+      ),
+      'module' => 'taxonomy',
+      'name' => 'vocabulary',
+    ));
+
+    $this->database->insert('vocabulary')
+      ->fields(array(
+        'vid' => 4,
+        'name' => 'Tags',
+        'description' => 'Tags Vocabulary',
+        'help' => '',
+        'relations' => '1',
+        'hierarchy' => '0',
+        'multiple' => '0',
+        'required' => '0',
+        'tags' => '0',
+        'module' => 'taxonomy',
+        'weight' => '0',
+      ))
+      ->execute();
+
+
+    $this->createTable('vocabulary_node_types', array(
+      'description' => 'Stores which node types vocabularies may be used with.',
+      'fields' => array(
+        'vid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+          'description' => 'Primary Key: the {vocabulary}.vid of the vocabulary.',
+        ),
+        'type' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+          'description' => 'The {node}.type of the node type for which the vocabulary may be used.',
+        ),
+      ),
+      'primary key' => array('type', 'vid'),
+      'indexes' => array(
+        'vid' => array('vid'),
+      ),
+    ));
+
+    $this->database->insert('vocabulary_node_types')->fields(array(
+      'vid',
+      'type',
+    ))
+    ->values(array(
+      'vid' => '1',
+      'type' => 'story',
+    ))
+    ->values(array(
+      'vid' => '2',
+      'type' => 'story',
+    ))
+    ->values(array(
+      'vid' => '3',
+      'type' => 'story',
+    ))
+    ->values(array(
+      'vid' => '4',
+      'type' => 'article',
+    ))
+    ->values(array(
+      'vid' => '4',
+      'type' => 'page',
+    ))
+    ->execute();
+    $this->setModuleVersion('taxonomy', 6001);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal7TrackerSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal7TrackerSettings.php
new file mode 100644
index 0000000..b82c025
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal7TrackerSettings.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal7TrackerSettings.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing tracker.settings.yml migration.
+ */
+class Drupal7TrackerSettings extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('variable');
+    $this->database->insert('variable')->fields(array(
+      'name',
+      'value',
+    ))
+    ->values(array(
+      'name' => 'cron_index_limit',
+      'value' => "i:1000;",
+    ))
+    ->execute();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/MigrateDrupalTestBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/MigrateDrupalTestBase.php
index 370351c..7a6579c 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/MigrateDrupalTestBase.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/MigrateDrupalTestBase.php
@@ -11,5 +11,10 @@
 
 class MigrateDrupalTestBase extends MigrateTestBase {
 
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
   public static $modules = array('migrate_drupal');
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateActionConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateActionConfigsTest.php
index ec3f29f..0d15565 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateActionConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateActionConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,16 +34,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of action variables to action.settings.yml.
+   * {@inheritdoc}
    */
-  public function testActionSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_action_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ActionSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of action variables to action.settings.yml.
+   */
+  public function testActionSettings() {
     $config = \Drupal::config('action.settings');
     $this->assertIdentical($config->get('recursion_limit'), 35);
   }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorConfigsTest.php
index 88ec847..4a13937 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,16 +34,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of aggregator variables to aggregator.settings.yml.
+   * {@inheritdoc}
    */
-  public function testAggregatorSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_aggregator_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of aggregator variables to aggregator.settings.yml.
+   */
+  public function testAggregatorSettings() {
     $config = \Drupal::config('aggregator.settings');
     $this->assertIdentical($config->get('fetcher'), 'aggregator');
     $this->assertIdentical($config->get('parser'), 'aggregator');
@@ -55,4 +61,5 @@ public function testAggregatorSettings() {
     $this->assertIdentical($config->get('source.list_max'), 3);
     $this->assertIdentical($config->get('source.category_selector'), 'checkboxes');
   }
+
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorFeedTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorFeedTest.php
new file mode 100644
index 0000000..a32d37b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorFeedTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateAggregatorFeedTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\aggregator\Entity\Feed;
+use Drupal\Core\Language\Language;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateAggregatorFeedTest extends MigrateDrupalTestBase {
+
+  static $modules = array('aggregator');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate variables to aggregator_feed entities.',
+      'description'  => 'Upgrade variables to aggregator_feed entities',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_aggregator_feed');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorFeed.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of aggregator feeds.
+   */
+  public function testAggregatorFeedImport() {
+    /** @var Feed $feed */
+    $feed = entity_load('aggregator_feed', 5);
+    $this->assertNotNull($feed->uuid());
+    $this->assertEqual($feed->title->value, 'Know Your Meme');
+    $this->assertEqual($feed->language()->id, Language::LANGCODE_NOT_SPECIFIED);
+    $this->assertEqual($feed->url->value, 'http://knowyourmeme.com/newsfeed.rss');
+    $this->assertEqual($feed->refresh->value, 900);
+    $this->assertEqual($feed->checked->value, 1387659487);
+    $this->assertEqual($feed->queued->value, 0);
+    $this->assertEqual($feed->link->value, 'http://knowyourmeme.com');
+    $this->assertEqual($feed->description->value, 'New items added to the News Feed');
+    $this->assertEqual($feed->image->value, 'http://b.thumbs.redditmedia.com/harEHsUUZVajabtC.png');
+    $this->assertEqual($feed->hash->value, '');
+    $this->assertEqual($feed->etag->value, '"213cc1365b96c310e92053c5551f0504"');
+    $this->assertEqual($feed->modified->value, 0);
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorItemTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorItemTest.php
new file mode 100644
index 0000000..6668c53
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateAggregatorItemTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateAggregatorItemTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\aggregator\Entity\Item;
+use Drupal\Core\Language\Language;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Test Drupal 6 aggregator item migration to Drupal 8.
+ */
+class MigrateAggregatorItemTest extends MigrateDrupalTestBase {
+
+  static $modules = array('aggregator');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate aggregator items',
+      'description'  => 'Upgrade aggregator items',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_aggregator_feed' => array(
+        array(array(5), array(5)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $entity = entity_create('aggregator_feed', array(
+      'fid' => 5,
+      'title' => 'Drupal Core',
+      'url' => 'https://groups.drupal.org/not_used/167169',
+      'refresh' => 900,
+      'checked' => 1389919932,
+      'description' => 'Drupal Core Group feed',
+    ));
+    $entity->enforceIsNew();
+    $entity->save();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_aggregator_item');
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorItem.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test Drupal 6 aggregator item migration to Drupal 8.
+   */
+  public function testAggregatorItem() {
+    /** @var Item $item */
+    $item = entity_load('aggregator_item', 1);
+    $this->assertEqual($item->id(), 1);
+    $this->assertEqual($item->getFeedId(), 5);
+    $this->assertEqual($item->label(), 'This (three) weeks in Drupal Core - January 10th 2014');
+    $this->assertEqual($item->getAuthor(), 'larowlan');
+    $this->assertEqual($item->getDescription(), "<h2 id='new'>What's new with Drupal 8?</h2>");
+    $this->assertEqual($item->getLink(), 'https://groups.drupal.org/node/395218');
+    $this->assertEqual($item->getPostedTime(), 1389297196);
+    $this->assertEqual($item->language()->id, Language::LANGCODE_NOT_SPECIFIED);
+    $this->assertEqual($item->getGuid(), '395218 at https://groups.drupal.org');
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateBlockTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateBlockTest.php
new file mode 100644
index 0000000..458c537a
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateBlockTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateBlockTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Test the block settings migration.
+ */
+class MigrateBlockTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array(
+    'block',
+    'views',
+    'comment',
+    'menu',
+    'custom_block',
+    'node',
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate block settings to block.block.*.yml',
+      'description'  => 'Upgrade block settings to block.block.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $entities = array(
+      entity_create('menu', array('id' => 'primary-links')),
+      entity_create('menu', array('id' => 'secondary-links')),
+      entity_create('custom_block', array('id' => 1, 'type' => 'basic')),
+    );
+    foreach ($entities as $entity) {
+      $entity->enforceIsNew(TRUE);
+      $entity->save();
+    }
+    $this->prepareIdMappings(array('d6_custom_block'  => array(array(array(1), array(1)))));
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_block');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Block.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test the block settings migration.
+   */
+  public function testBlockMigration() {
+    $blocks = entity_load_multiple('block');
+    $this->assertTrue(count($blocks));
+    // @TODO add more asserts.
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateBookConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateBookConfigsTest.php
index f3823e6..228b537 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateBookConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateBookConfigsTest.php
@@ -35,9 +35,10 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of book variables to book.settings.yml.
+   * {@inheritdoc}
    */
-  public function testBookSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_book_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6BookSettings.php',
@@ -45,6 +46,12 @@ public function testBookSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $executable->import();
+  }
+
+  /**
+   * Tests migration of book variables to book.settings.yml.
+   */
+  public function testBookSettings() {
     $config = \Drupal::config('book.settings');
     $this->assertIdentical($config->get('child_type'), 'book');
     $this->assertIdentical($config->get('block.navigation.mode'), 'all pages');
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCckFieldRevisionTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCckFieldRevisionTest.php
new file mode 100644
index 0000000..4f6c1f8
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCckFieldRevisionTest.php
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCckFieldRevisionTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Test cck field revision migration from Drupal 6 to 8.
+ */
+class MigrateCckFieldRevisionTest extends MigrateNodeTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('node', 'text');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate CCK field revisions',
+      'description'  => 'CCK field revision migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'field_test',
+      'type' => 'text',
+    ))->save();
+    entity_create('field_instance_config', array(
+      'entity_type' => 'node',
+      'field_name' => 'field_test',
+      'bundle' => 'story',
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'field_test_two',
+      'type' => 'integer',
+      'cardinality' => -1,
+    ))->save();
+    entity_create('field_instance_config', array(
+      'entity_type' => 'node',
+      'field_name' => 'field_test_two',
+      'bundle' => 'story',
+    ))->save();
+
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_cck_field_values' => array(
+        array(array(1), array(1)),
+      ),
+      'd6_node' => array(
+        array(array(1), array(1)),
+        array(array(2), array(2)),
+      ),
+      'd6_node_revision' => array(
+        array(array(1), array(1)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeRevision.php',
+    );
+    $this->loadDumps($dumps);
+
+    $migrations = entity_load_multiple('migration', array('d6_cck_field_revision:*'));
+    foreach ($migrations as $migration) {
+      $executable = new MigrateExecutable($migration, $this);
+      $executable->import();
+    }
+  }
+
+  /**
+   * Test CCK revision migration from Drupal 6 to 8.
+   */
+  public function testCckFieldRevision() {
+    $node = \Drupal::entityManager()->getStorageController('node')->loadRevision(2);
+    $this->assertEqual($node->id(), 1, 'Node 1 loaded.');
+    $this->assertEqual($node->getRevisionId(), 2, 'Node 1 revision 2loaded.');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCckFieldValuesTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCckFieldValuesTest.php
new file mode 100644
index 0000000..e9498ba
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCckFieldValuesTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCckFieldValuesTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Test cck field migration from Drupal 6 to 8.
+ */
+class MigrateCckFieldValuesTest extends MigrateNodeTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('node', 'text');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate CCK fields',
+      'description'  => 'CCK field content migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'field_test',
+      'type' => 'text',
+    ))->save();
+    entity_create('field_instance_config', array(
+      'entity_type' => 'node',
+      'field_name' => 'field_test',
+      'bundle' => 'story',
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'field_test_two',
+      'type' => 'integer',
+      'cardinality' => -1,
+    ))->save();
+    entity_create('field_instance_config', array(
+      'entity_type' => 'node',
+      'field_name' => 'field_test_two',
+      'bundle' => 'story',
+    ))->save();
+
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_field_formatter_settings' => array(
+        array(array('page', 'default', 'node', 'field_test'), array('node', 'page', 'default', 'field_test')),
+      ),
+      'd6_field_instance_widget_settings' => array(
+        array(array('page', 'field_test'), array('node', 'page', 'default', 'test')),
+      ),
+      'd6_node' => array(
+        array(array(1), array(1)),
+        array(array(2), array(2)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migrations = entity_load_multiple('migration', array('d6_cck_field_values:*'));
+    foreach ($migrations as $migration) {
+      $executable = new MigrateExecutable($migration, $this);
+      $executable->import();
+    }
+
+  }
+
+  /**
+   * Test CCK migration from Drupal 6 to 8.
+   */
+  public function testCckFields() {
+    $node = node_load(1);
+    $this->assertEqual($node->field_test->value, 'This is a text field', "Single field storage field is correct.");
+    $this->assertEqual($node->field_test_two->value, 10, 'Multi field storage field is correct');
+    $this->assertEqual($node->field_test_two[1]->value, 20, 'Multi field second value is correct.');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTest.php
new file mode 100644
index 0000000..f4fe8ca
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTest.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\comment\Entity\Comment;
+use Drupal\Core\Language\Language;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 to Drupal 6 comment migration.
+ */
+class MigrateCommentTest extends MigrateDrupalTestBase {
+
+  static $modules = array('node', 'comment');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comments.',
+      'description'  => 'Upgrade comments.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    entity_create('node_type', array('type' => 'page'))->save();
+    $node = entity_create('node', array(
+      'type' => 'page',
+      'nid' => 1,
+    ));
+    $node->enforceIsNew();
+    $node->save();
+    $id_mappings = array(
+      'd6_filter_format' => array(array(array(1), array('filtered_html'))),
+      'd6_node' => array(array(array(1), array(1))),
+      'd6_user' => array(array(array(0), array(0))),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    \Drupal::service('comment.manager')->addDefaultField('node', 'page');
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_comment');
+
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Comment.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 to Drupal 6 comment migration.
+   */
+  public function testComments() {
+    /** @var Comment $comment */
+    $comment = entity_load('comment', 1);
+    $this->assertEqual('The first comment.', $comment->subject->value);
+    $this->assertEqual('The first comment body.', $comment->comment_body->value);
+    $this->assertEqual('filtered_html', $comment->comment_body->format);
+    $this->assertEqual(0, $comment->pid->value);
+    $this->assertEqual(1, $comment->entity_id->value);
+    $this->assertEqual('node', $comment->entity_type->value);
+    $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $comment->language()->id);
+
+    $comment = entity_load('comment', 2);
+    $this->assertEqual('The response to the second comment.', $comment->subject->value);
+    $this->assertEqual(3, $comment->pid->value);
+
+    $comment = entity_load('comment', 3);
+    $this->assertEqual('The second comment.', $comment->subject->value);
+    $this->assertEqual(0, $comment->pid->value);
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableDisplayBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableDisplayBase.php
new file mode 100644
index 0000000..8878352
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableDisplayBase.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableDisplayBase.
+ */
+
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Base class for Drupal 6 comment variables to Drupal 8 entity display tests.
+ */
+class MigrateCommentVariableDisplayBase extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('comment', 'node');
+
+  /**
+   * The database dumps used.
+   *
+   * @var array
+   */
+  protected $dumps;
+
+  /**
+   * The node types being tested.
+   *
+   * @var array
+   */
+  protected $types = array('page', 'story');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'comment',
+      'type' => 'comment',
+      'translatable' => '0',
+    ))->save();
+    foreach ($this->types as $type) {
+      entity_create('node_type', array('type' => $type))->save();
+      entity_create('field_instance_config', array(
+        'label' => 'Comment settings',
+        'description' => '',
+        'field_name' => 'comment',
+        'entity_type' => 'node',
+        'bundle' => $type,
+        'required' => 1,
+      ))->save();
+    }
+    $this->dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php',
+    );
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', static::MIGRATION);
+    $this->prepare($migration, $this->dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityDisplay.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityDisplay.php
new file mode 100644
index 0000000..c702f0c
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityDisplay.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableEntityDisplay.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Tests comment variables migrated into an entity display.
+ */
+class MigrateCommentVariableEntityDisplay extends MigrateCommentVariableDisplayBase {
+
+  /**
+   * The migration to run.
+   */
+  const MIGRATION = 'd6_comment_entity_display';
+
+  /**
+   * The node types being used.
+   */
+  protected $types = array('page', 'story');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to entity displays,',
+      'description'  => 'Upgrade comment variables to entity.display.node.*.default.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * Tests comment variables migrated into an entity display.
+   */
+  public function testCommentEntityDisplay() {
+    foreach ($this->types as $type) {
+      $component = entity_get_display('node', $type, 'default')->getComponent('comment');
+      $this->assertEqual($component['label'], 'hidden');
+      $this->assertEqual($component['type'], 'comment_default');
+      $this->assertEqual($component['weight'], 20);
+    }
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityFormDisplay.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityFormDisplay.php
new file mode 100644
index 0000000..4d1700a
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityFormDisplay.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableEntityFormDisplay.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Tests comment variables migrated into an entity display.
+ */
+class MigrateCommentVariableEntityFormDisplay extends MigrateCommentVariableDisplayBase {
+
+  /**
+   * The migration to run.
+   */
+  const MIGRATION = 'd6_comment_entity_form_display';
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to entity form displays,',
+      'description'  => 'Upgrade comment variables to entity.form_display.node.*.default.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * Tests comment variables migrated into an entity display.
+   */
+  public function testCommentEntityFormDisplay() {
+    foreach ($this->types as $type) {
+      $component = entity_get_form_display('node', $type, 'default')->getComponent('comment');
+      $this->assertEqual($component['type'], 'comment_default');
+      $this->assertEqual($component['weight'], 20);
+    }
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableField.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableField.php
new file mode 100644
index 0000000..6c5d11d
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableField.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableField.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests comment variables migrated into a field entity.
+ */
+class MigrateCommentVariableField extends MigrateDrupalTestBase {
+
+  static $modules = array('comment', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to a field,',
+      'description'  => 'Upgrade comment variables  to field.field.node.comment.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    foreach (array('page', 'story', 'test') as $type) {
+      entity_create('node_type', array('type' => $type))->save();
+    }
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_comment_field');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests comment variables migrated into a field entity.
+   */
+  public function testCommentField() {
+    $this->assertTrue(is_object(entity_load('field_config', 'node.comment')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableInstance.php
new file mode 100644
index 0000000..ea268cf
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableInstance.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableInstance.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests comment variables migrated into a field instance.
+ */
+class MigrateCommentVariableInstance extends MigrateDrupalTestBase {
+
+  static $modules = array('comment', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to a field instance,',
+      'description'  => 'Upgrade comment variables to field.instance.node.*.comment.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_comment_field' => array(
+        array(array('page'), array('node', 'page')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    foreach (array('page', 'story') as $type) {
+      entity_create('node_type', array('type' => $type))->save();
+    }
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+        'name' => 'comment',
+        'type' => 'comment',
+        'translatable' => '0',
+    ))->save();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_comment_field_instance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test the migrated field instance values.
+   */
+  public function testCommentFieldInstance() {
+    $node = entity_create('node', array('type' => 'page'));
+    $this->assertEqual($node->comment->status, 0);
+    $node = entity_create('node', array('type' => 'story'));
+    $this->assertEqual($node->comment->status, 2);
+    $settings = $node->comment->getFieldDefinition()->getSettings();
+    $this->assertEqual($settings['default_mode'], 2);
+    $this->assertEqual($settings['per_page'], 70);
+    $this->assertEqual($settings['anonymous'], 1);
+    $this->assertEqual($settings['subject'], 0);
+    $this->assertEqual($settings['form_location'], 0);
+    $this->assertEqual($settings['preview'], 0);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateContactCategoryTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateContactCategoryTest.php
new file mode 100644
index 0000000..f46884c
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateContactCategoryTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateContactCategoryTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * The Drupal 6 contact categories to Drupal 8 migration.
+ */
+class MigrateContactCategoryTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('contact');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate contact categories.',
+      'description'  => 'Migrate contact categories to contact.category.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_contact_category');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactCategory.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * The Drupal 6 contact categories to Drupal 8 migration.
+   */
+  public function testContactCategory() {
+    /** @var \Drupal\contact\Entity\Category $contact_category */
+    $contact_category = entity_load('contact_category', 'website_feedback');
+    $this->assertEqual($contact_category->label, 'Website feedback');
+    $this->assertEqual($contact_category->recipients, 'admin@example.com');
+    $this->assertEqual($contact_category->reply, '');
+    $this->assertEqual($contact_category->weight, 0);
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateContactConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateContactConfigsTest.php
index 179b9e1..0c2790d 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateContactConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateContactConfigsTest.php
@@ -35,9 +35,10 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of aggregator variables to aggregator.settings.yml.
+   * {@inheritdoc}
    */
-  public function testContactSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_contact_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactSettings.php',
@@ -45,6 +46,12 @@ public function testContactSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $executable->import();
+  }
+
+  /**
+   * Tests migration of aggregator variables to aggregator.settings.yml.
+   */
+  public function testContactSettings() {
     $config = \Drupal::config('contact.settings');
     $this->assertIdentical($config->get('user_default_enabled'), true);
     $this->assertIdentical($config->get('flood.limit'), 3);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCustomBlockTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCustomBlockTest.php
new file mode 100644
index 0000000..7620793
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCustomBlockTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCustomBlockTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\Core\Language\Language;
+use Drupal\custom_block\Entity\CustomBlock;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 custom block to Drupal 8 migration.
+ */
+class MigrateCustomBlockTest extends MigrateDrupalTestBase {
+
+  static $modules = array('block', 'custom_block');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate custom blocks.',
+      'description'  => 'Upgrade custom blocks.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $this->prepareIdMappings(array(
+      'd6_filter_format' => array(
+        array(array(2), array('full_html'))
+      )
+    ));
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_custom_block');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Box.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 custom block to Drupal 8 migration.
+   */
+  public function testBlockMigration() {
+    /** @var CustomBlock $block */
+    $block = entity_load('custom_block', 1);
+    $this->assertEqual('My block 1', $block->label());
+    $this->assertEqual(1, $block->getRevisionId());
+    $this->assertTrue(REQUEST_TIME <= $block->getChangedTime() && $block->getChangedTime() <= time());
+    $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $block->language()->id);
+    $this->assertEqual('<h3>My custom block body</h3>', $block->body->value);
+    $this->assertEqual('full_html', $block->body->format);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDateFormatTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDateFormatTest.php
new file mode 100644
index 0000000..41e7cdc
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDateFormatTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+use Drupal\Core\Database\Database;
+
+/**
+ * Tests the Drupal 6 date formats to Drupal 8 migration.
+ */
+class MigrateDateFormatTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate date formats to system.date_format.*.yml',
+      'description'  => 'Upgrade date formats to system.date_format.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_date_formats');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DateFormat.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 date formats to Drupal 8 migration.
+   */
+  public function testDateFormats() {
+    $short_date_format = entity_load('date_format', 'short');
+    $this->assertEqual('\S\H\O\R\T m/d/Y - H:i', $short_date_format->getPattern(DrupalDateTime::PHP));
+
+    $medium_date_format = entity_load('date_format', 'medium');
+    $this->assertEqual('\M\E\D\I\U\M D, m/d/Y - H:i', $medium_date_format->getPattern(DrupalDateTime::PHP));
+
+    $long_date_format = entity_load('date_format', 'long');
+    $this->assertEqual('\L\O\N\G l, F j, Y - H:i', $long_date_format->getPattern(DrupalDateTime::PHP));
+
+    // Test that we can re-import using the EntityDateFormat destination.
+    Database::getConnection('default', 'migrate')
+      ->update('variable')
+      ->fields(array('value' => serialize('\S\H\O\R\T d/m/Y - H:i')))
+      ->condition('name', 'date_format_short')
+      ->execute();
+    db_truncate(entity_load('migration', 'd6_date_formats')->getIdMap()->mapTableName())->execute();
+    $migration = entity_load_unchanged('migration', 'd6_date_formats');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+    $short_date_format = entity_load('date_format', 'short');
+    $this->assertEqual('\S\H\O\R\T d/m/Y - H:i', $short_date_format->getPattern(DrupalDateTime::PHP));
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDblogConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDblogConfigsTest.php
index ecfa088..7bfda84 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDblogConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDblogConfigsTest.php
@@ -35,9 +35,10 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of dblog variables to dblog.settings.yml.
+   * {@inheritdoc}
    */
-  public function testBookSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_dblog_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DblogSettings.php',
@@ -45,6 +46,12 @@ public function testBookSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $executable->import();
+  }
+
+  /**
+   * Tests migration of dblog variables to dblog.settings.yml.
+   */
+  public function testBookSettings() {
     $config = \Drupal::config('dblog.settings');
     $this->assertIdentical($config->get('row_limit'), 1000);
   }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDrupal6Test.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDrupal6Test.php
new file mode 100644
index 0000000..81e8ec9
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDrupal6Test.php
@@ -0,0 +1,352 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateDrupal6Test.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+use Drupal\simpletest\TestBase;
+
+/**
+ * Test the complete Drupal 6 migration.
+ */
+class MigrateDrupal6Test extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array(
+    'action',
+    'aggregator',
+    'block',
+    'book',
+    'comment',
+    'contact',
+    'custom_block',
+    'datetime',
+    'dblog',
+    'email',
+    'file',
+    'forum',
+    'image',
+    'link',
+    'locale',
+    'menu',
+    'node',
+    'number',
+    'options',
+    'search',
+    'simpletest',
+    'syslog',
+    'taxonomy',
+    'telephone',
+    'text',
+    'update',
+    'views',
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate Drupal 6',
+      'description'  => 'Test every Drupal 6 migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function tearDown() {
+    // Move the results of every class under ours. This is solely for
+    // reporting, the filename will guide developers.
+    self::getDatabaseConnection()
+      ->update('simpletest')
+      ->fields(array('test_class' => get_class($this)))
+      ->condition('test_id', $this->testId)
+      ->execute();
+    parent::tearDown();
+  }
+
+
+  /**
+   * Test the complete Drupal 6 migration.
+   */
+  public function testDrupal6() {
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ActionSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorFeed.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorItem.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Block.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6BookSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Box.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Comment.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactCategory.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ContactSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DateFormat.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6DblogSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6File.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FileSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FilterFormat.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ForumSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6LocaleSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Menu.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6MenuSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeBodyInstance.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeRevision.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeType.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchPage.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SimpletestSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6StatisticsSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SyslogSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemCron.php',
+      // This dump contains the file directory path to the simpletest directory
+      // where the files are.
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFilter.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImageGd.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImage.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemMaintenance.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemPerformance.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemRss.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemSite.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemTheme.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomySettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyTerm.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TermNode.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TextSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UpdateSettings.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadInstance.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Upload.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UrlAlias.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserMail.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6User.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php',
+    );
+    $this->loadDumps($dumps);
+    $migrations = array(
+      'd6_action_settings',
+      'd6_aggregator_settings',
+      'd6_aggregator_feed',
+      'd6_aggregator_item',
+      'd6_block',
+      'd6_book_settings',
+      'd6_cck_field_values:*',
+      'd6_cck_field_revision:*',
+      'd6_comment',
+      'd6_comment_entity_display',
+      'd6_comment_entity_form_display',
+      'd6_comment_field',
+      'd6_comment_field_instance',
+      'd6_contact_category',
+      'd6_contact_settings',
+      'd6_custom_block',
+      'd6_date_formats',
+      'd6_dblog_settings',
+      'd6_field',
+      'd6_field_instance',
+      'd6_field_instance_widget_settings',
+      'd6_field_settings',
+      'd6_field_formatter_settings',
+      'd6_file_settings',
+      'd6_file',
+      'd6_filter_format',
+      'd6_forum_settings',
+      'd6_locale_settings',
+      'd6_menu_settings',
+      'd6_menu',
+      'd6_node_revision',
+      'd6_node',
+      'd6_node_settings',
+      'd6_node_type',
+      'd6_profile_values:user',
+      'd6_search_page',
+      'd6_search_settings',
+      'd6_simpletest_settings',
+      'd6_statistics_settings',
+      'd6_syslog_settings',
+      'd6_system_cron',
+      'd6_system_file',
+      'd6_system_filter',
+      'd6_system_image',
+      'd6_system_image_gd',
+      'd6_system_maintenance',
+      'd6_system_performance',
+      'd6_system_rss',
+      'd6_system_site',
+      'd6_system_theme',
+      'd6_taxonomy_settings',
+      'd6_taxonomy_term',
+      'd6_taxonomy_vocabulary',
+      'd6_term_node_revision:*',
+      'd6_term_node:*',
+      'd6_text_settings',
+      'd6_update_settings',
+      'd6_upload_entity_display',
+      'd6_upload_entity_form_display',
+      'd6_upload_field',
+      'd6_upload_field_instance',
+      'd6_upload',
+      'd6_url_alias',
+      'd6_user_mail',
+      'd6_user_profile_field_instance',
+      'd6_user_profile_entity_display',
+      'd6_user_profile_entity_form_display',
+      'd6_user_profile_field',
+      'd6_user_picture_entity_display',
+      'd6_user_picture_entity_form_display',
+      'd6_user_picture_field_instance',
+      'd6_user_picture_field',
+      'd6_user_picture_file',
+      'd6_user_role',
+      'd6_user',
+      'd6_view_modes',
+      'd6_vocabulary_entity_display',
+      'd6_vocabulary_entity_form_display',
+      'd6_vocabulary_field_instance',
+      'd6_vocabulary_field',
+    );
+    $classes = array(
+      __NAMESPACE__ . '\MigrateActionConfigsTest',
+      __NAMESPACE__ . '\MigrateAggregatorConfigsTest',
+      __NAMESPACE__ . '\MigrateAggregatorFeedTest',
+      __NAMESPACE__ . '\MigrateAggregatorItemTest',
+      __NAMESPACE__ . '\MigrateBlockTest',
+      __NAMESPACE__ . '\MigrateBookConfigsTest',
+      __NAMESPACE__ . '\MigrateCckFieldValuesTest',
+      __NAMESPACE__ . '\MigrateCckFieldRevisionTest',
+      __NAMESPACE__ . '\MigrateCommentTest',
+      __NAMESPACE__ . '\MigrateCommentVariableEntityDisplay',
+      __NAMESPACE__ . '\MigrateCommentVariableEntityFormDisplay',
+      __NAMESPACE__ . '\MigrateCommentVariableField',
+      __NAMESPACE__ . '\MigrateCommentVariableInstance',
+      __NAMESPACE__ . '\MigrateContactCategoryTest',
+      __NAMESPACE__ . '\MigrateContactConfigsTest',
+      __NAMESPACE__ . '\MigrateCustomBlockTest',
+      __NAMESPACE__ . '\MigrateDateFormatTest',
+      __NAMESPACE__ . '\MigrateDblogConfigsTest',
+      __NAMESPACE__ . '\MigrateFieldConfigsTest',
+      __NAMESPACE__ . '\MigrateFieldTest',
+      __NAMESPACE__ . '\MigrateFieldInstanceTest',
+      __NAMESPACE__ . '\MigrateFieldFormatterSettingsTest',
+      __NAMESPACE__ . '\MigrateFieldWidgetSettingsTest',
+      __NAMESPACE__ . '\MigrateFileConfigsTest',
+      __NAMESPACE__ . '\MigrateFileTest',
+      __NAMESPACE__ . '\MigrateFilterFormatTest',
+      __NAMESPACE__ . '\MigrateForumConfigsTest',
+      __NAMESPACE__ . '\MigrateLocaleConfigsTest',
+      __NAMESPACE__ . '\MigrateMenuConfigsTest',
+      __NAMESPACE__ . '\MigrateMenuTest',
+      __NAMESPACE__ . '\MigrateNodeConfigsTest',
+      __NAMESPACE__ . '\MigrateNodeRevisionTest',
+      __NAMESPACE__ . '\MigrateNodeTest',
+      __NAMESPACE__ . '\MigrateNodeTypeTest',
+      __NAMESPACE__ . '\MigrateProfileValuesTest',
+      __NAMESPACE__ . '\MigrateSearchConfigsTest',
+      __NAMESPACE__ . '\MigrateSearchPageTest',
+      __NAMESPACE__ . '\MigrateSimpletestConfigsTest',
+      __NAMESPACE__ . '\MigrateStatisticsConfigsTest',
+      __NAMESPACE__ . '\MigrateSyslogConfigsTest',
+      __NAMESPACE__ . '\MigrateSystemCronTest',
+      __NAMESPACE__ . '\MigrateSystemFileTest',
+      __NAMESPACE__ . '\MigrateSystemFilterTest',
+      __NAMESPACE__ . '\MigrateSystemImageGdTest',
+      __NAMESPACE__ . '\MigrateSystemImageTest',
+      __NAMESPACE__ . '\MigrateSystemMaintenanceTest',
+      __NAMESPACE__ . '\MigrateSystemPerformanceTest',
+      __NAMESPACE__ . '\MigrateSystemRssTest',
+      __NAMESPACE__ . '\MigrateSystemSiteTest',
+      __NAMESPACE__ . '\MigrateSystemThemeTest',
+      __NAMESPACE__ . '\MigrateTaxonomyConfigsTest',
+      __NAMESPACE__ . '\MigrateTaxonomyTermTest',
+      __NAMESPACE__ . '\MigrateTaxonomyVocabularyTest',
+      __NAMESPACE__ . '\MigrateTermNodeRevisionTest',
+      __NAMESPACE__ . '\MigrateTermNodeTest',
+      __NAMESPACE__ . '\MigrateTextConfigsTest',
+      __NAMESPACE__ . '\MigrateUpdateConfigsTest',
+      __NAMESPACE__ . '\MigrateUploadEntityDisplayTest',
+      __NAMESPACE__ . '\MigrateUploadEntityFormDisplayTest',
+      __NAMESPACE__ . '\MigrateUploadFieldTest',
+      __NAMESPACE__ . '\MigrateUploadInstanceTest',
+      __NAMESPACE__ . '\MigrateUploadTest',
+      __NAMESPACE__ . '\MigrateUrlAliasTest',
+      __NAMESPACE__ . '\MigrateUserConfigsTest',
+      __NAMESPACE__ . '\MigrateUserProfileEntityDisplayTest',
+      __NAMESPACE__ . '\MigrateUserProfileEntityFormDisplayTest',
+      __NAMESPACE__ . '\MigrateUserProfileFieldTest',
+      __NAMESPACE__ . '\MigrateUserProfileFieldInstanceTest',
+      __NAMESPACE__ . '\MigrateUserPictureEntityDisplayTest',
+      __NAMESPACE__ . '\MigrateUserPictureEntityFormDisplayTest',
+      __NAMESPACE__ . '\MigrateUserPictureFileTest',
+      __NAMESPACE__ . '\MigrateUserPictureFieldTest',
+      __NAMESPACE__ . '\MigrateUserPictureInstanceTest',
+      __NAMESPACE__ . '\MigrateUserRoleTest',
+      __NAMESPACE__ . '\MigrateUserTest',
+      __NAMESPACE__ . '\MigrateViewModesTest',
+      __NAMESPACE__ . '\MigrateVocabularyEntityDisplayTest',
+      __NAMESPACE__ . '\MigrateVocabularyEntityFormDisplayTest',
+      __NAMESPACE__ . '\MigrateVocabularyFieldInstanceTest',
+      __NAMESPACE__ . '\MigrateVocabularyFieldTest',
+    );
+    // Run every migration in the order specified by the storage controller.
+    foreach (entity_load_multiple('migration', $migrations) as $migration) {
+      (new MigrateExecutable($migration, $this))->import();
+    }
+    foreach ($classes as $class) {
+      $test_object = new $class($this->testId);
+      $test_object->databasePrefix = $this->databasePrefix;
+      $test_object->container = $this->container;
+      // run() does a lot of setup and tear down work which we don't need:
+      // it would setup a new database connection and wouldn't find the
+      // Drupal 6 dump. Also by skipping the setUp() methods there are no id
+      // mappings or entities prepared. The tests run against solely migrated
+      // data.
+      foreach (get_class_methods($test_object) as $method) {
+        if (strtolower(substr($method, 0, 4)) == 'test') {
+          // Insert a fail record. This will be deleted on completion to ensure
+          // that testing completed.
+          $method_info = new \ReflectionMethod($class, $method);
+          $caller = array(
+            'file' => $method_info->getFileName(),
+            'line' => $method_info->getStartLine(),
+            'function' => $class . '->' . $method . '()',
+          );
+          $completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, 'The test did not complete due to a fatal error.', 'Completion check', $caller);
+          // Run the test method.
+          try {
+            $test_object->$method();
+          }
+          catch (\Exception $e) {
+            $this->exceptionHandler($e);
+          }
+          // Remove the completion check record.
+          TestBase::deleteAssert($completion_check_id);
+        }
+      }
+      // Add the pass/fail/exception/debug results.
+      foreach ($this->results as $key => &$value) {
+        $value += $test_object->results[$key];
+      }
+    }
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldConfigsTest.php
index 0192130..d5647e3 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -28,16 +27,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of field variables to field.settings.yml.
+   * {@inheritdoc}
    */
-  public function testFieldSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_field_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of field variables to field.settings.yml.
+   */
+  public function testFieldSettings() {
     $config = \Drupal::config('field.settings');
     $this->assertIdentical($config->get('language_fallback'), TRUE);
   }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldFormatterSettingsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldFormatterSettingsTest.php
new file mode 100644
index 0000000..c1d5961
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldFormatterSettingsTest.php
@@ -0,0 +1,211 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\d6\MigrateFieldInstanceEntityDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Test formatter settings to display modes.
+ */
+class MigrateFieldFormatterSettingsTest extends MigrateDrupalTestBase {
+
+  static $modules = array('node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate field formatter settings to entity.display.*.*.yml',
+      'description'  => 'Upgrade field formatter settings to entity.display.*.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_view_modes' => array(
+        array(array(1), array('node', 'preview')),
+        array(array(4), array('node', 'rss')),
+        array(array('teaser'), array('node', 'teaser')),
+        array(array('full'), array('node', 'full')),
+      ),
+      'd6_field_instance' => array(
+        array(array('fieldname', 'page'), array('node', 'fieldname', 'page')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_field_formatter_settings');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test that migrated entity display settings can be loaded using D8 API's.
+   */
+  public function testEntityDisplaySettings() {
+    // Run tests.
+    $field_name = "field_test";
+    $expected = array(
+      'weight' => 1,
+      'label' => 'above',
+      'type' => 'text_trimmed',
+      'settings' => array('trim_length' => 600),
+    );
+
+    // Make sure we don't have the excluded print entity display.
+    $display = entity_load('entity_view_display', 'node.story.print');
+    $this->assertNull($display, "Print entity display not found.");
+    // Can we load any entity display.
+    $display = entity_load('entity_view_display', 'node.story.teaser');
+    $this->assertEqual($display->getComponent($field_name), $expected);
+
+    // Test migrate worked with multiple bundles.
+    $display = entity_load('entity_view_display', 'node.article.teaser');
+    $this->assertEqual($display->getComponent($field_name), $expected);
+
+    // Test RSS because that has been converted from 4 to rss.
+    $display = entity_load('entity_view_display', 'node.story.rss');
+    $this->assertEqual($display->getComponent($field_name), $expected);
+
+    // Test the full format with text_default which comes from a static map.
+    $expected['type'] = 'text_default';
+    $expected['settings'] = array();
+    $display = entity_load('entity_view_display', 'node.story.full');
+    $this->assertEqual($display->getComponent($field_name), $expected);
+
+    // Check that we can migrate multiple fields.
+    $content = $display->get('content');
+    $this->assertTrue(isset($content['field_test']), 'Settings for field_test exist.');
+    $this->assertTrue(isset($content['field_test_two']), "Settings for field_test_two exist.");
+
+    // Test the number field formatter settings are correct.
+    $expected['weight'] = 2;
+    $expected['type'] = 'number_integer';
+    $expected['settings'] = array(
+      'scale' => 0,
+      'decimal_separator' => '.',
+      'thousand_separator' => ',',
+      'prefix_suffix' => TRUE,
+    );
+    $component = $display->getComponent('field_test_two');
+    $this->assertEqual($component, $expected);
+    $expected['weight'] = 3;
+    $expected['type'] = 'number_decimal';
+    $expected['settings']['scale'] = 2;
+    $component = $display->getComponent('field_test_three');
+    $this->assertEqual($component, $expected);
+
+    // Test the email field formatter settings are correct.
+    $expected['weight'] = 4;
+    $expected['type'] = 'email_mailto';
+    $expected['settings'] = array();
+    $component = $display->getComponent('field_test_email');
+    $this->assertEqual($component, $expected);
+
+    // Test the link field formatter settings.
+    $expected['weight'] = 5;
+    $expected['type'] = 'link';
+    $expected['settings'] = array(
+      'trim_length' => 80,
+      'url_only' => 1,
+      'url_plain' => 1,
+      'rel' => 0,
+      'target' => 0,
+    );
+    $component = $display->getComponent('field_test_link');
+    $this->assertEqual($component, $expected, "node.story.full field_test_link has correct absolute link settings.");
+    $expected['settings']['url_only'] = 0;
+    $expected['settings']['url_plain'] = 0;
+    $display = entity_load('entity_view_display', 'node.story.teaser');
+    $component = $display->getComponent('field_test_link');
+    $this->assertEqual($component, $expected, "node.story.teaser field_test_link has correct default link settings.");
+
+    // Test the file field formatter settings.
+    $expected['weight'] = 7;
+    $expected['type'] = 'file_default';
+    $expected['settings'] = array();
+    $component = $display->getComponent('field_test_filefield');
+    $this->assertEqual($component, $expected, "node.story.teaser field_test_filefield is of type file_default.");
+    $display = entity_load('entity_view_display', 'node.story.full');
+    $expected['type'] = 'file_url_plain';
+    $component = $display->getComponent('field_test_filefield');
+    $this->assertEqual($component, $expected, "node.story.full field_test_filefield is of type file_url_plain.");
+
+    // Test the image field formatter settings.
+    $expected['weight'] = 8;
+    $expected['type'] = 'image';
+    $expected['settings'] = array('image_style' => '', 'image_link' => '');
+    $component = $display->getComponent('field_test_imagefield');
+    $this->assertEqual($component, $expected, "node.story.full field_test_imagefield is of type image with the correct settings.");
+    $display = entity_load('entity_view_display', 'node.story.teaser');
+    $expected['settings']['image_link'] = 'file';
+    $component = $display->getComponent('field_test_imagefield');
+    $this->assertEqual($component, $expected, "node.story.teaser field_test_imagefield is of type image with the correct settings.");
+
+    // Test phone field.
+    $expected['weight'] = 9;
+    $expected['type'] = 'text_plain';
+    $expected['settings'] = array();
+    $component = $display->getComponent('field_test_phone');
+    $this->assertEqual($component, $expected, "node.story.teaser field_test_phone is of type text_plain.");
+
+    // Test date field.
+    $expected['weight'] = 10;
+    $expected['type'] = 'date_default';
+    $expected['settings'] = array('format' => 'fallback');
+    $component = $display->getComponent('field_test_date');
+    $this->assertEqual($component, $expected, "node.story.teaser field_test_date is of type date_default.");
+    $display = entity_load('entity_view_display', 'node.story.full');
+    $expected['settings']['format'] = 'long';
+    $component = $display->getComponent('field_test_date');
+    $this->assertEqual($component, $expected, "node.story.full field_test_date is of type date_default with correct settings.");
+
+    // Test date stamp field.
+    $expected['weight'] = 11;
+    $expected['settings']['format'] = 'fallback';
+    $component = $display->getComponent('field_test_datestamp');
+    $this->assertEqual($component, $expected, "node.story.full field_test_datestamp is of type date_default with correct settings.");
+    $display = entity_load('entity_view_display', 'node.story.teaser');
+    $expected['settings'] = array('format' => 'medium');
+    $component = $display->getComponent('field_test_datestamp');
+    $this->assertEqual($component, $expected, "node.story.teaser field_test_datestamp is of type date_default.");
+
+    // Test datetime field.
+    $expected['weight'] = 12;
+    $expected['settings'] = array('format' => 'short');
+    $component = $display->getComponent('field_test_datetime');
+    $this->assertEqual($component, $expected, "node.story.teaser field_test_datetime is of type date_default.");
+    $display = entity_load('entity_view_display', 'node.story.full');
+    $expected['settings']['format'] = 'fallback';
+    $component = $display->getComponent('field_test_datetime');
+    $this->assertEqual($component, $expected, "node.story.full field_test_datetime is of type date_default with correct settings.");
+
+    // Test a date field with a random format which should be mapped
+    // to date_default.
+    $display = entity_load('entity_view_display', 'node.story.rss');
+    $expected['settings']['format'] = 'fallback';
+    $component = $display->getComponent('field_test_datetime');
+    $this->assertEqual($component, $expected, "node.story.full field_test_datetime is of type date_default with correct settings.");
+    // Test that our Id map has the correct data.
+    $this->assertEqual(array('node', 'story', 'teaser', 'field_test'), entity_load('migration', 'd6_field_formatter_settings')->getIdMap()->lookupDestinationID(array('story', 'teaser', 'node', 'field_test')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldInstanceTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldInstanceTest.php
new file mode 100644
index 0000000..9b03333
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldInstanceTest.php
@@ -0,0 +1,155 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateFieldInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests migration of field instances.
+ */
+class MigrateFieldInstanceTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array(
+    'number',
+    'email',
+    'telephone',
+    'link',
+    'file',
+    'image',
+    'datetime',
+    'node',
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Migrate field instances to field.instance.*.*.*.yml',
+      'description' => 'Migrate field instances.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_field' => array(
+        array(array('field_name'), array('node', 'field_name')),
+      ),
+      'd6_node_type' => array(
+        array(array('page'), array('page')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_field_instance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+    );
+    $this->createFields();
+
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+  /*
+   * Tests migration of file variables to file.settings.yml.
+   */
+  public function testFieldInstanceSettings() {
+    $entity = entity_create('node', array('type' => 'story'));
+    // Test a text field.
+    $field = entity_load('field_instance_config', 'node.story.field_test');
+    $this->assertEqual($field->label(), 'Text Field');
+    $expected = array('max_length' => 255, 'text_processing' => 1);
+    $this->assertEqual($field->getSettings(), $expected);
+    $this->assertEqual('text for default value', $entity->field_test->value);
+
+    // Test a number field.
+    $field = entity_load('field_instance_config', 'node.story.field_test_two');
+    $this->assertEqual($field->label(), 'Integer Field');
+    $expected = array(
+      'min' => '10',
+      'max' => '100',
+      'prefix' => 'pref',
+      'suffix' => 'suf',
+    );
+    $this->assertEqual($field->getSettings(), $expected, 'Field field_test_two settings are correct.');
+
+    // Test email field.
+    $field = entity_load('field_instance_config', 'node.story.field_test_email');
+    $this->assertEqual($field->label(), 'Email Field');
+    $this->assertEqual('benjy@example.com', $entity->field_test_email->value, 'Field field_test_email default_value is correct.');
+
+    // Test a filefield.
+    $field = entity_load('field_instance_config', 'node.story.field_test_filefield');
+    $this->assertEqual($field->label(), 'File Field');
+    $expected = array(
+      'file_extensions' => 'txt pdf doc',
+      'file_directory' => 'images',
+      'description_field' => TRUE,
+      'max_filesize' => '200KB',
+      'target_type' => 'file',
+      'display_field' => FALSE,
+      'display_default' => FALSE,
+      'uri_scheme' => 'public',
+    );
+    // This is the only way to compare arrays.
+    $this->assertFalse(array_diff_assoc($field->getSettings(), $expected));
+    $this->assertFalse(array_diff_assoc($expected, $field->getSettings()));
+
+    // Test a link field.
+    $field = entity_load('field_instance_config', 'node.story.field_test_link');
+    $this->assertEqual($field->label(), 'Link Field');
+    $expected = array('title' => 2);
+    $this->assertEqual($field->getSettings(), $expected, 'Field field_test_link settings are correct.');
+    $this->assertEqual('default link title', $entity->field_test_link->title, 'Field field_test_link default title is correct.');
+    $this->assertEqual('http://drupal.org', $entity->field_test_link->url, 'Field field_test_link default title is correct.');
+
+  }
+
+  /**
+   * Helper to create fields.
+   */
+  protected function createFields() {
+    $fields = array(
+      'field_test' => 'text',
+      'field_test_two' => 'number_integer',
+      'field_test_three' => 'number_float',
+      'field_test_email' => 'email',
+      'field_test_link' => 'link',
+      'field_test_filefield' => 'file',
+      'field_test_imagefield' => 'image',
+      'field_test_phone' => 'telephone',
+      'field_test_date' => 'datetime',
+      'field_test_datestamp' => 'datetime',
+      'field_test_datetime' => 'datetime',
+    );
+    foreach ($fields as $name => $type) {
+      entity_create('field_config', array(
+        'name' => $name,
+        'entity_type' => 'node',
+        'type' => $type,
+      ))->save();
+    }
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldTest.php
new file mode 100644
index 0000000..2afb79b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldTest.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserRoleTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 field to Drupal 8 migration.
+ */
+class MigrateFieldTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('number', 'email', 'telephone', 'link', 'file', 'image', 'datetime', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate fields to field.*.*.yml',
+      'description'  => 'Migrate fields',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_field');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 field to Drupal 8 migration.
+   */
+  public function testFields() {
+    // Text field.
+    $field = entity_load('field_config', 'node.field_test');
+    $expected = array('max_length' => 255);
+    $this->assertEqual($field->type, "text", "Field type is text.");
+    $this->assertEqual($field->status, TRUE, "Status is TRUE");
+    $this->assertEqual($field->settings, $expected, "Field type text settings are correct");
+
+    // Integer field.
+    $field = entity_load('field_config', 'node.field_test_two');
+    $this->assertEqual($field->type, "number_integer", "Field type is number_integer.");
+
+    // Float field.
+    $field = entity_load('field_config', 'node.field_test_three');
+    $this->assertEqual($field->type, "number_float", "Field type is number_float.");
+
+    // Link field.
+    $field = entity_load('field_config', 'node.field_test_link');
+    $this->assertEqual($field->type, "link", "Field type is link.");
+
+    // File field.
+    $field = entity_load('field_config', 'node.field_test_filefield');
+    $this->assertEqual($field->type, "file", "Field type is file.");
+
+    /** @var \Drupal\field\Entity\FieldConfig $field */
+    $field = entity_load('field_config', 'node.field_test_imagefield');
+    $this->assertEqual($field->type, "image", "Field type is image.");
+    $settings = $field->getSettings();
+    $this->assertEqual($settings['column_groups']['alt']['label'], 'Test alt');
+    $this->assertEqual($settings['column_groups']['title']['label'], 'Test title');
+    $this->assertEqual($settings['target_type'], 'file');
+    $this->assertEqual($settings['uri_scheme'], 'public');
+    $this->assertEqual($settings['default_image']['fid'], '');
+    $this->assertEqual(array_filter($settings['default_image']), array());
+
+    // Phone field.
+    $field = entity_load('field_config', 'node.field_test_phone');
+    $this->assertEqual($field->type, "telephone", "Field type is telephone.");
+
+    // Date field.
+    $field = entity_load('field_config', 'node.field_test_datetime');
+    $this->assertEqual($field->type, "datetime", "Field type is datetime.");
+    $this->assertEqual($field->status, FALSE, "Status is FALSE");
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldWidgetSettingsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldWidgetSettingsTest.php
new file mode 100644
index 0000000..d8bf228
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFieldWidgetSettingsTest.php
@@ -0,0 +1,143 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateFieldWidgetSettingsTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests migration of field instances.
+ */
+class MigrateFieldWidgetSettingsTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array(
+    'number',
+    'email',
+    'telephone',
+    'link',
+    'file',
+    'image',
+    'datetime',
+    'node',
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Migrate field widget settings to entity.form_display.*.*.default.yml',
+      'description' => 'Migrate field widget settings.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_field_instance' => array(
+        array(array('fieldname', 'page'), array('node', 'fieldname', 'page')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+    $migration = entity_load('migration', 'd6_field_instance_widget_settings');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+  /**
+   * Test that migrated view modes can be loaded using D8 API's.
+   */
+  public function testWidgetSettings() {
+    // Test the config can be loaded.
+    $form_display = entity_load('entity_form_display', 'node.story.default');
+    $this->assertEqual(is_null($form_display), FALSE, "Form display node.story.default loaded with config.");
+
+    // Text field.
+    $component = $form_display->getComponent('field_test');
+    $expected = array('weight' => 1, 'type' => 'text_textfield');
+    $expected['settings'] = array('size' => 60, 'placeholder' => '');
+    $this->assertEqual($component, $expected, 'Text field settings are correct.');
+
+    // Integer field.
+    $component = $form_display->getComponent('field_test_two');
+    $expected['type'] = 'number';
+    $expected['weight'] = 2;
+    $expected['settings'] = array('placeholder' => '');
+    $this->assertEqual($component, $expected, 'Integer field settings are correct.');
+
+    // Float field.
+    $component = $form_display->getComponent('field_test_three');
+    $expected['weight'] = 3;
+    $this->assertEqual($component, $expected, 'Float field settings are correct.');
+
+    // Email field.
+    $component = $form_display->getComponent('field_test_email');
+    $expected['type'] = 'email_default';
+    $expected['weight'] = 4;
+    $this->assertEqual($component, $expected, 'Email field settings are correct.');
+
+    // Link field.
+    $component = $form_display->getComponent('field_test_link');
+    $this->assertEqual($component['type'], 'link_default');
+    $this->assertEqual($component['weight'], 5);
+    $this->assertFalse(array_filter($component['settings']));
+
+    // File field.
+    $component = $form_display->getComponent('field_test_filefield');
+    $expected['type'] = 'file_generic';
+    $expected['weight'] = 7;
+    $expected['settings'] = array('progress_indicator' => 'bar');
+    $this->assertEqual($component, $expected, 'File field settings are correct.');
+
+    // Image field.
+    $component = $form_display->getComponent('field_test_imagefield');
+    $expected['type'] = 'image_image';
+    $expected['weight'] = 8;
+    $expected['settings'] = array('progress_indicator' => 'bar', 'preview_image_style' => 'thumbnail');
+    $this->assertEqual($component, $expected, 'Image field settings are correct.');
+
+    // Phone field.
+    $component = $form_display->getComponent('field_test_phone');
+    $expected['type'] = 'telephone_default';
+    $expected['weight'] = 9;
+    $expected['settings'] = array('placeholder' => '');
+    $this->assertEqual($component, $expected, 'Phone field settings are correct.');
+
+    // Date fields.
+    $component = $form_display->getComponent('field_test_date');
+    $expected['type'] = 'datetime_default';
+    $expected['weight'] = 10;
+    $expected['settings'] = array();
+    $this->assertEqual($component, $expected, 'Date field settings are correct.');
+
+    $component = $form_display->getComponent('field_test_datestamp');
+    $expected['weight'] = 11;
+    $this->assertEqual($component, $expected, 'Date stamp field settings are correct.');
+
+    $component = $form_display->getComponent('field_test_datetime');
+    $expected['weight'] = 12;
+    $this->assertEqual($component, $expected, 'Datetime field settings are correct.');
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFileConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFileConfigsTest.php
index cb8d39c..e35fff9 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFileConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFileConfigsTest.php
@@ -35,9 +35,10 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of file variables to file.settings.yml.
+   * {@inheritdoc}
    */
-  public function testFileSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_file_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FileSettings.php',
@@ -45,6 +46,12 @@ public function testFileSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $executable->import();
+  }
+
+  /**
+   * Tests migration of file variables to file.settings.yml.
+   */
+  public function testFileSettings() {
     $config = \Drupal::config('file.settings');
     $this->assertIdentical($config->get('description.type'), 'textfield');
     $this->assertIdentical($config->get('description.length'), 128);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFileTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFileTest.php
new file mode 100644
index 0000000..f453641
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFileTest.php
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateFileTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 files to Drupal 8 migration.
+ */
+class MigrateFileTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('file');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Migrate files',
+      'description' => 'file migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6File.php',
+    );
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_file');
+    $migration->source['conf_path'] = 'core/modules/simpletest';
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+    $this->standalone = TRUE;
+  }
+
+  /**
+   * Tests the Drupal 6 files to Drupal 8 migration.
+   */
+  public function testFiles() {
+    /** @var \Drupal\file\FileInterface $file */
+    $file = entity_load('file', 1);
+    $this->assertEqual($file->getFilename(), 'Image1.png');
+    $this->assertEqual($file->getSize(), 39325);
+    $this->assertEqual($file->getFileUri(), 'public://image-1.png');
+    $this->assertEqual($file->getMimeType(), 'image/png');
+    // It is pointless to run the second half from MigrateDrupal6Test.
+    if (empty($this->standalone)) {
+      return;
+    }
+
+    // Test that we can re-import and also test with file_directory_path set.
+    db_truncate(entity_load('migration', 'd6_file')->getIdMap()->mapTableName())->execute();
+    $migration = entity_load_unchanged('migration', 'd6_file');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php',
+    );
+    $this->loadDumps($dumps, 'loadMigrateFileStandalone');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+    $file = entity_load('file', 2);
+    $this->assertEqual($file->getFileUri(), 'public://core/modules/simpletest/files/image-2.jpg');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFilterFormatTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFilterFormatTest.php
new file mode 100644
index 0000000..f718ffd
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateFilterFormatTest.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\MigrateD6FilterFormatTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 filter format to Drupal 8 migration.
+ */
+class MigrateFilterFormatTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  static $modules = array('filter');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate variables to filter.formats.*.yml',
+      'description'  => 'Upgrade variables to filter.formats.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_filter_format');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FilterFormat.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 filter format to Drupal 8 migration.
+   */
+  public function testFilterFormat() {
+    $filter_format = entity_load('filter_format', 'filtered_html');
+
+    // Check filter status.
+    $filters = $filter_format->get('filters');
+    $this->assertTrue($filters['filter_autop']['status']);
+    $this->assertTrue($filters['filter_url']['status']);
+    $this->assertTrue($filters['filter_htmlcorrector']['status']);
+    $this->assertTrue($filters['filter_html_escape']['status']);
+
+    // These should be false by default.
+    $this->assertFalse($filters['filter_html']['status']);
+    $this->assertFalse($filters['filter_caption']['status']);
+    $this->assertFalse($filters['filter_html_image_secure']['status']);
+
+    // Check variables migrated into filter.
+    $this->assertIdentical($filters['filter_html_escape']['settings']['allowed_html'], '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>');
+    $this->assertIdentical($filters['filter_html_escape']['settings']['filter_html_help'], '1');
+    $this->assertIdentical($filters['filter_html']['settings']['filter_html_nofollow'], false);
+    $this->assertIdentical($filters['filter_url']['settings']['filter_url_length'], 72);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateForumConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateForumConfigsTest.php
index e5a2426..9c564f9 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateForumConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateForumConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,16 +34,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of forum variables to forum.settings.yml.
+   * {@inheritdoc}
    */
-  public function testForumSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_forum_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6ForumSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of forum variables to forum.settings.yml.
+   */
+  public function testForumSettings() {
     $config = \Drupal::config('forum.settings');
     $this->assertIdentical($config->get('topics.hot_threshold'), 15);
     $this->assertIdentical($config->get('topics.page_limit'), 25);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateLocaleConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateLocaleConfigsTest.php
index b47a0da..4c633e1 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateLocaleConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateLocaleConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,16 +34,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of locale variables to locale.settings.yml.
+   * {@inheritdoc}
    */
-  public function testLocaleSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_locale_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6LocaleSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of locale variables to locale.settings.yml.
+   */
+  public function testLocaleSettings() {
     $config = \Drupal::config('locale.settings');
     $this->assertIdentical($config->get('cache_string'), 1);
     $this->assertIdentical($config->get('javascript.directory'), 'languages');
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateMenuConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateMenuConfigsTest.php
index ee96563..7e09ccb 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateMenuConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateMenuConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,16 +34,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of forum variables to forum.settings.yml.
+   * {@inheritdoc}
    */
-  public function testMenuSettings() {
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_menu_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6MenuSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of variables for the menu module.
+   */
+  public function testMenuSettings() {
     $config = \Drupal::config('menu.settings');
     $this->assertIdentical($config->get('main_links'), 'primary-links');
     $this->assertIdentical($config->get('secondary_links'), 'secondary-links');
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateMenuTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateMenuTest.php
new file mode 100644
index 0000000..95e95c7
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateMenuTest.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateMenuTest
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+use Drupal\Core\Database\Database;
+
+/**
+ * Tests the Drupal 6 menu to Drupal 8 migration.
+ */
+class MigrateMenuTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate menus',
+      'description'  => 'Upgrade menus to system.menu.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_menu');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Menu.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 menu to Drupal 8 migration.
+   */
+  public function testMenu() {
+    $navigation_menu = entity_load('menu', 'navigation');
+    $this->assertEqual($navigation_menu->id(), 'navigation');
+    $this->assertEqual($navigation_menu->label(), 'Navigation');
+    $this->assertEqual($navigation_menu->description , 'The navigation menu is provided by Drupal and is the main interactive menu for any site. It is usually the only menu that contains personalized links for authenticated users, and is often not even visible to anonymous users.');
+
+    // Test that we can re-import using the ConfigEntityBase destination.
+    Database::getConnection('default', 'migrate')
+      ->update('menu_custom')
+      ->fields(array('title' => 'Home Navigation'))
+      ->condition('menu_name', 'navigation')
+      ->execute();
+
+    db_truncate(entity_load('migration', 'd6_menu')->getIdMap()->mapTableName())->execute();
+    $migration = entity_load_unchanged('migration', 'd6_menu');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+    $navigation_menu = entity_load_unchanged('menu', 'navigation');
+    $this->assertEqual($navigation_menu->label(), 'Home Navigation');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeConfigsTest.php
index d24ed35..a20ba71 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeConfigsTest.php
@@ -11,6 +11,9 @@
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
+/**
+ * Tests Drupal 6 node settings to Drupal 8 migration.
+ */
 class MigrateNodeConfigsTest extends MigrateDrupalTestBase {
 
   /**
@@ -31,7 +34,11 @@ public static function getInfo() {
     );
   }
 
-  function testNodeSettings() {
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_node_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeSettings.php',
@@ -39,6 +46,12 @@ function testNodeSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage);
     $executable->import();
+  }
+
+  /**
+   * Tests Drupal 6 node settings to Drupal 8 migration.
+   */
+  public function testNodeSettings() {
     $config = \Drupal::config('node.settings');
     $this->assertIdentical($config->get('use_admin_theme'), false);
   }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeRevisionTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeRevisionTest.php
new file mode 100644
index 0000000..0a1b703
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeRevisionTest.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateNodeRevisionTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Test node revisions migration from Drupal 6 to 8.
+ */
+class MigrateNodeRevisionTest extends MigrateNodeTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate nodes',
+      'description'  => 'Node content revisions migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $id_mappings = array(
+      'd6_node' => array(
+        array(array(1), array(1)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeRevision.php',
+    );
+    $this->loadDumps($dumps);
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_node_revision');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test node revisions migration from Drupal 6 to 8.
+   */
+  public function testNodeRevision() {
+    $node = \Drupal::entityManager()->getStorageController('node')->loadRevision(2);
+    $this->assertEqual($node->id(), 1, 'Node 1 loaded.');
+    $this->assertEqual($node->getRevisionId(), 2, 'Node 1 revision 2loaded.');
+    $this->assertEqual($node->body->value, 'test rev 2');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTest.php
new file mode 100644
index 0000000..e08d85f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTest.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateNodeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\Core\Database\Database;
+
+/**
+ * Test node migration from Drupal 6 to 8.
+ */
+class MigrateNodeTest extends MigrateNodeTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate nodes',
+      'description'  => 'Node content migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_node');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+    // This is required for the second import below.
+    db_truncate($migration->getIdMap()->mapTableName())->execute();
+    $this->standalone = TRUE;
+  }
+
+  /**
+   * Test node migration from Drupal 6 to 8.
+   */
+  public function testNode() {
+    $node = node_load(1);
+    $this->assertEqual($node->id(), 1, 'Node 1 loaded.');
+    $this->assertEqual($node->body->value, 'test');
+    $this->assertEqual($node->body->format, 'filtered_html');
+    $this->assertEqual($node->getType(), 'story', 'Node has the correct bundle.');
+    $this->assertEqual($node->getTitle(), 'Test title', 'Node has the correct title.');
+    $this->assertEqual($node->getCreatedTime(), 1388271197, 'Node has the correct created time.');
+    $this->assertEqual($node->isSticky(), FALSE);
+    $this->assertEqual($node->getOwnerId(), 1);
+    //$this->assertEqual($node->getRevisionCreationTime(), 1390095701, 'Node has the correct revision timestamp.');
+
+    // It is pointless to run the second half from MigrateDrupal6Test.
+    if (empty($this->standalone)) {
+      return;
+    }
+
+    // Test that we can re-import using the EntityContentBase destination.
+    $connection = Database::getConnection('default', 'migrate');
+    $connection->update('node_revisions')
+      ->fields(array(
+        'title' => 'New node title',
+        'format' => 2,
+      ))
+      ->condition('vid', 1)
+      ->execute();
+    $connection->delete('content_field_test_two')
+      ->condition('delta', 1)
+      ->execute();
+
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_node');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+    $node = node_load(1);
+    $this->assertEqual($node->getTitle(), 'New node title');
+    // Test a multi-column fields are correctly upgraded.
+    $this->assertEqual($node->body->value, 'test');
+    $this->assertEqual($node->body->format, 'full_html');
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTestBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTestBase.php
new file mode 100644
index 0000000..48e9d0a
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTestBase.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateNodeTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateNodeTestBase extends MigrateDrupalTestBase {
+
+  static $modules = array('node');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $node_type = entity_create('node_type', array('type' => 'story'));
+    $node_type->save();
+    node_add_body_field($node_type);
+
+    $id_mappings = array(
+      'd6_node_type' => array(
+        array(array('test_story'), array('story')),
+      ),
+      'd6_filter_format' => array(
+        array(array(1), array('filtered_html')),
+        array(array(2), array('full_html')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    // Create a test node.
+    $node = entity_create('node', array(
+      'type' => 'story',
+      'nid' => 1,
+      'vid' => 1,
+    ));
+    $node->enforceIsNew();
+    $node->save();
+
+    // Load dumps.
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeType.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+    );
+    $this->loadDumps($dumps);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTypeTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTypeTest.php
new file mode 100644
index 0000000..857d6de
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTypeTest.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateNodeTypeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests Drupal 6 node type to Drupal 8 migration.
+ */
+class MigrateNodeTypeTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Migrate node type to node.type.*.yml',
+      'description' => 'Upgrade node types to node.type.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_node_type');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeType.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests Drupal 6 node type to Drupal 8 migration.
+   */
+  public function testNodeType() {
+    $migration = entity_load('migration', 'd6_node_type');
+    // Test the test_page content type.
+    $node_type_page = entity_load('node_type', 'test_page');
+    $this->assertEqual($node_type_page->id(), 'test_page', 'Node type test_page loaded');
+    $expected = array(
+      'options' => array(
+        'status' => TRUE,
+        'promote' => TRUE,
+        'sticky' => FALSE,
+        'revision' => FALSE,
+      ),
+      'preview' => 1,
+      'submitted' => TRUE,
+    );
+
+    $this->assertEqual($node_type_page->settings['node'], $expected, 'Node type test_page settings correct.');
+    $this->assertEqual(array('test_page'), $migration->getIdMap()->lookupDestinationID(array('test_page')));
+
+    // Test we have a body field.
+    $instance = field_info_instance('node', 'body', 'test_page');
+    $this->assertEqual($instance->getLabel(), 'Body', 'Body field was found.');
+
+    // Test the test_story content type.
+    $node_type_story = entity_load('node_type', 'test_story');
+    $this->assertEqual($node_type_story->id(), 'test_story', 'Node type test_story loaded');
+    $expected = array(
+      'options' => array(
+        'status' => TRUE,
+        'promote' => TRUE,
+        'sticky' => FALSE,
+        'revision' => FALSE,
+      ),
+      'preview' => 1,
+      'submitted' => TRUE,
+    );
+    $this->assertEqual($node_type_page->settings['node'], $expected, 'Node type test_page settings correct.');
+    $this->assertEqual(array('test_story'), $migration->getIdMap()->lookupDestinationID(array('test_story')));
+
+    // Test we don't have a body field.
+    $instance = field_info_instance('node', 'body', 'test_story');
+    $this->assertEqual($instance, NULL, 'No body field found');
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateProfileValuesTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateProfileValuesTest.php
new file mode 100644
index 0000000..070db98
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateProfileValuesTest.php
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateProfileValuesTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\Dump\Drupal6User;
+use Drupal\migrate_drupal\Tests\Dump\Drupal6UserProfileFields;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests Drupal 6 profile values to Drupal 8 migration.
+ */
+class MigrateProfileValuesTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array(
+    'link',
+    'options',
+    'datetime',
+    'number',
+    'text',
+    'file',
+    'image',
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user profile values',
+      'description'  => 'User profile values migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Create some fields so the data gets stored.
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'profile_color',
+      'type' => 'text',
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'profile_biography',
+      'type' => 'text_long',
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'profile_sell_address',
+      'type' => 'list_integer',
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'profile_sold_to',
+      'type' => 'list_text',
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'profile_bands',
+      'type' => 'text',
+      'cardinality' => -1,
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'profile_blog',
+      'type' => 'link',
+    ))->save();
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'profile_birthdate',
+      'type' => 'datetime',
+    ))->save();
+
+    // Create the field instances.
+    foreach (Drupal6UserProfileFields::getData('profile_fields') as $field) {
+      entity_create('field_instance_config', array(
+        'label' => $field['title'],
+        'description' => '',
+        'field_name' => $field['name'],
+        'entity_type' => 'user',
+        'bundle' => 'user',
+        'required' => 0,
+      ))->save();
+    }
+
+    // Create some users to migrate the profile data to.
+    foreach (Drupal6User::getData('users') as $u) {
+      $user = entity_create('user', $u);
+      $user->enforceIsNew();
+      $user->save();
+    }
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_user_profile_field_instance' => array(
+        array(array(1), array('user', 'user', 'fieldname')),
+      ),
+      'd6_user_profile_entity_display' => array(
+        array(array(1), array('user', 'user', 'default', 'fieldname')),
+      ),
+      'd6_user_profile_entity_form_display' => array(
+        array(array(1), array('user', 'user', 'default', 'fieldname')),
+      ),
+      'd6_user' => array(
+        array(array(2), array(2)),
+        array(array(8), array(8)),
+        array(array(15), array(15)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    // Load database dumps to provide source data.
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6User.php',
+    );
+    $this->loadDumps($dumps);
+
+    // Migrate profile fields.
+    $migration_format = entity_load('migration', 'd6_profile_values:user');
+    $executable = new MigrateExecutable($migration_format, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests Drupal 6 profile values to Drupal 8 migration.
+   */
+  public function testUserProfileValues() {
+    $user = user_load(2);
+    $this->assertFalse(is_null($user));
+    $this->assertEqual($user->profile_color->value, 'red');
+    $this->assertEqual($user->profile_biography->value, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nulla sapien, congue nec risus ut, adipiscing aliquet felis. Maecenas quis justo vel nulla varius euismod. Quisque metus metus, cursus sit amet sem non, bibendum vehicula elit. Cras dui nisl, eleifend at iaculis vitae, lacinia ut felis. Nullam aliquam ligula volutpat nulla consectetur accumsan. Maecenas tincidunt molestie diam, a accumsan enim fringilla sit amet. Morbi a tincidunt tellus. Donec imperdiet scelerisque porta. Sed quis sem bibendum eros congue sodales. Vivamus vel fermentum est, at rutrum orci. Nunc consectetur purus ut dolor pulvinar, ut volutpat felis congue. Cras tincidunt odio sed neque sollicitudin, vehicula tempor metus scelerisque.');
+    $this->assertEqual($user->profile_sell_address->value, '1');
+    $this->assertEqual($user->profile_sold_to->value, 'Fitness spammers');
+    $this->assertEqual($user->profile_bands[0]->value, 'AC/DC');
+    $this->assertEqual($user->profile_bands[1]->value, 'Eagles');
+    #$this->assertEqual($user->profile_blog->url, 'http://example.com/blog');
+    $this->assertEqual($user->profile_birthdate->value, '1974-06-02');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSearchConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSearchConfigsTest.php
index ae05722..f1b86bd 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSearchConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSearchConfigsTest.php
@@ -30,14 +30,15 @@ public static function getInfo() {
     return array(
       'name'  => 'Migrate variables to search.settings.yml',
       'description'  => 'Upgrade variables to search.settings.yml',
-      'group' => 'Migrate',
+      'group' => 'Migrate Drupal',
     );
   }
 
   /**
-   * Tests migration of search variables to search.settings.yml.
+   * {@inheritdoc}
    */
-  public function testSearchSettings() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_search_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchSettings.php',
@@ -45,6 +46,12 @@ public function testSearchSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $executable->import();
+  }
+
+  /**
+   * Tests migration of search variables to search.settings.yml.
+   */
+  public function testSearchSettings() {
     $config = \Drupal::config('search.settings');
     $this->assertIdentical($config->get('index.minimum_word_size'), 3);
     $this->assertIdentical($config->get('index.overlap_cjk'), TRUE);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSearchPageTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSearchPageTest.php
new file mode 100644
index 0000000..6540099
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSearchPageTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSearchPageTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+use Drupal\Core\Database\Database;
+
+/**
+ * Tests Drupal 6 search settings to Drupal 8 search page entity migration.
+ */
+class MigrateSearchPageTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('node', 'search');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate search settings to search.page.*.yml',
+      'description'  => 'Upgrade search rank settings to search.page.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_search_page');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SearchPage.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests Drupal 6 search settings to Drupal 8 search page entity migration.
+   */
+  public function testSearchPage() {
+    $id = 'node_search';
+    /** @var \Drupal\search\Entity\SearchPage $search_page */
+    $search_page = entity_load('search_page', $id);
+    $this->assertEqual($search_page->id(), $id);
+    $configuration = $search_page->getPlugin()->getConfiguration();
+    $this->assertEqual($configuration['rankings'], array(
+      'comments' => 5,
+      'relevance' => 2,
+      'sticky' => 8,
+      'views' => 1,
+    ));
+    $this->assertEqual($search_page->getPath(), 'node');
+
+    // Test that we can re-import using the EntitySearchPage destination.
+    Database::getConnection('default', 'migrate')
+      ->update('variable')
+      ->fields(array('value' => serialize(4)))
+      ->condition('name', 'node_rank_comments')
+      ->execute();
+
+    $migration = entity_load_unchanged('migration', 'd6_search_page');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+    $search_page = entity_load('search_page', $id);
+    $configuration = $search_page->getPlugin()->getConfiguration();
+    $this->assertEqual($configuration['rankings']['comments'], 4);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSimpletestConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSimpletestConfigsTest.php
index ca88209..ab58367 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSimpletestConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSimpletestConfigsTest.php
@@ -35,9 +35,10 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of simpletest variables to simpletest.settings.yml.
+   * {@inheritdoc}
    */
-  public function testSimpletestSettings() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_simpletest_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SimpletestSettings.php',
@@ -45,6 +46,12 @@ public function testSimpletestSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $executable->import();
+  }
+
+  /**
+   * Tests migration of simpletest variables to simpletest.settings.yml.
+   */
+  public function testSimpletestSettings() {
     $config = \Drupal::config('simpletest.settings');
     $this->assertIdentical($config->get('clear_results'), TRUE);
     $this->assertIdentical($config->get('httpauth.method'), CURLAUTH_BASIC);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateStatisticsConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateStatisticsConfigsTest.php
index 44ae47b..c1c9e7d 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateStatisticsConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateStatisticsConfigsTest.php
@@ -35,9 +35,10 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of statistics variables to statistics.settings.yml.
+   * {@inheritdoc}
    */
-  public function testStatisticsSettings() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_statistics_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6StatisticsSettings.php',
@@ -45,6 +46,12 @@ public function testStatisticsSettings() {
     $this->prepare($migration, $dumps);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $executable->import();
+  }
+
+  /**
+   * Tests migration of statistics variables to statistics.settings.yml.
+   */
+  public function testStatisticsSettings() {
     $config = \Drupal::config('statistics.settings');
     $this->assertIdentical($config->get('access_log.enable'), 0);
     $this->assertIdentical($config->get('access_log.max_lifetime'), 259200);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSyslogConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSyslogConfigsTest.php
index 47546f2..971cf87 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSyslogConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSyslogConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,19 +34,25 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of syslog variables to syslog.settings.yml.
+   * {@inheritdoc}
    */
-  public function testSyslogSettings() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_syslog_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SyslogSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of syslog variables to syslog.settings.yml.
+   */
+  public function testSyslogSettings() {
     $config = \Drupal::config('syslog.settings');
     $this->assertIdentical($config->get('identity'), 'drupal');
-    // @TODO: change this to integer once there's schema of this config.
     $this->assertIdentical($config->get('facility'), '128');
   }
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemConfigsTest.php
deleted file mode 100644
index 0764d72..0000000
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemConfigsTest.php
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemSiteTest.
- */
-
-namespace Drupal\migrate_drupal\Tests\d6;
-
-use Drupal\migrate\MigrateMessage;
-use Drupal\migrate\MigrateExecutable;
-use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
-
-class MigrateSystemConfigsTest extends MigrateDrupalTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getInfo() {
-    return array(
-      'name'  => 'Migrate variables to system.*.yml',
-      'description'  => 'Upgrade variables to system.*.yml',
-      'group' => 'Migrate Drupal',
-    );
-  }
-
-  /**
-   * Tests migration of system (cron) variables to system.cron.yml.
-   */
-  public function testSystemCron() {
-    $migration = entity_load('migration', 'd6_system_cron');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemCron.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.cron');
-    $this->assertIdentical($config->get('threshold.warning'), 172800);
-    $this->assertIdentical($config->get('threshold.error'), 1209600);
-  }
-
-  /**
-   * Tests migration of system (rss) variables to system.rss.yml.
-   */
-  public function testSystemRss() {
-    $migration = entity_load('migration', 'd6_system_rss');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemRss.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.rss');
-    $this->assertIdentical($config->get('items.limit'), 10);
-  }
-
-  /**
-   * Tests migration of system (Performance) variables to system.performance.yml.
-   */
-  public function testSystemPerformance() {
-    $migration = entity_load('migration', 'd6_system_performance');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemPerformance.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.performance');
-    $this->assertIdentical($config->get('css.preprocess'), false);
-    $this->assertIdentical($config->get('js.preprocess'), false);
-    $this->assertIdentical($config->get('cache.page.max_age'), 0);
-  }
-
-  /**
-   * Tests migration of system (theme) variables to system.theme.yml.
-   */
-  public function testSystemTheme() {
-    $migration = entity_load('migration', 'd6_system_theme');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemTheme.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.theme');
-    $this->assertIdentical($config->get('admin'), '0');
-    $this->assertIdentical($config->get('default'), 'garland');
-  }
-
-  /**
-   * Tests migration of system (maintenance) variables to system.maintenance.yml.
-   */
-  public function testSystemMaintenance() {
-    $migration = entity_load('migration', 'd6_system_maintenance');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemMaintenance.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.maintenance');
-    $this->assertIdentical($config->get('enable'), 0);
-    $this->assertIdentical($config->get('message'), 'Drupal is currently under maintenance. We should be back shortly. Thank you for your patience.');
-  }
-
-  /**
-   * Tests migration of system (site) variables to system.site.yml.
-   */
-  public function testSystemSite() {
-    $migration = entity_load('migration', 'd6_system_site');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemSite.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.site');
-    $this->assertIdentical($config->get('name'), 'site_name');
-    $this->assertIdentical($config->get('mail'), 'site_mail@example.com');
-    $this->assertIdentical($config->get('slogan'), 'Migrate rocks');
-    $this->assertIdentical($config->get('page.403'), 'user');
-    $this->assertIdentical($config->get('page.404'), 'page-not-found');
-    $this->assertIdentical($config->get('page.front'), 'node');
-    $this->assertIdentical($config->get('admin_compact_mode'), FALSE);
-  }
-
-  /**
-   * Tests migration of system (filter) variables to system.filter.yml.
-   */
-  public function testSystemFilter() {
-    $migration = entity_load('migration', 'd6_system_filter');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFilter.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.filter');
-    $this->assertIdentical($config->get('protocols'), array('http', 'https', 'ftp', 'news', 'nntp', 'tel', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal', 'rtsp'));
-  }
-
-  /**
-   * Tests migration of system (image) variables to system.image.yml.
-   */
-  public function testSystemImage() {
-    $migration = entity_load('migration', 'd6_system_image');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImage.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.image');
-    $this->assertIdentical($config->get('toolkit'), 'gd');
-  }
-
-  /**
-   * Tests migration of system (image GD) variables to system.image.gd.yml.
-   */
-  public function testSystemImageGd() {
-    $migration = entity_load('migration', 'd6_system_image_gd');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImageGd.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $config = \Drupal::config('system.image.gd');
-    $this->assertIdentical($config->get('jpeg_quality'), 75);
-  }
-
-  /**
-   * Tests migration of system (file) variables to system.file.yml.
-   */
-  public function testSystemFile() {
-    $migration = entity_load('migration', 'd6_system_file');
-    $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php',
-    );
-    $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
-    $executable->import();
-    $old_state = \Drupal::configFactory()->getOverrideState();
-    \Drupal::configFactory()->setOverrideState(FALSE);
-    $config = \Drupal::config('system.file');
-    $this->assertIdentical($config->get('path.private'), 'files/test');
-    $this->assertIdentical($config->get('path.temporary'), 'files/temp');
-    \Drupal::configFactory()->setOverrideState($old_state);
-  }
-
-}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemCronTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemCronTest.php
new file mode 100644
index 0000000..e2c6a32
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemCronTest.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemCronTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemCronTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate cron variable to system.*.yml',
+      'description'  => 'Upgrade cron variable to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_cron');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemCron.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (cron) variables to system.cron.yml.
+   */
+  public function testSystemCron() {
+    $config = \Drupal::config('system.cron');
+    $this->assertIdentical($config->get('threshold.warning'), 172800);
+    $this->assertIdentical($config->get('threshold.error'), 1209600);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemFileTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemFileTest.php
new file mode 100644
index 0000000..797ee71
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemFileTest.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemFileTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemFileTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate variables to system.*.yml',
+      'description'  => 'Upgrade variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_file');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFile.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (file) variables to system.file.yml.
+   */
+  public function testSystemFile() {
+    $old_state = \Drupal::configFactory()->getOverrideState();
+    \Drupal::configFactory()->setOverrideState(FALSE);
+    $config = \Drupal::config('system.file');
+    $this->assertIdentical($config->get('path.private'), 'core/modules/simpletest/files');
+    $this->assertIdentical($config->get('path.temporary'), 'files/temp');
+    \Drupal::configFactory()->setOverrideState($old_state);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemFilterTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemFilterTest.php
new file mode 100644
index 0000000..1872fe3
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemFilterTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemFilterTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemFilterTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate filter variables to system.*.yml',
+      'description'  => 'Upgrade filter variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_filter');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemFilter.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (filter) variables to system.filter.yml.
+   */
+  public function testSystemFilter() {
+    $config = \Drupal::config('system.filter');
+    $this->assertIdentical($config->get('protocols'), array('http', 'https', 'ftp', 'news', 'nntp', 'tel', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal', 'rtsp'));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemImageGdTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemImageGdTest.php
new file mode 100644
index 0000000..23d3373
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemImageGdTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemImageGdTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemImageGdTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate image gd variables to system.*.yml',
+      'description'  => 'Upgrade image gd variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_image_gd');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImageGd.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (image GD) variables to system.image.gd.yml.
+   */
+  public function testSystemImageGd() {
+    $config = \Drupal::config('system.image.gd');
+    $this->assertIdentical($config->get('jpeg_quality'), 75);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemImageTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemImageTest.php
new file mode 100644
index 0000000..1894f4f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemImageTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemImageTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemImageTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate image variables to system.*.yml',
+      'description'  => 'Upgrade image variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_image');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemImage.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (image) variables to system.image.yml.
+   */
+  public function testSystemImage() {
+    $config = \Drupal::config('system.image');
+    $this->assertIdentical($config->get('toolkit'), 'gd');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemMaintenanceTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemMaintenanceTest.php
new file mode 100644
index 0000000..d08f9c7
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemMaintenanceTest.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemMaintenanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemMaintenanceTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate maintenance variables to system.*.yml',
+      'description'  => 'Upgrade maintenance variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_maintenance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemMaintenance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (maintenance) variables to system.maintenance.yml.
+   */
+  public function testSystemMaintenance() {
+    $config = \Drupal::config('system.maintenance');
+    $this->assertIdentical($config->get('enable'), 0);
+    $this->assertIdentical($config->get('message'), 'Drupal is currently under maintenance. We should be back shortly. Thank you for your patience.');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemPerformanceTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemPerformanceTest.php
new file mode 100644
index 0000000..ff3feb8
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemPerformanceTest.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemPerformanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemPerformanceTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate performance variables to system.*.yml',
+      'description'  => 'Upgrade performance variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_performance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemPerformance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (Performance) variables to system.performance.yml.
+   */
+  public function testSystemPerformance() {
+    $config = \Drupal::config('system.performance');
+    $this->assertIdentical($config->get('css.preprocess'), FALSE);
+    $this->assertIdentical($config->get('js.preprocess'), FALSE);
+    $this->assertIdentical($config->get('cache.page.max_age'), 0);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemRssTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemRssTest.php
new file mode 100644
index 0000000..69bc4e6
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemRssTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemRssTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemRssTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate rss variable to system.*.yml',
+      'description'  => 'Upgrade rss variable to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_rss');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemRss.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (rss) variables to system.rss.yml.
+   */
+  public function testSystemRss() {
+    $config = \Drupal::config('system.rss');
+    $this->assertIdentical($config->get('items.limit'), 10);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemSiteTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemSiteTest.php
new file mode 100644
index 0000000..bd17eb0
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemSiteTest.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemSiteTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemSiteTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate site variables to system.*.yml',
+      'description'  => 'Upgrade site variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_site');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemSite.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (site) variables to system.site.yml.
+   */
+  public function testSystemSite() {
+    $config = \Drupal::config('system.site');
+    $this->assertIdentical($config->get('name'), 'site_name');
+    $this->assertIdentical($config->get('mail'), 'site_mail@example.com');
+    $this->assertIdentical($config->get('slogan'), 'Migrate rocks');
+    $this->assertIdentical($config->get('page.403'), 'user');
+    $this->assertIdentical($config->get('page.404'), 'page-not-found');
+    $this->assertIdentical($config->get('page.front'), 'node');
+    $this->assertIdentical($config->get('admin_compact_mode'), FALSE);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemThemeTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemThemeTest.php
new file mode 100644
index 0000000..31bef18
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemThemeTest.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateSystemThemeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateSystemThemeTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate theme variables to system.*.yml',
+      'description'  => 'Upgrade theme variables to system.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_system_theme');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6SystemTheme.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of system (theme) variables to system.theme.yml.
+   */
+  public function testSystemTheme() {
+    $config = \Drupal::config('system.theme');
+    $this->assertIdentical($config->get('admin'), '0');
+    $this->assertIdentical($config->get('default'), 'garland');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyConfigsTest.php
index 4cedef4..4a6b7d6 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,16 +34,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of taxonomy variables to taxonomy.settings.yml.
+   * {@inheritdoc}
    */
-  public function testTaxonomySettings() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_taxonomy_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomySettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of taxonomy variables to taxonomy.settings.yml.
+   */
+  public function testTaxonomySettings() {
     $config = \Drupal::config('taxonomy.settings');
     $this->assertIdentical($config->get('terms_per_page_admin'), 100);
     $this->assertIdentical($config->get('override_selector'), FALSE);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyTermTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyTermTest.php
new file mode 100644
index 0000000..6f963ae
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyTermTest.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateTaxonomyTermTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+use Drupal\taxonomy\Entity\Term;
+
+/**
+ * Tests the Drupal 6 taxonomy term to Drupal 8 migration.
+ */
+class MigrateTaxonomyTermTest extends MigrateDrupalTestBase {
+
+  static $modules = array('taxonomy');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate taxonomy terms',
+      'description'  => 'Upgrade taxonomy terms',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->prepareIdMappings(array(
+      'd6_taxonomy_vocabulary' => array(
+        array(array(1), array('vocabulary_1_i_0_')),
+        array(array(2), array('vocabulary_2_i_1_')),
+        array(array(3), array('vocabulary_3_i_2_')),
+    )));
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_taxonomy_term');
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyTerm.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 taxonomy term to Drupal 8 migration.
+   */
+  public function testTaxonomyTerms() {
+    $expected_results = array(
+      '1' => array(
+        'source_vid' => 1,
+        'vid' => 'vocabulary_1_i_0_',
+        'weight' => 0,
+      ),
+      '2' => array(
+        'source_vid' => 2,
+        'vid' => 'vocabulary_2_i_1_',
+        'weight' => 3,
+      ),
+      '3' => array(
+        'source_vid' => 2,
+        'vid' => 'vocabulary_2_i_1_',
+        'weight' => 4,
+        'parent' => array(2),
+      ),
+      '4' => array(
+        'source_vid' => 3,
+        'vid' => 'vocabulary_3_i_2_',
+        'weight' => 6,
+      ),
+      '5' => array(
+        'source_vid' => 3,
+        'vid' => 'vocabulary_3_i_2_',
+        'weight' => 7,
+        'parent' => array(4),
+      ),
+      '6' => array(
+        'source_vid' => 3,
+        'vid' => 'vocabulary_3_i_2_',
+        'weight' => 8,
+        'parent' => array(4, 5),
+      ),
+    );
+    $terms = entity_load_multiple('taxonomy_term', array_keys($expected_results));
+    foreach ($expected_results as $tid => $values) {
+      /** @var Term $term */
+      $term = $terms[$tid];
+      $this->assertIdentical($term->name->value, "term {$tid} of vocabulary {$values['source_vid']}");
+      $this->assertIdentical($term->description->value, "description of term {$tid} of vocabulary {$values['source_vid']}");
+      $this->assertEqual($term->vid->value, $values['vid']);
+      $this->assertEqual($term->weight->value, $values['weight']);
+      if (empty($values['parent'])) {
+        $this->assertNull($term->parent->value);
+      }
+      else {
+        $parents = array();
+        foreach (taxonomy_term_load_parents($tid) as $parent) {
+          $parents[] = $parent->id();
+        }
+        $this->assertEqual($values['parent'], $parents);
+      }
+    }
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyVocabularyTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyVocabularyTest.php
new file mode 100644
index 0000000..52977b5
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTaxonomyVocabularyTest.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateTaxonomyVocabularyTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 taxonomy vocabularies to Drupal 8 migration.
+ */
+class MigrateTaxonomyVocabularyTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('taxonomy');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate taxonomy vocabularies.',
+      'description'  => 'Migrate taxonomy vocabularies to taxonomy.vocabulary.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_taxonomy_vocabulary');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 taxonomy vocabularies to Drupal 8 migration.
+   */
+  public function testTaxonomyVocabulary() {
+    for ($i = 0; $i < 3; $i++) {
+      $j = $i + 1;
+      $vocabulary = entity_load('taxonomy_vocabulary', "vocabulary_{$j}_i_{$i}_");
+      $this->assertEqual(array($vocabulary->id()), entity_load('migration', 'd6_taxonomy_vocabulary')->getIdMap()->lookupDestinationID(array($j)));
+      $this->assertEqual($vocabulary->name, "vocabulary $j (i=$i)");
+      $this->assertEqual($vocabulary->description, "description of vocabulary $j (i=$i)");
+      $this->assertEqual($vocabulary->hierarchy, $i);
+      $this->assertEqual($vocabulary->weight, 4   + $i);
+    }
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeRevisionTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeRevisionTest.php
new file mode 100644
index 0000000..666969f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeRevisionTest.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateTermNodeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Tests the Drupal 6 term-node revision association to Drupal 8 migration.
+ */
+class MigrateTermNodeRevisionTest extends MigrateTermNodeTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate taxonomy term node revisions',
+      'description'  => 'Upgrade taxonomy term node associations',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $id_mappings = array(
+      'd6_term_node' => array(
+        array(array(2), array(1)),
+      ),
+      'd6_node_revision' => array(
+        array(array(2), array(2)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migrations = entity_load_multiple('migration', array('d6_term_node_revision:*'));
+    foreach ($migrations as $migration) {
+      $executable = new MigrateExecutable($migration, $this);
+      $executable->import();
+    }
+  }
+
+  /**
+   * Tests the Drupal 6 term-node revision association to Drupal 8 migration.
+   */
+  public function testTermRevisionNode() {
+    $node = \Drupal::entityManager()->getStorageController('node')->loadRevision(2);
+    $this->assertEqual(count($node->vocabulary_3_i_2_), 2);
+    $this->assertEqual($node->vocabulary_3_i_2_[0]->value, 4);
+    $this->assertEqual($node->vocabulary_3_i_2_[1]->value, 5);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTest.php
new file mode 100644
index 0000000..8d24dfc
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTest.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateTermNodeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Tests the Drupal 6 term-node association to Drupal 8 migration.
+ */
+class MigrateTermNodeTest extends MigrateTermNodeTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate taxonomy term node',
+      'description'  => 'Upgrade taxonomy term node associations',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migrations = entity_load_multiple('migration', array('d6_term_node:*'));
+    foreach ($migrations as $migration) {
+      $executable = new MigrateExecutable($migration, $this);
+      $executable->import();
+    }
+  }
+
+  /**
+   * Tests the Drupal 6 term-node association to Drupal 8 migration.
+   */
+  public function testTermNode() {
+    $nodes = node_load_multiple(array(1, 2), TRUE);
+    $node = $nodes[1];
+    $this->assertEqual(count($node->vocabulary_1_i_0_), 1);
+    $this->assertEqual($node->vocabulary_1_i_0_[0]->value, 1);
+    $node = $nodes[2];
+    $this->assertEqual(count($node->vocabulary_2_i_1_), 2);
+    $this->assertEqual($node->vocabulary_2_i_1_[0]->value, 2);
+    $this->assertEqual($node->vocabulary_2_i_1_[1]->value, 3);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTestBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTestBase.php
new file mode 100644
index 0000000..6323c36
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTestBase.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateTermNodeTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateTermNodeTestBase extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  static $modules = array('node', 'taxonomy');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $vocabulary = entity_create('taxonomy_vocabulary', array(
+      'vid' => 'test',
+    ));
+    $vocabulary->save();
+    $node_type = entity_create('node_type', array('type' => 'story'));
+    $node_type->save();
+    foreach (array('vocabulary_1_i_0_', 'vocabulary_2_i_1_', 'vocabulary_3_i_2_') as $name) {
+      entity_create('field_config', array(
+        'name' => $name,
+        'entity_type' => 'node',
+        'type' => 'taxonomy_term_reference',
+        'cardinality' => -1,
+        'settings' => array(
+          'allowed_values' => array(
+            array(
+              'vocabulary' => $vocabulary->id(),
+              'parent' => '0',
+            ),
+          ),
+        ),
+      ))->save();
+      entity_create('field_instance_config', array(
+        'field_name' => $name,
+        'entity_type' => 'node',
+        'bundle' => 'story',
+      ))->save();
+
+    }
+    $id_mappings = array(
+      'd6_vocabulary_field_instance' => array(
+        array(array(1, 'page'), array('node', 'page', 'test')),
+      ),
+      'd6_vocabulary_entity_display' => array(
+        array(array(1, 'page'), array('node', 'page', 'default', 'test')),
+      ),
+      'd6_vocabulary_entity_form_display' => array(
+        array(array(1, 'page'), array('node', 'page', 'default', 'test')),
+      ),
+      'd6_node' => array(
+        array(array(1), array(1)),
+        array(array(2), array(2)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $vids = array(1, 2, 3);
+    for ($i = 1; $i <= 2; $i++) {
+      $node = entity_create('node', array(
+        'type' => 'story',
+        'nid' => $i,
+        'vid' => array_shift($vids),
+      ));
+      $node->enforceIsNew();
+      $node->save();
+      if ($i == 1) {
+        $node->vid->value = array_shift($vids);
+        $node->enforceIsNew(FALSE);
+        $node->isDefaultRevision(FALSE);
+        $node->save();
+      }
+    }
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TermNode.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyTerm.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php',
+    );
+    $this->loadDumps($dumps);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTextConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTextConfigsTest.php
index e47e99b..d33015e 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTextConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTextConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,18 +34,25 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of text variables to text.settings.yml.
+   * {@inheritdoc}
    */
-  public function testTextSettings() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_text_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TextSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of text variables to text.settings.yml.
+   */
+  public function testTextSettings() {
     $config = \Drupal::config('text.settings');
-    $this->assertIdentical($config->get('default_summary_length'), 600);
+    $this->assertIdentical($config->get('default_summary_length'), 456);
   }
 
 }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUpdateConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUpdateConfigsTest.php
index f8721c5..c685edf 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUpdateConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUpdateConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -35,16 +34,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of update variables to update.settings.yml.
+   * {@inheritdoc}
    */
-  public function testUpdateSettings() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_update_settings');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UpdateSettings.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of update variables to update.settings.yml.
+   */
+  public function testUpdateSettings() {
     $config = \Drupal::config('update.settings');
     $this->assertIdentical($config->get('fetch.max_attempts'), 2);
     $this->assertIdentical($config->get('fetch.url'), 'http://updates.drupal.org/release-history');
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadBase.php
new file mode 100644
index 0000000..90b46de
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadBase.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateUploadBase extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  static $modules = array('file', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Create new file entities.
+    for ($i = 1; $i <= 3; $i++) {
+      $file = entity_create('file', array(
+        'fid' => $i,
+        'uid' => 1,
+        'filename' => 'druplicon.txt',
+        'uri' => "public://druplicon-$i.txt",
+        'filemime' => 'text/plain',
+        'created' => 1,
+        'changed' => 1,
+        'status' => FILE_STATUS_PERMANENT,
+      ));
+      $file->enforceIsNew();
+      file_put_contents($file->getFileUri(), 'hello world');
+
+      // Save it, inserting a new record.
+      $file->save();
+      $id_mappings['d6_file'][] = array(array($i), array($i));
+    }
+
+    // Add a node type.
+    $node_type = entity_create('node_type', array('type' => 'story'));
+    $node_type->save();
+
+    // Add a file field.
+    entity_create('field_config', array(
+      'name' => 'upload',
+      'entity_type' => 'node',
+      'type' => 'file',
+      'cardinality' => -1,
+      'settings' => array(
+        'display_field' => TRUE,
+      ),
+    ))->save();
+    entity_create('field_instance_config', array(
+      'field_name' => 'upload',
+      'entity_type' => 'node',
+      'bundle' => 'story',
+    ))->save();
+    $id_mappings['d6_node'] = array(
+      array(array(1), array(1)),
+      array(array(2), array(2)),
+    );
+    $this->prepareIdMappings($id_mappings);
+    $vids = array(1, 2, 3);
+    for ($i = 1; $i <= 2; $i++) {
+      $node = entity_create('node', array(
+        'type' => 'story',
+        'nid' => $i,
+        'vid' => array_shift($vids),
+      ));
+      $node->enforceIsNew();
+      $node->save();
+      if ($i == 1) {
+        $node->vid->value = array_shift($vids);
+        $node->enforceIsNew(FALSE);
+        $node->isDefaultRevision(FALSE);
+        $node->save();
+      }
+    }
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Upload.php',
+    );
+    $this->loadDumps($dumps);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadEntityDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadEntityDisplayTest.php
new file mode 100644
index 0000000..0085fad
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadEntityDisplayTest.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadEntityDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 upload settings to Drupal 8 entity display migration.
+ */
+class MigrateUploadEntityDisplayTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('node', 'file');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate upload entity display.',
+      'description'  => 'Upload entity display',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $id_mappings = array(
+      'd6_upload_field_instance' => array(
+        array(array(1), array('node', 'page', 'upload')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_upload_entity_display');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadInstance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 upload settings to Drupal 8 entity display migration.
+   */
+  public function testUploadEntityDisplay() {
+    $display = entity_get_display('node', 'page', 'default');
+    $component = $display->getComponent('upload');
+    $this->assertEqual($component['type'], 'file_default');
+
+    $display = entity_get_display('node', 'story', 'default');
+    $component = $display->getComponent('upload');
+    $this->assertEqual($component['type'], 'file_default');
+
+    // Assure this doesn't exist.
+    $display = entity_get_display('node', 'article', 'default');
+    $component = $display->getComponent('upload');
+    $this->assertTrue(is_null($component));
+
+    $this->assertEqual(array('node', 'page', 'default', 'upload'), entity_load('migration', 'd6_upload_entity_display')->getIdMap()->lookupDestinationID(array('page')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadEntityFormDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadEntityFormDisplayTest.php
new file mode 100644
index 0000000..0789c22
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadEntityFormDisplayTest.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadEntityFormDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 upload settings to Drupal 8 entity form display migration.
+ */
+class MigrateUploadEntityFormDisplayTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('file', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate upload entity form display.',
+      'description'  => 'Upload form entity display',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $id_mappings = array(
+      'd6_upload_field_instance' => array(
+        array(array(1), array('node', 'page', 'upload')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_upload_entity_form_display');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadInstance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+  /**
+   * Tests the Drupal 6 upload settings to Drupal 8 entity form display migration.
+   */
+  public function testUploadEntityFormDisplay() {
+    $display = entity_get_form_display('node', 'page', 'default');
+    $component = $display->getComponent('upload');
+    $this->assertEqual($component['type'], 'file_generic');
+
+    $display = entity_get_form_display('node', 'story', 'default');
+    $component = $display->getComponent('upload');
+    $this->assertEqual($component['type'], 'file_generic');
+
+    // Assure this doesn't exist.
+    $display = entity_get_form_display('node', 'article', 'default');
+    $component = $display->getComponent('upload');
+    $this->assertTrue(is_null($component));
+
+    $this->assertEqual(array('node', 'page', 'default', 'upload'), entity_load('migration', 'd6_upload_entity_form_display')->getIdMap()->lookupDestinationID(array('page')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadFieldTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadFieldTest.php
new file mode 100644
index 0000000..83edcfb
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadFieldTest.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 upload settings to Drupal 8 field migration.
+ */
+class MigrateUploadFieldTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('file', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate uploads',
+      'description'  => 'Uploads migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_upload_field');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadField.php',
+    );
+    $this->prepare($migration, $dumps);
+  }
+
+  /**
+   * Tests the Drupal 6 upload settings to Drupal 8 field migration.
+   */
+  public function testUpload() {
+    $field = entity_load('field_config', 'node.upload');
+    $this->assertEqual($field->id(), 'node.upload');
+    $this->assertEqual(array('node', 'upload'), entity_load('migration', 'd6_upload_field')->getIdMap()->lookupDestinationID(array('')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadInstanceTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadInstanceTest.php
new file mode 100644
index 0000000..ee293df
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadInstanceTest.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 upload settings to Drupal 8 field instance migration.
+ */
+class MigrateUploadInstanceTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('file', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate upload field instance.',
+      'description'  => 'Upload field instance migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Add some node mappings to get past checkRequirements().
+    $id_mappings = array(
+      'd6_upload_field' => array(
+        array(array(1), array('node', 'upload')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    foreach (array('page', 'story') as $type) {
+      entity_create('node_type', array('type' => $type))->save();
+    }
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'upload',
+      'type' => 'file',
+      'translatable' => '0',
+    ))->save();
+
+    $migration = entity_load('migration', 'd6_upload_field_instance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UploadInstance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 upload settings to Drupal 8 field instance migration.
+   */
+  public function testUploadFieldInstance() {
+    $field = entity_load('field_instance_config', 'node.page.upload');
+    $settings = $field->getSettings();
+    $this->assertEqual($field->id(), 'node.page.upload');
+    $this->assertEqual($settings['file_extensions'], 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp');
+    $this->assertEqual($settings['max_filesize'], '1MB');
+    $this->assertEqual($settings['description_field'], TRUE);
+
+    $field = entity_load('field_instance_config', 'node.story.upload');
+    $this->assertEqual($field->id(), 'node.story.upload');
+
+    // Shouldn't exist.
+    $field = entity_load('field_instance_config', 'node.article.upload');
+    $this->assertTrue(is_null($field));
+
+    $this->assertEqual(array('node', 'page', 'upload'), entity_load('migration', 'd6_upload_field_instance')->getIdMap()->lookupDestinationID(array('page')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadTest.php
new file mode 100644
index 0000000..0c10228
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadTest.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Test upload migration from Drupal 6 to Drupal 8.
+ */
+class MigrateUploadTest extends MigrateUploadBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate upload',
+      'description'  => 'Migrate association data between nodes and files.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_upload');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test upload migration from Drupal 6 to Drupal 8.
+   */
+  function testUpload() {
+    $nodes = node_load_multiple(array(1, 2), TRUE);
+    $node = $nodes[1];
+    $this->assertEqual(count($node->upload), 1);
+    $this->assertEqual($node->upload[0]->target_id, 1);
+    $this->assertEqual($node->upload[0]->description, 'file 1-1-1');
+    $this->assertEqual($node->upload[0]->isDisplayed(), FALSE);
+    // @TODO: remove this.
+    return;
+    $node = $nodes[2];
+    $this->assertEqual(count($node->upload), 2);
+    $this->assertEqual($node->upload[0]->target_id, 3);
+    $this->assertEqual($node->upload[0]->description, 'file 2-3-3');
+    $this->assertEqual($node->upload[0]->isDisplayed(), FALSE);
+    $this->assertEqual($node->upload[1]->target_id, 2);
+    $this->assertEqual($node->upload[1]->isDisplayed(), TRUE);
+    $this->assertEqual($node->upload[1]->description, 'file 2-3-2');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUrlAliasTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUrlAliasTest.php
new file mode 100644
index 0000000..159019f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUrlAliasTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUrlAliasTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Plugin\MigrateIdMapInterface;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+use Drupal\Core\Database\Database;
+
+/**
+ * Test the url alias migration.
+ */
+class MigrateUrlAliasTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Url alias migration.',
+      'description'  => 'Url alias migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_url_alias');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UrlAlias.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test the url alias migration.
+   */
+  public function testUrlAlias() {
+    $migration = entity_load('migration', 'd6_url_alias');
+    // Test that the field exists.
+    $conditions = array(
+      'source' => 'node/1',
+      'alias' => 'alias-one',
+      'langcode' => 'en',
+    );
+    $path = \Drupal::service('path.crud')->load($conditions);
+    $this->assertNotNull($path, "Path alias for node/1 successfully loaded.");
+    $this->assertEqual(array(1), $migration->getIdMap()->lookupDestinationID(array($path['pid'])), "Test IdMap");
+    $conditions = array(
+      'source' => 'node/2',
+      'alias' => 'alias-two',
+      'langcode' => 'en',
+    );
+    $path = \Drupal::service('path.crud')->load($conditions);
+    $this->assertNotNull($path, "Path alias for node/2 successfully loaded.");
+
+    // Test that we can re-import using the UrlAlias destination.
+    Database::getConnection('default', 'migrate')
+      ->update('url_alias')
+      ->fields(array('dst' => 'new-url-alias'))
+      ->condition('src', 'node/2')
+      ->execute();
+
+    db_update($migration->getIdMap()->mapTableName())
+      ->fields(array('source_row_status' => MigrateIdMapInterface::STATUS_NEEDS_UPDATE))
+      ->execute();
+    $migration = entity_load_unchanged('migration', 'd6_url_alias');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+    $path = \Drupal::service('path.crud')->load(array('pid' => $path['pid']));
+    $this->assertEqual($path['alias'], 'new-url-alias');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserConfigsTest.php
index 3d35256..37211ea 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserConfigsTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserConfigsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate\MigrateExecutable;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
@@ -28,16 +27,23 @@ public static function getInfo() {
   }
 
   /**
-   * Tests migration of user variables to user.mail.yml.
+   * {@inheritdoc}
    */
-  public function testUserMail() {
+  protected function setUp() {
+    parent::setUp();
     $migration = entity_load('migration', 'd6_user_mail');
     $dumps = array(
       drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserMail.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
+
+  /**
+   * Tests migration of user variables to user.mail.yml.
+   */
+  public function testUserMail() {
     $config = \Drupal::config('user.mail');
     $this->assertIdentical($config->get('status_activated.subject'), 'Account details for !username at !site (approved)');
     $this->assertIdentical($config->get('status_activated.body'), "!username,\n\nYour account at !site has been activated.\n\nYou may now log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\nOnce you have set your own password, you will be able to log in to !login_uri in the future using:\n\nusername: !username\n");
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureEntityDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureEntityDisplayTest.php
new file mode 100644
index 0000000..3919c7f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureEntityDisplayTest.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserPictureEntityDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 user picture to Drupal 8 entity display migration.
+ */
+class MigrateUserPictureEntityDisplayTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('image');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user picture entity display.',
+      'description'  => 'User picture entity display',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    $id_mappings = array(
+      'd6_user_picture_field_instance' => array(
+        array(array(1), array('user', 'user', 'user_picture')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_user_picture_entity_display');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 user picture to Drupal 8 entity display migration.
+   */
+  public function testUserPictureEntityDisplay() {
+    $display = entity_get_display('user', 'user', 'default');
+    $component = $display->getComponent('user_picture');
+    $this->assertEqual($component['type'], 'image');
+    $this->assertEqual($component['settings']['image_link'], 'content');
+
+    $this->assertEqual(array('user', 'user', 'default', 'user_picture'), entity_load('migration', 'd6_user_picture_entity_display')->getIdMap()->lookupDestinationID(array('')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureEntityFormDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureEntityFormDisplayTest.php
new file mode 100644
index 0000000..c4de81b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureEntityFormDisplayTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserPictureEntityFormDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 user picture to Drupal 8 entity form display migration.
+ */
+class MigrateUserPictureEntityFormDisplayTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('image');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user picture entity form display.',
+      'description'  => 'User picture entity form display',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $id_mappings = array(
+      'd6_user_picture_field_instance' => array(
+        array(array(1), array('user', 'user', 'user_picture')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_user_picture_entity_form_display');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 user picture to Drupal 8 entity form display migration.
+   */
+  public function testUserPictureEntityFormDisplay() {
+    $display = entity_get_form_display('user', 'user', 'default');
+    $component = $display->getComponent('user_picture');
+    $this->assertEqual($component['type'], 'image_image');
+    $this->assertEqual($component['settings']['progress_indicator'], 'throbber');
+
+    $this->assertEqual(array('user', 'user', 'default', 'user_picture'), entity_load('migration', 'd6_user_picture_entity_form_display')->getIdMap()->lookupDestinationID(array('')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureFieldTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureFieldTest.php
new file mode 100644
index 0000000..9184d2c
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureFieldTest.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Test the user_picture field migration.
+ */
+class MigrateUserPictureFieldTest extends MigrateDrupalTestBase {
+
+  static $modules = array('image');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user picture field',
+      'description'  => 'User picture field migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_user_picture_field');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test the user picture field migration.
+   */
+  public function testUserPictureField() {
+    $field = entity_load('field_config', 'user.user_picture');
+    $this->assertEqual($field->id(), 'user.user_picture');
+    $this->assertEqual(array('user', 'user_picture'), entity_load('migration', 'd6_user_picture_field')->getIdMap()->lookupDestinationID(array('')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureFileTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureFileTest.php
new file mode 100644
index 0000000..0bf5947
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureFileTest.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserPictureFileTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 user pictures to Drupal 8 migration.
+ */
+class MigrateUserPictureFileTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('file');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Migrate user pictures',
+      'description' => 'User pictures migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6User.php',
+    );
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_user_picture_file');
+    $migration->source['conf_path'] = 'core/modules/simpletest';
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 user pictures to Drupal 8 migration.
+   */
+  public function testUserPictures() {
+    $file_ids = array();
+    foreach (entity_load('migration', 'd6_user_picture_file')->getIdMap() as $destination_ids) {
+      $file_ids[] = reset($destination_ids);
+    }
+    $files = entity_load_multiple('file', $file_ids);
+    /** @var \Drupal\file\FileInterface $file */
+    $file = array_shift($files);
+    $this->assertEqual($file->getFilename(), 'image-test.jpg');
+    $this->assertEqual($file->getFileUri(), 'public://image-test.jpg');
+    $this->assertEqual($file->getSize(), 1901);
+    $this->assertEqual($file->getMimeType(), 'image/jpeg');
+
+    $file = array_shift($files);
+    $this->assertEqual($file->getFilename(), 'image-test.png');
+    $this->assertEqual($file->getFileUri(), 'public://image-test.png');
+    $this->assertFalse($files);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureInstanceTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureInstanceTest.php
new file mode 100644
index 0000000..f6881de
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserPictureInstanceTest.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserPictureInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 user picture to Drupal 8 picture field instance migration.
+ */
+class MigrateUserPictureInstanceTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('image');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user picture field instance.',
+      'description'  => 'User picture field instance migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Add some node mappings to get past checkRequirements().
+    $id_mappings = array(
+      'd6_user_picture_field' => array(
+        array(array('user_upload'), array('name', 'bundle')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'user_picture',
+      'type' => 'image',
+      'translatable' => '0',
+    ))->save();
+
+    $migration = entity_load('migration', 'd6_user_picture_field_instance');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 user picture to Drupal 8 picture field instance migration.
+   */
+  public function testUserPictureFieldInstance() {
+    $field = entity_load('field_instance_config', 'user.user.user_picture');
+    $settings = $field->getSettings();
+    $this->assertEqual($settings['file_extensions'], 'png gif jpg jpeg');
+    $this->assertEqual($settings['file_directory'], 'pictures');
+    $this->assertEqual($settings['max_filesize'], '30KB');
+    $this->assertEqual($settings['max_resolution'], '85x85');
+
+    $this->assertEqual(array('user', 'user', 'user_picture'), entity_load('migration', 'd6_user_picture_field_instance')->getIdMap()->lookupDestinationID(array('')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileEntityDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileEntityDisplayTest.php
new file mode 100644
index 0000000..7bfb212
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileEntityDisplayTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserProfileEntityDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests migration of user profile fields.
+ */
+class MigrateUserProfileEntityDisplayTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('link', 'options');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user profile entity display',
+      'description'  => 'Test the user profile entity display migration.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_user_profile_entity_display');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+  /**
+   * Tests migration of user profile fields.
+   */
+  public function testUserProfileFields() {
+    $display = entity_get_display('user', 'user', 'default');
+
+    // Test a text field.
+    $component = $display->getComponent('profile_color');
+    $this->assertEqual($component['type'], 'text_default');
+
+    // Test a list field.
+    $component = $display->getComponent('profile_bands');
+    $this->assertEqual($component['type'], 'text_default');
+
+    // Test a date field.
+    $component = $display->getComponent('profile_birthdate');
+    $this->assertEqual($component['type'], 'datetime_default');
+
+    // Test PROFILE_PRIVATE field is hidden.
+    $this->assertNull($display->getComponent('profile_sell_address'));
+
+    // Test PROFILE_HIDDEN field is hidden.
+    $this->assertNull($display->getComponent('profile_sold_to'));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileEntityFormDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileEntityFormDisplayTest.php
new file mode 100644
index 0000000..374d43b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileEntityFormDisplayTest.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserProfileEntityFormDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests migration of user profile entity form display.
+ */
+class MigrateUserProfileEntityFormDisplayTest extends MigrateDrupalTestBase {
+
+  static $modules = array('link', 'options');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user profile entity form display',
+      'description'  => 'Test the user profile entity form display migration.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_user_profile_entity_form_display');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of user profile fields.
+   */
+  public function testUserProfileEntityFormDisplay() {
+    $display = entity_get_form_display('user', 'user', 'default');
+
+    // Test a text field.
+    $component = $display->getComponent('profile_color');
+    $this->assertEqual($component['type'], 'text_textfield');
+
+    // Test a list field.
+    $component = $display->getComponent('profile_bands');
+    $this->assertEqual($component['type'], 'text_textfield');
+
+    // Test a date field.
+    $component = $display->getComponent('profile_birthdate');
+    $this->assertEqual($component['type'], 'datetime_default');
+
+    // Test PROFILE_PRIVATE field is hidden.
+    $this->assertNull($display->getComponent('profile_sell_address'));
+
+    // Test PROFILE_HIDDEN field is hidden.
+    $this->assertNull($display->getComponent('profile_sold_to'));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileFieldInstanceTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileFieldInstanceTest.php
new file mode 100644
index 0000000..0281f47
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileFieldInstanceTest.php
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserProfileFieldInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests migration of user profile fields.
+ */
+class MigrateUserProfileFieldInstanceTest extends MigrateDrupalTestBase {
+
+  static $modules = array('link', 'options', 'datetime', 'number', 'text');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user profile field instance',
+      'description'  => 'Test the user profile field instance migration.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_user_profile_field' => array(
+        array(array(1), array('user', 'profile_color')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+    $this->createFields();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_user_profile_field_instance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+  /**
+   * Tests migration of user profile fields.
+   */
+  public function testUserProfileFields() {
+    // Migrated a text field.
+    $field = entity_load('field_instance_config', 'user.user.profile_color');
+    $this->assertEqual($field->label(), 'Favorite color');
+    $this->assertEqual($field->getDescription(), 'List your favorite color');
+
+    // Migrated a textarea.
+    $field = entity_load('field_instance_config', 'user.user.profile_biography');
+    $this->assertEqual($field->label(), 'Biography');
+    $this->assertEqual($field->getDescription(), 'Tell people a little bit about yourself');
+
+    // Migrated checkbox field.
+    $field = entity_load('field_instance_config', 'user.user.profile_sell_address');
+    $this->assertEqual($field->label(), 'Sell your e-mail address?');
+    $this->assertEqual($field->getDescription(), "If you check this box, we'll sell your address to spammers to help line the pockets of our shareholders. Thanks!");
+
+    // Migrated selection field.
+    $field = entity_load('field_instance_config', 'user.user.profile_sold_to');
+    $this->assertEqual($field->label(), 'Sales Category');
+    $this->assertEqual($field->getDescription(), "Select the sales categories to which this user's address was sold.");
+
+    // Migrated list field.
+    $field = entity_load('field_instance_config', 'user.user.profile_bands');
+    $this->assertEqual($field->label(), 'Favorite bands');
+    $this->assertEqual($field->getDescription(), "Enter your favorite bands. When you've saved your profile, you'll be able to find other people with the same favorites.");
+
+/*
+    // Migrated URL field.
+    $field = entity_load('field_instance_config', 'user.user.profile_blog');
+    $this->assertEqual($field->label(), 'Your blog');
+    $this->assertEqual($field->getDescription(), "Paste the full URL, including http://, of your personal blog.");
+*/
+
+    // Migrated date field.
+    $field = entity_load('field_instance_config', 'user.user.profile_birthdate');
+    $this->assertEqual($field->label(), 'Birthdate');
+    $this->assertEqual($field->getDescription(), "Enter your birth date and we'll send you a coupon.");
+  }
+
+  /**
+   * Helper to create fields.
+   */
+  protected function createFields() {
+    $fields = array(
+      'profile_color' => 'text',
+      'profile_biography' => 'text_long',
+      'profile_sell_address' => 'list_integer',
+      'profile_sold_to' => 'list_text',
+      'profile_bands' => 'text',
+      'profile_blog' => 'link',
+      'profile_birthdate' => 'datetime',
+    );
+    foreach ($fields as $name => $type) {
+      entity_create('field_config', array(
+        'name' => $name,
+        'entity_type' => 'user',
+        'type' => $type,
+      ))->save();
+    }
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileFieldTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileFieldTest.php
new file mode 100644
index 0000000..2d1a773
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserProfileFieldTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserProfileFieldTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests migration of user profile fields.
+ */
+class MigrateUserProfileFieldTest extends MigrateDrupalTestBase {
+
+  static $modules = array('link', 'options', 'datetime');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate user profile fields',
+      'description'  => 'Test the user profile field migration.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_user_profile_field');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+  /**
+   * Tests migration of user profile fields.
+   */
+  public function testUserProfileFields() {
+    // Migrated a text field.
+    $field = entity_load('field_config', 'user.profile_color');
+    $this->assertEqual($field->type, 'text', 'Field type is text.');
+    $this->assertEqual($field->cardinality, 1, 'Text field has correct cardinality');
+
+    // Migrated a textarea.
+    $field = entity_load('field_config', 'user.profile_biography');
+    $this->assertEqual($field->type, 'text_long', 'Field type is text_long.');
+
+    // Migrated checkbox field.
+    $field = entity_load('field_config', 'user.profile_sell_address');
+    $this->assertEqual($field->type, 'list_integer', 'Field type is list_integer.');
+
+    // Migrated selection field.
+    $field = entity_load('field_config', 'user.profile_sold_to');
+    $this->assertEqual($field->type, 'list_text', 'Field type is list_text.');
+
+    // Migrated list field.
+    $field = entity_load('field_config', 'user.profile_bands');
+    $this->assertEqual($field->type, 'text', 'Field type is text.');
+    $this->assertEqual($field->cardinality, -1, 'List field has correct cardinality');
+
+/*
+    // Migrated URL field.
+    $field = entity_load('field_config', 'user.profile_blog');
+    $this->assertEqual($field->type, 'link', 'Field type is link.');
+*/
+
+    // Migrated date field.
+    $field = entity_load('field_config', 'user.profile_birthdate');
+    $this->assertEqual($field->type, 'datetime', 'Field type is datetime.');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserRoleTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserRoleTest.php
index 19cabeb..ea3f7c2 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserRoleTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserRoleTest.php
@@ -8,11 +8,12 @@
 namespace Drupal\migrate_drupal\Tests\d6;
 
 use Drupal\migrate\MigrateExecutable;
-use Drupal\migrate\MigrateMessage;
 use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
 
 class MigrateUserRoleTest extends MigrateDrupalTestBase {
 
+  static $modules = array('filter');
+
   /**
    * {@inheritdoc}
    */
@@ -24,20 +25,59 @@ public static function getInfo() {
     );
   }
 
-  function testUserRole() {
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // We need some sample data so we can use the Migration process plugin.
+    $table_name = entity_load('migration', 'd6_filter_format')->getIdMap()->mapTableName();
+    db_insert($table_name)->fields(array(
+      'sourceid1',
+      'destid1',
+    ))
+    ->values(array(
+      'sourceid1' => 1,
+      'destid1' => 'filtered_html',
+    ))
+    ->values(array(
+      'sourceid1' => 2,
+      'destid1' => 'full_html',
+    ))
+    ->execute();
+
     /** @var \Drupal\migrate\entity\Migration $migration */
     $migration = entity_load('migration', 'd6_user_role');
+    $path = drupal_get_path('module', 'migrate_drupal');
     $dumps = array(
-      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FilterFormat.php',
     );
     $this->prepare($migration, $dumps);
-    $executable = new MigrateExecutable($migration, new MigrateMessage());
+    $executable = new MigrateExecutable($migration, $this);
     $executable->import();
+  }
 
+  /**
+   * Tests user role migration.
+   */
+  public function testUserRole() {
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_user_role');
+    $rid = 'anonymous';
+    $anonymous = entity_load('user_role', $rid);
+    $this->assertEqual($anonymous->id(), $rid);
+    $this->assertEqual($anonymous->getPermissions(), array('migrate test anonymous permission', 'use text format filtered_html'));
+    $this->assertEqual(array($rid), $migration->getIdMap()->lookupDestinationId(array(1)));
+    $rid = 'authenticated';
+    $authenticated = entity_load('user_role', $rid);
+    $this->assertEqual($authenticated->id(), $rid);
+    $this->assertEqual($authenticated->getPermissions(), array('migrate test authenticated permission', 'use text format filtered_html'));
+    $this->assertEqual(array($rid), $migration->getIdMap()->lookupDestinationId(array(2)));
     $rid = 'migrate_test_role_1';
     $migrate_test_role_1 = entity_load('user_role', $rid);
     $this->assertEqual($migrate_test_role_1->id(), $rid);
-    $this->assertEqual($migrate_test_role_1->getPermissions(), array(0 => 'migrate test role 1 test permission'));
+    $this->assertEqual($migrate_test_role_1->getPermissions(), array(0 => 'migrate test role 1 test permission', 'use text format full_html'));
     $this->assertEqual(array($rid), $migration->getIdMap()->lookupDestinationId(array(3)));
     $rid = 'migrate_test_role_2';
     $migrate_test_role_2 = entity_load('user_role', $rid);
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserTest.php
new file mode 100644
index 0000000..f4c2806
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUserTest.php
@@ -0,0 +1,201 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUserTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\Core\Database\Database;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal6 user to Drupal 8 migration.
+ */
+class MigrateUserTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array(
+    'link',
+    'options',
+    'datetime',
+    'number',
+    'text',
+    'file',
+    'image',
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate users',
+      'description'  => 'Users migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Create the user profile field and instance.
+    entity_create('field_config', array(
+      'entity_type' => 'user',
+      'name' => 'user_picture',
+      'type' => 'image',
+      'translatable' => '0',
+    ))->save();
+    entity_create('field_instance_config', array(
+      'label' => 'User Picture',
+      'description' => '',
+      'field_name' => 'user_picture',
+      'entity_type' => 'user',
+      'bundle' => 'user',
+      'required' => 0,
+    ))->save();
+
+    $file = entity_create('file', array(
+      'fid' => 2,
+      'uid' => 2,
+      'filename' => 'image-test.jpg',
+      'uri' => "public://image-test.jpg",
+      'filemime' => 'image/jpeg',
+      'created' => 1,
+      'changed' => 1,
+      'status' => FILE_STATUS_PERMANENT,
+    ));
+    $file->enforceIsNew();
+    file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-1.png'));
+    $file->save();
+
+    $file = entity_create('file', array(
+      'fid' => 8,
+      'uid' => 8,
+      'filename' => 'image-test.png',
+      'uri' => "public://image-test.png",
+      'filemime' => 'image/png',
+      'created' => 1,
+      'changed' => 1,
+      'status' => FILE_STATUS_PERMANENT,
+    ));
+    $file->enforceIsNew();
+    file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-2.jpg'));
+    $file->save();
+
+    // Load database dumps to provide source data.
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FilterFormat.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserProfileFields.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6UserRole.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6User.php',
+    );
+    $this->loadDumps($dumps);
+
+    $id_mappings = array(
+      'd6_filter_format' => array(
+        array(array(1), array('filtered_html')),
+        array(array(2), array('full_html')),
+        array(array(3), array('escape_html_filter')),
+      ),
+      'd6_user_role' => array(
+        array(array(1), array('anonymous user')),
+        array(array(2), array('authenticated user')),
+        array(array(3), array('migrate test role 1')),
+        array(array(4), array('migrate test role 2')),
+        array(array(5), array('migrate test role 3')),
+      ),
+      'd6_user_picture_entity_display' => array(
+        array(array(1), array('user', 'user', 'default', 'user_picture')),
+      ),
+      'd6_user_picture_entity_form_display' => array(
+        array(array(1), array('user', 'user', 'default', 'user_picture')),
+      ),
+      'd6_user_picture_file' => array(
+        array(array(2), array(2)),
+        array(array(8), array(8)),
+      ),
+    );
+
+    $this->prepareIdMappings($id_mappings);
+
+    // Migrate users.
+    $migration = entity_load('migration', 'd6_user');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal6 user to Drupal 8 migration.
+   */
+  public function testUser() {
+    $users = Database::getConnection('default', 'migrate')
+      ->select('users', 'u')
+      ->fields('u')
+      ->execute()
+      ->fetchAll();
+
+    foreach ($users as $source) {
+      // Get roles directly from the source.
+      $rids = Database::getConnection('default', 'migrate')
+        ->select('users_roles', 'ur')
+        ->fields('ur', array('rid'))
+        ->condition('ur.uid', $source->uid)
+        ->execute()
+        ->fetchCol();
+      $roles = array(DRUPAL_AUTHENTICATED_RID);
+      $migration_role = entity_load('migration', 'd6_user_role');
+      foreach ($rids as $rid) {
+        $role = $migration_role->getIdMap()->lookupDestinationId(array($rid));
+        $roles[] = reset($role);
+      }
+      // Get the user signature format.
+      $migration_format = entity_load('migration', 'd6_filter_format');
+      $signature_format = $migration_format->getIdMap()->lookupDestinationId(array($source->signature_format));
+
+      $user = user_load($source->uid);
+      $this->assertEqual($user->id(), $source->uid);
+      $this->assertEqual($user->label(), $source->name);
+      $this->assertEqual($user->getEmail(), $source->mail);
+      $this->assertEqual($user->getSignature(), $source->signature);
+      $this->assertEqual($user->getSignatureFormat(), reset($signature_format));
+      $this->assertEqual($user->getCreatedTime(), $source->created);
+      $this->assertEqual($user->getLastAccessedTime(), $source->access);
+      $this->assertEqual($user->getLastLoginTime(), $source->login);
+      $is_blocked = $source->status == 0;
+      $this->assertEqual($user->isBlocked(), $is_blocked);
+      // $user->getPreferredLangcode() might fallback to default language if the
+      // user preferred language is not configured on the site. We just want to
+      // test if the value was imported correctly.
+      $this->assertEqual($user->preferred_langcode->value, $source->language);
+      $time_zone = $source->expected_timezone ?: \Drupal::config('system.date')->get('timezone.default');
+      $this->assertEqual($user->getTimeZone(), $time_zone);
+      $this->assertEqual($user->getInitialEmail(), $source->init);
+      $this->assertEqual($user->getRoles(), $roles);
+
+      // We have one empty picture in the data so don't try load that.
+      if (!empty($source->picture)) {
+        // Test the user picture.
+        $file = file_load($user->user_picture->target_id);
+        $this->assertEqual($file->getFilename(), basename($source->picture));
+      }
+
+      // Use the UI to check if the password has been salted and re-hashed to
+      // conform the Drupal >= 7.
+      $credentials = array('name' => $source->name, 'pass' => $source->pass_plain);
+      $this->drupalPostForm('user/login', $credentials, t('Log in'));
+      $this->assertNoRaw(t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password', array('query' => array('name' => $source->name))))));
+      $this->drupalLogout();
+    }
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateViewModesTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateViewModesTest.php
new file mode 100644
index 0000000..f858e60
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateViewModesTest.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\d6\MigrateFieldInstanceViewModeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests Drupal 6 view modes to Drupal 8 migration.
+ */
+class MigrateViewModesTest extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate view modes to entity.view_mode.*.*.yml',
+      'description'  => 'Migrate view modes',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_view_modes');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests Drupal 6 view modes to Drupal 8 migration.
+   */
+  public function testViewModes() {
+    // Test a new view mode.
+    $view_mode = entity_load('view_mode', 'node.preview');
+    $this->assertEqual(is_null($view_mode), FALSE, 'Preview view mode loaded.');
+    $this->assertEqual($view_mode->label(), 'Preview', 'View mode has correct label.');
+    // Test the Id Map.
+    $this->assertEqual(array('node', 'preview'), entity_load('migration', 'd6_view_modes')->getIdMap()->lookupDestinationID(array(1)));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyEntityDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyEntityDisplayTest.php
new file mode 100644
index 0000000..94cae78
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyEntityDisplayTest.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateVocabularyEntityDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+ */
+class MigrateVocabularyEntityDisplayTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('field', 'node', 'taxonomy');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Vocabulary entity display migration',
+      'description'  => 'Vocabulary entity display migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_taxonomy_vocabulary' => array(
+        array(array(4), array('tags')),
+      ),
+      'd6_vocabulary_field_instance' => array(
+        array(array(4, 'page'), array('node', 'page', 'tags')),
+      )
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_vocabulary_entity_display');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+   */
+  public function testVocabularyEntityDisplay() {
+    // Test that the field exists.
+    $component = entity_get_display('node', 'page', 'default')->getComponent('tags');
+    $this->assertEqual($component['type'], 'taxonomy_term_reference');
+    $this->assertEqual($component['weight'], 20);
+    // Test the Id map.
+    $this->assertEqual(array('node', 'article', 'default', 'tags'), entity_load('migration', 'd6_vocabulary_entity_display')->getIdMap()->lookupDestinationID(array(4, 'article')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyEntityFormDisplayTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyEntityFormDisplayTest.php
new file mode 100644
index 0000000..ce7aa35
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyEntityFormDisplayTest.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateVocabularyEntityFormDisplayTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+ */
+class MigrateVocabularyEntityFormDisplayTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('taxonomy', 'field');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Vocabulary entity form display migration',
+      'description'  => 'Vocabulary entity form display migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_taxonomy_vocabulary' => array(
+        array(array(4), array('tags')),
+      ),
+      'd6_vocabulary_field_instance' => array(
+        array(array(4, 'page'), array('node', 'page', 'tags')),
+      )
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $migration = entity_load('migration', 'd6_vocabulary_entity_form_display');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+  /**
+   * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+   */
+  public function testVocabularyEntityFormDisplay() {
+    // Test that the field exists.
+    $component = entity_get_form_display('node', 'page', 'default')->getComponent('tags');
+    $this->assertEqual($component['type'], 'taxonomy_term_reference');
+    $this->assertEqual($component['weight'], 20);
+    // Test the Id map.
+    $this->assertEqual(array('node', 'article', 'default', 'tags'), entity_load('migration', 'd6_vocabulary_entity_form_display')->getIdMap()->lookupDestinationID(array(4, 'article')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyFieldInstanceTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyFieldInstanceTest.php
new file mode 100644
index 0000000..f611e31
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyFieldInstanceTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateVocabularyFieldInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+ */
+class MigrateVocabularyFieldInstanceTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('node', 'field', 'taxonomy');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Vocabulary field instance migration',
+      'description'  => 'Vocabulary field instance migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_taxonomy_vocabulary' => array(
+        array(array(4), array('tags')),
+      ),
+      'd6_vocabulary_field' => array(
+        array(array(4), array('node', 'tags')),
+      )
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    // Create the vocab.
+    entity_create('taxonomy_vocabulary', array(
+      'name' => 'Test Vocabulary',
+      'description' => 'Test Vocabulary',
+      'vid' => 'tags',
+    ))->save();
+    // Create the field itself.
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'tags',
+      'type' => 'taxonomy_term_reference',
+    ))->save();
+
+    $migration = entity_load('migration', 'd6_vocabulary_field_instance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+   */
+  public function testVocabularyFieldInstance() {
+    // Test that the field exists.
+    $field_id = 'node.article.tags';
+    $field = entity_load('field_instance_config', $field_id);
+    $this->assertEqual($field->id(), $field_id, 'Field instance exists on article bundle.');
+    $settings = $field->getSettings();
+    $this->assertEqual('tags', $settings['allowed_values'][0]['vocabulary'], "Vocabulary has correct settings.");
+
+    // Test the page bundle as well.
+    $field_id = 'node.page.tags';
+    $field = entity_load('field_instance_config', $field_id);
+    $this->assertEqual($field->id(), $field_id, 'Field instance exists on page bundle.');
+    $settings = $field->getSettings();
+    $this->assertEqual('tags', $settings['allowed_values'][0]['vocabulary'], "Vocabulary has correct settings.");
+
+    $this->assertEqual(array('node', 'article', 'tags'), entity_load('migration', 'd6_vocabulary_field_instance')->getIdMap()->lookupDestinationID(array(4, 'article')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyFieldTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyFieldTest.php
new file mode 100644
index 0000000..7127c77
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateVocabularyFieldTest.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateVocabularyToFieldTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+ */
+class MigrateVocabularyFieldTest extends MigrateDrupalTestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('taxonomy', 'field');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Vocabulary field migration',
+      'description'  => 'Vocabulary field migration',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_taxonomy_vocabulary' => array(
+        array(array(4), array('tags')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    entity_create('taxonomy_vocabulary', array(
+      'name' => 'Test Vocabulary',
+      'description' => 'Test Vocabulary',
+      'vid' => 'test_vocab',
+    ))->save();
+
+    $migration = entity_load('migration', 'd6_vocabulary_field');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6VocabularyField.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration.
+   */
+  public function testVocabularyField() {
+  // Test that the field exists.
+    $field_id = 'node.tags';
+    $field = entity_load('field_config', $field_id);
+    $this->assertEqual($field->id(), $field_id);
+    $settings = $field->getSettings();
+    $this->assertEqual('tags', $settings['allowed_values'][0]['vocabulary'], "Vocabulary has correct settings.");
+    $this->assertEqual(array('node', 'tags'), entity_load('migration', 'd6_vocabulary_field')->getIdMap()->lookupDestinationID(array(4)), "Test IdMap");
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d7/MigrateTrackerConfigTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d7/MigrateTrackerConfigTest.php
new file mode 100644
index 0000000..537a7df
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d7/MigrateTrackerConfigTest.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d7\MigrateTrackerConfigTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d7;
+
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests migration of variables from the Tracker module.
+ */
+class MigrateTrackerConfigTest extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('tracker');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate variables to tracker.*.yml',
+      'description'  => 'Upgrade variables to tracker.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * Tests migration of tracker settings variables to tracker.settings.yml.
+   */
+  public function testTrackerSettings() {
+    $migration = entity_load('migration', 'd7_tracker_settings');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal7TrackerSettings.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+    $config = \Drupal::config('tracker.settings');
+    $this->assertIdentical($config->get('cron_index_limit'), 1000);
+  }
+  
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/dependencies/MigrateDependenciesTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/dependencies/MigrateDependenciesTest.php
new file mode 100644
index 0000000..ee85cdb
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/dependencies/MigrateDependenciesTest.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\MigrateDependenciesTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\dependencies;
+
+use Drupal\Component\Utility\String;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Test the migrate dependencies
+ *
+ * @group Drupal
+ * @group migrate_drupal
+ */
+class MigrateDependenciesTest extends MigrateDrupalTestBase {
+
+  static $modules = array('aggregator');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate dependency tests',
+      'description'  => 'Ensure the consistency among the dependencies for migrate',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * Tests that the order is correct when loading several migrations.
+   */
+  public function testMigrateDependenciesOrder() {
+    $migration_items = array('d6_comment', 'd6_filter_format', 'd6_node');
+    $migrations = entity_load_multiple('migration', $migration_items);
+    $expected_order = array('d6_filter_format', 'd6_node', 'd6_comment');
+    $this->assertEqual(array_keys($migrations), $expected_order);
+    $expected_requirements = array('d6_node', 'd6_node_type', 'd6_filter_format', 'd6_user');
+    // Migration dependencies for comment include dependencies for node
+    // migration as well.
+    $actual_requirements = $migrations['d6_comment']->get('requirements');
+    $this->assertEqual(count($actual_requirements), count($expected_requirements));
+    foreach ($expected_requirements as $requirement) {
+      $this->assertEqual($actual_requirements[$requirement], $requirement);
+    }
+  }
+
+  /**
+   * Tests dependencies on the migration of aggregator feeds & items.
+   */
+  public function testAggregatorMigrateDependencies() {
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_aggregator_item');
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6AggregatorItem.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $this->startCollectingMessages();
+    $executable->import();
+    $this->assertEqual($this->migrateMessages['error'], array(String::format('Migration @id did not meet the requirements', array('@id' => $migration->id()))));
+    $this->collectMessages = FALSE;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/destination/ConfigDestinationTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/destination/ConfigDestinationTest.php
new file mode 100644
index 0000000..006fecc
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/destination/ConfigDestinationTest.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\ConfigDestinationTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\destination;
+
+use Drupal\migrate\Plugin\migrate\destination\Config;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Test the raw config destination.
+ *
+ * @see \Drupal\migrate_drupal\Plugin\migrate\destination\Config
+ * @group Drupal
+ * @group migrate_drupal
+ */
+class ConfigDestinationTest extends UnitTestCase {
+
+  /**
+   * Test the import method.
+   */
+  public function testImport() {
+    $source = array(
+      'test' => 'x',
+    );
+    $config = $this->getMockBuilder('Drupal\Core\Config\Config')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $config->expects($this->once())
+      ->method('setData')
+      ->with($this->equalTo($source))
+      ->will($this->returnValue($config));
+    $config->expects($this->once())
+      ->method('save');
+    $row = $this->getMockBuilder('Drupal\migrate\Row')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $row->expects($this->once())
+      ->method('getDestination')
+      ->will($this->returnValue($source));
+    $destination = new Config(array(), 'd8_config', array('pluginId' => 'd8_config'), $config);
+    $destination->import($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Destination test',
+      'description' => 'Tests for destination plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+}
diff --git a/core/modules/migrate_drupal/migrate.drush.inc b/core/modules/migrate_drupal/migrate.drush.inc
new file mode 100644
index 0000000..64d5a00
--- /dev/null
+++ b/core/modules/migrate_drupal/migrate.drush.inc
@@ -0,0 +1,33 @@
+<?php
+
+use Drupal\Core\Database\Database;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Plugin\migrate\source\SqlBase;
+use Drupal\migrate\Plugin\MigrateIdMapInterface;
+use Symfony\Component\Yaml\Yaml;
+
+function migrate_drush_command() {
+  $items['migrate-manifest'] = array(
+    'arguments' => array(
+      'db_url' => 'The source database URL',
+      'manifest' => 'The name of the manifest file',
+    ),
+  );
+  return $items;
+}
+
+function drush_migrate_manifest($db_url, $manifest) {
+  require_once __DIR__ . '/drushmigratemessage.inc';
+  $db_spec = drush_convert_db_from_db_url($db_url);
+  Database::addConnectionInfo('migrate', 'default', $db_spec);
+  $list = Yaml::parse($manifest);
+  $message = new DrushMigrateMessage();
+  foreach (entity_load_multiple('migration', $list) as $migration_id => $migration) {
+    drush_log("Running $migration_id");
+    #$migration->getIdMap()->prepareUpdate();
+    $executable = new MigrateExecutable($migration, $message);
+    $executable->import();
+  }
+  include_once DRUPAL_ROOT . '/core/includes/utility.inc';
+  drupal_rebuild();
+}
diff --git a/core/modules/migrate_drupal/migrate_drupal.info.yml b/core/modules/migrate_drupal/migrate_drupal.info.yml
index 59fb9ae..a0bdaf6 100644
--- a/core/modules/migrate_drupal/migrate_drupal.info.yml
+++ b/core/modules/migrate_drupal/migrate_drupal.info.yml
@@ -4,3 +4,5 @@ description: 'Contains migrations from older Drupal versions.'
 package: Core
 version: VERSION
 core: 8.x
+dependencies:
+  - migrate
diff --git a/core/modules/migrate_drupal/migrate_drupal.module b/core/modules/migrate_drupal/migrate_drupal.module
index e69de29..726222d 100644
--- a/core/modules/migrate_drupal/migrate_drupal.module
+++ b/core/modules/migrate_drupal/migrate_drupal.module
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * Implements hook_entity_type_alter().
+ */
+function migrate_drupal_entity_type_alter(array &$entity_types) {
+  /** @var \Drupal\Core\Config\Entity\ConfigEntityType[] $entity_types */
+  $entity_types['migration']
+    ->setClass('Drupal\migrate_drupal\Entity\Migration')
+    ->setControllerClass('storage', 'Drupal\migrate_drupal\MigrationStorageController');
+}
diff --git a/core/modules/migrate_drupal/migrate_drupal.routing.yml b/core/modules/migrate_drupal/migrate_drupal.routing.yml
new file mode 100644
index 0000000..a7e8fef
--- /dev/null
+++ b/core/modules/migrate_drupal/migrate_drupal.routing.yml
@@ -0,0 +1,7 @@
+migrate_drupal.run:
+  path: '/admin/structure/migrate/run'
+  defaults:
+    _form: '\Drupal\migrate_drupal\Form\MigrateDrupalRunForm'
+    _title: 'Run'
+  requirements:
+    _permission: 'administer site configuration'
diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml
new file mode 100644
index 0000000..8ed0b5c
--- /dev/null
+++ b/core/modules/migrate_drupal/migrate_drupal.services.yml
@@ -0,0 +1,4 @@
+services:
+  plugin.manager.migrate.load:
+    class: Drupal\migrate\Plugin\MigratePluginManager
+    arguments: [load, '@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
\ No newline at end of file
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/D6VariableTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/D6VariableTest.php
deleted file mode 100644
index 7853b12..0000000
--- a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/D6VariableTest.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\migrate\Tests\D6VariableSourceTest.
- */
-
-namespace Drupal\migrate_drupal\Tests;
-
-use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
-
-/**
- * @group migrate_drupal
- * @group Drupal
- */
-class D6VariableTest extends MigrateSqlSourceTestCase {
-
-  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Variable';
-
-  protected $migrationConfiguration = array(
-    'id' => 'test',
-    'highwaterProperty' => array('field' => 'test'),
-    'idlist' => array(),
-    'source' => array(
-      'plugin' => 'drupal6_variable',
-      'variables' => array(
-        'foo',
-        'bar',
-      ),
-    ),
-    'sourceIds' => array(),
-    'destinationIds' => array(),
-  );
-
-  protected $mapJoinable = FALSE;
-
-  protected $expectedResults = array(
-    array(
-      'foo' => 1,
-      'bar' => FALSE,
-    ),
-  );
-
-  protected $databaseContents = array(
-    'variable' => array(
-      array('name' => 'foo', 'value' => 'i:1;'),
-      array('name' => 'bar', 'value' => 'b:0;'),
-    ),
-  );
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getInfo() {
-    return array(
-      'name' => 'D6 variable source functionality',
-      'description' => 'Tests D6 variable source plugin.',
-      'group' => 'Migrate Drupal',
-    );
-  }
-
-}
-
-namespace Drupal\migrate_drupal\Tests\source\d6;
-
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\migrate_drupal\Plugin\migrate\source\d6\Variable;
-
-class TestVariable extends Variable {
-  function setDatabase(Connection $database) {
-    $this->database = $database;
-  }
-  function setModuleHandler(ModuleHandlerInterface $module_handler) {
-    $this->moduleHandler = $module_handler;
-  }
-}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowSourceWithHighwaterTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowSourceWithHighwaterTest.php
new file mode 100644
index 0000000..ea93ffd
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowSourceWithHighwaterTest.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\VariableMultiRowSourceWithHighwaterTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source;
+
+/**
+ * Tests variable multirow source w/ highwater handling.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class VariableMultiRowSourceWithHighwaterTest extends VariableMultiRowTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 variable multirow source + highwater',
+      'description' => 'Tests D6 variable multirow source plugin with highwater handling.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->migrationConfiguration['highwaterProperty']['field'] = 'test';
+    parent::setup();
+  }
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowTest.php
new file mode 100644
index 0000000..724f1cb
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowTest.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\VariableMultiRowTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source;
+
+/**
+ * Tests the Drupal 6 variable multirow source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class VariableMultiRowTest extends VariableMultiRowTestBase {
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowTestBase.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowTestBase.php
new file mode 100644
index 0000000..4f51aeb
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableMultiRowTestBase.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\VariableMultiRowTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Base test class for the variable multirow source tests.
+ */
+class VariableMultiRowTestBase extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\VariableMultiRow';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_variable_multirow',
+      'variables' => array(
+        'foo',
+        'bar',
+      ),
+    ),
+  );
+
+  protected $expectedResults = array(
+    array('name' => 'foo', 'value' => 1),
+    array('name' => 'bar', 'value' => FALSE),
+  );
+
+  protected $databaseContents = array(
+    'variable' => array(
+      array('name' => 'foo', 'value' => 'i:1;'),
+      array('name' => 'bar', 'value' => 'b:0;'),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 variable multirow source functionality',
+      'description' => 'Tests D6 variable multirow source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+}
+
+namespace Drupal\migrate_drupal\Tests\source;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+
+class TestVariableMultiRow extends \Drupal\migrate_drupal\Plugin\migrate\source\VariableMultiRow {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableTest.php
new file mode 100644
index 0000000..e23f02c
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/VariableTest.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\VariableTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class VariableTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\Variable';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'highwaterProperty' => array('field' => 'test'),
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_variable',
+      'variables' => array(
+        'foo',
+        'bar',
+      ),
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'foo' => 1,
+      'bar' => FALSE,
+    ),
+  );
+
+  protected $databaseContents = array(
+    'variable' => array(
+      array('name' => 'foo', 'value' => 'i:1;'),
+      array('name' => 'bar', 'value' => 'b:0;'),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 variable source functionality',
+      'description' => 'Tests D6 variable source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+
+class TestVariable extends \Drupal\migrate_drupal\Plugin\migrate\source\Variable {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ActionTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ActionTest.php
new file mode 100644
index 0000000..bbff96a
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ActionTest.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\ActionTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests Drupal action migration source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class ActionTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Action';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_action',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+
+  protected $expectedResults = array(
+    array(
+      'aid' => '1',
+      'type' => 'system',
+      'callback' => 'system_goto_action',
+      'parameters' => 'a:1:{s:3:"url";s:4:"node";}',
+      'description' => 'Redirect to node list page',
+    ),
+    array(
+      'aid' => '2',
+      'type' => 'system',
+      'callback' => 'system_send_email_action',
+      'parameters' => 'a:3:{s:9:"recipient";s:7:"%author";s:7:"subject";s:4:"Test";s:7:"message";s:4:"Test',
+      'description' => 'Test notice email',
+    ),
+    array(
+      'aid' => 'comment_publish_action',
+      'type' => 'comment',
+      'callback' => 'comment_publish_action',
+      'parameters' => null,
+      'description' => null,
+    ),
+    array(
+      'aid' => 'node_publish_action',
+      'type' => 'comment',
+      'callback' => 'node_publish_action',
+      'parameters' => null,
+      'description' => null,
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 action source functionality',
+      'description' => 'Tests D6 actions source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->databaseContents['actions'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Action;
+
+class TestAction extends Action {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/AggregatorFeedTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/AggregatorFeedTest.php
new file mode 100644
index 0000000..72441f4
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/AggregatorFeedTest.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\AggregatorFeedTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 aggregator feed source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class AggregatorFeedTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\AggregatorFeed';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_aggregator_feed',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'fid' => 1,
+      'title' => 'feed title 1',
+      'url' => 'http://example.com/feed.rss',
+      'refresh' => 900,
+      'checked' => 0,
+      'link' => 'http://example.com',
+      'description' => 'A vague description',
+      'image' => '',
+      'etag' => '',
+      'modified' => 0,
+      'block' => 5,
+    ),
+    array(
+      'fid' => 2,
+      'title' => 'feed title 2',
+      'url' => 'http://example.net/news.rss',
+      'refresh' => 1800,
+      'checked' => 0,
+      'link' => 'http://example.net',
+      'description' => 'An even more vague description',
+      'image' => '',
+      'etag' => '',
+      'modified' => 0,
+      'block' => 5,
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 aggregator feed source functionality',
+      'description' => 'Tests D6 aggregator feed source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+  * {@inheritdoc}
+  */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      $this->databaseContents['aggregator_feed'][$k] = $row;
+    }
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\AggregatorFeed;
+
+class TestAggregatorFeed extends AggregatorFeed {
+
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/AggregatorItemTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/AggregatorItemTest.php
new file mode 100644
index 0000000..a5d146e
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/AggregatorItemTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\AggregatorItemTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 aggregator item source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class AggregatorItemTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\AggregatorItem';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_aggregator_item',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'iid' => 1,
+      'fid' => 1,
+      'title' => 'This (three) weeks in Drupal Core - January 10th 2014',
+      'link' => 'https://groups.drupal.org/node/395218',
+      'author' => 'larowlan',
+      'description' => "<h2 id='new'>What's new with Drupal 8?</h2>",
+      'timestamp' => 1389297196,
+      'guid' => '395218 at https://groups.drupal.org',
+    ),
+  );
+
+  protected $databaseContents = array('aggregator_item' => array(array(
+      'iid' => 1,
+      'fid' => 1,
+      'title' => 'This (three) weeks in Drupal Core - January 10th 2014',
+      'link' => 'https://groups.drupal.org/node/395218',
+      'author' => 'larowlan',
+      'description' => "<h2 id='new'>What's new with Drupal 8?</h2>",
+      'timestamp' => 1389297196,
+      'guid' => '395218 at https://groups.drupal.org',
+    ),
+  ));
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 aggregator item source functionality',
+      'description' => 'Tests D6 aggregator item source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\AggregatorItem;
+
+class TestAggregatorItem extends AggregatorItem {
+
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/BlockTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/BlockTest.php
new file mode 100644
index 0000000..d5aaa36
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/BlockTest.php
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\BlockTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 block source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class BlockTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Block';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_block',
+    ),
+  );
+
+  /**
+   * Sample block instance query results from the source.
+   */
+  protected $expectedResults = array(
+    array(
+      'bid' => 1,
+      'module' => 'block',
+      'delta' => '1',
+      'theme' => 'garland',
+      'status' => 1,
+      'weight' => 0,
+      'region' => 'left',
+      'visibility' => 0,
+      'pages' => '',
+      'title' => 'Test Title 01',
+      'cache' => -1,
+    ),
+    array(
+      'bid' => 2,
+      'module' => 'block',
+      'delta' => '2',
+      'theme' => 'garland',
+      'status' => 1,
+      'weight' => 5,
+      'region' => 'right',
+      'visibility' => 0,
+      'pages' => '<front>',
+      'title' => 'Test Title 02',
+      'cache' => -1,
+    ),
+  );
+
+  /**
+   * Sample block roles table.
+   */
+  protected $expectedBlocksRoles = array(
+    array(
+      'module' => 'block',
+      'delta' => 1,
+      'rid' => 2,
+    ),
+  );
+
+  /**
+   * Prepopulate database contents.
+   */
+  protected function setUp() {
+    $this->databaseContents['blocks'] = $this->expectedResults;
+    $this->databaseContents['blocks_roles'] = $this->expectedBlocksRoles;
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 block source functionality',
+      'description' => 'Tests D6 block source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testRetrieval() {
+    // FakeSelect does not support multiple source identifiers, can not test.
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Block;
+
+class TestBlock extends Block {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/BoxTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/BoxTest.php
new file mode 100644
index 0000000..568f126
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/BoxTest.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\BoxesTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 box source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class BoxTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Box';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_boxes',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+  // These are sample result queries.
+  protected $expectedResults = array(
+    array(
+      'bid' => 1,
+      'body' => '<p>I made some custom content.</p>',
+      'info' => 'Static Block',
+      'format' => 1,
+    ),
+    array(
+      'bid' => 2,
+      'body' => '<p>I made some more custom content.</p>',
+      'info' => 'Test Content',
+      'format' => 1,
+    ),
+  );
+
+  /**
+   * Prepopulate contents with results.
+   */
+  protected function setUp() {
+    $this->databaseContents['boxes'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 block boxes source functionality',
+      'description' => 'Tests D6 block boxes source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Box;
+
+class TestBox extends Box {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentSourceWithHighwaterTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentSourceWithHighwaterTest.php
new file mode 100644
index 0000000..016ff94
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentSourceWithHighwaterTest.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\CommentSourceTestWithHighwater.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+/**
+ * Tests the Drupal 6 comment source w/ highwater handling.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class CommentSourceWithHighwaterTest extends CommentTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 comment source + highwater',
+      'description' => 'Tests D6 comment source plugin with highwater handling.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  const ORIGINAL_HIGHWATER = 1382255613;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->migrationConfiguration['highwaterProperty']['field'] = 'timestamp';
+    array_shift($this->expectedResults);
+    parent::setUp();
+  }
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentTest.php
new file mode 100644
index 0000000..9d5d3fe
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentTest.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\CommentTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+/**
+ * Tests the Drupal 6 comment source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class CommentTest extends CommentTestBase {
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentTestBase.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentTestBase.php
new file mode 100644
index 0000000..18d84cf
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/CommentTestBase.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\CommentTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Base class for the comment source tests.
+ */
+class CommentTestBase extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Comment';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    // This needs to be the identifier of the actual key: cid for comment, nid
+    // for node and so on.
+    'source' => array(
+      'plugin' => 'd6_comment',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+
+  protected $expectedResults = array(
+    array(
+      'cid' => 1,
+      'pid' => 0,
+      'nid' => 2,
+      'uid' => 3,
+      'subject' => 'subject value 1',
+      'comment' => 'comment value 1',
+      'hostname' => 'hostname value 1',
+      'timestamp' => 1382255613,
+      'status' => 1,
+      'thread' => '',
+      'name' => '',
+      'mail' => '',
+      'homepage' => '',
+      'format' => 'testformat1',
+    ),
+    array(
+      'cid' => 2,
+      'pid' => 1,
+      'nid' => 3,
+      'uid' => 4,
+      'subject' => 'subject value 2',
+      'comment' => 'comment value 2',
+      'hostname' => 'hostname value 2',
+      'timestamp' => 1382255662,
+      'status' => 1,
+      'thread' => '',
+      'name' => '',
+      'mail' => '',
+      'homepage' => '',
+      'format' => 'testformat2',
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 comment source functionality',
+      'description' => 'Tests D6 comment source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      $this->databaseContents['comments'][$k] = $row;
+      $this->databaseContents['comments'][$k]['status'] = 1 - $this->databaseContents['comments'][$k]['status'];
+    }
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Comment;
+
+class TestComment extends Comment {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ContactCategoryTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ContactCategoryTest.php
new file mode 100644
index 0000000..1b43e7d
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ContactCategoryTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\ContactCategoryTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 contact category source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class ContactCategoryTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\ContactCategory';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_contact_category',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'cid' => 1,
+      'category' => 'contact category value 1',
+      'recipients' => 'admin@example.com,user@example.com',
+      'reply' => 'auto reply value 1',
+      'weight' => 0,
+      'selected' => 0,
+    ),
+    array(
+      'cid' => 2,
+      'category' => 'contact category value 2',
+      'recipients' => 'admin@example.com,user@example.com',
+      'reply' => 'auto reply value 2',
+      'weight' => 0,
+      'selected' => 0,
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 contact category source functionality',
+      'description' => 'Tests D6 contact category source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      $this->databaseContents['contact'][$k] = $row;
+    }
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\ContactCategory;
+
+class TestContactCategory extends ContactCategory {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/Drupal6SqlBaseTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/Drupal6SqlBaseTest.php
new file mode 100644
index 0000000..7136d51
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/Drupal6SqlBaseTest.php
@@ -0,0 +1,226 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\Drupal6SqlBaseTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateTestCase;
+
+/**
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class Drupal6SqlBaseTest extends MigrateTestCase {
+
+  /**
+   * Define bare minimum migration configuration.
+   */
+  protected $migrationConfiguration = array(
+    'id' => 'Drupal6SqlBase',
+  );
+
+  /**
+   * @var \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase
+   */
+  protected $base;
+
+  /**
+   * Minimum database contents needed to test Drupal6SqlBase.
+   */
+  protected $databaseContents = array(
+    'system' => array(
+      array(
+        'filename' => 'sites/all/modules/module1',
+        'name' => 'module1',
+        'type' => 'module',
+        'status' => 1,
+        'schema_version' => -1,
+      ),
+      array(
+        'filename' => 'sites/all/modules/module2',
+        'name' => 'module2',
+        'type' => 'module',
+        'status' => 0,
+        'schema_version' => 7201,
+      ),
+      array(
+        'filename' => 'sites/all/modules/test2',
+        'name' => 'test2',
+        'type' => 'theme',
+        'status' => 1,
+        'schema_version' => -1,
+      ),
+    ),
+    'variable' => array(
+      array(
+        'name' => 'my_variable',
+        'value' => 'b:1;',
+      ),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 SQL base class tests',
+      'description' => 'Tests D6 SQL base class.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $plugin = 'placeholder_id';
+    $this->base = new TestDrupal6SqlBase($this->migrationConfiguration, $plugin, array(), $this->getMigration());
+    $this->base->setDatabase($this->getDatabase($this->databaseContents));
+  }
+
+  /**
+   * Tests for Drupal6SqlBase::getSystemData().
+   */
+  public function testGetSystemData() {
+    $system_data = $this->base->getSystemData();
+    // Should be 1 theme and 2 modules.
+    $this->assertEquals(1, count($system_data['theme']));
+    $this->assertEquals(2, count($system_data['module']));
+
+    // Calling again should be identical.
+    $this->assertSame($system_data, $this->base->getSystemData());
+  }
+
+  /**
+   * Tests for Drupal6SqlBase::moduleExists().
+   */
+  public function testDrupal6ModuleExists() {
+    // This module should exist.
+    $this->assertTrue($this->base->moduleExistsWrapper('module1'));
+
+    // These modules should not exist.
+    $this->assertFalse($this->base->moduleExistsWrapper('module2'));
+    $this->assertFalse($this->base->moduleExistsWrapper('module3'));
+  }
+
+  /**
+   * Tests for Drupal6SqlBase::getModuleSchemaVersion().
+   */
+  public function testGetModuleSchemaVersion() {
+    // Non-existent module.
+    $this->assertFalse($this->base->getModuleSchemaVersionWrapper('module3'));
+
+    // Disabled module should still return schema version.
+    $this->assertEquals(7201, $this->base->getModuleSchemaVersionWrapper('module2'));
+
+    // Enabled module.
+    $this->assertEquals(-1, $this->base->getModuleSchemaVersionWrapper('module1'));
+  }
+
+  /**
+   * Tests for Drupal6SqlBase::variableGet().
+   */
+  public function testVariableGet() {
+    // Test default value.
+    $this->assertEquals('my_default', $this->base->variableGetWrapper('non_existent_variable', 'my_default'));
+
+    // Test non-default.
+    $this->assertSame(TRUE, $this->base->variableGetWrapper('my_variable', FALSE));
+  }
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Extends the Drupal6SqlBase abstract class.
+ */
+class TestDrupal6SqlBase extends \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'filename' => t('The path of the primary file for this item.'),
+      'name' => t('The name of the item; e.g. node.'),
+      'type' => t('The type of the item, either module, theme, or theme_engine.'),
+      'owner' => t("A theme's 'parent'. Can be either a theme or an engine."),
+      'status' => t('Boolean indicating whether or not this item is enabled.'),
+      'throttle' => t('Boolean indicating whether this item is disabled when the throttle.module disables throttleable items.'),
+      'bootstrap' => t('Boolean indicating whether this module is loaded during Drupal\'s early bootstrapping phase (e.g. even before the page cache is consulted).'),
+      'schema_version' => t('The module\'s database schema version number.'),
+      'weight' => t('The order in which this module\'s hooks should be invoked.'),
+      'info' => t('A serialized array containing information from the module\'s .info file.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->database
+      ->select('system', 's')
+      ->fields('s', array('filename', 'name', 'schema_version'));
+    return $query;
+  }
+
+  /**
+   * Tweaks Drupal6SqlBase to set a new database connection for tests.
+   *
+   * @param \Drupal\Core\Database\Connection
+   *   The new conection to use.
+   *
+   * @see \Drupal\migrate\Tests\MigrateSqlTestCase
+   */
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+
+  /**
+   * Tweaks Drupal6SqlBase to set a new module handler for tests.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The new module handler to use.
+   *
+   * @see \Drupal\migrate\Tests\MigrateSqlTestCase
+   */
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * Wrapper method to test protected method moduleExists().
+   */
+  public function moduleExistsWrapper($module) {
+    return parent::moduleExists($module);
+  }
+
+  /**
+   * Wrapper method to test protected method getModuleSchemaVersion().
+   */
+  public function getModuleSchemaVersionWrapper($module) {
+    return parent::getModuleSchemaVersion($module);
+  }
+
+  /**
+   * Wrapper method to test protected method variableGet().
+   */
+  public function variableGetWrapper($name, $default) {
+    return parent::variableGet($name, $default);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return array();
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldInstancePerViewModeTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldInstancePerViewModeTest.php
new file mode 100644
index 0000000..ae0e470
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldInstancePerViewModeTest.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\FieldInstancePerViewModeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 field instance per view mode source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class FieldInstancePerViewModeTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\FieldInstancePerViewMode';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'view_mode_test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_field_instance_per_view_mode',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'entity_type' => 'node',
+      'view_mode' => 4,
+      'type_name' => 'article',
+      'field_name' => 'field_test',
+      'type' => 'text',
+      'module' => 'text',
+      'weight' => 1,
+      'label' => 'above',
+      'display_settings' => array(
+        'weight' => 1,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        4 => array(
+          'format' => 'trimmed',
+          'exclude' => 0,
+        ),
+      ),
+      'widget_settings' => array(),
+    ),
+    array(
+      'entity_type' => 'node',
+      'view_mode' => 'teaser',
+      'type_name' => 'story',
+      'field_name' => 'field_test',
+      'type' => 'text',
+      'module' => 'text',
+      'weight' => 1,
+      'label' => 'above',
+      'display_settings' => array(
+        'weight' => 1,
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'trimmed',
+          'exclude' => 0,
+        ),
+      ),
+      'widget_settings' => array(),
+    ),
+  );
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 per view mode source functionality',
+      'description' => 'Tests D6 fields per view mode source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $field_view_mode) {
+      // These are stored as serialized strings.
+      $field_view_mode['display_settings'] = serialize($field_view_mode['display_settings']);
+      $field_view_mode['widget_settings'] = serialize($field_view_mode['widget_settings']);
+
+      $this->databaseContents['content_node_field'][] = array(
+        'field_name' => $field_view_mode['field_name'],
+        'type' => $field_view_mode['type'],
+        'module' => $field_view_mode['module'],
+      );
+      unset($field_view_mode['type']);
+      unset($field_view_mode['module']);
+
+      $this->databaseContents['content_node_field_instance'][] = $field_view_mode;
+
+      // Update the expected display settings.
+      $this->expectedResults[$k]['display_settings'] = $this->expectedResults[$k]['display_settings'][$field_view_mode['view_mode']];
+
+    }
+    parent::setUp();
+  }
+
+}
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\FieldInstancePerViewMode;
+
+class TestFieldInstancePerViewMode extends FieldInstancePerViewMode {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldInstanceTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldInstanceTest.php
new file mode 100644
index 0000000..e2e5573
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldInstanceTest.php
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\FieldInstanceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 field instance source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class FieldInstanceTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\FieldInstance';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The id of the entity, can be any string.
+    'id' => 'test_fieldinstance',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_fieldinstance',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+  // These are sample result queries.
+  protected $expectedResults = array(
+    array(
+      'field_name' => 'field_body',
+      'type_name' => 'page',
+      'weight' => 1,
+      'label' => 'body',
+      'widget_type' => 'text_textarea',
+      'widget_settings' => '',
+      'display_settings' => '',
+      'description' => '',
+      'widget_module' => 'text',
+      'widget_active' => 1,
+      'required' => 1,
+      'active' => 1,
+      'global_settings' => array(),
+    ),
+  );
+
+  /**
+   * Prepopulate contents with results.
+   */
+  protected function setUp() {
+    $this->expectedResults[0]['widget_settings'] = array(
+      'rows' => 5,
+      'size' => 60,
+      'default_value' => array(
+        array(
+          'value' => '',
+          '_error_element' => 'default_value_widget][field_body][0][value',
+          'default_value_php' => '',
+        ),
+      ),
+    );
+    $this->expectedResults[0]['display_settings'] = array(
+      'label' => array(
+        'format' => 'above',
+        'exclude' => 0,
+      ),
+      'teaser' => array(
+        'format' => 'default',
+        'exclude' => 0,
+      ),
+      'full' => array(
+        'format' => 'default',
+        'exclude' => 0,
+      ),
+    );
+    $this->databaseContents['content_node_field_instance'] = $this->expectedResults;
+    $this->databaseContents['content_node_field_instance'][0]['widget_settings'] = serialize($this->expectedResults[0]['widget_settings']);
+    $this->databaseContents['content_node_field_instance'][0]['display_settings'] = serialize($this->expectedResults[0]['display_settings']);
+
+    $this->databaseContents['content_node_field'][0] = array(
+      'field_name' => 'field_body',
+      'required' => 1,
+      'type' => 'text',
+      'active' => 1,
+      'global_settings' => serialize(array()),
+    );
+    parent::setUp();
+  }
+
+  /**
+   * Provide meta information about this battery of tests.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 field instance source functionality',
+      'description' => 'Tests D6 field instance source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testRetrieval() {
+    // FakeSelect does not support multiple source identifiers, can not test.
+  }
+
+}
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\FieldInstance;
+
+class TestFieldInstance extends FieldInstance {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldTest.php
new file mode 100644
index 0000000..9310024
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FieldTest.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\FieldTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 field source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class FieldTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Field';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The id of the entity, can be any string.
+    'id' => 'test_field',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_field',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+  // These are sample result queries.
+  protected $expectedResults = array(
+    array(
+      'field_name' => 'field_body',
+      'type' => 'text',
+      'global_settings' => '',
+      'required' => 0,
+      'multiple' => 0,
+      'db_storage' => 1,
+      'module' => 'text',
+      'db_columns' => '',
+      'active' => 1,
+      'locked' => 0,
+    ),
+  );
+
+  /**
+   * Prepopulate contents with results.
+   */
+  protected function setUp() {
+    $this->expectedResults[0]['global_settings'] = array(
+      'text_processing' => 0,
+      'max_length' => '',
+      'allowed_values' => '',
+      'allowed_values_php' => '',
+    );
+    $this->expectedResults[0]['db_columns'] = array(
+      'value' => array(
+        'type' => 'text',
+        'size' => 'big',
+        'not null' => '',
+        'sortable' => 1,
+        'views' => 1,
+      ),
+    );
+    $this->databaseContents['content_node_field'] = $this->expectedResults;
+    $this->databaseContents['content_node_field'][0]['global_settings'] = serialize($this->databaseContents['content_node_field'][0]['global_settings']);
+    $this->databaseContents['content_node_field'][0]['db_columns'] = serialize($this->databaseContents['content_node_field'][0]['db_columns']);
+
+    $this->databaseContents['content_node_field_instance'][0]['widget_settings'] = serialize(array());
+    $this->databaseContents['content_node_field_instance'][0]['widget_type'] = 'text_textarea';
+    $this->databaseContents['content_node_field_instance'][0]['field_name'] = 'field_body';
+    parent::setUp();
+  }
+
+  /**
+   * Provide meta information about this battery of tests.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 field source functionality',
+      'description' => 'Tests D6 field source plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Field;
+
+class TestField extends Field {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FileTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FileTest.php
new file mode 100644
index 0000000..b06d27a
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FileTest.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\FileTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 file source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class FileTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\File';
+  const BASE_TABLE = 'file';
+  const BASE_ALIAS = 'f';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_file',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'fid' => 1,
+      'uid' => 1,
+      'filename' => 'migrate-test-file-1.pdf',
+      'filepath' => 'sites/default/files/migrate-test-file-1.pdf',
+      'filemime' => 'application/pdf',
+      'filesize' => 890404,
+      'status' => 1,
+      'timestamp' => 1382255613,
+    ),
+    array(
+      'fid' => 2,
+      'uid' => 1,
+      'filename' => 'migrate-test-file-2.pdf',
+      'filepath' => 'sites/default/files/migrate-test-file-2.pdf',
+      'filemime' => 'application/pdf',
+      'filesize' => 204124,
+      'status' => 1,
+      'timestamp' => 1382255662,
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 file source functionality',
+      'description' => 'Tests D6 file source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->databaseContents['files'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\File;
+
+class TestFile extends File {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FilterFormatTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FilterFormatTest.php
new file mode 100644
index 0000000..5a1b2b5
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/FilterFormatTest.php
@@ -0,0 +1,141 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\FilterFormatsTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests comment migration from D6 to D8.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class FilterFormatTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\FilterFormat';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'highwaterProperty' => array('field' => 'test'),
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_filter_formats',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'format' => 1,
+      'name' => 'Filtered HTML',
+      'roles' => array(1, 2),
+      'cache' => 1,
+      'filters' => array(
+        array(
+          'module' => 'filter',
+          'delta' => 2,
+          'weight' => 0,
+        ),
+        array(
+          'module' => 'filter',
+          'delta' => 0,
+          'weight' => 1,
+        ),
+        array(
+          'module' => 'filter',
+          'delta' => 1,
+          'weight' => 2,
+        ),
+      ),
+    ),
+    array(
+      'format' => 2,
+      'name' => 'Full HTML',
+      'roles' => array(),
+      'cache' => 1,
+      'filters' => array(
+        array(
+          'module' => 'filter',
+          'delta' => 2,
+          'weight' => 0,
+        ),
+        array(
+          'module' => 'filter',
+          'delta' => 1,
+          'weight' => 1,
+        ),
+        array(
+          'module' => 'filter',
+          'delta' => 3,
+          'weight' => 10,
+        ),
+      ),
+    ),
+    array(
+      'format' => 4,
+      'name' => 'Example Custom Format',
+      'roles' => array(4),
+      'cache' => 1,
+      'filters' => array(
+        // This custom format uses a filter defined by a contrib module.
+        array(
+          'module' => 'markdown',
+          'delta' => 1,
+          'weight' => 10,
+        ),
+      ),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 Filter Formats source functionality',
+      'description' => 'Tests D6 filter_formats table source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $fid = 1;
+    foreach ($this->expectedResults as $k => $row) {
+      $row['roles'] = ',' . implode(',', $row['roles']) . ',';
+      foreach ($row['filters'] as $filter) {
+        $this->databaseContents['filters'][$fid] = $filter;
+        $this->databaseContents['filters'][$fid]['format'] = $row['format'];
+        $this->databaseContents['filters'][$fid]['fid'] = $fid;
+        $fid++;
+      }
+      unset($row['filters']);
+      $this->databaseContents['filter_formats'][$k] = $row;
+    }
+    parent::setUp();
+  }
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\FilterFormat;
+
+class TestFilterFormat extends FilterFormat {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/MenuTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/MenuTest.php
new file mode 100644
index 0000000..0127047
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/MenuTest.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\MenuTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 menu source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class MenuTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Menu';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    // This needs to be the identifier of the actual key: cid for comment, nid
+    // for node and so on.
+    'source' => array(
+      'plugin' => 'd6_menu',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+
+  protected $expectedResults = array(
+    array(
+      'menu_name' => 'menu-name-1',
+      'title' => 'menu custom value 1',
+      'description' => 'menu custom description value 1',
+    ),
+    array(
+      'menu_name' => 'menu-name-2',
+      'title' => 'menu custom value 2',
+      'description' => 'menu custom description value 2',
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 menu source functionality',
+      'description' => 'Tests D6 menu source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    // This array stores the database.
+    foreach ($this->expectedResults as $k => $row) {
+      $this->databaseContents['menu_custom'][$k] = $row;
+    }
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Menu;
+
+class TestMenu extends Menu {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeRevisionTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeRevisionTest.php
new file mode 100644
index 0000000..4ff08dd
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeRevisionTest.php
@@ -0,0 +1,362 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\NodeRevisionTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 node revision source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class NodeRevisionTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\NodeRevision';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    // The fake configuration for the source.
+    'source' => array(
+      'node_type' => 'page',
+      'plugin' => 'd6_node_revision',
+      'bundle' => 'page',
+    ),
+    'sourceIds' => array(
+      'vid' => array(
+        'alias' => 'v',
+      ),
+    ),
+    'destinationIds' => array(
+      'vid' => array(
+        // This is where the field schema would go.
+      ),
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      // Node fields.
+      'nid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 1,
+      'uid' => 1,
+      'title' => 'title for revision 1 (node 1)',
+      'body' => 'body for revision 1 (node 1)',
+      'teaser' => 'teaser for revision 1 (node 1)',
+      'log' => 'log for revision 1 (node 1)',
+      'format' => 1,
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
+      // Node fields.
+      'nid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 3,
+      'uid' => 1,
+      'title' => 'title for revision 3 (node 1)',
+      'body' => 'body for revision 3 (node 1)',
+      'teaser' => 'teaser for revision 3 (node 1)',
+      'log' => 'log for revision 3 (node 1)',
+      'format' => 1,
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
+      // Node fields.
+      'nid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 4,
+      'uid' => 1,
+      'title' => 'title for revision 4 (node 1)',
+      'body' => 'body for revision 4 (node 1)',
+      'teaser' => 'teaser for revision 4 (node 1)',
+      'log' => 'log for revision 4 (node 1)',
+      'format' => 1,
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
+      // Node fields.
+      'nid' => 2,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279290908,
+      'changed' => 1279308993,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 2,
+      'uid' => 1,
+      'title' => 'title for revision 2 (node 2)',
+      'body' => 'body for revision 2 (node 2)',
+      'teaser' => 'teaser for revision 2 (node 2)',
+      'log' => 'log for revision 2 (node 2)',
+      'format' => 1,
+      'field_test_two' => array(
+        'test field node 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 2',
+      ),
+    ),
+  );
+
+  protected $fields = array(
+    'field_test_one' => array(
+      'content_node_field_instance' => array(
+        'field_name' => 'field_test_one',
+        'type_name' => 'page',
+        'weight' => 1,
+        'label' => 'Field Label One',
+        'widget_type' => 'text_textfield',
+        'widget_settings' => 'a:4:{s:4:"rows";i:5;s:4:"size";s:2:"60";s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:0:"";s:14:"_error_element";s:42:"default_value_widget][field_test][0][value";}}s:17:"default_value_php";N;}',
+        'display_settings' => 'a:6:{s:6:"weight";s:2:"31";s:6:"parent";s:0:"";s:5:"label";a:1:{s:6:"format";s:5:"above";}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}',
+        'description' => '',
+        'widget_module' => 'text',
+        'widget_active' => 1,
+      ),
+      'content_node_field' => array(
+        'field_name' => 'field_test_one',
+        'type' => 'text',
+        'global_settings' => 'a:4:{s:15:"text_processing";s:1:"0";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+        'required' => 0,
+        'multiple' => 0,
+        'db_storage' => 1,
+        'module' => 'text',
+        'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}',
+        'active' => 1,
+        'locked' => 0,
+      ),
+    ),
+    'field_test_two' => array(
+      'content_node_field_instance' => array(
+        'field_name' => 'field_test_two',
+        'type_name' => 'page',
+        'weight' => 1,
+        'label' => 'Field Label One',
+        'widget_type' => 'text_textfield',
+        'widget_settings' => 'a:4:{s:4:"rows";i:5;s:4:"size";s:2:"60";s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:0:"";s:14:"_error_element";s:42:"default_value_widget][field_test][0][value";}}s:17:"default_value_php";N;}',
+        'display_settings' => 'a:6:{s:6:"weight";s:2:"31";s:6:"parent";s:0:"";s:5:"label";a:1:{s:6:"format";s:5:"above";}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}',
+        'description' => '',
+        'widget_module' => 'text',
+        'widget_active' => 1,
+      ),
+      'content_node_field' => array(
+        'field_name' => 'field_test_two',
+        'type' => 'text',
+        'global_settings' => 'a:4:{s:15:"text_processing";s:1:"0";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+        'required' => 0,
+        'multiple' => 1,
+        'db_storage' => 0,
+        'module' => 'text',
+        'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}',
+        'active' => 1,
+        'locked' => 0,
+      ),
+
+      // Multi field values.
+      'values' => array(
+        array(
+          'vid' => 1,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 1,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 3,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 3,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 4,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 4,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 2,
+          'nid' => 2,
+          'field_test_two_value' => 'test field node 2',
+          'delta' => 0,
+        ),
+      ),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 node revision source functionality',
+      'description' => 'Tests D6 node revision source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      $this->databaseContents['node_revisions'][$k]['nid'] = $row['nid'];
+      $this->databaseContents['node_revisions'][$k]['vid'] = $row['vid'];
+      $this->databaseContents['node_revisions'][$k]['uid'] = $row['uid'];
+      $this->databaseContents['node_revisions'][$k]['title'] = $row['title'];
+      $this->databaseContents['node_revisions'][$k]['body'] = $row['body'];
+      $this->databaseContents['node_revisions'][$k]['teaser'] = $row['teaser'];
+      $this->databaseContents['node_revisions'][$k]['format'] = $row['format'];
+      $this->databaseContents['node_revisions'][$k]['log'] = $row['log'];
+
+      unset($row['body']);
+      unset($row['teaser']);
+      unset($row['format']);
+      unset($row['log']);
+
+      //$this->databaseContents['node'][$k] = $row;
+      $this->databaseContents['node'][$row['nid']] = $row;
+
+      // Add the column field storage data.
+      $table = 'content_type_' . $row['type'];
+      foreach ($row['fields'] as $field_name => $value) {
+        $this->databaseContents[$table][$k][$field_name . "_value"] = $value;
+        $this->databaseContents[$table][$k]['vid'] = $row['vid'];
+        $this->databaseContents[$table][$k]['nid'] = $row['nid'];
+      }
+      // Unset from results.
+      unset($row['fields']);
+      unset($this->expectedResults[$k]['fields']);
+    }
+
+    // Setup field tables.
+    foreach ($this->fields as $field) {
+      $cnf = $field['content_node_field'];
+      $this->databaseContents['content_node_field'][] = $cnf;
+      $this->databaseContents['content_node_field_instance'][] = $field['content_node_field_instance'];
+
+      // If it's a multi-field then setup a new table.
+      if ($cnf['multiple']) {
+        foreach ($field['values'] as $value) {
+          $this->databaseContents['content_' . $cnf['field_name']][] = $value;
+        }
+      }
+    }
+
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testRetrieval() {
+    // FakeSelect does not support multiple source identifiers, can not test.
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\NodeRevision;
+
+class TestNodeRevision extends NodeRevision {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeTest.php
new file mode 100644
index 0000000..dc21bf3
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeTest.php
@@ -0,0 +1,148 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\NodeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 node source
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class NodeTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Node';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    // The fake configuration for the source.
+    'source' => array(
+      'bundle' => 'page',
+      'plugin' => 'd6_node',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      // Node fields.
+      'nid' => 1,
+      'vid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'title' => 'node title 1',
+      'uid' => 1,
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'body' => 'body for node 1',
+      'teaser' => 'teaser for node 1',
+      'format' => 1,
+    ),
+    array(
+      // Node fields.
+      'nid' => 2,
+      'vid' => 2,
+      'type' => 'page',
+      'language' => 'en',
+      'title' => 'node title 2',
+      'uid' => 1,
+      'status' => 1,
+      'created' => 1279290908,
+      'changed' => 1279308993,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'body' => 'body for node 2',
+      'teaser' => 'teaser for node 2',
+      'format' => 1,
+    ),
+    array(
+      // Node fields.
+      'nid' => 5,
+      'vid' => 5,
+      'type' => 'article',
+      'language' => 'en',
+      'title' => 'node title 5',
+      'uid' => 1,
+      'status' => 1,
+      'created' => 1279290908,
+      'changed' => 1279308993,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'body' => 'body for node 5',
+      'teaser' => 'body for node 5',
+      'format' => 1,
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 node source functionality',
+      'description' => 'Tests D6 node source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      foreach (array('nid', 'vid', 'title', 'uid', 'body', 'teaser', 'format') as $i => $field) {
+        $this->databaseContents['node_revisions'][$k][$field] = $row[$field];
+        // Keep nid and vid.
+        if ($i > 1) {
+          unset($row[$field]);
+        }
+      }
+      $this->databaseContents['node'][$k] = $row;
+    }
+
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Node;
+
+class TestNode extends Node {
+  protected $cckSchemaCorrect = true;
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeTypeTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeTypeTest.php
new file mode 100644
index 0000000..c67219c
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/NodeTypeTest.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\NodeTypeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 node type source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class NodeTypeTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\NodeType';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test_nodetypes',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_nodetype',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+  // These are sample result queries.
+  protected $expectedResults = array(
+    array(
+      'type' => 'page',
+      'name' => 'Page',
+      'module' => 'node',
+      'description' => 'A <em>page</em>, similar in form to a <em>story</em>, is a simple method for creating and displaying information that rarely changes, such as an "About us" section of a website. By default, a <em>page</em> entry does not allow visitor comments and is not featured on the site\'s initial home page.',
+      'help' => '',
+      'has_title' => 1,
+      'title_label' => 'Title',
+      'has_body' => 1,
+      'body_label' => 'Body',
+      'min_word_count' => 0,
+      'custom' => 1,
+      'modified' => 0,
+      'locked' => 0,
+      'orig_type' => 'page',
+    ),
+    array(
+      'type' => 'story',
+      'name' => 'Story',
+      'module' => 'node',
+      'description' => 'A <em>story</em>, similar in form to a <em>page</em>, is ideal for creating and displaying content that informs or engages website visitors. Press releases, site announcements, and informal blog-like entries may all be created with a <em>story</em> entry. By default, a <em>story</em> entry is automatically featured on the site\'s initial home page, and provides the ability to post comments.',
+      'help' => '',
+      'has_title' => 1,
+      'title_label' => 'Title',
+      'has_body' => 1,
+      'body_label' => 'Body',
+      'min_word_count' => 0,
+      'custom' => 1,
+      'modified' => 0,
+      'locked' => 0,
+      'orig_type' => 'story',
+    ),
+  );
+
+  /**
+   * Prepopulate contents with results.
+   */
+  protected function setUp() {
+    $this->databaseContents['node_type'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 node type source functionality',
+      'description' => 'Tests D6 node type source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\NodeType;
+
+class TestNodeType extends NodeType {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ProfileFieldTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ProfileFieldTest.php
new file mode 100644
index 0000000..a05e338
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ProfileFieldTest.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\ProfileFieldTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 profile source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class ProfileFieldTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\ProfileField';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The id of the entity, can be any string.
+    'id' => 'test_profile_fields',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_profile_field',
+    ),
+  );
+
+  // We need to set up the database contents; it's easier to do that below.
+  // These are sample result queries.
+  //TODO: Add multiple cases
+  protected $expectedResults = array(
+    array(
+      'fid' => 1,
+      'title' => 'First name',
+      'name' => 'profile_first_name',
+      'explanation' => 'First name user',
+      'category' => 'profile',
+      'page' => '',
+      'type' => 'textfield',
+      'weight' => 0,
+      'required' => 1,
+      'register' => 0,
+      'visibility' => 2,
+      'autocomplete' => 0,
+      'options' => '',
+    ),
+    array(
+      'fid' => 2,
+      'title' => 'Last name',
+      'name' => 'profile_last_name',
+      'explanation' => 'Last name user',
+      'category' => 'profile',
+      'page' => '',
+      'type' => 'textfield',
+      'weight' => 0,
+      'required' => 0,
+      'register' => 0,
+      'visibility' => 2,
+      'autocomplete' => 0,
+      'options' => '',
+    ),
+    array(
+      'fid' => 3,
+      'title' => 'Policy',
+      'name' => 'profile_policy',
+      'explanation' => 'A checkbox that say if you accept policy of website',
+      'category' => 'profile',
+      'page' => '',
+      'type' => 'checkbox',
+      'weight' => 0,
+      'required' => 1,
+      'register' => 1,
+      'visibility' => 2,
+      'autocomplete' => 0,
+      'options' => '',
+    ),
+  );
+
+  /**
+   * Prepopulate contents with results.
+   */
+  protected function setUp() {
+    $this->databaseContents['profile_fields'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+  /**
+   * Provide meta information about this battery of tests.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 profile field source functionality',
+      'description' => 'Tests D6 profile field source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\ProfileField;
+
+class TestProfileField extends ProfileField {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/RoleSourceTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/RoleSourceTest.php
deleted file mode 100644
index 8cefa6a..0000000
--- a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/RoleSourceTest.php
+++ /dev/null
@@ -1,144 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\migrate_drupal\Tests\source\d6\RoleSourceTest.
- */
-
-namespace Drupal\migrate_drupal\Tests\source\d6;
-
-use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
-
-/**
- * Tests user role migration from D6 to D8.
- *
- * @group migrate_drupal
- * @group Drupal
- */
-class RoleSourceTest extends MigrateSqlSourceTestCase {
-
-  // The plugin system is not working during unit testing so the source plugin
-  // class needs to be manually specified.
-  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Role';
-
-  // The fake Migration configuration entity.
-  protected $migrationConfiguration = array(
-    // The ID of the entity, can be any string.
-    'id' => 'test',
-    // Leave it empty for now.
-    'idlist' => array(),
-    // This needs to be the identifier of the actual key: cid for comment, nid
-    // for node and so on.
-    'source' => array(
-      'plugin' => 'drupal6_user_role',
-    ),
-    'sourceIds' => array(
-      'rid' => array(
-        // This is where the field schema would go but for now we need to
-        // specify the table alias for the key. Most likely this will be the
-        // same as BASE_ALIAS.
-        'alias' => 'r',
-      ),
-    ),
-    'destinationIds' => array(
-      'rid' => array(
-        // This is where the field schema would go.
-      ),
-    ),
-  );
-
-  protected $expectedResults = array(
-    array(
-      'rid' => 1,
-      'name' => 'anonymous user',
-      'permissions' => array(
-        array(
-          'pid' => 1,
-          'rid' => 1,
-          'perm' => array(
-            'access content',
-          ),
-          'tid' => 0,
-        ),
-      ),
-    ),
-    array(
-      'rid' => 2,
-      'name' => 'authenticated user',
-      'permissions' => array(
-        array(
-          'pid' => 2,
-          'rid' => 2,
-          'perm' => array(
-            'access comments',
-            'access content',
-            'post comments',
-            'post comments without approval',
-          ),
-          'tid' => 0,
-        ),
-      ),
-    ),
-    array(
-      'rid' => 3,
-      'name' => 'administrator',
-      'permissions' => array(
-        array(
-          'pid' => 3,
-          'rid' => 3,
-          'perm' => array(
-            'access comments',
-            'administer comments',
-            'post comments',
-            'post comments without approval',
-            'access content',
-            'administer content types',
-            'administer nodes',
-          ),
-          'tid' => 0,
-        ),
-      ),
-    ),
-  );
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getInfo() {
-    return array(
-      'name' => 'D6 role source functionality',
-      'description' => 'Tests D6 role source plugin.',
-      'group' => 'Migrate Drupal',
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setUp() {
-    foreach ($this->expectedResults as $k => $row) {
-      foreach ($row['permissions'] as $perm) {
-        $this->databaseContents['permission'][$perm['pid']] = $perm;
-        $this->databaseContents['permission'][$perm['pid']]['perm'] = implode(',', $perm['perm']);
-        $this->databaseContents['permission'][$perm['pid']]['rid'] = $row['rid'];
-      }
-      unset($row['permissions']);
-      $this->databaseContents['role'][$k] = $row;
-    }
-    parent::setUp();
-  }
-
-}
-
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\migrate_drupal\Plugin\migrate\source\d6\Role;
-
-class TestRole extends Role {
-  function setDatabase(Connection $database) {
-    $this->database = $database;
-  }
-  function setModuleHandler(ModuleHandlerInterface $module_handler) {
-    $this->moduleHandler = $module_handler;
-  }
-}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/RoleTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/RoleTest.php
new file mode 100644
index 0000000..a346a79
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/RoleTest.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\RoleTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 user role source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class RoleTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Role';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    // This needs to be the identifier of the actual key: cid for comment, nid
+    // for node and so on.
+    'source' => array(
+      'plugin' => 'd6_user_role',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'rid' => 1,
+      'name' => 'anonymous user',
+      'permissions' => array(
+        'access content',
+      ),
+    ),
+    array(
+      'rid' => 2,
+      'name' => 'authenticated user',
+      'permissions' => array(
+        'access comments',
+        'access content',
+        'post comments',
+        'post comments without approval',
+      ),
+    ),
+    array(
+      'rid' => 3,
+      'name' => 'administrator',
+      'permissions' => array(
+        'access comments',
+        'administer comments',
+        'post comments',
+        'post comments without approval',
+        'access content',
+        'administer content types',
+        'administer nodes',
+      ),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 role source functionality',
+      'description' => 'Tests D6 role source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $row) {
+      $this->databaseContents['permission'][] = array(
+        'perm' => implode(', ', $row['permissions']),
+        'rid' => $row['rid'],
+      );
+      unset($row['permissions']);
+      $this->databaseContents['role'][] = $row;
+    }
+    $this->databaseContents['filter_formats'][] = array(
+      'format' => 1,
+      'roles' => '',
+    );
+    parent::setUp();
+  }
+
+}
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Role;
+
+class TestRole extends Role {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermSourceWithVocabularyFilterTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermSourceWithVocabularyFilterTest.php
new file mode 100644
index 0000000..cd60c86
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermSourceWithVocabularyFilterTest.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @file
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+
+/**
+ * Tests the Drupal 6 taxonomy term source with vocabulary filter.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class TermSourceWithVocabularyFilterTest extends TermTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 taxonomy term source with vocabulary filter functionality',
+      'description' => 'Tests D6 taxonomy term source plugin with vocabulary filter.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->migrationConfiguration['source']['vocabulary'] = array(5);
+    parent::setUp();
+    $this->expectedResults = array_values(array_filter($this->expectedResults, function($result) {
+      return $result['vid'] == 5;
+    }));
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermTest.php
new file mode 100644
index 0000000..aed5334
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermTest.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\TermTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+/**
+ * Tests the Drupal 6 taxonomy term source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class TermTest extends TermTestBase {
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermTestBase.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermTestBase.php
new file mode 100644
index 0000000..7b9580e
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TermTestBase.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\TermTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Base class for the term source tests.
+ */
+class TermTestBase extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Term';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'highwaterProperty' => array('field' => 'test'),
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_taxonomy_term',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'tid' => 1,
+      'vid' => 5,
+      'name' => 'name value 1',
+      'description' => 'description value 1',
+      'weight' => 0,
+      'parent' => array(0),
+    ),
+    array(
+      'tid' => 2,
+      'vid' => 6,
+      'name' => 'name value 2',
+      'description' => 'description value 2',
+      'weight' => 0,
+      'parent' => array(0),
+    ),
+    array(
+      'tid' => 3,
+      'vid' => 6,
+      'name' => 'name value 3',
+      'description' => 'description value 3',
+      'weight' => 0,
+      'parent' => array(0),
+    ),
+    array(
+      'tid' => 4,
+      'vid' => 5,
+      'name' => 'name value 4',
+      'description' => 'description value 4',
+      'weight' => 1,
+      'parent' => array(1),
+    ),
+    array(
+      'tid' => 5,
+      'vid' => 6,
+      'name' => 'name value 5',
+      'description' => 'description value 5',
+      'weight' => 1,
+      'parent' => array(2),
+    ),
+    array(
+      'tid' => 6,
+      'vid' => 6,
+      'name' => 'name value 6',
+      'description' => 'description value 6',
+      'weight' => 0,
+      'parent' => array(3, 2),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 taxonomy term source functionality',
+      'description' => 'Tests D6 taxonomy term source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      foreach ($row['parent'] as $parent) {
+        $this->databaseContents['term_hierarchy'][] = array(
+          'tid' => $row['tid'],
+          'parent' => $parent,
+        );
+      }
+      unset($row['parent']);
+      $this->databaseContents['term_data'][$k] = $row;
+    }
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Term ;
+
+class TestTerm extends Term {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TestComment.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TestComment.php
new file mode 100644
index 0000000..aa4e604
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TestComment.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\TestComment.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Comment;
+
+class TestComment extends Comment {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TestTerm.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TestTerm.php
new file mode 100644
index 0000000..bf822c9
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/TestTerm.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\TestTerm.
+ */
+
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Term;
+
+class TestTerm extends Term {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UrlAliasTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UrlAliasTest.php
new file mode 100644
index 0000000..6c81674
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UrlAliasTest.php
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\UrlAliasTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 url alias source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class UrlAliasTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\UrlAlias';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'highwaterProperty' => array('field' => 'test'),
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_url_alias',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'pid' => 1,
+      'src' => 'node/1',
+      'dst' => 'test-article',
+      'language' => 'en',
+    ),
+    array(
+      'pid' => 2,
+      'src' => 'node/2',
+      'dst' => 'another-alias',
+      'language' => 'en',
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $row) {
+      $this->databaseContents['url_alias'][] = $row;
+    }
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 url alias source functionality',
+      'description' => 'Tests the D6 url alias migrations.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\UrlAlias;
+
+class TestUrlAlias extends UrlAlias {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UserPictureTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UserPictureTest.php
new file mode 100644
index 0000000..633064e
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UserPictureTest.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\UserPictureTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 user picture source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class UserPictureTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\UserPicture';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test_user_picture',
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_user_picture',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'uid' => 1,
+      'access' => 1382835435,
+      'picture' => 'sites/default/files/pictures/picture-1.jpg',
+    ),
+    array(
+      'uid' => 2,
+      'access' => 1382835436,
+      'picture' => 'sites/default/files/pictures/picture-2.jpg',
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->databaseContents['users'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 user picture source functionality',
+      'description' => 'Tests D6 user picture source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\UserPicture;
+
+class TestUserPicture extends UserPicture {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UserTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UserTest.php
new file mode 100644
index 0000000..af2aefe
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/UserTest.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\CommentTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 user source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class UserTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\User';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_user',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'uid' => 2,
+      'name' => 'admin',
+      // @todo d6 hash?
+      'pass' => '1234',
+      'mail' => 'admin@example.com',
+      'theme' => '',
+      'signature' => '',
+      'signature_format' => 0,
+      'created' => 1279402616,
+      'access' => 1322981278,
+      'login' => 1322699994,
+      'status' => 0,
+      'timezone' => 'America/Lima',
+      'language' => 'en',
+      // @todo Add the file when needed.
+      'picture' => 'sites/default/files/pictures/picture-1.jpg',
+      'init' => 'admin@example.com',
+      'data' => NULL,
+    ),
+    array(
+      'uid' => 4,
+      'name' => 'alice',
+      // @todo d6 hash?
+      'pass' => '1234',
+      'mail' => 'alice@example.com',
+      'theme' => '',
+      'signature' => '',
+      'signature_format' => 0,
+      'created' => 1322981368,
+      'access' => 1322982419,
+      'login' => 132298140,
+      'status' => 0,
+      'timezone' => 'America/Lima',
+      'language' => 'en',
+      'picture' => '',
+      'init' => 'alice@example.com',
+      'data' => NULL,
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 user source functionality',
+      'description' => 'Tests D6 user source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      $this->databaseContents['users'][$k] = $row;
+    }
+    $this->databaseContents['users_roles'] = array();
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\User;
+
+class TestUser extends User {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ViewModeTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ViewModeTest.php
new file mode 100644
index 0000000..8e07a8e
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/ViewModeTest.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\ViewModeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 per view mode source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class ViewModeTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\ViewMode';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'view_mode_test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_field_instance_view_mode',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'entity_type' => 'node',
+      'view_mode' => '4',
+    ),
+    array(
+      'entity_type' => 'node',
+      'view_mode' => 'teaser',
+    ),
+    array(
+      'entity_type' => 'node',
+      'view_mode' => 'full',
+    ),
+  );
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 view mode source functionality',
+      'description' => 'Tests D6 view mode source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+
+    $this->databaseContents['content_node_field_instance'][] = array(
+      'display_settings' => serialize(array(
+        'weight' => '31',
+        'parent' => '',
+        'label' => array(
+          'format' => 'above',
+        ),
+        'teaser' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        'full' => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+        4 => array(
+          'format' => 'default',
+          'exclude' => 0,
+        ),
+      )),
+    );
+
+    parent::setUp();
+  }
+
+}
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\ViewMode;
+
+class TestViewMode extends ViewMode {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/VocabularyTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/VocabularyTest.php
new file mode 100644
index 0000000..b58e8fa
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/VocabularyTest.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\source\d6\VocabularyTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests the Drupal 6 vocabulary source.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class VocabularyTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Vocabulary';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_vocabulary',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'vid' => 1,
+      'name' => 'Tags',
+      'description' => 'Tags description.',
+      'help' => 1,
+      'relations' => 0,
+      'hierarchy' => 0,
+      'multiple' => 0,
+      'required' => 0,
+      'tags' => 1,
+      'module' => 'taxonomy',
+      'weight' => 0,
+      'node_types' => array('page', 'article'),
+    ),
+    array(
+      'vid' => 2,
+      'name' => 'Categories',
+      'description' => 'Categories description.',
+      'help' => 1,
+      'relations' => 1,
+      'hierarchy' => 1,
+      'multiple' => 0,
+      'required' => 1,
+      'tags' => 0,
+      'module' => 'taxonomy',
+      'weight' => 0,
+      'node_types' => array('article'),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 vocabulary source functionality',
+      'description' => 'Tests D6 vocabulary source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $row) {
+      foreach ($row['node_types'] as $type) {
+        $this->databaseContents['vocabulary_node_types'][] = array(
+          'type' => $type,
+          'vid' => $row['vid'],
+        );
+      }
+      unset($row['node_types']);
+    }
+    $this->databaseContents['vocabulary'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Vocabulary;
+
+class TestVocabulary extends Vocabulary {
+
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+
+}
