View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core;
15  
16  import java.io.File;
17  import java.io.FileInputStream;
18  import java.io.IOException;
19  
20  import ch.qos.logback.core.testUtil.EnvUtilForTests;
21  import org.junit.After;
22  import org.junit.Before;
23  import org.junit.Test;
24  
25  import ch.qos.logback.core.encoder.EchoEncoder;
26  import ch.qos.logback.core.testUtil.RandomUtil;
27  import ch.qos.logback.core.util.ResilienceUtil;
28  import ch.qos.logback.core.util.StatusPrinter;
29  
30  public class FileAppenderResilience_AS_ROOT_Test {
31  
32      static String MOUNT_POINT = "/mnt/loop/";
33  
34      static String LONG_STR = " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
35  
36      static String PATH_LOOPFS_SCRIPT = "/home/ceki/java/logback/logback-core/src/test/loopfs.sh";
37  
38      enum LoopFSCommand {
39          setup, shake, teardown;
40      }
41  
42      Context context = new ContextBase();
43      int diff = RandomUtil.getPositiveInt();
44      String outputDirStr = MOUNT_POINT + "resilience-" + diff + "/";
45      String logfileStr = outputDirStr + "output.log";
46  
47      FileAppender<Object> fa = new FileAppender<Object>();
48  
49      static boolean isConformingHost() {
50          return EnvUtilForTests.isLocalHostNameInList(new String[] { "haro" });
51      }
52  
53      @Before
54      public void setUp() throws IOException, InterruptedException {
55          if (!isConformingHost()) {
56              return;
57          }
58          Process p = runLoopFSScript(LoopFSCommand.setup);
59          p.waitFor();
60  
61          dump("/tmp/loopfs.log");
62  
63          fa.setContext(context);
64          File outputDir = new File(outputDirStr);
65          outputDir.mkdirs();
66          System.out.println("FileAppenderResilienceTest output dir [" + outputDirStr + "]");
67  
68          fa.setName("FILE");
69          fa.setEncoder(new EchoEncoder<Object>());
70          fa.setFile(logfileStr);
71          fa.start();
72      }
73  
74      void dump(String file) throws IOException {
75          FileInputStream fis = null;
76          try {
77              fis = new FileInputStream(file);
78              int r;
79              while ((r = fis.read()) != -1) {
80                  char c = (char) r;
81                  System.out.print(c);
82              }
83          } finally {
84              if (fis != null) {
85                  fis.close();
86              }
87          }
88      }
89  
90      @After
91      public void tearDown() throws IOException, InterruptedException {
92          if (!isConformingHost()) {
93              return;
94          }
95          StatusPrinter.print(context);
96          fa.stop();
97          Process p = runLoopFSScript(LoopFSCommand.teardown);
98          p.waitFor();
99          System.out.println("Tearing down");
100     }
101 
102     static int TOTAL_DURATION = 5000;
103     static int NUM_STEPS = 500;
104     static int DELAY = TOTAL_DURATION / NUM_STEPS;
105 
106     @Test
107     public void go() throws IOException, InterruptedException {
108         if (!isConformingHost()) {
109             return;
110         }
111         Process p = runLoopFSScript(LoopFSCommand.shake);
112         for (int i = 0; i < NUM_STEPS; i++) {
113             fa.append(String.valueOf(i) + LONG_STR);
114             Thread.sleep(DELAY);
115         }
116         p.waitFor();
117         // the extrernal script has the file system ready for IO 50% of the time
118         double bestCase = 0.5;
119         ResilienceUtil.verify(logfileStr, "^(\\d{1,3}) x*$", NUM_STEPS, bestCase * 0.6);
120         System.out.println("Done go");
121     }
122 
123     // the loopfs script is tightly coupled with the host machine
124     // it needs to be Unix, with sudo privileges granted to the script
125     Process runLoopFSScript(LoopFSCommand cmd) throws IOException, InterruptedException {
126         // causing a NullPointerException is better than locking the whole
127         // machine which the next operation can and will do.
128         if (!isConformingHost()) {
129             return null;
130         }
131         ProcessBuilder pb = new ProcessBuilder();
132         pb.command("/usr/bin/sudo", PATH_LOOPFS_SCRIPT, cmd.toString());
133         return pb.start();
134     }
135 }