1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ch.qos.logback.core.util;
16
17 import ch.qos.logback.core.Context;
18 import ch.qos.logback.core.ContextBase;
19 import ch.qos.logback.core.FileAppender;
20 import ch.qos.logback.core.encoder.EchoEncoder;
21 import ch.qos.logback.core.status.testUtil.StatusChecker;
22 import ch.qos.logback.core.testUtil.CoreTestConstants;
23 import ch.qos.logback.core.testUtil.RandomUtil;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.nio.file.Files;
30 import java.nio.file.Paths;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.concurrent.CountDownLatch;
34
35 import static org.junit.jupiter.api.Assertions.assertEquals;
36 import static org.junit.jupiter.api.Assertions.fail;
37
38 public class PrudentModeTest {
39
40 FileAppender<Object> fa = new FileAppender<Object>();
41 Context context = new ContextBase();
42
43 StatusChecker statusChecker = new StatusChecker(context);
44 int diff = RandomUtil.getPositiveInt();
45
46 String outputDirStr = CoreTestConstants.OUTPUT_DIR_PREFIX + "prudentLockTest-" + diff + "/";
47 String logfileStr = outputDirStr + "output.log";
48
49 private static final int THREAD_COUNT = 8;
50 private static final int LOOP_COUNT = 100/ THREAD_COUNT;
51
52 @BeforeEach
53 public void beforeEach() {
54 File outputDir = new File(outputDirStr);
55 if (!outputDir.mkdirs()) {
56 fail("failed to create folder " + outputDir);
57 }
58
59 fa.setContext(context);
60 fa.setName("FILE");
61 fa.setPrudent(true);
62 fa.setEncoder(new EchoEncoder<Object>());
63 fa.setFile(logfileStr);
64 fa.start();
65 }
66
67
68 @Test
69 public void assertNoOverlappingFileLockException () throws IOException {
70 CountDownLatch latch = new CountDownLatch(1);
71 List<Thread> threads = new ArrayList<>(THREAD_COUNT);
72 for (int i = 0; i < THREAD_COUNT; i++) {
73 LoggerThread thread = new LoggerThread(latch, "message from thread " + i);
74 thread.start();
75 threads.add(thread);
76 }
77 latch.countDown();
78 int i = 0;
79 for (Thread thread : threads) {
80 try {
81 thread.join();
82 } catch (InterruptedException e) {
83 e.printStackTrace();
84 }
85 }
86 StatusPrinter.print(context);
87 statusChecker.assertIsWarningOrErrorFree();
88
89 fa.stop();
90
91 File file = new File(logfileStr);
92 List<String> allLines = Files.readAllLines(file.toPath());
93 int actualLineCount = allLines.size();
94 assertEquals(LOOP_COUNT*THREAD_COUNT, actualLineCount, "unexpected line count "+actualLineCount);
95
96 }
97
98 class LoggerThread extends Thread {
99 private final CountDownLatch latch;
100 private final String message;
101
102 LoggerThread(CountDownLatch latch, String message) {
103 setDaemon(false);
104 this.latch = latch;
105 this.message = message;
106 }
107
108 @Override
109 public void run() {
110 try {
111 latch.await();
112 for (int i = 0; i < LOOP_COUNT; i++) {
113 if ((i & 0x08) == 0) {
114
115 Thread.yield();
116 }
117 PrudentModeTest.this.fa.doAppend(message + " i=" + i);
118 }
119 } catch (InterruptedException ex) {
120 Thread.currentThread().interrupt();
121 }
122 }
123
124 void delay(long millis) {
125 try {
126 Thread.sleep(millis);
127 } catch (InterruptedException e) {
128 throw new RuntimeException(e);
129 }
130 }
131 }
132 }
133