001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core; 015 016import java.io.File; 017import java.io.FileInputStream; 018import java.io.IOException; 019 020import ch.qos.logback.core.testUtil.EnvUtilForTests; 021import org.junit.After; 022import org.junit.Before; 023import org.junit.Test; 024 025import ch.qos.logback.core.encoder.EchoEncoder; 026import ch.qos.logback.core.testUtil.RandomUtil; 027import ch.qos.logback.core.util.ResilienceUtil; 028import ch.qos.logback.core.util.StatusPrinter; 029 030public class FileAppenderResilience_AS_ROOT_Test { 031 032 static String MOUNT_POINT = "/mnt/loop/"; 033 034 static String LONG_STR = " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 035 036 static String PATH_LOOPFS_SCRIPT = "/home/ceki/java/logback/logback-core/src/test/loopfs.sh"; 037 038 enum LoopFSCommand { 039 setup, shake, teardown; 040 } 041 042 Context context = new ContextBase(); 043 int diff = RandomUtil.getPositiveInt(); 044 String outputDirStr = MOUNT_POINT + "resilience-" + diff + "/"; 045 String logfileStr = outputDirStr + "output.log"; 046 047 FileAppender<Object> fa = new FileAppender<Object>(); 048 049 static boolean isConformingHost() { 050 return EnvUtilForTests.isLocalHostNameInList(new String[] { "haro" }); 051 } 052 053 @Before 054 public void setUp() throws IOException, InterruptedException { 055 if (!isConformingHost()) { 056 return; 057 } 058 Process p = runLoopFSScript(LoopFSCommand.setup); 059 p.waitFor(); 060 061 dump("/tmp/loopfs.log"); 062 063 fa.setContext(context); 064 File outputDir = new File(outputDirStr); 065 outputDir.mkdirs(); 066 System.out.println("FileAppenderResilienceTest output dir [" + outputDirStr + "]"); 067 068 fa.setName("FILE"); 069 fa.setEncoder(new EchoEncoder<Object>()); 070 fa.setFile(logfileStr); 071 fa.start(); 072 } 073 074 void dump(String file) throws IOException { 075 FileInputStream fis = null; 076 try { 077 fis = new FileInputStream(file); 078 int r; 079 while ((r = fis.read()) != -1) { 080 char c = (char) r; 081 System.out.print(c); 082 } 083 } finally { 084 if (fis != null) { 085 fis.close(); 086 } 087 } 088 } 089 090 @After 091 public void tearDown() throws IOException, InterruptedException { 092 if (!isConformingHost()) { 093 return; 094 } 095 StatusPrinter.print(context); 096 fa.stop(); 097 Process p = runLoopFSScript(LoopFSCommand.teardown); 098 p.waitFor(); 099 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}