CredentialScanUnitSource.java

1
package org.egothor.methodatlas.command;
2
3
import java.io.IOException;
4
import java.io.UncheckedIOException;
5
import java.nio.charset.StandardCharsets;
6
import java.nio.file.FileSystems;
7
import java.nio.file.Files;
8
import java.nio.file.Path;
9
import java.nio.file.PathMatcher;
10
import java.util.ArrayList;
11
import java.util.List;
12
import java.util.logging.Level;
13
import java.util.logging.Logger;
14
import java.util.stream.Stream;
15
import org.egothor.methodatlas.api.CredentialScanUnit;
16
17
/**
18
 * Selects files to scan for credentials by mask and reads each into a
19
 * {@link CredentialScanUnit}. The default mask is the test-file suffix list; an
20
 * optional glob override widens the scan to arbitrary source.
21
 *
22
 * @since 4.1.0
23
 */
24
public final class CredentialScanUnitSource {
25
26
    private static final Logger LOG = Logger.getLogger(CredentialScanUnitSource.class.getName());
27
28
    private final List<String> suffixes;
29
    private final PathMatcher globMatcher;
30
31
    /**
32
     * Creates a source.
33
     *
34
     * @param suffixes test-file suffixes used when no glob override is given; never {@code null}
35
     * @param glob     optional glob (e.g. {@code "**}{@code /*.java"}); {@code null} uses {@code suffixes}
36
     */
37
    public CredentialScanUnitSource(List<String> suffixes, String glob) {
38
        this.suffixes = List.copyOf(suffixes);
39 2 1. <init> : removed conditional - replaced equality check with true → KILLED
2. <init> : removed conditional - replaced equality check with false → KILLED
        this.globMatcher = glob == null ? null
40
                : FileSystems.getDefault().getPathMatcher("glob:" + glob);
41
    }
42
43
    /**
44
     * Walks {@code roots} and returns one unit per matching, readable file, in
45
     * deterministic sorted order.
46
     *
47
     * @param roots scan roots; never {@code null}
48
     * @return scan units; never {@code null}
49
     */
50
    public List<CredentialScanUnit> collect(List<Path> roots) {
51
        List<CredentialScanUnit> units = new ArrayList<>();
52
        for (Path root : roots) {
53
            try (Stream<Path> walk = Files.walk(root)) {
54 2 1. lambda$collect$0 : replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::lambda$collect$0 → SURVIVED
2. lambda$collect$0 : replaced boolean return with false for org/egothor/methodatlas/command/CredentialScanUnitSource::lambda$collect$0 → KILLED
                walk.filter(Files::isRegularFile)
55
                    .filter(this::matches)
56
                    .sorted()
57
                    .forEach(p -> readInto(p, units));
58
            } catch (IOException e) {
59
                throw new UncheckedIOException("Failed to walk " + root, e);
60
            }
61
        }
62 1 1. collect : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialScanUnitSource::collect → KILLED
        return units;
63
    }
64
65
    private boolean matches(Path p) {
66 2 1. matches : removed conditional - replaced equality check with true → KILLED
2. matches : removed conditional - replaced equality check with false → KILLED
        if (globMatcher != null) {
67 2 1. matches : replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → SURVIVED
2. matches : replaced boolean return with false for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → KILLED
            return globMatcher.matches(p);
68
        }
69
        Path fileName = p.getFileName();
70 2 1. matches : removed conditional - replaced equality check with false → SURVIVED
2. matches : removed conditional - replaced equality check with true → KILLED
        if (fileName == null) {
71 1 1. matches : replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → NO_COVERAGE
            return false;
72
        }
73
        String name = fileName.toString();
74 2 1. matches : replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → KILLED
2. matches : replaced boolean return with false for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → KILLED
        return suffixes.stream().anyMatch(name::endsWith);
75
    }
76
77
    private void readInto(Path p, List<CredentialScanUnit> units) {
78
        try {
79
            String source = Files.readString(p, StandardCharsets.UTF_8);
80
            units.add(new CredentialScanUnit(p.toAbsolutePath(), null, source, languageOf(p)));
81
        } catch (IOException e) {
82
            // Non-fatal: skip unreadable / binary files.
83
            LOG.log(Level.FINE, e, () -> "Skipping unreadable file: " + p);
84
        }
85
    }
86
87
    /**
88
     * Derives a short language identifier from a file's extension.
89
     *
90
     * @param p the file path; never {@code null}
91
     * @return the lowercase extension (without the dot), or {@code null} when the
92
     *         path has no file name or no extension
93
     */
94
    /* default */ static String languageOf(Path p) {
95
        Path fileName = p.getFileName();
96 2 1. languageOf : removed conditional - replaced equality check with false → SURVIVED
2. languageOf : removed conditional - replaced equality check with true → KILLED
        if (fileName == null) {
97 1 1. languageOf : replaced return value with "" for org/egothor/methodatlas/command/CredentialScanUnitSource::languageOf → NO_COVERAGE
            return null;
98
        }
99
        String name = fileName.toString();
100
        int dot = name.lastIndexOf('.');
101 5 1. languageOf : removed conditional - replaced comparison check with true → SURVIVED
2. languageOf : changed conditional boundary → SURVIVED
3. languageOf : removed conditional - replaced comparison check with false → KILLED
4. languageOf : replaced return value with "" for org/egothor/methodatlas/command/CredentialScanUnitSource::languageOf → KILLED
5. languageOf : Replaced integer addition with subtraction → KILLED
        return dot >= 0 ? name.substring(dot + 1) : null;
102
    }
103
}

