com.hellblazer.process.JavaProcessTest.java Source code

Java tutorial

Introduction

Here is the source code for com.hellblazer.process.JavaProcessTest.java

Source

/** (C) Copyright 2011-2014 Chiral Behaviors, All Rights Reserved
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package com.hellblazer.process;

import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;

import org.apache.commons.io.input.Tailer;
import org.apache.commons.io.input.TailerListener;
import org.apache.commons.io.input.TailerListenerAdapter;

import com.hellblazer.process.impl.JavaProcessImpl;
import com.hellblazer.process.impl.ManagedProcessFactoryImpl;
import com.hellblazer.utils.Condition;
import com.hellblazer.utils.Utils;

/**
 * @author Hal Hildebrand
 * 
 */
public class JavaProcessTest extends ProcessTest {
    protected static final String TEST_DIR = "test-dirs/java-process-test";
    protected static final String TEST_JAR = "test.jar";
    protected File testDir;
    MBeanServerConnection connection;
    ManagedProcessFactoryImpl processFactory = new ManagedProcessFactoryImpl();

    public void testClassExecution() throws Exception {
        copyTestClassFile();
        JavaProcess process = new JavaProcessImpl(processFactory.create());
        process.setArguments(new String[] { "-echo", "foo", "bar", "baz" });
        process.setJavaClass(HelloWorld.class.getCanonicalName());
        assertNull("No jar file set", process.getJarFile());

        try {
            launchProcess(process);

            assertEquals("Process exited normally", 0, process.waitFor());
            assertTrue("Process not active", !process.isActive());

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getStdErr()))) {
                validateExpectedEchoLines(reader);
            }

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getStdOut()))) {
                assertEquals(HelloWorld.STARTUP_MSG, reader.readLine());
                validateExpectedEchoLines(reader);
            }
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
    }

    public void testExitValue() throws Exception {
        copyTestClassFile();
        JavaProcess process = new JavaProcessImpl(processFactory.create());
        process.setArguments(new String[] { "-errno", "66" });
        process.setJavaClass(HelloWorld.class.getCanonicalName());
        process.setDirectory(testDir);
        process.setJavaExecutable(javaBin);

        try {
            launchProcess(process);
            assertEquals("Process exited abnormally", 66, process.waitFor());
            assertTrue("Process not active", !process.isActive());
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
    }

    public void testJarExecution() throws Exception {
        copyTestJarFile();
        JavaProcess process = new JavaProcessImpl(processFactory.create());
        process.setArguments(new String[] { "-echo", "hello" });
        process.setJarFile(new File(testDir, TEST_JAR));
        assertNull("No java class set", process.getJavaClass());

        try {
            launchProcess(process);
            assertEquals("Process exited normally", 0, process.waitFor());
            assertTrue("Process not active", !process.isActive());
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
    }

    public void testLocalMBeanServerConnection() throws Exception {
        copyTestClassFile();
        final JavaProcess process = new JavaProcessImpl(processFactory.create());
        int sleepTime = 60000;
        process.setArguments(new String[] { "-jmx", Integer.toString(sleepTime) });
        process.setJavaClass(HelloWorld.class.getCanonicalName());
        process.setDirectory(testDir);
        process.setJavaExecutable(javaBin);

        try {
            launchProcess(process);

            Condition condition = new Condition() {
                @Override
                public boolean isTrue() {
                    try {
                        connection = process.getLocalMBeanServerConnection(HelloWorld.JMX_CONNECTION_NAME);
                        return true;
                    } catch (ConnectException e) {
                        return false;
                    } catch (NoLocalJmxConnectionException e) {
                        return false;
                    } catch (IOException e) {
                        e.printStackTrace();
                        System.out.flush();
                        System.err.flush();
                        System.out.println("error");
                        fail("error retrieving JMX connection: " + e);
                        return false;
                    }
                }

            };

            assertTrue("JMX connection established", Utils.waitForCondition(60 * 1000, condition));

            Set<ObjectName> names = connection.queryNames(null, null);
            assertTrue(names.size() > 1);
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
        assertTrue("Process not active", !process.isActive());
    }

    public void testOnDemandInputOutputStreams() throws Exception {
        copyTestClassFile();
        JavaProcess process = new JavaProcessImpl(processFactory.create());
        process.setArguments(new String[] { "-loglines" });
        process.setJavaClass(HelloWorld.class.getCanonicalName());
        process.setDirectory(testDir);
        process.setJavaExecutable(javaBin);

        // Try it before launching process
        try {
            process.getStdOutTail(200);
            fail("Expected an illegal thread state exception because the process hasn't started yet");
        } catch (IllegalThreadStateException e) {
            System.out.println("Caught expected exception : " + e.getMessage());
        }

        try {
            process.getStdErrTail(200);
            fail("Expected an illegal thread state exception because the process hasn't started yet");
        } catch (IllegalThreadStateException e) {
            System.out.println("Caught expected exception : " + e.getMessage());
        }

        try {
            launchProcess(process);

            String stdout = process.getStdOutTail(200).trim();
            assertTrue(stdout.startsWith("Line #4800"));
            assertTrue(stdout.endsWith("Line #4999"));

            String stderr = process.getStdErrTail(200).trim();
            assertTrue(stderr.startsWith("Line #4800"));
            assertTrue(stderr.endsWith("Line #4999"));

        } finally {
            if (process != null) {
                process.destroy();
            }
        }
    }

    public void testTailStdInputOutputStreams() throws Exception {
        final List<String> lines = new CopyOnWriteArrayList<>();
        TailerListener listener = new TailerListenerAdapter() {
            @Override
            public void handle(String line) {
                lines.add(line);
            }
        };

        copyTestClassFile();
        JavaProcess process = new JavaProcessImpl(processFactory.create());
        String testLine = "hello";
        process.setArguments(new String[] { "-readln", testLine });
        process.setJavaClass(HelloWorld.class.getCanonicalName());
        process.setDirectory(testDir);
        process.setJavaExecutable(javaBin);

        Tailer tailer = null;
        try {
            launchProcess(process);
            tailer = process.tailStdOut(listener);

            try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(process.getStdIn()))) {
                writer.println(testLine);
                writer.flush();
            }

            assertEquals("Process exited normally", 0, process.waitFor());
            assertTrue("Process not active", !process.isActive());
            Utils.waitForCondition(1000, new Condition() {
                @Override
                public boolean isTrue() {
                    return lines.size() > 1;
                }
            });

            assertEquals(2, lines.size());
            assertEquals(testLine, lines.get(1));

            tailer.stop();
        } finally {
            if (tailer != null) {
                tailer.stop();
            }

            process.destroy();
        }
    }

    private void launchProcess(JavaProcess process) throws IOException {
        process.setDirectory(testDir);
        process.setJavaExecutable(javaBin);

        setupJavaClasspath(process);
        process.start();
        assertTrue("Expected successful process start",
                new ProcessStartWatcher(process).waitForSuccessfulStartup());

        // Give the process a chance to do its thing before launching into
        // evaluating output
        try {
            System.out.println("Waiting for process before evaluating output...");
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void validateExpectedEchoLines(BufferedReader reader) throws IOException {
        String line;
        line = reader.readLine();
        assertEquals("foo", line);
        line = reader.readLine();
        assertEquals("bar", line);
        line = reader.readLine();
        assertEquals("baz", line);
        line = reader.readLine();
        assertNull(line);
    }

    protected void copyTestClassFile() throws Exception {
        String classFileName = HelloWorld.class.getCanonicalName().replace('.', '/') + ".class";
        URL classFile = getClass().getResource("/" + classFileName);
        assertNotNull(classFile);
        File copiedFile = new File(testDir, classFileName);
        assertTrue(copiedFile.getParentFile().mkdirs());
        FileOutputStream out = new FileOutputStream(copiedFile);
        InputStream in = classFile.openStream();
        byte[] buffer = new byte[1024];
        for (int read = in.read(buffer); read != -1; read = in.read(buffer)) {
            out.write(buffer, 0, read);
        }
        in.close();
        out.close();
    }

    protected void copyTestJarFile() throws Exception {
        String classFileName = HelloWorld.class.getCanonicalName().replace('.', '/') + ".class";
        URL classFile = getClass().getResource("/" + classFileName);
        assertNotNull(classFile);

        Manifest manifest = new Manifest();
        Attributes attributes = manifest.getMainAttributes();
        attributes.putValue("Manifest-Version", "1.0");
        attributes.putValue("Main-Class", HelloWorld.class.getCanonicalName());

        FileOutputStream fos = new FileOutputStream(new File(testDir, TEST_JAR));
        JarOutputStream jar = new JarOutputStream(fos, manifest);
        JarEntry entry = new JarEntry(classFileName);
        jar.putNextEntry(entry);
        InputStream in = classFile.openStream();
        byte[] buffer = new byte[1024];
        for (int read = in.read(buffer); read != -1; read = in.read(buffer)) {
            jar.write(buffer, 0, read);
        }
        in.close();
        jar.closeEntry();
        jar.close();
    }

    @Override
    protected void setUp() {
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
        System.setProperty("javax.net.debug", "all");
        Utils.initializeDirectory(TEST_DIR);
        testDir = new File(TEST_DIR);
    }
}