org.codice.ddf.spatial.geocoding.extract.GeoNamesFileExtractorTest.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.spatial.geocoding.extract.GeoNamesFileExtractorTest.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * <p>This is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or any later version.
 *
 * <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details. A copy of the GNU Lesser General Public
 * License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package org.codice.ddf.spatial.geocoding.extract;

import static org.codice.ddf.spatial.geocoding.GeoEntryExtractor.ExtractionCallback;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import javax.ws.rs.core.Response;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.codice.ddf.spatial.geocoding.GeoEntry;
import org.codice.ddf.spatial.geocoding.GeoEntryExtractionException;
import org.codice.ddf.spatial.geocoding.GeoEntryIndexingException;
import org.codice.ddf.spatial.geocoding.GeoNamesRemoteDownloadException;
import org.codice.ddf.spatial.geocoding.ProgressCallback;
import org.codice.ddf.spatial.geocoding.TestBase;
import org.codice.ddf.spatial.geocoding.create.GeoNamesCreator;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

public class GeoNamesFileExtractorTest extends TestBase {
    private static final String VALID_TEXT_FILE_PATH = GeoNamesFileExtractorTest.class
            .getResource("/geonames/valid.txt").getPath();

    private static final String INVALID_TEXT_FILE_PATH = GeoNamesFileExtractorTest.class
            .getResource("/geonames/invalid.txt").getPath();

    private static final String VALID_ZIP_FILE_PATH = GeoNamesFileExtractorTest.class
            .getResource("/geonames/valid_zip.zip").getPath();

    private static final String UNSUPPORTED_FILE_PATH = GeoNamesFileExtractorTest.class
            .getResource("/geonames/foo.rtf").getPath();

    private GeoNamesFileExtractor geoNamesFileExtractor;

    private static final String URL = "http://example.com";

    @Before
    public void setUp() {
        geoNamesFileExtractor = Mockito.spy(new GeoNamesFileExtractor());
        geoNamesFileExtractor.setGeoEntryCreator(new GeoNamesCreator());
        geoNamesFileExtractor.setUrl(URL);
    }

    @Test
    public void testExtractFromValidTextFileAllAtOnce()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException {
        testFileExtractionAllAtOnce(VALID_TEXT_FILE_PATH, mock(ProgressCallback.class));
    }

    @Test
    public void testExtractFromValidTextFileStreaming()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException, GeoEntryIndexingException {
        testFileExtractionStreaming(VALID_TEXT_FILE_PATH);
    }

    @Test
    public void testExtractFromValidZipFileAllAtOnce()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException {
        testFileExtractionAllAtOnce(VALID_ZIP_FILE_PATH, null);
        // Delete the extracted text file.
        FileUtils.deleteQuietly(new File(FilenameUtils.removeExtension(VALID_ZIP_FILE_PATH) + ".txt"));
    }

    @Test
    public void testExtractFromValidZipFileStreaming()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException, GeoEntryIndexingException {
        testFileExtractionStreaming(VALID_ZIP_FILE_PATH);
        // Delete the extracted text file.
        FileUtils.deleteQuietly(new File(FilenameUtils.removeExtension(VALID_ZIP_FILE_PATH) + ".txt"));
    }

    @Test
    public void testExtractFromTextFileWrongFormat()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException {
        try {
            geoNamesFileExtractor.getGeoEntries(INVALID_TEXT_FILE_PATH, null);
            fail("Should have thrown a GeoEntryExtractionException because 'invalid.txt' is not "
                    + "formatted in the expected way.");
        } catch (GeoEntryExtractionException e) {
            assertThat(e.getCause(), instanceOf(IndexOutOfBoundsException.class));
        }
    }

    @Test
    public void testExtractFromNonexistentFile()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException {
        try {
            geoNamesFileExtractor.getGeoEntries(FilenameUtils.getFullPath(VALID_TEXT_FILE_PATH) + "fake.txt", null);
            fail("Should have thrown a GeoEntryExtractionException because 'fake.txt' does not " + "exist.");
        } catch (GeoEntryExtractionException e) {
            assertThat(e.getCause(), instanceOf(FileNotFoundException.class));
        }
    }

