From 118ffdbb7204c42d8a501276f36ec10f8f108c11 Mon Sep 17 00:00:00 2001 From: HMS17 Date: Tue, 29 Sep 2026 10:14:09 -0400 Subject: [PATCH 1/3] [BI-3032] - Prevent .vcf file name duplication --- .../geno/impl/GigwaGenotypeServiceImpl.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java b/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java index a6dc67a4b..7c2ba98b0 100644 --- a/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java +++ b/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java @@ -224,6 +224,21 @@ public ImportResponse submitGenotypeData(UUID userId, UUID programId, UUID submi progress.setId(upload.getImporterProgressId()); upload.setProgress(progress); + //Query all filenames to avoid duplicate file uploads + String fileName = uploadedFile.getFilename(); + List existingImports = getGenotypeImports(programId); + for (GenotypeImportDetails existingImport : existingImports) { + if (existingImport.getGenotypingFileName().equals(fileName)){ + ImportResponse response = new ImportResponse(); + upload.getProgress().setStatuscode((short)HttpStatus.BAD_REQUEST.getCode()); + upload.getProgress().setMessage(String.format("Import cannot proceed. File name '%s' already exists in the database.", fileName)); + importDAO.updateProgress(upload.getProgress()); + response.setImportId(upload.getId()); + response.setProgress(progress); + return response; + } + } + String gigwaAuthToken; try { gigwaAuthToken = getAuthToken(); From 04e15d1be903af013be691952bf074475673a617 Mon Sep 17 00:00:00 2001 From: HMS17 Date: Wed, 30 Sep 2026 01:55:49 -0400 Subject: [PATCH 2/3] [BI-3032] - Unit test --- ...gwaGenotypeServiceImplIntegrationTest.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java b/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java index e0cf269ac..72c93f4e7 100644 --- a/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java +++ b/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java @@ -561,6 +561,35 @@ public void testSubmitInvalidHeader() throws ApiException { assertEquals("Header row is not valid VCF format", response.getProgress().getMessage()); } + @Test + public void testSubmitSameFileName() throws ApiException { + UUID programId = UUID.fromString("29162e85-e739-4f19-9fd0-0c377ed59956"); + String programKey = "TESTSUBMITDUPNAME"; + UUID submissionId = UUID.randomUUID(); + setupMocksForSubmitGenoData(programId, submissionId, Collections.emptyList()); + + //First import should succeed + AtomicReference importResponse = new AtomicReference<>(); + assertTimeout(Duration.of(2, ChronoUnit.MINUTES), () -> importResponse.set(submitGenoData(programId, programKey, submissionId, "sample.vcf")), "Upload did not complete within the time period"); + + ImportResponse response = importResponse.get(); + assertNotNull(response); + assertNotNull(response.getProgress()); + assertEquals((short) HttpStatus.ACCEPTED.getCode(), + response.getProgress().getStatuscode(), + "Error importing geno file: " + response.getProgress().getMessage()); + + //Second import with same filename should return error + AtomicReference importResponseTwo = new AtomicReference<>(); + assertTimeout(Duration.of(2, ChronoUnit.MINUTES), () -> importResponseTwo.set(submitGenoData(programId, programKey, submissionId, "sample.vcf")), "Upload did not complete within the time period"); + + ImportResponse responseTwo = importResponseTwo.get(); + assertNotNull(responseTwo); + assertNotNull(responseTwo.getProgress()); + assertEquals((short) HttpStatus.BAD_REQUEST.getCode(), responseTwo.getProgress().getStatuscode()); + assertEquals("Import cannot proceed. File name 'sample.vcf' already exists in the database.", responseTwo.getProgress().getMessage()); + } + @Test public void testSubmitMissingSubmissionSamples() throws ApiException { UUID programId = UUID.fromString("29162e85-e739-4f19-9fd0-0c377ed59956"); From 30ce60ee1a78368f0fab7d9a9a292ad370328c3a Mon Sep 17 00:00:00 2001 From: HMS17 <84345306+HMS17@users.noreply.github.com> Date: Tue, 6 Oct 2026 10:03:00 -0400 Subject: [PATCH 3/3] [BI-3032] Code review unit test suggestion Co-authored-by: Nick <53413353+nickpalladino@users.noreply.github.com> --- .../GigwaGenotypeServiceImplIntegrationTest.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java b/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java index 72c93f4e7..20d1ea6fd 100644 --- a/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java +++ b/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java @@ -561,14 +561,14 @@ public void testSubmitInvalidHeader() throws ApiException { assertEquals("Header row is not valid VCF format", response.getProgress().getMessage()); } - @Test - public void testSubmitSameFileName() throws ApiException { +@Test + public void testSubmitSameFileName() throws ApiException, IOException { UUID programId = UUID.fromString("29162e85-e739-4f19-9fd0-0c377ed59956"); String programKey = "TESTSUBMITDUPNAME"; UUID submissionId = UUID.randomUUID(); - setupMocksForSubmitGenoData(programId, submissionId, Collections.emptyList()); + setupMocksForSubmitGenoData(programId, submissionId, buildSamplesFromValidVcf()); - //First import should succeed + // First upload should be accepted for asynchronous processing. AtomicReference importResponse = new AtomicReference<>(); assertTimeout(Duration.of(2, ChronoUnit.MINUTES), () -> importResponse.set(submitGenoData(programId, programKey, submissionId, "sample.vcf")), "Upload did not complete within the time period"); @@ -579,7 +579,11 @@ public void testSubmitSameFileName() throws ApiException { response.getProgress().getStatuscode(), "Error importing geno file: " + response.getProgress().getMessage()); - //Second import with same filename should return error + // The DAO is mocked: explicitly simulate the completed import before resubmitting. + doReturn(List.of(GenotypeImportDetails.builder() + .genotypingFileName("sample.vcf") + .build())) + .when(genotypeImportDAO).getGenotypeImportsByProgramId(programId); AtomicReference importResponseTwo = new AtomicReference<>(); assertTimeout(Duration.of(2, ChronoUnit.MINUTES), () -> importResponseTwo.set(submitGenoData(programId, programKey, submissionId, "sample.vcf")), "Upload did not complete within the time period");