Db.java

1
package com.renomad.minum.database;
2
3
import com.renomad.minum.logging.ILogger;
4
import com.renomad.minum.queue.AbstractActionQueue;
5
import com.renomad.minum.queue.ActionQueue;
6
import com.renomad.minum.state.Context;
7
import com.renomad.minum.utils.FileUtils;
8
import com.renomad.minum.utils.IFileUtils;
9
10
import java.io.IOException;
11
import java.nio.file.Path;
12
import java.text.ParseException;
13
import java.util.Collection;
14
import java.util.Collections;
15
import java.util.HashMap;
16
import java.util.concurrent.ConcurrentHashMap;
17
import java.util.concurrent.atomic.AtomicLong;
18
import java.util.concurrent.locks.ReentrantLock;
19
import java.util.function.Function;
20
21
import static com.renomad.minum.utils.Invariants.mustBeFalse;
22
import static com.renomad.minum.utils.Invariants.mustBeTrue;
23
24
/**
25
 * a memory-based disk-persisted database class.
26
 * @param <T> the type of data we'll be persisting (must extend from {@link DbData}
27
 */
28
public final class Db<T extends DbData<?>> extends AbstractDb<T> {
29
30
    /**
31
     * The suffix we will apply to each database file
32
     */
33
    static final String DATABASE_FILE_SUFFIX = ".ddps";
34
    private final AbstractActionQueue actionQueue;
35
36
    /**
37
     * A lock around loading the data - so we can't find ourselves
38
     * in a situation where multiple threads are loading the data.
39
     */
40
    private final ReentrantLock loadDataLock = new ReentrantLock();
41
42
    /**
43
     * The full path to the file that contains the most-recent index
44
     * for this data.  As we add new files, each gets its own index
45
     * value.  When we start the program, we use this to determine
46
     * where to start counting for new indexes.
47
     */
48
    private final Path fullPathForIndexFile;
49
50
    volatile boolean hasLoadedData;
51
52
    /**
53
     * Constructs an in-memory disk-persisted database.
54
     * Loading of data from disk happens at the first invocation of any command
55
     * changing or requesting data, such as {@link #write(DbData)}, {@link #delete(DbData)},
56
     * or {@link #values()}.  See the private method loadData() for details.
57
     * @param dbDirectory this uniquely names your database, and also sets the directory
58
     *                    name for this data.  The expected use case is to name this after
59
     *                    the data in question.  For example, "users", or "accounts".
60
     * @param context used to provide important state data to several components
61
     * @param instance an instance of the {@link DbData} object relevant for use in this database. Note
62
     *                 that each database (that is, each instance of this class), focuses on just one
63
     *                 data, which must be an implementation of {@link DbData}.
64
     */
65
    public Db(Path dbDirectory, Context context, T instance) {
66
        this(dbDirectory, context, instance, new FileUtils(context.getLogger(), context.getConstants()));
67
    }
68
69
    Db(Path dbDirectory, Context context, T instance, IFileUtils fileUtils) {
70
        super(dbDirectory, context, instance, fileUtils);
71
        this.hasLoadedData = false;
72
        this.fullPathForIndexFile = dbDirectory.resolve("index" + DATABASE_FILE_SUFFIX);
73
        this.actionQueue = new ActionQueue("DatabaseWriter " + dbDirectory, context).initialize();
74
75 1 1. <init> : negated conditional → KILLED
        if (fileUtils.exists(fullPathForIndexFile)) {
76
            try {
77
                long indexValue;
78
                String indexValueString = fileUtils.readString(fullPathForIndexFile);
79
                indexValue = Long.parseLong(indexValueString);
80
                this.index = new AtomicLong(indexValue);
81
            } catch (Exception ex) {
82
                throw new DbException("Error in Db constructor", ex);
83
            }
84
85
        } else {
86
            this.index = new AtomicLong(1L);
87
        }
88
89 2 1. lambda$new$0 : removed call to com/renomad/minum/utils/IFileUtils::makeDirectory → TIMED_OUT
2. <init> : removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → KILLED
        actionQueue.enqueue("create directory" + dbDirectory, () -> fileUtils.makeDirectory(dbDirectory));
90
    }
91
92
    /**
93
     * Write data to the database.  Use an index of 0 to store new data, and a positive
94
     * non-zero value to update data.
95
     * <p><em>
96
     *     Example of adding new data to the database:
97
     * </em></p>
98
     * {@snippet :
99
     *          final var newSalt = StringUtils.generateSecureRandomString(10);
100
     *          final var hashedPassword = CryptoUtils.createPasswordHash(newPassword, newSalt);
101
     *          final var newUser = new User(0L, newUsername, hashedPassword, newSalt);
102
     *          userDb.write(newUser);
103
     * }
104
     * <p><em>
105
     *     Example of updating data:
106
     * </em></p>
107
     * {@snippet :
108
     *         // write the updated salted password to the database
109
     *         final var updatedUser = new User(
110
     *                 user().getIndex(),
111
     *                 user().getUsername(),
112
     *                 hashedPassword,
113
     *                 newSalt);
114
     *         userDb.write(updatedUser);
115
     * }
116
     *
117
     * @param newData the data we are writing
118
     * @return the data with its new index assigned.
119
     */
120
    @Override
121
    public T write(T newData) {
122 1 1. write : removed call to com/renomad/minum/database/Db::basicDataChecks → TIMED_OUT
        basicDataChecks(newData);
123
124
        // load data if needed
125 1 1. write : negated conditional → TIMED_OUT
        if (!hasLoadedData) loadData();
126
127 1 1. write : removed call to com/renomad/minum/database/InspectableLock::lock → TIMED_OUT
        dbLock.lock();
128
        try {
129
            boolean newElementCreated = processDataIndex(newData);
130 1 1. write : removed call to com/renomad/minum/database/Db::writeToMemory → KILLED
            writeToMemory(newData, newElementCreated);
131
132
            // *** now handle the disk portion ***
133 1 1. write : removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → TIMED_OUT
            actionQueue.enqueue("persist data to disk",
134 1 1. lambda$write$1 : removed call to com/renomad/minum/database/Db::writeToDisk → TIMED_OUT
                    () -> writeToDisk(newData, dbDirectory, fileUtils, emptyInstance,
135
                            newElementCreated, fullPathForIndexFile, logger));
136
137
            // returning the data at this point is the most convenient
138
            // way users will have access to the new index of the data.
139 1 1. write : replaced return value with null for com/renomad/minum/database/Db::write → TIMED_OUT
            return newData;
140
        } catch (Exception ex) {
141
            throw new DbException("failed to write data " + newData, ex);
142
        } finally {
143 1 1. write : removed call to com/renomad/minum/database/InspectableLock::unlock → KILLED
            dbLock.unlock();
144
        }
145
    }
146
147
    static <T extends DbData<?>> void writeToDisk(T newData, Path dbDirectory, IFileUtils fileUtils, T emptyInstance,
148
                                                  boolean newItemCreated, Path fullPathForIndexFile, ILogger logger) {
149
        final Path fullPath = dbDirectory.resolve(newData.getIndex() + DATABASE_FILE_SUFFIX);
150
        logger.logTrace(() -> String.format("writing data to %s", fullPath));
151
        String serializedData = newData.serialize();
152
        mustBeFalse(serializedData == null || serializedData.isBlank(),
153
                "the serialized form of data must not be blank. " +
154
                        "Is the serialization code written properly? Our datatype: " + emptyInstance);
155
        try {
156 1 1. writeToDisk : removed call to com/renomad/minum/utils/IFileUtils::writeString → TIMED_OUT
            fileUtils.writeString(fullPath, serializedData);
157
158 1 1. writeToDisk : negated conditional → TIMED_OUT
            if (newItemCreated) {
159 2 1. writeToDisk : Replaced long addition with subtraction → TIMED_OUT
2. writeToDisk : removed call to com/renomad/minum/utils/IFileUtils::writeString → TIMED_OUT
                fileUtils.writeString(fullPathForIndexFile, String.valueOf(newData.getIndex() + 1));
160
            }
161
        } catch (IOException e) {
162
            throw new DbException("Error in Db.writeToDisk", e);
163
        }
164
    }
165
166
    /**
167
     * Delete data
168
     * <p><em>Example:</em></p>
169
     * {@snippet :
170
     *      userDb.delete(user);
171
     * }
172
     * @param dataToDelete the data we are serializing and writing
173
     */
174
    @Override
175
    public void delete(T dataToDelete) {
176 1 1. delete : removed call to com/renomad/minum/database/Db::basicDataChecks → KILLED
        basicDataChecks(dataToDelete);
177
178
        // load data if needed
179 1 1. delete : negated conditional → TIMED_OUT
        if (!hasLoadedData) loadData();
180
181 1 1. delete : removed call to com/renomad/minum/database/InspectableLock::lock → TIMED_OUT
        dbLock.lock();
182
        try {
183
            // deal with the in-memory portion
184 1 1. delete : removed call to com/renomad/minum/database/Db::deleteFromMemory → TIMED_OUT
            deleteFromMemory(dataToDelete);
185
186
            // get the current index
187
            boolean shouldResetIndexOnDisk = values().isEmpty();
188
189 1 1. delete : removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → TIMED_OUT
            actionQueue.enqueue("delete data from disk",
190 1 1. lambda$delete$3 : removed call to com/renomad/minum/database/Db::deleteFromDisk → TIMED_OUT
                    () -> deleteFromDisk(dataToDelete, dbDirectory, fileUtils,
191
                            shouldResetIndexOnDisk, fullPathForIndexFile, logger));
192
        } catch (Exception ex) {
193
            throw new DbException("failed to delete data " + dataToDelete, ex);
194
        } finally {
195 1 1. delete : removed call to com/renomad/minum/database/InspectableLock::unlock → KILLED
            dbLock.unlock();
196
        }
197
    }
198
199
    static <T extends DbData<?>> void deleteFromDisk(T dataToDelete, Path dbDirectory, IFileUtils fileUtils,
200
                                                     boolean shouldResetIndexOnDisk, Path fullPathForIndexFile, ILogger logger) {
201
        final Path fullPath = dbDirectory.resolve(dataToDelete.getIndex() + DATABASE_FILE_SUFFIX);
202
        logger.logTrace(() -> String.format("deleting data at %s", fullPath));
203
        try {
204 1 1. deleteFromDisk : negated conditional → TIMED_OUT
            if (!fileUtils.exists(fullPath)) {
205
                throw new DbException(fullPath + " must already exist before deletion");
206
            }
207 1 1. deleteFromDisk : removed call to com/renomad/minum/utils/IFileUtils::delete → TIMED_OUT
            fileUtils.delete(fullPath);
208
209 1 1. deleteFromDisk : negated conditional → TIMED_OUT
            if (shouldResetIndexOnDisk) {
210 1 1. deleteFromDisk : removed call to com/renomad/minum/utils/IFileUtils::writeString → TIMED_OUT
                fileUtils.writeString(fullPathForIndexFile, "1");
211
            }
212
        } catch (Exception ex) {
213
            throw new DbException("Error in Db.deleteFromDisk", ex);
214
        }
215
    }
216
217
    /**
218
     * Grabs all the data from disk and returns it as a list.  This
219
     * method is run by various programs when the system first loads.
220
     */
221
    private void loadDataFromDisk() throws IOException, ParseException {
222
        logger.logDebug(() -> "Loading data from disk. Db classic. Directory: " + dbDirectory);
223
224
        // check if the folder has content for a DbEngine2 database, meaning we
225
        // need to convert it back to the classic DB file structure.
226 1 1. loadDataFromDisk : negated conditional → KILLED
        if (fileUtils.exists(dbDirectory.resolve("currentAppendLog"))) {
227 1 1. loadDataFromDisk : removed call to com/renomad/minum/database/DbFileConverter::convertFolderStructureToDbClassic → TIMED_OUT
            new DbFileConverter(context, dbDirectory, fileUtils).convertFolderStructureToDbClassic();
228
        }
229
230 1 1. loadDataFromDisk : negated conditional → KILLED
        if (! fileUtils.exists(dbDirectory)) {
231
            logger.logDebug(() -> dbDirectory + " directory missing, adding nothing to the data list");
232
            return;
233
        }
234
235 1 1. loadDataFromDisk : removed call to com/renomad/minum/database/Db::walkAndLoad → KILLED
        walkAndLoad(dbDirectory);
236
    }
237
238
    void walkAndLoad(Path dbDirectory) throws IOException {
239
        // walk through all the files in this directory, collecting
240
        // all regular files (non-subdirectories) except for index.ddps
241
        try (final var pathStream = fileUtils.walk(dbDirectory)) {
242
            final var listOfFiles = pathStream.filter(path ->
243 2 1. lambda$walkAndLoad$7 : negated conditional → TIMED_OUT
2. lambda$walkAndLoad$7 : replaced boolean return with true for com/renomad/minum/database/Db::lambda$walkAndLoad$7 → KILLED
                        fileUtils.isRegularFile(path) &&
244 1 1. lambda$walkAndLoad$7 : negated conditional → TIMED_OUT
                        !path.getFileName().toString().startsWith("index")
245
            ).toList();
246
            for (Path p : listOfFiles) {
247 1 1. walkAndLoad : removed call to com/renomad/minum/database/Db::readAndDeserialize → TIMED_OUT
                readAndDeserialize(p);
248
            }
249
        }
250
    }
251
252
    /**
253
     * Carry out the process of reading data files into our in-memory structure
254
     * @param p the path of a particular file
255
     */
256
    void readAndDeserialize(Path p) {
257
        Path fileName = p.getFileName();
258 1 1. readAndDeserialize : negated conditional → KILLED
        if (fileName == null) throw new DbException("At readAndDeserialize, path " + p + " returned a null filename");
259
        String filename = fileName.toString();
260
        int startOfSuffixIndex = filename.indexOf('.');
261 1 1. readAndDeserialize : negated conditional → KILLED
        if(startOfSuffixIndex == -1) {
262
            throw new DbException("the files must have a ddps suffix, like 1.ddps.  filename: " + filename);
263
        }
264
        String fileContents;
265
        try {
266
            fileContents = fileUtils.readString(p);
267
        } catch (IOException e) {
268
            throw new DbException("Error at Db.readAndDeserialize", e);
269
        }
270 1 1. readAndDeserialize : negated conditional → TIMED_OUT
        if (fileContents.isBlank()) {
271
            logger.logDebug( () -> fileName + " file exists but empty, skipping");
272
        } else {
273
            try {
274
                @SuppressWarnings("unchecked")
275
                T deserializedData = (T) emptyInstance.deserialize(fileContents);
276
                mustBeTrue(deserializedData != null, "deserialization of " + emptyInstance +
277
                        " resulted in a null value. Was the serialization method implemented properly?");
278
                long fileNameIdentifier = Long.parseLong(filename.substring(0, startOfSuffixIndex));
279
                mustBeTrue(deserializedData.getIndex() == fileNameIdentifier,
280
                        "The filename must correspond to the data's index. e.g. 1.ddps must have an id of 1");
281
282
                // put the data into the in-memory data structure
283
                data.put(deserializedData.getIndex(), deserializedData);
284 1 1. readAndDeserialize : removed call to com/renomad/minum/database/Db::addToIndexes → TIMED_OUT
                addToIndexes(deserializedData);
285
286
            } catch (Exception e) {
287
                throw new DbException("Failed to deserialize "+ p +" with data (\""+fileContents+"\"). Caused by: " + e);
288
            }
289
        }
290
    }
291
292
    @Override
293
    public Collection<T> values() {
294
        // load data if needed
295 1 1. values : negated conditional → TIMED_OUT
        if (!hasLoadedData) loadData();
296
297 1 1. values : replaced return value with Collections.emptyList for com/renomad/minum/database/Db::values → TIMED_OUT
        return Collections.unmodifiableCollection(data.values());
298
    }
299
300
    /**
301
     * This is what loads the data from disk the
302
     * first time someone needs it.  Because it is
303
     * locked, only one thread can enter at
304
     * a time.  The first one in will load the data,
305
     * and the second will encounter a branch which skips loading.
306
     */
307
    @Override
308
    public Db<T> loadData() {
309 1 1. loadData : removed call to java/util/concurrent/locks/ReentrantLock::lock → TIMED_OUT
        loadDataLock.lock(); // block threads here if multiple are trying to get in - only one gets in at a time
310
        try {
311 1 1. loadData : negated conditional → KILLED
            if (!hasLoadedData) {
312
                // the following statements get the database's state initialized,
313
                // so in the edge case that the data load fails, then when it is
314
                // tried again, the containers will be clean and ready.
315
316
                // Initialize the database to an empty map
317
                this.data = new ConcurrentHashMap<>();
318
319
                // Initialize each of the registered indexes to a new empty map
320 2 1. loadData : removed call to java/util/Map::replaceAll → TIMED_OUT
2. lambda$loadData$9 : replaced return value with Collections.emptyMap for com/renomad/minum/database/Db::lambda$loadData$9 → KILLED
                registeredIndexes.replaceAll((key, value) -> new HashMap<>());
321
322
                // now actually load the data from disk
323 1 1. loadData : removed call to com/renomad/minum/database/Db::loadDataFromDisk → TIMED_OUT
                loadDataFromDisk();
324
            }
325
            hasLoadedData = true;
326 1 1. loadData : replaced return value with null for com/renomad/minum/database/Db::loadData → KILLED
            return this;
327
        } catch (Exception ex) {
328
            throw new DbException("Failed to load data from disk for database with path " + this.dbDirectory, ex);
329
        } finally {
330 1 1. loadData : removed call to java/util/concurrent/locks/ReentrantLock::unlock → KILLED
            loadDataLock.unlock();
331
        }
332
    }
333
334
    /**
335
     * Register an index in the database for higher performance data access.
336
     * <p>
337
     *     This command should be run immediately after database declaration,
338
     *     or more specifically, before any data is loaded from disk. Otherwise,
339
     *     it would be possible to skip indexing that data.
340
     * </p>
341
     * <br>
342
     * Example:
343
     *  {@snippet :
344
     *           final var myDatabase = context.getDb("photos", Photograph.EMPTY);
345
     *           myDatabase.registerIndex("url", photo -> photo.getUrl());
346
     *  }
347
     * @param indexName a string used to distinguish this index.  This string will be used again
348
     *                  when requesting data in a method like {@link #getIndexedData} or {@link #findExactlyOne}
349
     * @param keyObtainingFunction a function which obtains data from the data in this database, used
350
     *                             to partition the data into groups (potentially up to a 1-to-1 correspondence
351
     *                             between id and object)
352
     * @return the database instance if the registration succeeded
353
     * @throws DbException if the parameters are not entered properly, if the index has already
354
     * been registered, or if the data has already been loaded. It is necessary that
355
     * this is run immediately after declaring the database. To explain further: the data is not
356
     * actually loaded until the first time it is needed, such as running a write or delete, or
357
     * if the {@link #loadDataFromDisk()} method is run.  Creating an index map for the data that
358
     * is read from disk only occurs once, at data load time.  Thus, it is crucial that the
359
     * registerIndex command is run before any data is loaded.
360
     */
361
    @Override
362
    public Db<T> registerIndex(String indexName, Function<T, String> keyObtainingFunction) {
363 1 1. registerIndex : negated conditional → TIMED_OUT
        if (hasLoadedData) {
364
            throw new DbException("This method must be run before the database loads data from disk.  Typically, " +
365
                    "it should be run immediately after the database is created.  See this method's documentation");
366
        }
367
        super.registerIndex(indexName, keyObtainingFunction);
368 1 1. registerIndex : replaced return value with null for com/renomad/minum/database/Db::registerIndex → TIMED_OUT
        return this;
369
    }
370
371
    /**
372
     * Given the name of a registered index (see {@link #registerIndex(String, Function)}),
373
     * use the key to find the collection of data that matches it.
374
     * @param indexName the name of an index
375
     * @param key a string value that matches a partition calculated from the partition
376
     *            function provided to {@link #registerIndex(String, Function)}
377
     * @return a collection of data, an empty collection if nothing found
378
     */
379
    @Override
380
    public Collection<T> getIndexedData(String indexName, String key) {
381
        // load data if needed
382 1 1. getIndexedData : negated conditional → TIMED_OUT
        if (!hasLoadedData) loadData();
383 1 1. getIndexedData : replaced return value with Collections.emptyList for com/renomad/minum/database/Db::getIndexedData → TIMED_OUT
        return super.getIndexedData(indexName, key);
384
    }
385
386
    /**
387
     * This function will stop the minum.database persistence cleanly.
388
     * <p>
389
     * In order to do this, we need to wait for our threads
390
     * to finish their work.  In particular, we
391
     * have offloaded our file writes to [actionQueue], which
392
     * has an internal thread for serializing all actions
393
     * on our minum.database
394
     * </p>
395
     */
396
    @Override
397
    public void stop() {
398 1 1. stop : removed call to com/renomad/minum/database/Db::stop → TIMED_OUT
        this.stop(5, 20);
399
    }
400
401
    /**
402
     * Similar to {@link #stop()} but gives more control over how long
403
     * we'll wait before crashing it closed.  See {@link ActionQueue#stop(int, long)}
404
     */
405
    @Override
406
    public void stop(int count, long sleepTime) {
407 1 1. stop : removed call to com/renomad/minum/state/Context::removeFromPaths → TIMED_OUT
        context.removeFromPaths(this.dbDirectory);
408 1 1. stop : removed call to com/renomad/minum/queue/AbstractActionQueue::stop → TIMED_OUT
        actionQueue.stop(count, sleepTime);
409
    }
410
411
}

