From 8c13c21799beed76eea848504677eb935026397c Mon Sep 17 00:00:00 2001
From: Christian Kollmann <christian.kollmann@a-sit.at>
Date: Thu, 25 Feb 2021 11:18:44 +0100
Subject: Implement and test ReceiveAustrianResidenceGuiResponseTask

---
 .../modules/auth/eidas/v2/dao/RegisterResult.java  |  10 +-
 .../modules/auth/eidas/v2/dao/SimpleEidasData.java |   4 +
 .../eidas/v2/service/RegisterSearchService.java    |   7 +
 .../ReceiveAustrianResidenceGuiResponseTask.java   | 138 +++++++++------
 .../modules/auth/eidas/v2/zmr/DummyZmrClient.java  |   6 +
 .../modules/auth/eidas/v2/zmr/IZmrClient.java      |   3 +
 ...eceiveAustrianResidenceGuiResponseTaskTest.java | 196 +++++++++++++++++++++
 7 files changed, 310 insertions(+), 54 deletions(-)
 create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java

diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java
index 1cc36fe9..4674751d 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java
@@ -24,9 +24,15 @@
 package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao;
 
 import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;
-import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
 
-@Data
+@Getter
+@NoArgsConstructor
+@ToString
+@EqualsAndHashCode
 public class RegisterResult {
 
   // MDS
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java
index 84327941..f60a9906 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java
@@ -25,10 +25,14 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao;
 
 import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException;
 import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 
 @Data
+@AllArgsConstructor
+@NoArgsConstructor
 public class SimpleEidasData {
 
   private String citizenCountryCode;
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java
index 6a41893b..fad985c2 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java
@@ -11,6 +11,7 @@ import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
 import java.util.List;
 
 @Slf4j
@@ -38,6 +39,7 @@ public class RegisterSearchService {
   public String step7aKittProcess(MergedRegisterSearchResult initialSearchResult,
                                   MergedRegisterSearchResult specificDetailSearchResult,
                                   SimpleEidasData eidasData, IRequest pendingReq) throws TaskExecutionException {
+    // TODO verify with which data this method gets called
     try {
       if (initialSearchResult.getResultCount() != 0) {
         throw new WorkflowException("initialSearchResult.getResultCount() != 0");
@@ -107,4 +109,9 @@ public class RegisterSearchService {
     List<RegisterResult> resultsErnp = ernpClient.searchWithBpkZp(bpkZp);
     return new MergedRegisterSearchResult(resultsZmr, resultsErnp);
   }
+
+  public MergedRegisterSearchResult searchWithResidence(String zipcode, String city, String street) {
+    List<RegisterResult> resultsZmr = zmrClient.searchWithResidenceData(zipcode, city, street);
+    return new MergedRegisterSearchResult(resultsZmr, Collections.emptyList());
+  }
 }
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java
index 7dcf62ac..d565c329 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java
@@ -24,94 +24,128 @@
 package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;
 
 import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
 import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.InvalidUserInputException;
-import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient;
-import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService;
 import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
 import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
 import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
 import org.springframework.stereotype.Component;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.Enumeration;
 
+import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.DATA_INITIAL_REGISTER_RESULT;
+import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.DATA_SIMPLE_EIDAS;
+
 /**
  * Task receives the response of {@link GenerateAustrianResidenceGuiTask} and handles it.
+ * This corresponds to Steps 17B, 18, 19 in the eIDAS Matching Concept.
  *
  * @author amarsalek
+ * @author ckollmann
  */
 @Slf4j
 @Component("ReceiveAustrianResidenceGuiResponseTask")
 public class ReceiveAustrianResidenceGuiResponseTask extends AbstractAuthServletTask {
 
-  final String formerResidenceAvailableParameterName = "formerResidenceAvailable";
-  final String streetParameterName = "street";
-  final String zipCodeParameterName = "zipcode";
-  final String cityParameterName = "city";
-  private final IZmrClient zmrClient;
+  public static final String PARAM_FORMER_RESIDENCE_AVAILABLE = "formerResidenceAvailable";
+  public static final String PARAM_STREET = "street";
+  public static final String PARAM_CITY = "city";
+  public static final String PARAM_ZIPCODE = "zipcode";
+  private final RegisterSearchService registerSearchService;
+
+  public ReceiveAustrianResidenceGuiResponseTask(RegisterSearchService registerSearchService) {
+    this.registerSearchService = registerSearchService;
+  }
 
-  public ReceiveAustrianResidenceGuiResponseTask(IZmrClient zmrClient) {
-    this.zmrClient = zmrClient;
+  @Data
+  @AllArgsConstructor
+  @NoArgsConstructor
+  public static class UserInput {
+    private boolean formerResidenceAvailable;
+    private String zipcode;
+    private String city;
+    private String street;
   }
 
-  //TODO
   @Override
   public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
       throws TaskExecutionException {
-
     log.trace("Starting ReceiveAustrianResidenceGuiResponseTask");
-    // set parameter execution context
-    final Enumeration<String> reqParamNames = request.getParameterNames();
-    String street = null;
-    String city = null;
-    String zipcode = null;
-    Boolean formerResidenceAvailable = false;
-    while (reqParamNames.hasMoreElements()) {
-      final String paramName = reqParamNames.nextElement();
-      if (StringUtils.isNotEmpty(paramName)
-          && !EaafConstants.PROCESS_ENGINE_PENDINGREQUESTID.equalsIgnoreCase(paramName)
-          && formerResidenceAvailableParameterName.equalsIgnoreCase(paramName)) {
-        formerResidenceAvailable =
-            Boolean.parseBoolean(StringEscapeUtils.escapeHtml(request.getParameter(paramName)));
-      }
-      if (StringUtils.isNotEmpty(paramName)
-          && !EaafConstants.PROCESS_ENGINE_PENDINGREQUESTID.equalsIgnoreCase(paramName)
-          && streetParameterName.equalsIgnoreCase(paramName)) {
-        street = StringEscapeUtils.escapeHtml(request.getParameter(paramName));
-      }
-      if (StringUtils.isNotEmpty(paramName)
-          && !EaafConstants.PROCESS_ENGINE_PENDINGREQUESTID.equalsIgnoreCase(paramName)
-          && cityParameterName.equalsIgnoreCase(paramName)) {
-        city = StringEscapeUtils.escapeHtml(request.getParameter(paramName));
-      }
-      if (StringUtils.isNotEmpty(paramName)
-          && !EaafConstants.PROCESS_ENGINE_PENDINGREQUESTID.equalsIgnoreCase(paramName)
-          && zipCodeParameterName.equalsIgnoreCase(paramName)) {
-        zipcode = StringEscapeUtils.escapeHtml(request.getParameter(paramName));
-      }
-    }
-    if (formerResidenceAvailable) {
-      //step 18
-      if (street.isEmpty() || city.isEmpty() || zipcode.isEmpty()) {
-        //form should ensure that mandatory fields are field =>
-        //this can never happen, expect somebody manipulated the response
+    UserInput input = parseHtmlInput(request);
+    if (input.isFormerResidenceAvailable()) {
+      if (input.getStreet().isEmpty() || input.getCity().isEmpty() || input.getZipcode().isEmpty()) {
+        // form should ensure that mandatory fields are field => this should never happen
         throw new TaskExecutionException(pendingReq, "Invalid user input", new InvalidUserInputException());
       }
-      step18_RegisterSearch(street, city, zipcode);//TODO also MDS?
+      // TODO Also search with MDS?
+      MergedRegisterSearchResult result = registerSearchService
+          .searchWithResidence(input.zipcode, input.city, input.street);
+      if (result.getResultCount() == 0) {
+        moveToNextTask(executionContext);
+        return;
+      } else if (result.getResultCount() == 1) {
+        compareSearchResultWithInitialData(executionContext, result);
+      } else {
+        throw new TaskExecutionException(pendingReq, "Manual Fix necessary", new ManualFixNecessaryException("todo"));
+      }
     } else {
-      //step 20 or for now (phase 1) step 9
-      executionContext.put(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK, true);
+      moveToNextTask(executionContext);
     }
+  }
 
+  private void compareSearchResultWithInitialData(ExecutionContext executionContext, MergedRegisterSearchResult result)
+      throws TaskExecutionException {
+    try {
+      AuthProcessDataWrapper authProcessDataWrapper = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+      MergedRegisterSearchResult initialSearchResult = authProcessDataWrapper
+          .getGenericDataFromSession(DATA_INITIAL_REGISTER_RESULT, MergedRegisterSearchResult.class);
+      SimpleEidasData simpleEidasData = authProcessDataWrapper
+          .getGenericDataFromSession(DATA_SIMPLE_EIDAS, SimpleEidasData.class);
+      if (simpleEidasData.equalsRegisterData(result)) {
+        registerSearchService.step7aKittProcess(initialSearchResult, result, simpleEidasData, pendingReq);
+      } else {
+        moveToNextTask(executionContext);
+      }
+    } catch (WorkflowException e) {
+      throw new TaskExecutionException(pendingReq, "Search failed", new ManualFixNecessaryException("todo"));
+    }
+  }
 
+  private void moveToNextTask(ExecutionContext executionContext) {
+    // Later on, this should transition to Step 20
+    executionContext.put(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK, true);
   }
 
-  private void step18_RegisterSearch(String street, String city, String zipcode) {
-    System.out.println(street + city + zipcode + zmrClient);//TODO
+  private @NotNull UserInput parseHtmlInput(HttpServletRequest request) {
+    Enumeration<String> reqParamNames = request.getParameterNames();
+    UserInput result = new UserInput();
+    while (reqParamNames.hasMoreElements()) {
+      final String paramName = reqParamNames.nextElement();
+      String escaped = StringEscapeUtils.escapeHtml(request.getParameter(paramName));
+      if (PARAM_FORMER_RESIDENCE_AVAILABLE.equalsIgnoreCase(paramName)) {
+        result.setFormerResidenceAvailable(Boolean.parseBoolean(escaped));
+      } else if (PARAM_STREET.equalsIgnoreCase(paramName)) {
+        result.setStreet(escaped);
+      } else if (PARAM_CITY.equalsIgnoreCase(paramName)) {
+        result.setCity(escaped);
+      } else if (PARAM_ZIPCODE.equalsIgnoreCase(paramName)) {
+        result.setZipcode(escaped);
+      }
+    }
+    return result;
   }
 
 }
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java
index 87b00f07..80e61451 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java
@@ -68,4 +68,10 @@ public class DummyZmrClient implements IZmrClient {
     return Collections.emptyList();
   }
 
+  @Override
+  public List<RegisterResult> searchWithResidenceData(String zipcode, String city, String street) {
+    // TODO
+    return Collections.emptyList();
+  }
+
 }
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java
index 2742ae31..5ca69d3d 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java
@@ -42,4 +42,7 @@ public interface IZmrClient {
   void update(RegisterResult registerResult, SimpleEidasData eidData);
 
   List<RegisterResult> searchWithBpkZp(String bpkzp);
+
+  List<RegisterResult> searchWithResidenceData(String zipcode, String city, String street);
+
 }
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java
new file mode 100644
index 00000000..38693f49
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java
@@ -0,0 +1,196 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks;
+
+import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.util.Collections;
+import java.util.List;
+
+import static at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask.*;
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.springframework.util.Assert.isInstanceOf;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+    "/SpringTest-context_tasks_test.xml",
+    "/SpringTest-context_basic_mapConfig.xml"
+})
+public class ReceiveAustrianResidenceGuiResponseTaskTest {
+
+  @Autowired
+  protected MsConnectorDummyConfigMap authConfig;
+  @Autowired
+  private ReceiveAustrianResidenceGuiResponseTask task;
+  @MockBean
+  private RegisterSearchService registerSearchService;
+
+  private final ExecutionContext executionContext = new ExecutionContextImpl();
+  private MockHttpServletRequest httpReq;
+  private MockHttpServletResponse httpResp;
+  private TestRequestImpl pendingReq;
+
+  /**
+   * jUnit test set-up.
+   *
+   * @throws Exception In case of an set-up error
+   */
+  @Before
+  public void setUp() throws Exception {
+    MockitoAnnotations.initMocks(this);
+
+    httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector");
+    httpResp = new MockHttpServletResponse();
+    RequestContextHolder.resetRequestAttributes();
+    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+    pendingReq = new TestRequestImpl();
+    pendingReq.setAuthUrl("https://localhost/ms_connector");
+    pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10));
+
+    LocaleContextHolder.resetLocaleContext();
+  }
+
+  @Test
+  public void noRegisterResult() throws Exception {
+    UserInput userInput = setupUserInput();
+    SimpleEidasData eidasData = setupEidasData();
+    MergedRegisterSearchResult registerSearchResult = buildEmptyResult();
+    mockRegisterSearch(userInput, registerSearchResult);
+
+    task.execute(pendingReq, executionContext);
+
+    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK));
+  }
+
+  @Test
+  public void exactlyOneRegisterResult_Matching() throws Exception {
+    UserInput userInput = setupUserInput();
+    SimpleEidasData eidasData = setupEidasData();
+    MergedRegisterSearchResult registerSearchResult = buildResultWithOneMatch(buildMatchingRegisterResult(eidasData));
+    mockRegisterSearch(userInput, registerSearchResult);
+
+    task.execute(pendingReq, executionContext);
+
+    assertNull("Transition To S9", executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK));
+    Mockito.verify(registerSearchService).step7aKittProcess(any(), eq(registerSearchResult), eq(eidasData), eq(pendingReq));
+  }
+
+  @Test
+  public void exactlyOneRegisterResult_NotMatching() throws Exception {
+    UserInput userInput = setupUserInput();
+    SimpleEidasData eidasData = setupEidasData();
+    MergedRegisterSearchResult registerSearchResult = buildResultWithOneMatch(buildNotMatchingRegisterResult(eidasData));
+    mockRegisterSearch(userInput, registerSearchResult);
+
+    task.execute(pendingReq, executionContext);
+
+    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK));
+  }
+
+  @Test
+  public void moreThanOneRegisterResult() throws Exception {
+    UserInput userInput = setupUserInput();
+    SimpleEidasData eidasData = setupEidasData();
+    MergedRegisterSearchResult registerSearchResult = buildResultWithTwoMatches();
+    mockRegisterSearch(userInput, registerSearchResult);
+
+    TaskExecutionException e = assertThrows(TaskExecutionException.class,
+        () -> task.execute(pendingReq, executionContext));
+
+    assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+    isInstanceOf(ManualFixNecessaryException.class, e.getOriginalException());
+    assertNull("Transition To S16", executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK));
+  }
+
+  private void mockRegisterSearch(UserInput userInput, MergedRegisterSearchResult registerSearchResult) {
+    Mockito.when(registerSearchService.searchWithResidence(eq(userInput.getZipcode()), eq(userInput.getCity()), eq(userInput.getStreet()))).thenReturn(registerSearchResult);
+  }
+
+  @NotNull
+  private MergedRegisterSearchResult buildEmptyResult() {
+    return new MergedRegisterSearchResult(Collections.emptyList(), Collections.emptyList());
+  }
+
+  @NotNull
+  private MergedRegisterSearchResult buildResultWithOneMatch(RegisterResult registerResult) {
+    return new MergedRegisterSearchResult(Collections.singletonList(registerResult), Collections.emptyList());
+  }
+
+  @NotNull
+  private MergedRegisterSearchResult buildResultWithTwoMatches() {
+    List<RegisterResult> results = Lists.newArrayList(buildRandomRegisterResult(), buildRandomRegisterResult());
+    return new MergedRegisterSearchResult(results, Collections.emptyList());
+  }
+
+  @NotNull
+  private RegisterResult buildRandomRegisterResult() {
+    return new RegisterResult(RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8));
+  }
+
+  private RegisterResult buildMatchingRegisterResult(SimpleEidasData eidData) {
+    return new RegisterResult(RandomStringUtils.randomAlphabetic(8), eidData.getPseudonym(), eidData.getGivenName(), eidData.getFamilyName(), eidData.getDateOfBirth());
+  }
+
+  private RegisterResult buildNotMatchingRegisterResult(SimpleEidasData eidData) {
+    return new RegisterResult(RandomStringUtils.randomAlphabetic(8), eidData.getPseudonym() + RandomStringUtils.randomAlphabetic(8), eidData.getGivenName(), eidData.getFamilyName(), eidData.getDateOfBirth());
+  }
+
+  private void setHttpParameters(UserInput input) {
+    httpReq.setParameter(PARAM_FORMER_RESIDENCE_AVAILABLE, String.valueOf(input.isFormerResidenceAvailable()));
+    httpReq.setParameter(PARAM_STREET, input.getStreet());
+    httpReq.setParameter(PARAM_CITY, input.getCity());
+    httpReq.setParameter(PARAM_ZIPCODE, input.getZipcode());
+  }
+
+  @NotNull
+  private SimpleEidasData setupEidasData() throws EaafStorageException {
+    SimpleEidasData result = new SimpleEidasData();
+    result.setPseudonym(RandomStringUtils.randomAlphabetic(8));
+    result.setFamilyName(RandomStringUtils.randomAlphabetic(8));
+    result.setGivenName(RandomStringUtils.randomAlphabetic(8));
+    result.setDateOfBirth("1970-01-01");
+    AuthProcessDataWrapper authProcessDataWrapper = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+    authProcessDataWrapper.setGenericDataToSession(Constants.DATA_SIMPLE_EIDAS, result);
+    return result;
+  }
+
+  @NotNull
+  private UserInput setupUserInput() {
+    UserInput result = new UserInput(true, RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8));
+    setHttpParameters(result);
+    return result;
+  }
+
+
+}
-- 
cgit v1.2.3