    @Test(expected = GeoEntryExtractionException.class)
    public void testExtractFromUnsupportedFileType()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException {
        geoNamesFileExtractor.getGeoEntries(UNSUPPORTED_FILE_PATH, null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testNullExtractionCallback() throws GeoEntryExtractionException, GeoNamesRemoteDownloadException {
        geoNamesFileExtractor.pushGeoEntriesToExtractionCallback(VALID_TEXT_FILE_PATH, null);
    }

    @Test
    public void testExtractFromMockWebConnection() throws GeoEntryExtractionException,
            GeoNamesRemoteDownloadException, GeoEntryIndexingException, IOException {
        setMockConnection(200, 12345);
        setMockInputStream("/geonames/AU.zip");
        testFileExtractionStreaming("AU");
    }

    @Test(expected = GeoEntryExtractionException.class)
    public void testExtractFromMockWebConnectionInvalidFileExtension()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException, IOException {
        setMockConnection(404, 12345);
        setMockInputStream("/geonames/valid.txt");
        geoNamesFileExtractor.getGeoEntries("valid", mock(ProgressCallback.class));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testExtractFromMockWebConnectionNullCallback()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException, IOException {
        setMockConnection(404, 12345);
        setMockInputStream("/geonames/nonexistentfile.txt");
        geoNamesFileExtractor.pushGeoEntriesToExtractionCallback("nonexistentfile.txt", null);
    }

    @Test(expected = GeoNamesRemoteDownloadException.class)
    public void testExtractFromMockWebConnectionNonExistentFile()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException, IOException {
        setMockConnection(404, 12345);
        setMockInputStream("/geonames/s.txt");
        geoNamesFileExtractor.getGeoEntries("s", mock(ProgressCallback.class));
    }

    @Test(expected = GeoNamesRemoteDownloadException.class)
    public void testExtractFromMockWebConnectionInvalidStreamForFile()
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException, IOException {
        setMockConnection(404, 12345);
        doReturn(null).when(geoNamesFileExtractor).getUrlInputStreamFromWebClient();
        geoNamesFileExtractor.getGeoEntries("valid", mock(ProgressCallback.class));
    }

    @Test
    public void testDownloadFromValidUrl() throws Exception {
        setMockConnection(200, 192837);
        setMockInputStream("/geonames/AU.zip");

        List<GeoEntry> entries = geoNamesFileExtractor.getGeoEntries("http://foo.bar/AU.zip",
                mock(ProgressCallback.class));
        verifyGeoEntryList(entries);
    }

    @Test(expected = GeoNamesRemoteDownloadException.class)
    public void testDownloadFailureFromUrl() throws Exception {
        setMockConnection(404, 102938437);
        doThrow(GeoNamesRemoteDownloadException.class).when(geoNamesFileExtractor).getUrlInputStreamFromWebClient();
        geoNamesFileExtractor.getGeoEntries("http://fake.com/file.zip", mock(ProgressCallback.class));
    }

    @Test
    public void testDownloadFromFileUrl() throws Exception {
        testFileExtractionAllAtOnce("file://" + VALID_TEXT_FILE_PATH, mock(ProgressCallback.class));
    }

    private void verifyGeoEntryList(final List<GeoEntry> geoEntryList) {
        assertEquals(3, geoEntryList.size());

        verifyGeoEntry(geoEntryList.get(0), "Kingman", 35.18944, -114.05301, "PPLA2", 28068,
                "IGM,Kingman,Kingmen,Kingmun", "USA");
        verifyGeoEntry(geoEntryList.get(1), "Lake Havasu City", 34.4839, -114.32245, "PPL", 52527,
                "HII,Lejk Khavasu Siti,Lejk-Gavasu-Siti", "USA");
        verifyGeoEntry(geoEntryList.get(2), "Marana", 32.43674, -111.22538, "PPL", 34961, "MZJ", "USA");
    }

    private void testFileExtractionAllAtOnce(final String fileLocation, final ProgressCallback mockProgressCallback)
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException {
        final List<GeoEntry> geoEntryList = geoNamesFileExtractor.getGeoEntries(fileLocation, mockProgressCallback);

        if (mockProgressCallback != null) {
            verify(mockProgressCallback, atLeastOnce()).updateProgress(anyInt());
        }

        verifyGeoEntryList(geoEntryList);
    }

    private void testFileExtractionStreaming(final String fileLocation)
            throws GeoEntryExtractionException, GeoNamesRemoteDownloadException, GeoEntryIndexingException {
        final ExtractionCallback extractionCallback = mock(ExtractionCallback.class);

        final ArgumentCaptor<GeoEntry> geoEntryArgumentCaptor = ArgumentCaptor.forClass(GeoEntry.class);

        geoNamesFileExtractor.pushGeoEntriesToExtractionCallback(fileLocation, extractionCallback);

        verify(extractionCallback, atLeastOnce()).updateProgress(anyInt());
        verify(extractionCallback, times(3)).extracted(geoEntryArgumentCaptor.capture());

        final List<GeoEntry> capturedGeoEntryList = geoEntryArgumentCaptor.getAllValues();

        verifyGeoEntryList(capturedGeoEntryList);
    }

    private void setMockInputStream(String filePath) throws FileNotFoundException, GeoNamesRemoteDownloadException {
        FileInputStream fileInputStream = getFileInputStream(filePath);
        doReturn(fileInputStream).when(geoNamesFileExtractor).getUrlInputStreamFromWebClient();
    }

    private void setMockConnection(int responseCode, int length) {
        Response mockResponse = mock(Response.class);
        doReturn(responseCode).when(mockResponse).getStatus();
        doReturn(length).when(mockResponse).getLength();
        doReturn(mockResponse).when(geoNamesFileExtractor).createConnection(anyString());
        doNothing().when(geoNamesFileExtractor).closeConnection();
    }

    private FileInputStream getFileInputStream(String fileName) {
        File file;
        FileInputStream fileInputStream;
        try {
            file = new File(GeoNamesFileExtractorTest.class.getResource(fileName).getPath());
            fileInputStream = new FileInputStream(file);
        } catch (NullPointerException | FileNotFoundException e) {
            fileInputStream = null;
        }
        return fileInputStream;
    }
}