Mutations

75

1.1
Location : <init>
Killed by : com.renomad.minum.utils.ActionQueueKillerTests
negated conditional → KILLED

89

1.1
Location : <init>
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → KILLED

2.2
Location : lambda$new$0
Killed by : none
removed call to com/renomad/minum/utils/IFileUtils::makeDirectory → TIMED_OUT

122

1.1
Location : write
Killed by : none
removed call to com/renomad/minum/database/Db::basicDataChecks → TIMED_OUT

125

1.1
Location : write
Killed by : none
negated conditional → TIMED_OUT

127

1.1
Location : write
Killed by : none
removed call to com/renomad/minum/database/InspectableLock::lock → TIMED_OUT

130

1.1
Location : write
Killed by : com.renomad.minum.database.FindingsDatabaseTests
removed call to com/renomad/minum/database/Db::writeToMemory → KILLED

133

1.1
Location : write
Killed by : none
removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → TIMED_OUT

134

1.1
Location : lambda$write$1
Killed by : none
removed call to com/renomad/minum/database/Db::writeToDisk → TIMED_OUT

139

1.1
Location : write
Killed by : none
replaced return value with null for com/renomad/minum/database/Db::write → TIMED_OUT

143

1.1
Location : write
Killed by : com.renomad.minum.database.FindingsDatabaseTests
removed call to com/renomad/minum/database/InspectableLock::unlock → KILLED

