-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathThreadPoolTest.java
More file actions
143 lines (118 loc) · 4.49 KB
/
ThreadPoolTest.java
File metadata and controls
143 lines (118 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package com.taskscheduler;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class ThreadPoolTest {
private ThreadPool pool;
@BeforeEach
void setUp() {
pool = new ThreadPool(3, 20);
}
@AfterEach
void tearDown() {
if (!pool.isShutdown()) {
pool.shutdown();
}
}
@Test
@Order(1)
@DisplayName("Tasks are executed by worker threads")
void testTasksAreExecuted() throws InterruptedException {
AtomicInteger counter = new AtomicInteger(0);
CountDownLatch latch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
pool.submit("Task-" + i, () -> {
counter.incrementAndGet();
latch.countDown();
});
}
assertTrue(latch.await(3, TimeUnit.SECONDS), "All tasks should complete within 3s");
assertEquals(5, counter.get());
}
@Test
@Order(2)
@DisplayName("Stats track completed tasks correctly")
void testStatsTracking() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
pool.submit("StatTask-" + i, () -> {
try { Thread.sleep(50); } catch (InterruptedException e) {}
latch.countDown();
});
}
latch.await(3, TimeUnit.SECONDS);
Thread.sleep(100); // allow stats to settle
assertEquals(3, pool.getStats().getTotalCompleted());
assertEquals(0, pool.getStats().getTotalFailed());
}
@Test
@Order(3)
@DisplayName("Failed tasks are recorded in stats")
void testFailedTaskStats() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
pool.submit("FailingTask", () -> {
latch.countDown();
throw new RuntimeException("Intentional failure");
});
latch.await(3, TimeUnit.SECONDS);
Thread.sleep(100);
assertEquals(1, pool.getStats().getTotalFailed());
}
@Test
@Order(4)
@DisplayName("High priority tasks have higher priority level than low")
void testTaskPriorityOrdering() {
Task low = new Task("Low", () -> {}, Task.Priority.LOW);
Task medium = new Task("Med", () -> {}, Task.Priority.MEDIUM);
Task high = new Task("High", () -> {}, Task.Priority.HIGH);
// High should come before medium and low (compareTo returns negative = comes first)
assertTrue(high.compareTo(low) < 0);
assertTrue(high.compareTo(medium) < 0);
assertTrue(medium.compareTo(low) < 0);
}
@Test
@Order(5)
@DisplayName("Pool rejects tasks after shutdown")
void testRejectionAfterShutdown() throws InterruptedException {
pool.shutdown();
boolean accepted = pool.submit("LateTask", () -> {});
assertFalse(accepted, "Pool should reject tasks after shutdown");
}
@Test
@Order(6)
@DisplayName("Queue rejects tasks when at capacity")
void testQueueCapacity() {
ThreadPool smallPool = new ThreadPool(1, 3);
// Flood with slow tasks to fill the queue
for (int i = 0; i < 10; i++) {
smallPool.submit("Task-" + i, () -> {
try { Thread.sleep(500); } catch (InterruptedException e) {}
});
}
// Queue should be bounded — not all tasks accepted
assertTrue(smallPool.getQueueSize() <= 3);
smallPool.shutdownNow();
}
@Test
@Order(7)
@DisplayName("Multiple tasks execute concurrently across workers")
void testConcurrentExecution() throws InterruptedException {
AtomicInteger concurrent = new AtomicInteger(0);
AtomicInteger maxConcurrent = new AtomicInteger(0);
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
pool.submit("ConcurrentTask-" + i, () -> {
int current = concurrent.incrementAndGet();
maxConcurrent.updateAndGet(max -> Math.max(max, current));
try { Thread.sleep(200); } catch (InterruptedException e) {}
concurrent.decrementAndGet();
latch.countDown();
});
}
latch.await(3, TimeUnit.SECONDS);
assertTrue(maxConcurrent.get() > 1, "Tasks should run concurrently");
}
}