From 261cb359cfa5a126ef6ed7c7207edd45c28d2a1e Mon Sep 17 00:00:00 2001 From: Morphyum Date: Tue, 15 Feb 2022 11:51:07 +0100 Subject: [PATCH 1/5] * added /pocnat endpoints and converted results for /app --- .../testresult/TestResultController.java | 78 +++++++++++++++++-- .../testresult/entity/TestResultEntity.java | 3 +- .../testresult/model/PoCNATResult.java | 74 ++++++++++++++++++ .../testresult/model/PoCNATResultList.java | 66 ++++++++++++++++ .../coronawarn/testresult/model/TestType.java | 7 ++ .../testresult/service/TestResultService.java | 42 +++++++++- .../testresult/TestResultServiceTest.java | 9 ++- 7 files changed, 262 insertions(+), 17 deletions(-) create mode 100644 src/main/java/app/coronawarn/testresult/model/PoCNATResult.java create mode 100644 src/main/java/app/coronawarn/testresult/model/PoCNATResultList.java create mode 100644 src/main/java/app/coronawarn/testresult/model/TestType.java diff --git a/src/main/java/app/coronawarn/testresult/TestResultController.java b/src/main/java/app/coronawarn/testresult/TestResultController.java index 0448ed7..def7452 100644 --- a/src/main/java/app/coronawarn/testresult/TestResultController.java +++ b/src/main/java/app/coronawarn/testresult/TestResultController.java @@ -21,11 +21,7 @@ package app.coronawarn.testresult; -import app.coronawarn.testresult.model.QuickTestResultList; -import app.coronawarn.testresult.model.TestResult; -import app.coronawarn.testresult.model.TestResultList; -import app.coronawarn.testresult.model.TestResultRequest; -import app.coronawarn.testresult.model.TestResultResponse; +import app.coronawarn.testresult.model.*; import app.coronawarn.testresult.service.TestResultService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -79,10 +75,10 @@ public ResponseEntity result( ) { log.info("Received test result request from app."); - TestResult result = testResultService.getOrCreate(request.getId(), false, null); + TestResult result = testResultService.getOrCreate(request.getId(), TestType.PCR, null); return ResponseEntity.ok(new TestResultResponse() .setLabId(result.getLabId()) - .setTestResult(result.getResult(), result.getSc()) + .setTestResult(testResultService.conversionCheck(result.getResult()), result.getSc()) ); } @@ -146,7 +142,7 @@ public ResponseEntity quickTestResult( @org.springframework.web.bind.annotation.RequestBody @Valid TestResultRequest request ) { log.info("Received test result request from Quicktest."); - TestResult result = testResultService.getOrCreate(request.getId(), true, request.getSc()); + TestResult result = testResultService.getOrCreate(request.getId(), TestType.QUICKTEST, request.getSc()); return ResponseEntity.ok(new TestResultResponse() .setLabId(result.getLabId()) .setTestResult(result.getResult())); @@ -185,4 +181,70 @@ public ResponseEntity quicktestResults( return ResponseEntity.noContent().build(); } + + /** + * Get the test result response from a request containing the id. + * + * @param request the test result request with id + * @return the test result response + */ + @Operation( + description = "The result and the sc (sample collection) timestamp of a PoC-NAT can be set.", + summary = "Set the testresult for a PoC-NAT.", + requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = TestResultRequest.class))), + responses = { + @ApiResponse( + responseCode = "200", + description = "Ok, PoC-NAT result inserted successfully." + ) + } + ) + @PostMapping( + value = "/api/v1/pocnat/result", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE + ) + public ResponseEntity pocnatResult( + @org.springframework.web.bind.annotation.RequestBody @Valid TestResultRequest request + ) { + log.info("Received test result request from PoC-NAT."); + TestResult result = testResultService.getOrCreate(request.getId(), TestType.POCNAT, request.getSc()); + return ResponseEntity.ok(new TestResultResponse() + .setLabId(result.getLabId()) + .setTestResult(result.getResult())); + } + + /** + * Insert or update the PoC-NAT. + * + * @param list the test result list request + * @return the response + */ + @Operation( + description = "The result and the sc (sample collection) timestamp of a PoC-NAT can be set.", + summary = "Set multiple testresults for a PoC-NAT as an array.", + requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = TestResultRequest.class))), + responses = { + @ApiResponse( + responseCode = "204", + description = "No content, PoC-NAT result(s) inserted successfully." + ) + } + ) + @PostMapping( + value = "/api/v1/pocnat/results", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE + ) + public ResponseEntity pocnatResults( + @org.springframework.web.bind.annotation.RequestBody @NotNull @Valid PoCNATResultList list + ) { + log.info("Received {} test result to insert or update from PoC-NATs. ", list.getTestResults().size()); + + list.getTestResults().stream() + .map(tr -> testResultService.convertPoCNAT(tr, list.getLabId())) + .forEach(testResultService::createOrUpdate); + + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/app/coronawarn/testresult/entity/TestResultEntity.java b/src/main/java/app/coronawarn/testresult/entity/TestResultEntity.java index 2cb45aa..219aec2 100644 --- a/src/main/java/app/coronawarn/testresult/entity/TestResultEntity.java +++ b/src/main/java/app/coronawarn/testresult/entity/TestResultEntity.java @@ -93,6 +93,7 @@ public TestResultEntity setLabId(String labId) { public enum Result { PENDING, NEGATIVE, POSITIVE, INVALID, REDEEMED, - QUICK_PENDING, QUICK_NEGATIVE, QUICK_POSITIVE, QUICK_INVALID, QUICK_REDEEMED + QUICK_PENDING, QUICK_NEGATIVE, QUICK_POSITIVE, QUICK_INVALID, QUICK_REDEEMED, + POCNAT_PENDING, POCNAT_NEGATIVE, POCNAT_POSITIVE, POCNAT_INVALID, POCNAT_REDEEMED } } diff --git a/src/main/java/app/coronawarn/testresult/model/PoCNATResult.java b/src/main/java/app/coronawarn/testresult/model/PoCNATResult.java new file mode 100644 index 0000000..a1366c8 --- /dev/null +++ b/src/main/java/app/coronawarn/testresult/model/PoCNATResult.java @@ -0,0 +1,74 @@ +/* + * Corona-Warn-App / cwa-testresult-server + * + * (C) 2020, T-Systems International GmbH + * + * Deutsche Telekom AG and all other contributors / + * copyright owners license this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package app.coronawarn.testresult.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.*; + +/** + * Model of the test result. + */ +@Schema( + description = "The PoC-NAT result model." +) +@Getter +@Setter +@ToString +@EqualsAndHashCode +@Accessors(chain = true) +public class PoCNATResult { + + /** + * Hash (SHA256) of test result id (aka QR-Code, GUID) encoded as hex string. + */ + @NotBlank + @Pattern(regexp = "^[XxA-Fa-f0-9]([A-Fa-f0-9]{63})$") + @Schema(description = "the testId (Hashed GUID") + private String id; + + /** + * The test result. + * 10: PoC-NAT-Pending + * 11: PoC-NAT-Negative + * 12: PoC-NAT-Positive + * 13: PoC-NAT-Invalid + * 14: PoC-NAT-Redeemed + */ + @Min(10) + @Max(14) + @NotNull + @Schema(description = "the result of the PoC-NAT", required = true) + private Integer result; + + /** + * Timestamp of the SampleCollection (sc). + */ + @Schema(description = "the timestamp of the sample collection (sc) in unix epoch format. If not set," + + " the time of insertion will be used instead") + private Long sc; +} diff --git a/src/main/java/app/coronawarn/testresult/model/PoCNATResultList.java b/src/main/java/app/coronawarn/testresult/model/PoCNATResultList.java new file mode 100644 index 0000000..3bc286b --- /dev/null +++ b/src/main/java/app/coronawarn/testresult/model/PoCNATResultList.java @@ -0,0 +1,66 @@ +/* + * Corona-Warn-App / cwa-testresult-server + * + * (C) 2020, T-Systems International GmbH + * + * Deutsche Telekom AG and all other contributors / + * copyright owners license this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package app.coronawarn.testresult.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * Model of the test result list. + */ +@Schema( + description = "The PoC-NAT result list model." +) +@Getter +@Setter +@ToString +@EqualsAndHashCode +@Accessors(chain = true) +public class PoCNATResultList { + + /** + * The test result entries. + */ + @NotNull + @NotEmpty + @Schema(description = "array of PoC-NAT results", required = true) + private List<@Valid PoCNATResult> testResults; + + /** + * The labId of the uploader. + */ + @Schema(description = "The id that identifies a lab. Every lab can choose its own labid, " + + "but it must be unique over all labs, should be generated once via cryptographic hash function", + required = true, maxLength = 64) + @JsonInclude(JsonInclude.Include.NON_NULL) + private String labId; +} diff --git a/src/main/java/app/coronawarn/testresult/model/TestType.java b/src/main/java/app/coronawarn/testresult/model/TestType.java new file mode 100644 index 0000000..165ec2b --- /dev/null +++ b/src/main/java/app/coronawarn/testresult/model/TestType.java @@ -0,0 +1,7 @@ +package app.coronawarn.testresult.model; + +public enum TestType { + PCR, + QUICKTEST, + POCNAT +} diff --git a/src/main/java/app/coronawarn/testresult/service/TestResultService.java b/src/main/java/app/coronawarn/testresult/service/TestResultService.java index 9c9def2..ed2a8fb 100644 --- a/src/main/java/app/coronawarn/testresult/service/TestResultService.java +++ b/src/main/java/app/coronawarn/testresult/service/TestResultService.java @@ -24,12 +24,16 @@ import app.coronawarn.testresult.TestResultRepository; import app.coronawarn.testresult.entity.TestResultEntity; import app.coronawarn.testresult.exception.TestResultException; +import app.coronawarn.testresult.model.PoCNATResult; import app.coronawarn.testresult.model.QuickTestResult; import app.coronawarn.testresult.model.TestResult; + import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Optional; + +import app.coronawarn.testresult.model.TestType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; @@ -97,7 +101,7 @@ public TestResult createOrUpdate(final TestResult result) { LocalDateTime sc = LocalDateTime.now(); if (result.getSc() != null) { log.warn("Set Sc for Lab {}", result.getLabId()); - sc = LocalDateTime.ofEpochSecond(result.getSc(),0, ZoneOffset.UTC); + sc = LocalDateTime.ofEpochSecond(result.getSc(), 0, ZoneOffset.UTC); } entity.setResult(result.getResult()) .setResultDate(sc); @@ -118,15 +122,18 @@ public TestResult createOrUpdate(final TestResult result) { * @param id the test result id * @return the test result */ - public TestResult getOrCreate(final String id, boolean quicktest, Long sc) { + public TestResult getOrCreate(final String id, TestType testtype, Long sc) { try { TestResultEntity entity = testResultRepository.findByResultId(id) .orElseGet(() -> { log.info("Get failed now creating test result in database."); TestResultEntity resultEntity = new TestResultEntity(); - if (quicktest) { + if (testtype == TestType.QUICKTEST) { resultEntity.setResult(TestResultEntity.Result.QUICK_PENDING.ordinal()); resultEntity.setResultId(DigestUtils.sha256Hex(id)); + } else if (testtype == TestType.POCNAT) { + resultEntity.setResult(TestResultEntity.Result.POCNAT_PENDING.ordinal()); + resultEntity.setResultId(id); } else { resultEntity.setResult(TestResultEntity.Result.PENDING.ordinal()); resultEntity.setResultId(id); @@ -134,7 +141,7 @@ public TestResult getOrCreate(final String id, boolean quicktest, Long sc) { if (sc == null) { log.info("Set Sc during get or create"); resultEntity.setResultDate(LocalDateTime.now()); - } else { + } else { resultEntity.setResultDate(LocalDateTime.ofEpochSecond(sc, 0, ZoneOffset.UTC)); } return testResultRepository.save(resultEntity); @@ -162,4 +169,31 @@ public TestResult convertQuickTest(QuickTestResult quickTestResult, String labId return testResult; } + /** + * Converting a PoCNATResult to Testresult for saving. + * + * @param pocnatResult the Result to convert + * @return the converted test result + */ + public TestResult convertPoCNAT(PoCNATResult pocnatResult, String labId) { + TestResult testResult = new TestResult(); + testResult.setResult(pocnatResult.getResult()); + testResult.setLabId(labId); + testResult.setId(DigestUtils.sha256Hex(pocnatResult.getId())); + testResult.setSc(pocnatResult.getSc()); + return testResult; + } + + /** + * Checks and converts PoC-NAT results to PCR results for REST reponse + * + * @param result the Result to check and possibly convert + * @return either the original result or the converted result + */ + public Integer conversionCheck(Integer result) { + if (result >= 10 && result <= 14) { + result -= 10; + } + return result; + } } diff --git a/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java b/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java index c83d9c7..5b213e8 100644 --- a/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java +++ b/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java @@ -23,6 +23,7 @@ import app.coronawarn.testresult.entity.TestResultEntity; import app.coronawarn.testresult.model.TestResult; +import app.coronawarn.testresult.model.TestType; import app.coronawarn.testresult.service.TestResultService; import org.junit.Assert; import org.junit.Before; @@ -90,7 +91,7 @@ public void insertOrUpdate() { Assert.assertEquals(result, create.getResult()); Assert.assertEquals(labId, create.getLabId()); // get - TestResult get = testResultService.getOrCreate(id, false, 0L); + TestResult get = testResultService.getOrCreate(id, TestType.PCR, 0L); Assert.assertNotNull(get); Assert.assertEquals(result, get.getResult()); Assert.assertEquals(labId, get.getLabId()); @@ -113,7 +114,7 @@ public void insertAndUpdate() { Assert.assertEquals(resultCreate, create.getResult()); Assert.assertEquals(labId, create.getLabId()); // get - TestResult get = testResultService.getOrCreate(id, false, 0L); + TestResult get = testResultService.getOrCreate(id, TestType.PCR, 0L); Assert.assertNotNull(get); Assert.assertEquals(resultCreate, get.getResult()); Assert.assertEquals(labId, get.getLabId()); @@ -127,7 +128,7 @@ public void insertAndUpdate() { Assert.assertEquals(resultUpdate, update.getResult()); Assert.assertEquals(labId, update.getLabId()); // get - get = testResultService.getOrCreate(id, false, 0L); + get = testResultService.getOrCreate(id, TestType.PCR, 0L); Assert.assertNotNull(get); Assert.assertEquals(resultUpdate, get.getResult()); Assert.assertEquals(labId, get.getLabId()); @@ -139,7 +140,7 @@ public void getOrCreate() { String id = "a".repeat(64); Integer result = 0; // get - TestResult get = testResultService.getOrCreate(id, false, 0L); + TestResult get = testResultService.getOrCreate(id, TestType.PCR, 0L); Assert.assertNotNull(get); Assert.assertEquals(result, get.getResult()); Assert.assertNull(get.getLabId()); From d131a91574869f790eda4f9e64eccf598420d570 Mon Sep 17 00:00:00 2001 From: Morphyum Date: Tue, 15 Feb 2022 11:57:14 +0100 Subject: [PATCH 2/5] * fixed checkstyle --- .../coronawarn/testresult/TestResultController.java | 12 +++++++++--- .../model/{PoCNATResult.java => PocNatResult.java} | 9 ++++++--- ...{PoCNATResultList.java => PocNatResultList.java} | 13 +++++++------ .../testresult/service/TestResultService.java | 10 ++++------ 4 files changed, 26 insertions(+), 18 deletions(-) rename src/main/java/app/coronawarn/testresult/model/{PoCNATResult.java => PocNatResult.java} (88%) rename src/main/java/app/coronawarn/testresult/model/{PoCNATResultList.java => PocNatResultList.java} (95%) diff --git a/src/main/java/app/coronawarn/testresult/TestResultController.java b/src/main/java/app/coronawarn/testresult/TestResultController.java index def7452..7c32d9f 100644 --- a/src/main/java/app/coronawarn/testresult/TestResultController.java +++ b/src/main/java/app/coronawarn/testresult/TestResultController.java @@ -21,7 +21,13 @@ package app.coronawarn.testresult; -import app.coronawarn.testresult.model.*; +import app.coronawarn.testresult.model.PocNatResultList; +import app.coronawarn.testresult.model.QuickTestResultList; +import app.coronawarn.testresult.model.TestResult; +import app.coronawarn.testresult.model.TestResultList; +import app.coronawarn.testresult.model.TestResultRequest; +import app.coronawarn.testresult.model.TestResultResponse; +import app.coronawarn.testresult.model.TestType; import app.coronawarn.testresult.service.TestResultService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -237,12 +243,12 @@ public ResponseEntity pocnatResult( produces = MediaType.APPLICATION_JSON_VALUE ) public ResponseEntity pocnatResults( - @org.springframework.web.bind.annotation.RequestBody @NotNull @Valid PoCNATResultList list + @org.springframework.web.bind.annotation.RequestBody @NotNull @Valid PocNatResultList list ) { log.info("Received {} test result to insert or update from PoC-NATs. ", list.getTestResults().size()); list.getTestResults().stream() - .map(tr -> testResultService.convertPoCNAT(tr, list.getLabId())) + .map(tr -> testResultService.convertPocNat(tr, list.getLabId())) .forEach(testResultService::createOrUpdate); return ResponseEntity.noContent().build(); diff --git a/src/main/java/app/coronawarn/testresult/model/PoCNATResult.java b/src/main/java/app/coronawarn/testresult/model/PocNatResult.java similarity index 88% rename from src/main/java/app/coronawarn/testresult/model/PoCNATResult.java rename to src/main/java/app/coronawarn/testresult/model/PocNatResult.java index a1366c8..36988c8 100644 --- a/src/main/java/app/coronawarn/testresult/model/PoCNATResult.java +++ b/src/main/java/app/coronawarn/testresult/model/PocNatResult.java @@ -22,14 +22,17 @@ package app.coronawarn.testresult.model; import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; import lombok.experimental.Accessors; -import javax.validation.constraints.*; - /** * Model of the test result. */ @@ -41,7 +44,7 @@ @ToString @EqualsAndHashCode @Accessors(chain = true) -public class PoCNATResult { +public class PocNatResult { /** * Hash (SHA256) of test result id (aka QR-Code, GUID) encoded as hex string. diff --git a/src/main/java/app/coronawarn/testresult/model/PoCNATResultList.java b/src/main/java/app/coronawarn/testresult/model/PocNatResultList.java similarity index 95% rename from src/main/java/app/coronawarn/testresult/model/PoCNATResultList.java rename to src/main/java/app/coronawarn/testresult/model/PocNatResultList.java index 3bc286b..01de944 100644 --- a/src/main/java/app/coronawarn/testresult/model/PoCNATResultList.java +++ b/src/main/java/app/coronawarn/testresult/model/PocNatResultList.java @@ -23,16 +23,17 @@ import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; import lombok.experimental.Accessors; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.List; + /** * Model of the test result list. @@ -45,7 +46,7 @@ @ToString @EqualsAndHashCode @Accessors(chain = true) -public class PoCNATResultList { +public class PocNatResultList { /** * The test result entries. @@ -53,7 +54,7 @@ public class PoCNATResultList { @NotNull @NotEmpty @Schema(description = "array of PoC-NAT results", required = true) - private List<@Valid PoCNATResult> testResults; + private List<@Valid PocNatResult> testResults; /** * The labId of the uploader. diff --git a/src/main/java/app/coronawarn/testresult/service/TestResultService.java b/src/main/java/app/coronawarn/testresult/service/TestResultService.java index ed2a8fb..f9040d2 100644 --- a/src/main/java/app/coronawarn/testresult/service/TestResultService.java +++ b/src/main/java/app/coronawarn/testresult/service/TestResultService.java @@ -24,16 +24,14 @@ import app.coronawarn.testresult.TestResultRepository; import app.coronawarn.testresult.entity.TestResultEntity; import app.coronawarn.testresult.exception.TestResultException; -import app.coronawarn.testresult.model.PoCNATResult; +import app.coronawarn.testresult.model.PocNatResult; import app.coronawarn.testresult.model.QuickTestResult; import app.coronawarn.testresult.model.TestResult; - +import app.coronawarn.testresult.model.TestType; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Optional; - -import app.coronawarn.testresult.model.TestType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; @@ -175,7 +173,7 @@ public TestResult convertQuickTest(QuickTestResult quickTestResult, String labId * @param pocnatResult the Result to convert * @return the converted test result */ - public TestResult convertPoCNAT(PoCNATResult pocnatResult, String labId) { + public TestResult convertPocNat(PocNatResult pocnatResult, String labId) { TestResult testResult = new TestResult(); testResult.setResult(pocnatResult.getResult()); testResult.setLabId(labId); @@ -185,7 +183,7 @@ public TestResult convertPoCNAT(PoCNATResult pocnatResult, String labId) { } /** - * Checks and converts PoC-NAT results to PCR results for REST reponse + * Checks and converts PoC-NAT results to PCR results for REST reponse. * * @param result the Result to check and possibly convert * @return either the original result or the converted result From 38d0191e54f58414433b6c7b0583b70b372c2d5a Mon Sep 17 00:00:00 2001 From: Morphyum Date: Tue, 15 Feb 2022 12:20:09 +0100 Subject: [PATCH 3/5] * added tests for PoC-NAT --- .../testresult/TestResultControllerTest.java | 136 +++++++++++++++++- .../testresult/TestResultServiceTest.java | 23 +++ 2 files changed, 154 insertions(+), 5 deletions(-) diff --git a/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java b/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java index 8b43a47..46df313 100644 --- a/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java +++ b/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java @@ -24,11 +24,7 @@ import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import app.coronawarn.testresult.model.QuickTestResult; -import app.coronawarn.testresult.model.QuickTestResultList; -import app.coronawarn.testresult.model.TestResult; -import app.coronawarn.testresult.model.TestResultList; -import app.coronawarn.testresult.model.TestResultRequest; +import app.coronawarn.testresult.model.*; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Collections; import java.util.List; @@ -384,4 +380,134 @@ public void quickInsertInValidShouldReturnUnprocessableEntity() throws Exception .andExpect(MockMvcResultMatchers.status().isBadRequest()); } + @Test + public void pocnatInsertValidWithCsShouldReturnNoContent() throws Exception { + // data + String id = "b".repeat(64); + Integer result = 10; + // create + PocNatResultList valid = new PocNatResultList(); + valid.setTestResults(Collections.singletonList( + new PocNatResult().setId(id).setResult(result).setSc(System.currentTimeMillis()) + )); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/pocnat/results") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(valid))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isNoContent()); + } + + @Test + public void pocnatInsertValidWithDobHashAndWithCsShouldReturnNoContent() throws Exception { + // data + String id = "x" + "b".repeat(63); + Integer result = 10; + // create + PocNatResultList valid = new PocNatResultList(); + valid.setTestResults(Collections.singletonList( + new PocNatResult().setId(id).setResult(result).setSc(System.currentTimeMillis()) + )); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/pocnat/results") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(valid))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isNoContent()); + } + + @Test + public void pocnatInsertValidWithCsShouldReturnNoContentWithLabId() throws Exception { + // data + String id = "b".repeat(64); + String labId = "l".repeat(64); + Integer result = 10; + // create + PocNatResultList valid = new PocNatResultList(); + valid.setLabId(labId); + valid.setTestResults(Collections.singletonList( + new PocNatResult().setId(id).setResult(result).setSc(System.currentTimeMillis()) + )); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/pocnat/results") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(valid))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isNoContent()); + } + + @Test + public void pocnatInsertValidWithCsShouldReturnNoContentAndQueryResult() throws Exception { + // data + String id = "b".repeat(64); + Integer result = 10; + // create + PocNatResultList valid = new PocNatResultList(); + valid.setTestResults(Collections.singletonList( + new PocNatResult().setId(id).setResult(result).setSc(System.currentTimeMillis()) + )); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/pocnat/results") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(valid))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isNoContent()); + + TestResultRequest request = new TestResultRequest() + .setId(id); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/app/result") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(request))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + .getResponse() + .getContentAsString() + .contains("cs"); + } + + @Test + public void pocnatInsertValidShouldReturnNoContent() throws Exception { + // data + String id = "b".repeat(64); + Integer result = 10; + // create + PocNatResultList valid = new PocNatResultList(); + valid.setTestResults(Collections.singletonList( + new PocNatResult().setId(id).setResult(result) + )); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/pocnat/results") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(valid))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isNoContent()); + } + + @Test + public void pocnatInsertInValidShouldReturnUnprocessableEntity() throws Exception { + // data + String id = "b".repeat(64); + Integer result = 9; + // create + PocNatResultList valid = new PocNatResultList(); + valid.setTestResults(Collections.singletonList( + new PocNatResult().setId(id).setResult(result) + )); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/pocnat/results") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(valid))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + } diff --git a/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java b/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java index 5b213e8..3d30a3d 100644 --- a/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java +++ b/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java @@ -171,4 +171,27 @@ public void createAndDenyRedeemedUpdate() { Assert.assertNotNull(update); Assert.assertNotEquals(resultUpdate, update.getResult()); } + + @Test + public void conversionCheckIsPocNat() { + Assert.assertEquals(TestResultEntity.Result.PENDING.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.POCNAT_PENDING.ordinal())); + Assert.assertEquals(TestResultEntity.Result.REDEEMED.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.POCNAT_REDEEMED.ordinal())); + Assert.assertEquals(TestResultEntity.Result.INVALID.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.POCNAT_INVALID.ordinal())); + Assert.assertEquals(TestResultEntity.Result.NEGATIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.POCNAT_NEGATIVE.ordinal())); + Assert.assertEquals(TestResultEntity.Result.POSITIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.POCNAT_POSITIVE.ordinal())); + } + + @Test + public void conversionCheckNotPocNat() { + Assert.assertEquals(TestResultEntity.Result.PENDING.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.PENDING.ordinal())); + Assert.assertEquals(TestResultEntity.Result.REDEEMED.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.REDEEMED.ordinal())); + Assert.assertEquals(TestResultEntity.Result.INVALID.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.INVALID.ordinal())); + Assert.assertEquals(TestResultEntity.Result.NEGATIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.NEGATIVE.ordinal())); + Assert.assertEquals(TestResultEntity.Result.POSITIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.POSITIVE.ordinal())); + Assert.assertEquals(TestResultEntity.Result.QUICK_PENDING.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.QUICK_PENDING.ordinal())); + Assert.assertEquals(TestResultEntity.Result.QUICK_REDEEMED.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.QUICK_REDEEMED.ordinal())); + Assert.assertEquals(TestResultEntity.Result.QUICK_INVALID.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.QUICK_INVALID.ordinal())); + Assert.assertEquals(TestResultEntity.Result.QUICK_NEGATIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.QUICK_NEGATIVE.ordinal())); + Assert.assertEquals(TestResultEntity.Result.QUICK_POSITIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.QUICK_POSITIVE.ordinal())); + } } From 0cc4e26a2a5893296290291fa1fd30d424add09d Mon Sep 17 00:00:00 2001 From: Morphyum Date: Wed, 16 Feb 2022 09:07:54 +0100 Subject: [PATCH 4/5] * added test coverage --- .../testresult/TestResultControllerTest.java | 28 +++++++++++ .../testresult/TestResultServiceTest.java | 49 ++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java b/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java index 46df313..ef7840d 100644 --- a/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java +++ b/src/test/java/app/coronawarn/testresult/TestResultControllerTest.java @@ -340,6 +340,20 @@ public void quickInsertValidWithCsShouldReturnNoContentAndQueryResult() throws E .getResponse() .getContentAsString() .contains("cs"); + + request = new TestResultRequest() + .setId(id); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/quicktest/result") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(request))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + .getResponse() + .getContentAsString() + .contains("cs"); } @Test @@ -470,6 +484,20 @@ public void pocnatInsertValidWithCsShouldReturnNoContentAndQueryResult() throws .getResponse() .getContentAsString() .contains("cs"); + + request = new TestResultRequest() + .setId(id); + mockMvc.perform(MockMvcRequestBuilders + .post("/api/v1/pocnat/result") + .accept(MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(request))) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + .getResponse() + .getContentAsString() + .contains("cs"); } @Test diff --git a/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java b/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java index 3d30a3d..9cad19c 100644 --- a/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java +++ b/src/test/java/app/coronawarn/testresult/TestResultServiceTest.java @@ -22,6 +22,8 @@ package app.coronawarn.testresult; import app.coronawarn.testresult.entity.TestResultEntity; +import app.coronawarn.testresult.model.PocNatResult; +import app.coronawarn.testresult.model.QuickTestResult; import app.coronawarn.testresult.model.TestResult; import app.coronawarn.testresult.model.TestType; import app.coronawarn.testresult.service.TestResultService; @@ -35,6 +37,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; +import java.time.Instant; + @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc @@ -122,7 +126,8 @@ public void insertAndUpdate() { TestResult update = new TestResult() .setId(id) .setResult(resultUpdate) - .setLabId(labId); + .setLabId(labId) + .setSc(Instant.now().getEpochSecond()); update = testResultService.createOrUpdate(update); Assert.assertNotNull(update); Assert.assertEquals(resultUpdate, update.getResult()); @@ -144,6 +149,20 @@ public void getOrCreate() { Assert.assertNotNull(get); Assert.assertEquals(result, get.getResult()); Assert.assertNull(get.getLabId()); + + id = "b".repeat(64); + result = 5; + get = testResultService.getOrCreate(id, TestType.QUICKTEST, null); + Assert.assertNotNull(get); + Assert.assertEquals(result, get.getResult()); + Assert.assertNull(get.getLabId()); + + id = "c".repeat(64); + result = 10; + get = testResultService.getOrCreate(id, TestType.POCNAT, 0L); + Assert.assertNotNull(get); + Assert.assertEquals(result, get.getResult()); + Assert.assertNull(get.getLabId()); } @Test @@ -194,4 +213,32 @@ public void conversionCheckNotPocNat() { Assert.assertEquals(TestResultEntity.Result.QUICK_NEGATIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.QUICK_NEGATIVE.ordinal())); Assert.assertEquals(TestResultEntity.Result.QUICK_POSITIVE.ordinal(), (int) testResultService.conversionCheck(TestResultEntity.Result.QUICK_POSITIVE.ordinal())); } + + @Test + public void convertQuickTest() { + String id = "b".repeat(64); + QuickTestResult quicktest = new QuickTestResult(); + quicktest.setResult(5); + quicktest.setId(id); + quicktest.setSc(Instant.now().getEpochSecond()); + TestResult result = testResultService.convertQuickTest(quicktest,"TestId"); + + Assert.assertEquals(quicktest.getResult(), result.getResult()); + Assert.assertEquals(quicktest.getSc(), result.getSc()); + Assert.assertNotEquals(quicktest.getId(), result.getId()); + } + + @Test + public void convertPocNat() { + String id = "b".repeat(64); + PocNatResult pocnat = new PocNatResult(); + pocnat.setResult(5); + pocnat.setId(id); + pocnat.setSc(Instant.now().getEpochSecond()); + TestResult result = testResultService.convertPocNat(pocnat,"TestId"); + + Assert.assertEquals(pocnat.getResult(), result.getResult()); + Assert.assertEquals(pocnat.getSc(), result.getSc()); + Assert.assertNotEquals(pocnat.getId(), result.getId()); + } } From ac4d70e3506ee325a3e4dbf7c249a8b41df6be85 Mon Sep 17 00:00:00 2001 From: Morphyum Date: Wed, 16 Feb 2022 09:23:56 +0100 Subject: [PATCH 5/5] * removed some code smells --- .../app/coronawarn/testresult/TestResultController.java | 6 +++--- .../testresult/exception/TestResultExceptionHandler.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/app/coronawarn/testresult/TestResultController.java b/src/main/java/app/coronawarn/testresult/TestResultController.java index 7c32d9f..8335407 100644 --- a/src/main/java/app/coronawarn/testresult/TestResultController.java +++ b/src/main/java/app/coronawarn/testresult/TestResultController.java @@ -110,7 +110,7 @@ public ResponseEntity result( consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE ) - public ResponseEntity results( + public ResponseEntity results( @org.springframework.web.bind.annotation.RequestBody @NotNull @Valid TestResultList list ) { log.info("Received {} test results to insert or update from lab.", list.getTestResults().size()); @@ -176,7 +176,7 @@ public ResponseEntity quickTestResult( consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE ) - public ResponseEntity quicktestResults( + public ResponseEntity quicktestResults( @org.springframework.web.bind.annotation.RequestBody @NotNull @Valid QuickTestResultList list ) { log.info("Received {} test result to insert or update from Quicktests. ", list.getTestResults().size()); @@ -242,7 +242,7 @@ public ResponseEntity pocnatResult( consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE ) - public ResponseEntity pocnatResults( + public ResponseEntity pocnatResults( @org.springframework.web.bind.annotation.RequestBody @NotNull @Valid PocNatResultList list ) { log.info("Received {} test result to insert or update from PoC-NATs. ", list.getTestResults().size()); diff --git a/src/main/java/app/coronawarn/testresult/exception/TestResultExceptionHandler.java b/src/main/java/app/coronawarn/testresult/exception/TestResultExceptionHandler.java index 0fb7c63..ee9804c 100644 --- a/src/main/java/app/coronawarn/testresult/exception/TestResultExceptionHandler.java +++ b/src/main/java/app/coronawarn/testresult/exception/TestResultExceptionHandler.java @@ -41,13 +41,13 @@ public class TestResultExceptionHandler { MethodArgumentNotValidException.class, ConstraintViolationException.class }) - public ResponseEntity handleValidationExceptions() { + public ResponseEntity handleValidationExceptions() { log.warn("Request contains invalid arguments or constraint violations in body."); return ResponseEntity.badRequest().build(); } @ExceptionHandler(TestResultException.class) - public ResponseEntity handleTestResultExceptions( + public ResponseEntity handleTestResultExceptions( TestResultException exception ) { log.warn("Request produced a test result exception with status {}.", exception.getStatus());