/** * Logback: the reliable, generic, fast and flexible logging framework. * Copyright (C) 1999-2015, QOS.ch. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. */ package ch.qos.logback.core; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import ch.qos.logback.core.testUtil.EnvUtilForTests; import org.junit.After; import org.junit.Before; import org.junit.Test; import ch.qos.logback.core.encoder.EchoEncoder; import ch.qos.logback.core.testUtil.RandomUtil; import ch.qos.logback.core.util.ResilienceUtil; import ch.qos.logback.core.util.StatusPrinter; public class FileAppenderResilience_AS_ROOT_Test { static String MOUNT_POINT = "/mnt/loop/"; static String LONG_STR = " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; static String PATH_LOOPFS_SCRIPT = "/home/ceki/java/logback/logback-core/src/test/loopfs.sh"; enum LoopFSCommand { setup, shake, teardown; } Context context = new ContextBase(); int diff = RandomUtil.getPositiveInt(); String outputDirStr = MOUNT_POINT + "resilience-" + diff + "/"; String logfileStr = outputDirStr + "output.log"; FileAppender<Object> fa = new FileAppender<Object>(); static boolean isConformingHost() { return EnvUtilForTests.isLocalHostNameInList(new String[] { "haro" }); } @Before public void setUp() throws IOException, InterruptedException { if (!isConformingHost()) { return; } Process p = runLoopFSScript(LoopFSCommand.setup); p.waitFor(); dump("/tmp/loopfs.log"); fa.setContext(context); File outputDir = new File(outputDirStr); outputDir.mkdirs(); System.out.println("FileAppenderResilienceTest output dir [" + outputDirStr + "]"); fa.setName("FILE"); fa.setEncoder(new EchoEncoder<Object>()); fa.setFile(logfileStr); fa.start(); } void dump(String file) throws IOException { FileInputStream fis = null; try { fis = new FileInputStream(file); int r; while ((r = fis.read()) != -1) { char c = (char) r; System.out.print(c); } } finally { if (fis != null) { fis.close(); } } } @After public void tearDown() throws IOException, InterruptedException { if (!isConformingHost()) { return; } StatusPrinter.print(context); fa.stop(); Process p = runLoopFSScript(LoopFSCommand.teardown); p.waitFor(); System.out.println("Tearing down"); } static int TOTAL_DURATION = 5000; static int NUM_STEPS = 500; static int DELAY = TOTAL_DURATION / NUM_STEPS; @Test public void go() throws IOException, InterruptedException { if (!isConformingHost()) { return; } Process p = runLoopFSScript(LoopFSCommand.shake); for (int i = 0; i < NUM_STEPS; i++) { fa.append(String.valueOf(i) + LONG_STR); Thread.sleep(DELAY); } p.waitFor(); // the extrernal script has the file system ready for IO 50% of the time double bestCase = 0.5; ResilienceUtil.verify(logfileStr, "^(\\d{1,3}) x*$", NUM_STEPS, bestCase * 0.6); System.out.println("Done go"); } // the loopfs script is tightly coupled with the host machine // it needs to be Unix, with sudo privileges granted to the script Process runLoopFSScript(LoopFSCommand cmd) throws IOException, InterruptedException { // causing a NullPointerException is better than locking the whole // machine which the next operation can and will do. if (!isConformingHost()) { return null; } ProcessBuilder pb = new ProcessBuilder(); pb.command("/usr/bin/sudo", PATH_LOOPFS_SCRIPT, cmd.toString()); return pb.start(); } }