test(save): cover version mismatch + slug; clean up tmp on move failure

Add loadRejectsIncompatibleVersion test asserting SaveException on schema
version 999, assert derived slug in listReturnsSlotMetadata, and harden
save() to delete the orphaned .tmp file when the non-atomic fallback move
also fails before re-throwing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 14:50:10 +02:00
parent 6a68d7e2f5
commit ed41418434
2 changed files with 19 additions and 1 deletions

View File

@@ -52,7 +52,12 @@ public class SaveService {
try {
Files.move(tmp, target, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
} catch (IOException atomicFailed) {
Files.move(tmp, target, StandardCopyOption.REPLACE_EXISTING);
try {
Files.move(tmp, target, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException fallbackFailed) {
Files.deleteIfExists(tmp);
throw fallbackFailed;
}
}
} catch (IOException e) {
throw new SaveException("Could not write save '" + session.getSlotName() + "': " + e.getMessage(), e);

View File

@@ -45,6 +45,7 @@ class SaveServiceTest {
List<SaveSlotInfo> slots = svc.list();
assertThat(slots).hasSize(1);
assertThat(slots.getFirst().slotName()).isEqualTo("Alpha Run");
assertThat(slots.getFirst().slug()).isEqualTo("alpha_run");
assertThat(slots.getFirst().turn()).isEqualTo(3);
}
@@ -60,4 +61,16 @@ class SaveServiceTest {
SaveService svc = new SaveService(dir);
assertThrows(SaveException.class, () -> svc.load("bad"));
}
@Test
void loadRejectsIncompatibleVersion(@TempDir Path dir) throws Exception {
// a syntactically valid SaveData JSON but with a future schemaVersion
String json = "{\"schemaVersion\":999,\"worldTitle\":\"X\",\"slotName\":\"v\","
+ "\"savedAtEpochMillis\":0,\"turn\":0,\"currentRoomId\":\"k\","
+ "\"visitedRoomIds\":[],\"gold\":0,\"inventoryItemIds\":[],\"flags\":[],"
+ "\"questStages\":{},\"questCompleted\":[],\"roomItemIds\":{},\"switchStates\":{}}";
Files.writeString(dir.resolve("v.json"), json);
SaveService svc = new SaveService(dir);
assertThrows(SaveException.class, () -> svc.load("v"));
}
}