1 package ch.qos.logback.classic;
2
3 import java.util.concurrent.CyclicBarrier;
4
5 import org.junit.jupiter.api.Disabled;
6 import org.junit.jupiter.api.Test;
7
8 import ch.qos.logback.core.contention.AbstractMultiThreadedHarness;
9 import ch.qos.logback.core.contention.RunnableWithCounterAndDone;
10 import ch.qos.logback.core.status.testUtil.StatusChecker;
11 import org.junit.jupiter.api.Timeout;
12
13 @Disabled
14 public class LoggerContextConcurrentResetTest {
15 static int CONCURRENT_RESET_THREAD_COUNT = 10;
16
17
18 @Test
19 @Timeout(value = 1)
20 public void concurrentReset() throws InterruptedException {
21 LoggerContext loggerContext = new LoggerContext();
22 CyclicBarrier cyclicBarrier = new CyclicBarrier(CONCURRENT_RESET_THREAD_COUNT);
23 StatusChecker statusChecker = new StatusChecker(loggerContext);
24 int desiredResetCount = 100;
25 RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(loggerContext, cyclicBarrier);
26 Harness harness = new Harness((Resetter) runnableArray[0], desiredResetCount);
27 harness.execute(runnableArray);
28 statusChecker.assertIsErrorFree();
29 }
30
31 class Harness extends AbstractMultiThreadedHarness {
32 int desiredResetCount;
33 Resetter resetter;
34
35 Harness(Resetter resetter, int desiredResetCount) {
36 this.resetter = resetter;
37 this.desiredResetCount = desiredResetCount;
38 }
39
40 public void waitUntilEndCondition() throws InterruptedException {
41 while (resetter.getCounter() < desiredResetCount) {
42 Thread.yield();
43 }
44 }
45 }
46
47 static class GetLoggerRunnable extends RunnableWithCounterAndDone {
48
49 final int burstLength = 30;
50 LoggerContext loggerContext;
51 CyclicBarrier cyclicBarrier;
52 String nameSuffix;
53
54 GetLoggerRunnable(LoggerContext loggerContext, CyclicBarrier cyclicBarrier, String nameSuffix) {
55 this.loggerContext = loggerContext;
56 this.cyclicBarrier = cyclicBarrier;
57 this.nameSuffix = nameSuffix;
58 }
59
60 public void run() {
61 try {
62 cyclicBarrier.await();
63 } catch (Exception e) {
64 }
65
66 while (!isDone()) {
67 long i = counter % burstLength;
68 loggerContext.getLogger("org.bla." + nameSuffix + ".x" + i);
69 counter++;
70 if (i == 0) {
71 Thread.yield();
72 }
73 }
74 }
75 }
76
77 static class Resetter extends RunnableWithCounterAndDone {
78 LoggerContext loggerContext;
79 CyclicBarrier cyclicBarrier;
80 public int resetCount = 0;
81
82 Resetter(LoggerContext loggerContext, CyclicBarrier cyclicBarrier) {
83 this.loggerContext = loggerContext;
84 this.cyclicBarrier = cyclicBarrier;
85 }
86
87 public void run() {
88 try {
89 cyclicBarrier.await();
90 } catch (Exception e) {
91 }
92 while (!isDone()) {
93 loggerContext.reset();
94 counter++;
95 Thread.yield();
96 }
97 }
98 }
99
100 private RunnableWithCounterAndDone[] buildRunnableArray(LoggerContext loggerContext, CyclicBarrier cyclicBarrier) {
101 RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[CONCURRENT_RESET_THREAD_COUNT];
102 rArray[0] = new Resetter(loggerContext, cyclicBarrier);
103 for (int i = 1; i < CONCURRENT_RESET_THREAD_COUNT; i++) {
104 rArray[i] = new GetLoggerRunnable(loggerContext, cyclicBarrier, "mouse-" + i);
105 }
106 return rArray;
107 }
108 }