Skip to content

Commit b00dc90

Browse files
committed
Ensure unique file names for dataset parts during creation and update operations
- Added validation to enforce unique file names in `DatasetServiceImpl`. - Introduced integration tests for dataset creation and update with duplicate file names.
1 parent 41d001a commit b00dc90

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

dataset/src/integrationTest/kotlin/com/cosmotech/dataset/service/DatasetServiceIntegrationTest.kt

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,67 @@ class DatasetServiceIntegrationTest() : CsmTestBase() {
408408
assertEquals(DatasetPartTypeEnum.File, inventoryCreatedDatasetPart.type)
409409
}
410410

411+
@Test
412+
fun `test createDataset with two dataset part with same name`() {
413+
414+
val customerPartName = "Customers list"
415+
val customerPartDescription = "List of customers"
416+
val customerPartTags = mutableListOf("part", "public", "customers")
417+
val customerPartCreateRequest =
418+
DatasetPartCreateRequest(
419+
name = customerPartName,
420+
sourceName = CUSTOMER_SOURCE_FILE_NAME,
421+
description = customerPartDescription,
422+
tags = customerPartTags,
423+
type = DatasetPartTypeEnum.File)
424+
425+
val datasetName = "Shop Dataset"
426+
val datasetDescription = "Dataset for shop"
427+
val datasetTags = mutableListOf("dataset", "public", "shop")
428+
val datasetCreateRequest =
429+
DatasetCreateRequest(
430+
name = datasetName,
431+
description = datasetDescription,
432+
tags = datasetTags,
433+
parts =
434+
mutableListOf(
435+
customerPartCreateRequest,
436+
DatasetPartCreateRequest(
437+
name = "Part create request 2", sourceName = "anotherFile.txt")))
438+
439+
val customerTestFile = resourceLoader.getResource("classpath:/$CUSTOMER_SOURCE_FILE_NAME").file
440+
441+
val customerFileToSend = FileInputStream(customerTestFile)
442+
443+
val customerMockMultipartFile =
444+
MockMultipartFile(
445+
"files",
446+
CUSTOMER_SOURCE_FILE_NAME,
447+
MediaType.MULTIPART_FORM_DATA_VALUE,
448+
IOUtils.toByteArray(customerFileToSend))
449+
450+
val customerMockMultipartFile2 =
451+
MockMultipartFile(
452+
"files",
453+
CUSTOMER_SOURCE_FILE_NAME,
454+
MediaType.MULTIPART_FORM_DATA_VALUE,
455+
InputStream.nullInputStream())
456+
457+
val exception =
458+
assertThrows<IllegalArgumentException> {
459+
datasetApiService.createDataset(
460+
organizationSaved.id,
461+
workspaceSaved.id,
462+
datasetCreateRequest,
463+
arrayOf(customerMockMultipartFile, customerMockMultipartFile2))
464+
}
465+
assertEquals(
466+
"Part File names should be unique during dataset creation. " +
467+
"Files: [$CUSTOMER_SOURCE_FILE_NAME, $CUSTOMER_SOURCE_FILE_NAME]. " +
468+
"Dataset Parts: [$CUSTOMER_SOURCE_FILE_NAME, anotherFile.txt].",
469+
exception.message)
470+
}
471+
411472
@Test
412473
fun `test createDataset with empty files`() {
413474

@@ -1565,6 +1626,75 @@ class DatasetServiceIntegrationTest() : CsmTestBase() {
15651626
constructFilePathForDatasetPart(updatedDataset, 0)))
15661627
}
15671628