156

1.1
Location : writeToDisk
Killed by : none
removed call to com/renomad/minum/utils/IFileUtils::writeString → TIMED_OUT

158

1.1
Location : writeToDisk
Killed by : none
negated conditional → TIMED_OUT

159

1.1
Location : writeToDisk
Killed by : none
Replaced long addition with subtraction → TIMED_OUT

2.2
Location : writeToDisk
Killed by : none
removed call to com/renomad/minum/utils/IFileUtils::writeString → TIMED_OUT

176

1.1
Location : delete
Killed by : com.renomad.minum.FunctionalTests.testEndToEnd_Functional(com.renomad.minum.FunctionalTests)
removed call to com/renomad/minum/database/Db::basicDataChecks → KILLED

179

1.1
Location : delete
Killed by : none
negated conditional → TIMED_OUT

181

1.1
Location : delete
Killed by : none
removed call to com/renomad/minum/database/InspectableLock::lock → TIMED_OUT

184

1.1
Location : delete
Killed by : none
removed call to com/renomad/minum/database/Db::deleteFromMemory → TIMED_OUT

189

1.1
Location : delete
Killed by : none
removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → TIMED_OUT

190

1.1
Location : lambda$delete$3
Killed by : none
removed call to com/renomad/minum/database/Db::deleteFromDisk → TIMED_OUT

