de.metalcon.musicStorageServer.MusicStorageServerTest.java Source code

Java tutorial

Introduction

Here is the source code for de.metalcon.musicStorageServer.MusicStorageServerTest.java

Source

package de.metalcon.musicStorageServer;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import org.apache.commons.io.FileUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import de.metalcon.musicStorageServer.protocol.ProtocolConstants;
import de.metalcon.musicStorageServer.protocol.Response;
import de.metalcon.musicStorageServer.protocol.create.CreateResponse;
import de.metalcon.musicStorageServer.protocol.delete.DeleteResponse;
import de.metalcon.musicStorageServer.protocol.read.ReadResponse;
import de.metalcon.musicStorageServer.protocol.update.UpdateResponse;
import de.metalcon.musicstreamingserver.api.MusicData;
import de.metalcon.musicstreamingserver.api.MusicItemVersion;

public class MusicStorageServerTest {

    private static final Format FORMATTER = new SimpleDateFormat("yyyy-MM-dd");

    private static final JSONParser PARSER = new JSONParser();

    private static final String CONFIG_PATH = "test.mss.config";

    private static final String VALID_READ_IDENTIFIER = "mi1";

    private static final String VALID_CREATE_IDENTIFIER = "mi2";

    private static File TEST_FILE_DIRECTORY;

    private static File BACKUP_FILE_ORIGINAL, BACKUP_FILE_BASIS, BACKUP_FILE_STREAMING;

    private static File DESTINATION_FILE_ORIGINAL, DESTINATION_FILE_BASIS, DESTINATION_FILE_STREAMING;

    private static InputStream VALID_READ_STREAM_MP3;

    private static InputStream INVALID_READ_STREAM_JPEG, INVALID_READ_STREAM_TXT, INVALID_READ_STREAM_EMPTY;

    private static JSONObject VALID_READ_META_DATA_JSON;

    private static String VALID_READ_META_DATA;

    private static JSONObject VALID_CREATE_META_DATA_JSON;

    private static String VALID_CREATE_META_DATA;

    private static String INVALID_CREATE_META_DATA = "{ artist: Testy }";

    private MusicStorageServer server;

    private JSONObject jsonResponse;

    private CreateResponse createResponse;

    private ReadResponse readResponse;

    private UpdateResponse updateResponse;

    private DeleteResponse deleteResponse;

    @SuppressWarnings("unchecked")
    @BeforeClass
    public static void beforeClass() throws IOException {
        final MSSConfig config = new MSSConfig(CONFIG_PATH);
        TEST_FILE_DIRECTORY = new File(config.getMusicDirectory()).getParentFile();

        VALID_READ_META_DATA_JSON = new JSONObject();
        VALID_READ_META_DATA_JSON.put("title", "My Great Song");
        VALID_READ_META_DATA_JSON.put("album", "Testy Forever");
        VALID_READ_META_DATA_JSON.put("artist", "Testy");

        VALID_READ_META_DATA = VALID_READ_META_DATA_JSON.toJSONString();

        VALID_CREATE_META_DATA_JSON = new JSONObject();
        VALID_CREATE_META_DATA_JSON.putAll(VALID_READ_META_DATA_JSON);
        VALID_CREATE_META_DATA_JSON.put("license", "General Less AllYouCanEat License");
        VALID_CREATE_META_DATA_JSON.put("date", "1991-11-11");

        VALID_CREATE_META_DATA_JSON.put("comment", "All your cookies belong to me!");

        VALID_CREATE_META_DATA = VALID_CREATE_META_DATA_JSON.toJSONString();

        // convert files for reading tests once
        final MusicStorageServer server = new MusicStorageServer(CONFIG_PATH);
        server.clear();

        BACKUP_FILE_ORIGINAL = new File(TEST_FILE_DIRECTORY, "original.mp3");
        BACKUP_FILE_BASIS = new File(TEST_FILE_DIRECTORY, "basis.ogg");
        BACKUP_FILE_STREAMING = new File(TEST_FILE_DIRECTORY, "streaming.ogg");

        final String hash = "108053";
        final Calendar calendar = Calendar.getInstance();
        final String day = FORMATTER.format(calendar.getTime());
        final String year = String.valueOf(calendar.get(Calendar.YEAR));

        DESTINATION_FILE_ORIGINAL = new File(
                config.getMusicDirectory() + "originals/" + year + "/" + day + "/1/10/", hash);
        DESTINATION_FILE_BASIS = new File(config.getMusicDirectory() + "1/10/108/basis/", hash + ".ogg");
        DESTINATION_FILE_STREAMING = new File(config.getMusicDirectory() + "1/10/108/streaming/", hash + ".ogg");

        // convert and copy files if not existing
        if (!(BACKUP_FILE_ORIGINAL.exists() && BACKUP_FILE_BASIS.exists() && BACKUP_FILE_STREAMING.exists())) {
            try {
                assertTrue(server.createMusicItem(VALID_READ_IDENTIFIER,
                        new FileInputStream(new File(TEST_FILE_DIRECTORY, "mp3.mp3")), VALID_READ_META_DATA,
                        new CreateResponse()));

                FileUtils.copyFile(DESTINATION_FILE_ORIGINAL, BACKUP_FILE_ORIGINAL);
                FileUtils.copyFile(DESTINATION_FILE_BASIS, BACKUP_FILE_BASIS);
                FileUtils.copyFile(DESTINATION_FILE_STREAMING, BACKUP_FILE_STREAMING);
            } catch (final FileNotFoundException e) {
                fail("audio file for test is not avialable!\n" + e.getMessage());
            }
        }
    }

