org.chililog.server.workbench.WorkbenchServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.chililog.server.workbench.WorkbenchServiceTest.java

Source

//
// Copyright 2010 Cinch Logic Pty Ltd.
//
// http://www.chililog.com
//
// 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 org.chililog.server.workbench;

import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Random;
import java.util.TimeZone;
import java.util.UUID;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.lang.StringUtils;
import org.chililog.server.common.AppProperties;
import org.chililog.server.common.Log4JLogger;
import org.chililog.server.workbench.WorkbenchService;
import org.jboss.netty.util.internal.jzlib.JZlib;
import org.jboss.netty.util.internal.jzlib.ZStream;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Test the UI web server
 * 
 * @author vibul
 * 
 */
public class WorkbenchServiceTest {

    private static Log4JLogger _logger = Log4JLogger.getLogger(WorkbenchServiceTest.class);

    private static String _workbenchStaticFilesDirectory = null;

    @BeforeClass
    public static void classSetup() throws Exception {
        _workbenchStaticFilesDirectory = AppProperties.getInstance().getWorkbenchStaticFilesDirectory()
                + "/testdata";

        File dir = deleteDirectory(_workbenchStaticFilesDirectory);
        dir.mkdirs();

        WorkbenchService.getInstance().start();
    }

    @AfterClass
    public static void classTeardown() {
        WorkbenchService.getInstance().stop();
        deleteDirectory(_workbenchStaticFilesDirectory);
    }

    private static File deleteDirectory(String dirPath) {
        File dir = new File(dirPath);
        if (dir.exists()) {
            for (String f : dir.list()) {
                new File(dir, f).delete();
            }
            dir.delete();
        }
        return dir;
    }

    @Test
    public void testEchoGET2() throws IOException {
        // Create a URL for the desired page
        URL url = new URL("http://localhost:8989/echo/test");

        // Read all the text returned by the server
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        StringBuffer sb = new StringBuffer();
        String str;
        while ((str = in.readLine()) != null) {
            sb.append(str + "\n");
        }
        in.close();

        _logger.info(sb.toString());

        assertTrue(sb.toString().contains("REQUEST_URI: /echo/test"));
    }

    /**
     * We should get back a 404 file not found when we cannot route to a service
     * 
     * @throws IOException
     */
    @Test(expected = FileNotFoundException.class)
    public void testNotFound() throws IOException {
        // Create a URL for the desired page
        URL url = new URL("http://localhost:8989/not/found");
        url.getContent();
    }