195

1.1
Location : delete
Killed by : com.renomad.minum.FunctionalTests.testEndToEnd_Functional(com.renomad.minum.FunctionalTests)
removed call to com/renomad/minum/database/InspectableLock::unlock → KILLED

204

1.1
Location : deleteFromDisk
Killed by : none
negated conditional → TIMED_OUT

207

1.1
Location : deleteFromDisk
Killed by : none
removed call to com/renomad/minum/utils/IFileUtils::delete → TIMED_OUT

209

1.1
Location : deleteFromDisk
Killed by : none
negated conditional → TIMED_OUT

210

1.1
Location : deleteFromDisk
Killed by : none
removed call to com/renomad/minum/utils/IFileUtils::writeString → TIMED_OUT

226

1.1
Location : loadDataFromDisk
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
negated conditional → KILLED

227

1.1
Location : loadDataFromDisk
Killed by : none
removed call to com/renomad/minum/database/DbFileConverter::convertFolderStructureToDbClassic → TIMED_OUT

230

1.1
Location : loadDataFromDisk
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
negated conditional → KILLED

235

1.1
Location : loadDataFromDisk
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
removed call to com/renomad/minum/database/Db::walkAndLoad → KILLED

243

1.1
Location : lambda$walkAndLoad$7
Killed by : none
negated conditional → TIMED_OUT

