diff --git a/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php b/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php
index 2b5238c..42c6289 100755
--- a/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php
+++ b/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php
@@ -31,6 +31,15 @@ public function query() {
       ->condition('fc.storage_active', 1);
     $query->innerJoin('field_config', 'fc', 'fci.field_id = fc.id');
 
+    // Optionally filter by entity type and bundle.
+    if (isset($this->configuration['entity_type'])) {
+      $query->condition('entity_type', $this->configuration['entity_type']);
+
+      if (isset($this->configuration['bundle'])) {
+        $query->condition('bundle', $this->configuration['bundle']);
+      }
+    }
+
     return $query;
   }
 
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php
new file mode 100644
index 0000000..aa69325
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d7;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Base class for D7 source plugins which need to collect field values from
+ * the Field API.
+ */
+abstract class FieldableEntity extends DrupalSqlBase {
+
+  /**
+   * Returns all non-deleted field instances attached to a specific entity type.
+   *
+   * @param string $entity_type
+   *   The entity type ID.
+   * @param string|NULL $bundle
+   *   (optional) The bundle.
+   *
+   * @return array[]
+   *   The field instances, keyed by field name.
+   */
+  protected function getFields($entity_type, $bundle = NULL) {
+    return $this->select('field_config_instance', 'fci')
+      ->fields('fci')
+      ->condition('entity_type', $entity_type)
+      ->condition('bundle', isset($bundle) ? $bundle : $entity_type)
+      ->condition('deleted', 0)
+      ->execute()
+      ->fetchAllAssoc('field_name');
+  }
+
+  /**
+   * Retrieves field values for a single field of a single entity.
+   *
+   * @param string $entity_type
+   *   The entity type.
+   * @param string $field
+   *   The field name.
+   * @param int $entity_id
+   *   The entity ID.
+   * @param int|null $revision_id
+   *   (optional) The entity revision ID.
+   *
+   * @return array
+   *   The raw field values, keyed by delta.
+   *
+   * @todo Support multilingual field values.
+   */
+  protected function getFieldValues($entity_type, $field, $entity_id, $revision_id = NULL) {
+    $table = (isset($revision_id) ? 'field_revision_' : 'field_data_') . $field;
+    $query = $this->select($table, 't')
+      ->fields('t')
+      ->condition('entity_type', $entity_type)
+      ->condition('entity_id', $entity_id)
+      ->condition('deleted', 0);
+    if (isset($revision_id)) {
+      $query->condition('revision_id', $revision_id);
+    }
+    $values = [];
+    foreach ($query->execute() as $row) {
+      foreach ($row as $key => $value) {
+        $delta = $row['delta'];
+        if (strpos($key, $field) === 0) {
+          $column = substr($key, strlen($field) + 1);
+          $values[$delta][$column] = $value;
+        }
+      }
+    }
+    return $values;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/Users.php b/core/modules/migrate_drupal/src/Tests/Table/d7/Users.php
index e14c767..47f80c3 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/Users.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/Users.php
@@ -140,8 +140,25 @@ public function load() {
       'init',
       'data',
     ))
-    ->execute();
+    ->values(array(
+      'uid' => '2',
+      'name' => 'Odo',
+      'pass' => '$S$DZ4P7zZOh92vgrgZDBbv8Pu6lQB337OJ1wsOy21602G4A5F7.M9K',
+      'mail' => 'odo@local.host',
+      'theme' => '',
+      'signature' => '',
+      'signature_format' => 'filtered_html',
+      'created' => '1440532218',
+      'access' => '0',
+      'login' => '0',
+      'status' => '1',
+      'timezone' => 'America/Chicago',
+      'language' => '',
+      'picture' => '0',
+      'init' => 'odo@local.host',
+      'data' => 'a:1:{s:7:"contact";i:1;}',
+    ))->execute();
   }
 
 }
