Skip to content

Commit d9af94f

Browse files
authored
test: preserve independent tasks under filename collisions
1 parent 54eaf78 commit d9af94f

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

‎base/src/test/java/ai/javaclaw/tasks/FileSystemTaskRepositoryTest.java‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,16 @@
88
import java.io.IOException;
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
11+
import java.time.Instant;
1112
import java.time.LocalDate;
1213
import java.time.LocalDateTime;
1314
import java.time.ZoneId;
1415
import java.util.List;
16+
import java.util.ArrayList;
17+
import java.util.HashSet;
18+
import java.util.concurrent.Executors;
19+
import java.util.concurrent.Future;
20+
import java.util.concurrent.TimeUnit;
1521
import java.util.stream.Stream;
1622

1723
import static org.assertj.core.api.Assertions.assertThat;
@@ -27,6 +33,47 @@ void setUp() throws IOException {
2733
repository = new FileSystemTaskRepository(new FileSystemResource(workspaceDir));
2834
}
2935

36+
@Test
37+
void concurrentCreatesNeverShareAFile() throws Exception {
38+
Instant timestamp = Instant.parse("2026-03-21T10:00:00Z");
39+
try (var executor = Executors.newFixedThreadPool(8)) {
40+
var futures = new ArrayList<Future<Task>>();
41+
for (int index = 0; index < 20; index++) {
42+
String description = "Request " + index;
43+
futures.add(executor.submit(() -> repository.save(Task.newTask("same-name", timestamp, description))));
44+
}
45+
var ids = new HashSet<String>();
46+
for (var future : futures) {
47+
Task saved = future.get(10, TimeUnit.SECONDS);
48+
assertThat(ids.add(saved.getId())).isTrue();
49+
assertThat(repository.getTaskById(saved.getId()).getDescription()).isEqualTo(saved.getDescription());
50+
}
51+
}
52+
}
53+
54+
@Test
55+
void sameNameAndTimestampTasksRemainIndependent() {
56+
var timestamp = Instant.parse("2026-03-21T10:00:00Z");
57+
Task first = repository.save(Task.newTask("check-mail", timestamp, "First request"));
58+
Task second = repository.save(Task.newTask("check-mail", timestamp, "Second request"));
59+
60+
assertThat(second.getId()).isNotEqualTo(first.getId());
61+
assertThat(repository.getTaskById(first.getId()).getDescription()).isEqualTo("First request");
62+
assertThat(repository.getTaskById(second.getId()).getDescription()).isEqualTo("Second request");
63+
repository.save(first.withStatus(Task.Status.completed));
64+
assertThat(repository.getTaskById(second.getId()).getStatus()).isEqualTo(Task.Status.todo);
65+
}
66+
67+
@Test
68+
void sanitizedNameCollisionsRemainIndependent() {
69+
var timestamp = Instant.parse("2026-03-21T10:00:00Z");
70+
Task first = repository.save(Task.newTask("check mail", timestamp, "First"));
71+
Task second = repository.save(Task.newTask("check?mail", timestamp, "Second"));
72+
73+
assertThat(second.getId()).isNotEqualTo(first.getId());
74+
assertThat(repository.getTaskById(first.getId()).getName()).isEqualTo("check mail");
75+
}
76+
3077
@Test
3178
void saveTaskCreatesFileWithCorrectContent() throws IOException {
3279
Task task = Task.newTask("handle-email", "Process unread email messages");

0 commit comments

Comments
 (0)