    /**
     * Check if our 304 Not Modified is working when getting a static file.
     * 
     * @throws IOException
     * @throws ParseException
     */
    @Test()
    public void testStaticFileCache() throws IOException, ParseException {
        String TEXT = "abc\n123";

        String fileName = UUID.randomUUID().toString() + ".txt";
        File file = new File(_workbenchStaticFilesDirectory, fileName);

        FileOutputStream fos = new FileOutputStream(file);
        OutputStreamWriter out = new OutputStreamWriter(fos, "UTF-8");
        out.write(TEXT);
        out.close();

        // Refresh
        file = new File(file.getPath());

        // ******************************************************
        // Initial request
        // ******************************************************
        // Create a URL for the desired page
        URL url = new URL("http://localhost:8989/static/testdata/" + fileName);
        URLConnection conn = url.openConnection();

        // Read all the text returned by the server
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuffer sb = new StringBuffer();
        String str;
        while ((str = in.readLine()) != null) {
            sb.append(str + "\n");
        }
        in.close();

        assertEquals(TEXT, sb.toString().trim());

        // Get headers
        HashMap<String, String> headers = new HashMap<String, String>();
        for (int i = 0;; i++) {
            String name = conn.getHeaderFieldKey(i);
            String value = conn.getHeaderField(i);
            if (name == null && value == null) {
                break;
            }
            if (name == null) {
                _logger.debug("*** Intial Call, Response code: %s", value);
            } else {
                headers.put(name, value);
                _logger.debug("%s = %s", name, value);
            }
        }

        assertEquals("7", headers.get("Content-Length"));
        assertEquals("text/plain", headers.get("Content-Type"));

        // Check last modified should be the same as the file's last modified date
        SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
        fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
        assertEquals(fmt.format(new Date(file.lastModified())), headers.get("Last-Modified"));

        // Check Expiry
        Date expires = fmt.parse(headers.get("Expires"));
        Date serverDate = fmt.parse(headers.get("Date"));
        Calendar cal = new GregorianCalendar();
        cal.setTime(serverDate);
        cal.add(Calendar.SECOND, AppProperties.getInstance().getWorkbenchStaticFilesCacheSeconds());
        assertEquals(cal.getTimeInMillis(), expires.getTime());

        // ******************************************************
        // Cache Validation
        // ******************************************************
        url = new URL("http://localhost:8989/static/testdata/" + fileName);
        conn = url.openConnection();
        conn.setIfModifiedSince(fmt.parse(headers.get("Last-Modified")).getTime());

        in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        sb = new StringBuffer();
        while ((str = in.readLine()) != null) {
            sb.append(str + "\n");
        }
        in.close();

        // No content should be returned
        assertEquals("", sb.toString().trim());

        HashMap<String, String> headers2 = new HashMap<String, String>();
        String responseCode = "";
        for (int i = 0;; i++) {
            String name = conn.getHeaderFieldKey(i);
            String value = conn.getHeaderField(i);
            if (name == null && value == null) {
                break;
            }
            if (name == null) {
                responseCode = value;
                _logger.debug("*** Cache Call, Response code: %s", value);
            } else {
                headers2.put(name, value);
                _logger.debug("%s = %s", name, value);
            }
        }

        // Should get back a 304
        assertEquals("HTTP/1.1 304 Not Modified", responseCode);
        assertTrue(!StringUtils.isBlank(headers2.get("Date")));

        // ******************************************************
        // Finish
        // ******************************************************
        // Clean up
        file.delete();
    }

    /**
     * Check if our expected file types are compressed
     * 
     * @throws IOException
     * @throws ParseException
     * @throws DecoderException
     */
    @Test()
    public void testStaticFileCompression() throws IOException, ParseException, DecoderException {
        String[] fileExtensions = new String[] { ".html", ".js", ".css", ".json", ".txt", ".xml",
                ".nocompression" };

        // Get 10K string
        String TEXT = new RandomString(1024 * 10).nextString();
        byte[] TEXT_ARRAY = TEXT.getBytes("UTF-8");

        for (String fileExtension : fileExtensions) {
            String fileName = UUID.randomUUID().toString() + fileExtension;
            File file = new File(_workbenchStaticFilesDirectory, fileName);

            FileOutputStream fos = new FileOutputStream(file);
            OutputStreamWriter out = new OutputStreamWriter(fos, "UTF-8");
            out.write(TEXT);
            out.close();

            // Refresh
            file = new File(file.getPath());

            // Create a URL for the desired page
            URL url = new URL("http://localhost:8989/static/testdata/" + fileName + "?testquerystring=abc");
            URLConnection conn = url.openConnection();
            conn.setRequestProperty("Accept-Encoding", "gzip,deflate");

            // Read all the compressed data
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            InputStream is = conn.getInputStream();
            int b;
            while ((b = is.read()) != -1) {
                os.write(b);
            }

            // Get headers
            String responseCode = "";
            HashMap<String, String> headers = new HashMap<String, String>();
            for (int i = 0;; i++) {
                String name = conn.getHeaderFieldKey(i);
                String value = conn.getHeaderField(i);
                if (name == null && value == null) {
                    break;
                }
                if (name == null) {
                    responseCode = value;
                    _logger.debug("*** Intial Call, Response code: %s", value);
                } else {
                    headers.put(name, value);
                    _logger.debug("%s = %s", name, value);
                }
            }

            // Should get back a 200
            assertEquals("HTTP/1.1 200 OK", responseCode);
            assertTrue(!StringUtils.isBlank(headers.get("Date")));

            if (fileExtension != ".nocompression") {
                // Uncompress and check it out
                assertEquals("gzip", headers.get("Content-Encoding"));
                byte[] uncompressedContent = uncompress(os.toByteArray());
                for (int j = 0; j < TEXT_ARRAY.length; j++) {
                    assertEquals(TEXT_ARRAY[j], uncompressedContent[j]);
                }
            }

            // Clean up
            file.delete();
        }

        return;
    }