-#c4f52bf31f5fe27b4742639dea21039a
+#b33078324746c718e26c067131e97dcd
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/Variable.php b/core/modules/migrate_drupal/src/Tests/Table/d7/Variable.php
index 0591deb..64eed83 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/Variable.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/Variable.php
@@ -123,7 +123,7 @@ public function load() {
       'value' => 's:43:"_vWFj-dRR2rNoHDwl7N__J9uZNutDcLz3w4tlPJzRAM";',
     ))->values(array(
       'name' => 'cron_last',
-      'value' => 'i:1432653550;',
+      'value' => 'i:1440523817;',
     ))->values(array(
       'name' => 'css_js_query_string',
       'value' => 's:6:"nihmmw";',
@@ -150,7 +150,7 @@ public function load() {
       'value' => 's:43:"9eRJWxrMwQ5CufYJjXBZbPGz_t8vPIYRQr18PamdKmM";',
     ))->values(array(
       'name' => 'email__active_tab',
-      'value' => 's:25:"edit-email-password-reset";',
+      'value' => 's:27:"edit-email-pending-approval";',
     ))->values(array(
       'name' => 'field_bundle_settings_comment__comment_node_test_content_type',
       'value' => 'a:2:{s:10:"view_modes";a:0:{}s:12:"extra_fields";a:2:{s:4:"form";a:2:{s:6:"author";a:1:{s:6:"weight";s:2:"-2";}s:7:"subject";a:1:{s:6:"weight";s:2:"-1";}}s:7:"display";a:0:{}}}',
@@ -393,61 +393,61 @@ public function load() {
       'value' => 'i:86400;',
     ))->values(array(
       'name' => 'user_mail_cancel_confirm_body',
-      'value' => "s:381:\"[user:name],\r\n\r\nA request to cancel your account has been made at [site:name].\r\n\r\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\r\n\r\n[user:cancel-url]\r\n\r\nNOTE: The cancellation of your account is not reversible.\r\n\r\nThis link expires in one day and nothing will happen if it is not used.\r\n\r\n--  [site:name] team\";",
+      'value' => 's:55:"A little birdie said you wanted to cancel your account.";',
     ))->values(array(
       'name' => 'user_mail_cancel_confirm_subject',
-      'value' => 's:59:"Account cancellation request for [user:name] at [site:name]";',
+      'value' => 's:13:"Are you sure?";',
     ))->values(array(
       'name' => 'user_mail_password_reset_body',
-      'value' => "s:407:\"[user:name],\r\n\r\nA request to reset the password for your account has been made at [site:name].\r\n\r\nYou may now log in by clicking this link or copying and pasting it to your browser:\r\n\r\n[user:one-time-login-url]\r\n\r\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\r\n\r\n--  [site:name] team\";",
+      'value' => "s:32:\"Nope! You're locked out forever.\";",
     ))->values(array(
       'name' => 'user_mail_password_reset_subject',
-      'value' => 's:60:"Replacement login information for [user:name] at [site:name]";',
+      'value' => 's:17:"Fix your password";',
     ))->values(array(
       'name' => 'user_mail_register_admin_created_body',
-      'value' => "s:476:\"[user:name],\r\n\r\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\r\n\r\n[user:one-time-login-url]\r\n\r\nThis link can only be used once to log in and will lead you to a page where you can set your password.\r\n\r\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\r\n\r\nusername: [user:name]\r\npassword: Your password\r\n\r\n--  [site:name] team\";",
+      'value' => 's:30:"...and she could take it away.";',
     ))->values(array(
       'name' => 'user_mail_register_admin_created_subject',
-      'value' => 's:58:"An administrator created an account for you at [site:name]";',
+      'value' => 's:24:"Gawd made you an account";',
     ))->values(array(
       'name' => 'user_mail_register_no_approval_required_body',
-      'value' => "s:450:\"[user:name],\r\n\r\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\r\n\r\n[user:one-time-login-url]\r\n\r\nThis link can only be used once to log in and will lead you to a page where you can set your password.\r\n\r\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\r\n\r\nusername: [user:name]\r\npassword: Your password\r\n\r\n--  [site:name] team\";",
+      'value' => 's:59:"You can now log in if you can figure out how to use Drupal!";',
     ))->values(array(
       'name' => 'user_mail_register_no_approval_required_subject',
-      'value' => 's:46:"Account details for [user:name] at [site:name]";',
+      'value' => 's:8:"Welcome!";',
     ))->values(array(
       'name' => 'user_mail_register_pending_approval_body',
-      'value' => "s:287:\"[user:name],\r\n\r\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another e-mail containing information about how to log in, set your password, and other details.\r\n\r\n\r\n--  [site:name] team\";",
+      'value' => 's:61:"...you will join our Circle. Let the Drupal flow through you.";',
     ))->values(array(
       'name' => 'user_mail_register_pending_approval_subject',
-      'value' => 's:71:"Account details for [user:name] at [site:name] (pending admin approval)";',
+      'value' => 's:7:"Soon...";',
     ))->values(array(
       'name' => 'user_mail_status_activated_body',
-      'value' => "s:461:\"[user:name],\r\n\r\nYour account at [site:name] has been activated.\r\n\r\nYou may now log in by clicking this link or copying and pasting it into your browser:\r\n\r\n[user:one-time-login-url]\r\n\r\nThis link can only be used once to log in and will lead you to a page where you can set your password.\r\n\r\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\r\n\r\nusername: [user:name]\r\npassword: Your password\r\n\r\n--  [site:name] team\";",
+      'value' => 's:57:"Your account was activated, and there was much rejoicing.";',
     ))->values(array(
       'name' => 'user_mail_status_activated_notify',
       'value' => 'i:1;',
     ))->values(array(
       'name' => 'user_mail_status_activated_subject',
-      'value' => 's:57:"Account details for [user:name] at [site:name] (approved)";',
+      'value' => 's:25:"Your account is approved!";',
     ))->values(array(
       'name' => 'user_mail_status_blocked_body',
-      'value' => "s:85:\"[user:name],\r\n\r\nYour account on [site:name] has been blocked.\r\n\r\n--  [site:name] team\";",
+      'value' => 's:72:"You no longer please the robot overlords. Go to your room and chill out.";',
     ))->values(array(
       'name' => 'user_mail_status_blocked_notify',
-      'value' => 'i:0;',
+      'value' => 'i:1;',
     ))->values(array(
       'name' => 'user_mail_status_blocked_subject',
-      'value' => 's:56:"Account details for [user:name] at [site:name] (blocked)";',
+      'value' => 's:7:"BEGONE!";',
     ))->values(array(
       'name' => 'user_mail_status_canceled_body',
-      'value' => "s:86:\"[user:name],\r\n\r\nYour account on [site:name] has been canceled.\r\n\r\n--  [site:name] team\";",
+      'value' => 's:75:"The gates of Drupal are closed to you. Now you will work in the salt mines.";',
     ))->values(array(
       'name' => 'user_mail_status_canceled_notify',
-      'value' => 'i:0;',
+      'value' => 'i:1;',
     ))->values(array(
       'name' => 'user_mail_status_canceled_subject',
-      'value' => 's:57:"Account details for [user:name] at [site:name] (canceled)";',
+      'value' => 's:12:"So long, bub";',
     ))->values(array(
       'name' => 'user_pictures',
       'value' => 'i:1;',
@@ -479,4 +479,4 @@ public function load() {
   }
 
 }
-#dbc0f593050ff48cc18dfa4fed47daaf
+#502534c5e998ee5c14f5a2d510b9dc85
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
index 48f1d6e..6feed78 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
@@ -139,14 +139,14 @@ class MigrateDrupal6Test extends MigrateFullDrupalTestBase {
     'd6_url_alias',
     'd6_user_mail',
     'd6_user_contact_settings',
-    'd6_user_profile_field_instance',
-    'd6_user_profile_entity_display',
-    'd6_user_profile_entity_form_display',
-    'd6_user_profile_field',
-    'd6_user_picture_entity_display',
-    'd6_user_picture_entity_form_display',
-    'd6_user_picture_field_instance',
-    'd6_user_picture_field',
+    'user_profile_field_instance',
+    'user_profile_entity_display',
+    'user_profile_entity_form_display',
+    'user_profile_field',
+    'user_picture_entity_display',
+    'user_picture_entity_form_display',
+    'user_picture_field_instance',
+    'user_picture_field',
     'd6_user_picture_file',
     'd6_user_role',
     'd6_user_settings',
diff --git a/core/modules/user/config/schema/user.source.schema.yml b/core/modules/user/config/schema/user.source.schema.yml
index f1ff1b8..19990aa 100644
--- a/core/modules/user/config/schema/user.source.schema.yml
+++ b/core/modules/user/config/schema/user.source.schema.yml
@@ -38,9 +38,9 @@ migrate.source.d6_user_picture_instance:
       type: migrate_entity_constant
       label: 'Constants'
 
-migrate.source.d6_profile_field:
+migrate.source.profile_field:
   type: migrate_source_sql
-  label: 'Drupal 6 profile field'
+  label: 'Profile field'
   mapping:
     constants:
       type: migrate_entity_constant
diff --git a/core/modules/user/migration_templates/d6_profile_values.yml b/core/modules/user/migration_templates/d6_profile_values.yml
index 9cd4a6b..68c659a 100644
--- a/core/modules/user/migration_templates/d6_profile_values.yml
+++ b/core/modules/user/migration_templates/d6_profile_values.yml
@@ -15,6 +15,6 @@ destination:
 migration_dependencies:
   required:
     - d6_user
-    - d6_user_profile_field_instance
-    - d6_user_profile_entity_display
-    - d6_user_profile_entity_form_display
+    - user_profile_field_instance
+    - user_profile_entity_display
+    - user_profile_entity_form_display
diff --git a/core/modules/user/migration_templates/d6_user_mail.yml b/core/modules/user/migration_templates/d6_user_mail.yml
index bc48dfd..b06b6ea 100644
--- a/core/modules/user/migration_templates/d6_user_mail.yml
+++ b/core/modules/user/migration_templates/d6_user_mail.yml
@@ -1,5 +1,5 @@
 id: d6_user_mail
-label: Drupal 6 user mail configuration
+label: User mail configuration
 migration_tags:
   - Drupal 6
 source:
diff --git a/core/modules/user/migration_templates/d7_user.yml b/core/modules/user/migration_templates/d7_user.yml
new file mode 100755
index 0000000..07df192
--- /dev/null
+++ b/core/modules/user/migration_templates/d7_user.yml
@@ -0,0 +1,31 @@
+id: d7_user
+label: Drupal 7 user accounts
+migration_tags:
+  - Drupal 7
+builder:
+  plugin: d7_user
+source:
+  plugin: d7_user
+process:
+  uid: uid
+  name: name
+  pass: pass
+  mail: mail
+  created: created
+  access: access
+  login: login
+  status: status
+  timezone: timezone
+  langcode: language
+  preferred_langcode: language
+  preferred_admin_langcode: language
+  init: init
+  roles:
+    plugin: migration
+    migration: d7_user_role
+    source: roles
+destination:
+  plugin: entity:user
+migration_dependencies:
+  required:
+    - d7_user_role
diff --git a/core/modules/user/migration_templates/d7_user_flood.yml b/core/modules/user/migration_templates/d7_user_flood.yml
new file mode 100755
index 0000000..016acec
--- /dev/null
+++ b/core/modules/user/migration_templates/d7_user_flood.yml
@@ -0,0 +1,20 @@
+id: d7_user_flood
+migration_tags:
+  - Drupal 7
+source:
+  plugin: variable
+  variables:
+    - user_failed_login_identifier_uid_only
+    - user_failed_login_ip_limit
+    - user_failed_login_ip_window
+    - user_failed_login_user_window
+    - user_failed_login_user_limit
+process:
+  uid_only: user_failed_login_identifier_uid_only
+  ip_limit: user_failed_login_ip_limit
+  ip_window: user_failed_login_ip_window
+  user_limit: user_failed_login_user_limit
+  user_window: user_failed_login_user_window
+destination:
+  plugin: config
+  config_name: user.flood
diff --git a/core/modules/user/migration_templates/d7_user_mail.yml b/core/modules/user/migration_templates/d7_user_mail.yml
new file mode 100644
index 0000000..0c5e74c
--- /dev/null
+++ b/core/modules/user/migration_templates/d7_user_mail.yml
@@ -0,0 +1,39 @@
+id: d7_user_mail
+label: User mail configuration
+migration_tags:
+  - Drupal 7
+source:
+  plugin: variable
+  variables:
+    - user_mail_status_activated_subject
+    - user_mail_status_activated_body
+    - user_mail_password_reset_subject
+    - user_mail_password_reset_body
+    - user_mail_status_canceled_subject
+    - user_mail_status_canceled_body
+    - user_mail_register_admin_created_subject
+    - user_mail_register_admin_created_body
+    - user_mail_register_no_approval_required_subject
+    - user_mail_register_no_approval_required_body
+    - user_mail_register_pending_approval_subject
+    - user_mail_register_pending_approval_body
+    - user_mail_status_blocked_subject
+    - user_mail_status_blocked_body
+process:
+   'status_activated/subject': user_mail_status_activated_subject
+   'status_activated/body': user_mail_status_activated_body
+   'password_reset/subject': user_mail_password_reset_subject
+   'password_reset/body': user_mail_password_reset_body
+   'cancel_confirm/subject': user_mail_status_canceled_subject
+   'cancel_confirm/body': user_mail_status_canceled_body
+   'register_admin_created/subject': user_mail_register_admin_created_subject
+   'register_admin_created/body': user_mail_register_admin_created_body
+   'register_no_approval_required/subject': user_mail_register_no_approval_required_subject
+   'register_no_approval_required/body': user_mail_register_no_approval_required_body
+   'register_pending_approval/subject': user_mail_register_pending_approval_subject
+   'register_pending_approval/body': user_mail_register_pending_approval_body
+   'status_blocked/subject': user_mail_status_blocked_subject
+   'status_blocked/body': user_mail_status_blocked_body
+destination:
+  plugin: config
+  config_name: user.mail
diff --git a/core/modules/user/migration_templates/d7_user_role.yml b/core/modules/user/migration_templates/d7_user_role.yml
new file mode 100755
index 0000000..6688083
--- /dev/null
+++ b/core/modules/user/migration_templates/d7_user_role.yml
@@ -0,0 +1,44 @@
+id: d7_user_role
+label: Drupal 7 user roles
+migration_tags:
+  - Drupal 7
+source:
+  plugin: d7_user_role
+process:
+  id:
+    -
+      plugin: machine_name
+      source: name
+    -
+      plugin: dedupe_entity
+      entity_type: user_role
+      field: id
+      length: 32
+    -
+      plugin: user_update_8002
+  label: name
+  permissions:
+    -
+      plugin: static_map
+      source: permissions
+      bypass: true
+      map:
+        'use PHP for block visibility': 'use PHP for settings'
+        'administer site-wide contact form': 'administer contact forms'
+        'post comments without approval': 'skip comment approval'
+        'edit own blog entries' : 'edit own blog content'
+        'edit any blog entry' : 'edit any blog content'
+        'delete own blog entries' : 'delete own blog content'
+        'delete any blog entry' : 'delete any blog content'
+        'create forum topics' : 'create forum content'
+        'delete any forum topic' : 'delete any forum content'
+        'delete own forum topics' : 'delete own forum content'
+        'edit any forum topic' : 'edit any forum content'
+        'edit own forum topics' : 'edit own forum content'
+    - plugin: flatten
+  weight: weight
+destination:
+  plugin: entity:user_role
+migration_dependencies:
+  optional:
+    - d7_filter_format
diff --git a/core/modules/user/migration_templates/d6_user_picture_entity_display.yml b/core/modules/user/migration_templates/user_picture_entity_display.yml
similarity index 77%
rename from core/modules/user/migration_templates/d6_user_picture_entity_display.yml
rename to core/modules/user/migration_templates/user_picture_entity_display.yml
index f38bc36..78c0ae0 100644
--- a/core/modules/user/migration_templates/d6_user_picture_entity_display.yml
+++ b/core/modules/user/migration_templates/user_picture_entity_display.yml
@@ -1,9 +1,10 @@
-id: d6_user_picture_entity_display
-label: Drupal 6 user picture display configuration
+id: user_picture_entity_display
+label: User picture display configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
-  plugin: d6_user_picture_instance
+  plugin: user_picture_instance
   constants:
     entity_type: user
     bundle: user
@@ -27,4 +28,4 @@ destination:
   plugin: component_entity_display
 migration_dependencies:
   required:
-    - d6_user_picture_field_instance
+    - user_picture_field_instance
diff --git a/core/modules/user/migration_templates/d6_user_picture_entity_form_display.yml b/core/modules/user/migration_templates/user_picture_entity_form_display.yml
similarity index 77%
rename from core/modules/user/migration_templates/d6_user_picture_entity_form_display.yml
rename to core/modules/user/migration_templates/user_picture_entity_form_display.yml
index 4e42228..60d782f 100644
--- a/core/modules/user/migration_templates/d6_user_picture_entity_form_display.yml
+++ b/core/modules/user/migration_templates/user_picture_entity_form_display.yml
@@ -1,9 +1,10 @@
-id: d6_user_picture_entity_form_display
-label: Drupal 6 user picture form display configuration
+id: user_picture_entity_form_display
+label: User picture form display configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
-  plugin: d6_user_picture_instance
+  plugin: user_picture_instance
   constants:
     entity_type: user
     bundle: user
@@ -26,4 +27,4 @@ destination:
   plugin: component_entity_form_display
 migration_dependencies:
   required:
-    - d6_user_picture_field_instance
+    - user_picture_field_instance
diff --git a/core/modules/user/migration_templates/d6_user_picture_field.yml b/core/modules/user/migration_templates/user_picture_field.yml
similarity index 85%
rename from core/modules/user/migration_templates/d6_user_picture_field.yml
rename to core/modules/user/migration_templates/user_picture_field.yml
index 27a39a2..a484ab8 100644
--- a/core/modules/user/migration_templates/d6_user_picture_field.yml
+++ b/core/modules/user/migration_templates/user_picture_field.yml
@@ -1,7 +1,8 @@
-id: d6_user_picture_field
-label: Drupal 6 user picture field configuration
+id: user_picture_field
+label: User picture field configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
   # We do an empty source and a proper destination to have an idmap for
   # dependencies.
diff --git a/core/modules/user/migration_templates/d6_user_picture_field_instance.yml b/core/modules/user/migration_templates/user_picture_field_instance.yml
similarity index 80%
rename from core/modules/user/migration_templates/d6_user_picture_field_instance.yml
rename to core/modules/user/migration_templates/user_picture_field_instance.yml
index 7dc83b1..4332e09 100644
--- a/core/modules/user/migration_templates/d6_user_picture_field_instance.yml
+++ b/core/modules/user/migration_templates/user_picture_field_instance.yml
@@ -1,9 +1,10 @@
-id: d6_user_picture_field_instance
-label: Drupal 6 user picture field instance configuration
+id: user_picture_field_instance
+label: User picture field instance configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
-  plugin: d6_user_picture_instance
+  plugin: user_picture_instance
   constants:
     entity_type: user
     bundle: user
@@ -27,4 +28,4 @@ destination:
   plugin: entity:field_config
 migration_dependencies:
   required:
-    - d6_user_picture_field
+    - user_picture_field
diff --git a/core/modules/user/migration_templates/d6_user_profile_entity_display.yml b/core/modules/user/migration_templates/user_profile_entity_display.yml
similarity index 87%
rename from core/modules/user/migration_templates/d6_user_profile_entity_display.yml
rename to core/modules/user/migration_templates/user_profile_entity_display.yml
index 3e7b467..76553a1 100644
--- a/core/modules/user/migration_templates/d6_user_profile_entity_display.yml
+++ b/core/modules/user/migration_templates/user_profile_entity_display.yml
@@ -1,9 +1,10 @@
-id: d6_user_profile_entity_display
-label: Drupal 6 user profile display configuration
+id: user_profile_entity_display
+label: User profile display configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
-  plugin: d6_profile_field
+  plugin: profile_field
   constants:
     entity_type: user
     bundle: user
diff --git a/core/modules/user/migration_templates/d6_user_profile_entity_form_display.yml b/core/modules/user/migration_templates/user_profile_entity_form_display.yml
similarity index 90%
rename from core/modules/user/migration_templates/d6_user_profile_entity_form_display.yml
rename to core/modules/user/migration_templates/user_profile_entity_form_display.yml
index d1cde0b..c75c2c8 100644
--- a/core/modules/user/migration_templates/d6_user_profile_entity_form_display.yml
+++ b/core/modules/user/migration_templates/user_profile_entity_form_display.yml
@@ -1,9 +1,10 @@
-id: d6_user_profile_entity_form_display
-label: Drupal 6 user profile form display configuration
+id: user_profile_entity_form_display
+label: User profile form display configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
-  plugin: d6_profile_field
+  plugin: profile_field
   constants:
     empty: {}
     entity_type: user
diff --git a/core/modules/user/migration_templates/d6_user_profile_field.yml b/core/modules/user/migration_templates/user_profile_field.yml
similarity index 80%
rename from core/modules/user/migration_templates/d6_user_profile_field.yml
rename to core/modules/user/migration_templates/user_profile_field.yml
index 9917673..bf81898 100644
--- a/core/modules/user/migration_templates/d6_user_profile_field.yml
+++ b/core/modules/user/migration_templates/user_profile_field.yml
@@ -1,9 +1,10 @@
-id: d6_user_profile_field
-label: Drupal 6 user profile field configuration
+id: user_profile_field
+label: User profile field configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
-  plugin: d6_profile_field
+  plugin: profile_field
   constants:
     entity_type: user
 process:
@@ -21,7 +22,7 @@ process:
       textarea: text_long
       url: link
   settings:
-    plugin: d6_profile_field_settings
+    plugin: profile_field_settings
     source: type
   'settings/allowed_values': options
   cardinality:
diff --git a/core/modules/user/migration_templates/d6_user_profile_field_instance.yml b/core/modules/user/migration_templates/user_profile_field_instance.yml
similarity index 68%
rename from core/modules/user/migration_templates/d6_user_profile_field_instance.yml
rename to core/modules/user/migration_templates/user_profile_field_instance.yml
index ec0e526..b9f213b 100644
--- a/core/modules/user/migration_templates/d6_user_profile_field_instance.yml
+++ b/core/modules/user/migration_templates/user_profile_field_instance.yml
@@ -1,9 +1,10 @@
-id: d6_user_profile_field_instance
-label: Drupal 6 user profile field instance configuration
+id: user_profile_field_instance
+label: User profile field instance configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
-  plugin: d6_profile_field
+  plugin: profile_field
   constants:
     entity_type: user
     bundle: user
@@ -18,4 +19,4 @@ destination:
   plugin: entity:field_config
 migration_dependencies:
   required:
-    - d6_user_profile_field
+    - user_profile_field
diff --git a/core/modules/user/src/Plugin/migrate/builder/d6/ProfileValues.php b/core/modules/user/src/Plugin/migrate/builder/d6/ProfileValues.php
index 937772b..be33173 100644
--- a/core/modules/user/src/Plugin/migrate/builder/d6/ProfileValues.php
+++ b/core/modules/user/src/Plugin/migrate/builder/d6/ProfileValues.php
@@ -24,7 +24,7 @@ public function buildMigrations(array $template) {
 
     // @TODO The source plugin should accept a database connection.
     // @see https://www.drupal.org/node/2552791
-    $source_plugin = $this->getSourcePlugin('d6_profile_field', $template['source']);
+    $source_plugin = $this->getSourcePlugin('profile_field', $template['source']);
     try {
       $source_plugin->checkRequirements();
     }
diff --git a/core/modules/user/src/Plugin/migrate/builder/d7/User.php b/core/modules/user/src/Plugin/migrate/builder/d7/User.php
new file mode 100644
index 0000000..10bcb47
--- /dev/null
+++ b/core/modules/user/src/Plugin/migrate/builder/d7/User.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Plugin\migrate\builder\d7\User.
+ */
+
+namespace Drupal\user\Plugin\migrate\builder\d7;
+
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\Migration;
+use Drupal\migrate\Exception\RequirementsException;
+use Drupal\migrate\Plugin\migrate\builder\BuilderBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @PluginID("d7_user")
+ */
+class User extends BuilderBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The module handler service.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * Constructs a d7_user builder plugin instance.
+   *
+   * @param array $configuration
+   *   The plugin configuration.
+   * @param string $plugin_id
+   *   The plugin ID.
+   * @param mixed $plugin_definition
+   *   The plugin definition.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler service.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ModuleHandlerInterface $module_handler) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('module_handler')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildMigrations(array $template) {
+    $migration = Migration::create($template);
+
+    if ($this->moduleHandler->moduleExists('field')) {
+      $template['source']['entity_type'] = 'user';
+
+      $source_plugin = $this->getSourcePlugin('d7_field_instance', $template['source']);
+      foreach ($source_plugin as $field) {
+        $field_name = $field->getSourceProperty('field_name');
+        $migration->setProcessOfProperty($field_name, $field_name);
+      }
+    }
+
+    try {
+      $profile_fields = $this->getSourcePlugin('profile_field', $template['source']);
+      // Ensure that Profile is enabled in the source DB.
+      $profile_fields->checkRequirements();
+      foreach ($profile_fields as $field) {
+        $field_name = $field->getSourceProperty('name');
+        $migration->setProcessOfProperty($field_name, $field_name);
+      }
+    }
+    catch (RequirementsException $e) {
+      // Profile is not enabled in the source DB, so don't do anything.
+    }
+
+    return [$migration];
+  }
+
+}
diff --git a/core/modules/user/src/Plugin/migrate/process/d6/ProfileFieldSettings.php b/core/modules/user/src/Plugin/migrate/process/ProfileFieldSettings.php
similarity index 71%
rename from core/modules/user/src/Plugin/migrate/process/d6/ProfileFieldSettings.php
rename to core/modules/user/src/Plugin/migrate/process/ProfileFieldSettings.php
index 87e3d38..c1ca359 100644
--- a/core/modules/user/src/Plugin/migrate/process/d6/ProfileFieldSettings.php
+++ b/core/modules/user/src/Plugin/migrate/process/ProfileFieldSettings.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\user\Plugin\migrate\process\d6\ProfileFieldSettings.
+ * Contains \Drupal\user\Plugin\migrate\process\ProfileFieldSettings.
  */
 
-namespace Drupal\user\Plugin\migrate\process\d6;
+namespace Drupal\user\Plugin\migrate\process;
 
 use Drupal\migrate\MigrateExecutableInterface;
 use Drupal\migrate\ProcessPluginBase;
@@ -13,15 +13,13 @@
 
 /**
  * @MigrateProcessPlugin(
- *   id = "d6_profile_field_settings"
+ *   id = "profile_field_settings"
  * )
  */
 class ProfileFieldSettings extends ProcessPluginBase {
 
   /**
    * {@inheritdoc}
-   *
-   * Set the profile field settings configuration.
    */
   public function transform($type, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
     $settings = array();
diff --git a/core/modules/user/src/Plugin/migrate/process/d6/UserUpdate8002.php b/core/modules/user/src/Plugin/migrate/process/UserUpdate8002.php
similarity index 85%
rename from core/modules/user/src/Plugin/migrate/process/d6/UserUpdate8002.php
rename to core/modules/user/src/Plugin/migrate/process/UserUpdate8002.php
index ff8a816..41a9b03 100644
--- a/core/modules/user/src/Plugin/migrate/process/d6/UserUpdate8002.php
+++ b/core/modules/user/src/Plugin/migrate/process/UserUpdate8002.php
@@ -2,10 +2,11 @@
 
 /**
  * @file
- * Contains \Drupal\user\Plugin\migrate\process\d6\UserUpdate8002.
+ * Contains \Drupal\user\Plugin\migrate\process\UserUpdate8002.
  */
 
-namespace Drupal\user\Plugin\migrate\process\d6;
+namespace Drupal\user\Plugin\migrate\process;
+
 use Drupal\migrate\MigrateExecutableInterface;
 use Drupal\migrate\ProcessPluginBase;
 use Drupal\migrate\Row;
diff --git a/core/modules/user/src/Plugin/migrate/source/d6/ProfileField.php b/core/modules/user/src/Plugin/migrate/source/ProfileField.php
similarity index 72%
rename from core/modules/user/src/Plugin/migrate/source/d6/ProfileField.php
rename to core/modules/user/src/Plugin/migrate/source/ProfileField.php
index 68498b2..4550d5b 100644
--- a/core/modules/user/src/Plugin/migrate/source/d6/ProfileField.php
+++ b/core/modules/user/src/Plugin/migrate/source/ProfileField.php
@@ -2,46 +2,53 @@
 
 /**
  * @file
- * Contains \Drupal\user\Plugin\migrate\source\d6\ProfileField.
+ * Contains \Drupal\user\Plugin\migrate\source\ProfileField.
  */
 
-namespace Drupal\user\Plugin\migrate\source\d6;
+namespace Drupal\user\Plugin\migrate\source;
 
 use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
 use Drupal\migrate\Row;
 
 /**
- * Drupal 6 profile fields source from database.
+ * Profile field source from database.
  *
  * @MigrateSource(
- *   id = "d6_profile_field",
+ *   id = "profile_field",
  *   source_provider = "profile"
  * )
  */
 class ProfileField extends DrupalSqlBase {
 
   /**
+   * The source table containing profile field info.
+   *
+   * @var string
+   */
+  protected $fieldTable;
+
+  /**
+   * The source table containing the profile values.
+   *
+   * @var string
+   */
+  protected $valueTable;
+
+  /**
    * {@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;
+    if (empty($this->fieldTable) || empty($this->valueTable)) {
+      if ($this->getModuleSchemaVersion('system') >= 7000) {
+        $this->fieldTable = 'profile_field';
+        $this->valueTable = 'profile_value';
+      }
+      else {
+        $this->fieldTable = 'profile_fields';
+        $this->valueTable = 'profile_values';
+      }
+    }
+    return $this->select($this->fieldTable, 'pf')->fields('pf');
   }
 
   /**
@@ -53,7 +60,12 @@ public function prepareRow(Row $row) {
       $current_options = preg_split("/[\r\n]+/", $row->getSourceProperty('options'));
       // Select the list values from the profile_values table to ensure we get
       // them all since they can get out of sync with profile_fields.
-      $options = $this->getDatabase()->query('SELECT DISTINCT value FROM {profile_values} WHERE fid = :fid', array(':fid' => $row->getSourceProperty('fid')))->fetchCol();
+      $options = $this->select($this->valueTable, 'pv')
+        ->distinct()
+        ->fields('pv', ['value'])
+        ->condition('fid', $row->getSourceProperty('fid'))
+        ->execute()
+        ->fetchCol();
       $options = array_merge($current_options, $options);
       // array_combine() takes care of any duplicates options.
       $row->setSourceProperty('options', array_combine($options, $options));
diff --git a/core/modules/user/src/Plugin/migrate/source/d6/UserPictureInstance.php b/core/modules/user/src/Plugin/migrate/source/UserPictureInstance.php
similarity index 86%
rename from core/modules/user/src/Plugin/migrate/source/d6/UserPictureInstance.php
rename to core/modules/user/src/Plugin/migrate/source/UserPictureInstance.php
index 48e409b..99099e3 100644
--- a/core/modules/user/src/Plugin/migrate/source/d6/UserPictureInstance.php
+++ b/core/modules/user/src/Plugin/migrate/source/UserPictureInstance.php
@@ -2,21 +2,21 @@
 
 /**
  * @file
- * Contains \Drupal\user\Plugin\migrate\source\d6\UserPictureInstance.
+ * Contains \Drupal\user\Plugin\migrate\source\UserPictureInstance.
  */
 
-namespace Drupal\user\Plugin\migrate\source\d6;
+namespace Drupal\user\Plugin\migrate\source;
 
 use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
 use Drupal\migrate\Plugin\migrate\source\DummyQueryTrait;
 
 /**
- * Drupal 6 user picture field instance source.
+ * User picture field instance source.
  *
  * @todo Support default picture?
  *
  * @MigrateSource(
- *   id = "d6_user_picture_instance"
+ *   id = "user_picture_instance"
  * )
  */
 class UserPictureInstance extends DrupalSqlBase {
diff --git a/core/modules/user/src/Plugin/migrate/source/d7/Role.php b/core/modules/user/src/Plugin/migrate/source/d7/Role.php
new file mode 100755
index 0000000..4f84290
--- /dev/null
+++ b/core/modules/user/src/Plugin/migrate/source/d7/Role.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Plugin\migrate\source\d7\Role.
+ */
+
+namespace Drupal\user\Plugin\migrate\source\d7;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 7 role source from database.
+ *
+ * @MigrateSource(
+ *   id = "d7_user_role"
+ * )
+ */
+class Role extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('role', 'r')->fields('r');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'rid' => $this->t('Role ID.'),
+      'name' => $this->t('The name of the user role.'),
+      'weight' => $this->t('The weight of the role.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $permissions = $this->select('role_permission', 'rp')
+      ->fields('rp', ['permission'])
+      ->condition('rid', $row->getSourceProperty('rid'))
+      ->execute()
+      ->fetchCol();
+    $row->setSourceProperty('permissions', $permissions);
+
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['rid']['type'] = 'integer';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/user/src/Plugin/migrate/source/d7/User.php b/core/modules/user/src/Plugin/migrate/source/d7/User.php
new file mode 100755
index 0000000..9b42fa7
--- /dev/null
+++ b/core/modules/user/src/Plugin/migrate/source/d7/User.php
@@ -0,0 +1,123 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Plugin\migrate\source\d7\User.
+ */
+
+namespace Drupal\user\Plugin\migrate\source\d7;
+
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
+
+/**
+ * Drupal 7 user source from database.
+ *
+ * @MigrateSource(
+ *   id = "d7_user"
+ * )
+ */
+class User extends FieldableEntity {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('users', 'u')
+      ->fields('u')
+      ->condition('uid', 1, '>');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    $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'),
+      'data' => $this->t('User data'),
+      '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) {
+    $roles = $this->select('role', 'r')
+      ->fields('r', ['rid', 'name']);
+    $roles->join('users_roles', 'ur', 'ur.rid = r.rid');
+    $roles->condition('ur.uid', $row->getSourceProperty('uid'));
+    $row->setSourceProperty('roles', $roles->execute()->fetchAllKeyed());
+
+    $row->setSourceProperty('data', unserialize($row->getSourceProperty('data')));
+
+    // Get Field API field values.
+    foreach (array_keys($this->getFields('user')) as $field) {
+      $row->setSourceProperty($field, $this->getFieldValues('user', $field, $row->getSourceProperty('uid')));
+    }
+
+    // Get profile field values. This code is lifted directly from the D6
+    // ProfileFieldValues plugin.
+    if ($this->getDatabase()->schema()->tableExists('profile_value')) {
+      $query = $this->select('profile_value', 'pv')
+        ->fields('pv', array('fid', 'value'));
+      $query->leftJoin('profile_field', '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) {
+        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') {
+          // Explode by newline and comma.
+          $row->setSourceProperty($profile_value['name'], preg_split("/[\r\n,]+/", $profile_value['value']));
+        }
+        else {
+          $row->setSourceProperty($profile_value['name'], array($profile_value['value']));
+        }
+      }
+    }
+
+    return parent::prepareRow($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return array(
+      'uid' => array(
+        'type' => 'integer',
+        'alias' => 'u',
+      ),
+    );
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/MigrateUserPictureEntityDisplayTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserPictureEntityDisplayTest.php
new file mode 100644
index 0000000..0613261
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserPictureEntityDisplayTest.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserPictureEntityDisplayTest.
+ */
+
+namespace Drupal\user\Tests\Migrate;
+
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+
+/**
+ * User picture entity display.
+ *
+ * @group user
+ */
+class MigrateUserPictureEntityDisplayTest extends MigrateDrupal7TestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('file', 'image');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installEntitySchema('file');
+    $this->executeMigration('user_picture_field');
+    $this->executeMigration('user_picture_field_instance');
+    $this->executeMigration('user_picture_entity_display');
+  }
+
+  /**
+   * Tests the Drupal 7 user picture to Drupal 8 entity display migration.
+   */
+  public function testUserPictureEntityDisplay() {
+    $component = entity_get_display('user', 'user', 'default')->getComponent('user_picture');
+    $this->assertIdentical('image', $component['type']);
+    $this->assertIdentical('', $component['settings']['image_style']);
+    $this->assertIdentical('content', $component['settings']['image_link']);
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/MigrateUserPictureEntityFormDisplayTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserPictureEntityFormDisplayTest.php
new file mode 100644
index 0000000..0902194
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserPictureEntityFormDisplayTest.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserPictureEntityFormDisplayTest.
+ */
+
+namespace Drupal\user\Tests\Migrate;
+
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+
+/**
+ * Tests migration of the user_picture field's entity form display settings.
+ *
+ * @group user
+ */
+class MigrateUserPictureEntityFormDisplayTest extends MigrateDrupal7TestBase {
+
+  static $modules = array('image', 'file');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->executeMigration('user_picture_field');
+    $this->executeMigration('user_picture_field_instance');
+    $this->executeMigration('user_picture_entity_form_display');
+  }
+
+  /**
+   * Tests the field's entity form display settings.
+   */
+  public function testEntityFormDisplaySettings() {
+    $component = entity_get_form_display('user', 'user', 'default')->getComponent('user_picture');
+    $this->assertIdentical('image_image', $component['type']);
+    $this->assertIdentical('throbber', $component['settings']['progress_indicator']);
+    $this->assertIdentical('thumbnail', $component['settings']['preview_image_style']);
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/MigrateUserPictureFieldInstanceTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserPictureFieldInstanceTest.php
new file mode 100644
index 0000000..45367f9
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserPictureFieldInstanceTest.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserPictureFieldInstanceTest.
+ */
+
+namespace Drupal\user\Tests\Migrate;
+
+use Drupal\Core\Field\FieldConfigInterface;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+
+/**
+ * User picture field instance migration.
+ *
+ * @group user
+ */
+class MigrateUserPictureFieldInstanceTest extends MigrateDrupal7TestBase {
+
+  static $modules = array('image', 'file');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->executeMigration('user_picture_field');
+    $this->executeMigration('user_picture_field_instance');
+  }
+
+  /**
+   * Test the user picture field migration.
+   */
+  public function testUserPictureField() {
+    /** @var \Drupal\field\FieldConfigInterface $field */
+    $field = FieldConfig::load('user.user.user_picture');
+    $this->assertTrue($field instanceof FieldConfigInterface);
+    $this->assertIdentical('user', $field->getTargetEntityTypeId());
+    $this->assertIdentical('user', $field->getTargetBundle());
+    $this->assertIdentical('user_picture', $field->getName());
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/MigrateUserPictureFieldTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserPictureFieldTest.php
new file mode 100644
index 0000000..cf4120f
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserPictureFieldTest.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserPictureFieldTest.
+ */
+
+namespace Drupal\user\Tests\Migrate;
+
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\field\FieldStorageConfigInterface;
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+
+/**
+ * User picture field migration.
+ *
+ * @group user
+ */
+class MigrateUserPictureFieldTest extends MigrateDrupal7TestBase {
+
+  static $modules = array('image', 'file');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->executeMigration('user_picture_field');
+  }
+
+  /**
+   * Test the user picture field migration.
+   */
+  public function testUserPictureField() {
+    /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
+    $field_storage = FieldStorageConfig::load('user.user_picture');
+    $this->assertTrue($field_storage instanceof FieldStorageConfigInterface);
+    $this->assertIdentical('user.user_picture', $field_storage->id());
+    $this->assertIdentical('image', $field_storage->getType());
+    $this->assertIdentical('user', $field_storage->getTargetEntityTypeId());
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileEntityDisplayTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserProfileEntityDisplayTest.php
similarity index 94%
rename from core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileEntityDisplayTest.php
rename to core/modules/user/src/Tests/Migrate/MigrateUserProfileEntityDisplayTest.php
index e97b0e0..526bdd8 100644
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileEntityDisplayTest.php
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserProfileEntityDisplayTest.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserProfileEntityDisplayTest.
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserProfileEntityDisplayTest.
  */
 
-namespace Drupal\user\Tests\Migrate\d6;
+namespace Drupal\user\Tests\Migrate;
 
 use Drupal\Core\Database\Database;
 use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
@@ -89,7 +89,7 @@ protected function setUp() {
       ))->save();
     }
 
-    $this->executeMigration('d6_user_profile_entity_display');
+    $this->executeMigration('user_profile_entity_display');
   }
 
   /**
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileEntityFormDisplayTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserProfileEntityFormDisplayTest.php
similarity index 94%
rename from core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileEntityFormDisplayTest.php
rename to core/modules/user/src/Tests/Migrate/MigrateUserProfileEntityFormDisplayTest.php
index ea3dc23..9920d65 100644
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileEntityFormDisplayTest.php
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserProfileEntityFormDisplayTest.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserProfileEntityFormDisplayTest.
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserProfileEntityFormDisplayTest.
  */
 
-namespace Drupal\user\Tests\Migrate\d6;
+namespace Drupal\user\Tests\Migrate;
 
 use Drupal\Core\Database\Database;
 use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
@@ -84,7 +84,7 @@ protected function setUp() {
       ))->save();
     }
 
-    $this->executeMigration('d6_user_profile_entity_form_display');
+    $this->executeMigration('user_profile_entity_form_display');
   }
 
   /**
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileFieldInstanceTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserProfileFieldInstanceTest.php
similarity index 94%
rename from core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileFieldInstanceTest.php
rename to core/modules/user/src/Tests/Migrate/MigrateUserProfileFieldInstanceTest.php
index eb45617..2c31542 100644
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileFieldInstanceTest.php
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserProfileFieldInstanceTest.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserProfileFieldInstanceTest.
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserProfileFieldInstanceTest.
  */
 
-namespace Drupal\user\Tests\Migrate\d6;
+namespace Drupal\user\Tests\Migrate;
 
 use Drupal\field\Entity\FieldConfig;
 use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
@@ -26,13 +26,13 @@ protected function setUp() {
     parent::setUp();
     // Add some id mappings for the dependant migrations.
     $id_mappings = array(
-      'd6_user_profile_field' => array(
+      'user_profile_field' => array(
         array(array(1), array('user', 'profile_color')),
       ),
     );
     $this->prepareMigrations($id_mappings);
     $this->createFields();
-    $this->executeMigration('d6_user_profile_field_instance');
+    $this->executeMigration('user_profile_field_instance');
   }
 
   /**
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileFieldTest.php b/core/modules/user/src/Tests/Migrate/MigrateUserProfileFieldTest.php
similarity index 94%
rename from core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileFieldTest.php
rename to core/modules/user/src/Tests/Migrate/MigrateUserProfileFieldTest.php
index 356efc2..923bd13 100644
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileFieldTest.php
+++ b/core/modules/user/src/Tests/Migrate/MigrateUserProfileFieldTest.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserProfileFieldTest.
+ * Contains \Drupal\user\Tests\Migrate\MigrateUserProfileFieldTest.
  */
 
-namespace Drupal\user\Tests\Migrate\d6;
+namespace Drupal\user\Tests\Migrate;
 
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
@@ -24,7 +24,7 @@ class MigrateUserProfileFieldTest extends MigrateDrupal6TestBase {
    */
   protected function setUp() {
     parent::setUp();
-    $this->executeMigration('d6_user_profile_field');
+    $this->executeMigration('user_profile_field');
   }
 
   /**
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureEntityDisplayTest.php b/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureEntityDisplayTest.php
deleted file mode 100644
index ca18375..0000000
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureEntityDisplayTest.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserPictureEntityDisplayTest.
- */
-
-namespace Drupal\user\Tests\Migrate\d6;
-
-use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
-
-/**
- * User picture entity display.
- *
- * @group migrate_drupal_6
- */
-class MigrateUserPictureEntityDisplayTest extends MigrateDrupal6TestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  static $modules = array('image');
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $id_mappings = array(
-      'd6_user_picture_field_instance' => array(
-        array(array(1), array('user', 'user', 'user_picture')),
-      ),
-    );
-    $this->prepareMigrations($id_mappings);
-    $this->executeMigration('d6_user_picture_entity_display');
-  }
-
-  /**
-   * Tests the Drupal 6 user picture to Drupal 8 entity display migration.
-   */
-  public function testUserPictureEntityDisplay() {
-    $display = entity_get_display('user', 'user', 'default');
-    $component = $display->getComponent('user_picture');
-    $this->assertIdentical('image', $component['type']);
-    $this->assertIdentical('content', $component['settings']['image_link']);
-
-    $this->assertIdentical(array('user', 'user', 'default', 'user_picture'), entity_load('migration', 'd6_user_picture_entity_display')->getIdMap()->lookupDestinationID(array('')));
-  }
-
-}
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureEntityFormDisplayTest.php b/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureEntityFormDisplayTest.php
deleted file mode 100644
index 05c3575..0000000
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureEntityFormDisplayTest.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserPictureEntityFormDisplayTest.
- */
-
-namespace Drupal\user\Tests\Migrate\d6;
-
-use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
-
-/**
- * User picture entity form display.
- *
- * @group migrate_drupal_6
- */
-class MigrateUserPictureEntityFormDisplayTest extends MigrateDrupal6TestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  static $modules = array('image');
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $id_mappings = array(
-      'd6_user_picture_field_instance' => array(
-        array(array(1), array('user', 'user', 'user_picture')),
-      ),
-    );
-    $this->prepareMigrations($id_mappings);
-    $this->executeMigration('d6_user_picture_entity_form_display');
-  }
-
-  /**
-   * Tests the Drupal 6 user picture to Drupal 8 entity form display migration.
-   */
-  public function testUserPictureEntityFormDisplay() {
-    $display = entity_get_form_display('user', 'user', 'default');
-    $component = $display->getComponent('user_picture');
-    $this->assertIdentical('image_image', $component['type']);
-    $this->assertIdentical('throbber', $component['settings']['progress_indicator']);
-
-    $this->assertIdentical(array('user', 'user', 'default', 'user_picture'), entity_load('migration', 'd6_user_picture_entity_form_display')->getIdMap()->lookupDestinationID(array('')));
-  }
-
-}
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureFieldTest.php b/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureFieldTest.php
deleted file mode 100644
index ace1a35..0000000
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureFieldTest.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserPictureFieldTest.
- */
-
-namespace Drupal\user\Tests\Migrate\d6;
-
-use Drupal\field\Entity\FieldStorageConfig;
-use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
-
-/**
- * User picture field migration.
- *
- * @group migrate_drupal_6
- */
-class MigrateUserPictureFieldTest extends MigrateDrupal6TestBase {
-
-  static $modules = array('image', 'file');
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->executeMigration('d6_user_picture_field');
-  }
-
-  /**
-   * Test the user picture field migration.
-   */
-  public function testUserPictureField() {
-    $field_storage = FieldStorageConfig::load('user.user_picture');
-    $this->assertIdentical('user.user_picture', $field_storage->id());
-    $this->assertIdentical(array('user', 'user_picture'), entity_load('migration', 'd6_user_picture_field')->getIdMap()->lookupDestinationID(array('')));
-  }
-
-}
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureInstanceTest.php b/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureInstanceTest.php
deleted file mode 100644
index a4219fd..0000000
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserPictureInstanceTest.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Tests\Migrate\d6\MigrateUserPictureInstanceTest.
- */
-
-namespace Drupal\user\Tests\Migrate\d6;
-
-use Drupal\field\Entity\FieldConfig;
-use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
-
-/**
- * User picture field instance migration.
- *
- * @group migrate_drupal_6
- */
-class MigrateUserPictureInstanceTest extends MigrateDrupal6TestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  static $modules = array('image', 'file');
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    // Add some node mappings to get past checkRequirements().
-    $id_mappings = array(
-      'd6_user_picture_field' => array(
-        array(array('user_upload'), array('name', 'bundle')),
-      ),
-    );
-    $this->prepareMigrations($id_mappings);
-    entity_create('field_storage_config', array(
-      'entity_type' => 'user',
-      'field_name' => 'user_picture',
-      'type' => 'image',
-      'translatable' => '0',
-    ))->save();
-
-    $this->executeMigration('d6_user_picture_field_instance');
-  }
-
-  /**
-   * Tests the Drupal 6 user picture to Drupal 8 picture field instance migration.
-   */
-  public function testUserPictureFieldInstance() {
-    $field = FieldConfig::load('user.user.user_picture');
-    $settings = $field->getSettings();
-    $this->assertIdentical('png gif jpg jpeg', $settings['file_extensions']);
-    $this->assertIdentical('pictures', $settings['file_directory']);
-    $this->assertIdentical('30KB', $settings['max_filesize']);
-    $this->assertIdentical('85x85', $settings['max_resolution']);
-
-    $this->assertIdentical(array('user', 'user', 'user_picture'), entity_load('migration', 'd6_user_picture_field_instance')->getIdMap()->lookupDestinationID(array('')));
-  }
-
-}
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileValuesTest.php b/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileValuesTest.php
index d44f737..a12976d 100644
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileValuesTest.php
+++ b/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileValuesTest.php
@@ -88,13 +88,13 @@ protected function setUp() {
 
     // Add some id mappings for the dependant migrations.
     $id_mappings = array(
-      'd6_user_profile_field_instance' => array(
+      'user_profile_field_instance' => array(
         array(array(1), array('user', 'user', 'fieldname')),
       ),
-      'd6_user_profile_entity_display' => array(
+      'user_profile_entity_display' => array(
         array(array(1), array('user', 'user', 'default', 'fieldname')),
       ),
-      'd6_user_profile_entity_form_display' => array(
+      'user_profile_entity_form_display' => array(
         array(array(1), array('user', 'user', 'default', 'fieldname')),
       ),
       'd6_user' => array(
diff --git a/core/modules/user/src/Tests/Migrate/d6/MigrateUserTest.php b/core/modules/user/src/Tests/Migrate/d6/MigrateUserTest.php
index b38bdee..9980ba0 100644
--- a/core/modules/user/src/Tests/Migrate/d6/MigrateUserTest.php
+++ b/core/modules/user/src/Tests/Migrate/d6/MigrateUserTest.php
@@ -95,10 +95,10 @@ protected function setUp() {
         array(array(4), array('migrate test role 2')),
         array(array(5), array('migrate test role 3')),
       ),
-      'd6_user_picture_entity_display' => array(
+      'user_picture_entity_display' => array(
         array(array(1), array('user', 'user', 'default', 'user_picture')),
       ),
-      'd6_user_picture_entity_form_display' => array(
+      'user_picture_entity_form_display' => array(
         array(array(1), array('user', 'user', 'default', 'user_picture')),
       ),
       'd6_user_picture_file' => array(
diff --git a/core/modules/user/src/Tests/Migrate/ProfileValuesBuilderTest.php b/core/modules/user/src/Tests/Migrate/d6/ProfileValuesBuilderTest.php
similarity index 89%
copy from core/modules/user/src/Tests/Migrate/ProfileValuesBuilderTest.php
copy to core/modules/user/src/Tests/Migrate/d6/ProfileValuesBuilderTest.php
index 747edc9..c159d9e 100644
--- a/core/modules/user/src/Tests/Migrate/ProfileValuesBuilderTest.php
+++ b/core/modules/user/src/Tests/Migrate/d6/ProfileValuesBuilderTest.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\user\Tests\Migrate\ProfileValuesBuilderTest.
+ * Contains \Drupal\user\Tests\Migrate\d6\ProfileValuesBuilderTest.
  */
 
-namespace Drupal\user\Tests\Migrate;
+namespace Drupal\user\Tests\Migrate\d6;
 
 use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
 
diff --git a/core/modules/user/src/Tests/Migrate/d7/MigrateUserFloodTest.php b/core/modules/user/src/Tests/Migrate/d7/MigrateUserFloodTest.php
new file mode 100644
index 0000000..92c2c23
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/d7/MigrateUserFloodTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\d7\MigrateUserFloodTest.
+ */
+
+namespace Drupal\user\Tests\Migrate\d7;
+
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+
+/**
+ * Migrates user flood control configuration.
+ *
+ * @group user
+ */
+class MigrateUserFloodTest extends MigrateDrupal7TestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('system');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installConfig(['user']);
+    $this->executeMigration('d7_user_flood');
+  }
+
+  /**
+   * Tests the migration.
+   */
+  public function testMigration() {
+    $expected = [
+      'uid_only' => TRUE,
+      'ip_limit' => 30,
+      'ip_window' => 7200,
+      'user_limit' => 22,
+      'user_window' => 86400,
+    ];
+    $this->assertIdentical($expected, $this->config('user.flood')->get());
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/d7/MigrateUserMailTest.php b/core/modules/user/src/Tests/Migrate/d7/MigrateUserMailTest.php
new file mode 100644
index 0000000..9c88f55
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/d7/MigrateUserMailTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\d7\MigrateUserMailTest.
+ */
+
+namespace Drupal\user\Tests\Migrate\d7;
+
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+
+/**
+ * Migrates user mail configuration.
+ *
+ * @group user
+ */
+class MigrateUserMailTest extends MigrateDrupal7TestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installConfig(['user']);
+    $this->executeMigration('d7_user_mail');
+  }
+
+  /**
+   * Tests the migration.
+   */
+  public function testMigration() {
+    $config = $this->config('user.mail');
+    $this->assertIdentical('Your account is approved!', $config->get('status_activated.subject'));
+    $this->assertIdentical('Your account was activated, and there was much rejoicing.', $config->get('status_activated.body'));
+    $this->assertIdentical('Fix your password', $config->get('password_reset.subject'));
+    $this->assertIdentical("Nope! You're locked out forever.", $config->get('password_reset.body'));
+    $this->assertIdentical('So long, bub', $config->get('cancel_confirm.subject'));
+    $this->assertIdentical('The gates of Drupal are closed to you. Now you will work in the salt mines.', $config->get('cancel_confirm.body'));
+    $this->assertIdentical('Gawd made you an account', $config->get('register_admin_created.subject'));
+    $this->assertIdentical('...and she could take it away.', $config->get('register_admin_created.body'));
+    $this->assertIdentical('Welcome!', $config->get('register_no_approval_required.subject'));
+    $this->assertIdentical('You can now log in if you can figure out how to use Drupal!', $config->get('register_no_approval_required.body'));
+    $this->assertIdentical('Soon...', $config->get('register_pending_approval.subject'));
+    $this->assertIdentical('...you will join our Circle. Let the Drupal flow through you.', $config->get('register_pending_approval.body'));
+    $this->assertIdentical('BEGONE!', $config->get('status_blocked.subject'));
+    $this->assertIdentical('You no longer please the robot overlords. Go to your room and chill out.', $config->get('status_blocked.body'));
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/d7/MigrateUserRoleTest.php b/core/modules/user/src/Tests/Migrate/d7/MigrateUserRoleTest.php
new file mode 100644
index 0000000..51f8f97
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/d7/MigrateUserRoleTest.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\d7\MigrateUserRoleTest.
+ */
+
+namespace Drupal\user\Tests\Migrate\d7;
+
+use Drupal\Core\Database\Database;
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+use Drupal\user\Entity\Role;
+use Drupal\user\RoleInterface;
+
+/**
+ * Upgrade user roles to user.role.*.yml.
+ *
+ * @group user
+ */
+class MigrateUserRoleTest extends MigrateDrupal7TestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('user');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->executeMigration('d7_user_role');
+  }
+
+  /**
+   * Asserts aspects of a user role config entity.
+   *
+   * @param string $id
+   *   The role ID.
+   * @param string $label
+   *   The role's expected label.
+   * @param int|NULL $original_rid
+   *   The original (integer) ID of the role, to check permissions.
+   */
+  protected function assertEntity($id, $label, $original_rid) {
+    /** @var \Drupal\user\RoleInterface $entity */
+    $entity = Role::load($id);
+    $this->assertTrue($entity instanceof RoleInterface);
+    $this->assertIdentical($label, $entity->label());
+
+    if (isset($original_rid)) {
+      $permissions = Database::getConnection('default', 'migrate')
+        ->select('role_permission', 'rp')
+        ->fields('rp', ['permission'])
+        ->condition('rid', $original_rid)
+        ->execute()
+        ->fetchCol();
+      $this->assertIdentical($permissions, $entity->getPermissions());
+    }
+  }
+
+  /**
+   * Tests user role migration.
+   */
+  public function testUserRole() {
+    $this->assertEntity('anonymous', 'anonymous user', 1);
+    $this->assertEntity('authenticated', 'authenticated user', 2);
+    $this->assertEntity('administrator', 'administrator', 3);
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/d7/MigrateUserTest.php b/core/modules/user/src/Tests/Migrate/d7/MigrateUserTest.php
new file mode 100644
index 0000000..3b70a08
--- /dev/null
+++ b/core/modules/user/src/Tests/Migrate/d7/MigrateUserTest.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Migrate\d7\MigrateUserTest.
+ */
+
+namespace Drupal\user\Tests\Migrate\d7;
+
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+use Drupal\user\Entity\User;
+use Drupal\user\RoleInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * Users migration.
+ *
+ * @group user
+ */
+class MigrateUserTest extends MigrateDrupal7TestBase {
+
+  /**
+   * The modules to be enabled during the test.
+   *
+   * @var array
+   */
+  static $modules = array('user');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->executeMigration('d7_user_role');
+    $this->executeMigration('d7_user');
+  }
+
+  /**
+   * Asserts various aspects of a user account.
+   *
+   * @param string $id
+   *   The user ID.
+   * @param string $label
+   *   The username.
+   * @param string $mail
+   *   The user's e-mail address.
+   * @param int $access
+   *   The last access time.
+   * @param int $login
+   *   The last login time.
+   * @param bool $blocked
+   *   Whether or not the account is blocked.
+   * @param string $langcode
+   *   The user account's language code.
+   * @param string $init
+   *   The user's initial e-mail address.
+   * @param string[] $roles
+   *   Role IDs the user account is expected to have.
+   */
+  protected function assertEntity($id, $label, $mail, $access, $login, $blocked, $langcode, $init, array $roles = [RoleInterface::AUTHENTICATED_ID]) {
+    /** @var \Drupal\user\UserInterface $user */
+    $user = User::load($id);
+    $this->assertTrue($user instanceof UserInterface);
+    $this->assertIdentical($label, $user->label());
+    $this->assertIdentical($mail, $user->getEmail());
+    $this->assertIdentical($access, $user->getLastAccessedTime());
+    $this->assertIdentical($login, $user->getLastLoginTime());
+    $this->assertIdentical($blocked, $user->isBlocked());
+    // $user->getPreferredLangcode() might fallback to default language if the
+    // user preferred language is not configured on the site. We just want to
+    // test if the value was imported correctly.
+    $this->assertIdentical($langcode, $user->langcode->value);
+    $this->assertIdentical($langcode, $user->preferred_langcode->value);
+    $this->assertIdentical($langcode, $user->preferred_admin_langcode->value);
+    $this->assertIdentical($init, $user->getInitialEmail());
+    $this->assertIdentical($roles, $user->getRoles());
+  }
+
+  /**
+   * Tests the Drupal 7 user to Drupal 8 migration.
+   */
+  public function testUser() {
+    $this->assertEntity(2, 'Odo', 'odo@local.host', '0', '0', FALSE, '', 'odo@local.host');
+  }
+
+}
diff --git a/core/modules/user/src/Tests/Migrate/ProfileValuesBuilderTest.php b/core/modules/user/src/Tests/Migrate/d7/UserMigrationBuilderTest.php
similarity index 55%
rename from core/modules/user/src/Tests/Migrate/ProfileValuesBuilderTest.php
rename to core/modules/user/src/Tests/Migrate/d7/UserMigrationBuilderTest.php
index 747edc9..77b7abb 100644
--- a/core/modules/user/src/Tests/Migrate/ProfileValuesBuilderTest.php
+++ b/core/modules/user/src/Tests/Migrate/d7/UserMigrationBuilderTest.php
@@ -2,17 +2,17 @@
 
 /**
  * @file
- * Contains \Drupal\user\Tests\Migrate\ProfileValuesBuilderTest.
+ * Contains \Drupal\user\Tests\Migrate\d7\UserMigrationBuilderTest.
  */
 
-namespace Drupal\user\Tests\Migrate;
+namespace Drupal\user\Tests\Migrate\d7;
 
-use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
 
 /**
  * @group user
  */
-class ProfileValuesBuilderTest extends MigrateDrupal6TestBase {
+class UserMigrationBuilderTest extends MigrateDrupal7TestBase {
 
   public static $modules = ['migrate', 'migrate_drupal', 'user'];
 
@@ -22,15 +22,15 @@ class ProfileValuesBuilderTest extends MigrateDrupal6TestBase {
    */
   public function testBuilder() {
     $template = \Drupal::service('migrate.template_storage')
-      ->getTemplateByName('d6_profile_values');
+      ->getTemplateByName('d7_user');
     /** @var \Drupal\migrate\Entity\MigrationInterface[] $migrations */
     $migrations = \Drupal::service('plugin.manager.migrate.builder')
-      ->createInstance('d6_profile_values')
+      ->createInstance('d7_user')
       ->buildMigrations($template);
 
-    $this->assertIdentical('d6_profile_values', $migrations[0]->id());
+    $this->assertIdentical('d7_user', $migrations[0]->id());
     $process = $migrations[0]->getProcess();
-    $this->assertIdentical('profile_color', $process['profile_color'][0]['source']);
+    $this->assertIdentical('field_file', $process['field_file'][0]['source']);
   }
 
 }
diff --git a/core/modules/user/tests/src/Unit/Migrate/d6/ProfileFieldTest.php b/core/modules/user/tests/src/Unit/Migrate/ProfileFieldTest.php
similarity index 79%
rename from core/modules/user/tests/src/Unit/Migrate/d6/ProfileFieldTest.php
rename to core/modules/user/tests/src/Unit/Migrate/ProfileFieldTest.php
index ccc2ec2..307a259 100644
--- a/core/modules/user/tests/src/Unit/Migrate/d6/ProfileFieldTest.php
+++ b/core/modules/user/tests/src/Unit/Migrate/ProfileFieldTest.php
@@ -2,30 +2,24 @@
 
 /**
  * @file
- * Contains \Drupal\Tests\user\Unit\Migrate\d6\ProfileFieldTest.
+ * Contains \Drupal\Tests\user\Unit\Migrate\ProfileFieldTest.
  */
 
-namespace Drupal\Tests\user\Unit\Migrate\d6;
+namespace Drupal\Tests\user\Unit\Migrate;
 
 use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
 
 /**
- * Tests D6 profile field source plugin.
+ * Tests profile_field source plugin.
  *
  * @group user
  */
 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\user\Plugin\migrate\source\d6\ProfileField';
+  const PLUGIN_CLASS = 'Drupal\user\Plugin\migrate\source\ProfileField';
 
-  // The fake Migration configuration entity.
   protected $migrationConfiguration = [
-    // The id of the entity, can be any string.
     'id' => 'test_profile_fields',
-    // Leave it empty for now.
-    'idlist' => [],
     'source' => [
       'plugin' => 'd6_profile_field',
     ],
diff --git a/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/RoleTest.php b/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/RoleTest.php
new file mode 100644
index 0000000..3fcde05
--- /dev/null
+++ b/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/RoleTest.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\user\Unit\Plugin\migrate\source\d7\RoleTest.
+ */
+
+namespace Drupal\Tests\user\Unit\Plugin\migrate\source\d7;
+
+use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
+
+/**
+ * Tests D7 role source plugin.
+ *
+ * @group user
+ */
+class RoleTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\user\Plugin\migrate\source\d7\Role';
+
+  protected $migrationConfiguration = array(
+    'id' => 'test',
+    'source' => array(
+      'plugin' => 'd7_user_role',
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'rid' => 1,
+      'name' => 'anonymous user',
+      'permissions' => array(
+        'access content',
+      ),
+    ),
+    array(
+      'rid' => 2,
+      'name' => 'authenticated user',
+      'permissions' => array(
+        'access comments',
+        'access content',
+        'post comments',
+        'post comments without approval',
+      ),
+    ),
+    array(
+      'rid' => 3,
+      'name' => 'administrator',
+      'permissions' => array(
+        'access comments',
+        'administer comments',
+        'post comments',
+        'post comments without approval',
+        'access content',
+        'administer content types',
+        'administer nodes',
+      ),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $row) {
+      foreach ($row['permissions'] as $permission) {
+        $this->databaseContents['role_permission'][] = array(
+          'permission' => $permission,
+          'rid' => $row['rid'],
+        );
+      }
+      unset($row['permissions']);
+      $this->databaseContents['role'][] = $row;
+    }
+    parent::setUp();
+  }
+
+}
diff --git a/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/UserTest.php b/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/UserTest.php
new file mode 100644
index 0000000..c7e35e1
--- /dev/null
+++ b/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/UserTest.php
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\user\Unit\Plugin\migrate\source\d7\UserTest.
+ */
+
+namespace Drupal\Tests\user\Unit\Plugin\migrate\source\d7;
+
+use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
+
+/**
+ * Tests D7 user source plugin.
+ *
+ * @group user
+ */
+class UserTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\user\Plugin\migrate\source\d7\User';
+
+  protected $migrationConfiguration = [
+    'id' => 'test',
+    'source' => [
+      'plugin' => 'd7_user',
+    ],
+  ];
+
+  protected $expectedResults = [
+    [
+      'uid' => '2',
+      'name' => 'Odo',
+      'pass' => '$S$DVpvPItXvnsmF3giVEe7Jy2lG.SCoEs8uKwpHsyPvdeNAaNZYxZ8',
+      'mail' => 'odo@local.host',
+      'signature' => '',
+      'signature_format' => 'filtered_html',
+      'created' => '1432750741',
+      'access' => '0',
+      'login' => '0',
+      'status' => '1',
+      'timezone' => 'America/Chicago',
+      'language' => '',
+      'picture' => '0',
+      'init' => 'odo@local.host',
+      'roles' => [
+        2 => 'authenticated user',
+      ],
+      'data' => [
+        'contact' => 1,
+      ],
+      'field_file' => [
+        [
+          'fid' => 99,
+          'display' => 1,
+          'description' => 'None',
+        ],
+      ],
+    ],
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->databaseContents['users'][] = [
+      'uid' => '2',
+      'name' => 'Odo',
+      'pass' => '$S$DVpvPItXvnsmF3giVEe7Jy2lG.SCoEs8uKwpHsyPvdeNAaNZYxZ8',
+      'mail' => 'odo@local.host',
+      'theme' => '',
+      'signature' => '',
+      'signature_format' => 'filtered_html',
+      'created' => '1432750741',
+      'access' => '0',
+      'login' => '0',
+      'status' => '1',
+      'timezone' => 'America/Chicago',
+      'language' => '',
+      'picture' => '0',
+      'init' => 'odo@local.host',
+      'data' => 'a:1:{s:7:"contact";i:1;}',
+    ];
+    $this->databaseContents['users_roles'][] = [
+      'uid' => 2,
+      'rid' => 2,
+    ];
+    $this->databaseContents['role'][] = [
+      'rid' => 2,
+      'name' => 'authenticated user',
+      'weight' => 0,
+    ];
+    $this->databaseContents['field_config_instance'] = [
+      [
+        'id' => '33',
+        'field_id' => '11',
+        'field_name' => 'field_file',
+        'entity_type' => 'user',
+        'bundle' => 'user',
+        'data' => 'a:0:{}',
+        'deleted' => '0',
+      ],
+    ];
+    $this->databaseContents['field_data_field_file'] = [
+      [
+        'entity_type' => 'user',
+        'bundle' => 'user',
+        'deleted' => 0,
+        'entity_id' => 2,
+        'revision_id' => NULL,
+        'language' => 'und',
+        'delta' => 0,
+        'field_file_fid' => 99,
+        'field_file_display' => 1,
+        'field_file_description' => 'None',
+      ],
+    ];
+    parent::setUp();
+  }
+
+}