    @Before
    public void setUp() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException,
            IllegalAccessException {
        server = new MusicStorageServer(CONFIG_PATH);
        server.clear();
        assertTrue(server.isRunning());

        // restore converted files to save time
        FileUtils.copyFile(BACKUP_FILE_ORIGINAL, DESTINATION_FILE_ORIGINAL);
        FileUtils.copyFile(BACKUP_FILE_BASIS, DESTINATION_FILE_BASIS);
        FileUtils.copyFile(BACKUP_FILE_STREAMING, DESTINATION_FILE_STREAMING);

        // TODO: find a better solution
        final Field metaDatabase = MusicStorageServer.class.getDeclaredField("musicMetaDatabase");
        metaDatabase.setAccessible(true);
        ((MusicMetaDatabase) metaDatabase.get(server)).addDatabaseEntry(VALID_READ_IDENTIFIER,
                VALID_READ_META_DATA_JSON);

        assertFalse(server.createMusicItem(VALID_READ_IDENTIFIER,
                new FileInputStream(new File(TEST_FILE_DIRECTORY, "mp3.mp3")), VALID_CREATE_META_DATA,
                new CreateResponse()));

        VALID_READ_STREAM_MP3 = new FileInputStream(new File(TEST_FILE_DIRECTORY, "mp3.mp3"));

        INVALID_READ_STREAM_JPEG = new FileInputStream(new File(TEST_FILE_DIRECTORY, "jpeg.jpeg"));
        INVALID_READ_STREAM_TXT = new FileInputStream(new File(TEST_FILE_DIRECTORY, "txt.txt"));
        INVALID_READ_STREAM_EMPTY = new FileInputStream(new File(TEST_FILE_DIRECTORY, "empty"));

        createResponse = new CreateResponse();
        readResponse = new ReadResponse();
        updateResponse = new UpdateResponse();
        deleteResponse = new DeleteResponse();
    }

    @Test
    public void testCreateMusicItemMp3Valid() {
        assertTrue(server.createMusicItem(VALID_CREATE_IDENTIFIER, VALID_READ_STREAM_MP3, VALID_CREATE_META_DATA,
                createResponse));
    }

