diff --git a/plugins/FeedsUserProcessor.inc b/plugins/FeedsUserProcessor.inc
index 47d26e5cda4b8931b7ad02a07fd5bfddcd2f8c6a..606a0440f92f19bc1beedb43de776bfc987b6973 100644
--- a/plugins/FeedsUserProcessor.inc
+++ b/plugins/FeedsUserProcessor.inc
@@ -16,6 +16,15 @@ define('FEEDS_BLOCK_NON_EXISTENT', 'block');
  * Feeds processor plugin. Create users from feed items.
  */
 class FeedsUserProcessor extends FeedsProcessor {
+  /**
+   * Search by role name.
+   */
+  const ROLE_SEARCH_NAME = 'name';
+
+  /**
+   * Search by role id.
+   */
+  const ROLE_SEARCH_RID = 'rid';
 
   /**
    * Define entity type.
@@ -147,17 +156,44 @@ class FeedsUserProcessor extends FeedsProcessor {
     return $form;
   }
 
+  /**
+   * Overrides FeedsProcessor::map().
+   *
+   * Ensures that the user is assigned additional roles that are configured on
+   * the settings. The roles could have been revoked when there was mapped to
+   * the "roles_list" target.
+   */
+  protected function map(FeedsSource $source, FeedsParserResult $result, $target_item = NULL) {
+    $target_item = parent::map($source, $result, $target_item);
+
+    // Assign additional roles as configured.
+    $roles = array_filter($this->config['roles']);
+    foreach ($roles as $rid) {
+      $target_item->roles[$rid] = $rid;
+    }
+
+    return $target_item;
+  }
+
   /**
    * Override setTargetElement to operate on a target item that is a node.
    */
-  public function setTargetElement(FeedsSource $source, $target_user, $target_element, $value) {
+  public function setTargetElement(FeedsSource $source, $target_user, $target_element, $value, array $mapping = array()) {
     switch ($target_element) {
       case 'created':
         $target_user->created = feeds_to_unixtime($value, REQUEST_TIME);
         break;
+
       case 'language':
         $target_user->language = strtolower($value);
         break;
+
+      case 'roles_list':
+        // Ensure that the role list is an array.
+        $value = (array) $value;
+        $this->rolesListSetTarget($source, $target_user, $target_element, $value, $mapping);
+        break;
+
       default:
         parent::setTargetElement($source, $target_user, $target_element, $value);
         break;
@@ -196,6 +232,12 @@ class FeedsUserProcessor extends FeedsProcessor {
         'name' => t('User language'),
         'description' => t('Default language for the user.'),
       ),
+      'roles_list' => array(
+        'name' => t('User roles'),
+        'description' => t('User roles provided as role names in comma separated list.'),
+        'summary_callbacks' => array(array($this, 'rolesListSummaryCallback')),
+        'form_callbacks' => array(array($this, 'rolesListFormCallback')),
+      ),
     );
     if (module_exists('openid')) {
       $targets['openid'] = array(
@@ -270,4 +312,170 @@ class FeedsUserProcessor extends FeedsProcessor {
     }
   }
 
+  /**
+   * Returns default values for mapper "roles_list".
+   */
+  public function rolesListDefaults() {
+    $roles = user_roles(TRUE);
+    unset($roles[DRUPAL_AUTHENTICATED_RID]);
+    $rids = array_keys($roles);
+    $rids = array_combine($rids, $rids);
+    return array(
+      'role_search' => self::ROLE_SEARCH_NAME,
+      'allowed_roles' => $rids,
+      'autocreate' => 0,
+      'revoke_roles' => 1,
+    );
+  }
+
+  /**
+   * Mapping configuration summary callback for target "roles_list".
+   */
+  public function rolesListSummaryCallback(array $mapping, $target, array $form, array $form_state) {
+    $options = array();
+
+    // Add in defaults.
+    $defaults = $this->rolesListDefaults();
+    $mapping += $defaults;
+    $mapping['allowed_roles'] += $defaults['allowed_roles'];
+
+    // Role search.
+    $role_search_options = $this->rolesListRoleSearchOptions();
+    $options[] = t('Search roles by: <strong>@search</strong>', array('@search' => $role_search_options[$mapping['role_search']]));
+
+    // Allowed roles.
+    $role_names = array();
+    $roles = user_roles(TRUE);
+    foreach (array_filter($mapping['allowed_roles']) as $rid => $enabled) {
+      $role_names[] = $roles[$rid];
+    }
+
+    if (empty($role_names)) {
+      $role_names = array('<' . t('none') . '>');
+    }
+    $options[] = t('Allowed roles: %roles', array('%roles' => implode(', ', $role_names)));
+
+    // Autocreate.
+    if ($mapping['autocreate']) {
+      $options[] = t('Automatically create roles');
+    }
+    else {
+      $options[] = t('Only assign existing roles');
+    }
+
+    // Revoke roles.
+    if ($mapping['revoke_roles']) {
+      $options[] = t('Revoke roles: yes');
+    }
+    else {
+      $options[] = t('Revoke roles: no');
+    }
+
+    return implode('<br />', $options);
+  }
+
+  /**
+   * Mapping configuration form callback for target "roles_list".
+   */
+  public function rolesListFormCallback(array $mapping, $target, array $form, array $form_state) {
+    // Add in defaults.
+    $defaults = $this->rolesListDefaults();
+    $mapping += $defaults;
+    $mapping['allowed_roles'] += $defaults['allowed_roles'];
+
+    $allowed_roles_options = user_roles(TRUE);
+    unset($allowed_roles_options[DRUPAL_AUTHENTICATED_RID]);
+
+    return array(
+      'role_search' => array(
+        '#type' => 'select',
+        '#title' => t('Search roles by'),
+        '#options' => $this->rolesListRoleSearchOptions(),
+        '#default_value' => $mapping['role_search'],
+      ),
+      'allowed_roles' => array(
+        '#type' => 'checkboxes',
+        '#title' => t('Allowed roles'),
+        '#options' => $allowed_roles_options,
+        '#default_value' => $mapping['allowed_roles'],
+        '#description' => t('Select the roles to accept from the feed.<br />Any other roles will be ignored.')
+      ),
+      'autocreate' => array(
+        '#type' => 'checkbox',
+        '#title' => t('Auto create'),
+        '#description' => t("Create the role if it doesn't exist."),
+        '#default_value' => $mapping['autocreate'],
+      ),
+      'revoke_roles' => array(
+        '#type' => 'checkbox',
+        '#title' => t('Revoke roles'),
+        '#description' => t('If enabled, roles that are not provided by the feed will be revoked for the user. This affects only the "Allowed roles" as configured above.'),
+        '#default_value' => $mapping['revoke_roles'],
+      ),
+    );
+  }
+
+  /**
+   * Returns role list options.
+   */
+  public function rolesListRoleSearchOptions() {
+    return array(
+      self::ROLE_SEARCH_NAME => t('Role name'),
+      self::ROLE_SEARCH_RID => t('Role ID'),
+    );
+  }
+
+  /**
+   * Sets role target on the user entity.
+   */
+  public function rolesListSetTarget(FeedsSource $source, $entity, $target, array $values, array $mapping) {
+    // Add in defaults.
+    $defaults = $this->rolesListDefaults();
+    $mapping += $defaults;
+    $mapping['allowed_roles'] += $defaults['allowed_roles'];
+
+    // Eventually revoke roles. Do not touch roles that are not allowed to set
+    // by the source.
+    if ($mapping['revoke_roles']) {
+      foreach ($mapping['allowed_roles'] as $rid) {
+        unset($entity->roles[$rid]);
+      }
+    }
+
+    foreach ($values as $value) {
+      $role = NULL;
+
+      $value = trim($value);
+      if (strlen($value) < 1) {
+        // No role provided. Continue to the next role.
+        continue;
+      }
+
+      switch ($mapping['role_search']) {
+        case self::ROLE_SEARCH_NAME:
+          $role = user_role_load_by_name($value);
+          if (!$role && !empty($mapping['autocreate'])) {
+            // Create new role if role doesn't exist.
+            $role = new stdClass();
+            $role->name = $value;
+            user_role_save($role);
+            $role = user_role_load_by_name($role->name);
+          }
+          break;
+
+        case self::ROLE_SEARCH_RID:
+          $role = user_role_load($value);
+          break;
+      }
+
+      if ($role) {
+        // Check if the role may be assigned.
+        if (isset($mapping['allowed_roles'][$role->rid]) && !$mapping['allowed_roles'][$role->rid]) {
+          // This role may *not* be assiged.
+          continue;
+        }
+        $entity->roles[$role->rid] = $role->name;
+      }
+    }
+  }
 }
diff --git a/tests/feeds.test b/tests/feeds.test
index b3ce145cebe0088f6bb9666682bbb538c814ad87..e80352514a98efc2db224df78eeb35b403d0cf49 100644
--- a/tests/feeds.test
+++ b/tests/feeds.test
@@ -468,7 +468,14 @@ class FeedsWebTestCase extends DrupalWebTestCase {
         // Set some settings.
         $edit = array();
         foreach ($config as $key => $value) {
-          $edit["config[$i][settings][$key]"] = $value;
+          if (is_array($value)) {
+            foreach ($value as $subkey => $subvalue) {
+              $edit["config[$i][settings][$key][$subkey]"] = $subvalue;
+            }
+          }
+          else {
+            $edit["config[$i][settings][$key]"] = $value;
+          }
         }
         $this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_' . $i);
         $this->drupalPost(NULL, array(), t('Save'));
diff --git a/tests/feeds/users_roles.csv b/tests/feeds/users_roles.csv
new file mode 100644
index 0000000000000000000000000000000000000000..414cfef42bf865a2822f90aec172da5c31c60151
--- /dev/null
+++ b/tests/feeds/users_roles.csv
@@ -0,0 +1,5 @@
+name,mail,since,password,roles,rids
+Morticia,morticia@example.com,1244347500,mort,editor,6
+Fester,fester@example.com,1241865600,fest,manager,4
+Gomez,gomez@example.com,1228572000,gome,tester| |manager,5| |4
+Pugsley,pugsley@example.com,1228260225,pugs,,
\ No newline at end of file
diff --git a/tests/feeds_processor_user.test b/tests/feeds_processor_user.test
index 4bc82d5109f62b1017a80937a62aa6036dd0d15a..c51898bd786b1750f392a35fb52bda56f1df1e30 100644
--- a/tests/feeds_processor_user.test
+++ b/tests/feeds_processor_user.test
@@ -18,9 +18,14 @@ class FeedsCSVtoUsersTest extends FeedsWebTestCase {
   }
 
   /**
-   * Test node creation, refreshing/deleting feeds and feed items.
+   * {@inheritdoc}
    */
-  public function test() {
+  public function setUp() {
+    parent::setUp();
+
+    // Include FeedsProcessor.inc to make its constants available.
+    module_load_include('inc', 'feeds', 'plugins/FeedsProcessor');
+
     // Create an importer.
     $this->createImporterConfiguration('User import', 'user_import');
 
@@ -57,7 +62,12 @@ class FeedsCSVtoUsersTest extends FeedsWebTestCase {
       'content_type' => '',
     );
     $this->drupalPost('admin/structure/feeds/user_import/settings', $edit, 'Save');
+  }
 
+  /**
+   * Test user creation, refreshing/deleting feeds and feed items.
+   */
+  public function test() {
     // Create roles and assign one of them to the users to be imported.
     $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
     $admin_rid = $this->drupalCreateRole(array('access content'), 'administrator');
@@ -134,4 +144,460 @@ class FeedsCSVtoUsersTest extends FeedsWebTestCase {
     $this->assertText('Failed importing 2 user');
   }
 
+  /**
+   * Tests mapping to role without automatically creating new roles.
+   */
+  public function testRoleTargetWithoutRoleCreation() {
+    // Add mapping to role.
+    $this->addMappings('user_import', array(
+      4 => array(
+        'source' => 'roles',
+        'target' => 'roles_list',
+      ),
+    ));
+
+    // Create manager role.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that Morticia did not get the editor role and has one role in
+    // total.
+    $account = user_load_by_name('Morticia');
+    $this->assertFalse(in_array('editor', $account->roles), 'Morticia does not have the editor role.');
+    $this->assertEqual(1, count($account->roles), 'Morticia has one role.');
+
+    // Assert that Fester got the manager role and two roles in total.
+    $account = user_load_by_name('Fester');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Fester has the manager role.');
+    $this->assertEqual(2, count($account->roles), 'Fester has two roles.');
+
+    // Assert that Gomez got the manager role but not the tester role, since
+    // that role doesn't exist on the system.
+    $account = user_load_by_name('Gomez');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Gomez has the manager role.');
+    $this->assertFalse(in_array('tester', $account->roles), 'Gomez does not have the tester role.');
+    $this->assertEqual(2, count($account->roles), 'Gomez has two roles.');
+
+    // Assert that Pugsley only has one role.
+    $account = user_load_by_name('Pugsley');
+    $this->assertEqual(1, count($account->roles), 'Pugsley has one role.');
+
+    // Assert that only three roles exist:
+    // - authenticated user
+    // - role from the admin user
+    // - manager
+    $roles = user_roles(TRUE);
+    $this->assertEqual(3, count($roles), 'Only three roles exist.');
+  }
+
+  /**
+   * Tests mapping to role with automatically creating new roles.
+   */
+  public function testRoleTargetWithRoleCreation() {
+    // Add mapping to role.
+    $this->addMappings('user_import', array(
+      4 => array(
+        'source' => 'roles',
+        'target' => 'roles_list',
+        'autocreate' => TRUE,
+      ),
+    ));
+
+    // Create manager role.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that Morticia got the editor role and two roles in total.
+    $account = user_load_by_name('Morticia');
+    $this->assertTrue(in_array('editor', $account->roles), 'Morticia has the editor role.');
+    $this->assertEqual(2, count($account->roles), 'Morticia has two roles.');
+
+    // Assert that Fester got the manager role and two roles in total.
+    $account = user_load_by_name('Fester');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Fester has the manager role.');
+    $this->assertEqual(2, count($account->roles), 'Fester has two roles.');
+
+    // Assert that Gomez got the manager, the editor role and three roles in
+    // total.
+    $account = user_load_by_name('Gomez');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Gomez has the manager role.');
+    $this->assertTrue(in_array('tester', $account->roles), 'Gomez has the tester role.');
+    $this->assertEqual(3, count($account->roles), 'Gomez has three roles.');
+
+    // Assert that Pugsley only has one role.
+    $account = user_load_by_name('Pugsley');
+    $this->assertEqual(1, count($account->roles), 'Pugsley has one role.');
+
+    // Assert that five roles exist:
+    // - authenticated user
+    // - role from the admin user
+    // - manager
+    // - editor
+    // - tester
+    $roles = user_roles(TRUE);
+    $this->assertEqual(5, count($roles), 'Five roles exist.');
+  }
+
+  /**
+   * Tests mapping to role using role ID's.
+   */
+  public function testRoleTargetRids() {
+    // Add mapping to role.
+    $this->addMappings('user_import', array(
+      4 => array(
+        'source' => 'rids',
+        'target' => 'roles_list',
+        'role_search' => FeedsUserProcessor::ROLE_SEARCH_RID,
+      ),
+    ));
+
+    // Create manager and tester roles.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+    $tester_rid = $this->drupalCreateRole(array('access content'), 'tester');
+    // Ensure expected ID's of these roles.
+    $this->assertEqual(4, $manager_rid);
+    $this->assertEqual(5, $tester_rid);
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that Morticia did not get the editor role and has one role in
+    // total.
+    $account = user_load_by_name('Morticia');
+    $this->assertFalse(in_array('editor', $account->roles), 'Morticia does not have the editor role.');
+    $this->assertEqual(1, count($account->roles), 'Morticia has one role.');
+
+    // Assert that Fester got the manager role and two roles in total.
+    $account = user_load_by_name('Fester');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Fester has the manager role.');
+    $this->assertEqual(2, count($account->roles), 'Fester has two roles.');
+
+    // Assert that Gomez got the manager and tester roles.
+    $account = user_load_by_name('Gomez');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Gomez has the manager role.');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Gomez has the tester role.');
+    $this->assertEqual(3, count($account->roles), 'Gomez has two roles.');
+
+    // Assert that Pugsley only has one role.
+    $account = user_load_by_name('Pugsley');
+    $this->assertEqual(1, count($account->roles), 'Pugsley has one role.');
+
+    // Assert that four roles exist:
+    // - authenticated user
+    // - role from the admin user
+    // - manager
+    // - tester
+    $roles = user_roles(TRUE);
+    $this->assertEqual(4, count($roles), 'Four roles exist.');
+  }
+
+  /**
+   * Tests mapping to role using only allowed roles.
+   */
+  public function testRoleTargetWithAllowedRoles() {
+    // Create manager role.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+    // Create editor role.
+    $editor_rid = $this->drupalCreateRole(array('access content'), 'editor');
+
+    // Add mapping to role.
+    // The manager role may not be assigned to the user by the feed.
+    $this->addMappings('user_import', array(
+      4 => array(
+        'source' => 'roles',
+        'target' => 'roles_list',
+        'allowed_roles' => array(
+          $manager_rid => FALSE,
+          $editor_rid => $editor_rid,
+        ),
+        'autocreate' => TRUE,
+      ),
+    ));
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that Morticia got the editor role and two roles in total.
+    $account = user_load_by_name('Morticia');
+    $this->assertTrue(in_array('editor', $account->roles), 'Morticia has the editor role.');
+    $this->assertEqual(2, count($account->roles), 'Morticia has two roles.');
+
+    // Assert that Fester did not got the manager role, because that role was
+    // not an allowed value.
+    $account = user_load_by_name('Fester');
+    $this->assertFalse(isset($account->roles[$manager_rid]), 'Fester does not have the manager role.');
+    $this->assertEqual(1, count($account->roles), 'Fester has one role.');
+
+    // Assert that Gomez only got the tester role and not the manager role.
+    $account = user_load_by_name('Gomez');
+    $this->assertFalse(isset($account->roles[$manager_rid]), 'Gomez does not have the manager role.');
+    $this->assertTrue(in_array('tester', $account->roles), 'Gomez has the tester role.');
+    $this->assertEqual(2, count($account->roles), 'Gomez has two roles.');
+  }
+
+  /**
+   * Tests that roles can be revoked and that only allowed roles are revoked.
+   */
+  public function testRoleTargetRevokeRoles() {
+    // Create manager role.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+    // Create editor role.
+    $editor_rid = $this->drupalCreateRole(array('access content'), 'editor');
+    // Create tester role.
+    $tester_rid = $this->drupalCreateRole(array('access content'), 'tester');
+
+    // Set to update existing users.
+    $this->setSettings('user_import', 'FeedsUserProcessor', array('update_existing' => FEEDS_UPDATE_EXISTING));
+
+    // Add mapping to role.
+    // The manager role may not be revoked, but the editor role may.
+    $this->addMappings('user_import', array(
+      4 => array(
+        'source' => 'roles',
+        'target' => 'roles_list',
+        'allowed_roles' => array(
+          $manager_rid => FALSE,
+          $editor_rid => $editor_rid,
+          $tester_rid => $tester_rid,
+        ),
+      ),
+    ));
+
+    // Create account for Morticia with roles "manager" and "editor". In the
+    // source only "editor" is specified. Morticia should keep both roles.
+    user_save(drupal_anonymous_user(), array(
+      'name' => 'Morticia',
+      'mail' => 'morticia@example.com',
+      'pass' => 'mort',
+      'status' => 1,
+      'roles' => array(
+        $manager_rid => $manager_rid,
+        $editor_rid => $editor_rid,
+      ),
+    ));
+    // Create account for Pugsley with roles "manager", "editor" and "tester".
+    // Pugsley has no roles in the source so should only keep the "manager"
+    // role.
+    user_save(drupal_anonymous_user(), array(
+      'name' => 'Pugsley',
+      'mail' => 'pugsley@example.com',
+      'pass' => 'pugs',
+      'status' => 1,
+      'roles' => array(
+        $manager_rid => $manager_rid,
+        $editor_rid => $editor_rid,
+        $tester_rid => $tester_rid,
+      ),
+    ));
+    // Create account for Gomez and give it the "editor" role. Gomez has roles
+    // "tester" and "manager" in the source, so it should lose the "editor" role
+    // and gain the "tester" role.
+    user_save(drupal_anonymous_user(), array(
+      'name' => 'Gomez',
+      'mail' => 'gomez@example.com',
+      'pass' => 'gome',
+      'status' => 1,
+      'roles' => array(
+        $editor_rid => $editor_rid,
+      ),
+    ));
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that Morticia kept the manager and editor roles.
+    $account = user_load_by_name('Morticia');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Morticia still has the manager role.');
+    $this->assertTrue(isset($account->roles[$editor_rid]), 'Morticia has the editor role.');
+    $this->assertEqual(3, count($account->roles), 'Morticia has three roles.');
+
+    // Assert that Pugsley only kept the manager role.
+    $account = user_load_by_name('Pugsley');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Pugsley still has the manager role.');
+    $this->assertFalse(isset($account->roles[$editor_rid]), 'Pugsley no longer has the editor role.');
+    $this->assertFalse(isset($account->roles[$tester_rid]), 'Pugsley no longer has the tester role.');
+    $this->assertEqual(2, count($account->roles), 'Pugsley has two roles.');
+
+    // Assert that Gomez lost the editor role, and gained the tester role.
+    $account = user_load_by_name('Gomez');
+    $this->assertFalse(isset($account->roles[$editor_rid]), 'Gomez no longer has the editor role.');
+    $this->assertTrue(isset($account->roles[$tester_rid]), 'Gomez has the tester role.');
+    $this->assertEqual(2, count($account->roles), 'Gomez has two roles.');
+  }
+
+  /**
+   * Tests if no roles are revoked if the option "Revoke roles" is disabled.
+   */
+  public function testRoleTargetNoRevokeRoles() {
+    // Create manager role.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+    // Create editor role.
+    $editor_rid = $this->drupalCreateRole(array('access content'), 'editor');
+
+    // Set to update existing users.
+    $this->setSettings('user_import', 'FeedsUserProcessor', array('update_existing' => FEEDS_UPDATE_EXISTING));
+
+    // Add mapping to role. Set option to not revoke roles.
+    $this->addMappings('user_import', array(
+      4 => array(
+        'source' => 'roles',
+        'target' => 'roles_list',
+        'allowed_roles' => array(
+          $manager_rid => FALSE,
+          $editor_rid => $editor_rid,
+        ),
+        'revoke_roles' => FALSE,
+      ),
+    ));
+
+    // Create account for Pugsley with roles "manager" and "editor". Pugsley has
+    // no roles, but roles should not be revoked, so Pugsley should keep all
+    // roles.
+    user_save(drupal_anonymous_user(), array(
+      'name' => 'Pugsley',
+      'mail' => 'pugsley@example.com',
+      'pass' => 'pugs',
+      'status' => 1,
+      'roles' => array(
+        $manager_rid => $manager_rid,
+        $editor_rid => $editor_rid,
+      ),
+    ));
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that Pugsley kept all roles.
+    $account = user_load_by_name('Pugsley');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Pugsley still has the manager role.');
+    $this->assertTrue(isset($account->roles[$editor_rid]), 'Pugsley still has the editor role.');
+    $this->assertEqual(3, count($account->roles), 'Pugsley has three roles.');
+  }
+
+  /**
+   * Tests if additional roles are assigned when creating or updating users.
+   */
+  public function testAdditionalRolesSetting() {
+    // Create manager role.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+    // Create editor role.
+    $editor_rid = $this->drupalCreateRole(array('access content'), 'editor');
+
+    // Set that the "manager" role should be assigned to every user that is
+    // imported.
+    $this->setSettings('user_import', 'FeedsUserProcessor', array(
+      "roles[$manager_rid]" => TRUE,
+      'update_existing' => FEEDS_UPDATE_EXISTING,
+    ));
+
+    // Create account for Gomez and give it the "editor" role. After import
+    // Gomez should have the roles "editor" and "manager".
+    user_save(drupal_anonymous_user(), array(
+      'name' => 'Gomez',
+      'mail' => 'gomez@example.com',
+      'pass' => 'gome',
+      'status' => 1,
+      'roles' => array(
+        $editor_rid => $editor_rid,
+      ),
+    ));
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that every imported user has gained the "manager" role.
+    $user_names = array(
+      'Morticia',
+      'Fester',
+      'Pugsley',
+    );
+    foreach ($user_names as $user_name) {
+      $vars = array(
+        '@user' => $user_name,
+      );
+      // Assert that this user has the "manager" role.
+      $account = user_load_by_name($user_name);
+      $this->assertTrue(isset($account->roles[$manager_rid]), format_string('@user has the manager role.', $vars));
+      $this->assertEqual(2, count($account->roles), format_string('@user has two roles.', $vars));
+    }
+
+    // Assert that Gomez has gained the role "manager" and still has the
+    // "editor" role.
+    $account = user_load_by_name('Gomez');
+    $this->assertTrue(isset($account->roles[$editor_rid]), 'Gomez still has the editor role.');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Gomez has the manager role.');
+    $this->assertEqual(3, count($account->roles), 'Gomez has three roles.');
+  }
+
+  /**
+   * Tests if additional roles are assigned when also the role mapper is used.
+   */
+  public function testAdditionalRolesSettingWithRoleTarget() {
+    // Create manager role.
+    $manager_rid = $this->drupalCreateRole(array('access content'), 'manager');
+    // Create editor role.
+    $editor_rid = $this->drupalCreateRole(array('access content'), 'editor');
+    // Create tester role.
+    $tester_rid = $this->drupalCreateRole(array('access content'), 'tester');
+
+    // Set that the "manager" role should be assigned to every user that is
+    // imported.
+    $this->setSettings('user_import', 'FeedsUserProcessor', array(
+      "roles[$manager_rid]" => TRUE,
+      'update_existing' => FEEDS_UPDATE_EXISTING,
+    ));
+    // Add mapping to role.
+    $this->addMappings('user_import', array(
+      4 => array(
+        'source' => 'roles',
+        'target' => 'roles_list',
+      ),
+    ));
+
+    // Create account for Morticia with roles "manager" and "tester". In the
+    // source, Morticia does not have the "manager" role, but because on the
+    // user processor settings that is an additional role to add, that role
+    // should not be revoked. The "tester" role, on the other hand, should be
+    // revoked.
+    user_save(drupal_anonymous_user(), array(
+      'name' => 'Morticia',
+      'mail' => 'morticia@example.com',
+      'pass' => 'mort',
+      'status' => 1,
+      'roles' => array(
+        $manager_rid => $manager_rid,
+        $tester_rid => $tester_rid,
+      ),
+    ));
+
+    // Import CSV file.
+    $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users_roles.csv');
+
+    // Assert that Morticia kept the "manager" role, lost the "tester" role and
+    // gained the "editor" role.
+    $account = user_load_by_name('Morticia');
+    $this->assertTrue(isset($account->roles[$manager_rid]), 'Morticia still has the manager role.');
+    $this->assertTrue(isset($account->roles[$editor_rid]), 'Morticia has the editor role.');
+    $this->assertFalse(isset($account->roles[$tester_rid]), 'Morticia no longer has the tester role.');
+    $this->assertEqual(3, count($account->roles), 'Morticia has three roles.');
+
+    // Assert that all other imported users got the "manager" role as well.
+    $user_names = array(
+      'Fester',
+      'Gomez',
+      'Pugsley',
+    );
+    foreach ($user_names as $user_name) {
+      $vars = array(
+        '@user' => $user_name,
+      );
+      // Assert that this user has the "manager" role.
+      $account = user_load_by_name($user_name);
+      $this->assertTrue(isset($account->roles[$manager_rid]), format_string('@user has the manager role.', $vars));
+    }
+  }
 }
diff --git a/tests/feeds_tests.module b/tests/feeds_tests.module
index 79df5875d675f5be518f98370ec6680397164ca8..5688b6646584f1ede7198a526fff01f2020aa223 100644
--- a/tests/feeds_tests.module
+++ b/tests/feeds_tests.module
@@ -352,20 +352,35 @@ function feeds_tests_mapper_unique(FeedsSource $source, $entity_type, $bundle, $
 
 /**
  * Implements hook_feeds_after_parse().
- *
- * Empties the list of items to import in case the test says that there are
- * items in there with encoding issues. These items can not be processed during
- * tests without having a test failure because in < PHP 5.4 that would produce
- * the following warning:
- *   htmlspecialchars(): Invalid multibyte sequence in argument
- *
- * @see FeedsCSVParserTestCase::testMbstringExtensionDisabled()
  */
 function feeds_tests_feeds_after_parse(FeedsSource $source, FeedsParserResult $result) {
+  // Empties the list of items to import in case the test says that there are
+  // items in there with encoding issues. These items can not be processed
+  // during tests without having a test failure because in < PHP 5.4 that would
+  // produce the following warning:
+  //   htmlspecialchars(): Invalid multibyte sequence in argument
+  // @see FeedsCSVParserTestCase::testMbstringExtensionDisabled()
   if (variable_get('feeds_tests_feeds_after_parse_empty_items', FALSE)) {
     // Remove all items. No items will be processed.
     $result->items = array();
   }
+
+  if ($source->id == 'user_import') {
+    foreach ($result->items as &$item) {
+      if (!empty($item['roles']) && strpos($item['roles'], '|')) {
+        // Convert roles value to multiple values.
+        // @see FeedsCSVtoUsersTest::testRoleTargetWithoutRoleCreation()
+        // @see FeedsCSVtoUsersTest::testRoleTargetWithRoleCreation()
+        // @see FeedsCSVtoUsersTest::testRoleTargetWithAllowedRoles()
+        $item['roles'] = explode('|', $item['roles']);
+      }
+      if (!empty($item['rids']) && strpos($item['rids'], '|')) {
+        // Convert roles value to multiple values.
+        // @see FeedsCSVtoUsersTest::testRoleTargetRids()
+        $item['rids'] = explode('|', $item['rids']);
+      }
+    }
+  }
 }
 
 /**