2.2
Location : lambda$walkAndLoad$7
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
replaced boolean return with true for com/renomad/minum/database/Db::lambda$walkAndLoad$7 → KILLED

244

1.1
Location : lambda$walkAndLoad$7
Killed by : none
negated conditional → TIMED_OUT

247

1.1
Location : walkAndLoad
Killed by : none
removed call to com/renomad/minum/database/Db::readAndDeserialize → TIMED_OUT

258

1.1
Location : readAndDeserialize
Killed by : com.renomad.minum.database.FindingsDatabaseTests
negated conditional → KILLED

261

1.1
Location : readAndDeserialize
Killed by : com.renomad.minum.database.FindingsDatabaseTests
negated conditional → KILLED

270

1.1
Location : readAndDeserialize
Killed by : none
negated conditional → TIMED_OUT

284

1.1
Location : readAndDeserialize
Killed by : none
removed call to com/renomad/minum/database/Db::addToIndexes → TIMED_OUT

295

1.1
Location : values
Killed by : none
negated conditional → TIMED_OUT

297

1.1
Location : values
Killed by : none
replaced return value with Collections.emptyList for com/renomad/minum/database/Db::values → TIMED_OUT

309

1.1
Location : loadData
Killed by : none
removed call to java/util/concurrent/locks/ReentrantLock::lock → TIMED_OUT