1629+
@Test
1630+
fun `test updateDataset with two dataset part with same name`() {
1631+
1632+
val initialDataset =
1633+
datasetApiService.createDataset(
1634+
organizationSaved.id,
1635+
workspaceSaved.id,
1636+
DatasetCreateRequest(name = "Dataset without parts"),
1637+
emptyArray())
1638+
1639+
val customerPartName = "Customers list"
1640+
val customerPartDescription = "List of customers"
1641+
val customerPartTags = mutableListOf("part", "public", "customers")
1642+
val customerPartCreateRequest =
1643+
DatasetPartCreateRequest(
1644+
name = customerPartName,
1645+
sourceName = CUSTOMER_SOURCE_FILE_NAME,
1646+
description = customerPartDescription,
1647+
tags = customerPartTags,
1648+
type = DatasetPartTypeEnum.File)
1649+
1650+
val datasetName = "Shop Dataset"
1651+
val datasetDescription = "Dataset for shop"
1652+
val datasetTags = mutableListOf("dataset", "public", "shop")
1653+
val datasetUpdateRequest =
1654+
DatasetUpdateRequest(
1655+
name = datasetName,
1656+
description = datasetDescription,
1657+
tags = datasetTags,
1658+
parts =
1659+
mutableListOf(
1660+
customerPartCreateRequest,
1661+
DatasetPartCreateRequest(
1662+
name = "Part create request 2", sourceName = "anotherFile.txt")))
1663+
1664+
val customerTestFile = resourceLoader.getResource("classpath:/$CUSTOMER_SOURCE_FILE_NAME").file
1665+
1666+
val customerFileToSend = FileInputStream(customerTestFile)
1667+
1668+
val customerMockMultipartFile =
1669+
MockMultipartFile(
1670+
"files",
1671+
CUSTOMER_SOURCE_FILE_NAME,
1672+
MediaType.MULTIPART_FORM_DATA_VALUE,
1673+
IOUtils.toByteArray(customerFileToSend))
1674+
1675+
val customerMockMultipartFile2 =
1676+
MockMultipartFile(
1677+
"files",
1678+
CUSTOMER_SOURCE_FILE_NAME,
1679+
MediaType.MULTIPART_FORM_DATA_VALUE,
1680+
InputStream.nullInputStream())
1681+
1682+
val exception =
1683+
assertThrows<IllegalArgumentException> {
1684+
datasetApiService.updateDataset(
1685+
organizationSaved.id,
1686+
workspaceSaved.id,
1687+
initialDataset.id,
1688+
datasetUpdateRequest,
1689+
arrayOf(customerMockMultipartFile, customerMockMultipartFile2))
1690+
}
1691+
assertEquals(
1692+
"Part File names should be unique during dataset update. " +
1693+
"Files: [$CUSTOMER_SOURCE_FILE_NAME, $CUSTOMER_SOURCE_FILE_NAME]. " +
1694+
"Dataset Parts: [$CUSTOMER_SOURCE_FILE_NAME, anotherFile.txt].",
1695+
exception.message)
1696+
}
1697+
15681698
@Test
15691699
fun `test updateDataset with File dataset part with unallowed mimetype`() {
15701700

dataset/src/main/kotlin/com/cosmotech/dataset/service/DatasetServiceImpl.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,12 @@ class DatasetServiceImpl(
682682
"Number of files must be equal to the number of parts if specified. " +
683683
"${files.size} != ${datasetCreateRequest.parts?.size}"
684684
}
685+
require(
686+
files.groupingBy { it.originalFilename }.eachCount().filter { it.value > 1 }.isEmpty()) {
687+
"Part File names should be unique during dataset creation. " +
688+
"Files: ${files.map { it.originalFilename }}. " +
689+
"Dataset Parts: ${datasetCreateRequest.parts?.map { it.sourceName }}."
690+
}
685691
require(
686692
files.mapNotNull { it.originalFilename }.toSortedSet(naturalOrder()) ==
687693
datasetCreateRequest.parts?.map { it.sourceName }?.toSortedSet(naturalOrder())) {
@@ -712,6 +718,12 @@ class DatasetServiceImpl(
712718
"Number of files must be equal to the number of parts if specified. " +
713719
"${files.size} != ${datasetUpdateRequest.parts?.size}"
714720
}
721+
require(
722+
files.groupingBy { it.originalFilename }.eachCount().filter { it.value > 1 }.isEmpty()) {
723+
"Part File names should be unique during dataset update. " +
724+
"Files: ${files.map { it.originalFilename }}. " +
725+
"Dataset Parts: ${datasetUpdateRequest.parts?.map { it.sourceName }}."
726+
}
715727
require(
716728
files.mapNotNull { it.originalFilename }.toSortedSet(naturalOrder()) ==
717729
(datasetUpdateRequest.parts?.map { it.sourceName }?.toSortedSet(naturalOrder())

0 commit comments

Comments
 (0)