Mutations

39

1.1
Location : <init>
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:globOverrideWidensScope(java.nio.file.Path)]
removed conditional - replaced equality check with true → KILLED

2.2
Location : <init>
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
removed conditional - replaced equality check with false → KILLED

54

1.1
Location : lambda$collect$0
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:globOverrideWidensScope(java.nio.file.Path)]
replaced boolean return with false for org/egothor/methodatlas/command/CredentialScanUnitSource::lambda$collect$0 → KILLED

2.2
Location : lambda$collect$0
Killed by : none
replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::lambda$collect$0 → SURVIVED
Covering tests

62

1.1
Location : collect
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:globOverrideWidensScope(java.nio.file.Path)]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialScanUnitSource::collect → KILLED

66

1.1
Location : matches
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
removed conditional - replaced equality check with true → KILLED

2.2
Location : matches
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:globOverrideWidensScope(java.nio.file.Path)]
removed conditional - replaced equality check with false → KILLED

67

1.1
Location : matches
Killed by : none
replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → SURVIVED
Covering tests

2.2
Location : matches
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:globOverrideWidensScope(java.nio.file.Path)]
replaced boolean return with false for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → KILLED

70

1.1
Location : matches
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
removed conditional - replaced equality check with true → KILLED

2.2
Location : matches
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

71

1.1
Location : matches
Killed by : none
replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → NO_COVERAGE

74

1.1
Location : matches
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
replaced boolean return with true for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → KILLED

2.2
Location : matches
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
replaced boolean return with false for org/egothor/methodatlas/command/CredentialScanUnitSource::matches → KILLED

96

1.1
Location : languageOf
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
removed conditional - replaced equality check with true → KILLED

2.2
Location : languageOf
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

97

1.1
Location : languageOf
Killed by : none
replaced return value with "" for org/egothor/methodatlas/command/CredentialScanUnitSource::languageOf → NO_COVERAGE

101

1.1
Location : languageOf
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
removed conditional - replaced comparison check with false → KILLED

2.2
Location : languageOf
Killed by : none
removed conditional - replaced comparison check with true → SURVIVED
Covering tests

3.3
Location : languageOf
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
replaced return value with "" for org/egothor/methodatlas/command/CredentialScanUnitSource::languageOf → KILLED

4.4
Location : languageOf
Killed by : none
changed conditional boundary → SURVIVED Covering tests

5.5
Location : languageOf
Killed by : org.egothor.methodatlas.command.CredentialScanUnitSourceTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialScanUnitSourceTest]/[method:selectsFilesMatchingSuffixes(java.nio.file.Path)]
Replaced integer addition with subtraction → KILLED

Active mutators

Tests examined


Report generated by PIT 1.30.1 support