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/Book.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Book.php
new file mode 100644
index 0000000..dc95d7a
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Book.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\source\d6\Book.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 book source.
+ *
+ * @MigrateSource(
+ *   id = "d6_book"
+ * )
+ */
+class Book extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('book', 'b')->fields('b', array('nid', 'bid'));
+    $query->join('menu_links', 'ml', 'b.mlid = ml.mlid');
+    $ml_fields = array('mlid', 'plid', 'weight', 'has_children', 'depth');
+    for ($i = 1; $i <= 9; $i++) {
+      $field = "p$i";
+      $ml_fields[] = $field;
+      $query->orderBy($field);
+    }
+    $query->fields('ml', $ml_fields);
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['mlid']['type'] = 'integer';
+    $ids['mlid']['alias'] = 'ml';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'nid' => $this->t('Node ID'),
+      'bid' => $this->t('Book ID'),
+      'mlid' => $this->t('Menu link ID'),
+      'plid' => $this->t('Parent link ID'),
+      'weight' => $this->t('Weight'),
+      'p1' => $this->t('The first mlid in the materialized path.'),
+      'p2' => $this->t('The second mlid in the materialized path.'),
+      'p3' => $this->t('The third mlid in the materialized path.'),
+      'p4' => $this->t('The fourth mlid in the materialized path.'),
+      'p5' => $this->t('The fifth mlid in the materialized path.'),
+      'p6' => $this->t('The sixth mlid in the materialized path.'),
+      'p7' => $this->t('The seventh mlid in the materialized path.'),
+      'p8' => $this->t('The eight mlid in the materialized path.'),
+      'p9' => $this->t('The nine mlid in the materialized path.'),
+    );
+  }
+
+}
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..1f241c2
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/CckFieldValues.php
@@ -0,0 +1,270 @@
+<?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";
+        $data = $this
+          ->select($table, 't')
+          ->fields('t', array('delta') + $field_info['columns'])
+          ->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/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/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..9756641
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Node.php
@@ -0,0 +1,109 @@
+<?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_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/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/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/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/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/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/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;
+  }
+
+}