    @Test
    public void testCreateInvalidIdentifier() {
        assertFalse(server.createMusicItem(VALID_READ_IDENTIFIER, VALID_READ_STREAM_MP3, VALID_CREATE_META_DATA,
                createResponse));

        extractJson(createResponse);
        assertEquals(ProtocolConstants.StatusMessage.Create.MUSIC_ITEM_IDENTIFIER_IN_USE,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testCreateInvalidMetaData() {
        assertFalse(server.createMusicItem(VALID_CREATE_IDENTIFIER, VALID_READ_STREAM_MP3, INVALID_CREATE_META_DATA,
                createResponse));

        extractJson(createResponse);
        assertEquals(ProtocolConstants.StatusMessage.Create.META_DATA_MALFORMED,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testCreateMusicItemJpeg() {
        assertFalse(server.createMusicItem(VALID_CREATE_IDENTIFIER, INVALID_READ_STREAM_JPEG,
                VALID_CREATE_META_DATA, createResponse));

        extractJson(createResponse);
        assertEquals(ProtocolConstants.StatusMessage.Create.MUSIC_ITEM_STREAM_INVALID,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testCreateMusicItemTxt() {
        assertFalse(server.createMusicItem(VALID_CREATE_IDENTIFIER, INVALID_READ_STREAM_TXT, VALID_CREATE_META_DATA,
                createResponse));

        extractJson(createResponse);
        assertEquals(ProtocolConstants.StatusMessage.Create.MUSIC_ITEM_STREAM_INVALID,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testCreateMusicItemEmpty() {
        assertFalse(server.createMusicItem(VALID_CREATE_IDENTIFIER, INVALID_READ_STREAM_EMPTY,
                VALID_CREATE_META_DATA, createResponse));

        extractJson(createResponse);
        assertEquals(ProtocolConstants.StatusMessage.Create.MUSIC_ITEM_STREAM_INVALID,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testReadMusicItemOriginal() throws FileNotFoundException, IOException {
        final MusicData musicData = server.readMusicItem(VALID_READ_IDENTIFIER, MusicItemVersion.ORIGINAL,
                readResponse);
        assertNotNull(musicData);

        compareJson(VALID_READ_META_DATA, musicData.getMetaData());
        assertTrue(compareInputStreams(new FileInputStream(BACKUP_FILE_ORIGINAL), musicData.getMusicItemStream()));
    }

    @Test
    public void testReadMusicItemBasis() throws FileNotFoundException, IOException {
        final MusicData musicData = server.readMusicItem(VALID_READ_IDENTIFIER, MusicItemVersion.BASIS,
                readResponse);
        assertNotNull(musicData);

        compareJson(VALID_READ_META_DATA, musicData.getMetaData());
        assertTrue(compareInputStreams(new FileInputStream(BACKUP_FILE_BASIS), musicData.getMusicItemStream()));
    }

    @Test
    public void testReadMusicItemStreaming() throws FileNotFoundException, IOException {
        final MusicData musicData = server.readMusicItem(VALID_READ_IDENTIFIER, MusicItemVersion.STREAM,
                readResponse);
        assertNotNull(musicData);

        compareJson(VALID_READ_META_DATA, musicData.getMetaData());
        assertTrue(compareInputStreams(new FileInputStream(BACKUP_FILE_STREAMING), musicData.getMusicItemStream()));
    }

    @Test
    public void testReadInvalidIdentifier() {
        assertNull(server.readMusicItem(VALID_CREATE_IDENTIFIER, MusicItemVersion.ORIGINAL, readResponse));

        extractJson(readResponse);
        assertEquals(ProtocolConstants.StatusMessage.Read.MUSIC_ITEM_NOT_EXISTING,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testReadMusicItemVersionNull() throws FileNotFoundException, IOException {
        final MusicData musicData = server.readMusicItem(VALID_READ_IDENTIFIER, null, readResponse);
        assertNotNull(musicData);

        compareJson(VALID_READ_META_DATA, musicData.getMetaData());
        assertTrue(compareInputStreams(new FileInputStream(BACKUP_FILE_STREAMING), musicData.getMusicItemStream()));
    }

    @Test
    public void testReadMetaDataSingle() {
        final String[] identifiers = new String[] { VALID_READ_IDENTIFIER };
        final String[] metaData = server.readMusicItemMetaData(identifiers, readResponse);
        assertNotNull(metaData);
        assertEquals(identifiers.length, metaData.length);
        compareJson(VALID_READ_META_DATA, metaData[0]);
    }

    @Test
    public void testReadMetaDataInvalidIdentifier() {
        final String[] identifiers = new String[] { VALID_READ_IDENTIFIER, VALID_CREATE_IDENTIFIER };
        assertNull(server.readMusicItemMetaData(identifiers, readResponse));

        extractJson(readResponse);
        assertEquals(ProtocolConstants.StatusMessage.Read.MUSIC_ITEM_NOT_EXISTING,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testUpdateMetaData() {
        assertTrue(server.updateMetaData(VALID_READ_IDENTIFIER, VALID_CREATE_META_DATA, updateResponse));
    }

    @Test
    public void testUpdateMetaDataInvalidIdentifier() {
        assertFalse(server.updateMetaData(VALID_CREATE_IDENTIFIER, VALID_CREATE_META_DATA, updateResponse));

        extractJson(updateResponse);
        assertEquals(ProtocolConstants.StatusMessage.Update.MUSIC_ITEM_NOT_EXISTING,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testUpdateMetaDataInvalidMetaData() {
        assertFalse(server.updateMetaData(VALID_READ_IDENTIFIER, INVALID_CREATE_META_DATA, updateResponse));

        extractJson(updateResponse);
        assertEquals(ProtocolConstants.StatusMessage.Update.META_DATA_MALFORMED,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    @Test
    public void testDelete() {
        assertTrue(server.deleteMusicItem(VALID_READ_IDENTIFIER, deleteResponse));
    }

    @Test
    public void testDeleteInvalidIdentifier() {
        assertFalse(server.deleteMusicItem(VALID_CREATE_IDENTIFIER, deleteResponse));

        extractJson(deleteResponse);
        assertEquals(ProtocolConstants.StatusMessage.Delete.MUSIC_ITEM_NOT_EXISTING,
                jsonResponse.get(ProtocolConstants.STATUS_MESSAGE));
    }

    /**
     * compare two input streams
     * 
     * @param stream1
     *            first input stream
     * @param stream2
     *            second input stream
     * @return true - if the two streams does contain the same content<br>
     *         false - otherwise
     * @throws IOException
     *             if IO errors occurred
     */
    private static boolean compareInputStreams(final InputStream stream1, final InputStream stream2)
            throws IOException {
        final ReadableByteChannel channel1 = Channels.newChannel(stream1);
        final ReadableByteChannel channel2 = Channels.newChannel(stream2);
        final ByteBuffer buffer1 = ByteBuffer.allocateDirect(4096);
        final ByteBuffer buffer2 = ByteBuffer.allocateDirect(4096);

        try {
            while (true) {

                int n1 = channel1.read(buffer1);
                int n2 = channel2.read(buffer2);

                if ((n1 == -1) || (n2 == -1)) {
                    return n1 == n2;
                }

                buffer1.flip();
                buffer2.flip();

                for (int i = 0; i < Math.min(n1, n2); i++) {
                    if (buffer1.get() != buffer2.get()) {
                        return false;
                    }
                }

                buffer1.compact();
                buffer2.compact();
            }

        } finally {
            if (stream1 != null) {
                stream1.close();
            }
            if (stream2 != null) {
                stream2.close();
            }
        }
    }

    /**
     * compare two JSON strings at JSON level (ignoring spaces aso.)
     * 
     * @param json1
     *            first JSON string
     * @param json2
     *            second JSON string
     */
    private static void compareJson(final String json1, final String json2) {
        final JSONObject object1 = parseToJson(json1);
        final JSONObject object2 = parseToJson(json2);

        assertEquals(object1, object2);
    }

    /**
     * parse a String to a JSON object<br>
     * <b>fails the test</b> if the parsing failed
     * 
     * @param value
     *            String to be parsed
     * @return JSON object represented by the String passed<br>
     *         <b>null</b> if the parsing failed
     */
    private static JSONObject parseToJson(final String value) {
        try {
            return (JSONObject) PARSER.parse(value);
        } catch (final ParseException e) {
            fail("failed to parse to JSON object!");
        }

        return null;
    }

    /**
     * extract the JSON object from the response, failing the test if this is
     * not possible
     * 
     * @param response
     *            MSSP response
     */
    protected void extractJson(final Response response) {
        try {
            final Field field = Response.class.getDeclaredField("json");
            field.setAccessible(true);
            jsonResponse = (JSONObject) field.get(response);
        } catch (final Exception e) {
            fail("failed to extract the JSON object from class Response");
        }
    }

}