SavePaths.java

1
package com.rox.save;
2
3
import java.io.IOException;
4
import java.nio.file.FileAlreadyExistsException;
5
import java.nio.file.Files;
6
import java.nio.file.Path;
7
import java.time.LocalDateTime;
8
import java.time.format.DateTimeFormatter;
9
10
/**
11
 * Where a ROM's save files live: a directory named after the ROM (its filename without extension),
12
 * alongside the ROM file itself - not a hardcoded project path, since a ROM can be loaded from
13
 * anywhere.
14
 */
15
public final class SavePaths {
16
    private static final String BATTERY_SAVE_FILE_NAME = "battery.sav";
17
    private static final String LIVE_SAVE_FILE_NAME = "latest.sav";
18
    private static final String LABELS_FILE_NAME = "labels.txt";
19
    private static final String DEBUG_SNAPSHOT_PREFIX = "debug-snapshot-";
20
    private static final DateTimeFormatter DEBUG_SNAPSHOT_TIMESTAMP = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss");
21
22
    private SavePaths(){
23
    }
24
25
    public static Path saveDirectory(final Path romPath){
26
        final Path absoluteRomPath = romPath.toAbsolutePath();
27
        final String fileName = absoluteRomPath.getFileName().toString();
28
        final int extensionIndex = fileName.lastIndexOf('.');
29 2 1. saveDirectory : changed conditional boundary → KILLED
2. saveDirectory : negated conditional → KILLED
        final String baseName = extensionIndex > 0 ? fileName.substring(0, extensionIndex) : fileName;
30 1 1. saveDirectory : replaced return value with null for com/rox/save/SavePaths::saveDirectory → KILLED
        return absoluteRomPath.getParent().resolve(baseName);
31
    }
32
33
    public static Path batterySaveFile(final Path romPath){
34 1 1. batterySaveFile : replaced return value with null for com/rox/save/SavePaths::batterySaveFile → KILLED
        return saveDirectory(romPath).resolve(BATTERY_SAVE_FILE_NAME);
35
    }
36
37
    public static Path liveSaveFile(final Path romPath){
38 1 1. liveSaveFile : replaced return value with null for com/rox/save/SavePaths::liveSaveFile → KILLED
        return saveDirectory(romPath).resolve(LIVE_SAVE_FILE_NAME);
39
    }
40
41
    /** The ROM's memory labels - see {@code com.rox.debug.labels.LabelFile}. */
42
    public static Path labelsFile(final Path romPath){
43 1 1. labelsFile : replaced return value with null for com/rox/save/SavePaths::labelsFile → KILLED
        return saveDirectory(romPath).resolve(LABELS_FILE_NAME);
44
    }
45
46
    /** {@code debug-snapshot-<yyyyMMdd-HHmmss>} - names both a flagged issue's folder and the {@code .sav} inside it. */
47
    public static String debugSnapshotName(final LocalDateTime capturedAt){
48 1 1. debugSnapshotName : replaced return value with "" for com/rox/save/SavePaths::debugSnapshotName → KILLED
        return DEBUG_SNAPSHOT_PREFIX + DEBUG_SNAPSHOT_TIMESTAMP.format(capturedAt);
49
    }
50
51
    /** Where a flagged issue's files go: a {@link #debugSnapshotName} folder in the ROM's save directory. */
52
    public static Path debugSnapshotDirectory(final Path romPath, final LocalDateTime capturedAt){
53 1 1. debugSnapshotDirectory : replaced return value with null for com/rox/save/SavePaths::debugSnapshotDirectory → KILLED
        return saveDirectory(romPath).resolve(debugSnapshotName(capturedAt));
54
    }
55
56
    /**
57
     * Creates and returns a fresh folder for a flagged issue: {@link #debugSnapshotDirectory} itself, or
58
     * that name plus {@code -2}, {@code -3}... if a capture in the same second already took it. Creating
59
     * the folder is the claim - {@link Files#createDirectory} fails if it exists - so two captures can't
60
     * both end up writing into the same one.
61
     */
62
    public static Path reserveDebugSnapshotDirectory(final Path romPath, final LocalDateTime capturedAt) throws IOException {
63
        final Path base = debugSnapshotDirectory(romPath, capturedAt);
64
        Files.createDirectories(base.getParent());
65
        Path candidate = base;
66 1 1. reserveDebugSnapshotDirectory : Changed increment from 1 to -1 → KILLED
        for (int suffix = 2; ; suffix++){
67
            try {
68 1 1. reserveDebugSnapshotDirectory : replaced return value with null for com/rox/save/SavePaths::reserveDebugSnapshotDirectory → KILLED
                return Files.createDirectory(candidate);
69
            } catch (FileAlreadyExistsException e){
70
                candidate = base.resolveSibling(base.getFileName() + "-" + suffix);
71
            }
72
        }
73
    }
74
}

Mutations

29

1.1
Location : saveDirectory
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:romFileNameThatIsOnlyADotIsUsedAsIsNotAsAnEmptyBaseName()]
changed conditional boundary → KILLED

2.2
Location : saveDirectory
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:romFileNameWithNoExtensionIsUsedAsIs()]
negated conditional → KILLED

30

1.1
Location : saveDirectory
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:romFileNameWithNoExtensionIsUsedAsIs()]
replaced return value with null for com/rox/save/SavePaths::saveDirectory → KILLED

34

1.1
Location : batterySaveFile
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:batterySaveFileIsInsideTheSaveDirectory()]
replaced return value with null for com/rox/save/SavePaths::batterySaveFile → KILLED

38

1.1
Location : liveSaveFile
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:liveSaveFileIsInsideTheSaveDirectory()]
replaced return value with null for com/rox/save/SavePaths::liveSaveFile → KILLED

43

1.1
Location : labelsFile
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:labelsFileIsInTheRomsSaveDirectory()]
replaced return value with null for com/rox/save/SavePaths::labelsFile → KILLED

48

1.1
Location : debugSnapshotName
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:debugSnapshotNameIsTheZeroPaddedLocalTimestamp()]
replaced return value with "" for com/rox/save/SavePaths::debugSnapshotName → KILLED

53

1.1
Location : debugSnapshotDirectory
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:debugSnapshotDirectoryIsInTheRomsSaveDirectory()]
replaced return value with null for com/rox/save/SavePaths::debugSnapshotDirectory → KILLED

66

1.1
Location : reserveDebugSnapshotDirectory
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:reserveDebugSnapshotDirectorySuffixesCapturesInTheSameSecond(java.nio.file.Path)]
Changed increment from 1 to -1 → KILLED

68

1.1
Location : reserveDebugSnapshotDirectory
Killed by : com.rox.save.SavePathsTest.[engine:junit-jupiter]/[class:com.rox.save.SavePathsTest]/[method:reserveDebugSnapshotDirectoryCreatesTheTimestampFolderWhenFree(java.nio.file.Path)]
replaced return value with null for com/rox/save/SavePaths::reserveDebugSnapshotDirectory → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1