Package com.splunk

Source Code of com.splunk.SDKTestCase$EventuallyTrueBehavior

/*
* Copyright 2012 Splunk, Inc.
*
* 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.splunk;

import junit.framework.TestCase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
* Base test case for SDK test suite.
*
* TestCase does the following actions in the various test contexts:
*
* @@Before:
*   - Read ~/.splunkrc to get host, port, user, and password to connect with.
*   - Create a Service object connected to the Splunk instance.
*
* @@After:
*   - Logout the Service object.
*/
public abstract class SDKTestCase {
    protected static final boolean WORKAROUND_KNOWN_BUGS = true;
    private static final boolean VERBOSE_PORT_SCAN = false;

    protected static Service service;
    protected List<String> installedApps;

    protected Command command;

    public static String streamToString(java.io.InputStream is) {
        Reader r = null;
        try {
            r = new InputStreamReader(is, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Your JVM does not support UTF-8!");
        }
        StringBuffer sb = new StringBuffer();
        int ch;
        try {
            while ((ch = r.read()) != -1) {
                sb.append((char)ch);
            }
        } catch (IOException ioex) {
            throw new RuntimeException(ioex.getMessage());
        }
        return sb.toString();
    }

    public void connect() {
        if (service != null) {
            service.login(service.username, service.password);
        } else {
            service = Service.connect(command.opts);
        }
    }

    @Before
    public void setUp() throws Exception {
        // If using Charles Proxy for debugging, uncomment these lines.
        //System.setProperty("https.proxyHost", "127.0.0.1");
        //System.setProperty("https.proxyPort", "8888");

        command = Command.splunk();
        connect();
        if (restartRequired()) {
            System.out.println(
                    "WARNING: Splunk was already in a state requiring a " +
                    "restart prior to running this test. Trying to recover...");
            splunkRestart();
            System.out.println("Restart complete.");
        }
        installedApps = new ArrayList<String>();
    }

    @After
    public void tearDown() throws Exception {
        if (restartRequired()) {
            Assert.fail("Test left Splunk in a state that required restart.");
        }

        // Cannot delete applications in Splunk 4.2.
        if (service.versionIsAtLeast("4.3")) {
            // We delete the apps we installed for capabilities after checking
            // for restarts that might be required, since deleting an app
            // triggers a restart (but one that we can safely ignore).
            for (String applicationName : installedApps) {
                try {
                    service.getApplications().remove(applicationName);
                } catch (HttpException e) {
                    // WORKAROUND (SPL-75224): Under Splunk 6.0 on Windows, deleting apps sometimes fails with
                    // the message "Operation completed successfully." The app is actually deleted, but it will
                    // cause tests to fail.
                    if (service.versionCompare("6.0.0") == 0 && e.getStatus() != 500) {
                        throw e;
                    }
                }
                clearRestartMessage();
            }
        }
    }
   
    // === Temporary Names ===

    protected static String createTimestamp() {
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss");
        return dateFormat.format(new Date());
    }

    protected static String createTemporaryName() {
        return "delete-me-" + UUID.randomUUID().toString();
    }

    public static InputStream openResource(String path) {
        if (path.startsWith("splunk_search:")) {
            path = path.substring("splunk_search:".length());

            String[] pathComponents = path.split("/");
            String searchType = pathComponents[0];
            String outputMode = pathComponents[1];
            String search = pathComponents[2];

            Args resultsArgs = new Args("output_mode", outputMode);
            if (searchType.equals("blocking")) {
                Job job = service.getJobs().create(
                        search,
                        new Args("exec_mode", "blocking"));
                return job.getResults(resultsArgs);
            }
            else if (searchType.equals("oneshot")) {
                return service.oneshotSearch(search, resultsArgs);
            }
            else {
                throw new IllegalArgumentException(
                        "Unrecognized search type: " + searchType);
            }
        }

        InputStream input = ResourceRoot.class.getResourceAsStream(path);
        Assert.assertNotNull("Could not open " + path, input);
        return input;
    }

    // === Asserts ===

    public static abstract class EventuallyTrueBehavior {
        public int tries;
        public int pauseTime;

        {
            tries = 10;
            pauseTime = 1000;
        }

        public String timeoutMessage = "Test timed out before true.";
        public abstract boolean predicate();
    }

    public static boolean assertEventuallyTrue(EventuallyTrueBehavior behavior) {
        int remainingTries = behavior.tries;
        while (remainingTries > 0) {
            boolean succeeded = behavior.predicate();
            if (succeeded) {
                return true;
            } else {
                remainingTries -= 1;
                try {
                    Thread.sleep(behavior.pauseTime);
                } catch (InterruptedException e) {}
            }
        }
        Assert.fail(behavior.timeoutMessage);
        return false;
    }
   
    // === Test Data Installation ===

    public boolean hasTestData() {
        String collectionName = "sdk-app-collection";
        return service.getApplications().containsKey("sdk-app-collection");
    }

    public void installApplicationFromTestData(String applicationName) {
        String collectionName = "sdk-app-collection";
        if (!service.getApplications().containsKey("sdk-app-collection")) {
            throw new TestDataNotInstalledException();
        }

        String splunkHome = service.getSettings().getSplunkHome();

        // This is the filename separator sequence for splunkd, not
        // the Splunk SDK. Therefore we can't just use File.separator here.
        String separator;
        if (splunkHome.contains("/") && splunkHome.contains("\\")) {
            // Windows - allows mixed paths
            separator = "\\";
        } else if (splunkHome.contains("/")) {
            // Unix or Mac OS X
            separator = "/";
        } else if (splunkHome.contains("\\")) {
            // Windows
            separator = "\\";
        } else {
            throw new RuntimeException(
                    "Couldn't determine what the path separator was " +
                    "for splunkd.");
        }

        String[] pathComponents = {splunkHome, "etc", "apps",
                collectionName, "build", applicationName + ".tar"};
        String appPath = Util.join(separator, pathComponents);

        Args args = new Args();
        args.put("name", appPath);
        args.put("update", "1");
        service.post("apps/appinstall", args);
       
        installedApps.add(applicationName);
    }
   
    // === Restarts ===

    public void clearRestartMessage() {
        final MessageCollection messages = service.getMessages();
        if (messages.containsKey("restart_required")) {
            messages.remove("restart_required");
            assertEventuallyTrue(new EventuallyTrueBehavior() {
                @Override public boolean predicate() {
                    messages.refresh();
                    return !messages.containsKey("restart_required");
                }
            });
        }
    }

    public boolean restartRequired() {
        for (Message message : service.getMessages().values()) {
            if (message.containsKey("restart_required")) {
                return true;
            }
        }
        return false;
    }
   
    private void markAsRestartRequired() {
        service.getMessages().create(
                "restart_required",
                "Unit test called markAsRestartRequired().");
    }

    public void splunkRestart() {
        if (!restartRequired()) {
            Assert.fail("Asked to restart Splunk when no restart was required.");
        }
        uncheckedSplunkRestart();
    }

    public void uncheckedSplunkRestart() {
        ResponseMessage response = service.restart();
        if (response.getStatus() != 200) {
            Assert.fail("Restart command failed: " + response.getContent());
        }
       
        // (This status will be cleared when Splunk actually restarts.)
        markAsRestartRequired();

        // Wait for splunkd to come back up fresh.
        // (And update 'service'.)
        assertEventuallyTrue(new EventuallyTrueBehavior() {
            {
                tries = 20;
                pauseTime = 1000;
            }
           
            @Override
            public boolean predicate() {
                try {
                    connect();
                    return !restartRequired();
                } catch (Exception e) {
                    return false;
                }
            }
        });
    }
   
    // === Misc ===
   
    protected static void sleep(int milliseconds) {
        try {
            Thread.sleep(milliseconds);
        }
        catch (InterruptedException e) {}
    }

    protected int findNextUnusedPort(int startingPort) {
        int port = startingPort;
        while (isPortInUse(port)) {
            port++;
        }
        return port;
    }

    public boolean isPortInUse(int port) {
        try {
            Socket pingSocket = new Socket();
            // On Windows, the firewall doesn't respond at all if you connect to an unbound port, so we need to
            // take lack of a connection as an empty port. Timeout is 1000ms.
            try {
                pingSocket.connect(new InetSocketAddress(service.getHost(), port), 1000);
            } catch (SocketTimeoutException ste) {
                return false;
            }
            pingSocket.close();
            if (VERBOSE_PORT_SCAN) {
                System.out.println("IN-USE(" + port + ")");
            }
            return true;
        } catch (IOException e) {
            if (VERBOSE_PORT_SCAN) {
                System.out.println("OPEN(" + port + "): " + e.getMessage());
            }
            return false;
        }
    }
   
    protected static boolean contains(String[] array, String value) {
        return Arrays.asList(array).contains(value);
    }
   
    protected static void assertEquals(String[] a1, String[] a2) {
        Assert.assertArrayEquals(a1, a2);
    }

    protected static String locateSystemLog() {
        String filename = null;
        String osName = service.getInfo().getOsName();
        if (osName.equals("Windows"))
            filename = "C:\\Windows\\WindowsUpdate.log";
        else if (osName.equals("Linux")) {
            filename = "/etc/fstab";
        }
        else if (osName.equals("Darwin")) {
            filename = "/var/log/system.log";
        } else {
            throw new RuntimeException("OS " + osName + " not recognized");
        }

        Assert.assertNotNull(filename);
        return filename;
    }
   
    protected static String joinServerPath(String[] components) {
        String separator;
        String osName = service.getInfo().getOsName();
        if (osName.equals("Windows"))
            separator = "\\";
        else if (osName.equals("Linux"))
            separator = "/";
        else if (osName.equals("Darwin")) {
            separator = "/";
        } else {
            throw new RuntimeException("OS " + osName + " not recognized");
        }
       
        return Util.join(separator, components);
    }

    protected boolean firstLineIsXmlDtd(InputStream stream) {
        InputStreamReader reader;
        try {
            reader = new InputStreamReader(stream, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new Error(e);
        }
        BufferedReader lineReader = new BufferedReader(reader);
        try {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".equals(
                    lineReader.readLine()
            );
        } catch (IOException e) {
            Assert.fail(e.toString());
            return false;
        }
    }
}
TOP

Related Classes of com.splunk.SDKTestCase$EventuallyTrueBehavior

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.