LoggingActionQueue.java

1
package com.renomad.minum.logging;
2
3
import com.renomad.minum.queue.AbstractActionQueue;
4
import com.renomad.minum.queue.ActionQueue;
5
import com.renomad.minum.state.Constants;
6
import com.renomad.minum.utils.*;
7
8
import java.util.Map;
9
import java.util.concurrent.*;
10
11
/**
12
 * This class is very similar to {@link ActionQueue} but is
13
 * focused on Logging.
14
 * <p>
15
 *     It is necessary to create independent classes for logging to avoid circular dependencies
16
 * </p>
17
 */
18
final class LoggingActionQueue implements AbstractActionQueue {
19
    private final String name;
20
    private final ExecutorService executorService;
21
    private final LinkedBlockingQueue<RunnableWithDescription> queue;
22
    private Thread queueThread;
23
    private boolean stop = false;
24
    private boolean isStoppedStatus = false;
25
    private final Map<LoggingLevel, Boolean> enabledLogLevels;
26
27
    LoggingActionQueue(String name, ExecutorService executorService, Constants constants) {
28
        this.name = name;
29
        this.executorService = executorService;
30
        this.queue = new LinkedBlockingQueue<>();
31
        this.enabledLogLevels = Logger.convertToMap(constants.logLevels);
32
    }
33
34
    // Regarding the InfiniteLoopStatement - indeed, we expect that the while loop
35
    // below is an infinite loop unless there's an exception thrown, that is what it is.
36
    @Override
37
    @SuppressWarnings("InfiniteLoopStatement")
38
    public AbstractActionQueue initialize() {
39
        Runnable centralLoop = () -> {
40
            Thread.currentThread().setName(name);
41
            this.queueThread = Thread.currentThread();
42
            try {
43
                while (true) {
44
                    runAction(queue.take());
45
                }
46
            } catch (InterruptedException ex) {
47
                /*
48
                this is what we expect to happen.
49
                once this happens, we just continue on.
50
                this only gets called when we are trying to shut everything
51
                down cleanly
52
                 */
53
                Logger.logHelper(() -> String.format("%s LoggingActionQueue for %s is stopped.%n", TimeUtils.getTimestampIsoInstant(), name), LoggingLevel.DEBUG, enabledLogLevels, this);
54
                Thread.currentThread().interrupt();
55
            }
56
        };
57
        executorService.submit(centralLoop);
58 1 1. initialize : replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::initialize → KILLED
        return this;
59
    }
60
61
    static void runAction(RunnableWithDescription action) {
62 1 1. runAction : removed call to com/renomad/minum/utils/RunnableWithDescription::run → KILLED
        action.run();
63
    }
64
65
    /**
66
     * Adds something to the queue to be processed.
67
     */
68
    @Override
69
    public void enqueue(String description, ThrowingRunnable action) {
70 1 1. enqueue : negated conditional → KILLED
        if (! stop) {
71
            queue.add(new RunnableWithDescription(action, description));
72
        }
73
    }
74
75
    /**
76
     * Stops the action queue
77
     * @param count how many loops to wait before we crash it closed
78
     * @param sleepTime how long to wait in milliseconds between loops
79
     */
80
    @Override
81
    public void stop(int count, int sleepTime) {
82
        Logger.logHelper(() -> String.format("%s Stopping queue %s%n", TimeUtils.getTimestampIsoInstant(), this), LoggingLevel.DEBUG, enabledLogLevels, this);
83
        stop = true;
84 2 1. stop : changed conditional boundary → TIMED_OUT
2. stop : negated conditional → TIMED_OUT
        for (int i = 0; i < count; i++) {
85 1 1. stop : negated conditional → TIMED_OUT
            if (queue.isEmpty()) return;
86
            Logger.logHelper(() -> String.format("%s Queue not yet empty, has %d elements. waiting...%n", TimeUtils.getTimestampIsoInstant(), queue.size()), LoggingLevel.DEBUG, enabledLogLevels, this);
87
            MyThread.sleep(sleepTime);
88
        }
89
        isStoppedStatus = true;
90
        Logger.logHelper(() -> String.format("%s Queue %s has %d elements left but we're done waiting.  Queue toString: %s",TimeUtils.getTimestampIsoInstant(), this, queue.size(), queue), LoggingLevel.DEBUG, enabledLogLevels, this);
91
    }
92
93
    /**
94
     * This will prevent any new actions being
95
     * queued (by setting the stop flag to true and thus
96
     * causing an exception to be thrown
97
     * when a call is made to [enqueue]) and will
98
     * block until the queue is empty.
99
     */
100
    @Override
101
    public void stop() {
102
        stop(5, 20);
103
    }
104
105
    public Thread getQueueThread() {
106 1 1. getQueueThread : replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueueThread → KILLED
        return queueThread;
107
    }
108
109
    @Override
110
    public LinkedBlockingQueue<RunnableWithDescription> getQueue() {
111 1 1. getQueue : replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueue → KILLED
        return queue;
112
    }
113
114
    @Override
115
    public String toString() {
116 1 1. toString : replaced return value with "" for com/renomad/minum/logging/LoggingActionQueue::toString → KILLED
        return this.name;
117
    }
118
119
    @Override
120
    public boolean isStopped() {
121 2 1. isStopped : replaced boolean return with false for com/renomad/minum/logging/LoggingActionQueue::isStopped → KILLED
2. isStopped : replaced boolean return with true for com/renomad/minum/logging/LoggingActionQueue::isStopped → KILLED
        return isStoppedStatus;
122
    }
123
}

Mutations

58

1.1
Location : initialize
Killed by : com.renomad.minum.web.RequestTests.test_Request_ToString(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::initialize → KILLED

62

1.1
Location : runAction
Killed by : com.renomad.minum.logging.LoggingActionQueueTests.testErrorWhileRunningAction(com.renomad.minum.logging.LoggingActionQueueTests)
removed call to com/renomad/minum/utils/RunnableWithDescription::run → KILLED

70

1.1
Location : enqueue
Killed by : com.renomad.minum.logging.LoggingActionQueueTests.testGetQueue(com.renomad.minum.logging.LoggingActionQueueTests)
negated conditional → KILLED

84

1.1
Location : stop
Killed by : none
changed conditional boundary → TIMED_OUT

2.2
Location : stop
Killed by : none
negated conditional → TIMED_OUT

85

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

106

1.1
Location : getQueueThread
Killed by : com.renomad.minum.logging.LoggingActionQueueTests.testGetQueueThread(com.renomad.minum.logging.LoggingActionQueueTests)
replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueueThread → KILLED

111

1.1
Location : getQueue
Killed by : com.renomad.minum.logging.LoggingActionQueueTests.testGetQueue(com.renomad.minum.logging.LoggingActionQueueTests)
replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueue → KILLED

116

1.1
Location : toString
Killed by : com.renomad.minum.web.RequestTests.test_Request_ToString(com.renomad.minum.web.RequestTests)
replaced return value with "" for com/renomad/minum/logging/LoggingActionQueue::toString → KILLED

121

1.1
Location : isStopped
Killed by : com.renomad.minum.web.FullSystemTests.testFullSystem_EdgeCase_InstantlyClosed(com.renomad.minum.web.FullSystemTests)
replaced boolean return with false for com/renomad/minum/logging/LoggingActionQueue::isStopped → KILLED

2.2
Location : isStopped
Killed by : com.renomad.minum.web.FullSystemTests.testFullSystem_EdgeCase_InstantlyClosed(com.renomad.minum.web.FullSystemTests)
replaced boolean return with true for com/renomad/minum/logging/LoggingActionQueue::isStopped → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0