    /**
     * Check if we redirect to index.html successfully
     * 
     * @throws IOException
     */
    @Test()
    public void testRedirectToIndexHtml() throws IOException {
        URL url = new URL("http://localhost:8989/workbench");
        URLConnection conn = url.openConnection();
        HashMap<String, String> headers = new HashMap<String, String>();
        String responseCode = ApiUtils.getResponseHeaders(conn, headers);
        assertEquals("HTTP/1.1 200 OK", responseCode);

        url = new URL("http://localhost:8989/workbench/");
        conn = url.openConnection();
        headers = new HashMap<String, String>();
        responseCode = ApiUtils.getResponseHeaders(conn, headers);
        assertEquals("HTTP/1.1 200 OK", responseCode);
    }

    /**
     * Check for ApiNotFound error. 404 Not Found
     * 
     * @throws IOException
     * @throws ParseException
     */
    @Test()
    public void testApiNotFound() throws IOException, ParseException {
        URL url = new URL("http://localhost:8989/api/notfound");
        URLConnection conn = url.openConnection();

        // String content = ApiUtils.getResponseContent((HttpURLConnection) conn);

        HashMap<String, String> headers = new HashMap<String, String>();
        String responseCode = ApiUtils.getResponseHeaders(conn, headers);

        // _logger.debug(WebServerManagerTest.formatResponseForLogging(responseCode, headers, content));

        assertEquals("HTTP/1.1 404 Not Found", responseCode);
        assertTrue(!StringUtils.isBlank(headers.get("Date")));
    }

    /**
     * Uncompress. See http://www.jcraft.com/jzlib/. This is the same lib that is used inside netty
     * 
     * @param input
     * @return
     * @throws DecoderException
     */
    public byte[] uncompress(byte[] input) throws DecoderException {
        int uncomprLen = 40000;
        byte[] uncompr = new byte[uncomprLen];
        int err;

        ZStream d_stream = new ZStream();

        d_stream.next_in = input;
        d_stream.next_in_index = 0;
        d_stream.next_out = uncompr;
        d_stream.next_out_index = 0;

        err = d_stream.inflateInit(JZlib.W_GZIP);
        checkZipError(d_stream, err, "inflateInit");

        while (d_stream.total_out < uncomprLen && d_stream.total_in < input.length) {
            d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
            err = d_stream.inflate(JZlib.Z_NO_FLUSH);
            if (err == JZlib.Z_STREAM_END)
                break;
            checkZipError(d_stream, err, "inflate");
        }

        err = d_stream.inflateEnd();
        checkZipError(d_stream, err, "inflateEnd");

        return uncompr;
    }

    /**
     * Check for zip error
     * 
     * @param z
     * @param err
     * @param msg
     * @throws DecoderException
     */
    void checkZipError(ZStream z, int err, String msg) throws DecoderException {
        if (err != JZlib.Z_OK) {
            throw new DecoderException(z.msg);
        }
    }

    /**
     * Create a random string
     */
    public static class RandomString {

        private final char[] symbols = new char[36];

        private final Random random = new Random();

        private final char[] buf;

        public RandomString(int length) {
            for (int idx = 0; idx < 10; ++idx)
                symbols[idx] = (char) ('0' + idx);
            for (int idx = 10; idx < 36; ++idx)
                symbols[idx] = (char) ('a' + idx - 10);

            if (length < 1)
                throw new IllegalArgumentException("length < 1: " + length);
            buf = new char[length];
        }

        public String nextString() {
            for (int idx = 0; idx < buf.length; ++idx)
                buf[idx] = symbols[random.nextInt(symbols.length)];
            return new String(buf);
        }
    }

}