311

1.1
Location : loadData
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
negated conditional → KILLED

320

1.1
Location : lambda$loadData$9
Killed by : com.renomad.minum.database.FindingsDatabaseTests
replaced return value with Collections.emptyMap for com/renomad/minum/database/Db::lambda$loadData$9 → KILLED

2.2
Location : loadData
Killed by : none
removed call to java/util/Map::replaceAll → TIMED_OUT

323

1.1
Location : loadData
Killed by : none
removed call to com/renomad/minum/database/Db::loadDataFromDisk → TIMED_OUT

326

1.1
Location : loadData
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
replaced return value with null for com/renomad/minum/database/Db::loadData → KILLED

330

1.1
Location : loadData
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
removed call to java/util/concurrent/locks/ReentrantLock::unlock → KILLED

363

1.1
Location : registerIndex
Killed by : none
negated conditional → TIMED_OUT

368

1.1
Location : registerIndex
Killed by : none
replaced return value with null for com/renomad/minum/database/Db::registerIndex → TIMED_OUT

382

1.1
Location : getIndexedData
Killed by : none
negated conditional → TIMED_OUT

383

1.1
Location : getIndexedData
Killed by : none
replaced return value with Collections.emptyList for com/renomad/minum/database/Db::getIndexedData → TIMED_OUT

398

1.1
Location : stop
Killed by : none
removed call to com/renomad/minum/database/Db::stop → TIMED_OUT

407

1.1
Location : stop
Killed by : none
removed call to com/renomad/minum/state/Context::removeFromPaths → TIMED_OUT

408

1.1
Location : stop
Killed by : none
removed call to com/renomad/minum/queue/AbstractActionQueue::stop → TIMED_OUT

Active mutators

Tests examined


Report generated by PIT 1.17.0