package eu.balticdiversity.feedreaders;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import fi.luomus.commons.containers.KeyValuePair;
import fi.luomus.commons.http.HttpClientService;
import fi.luomus.commons.xml.Document;
import fi.luomus.commons.xml.XMLReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URLEncodedUtils;
import org.junit.Test;
public class HTTPFeedReaderClientTest {
private final String SINGLE_ENTRY = "<SimpleDarwinRecordSet xmlns:dc=\"http://purl.org/dc/terms/\" xmlns:dwc=\"http://rs.tdwg.org/dwc/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
"<SimpleDarwinRecord>\n" +
"<dwc:occurrenceID>52685402</dwc:occurrenceID>\n" +
"<dc:modified>2011-12-12T10:19:00Z</dc:modified>\n" +
"<dwc:institutionCode>NRM</dwc:institutionCode>\n" +
"<dwc:collectionCode>RingedBirds</dwc:collectionCode>\n" +
"<dwc:datasetName>NRM Bird ringing</dwc:datasetName>\n" +
"<dwc:basisOfRecord>O</dwc:basisOfRecord>\n" +
"<dwc:catalogNumber>926501</dwc:catalogNumber>\n" +
"<dwc:occurrenceRemarks></dwc:occurrenceRemarks>\n" +
"<dwc:individualCount>1</dwc:individualCount>\n" +
"<dwc:associatedReferences>http://www.gbif.se/occurrence/52685402</dwc:associatedReferences>\n" +
"<dwc:eventDate>2002-09-09</dwc:eventDate>\n" +
"<dwc:year>2002</dwc:year>\n" +
"<dwc:month>9</dwc:month>\n" +
"<dwc:day>9</dwc:day>\n" +
"<dwc:continent>EUROPE</dwc:continent>\n" +
"<dwc:country>SWEDEN</dwc:country>\n" +
"<dwc:stateProvince> Blekinge</dwc:stateProvince>\n" +
"<dwc:locality>TORHAMN</dwc:locality>\n" +
"<dwc:maximumDepthInMeters>0</dwc:maximumDepthInMeters>\n" +
"<dwc:decimalLatitude>56.0833</dwc:decimalLatitude>\n" +
"<dwc:decimalLongitude>15.8500</dwc:decimalLongitude>\n" +
"<dwc:dateIdentified>2002-09-09</dwc:dateIdentified>\n" +
"<dwc:scientificName>Sylvia atricapilla</dwc:scientificName>\n" +
"<dwc:kingdom>Animalia</dwc:kingdom>\n" +
"<dwc:phylum>Chordata</dwc:phylum>\n" +
"<dwc:class>Aves</dwc:class>\n" +
"<dwc:genus>Sylvia</dwc:genus>\n" +
"<dwc:specificEpithet>atricapilla</dwc:specificEpithet>\n" +
"</SimpleDarwinRecord>\n" +
"</SimpleDarwinRecordSet>";
@Test
public void testSingleEntry() throws Exception {
MockHTTPClient httpClient = new MockHTTPClient(SINGLE_ENTRY);
FeedReaderClient feedClient = new HTTPFeedReaderClient(httpClient);
String doc = feedClient.getFeedDocument(getMockUri());
assertEquals(SINGLE_ENTRY, doc);
}
@Test
public void testEmptyEntry() throws Exception {
final String xml = "<SimpleDarwinRecordSet />";
MockHTTPClient httpClient = new MockHTTPClient(xml);
FeedReaderClient feedClient = new HTTPFeedReaderClient(httpClient);
String doc = feedClient.getFeedDocument(getMockUri());
assertEquals(xml, doc);
}
@Test
public void testInvalidEntry() throws Exception {
final String xml = "<foo><bar/></foo>";
MockHTTPClient httpClient = new MockHTTPClient(xml);
HTTPFeedReaderClient client = new HTTPFeedReaderClient(httpClient);
try {
client.getFeedDocument(getMockUri());
fail("no error");
} catch (HTTPFeedReaderClient.FeedReaderClientException e) {
}
}
@Test
public void testInvalidEntryInvalidXML() throws Exception {
final String response = "invalid";
MockHTTPClient httpClient = new MockHTTPClient(response);
HTTPFeedReaderClient client = new HTTPFeedReaderClient(httpClient);
try {
client.getFeedDocument(getMockUri());
fail("no error");
} catch (HTTPFeedReaderClient.FeedReaderClientException e) {
}
}
@Test
public void testEntryClientError() throws Exception {
MockHTTPClient httpClient = new MockHTTPClient(SINGLE_ENTRY);
httpClient.setError(true);
HTTPFeedReaderClient client = new HTTPFeedReaderClient(httpClient);
try {
client.getFeedDocument(getMockUri());
} catch (FeedReaderClient.FeedReaderClientException e) {
}
}
private final String FEED_WITH_ENTRIES_XML = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
"<id>caa92658-d779-4ccc-96f8-75f5f0821f69</id>\n" +
"<link href=\"http://www.gbif.se/transactions/?from=10000&limit=5\"/>\n" +
"<title>GBIF-Sweden - transaction feed for occurrence data</title>\n" +
"<updated>2013-06-20T14:25:00+02:00</updated>\n" +
"<author>\n" +
"<name>GBIF-Sweden</name>\n" +
"<email>gbif@nrm.se</email>\n" +
"<uri>http://www.gbif.se</uri>\n" +
"</author>\n" +
"<entry>\n" +
"<id>10000</id>\n" +
"<title>52685402</title>\n" +
"<link href=\"http://www.gbif.se/transactions/unit/52685402\" rel=\"alternate\" type=\"application/xml\"/>\n" +
"<updated>2012-11-16T10:28:06+01:00</updated>\n" +
"<summary>INSERT</summary>\n" +
"</entry>\n" +
"<entry>\n" +
"<id>10001</id>\n" +
"<title>52685401</title>\n" +
"<link href=\"http://www.gbif.se/transactions/unit/52685401\" rel=\"alternate\" type=\"application/xml\"/>\n" +
"<updated>2012-11-16T10:28:06+01:00</updated>\n" +
"<summary>INSERT</summary>\n" +
"</entry>\n" +
"</feed>";
@Test
public void testEntries() throws Exception {
MockHTTPClient httpClient = new MockHTTPClient(FEED_WITH_ENTRIES_XML);
FeedReaderClient client = new HTTPFeedReaderClient(httpClient);
List<FeedEntryWithSeqID> entries = client.getFeedEntriesFromSeq(getMockUri(), 1, 1);
assertEquals(2, entries.size());
assertTrue(10000 == entries.get(0).getSeqID());
assertEquals(new URI("http://www.gbif.se/transactions/unit/52685402"), entries.get(0).getUri());
assertEquals("52685402", entries.get(0).getDocumentId());
assertTrue(10001 == entries.get(1).getSeqID());
assertEquals(new URI("http://www.gbif.se/transactions/unit/52685401"), entries.get(1).getUri());
assertEquals("52685401", entries.get(1).getDocumentId());
}
@Test
public void testNoEntries() throws Exception {
final String xml = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
"<id>caa92658-d779-4ccc-96f8-75f5f0821f69</id>\n" +
"<link href=\"http://www.gbif.se/transactions/?from=999999999999999999\"/>\n" +
"<title>GBIF-Sweden - transaction feed for occurrence data</title>\n" +
"<updated>2013-06-20T15:08:03+02:00</updated>\n" +
"<author>\n" +
"<name>GBIF-Sweden</name>\n" +
"<email>gbif@nrm.se</email>\n" +
"<uri>http://www.gbif.se</uri>\n" +
"</author>\n" +
"</feed>";
MockHTTPClient httpClient = new MockHTTPClient(xml);
FeedReaderClient client = new HTTPFeedReaderClient(httpClient);
List<FeedEntryWithSeqID> entries = client.getFeedEntriesFromSeq(getMockUri(), 1, 1);
assertEquals(0, entries.size());
}
@Test
public void testLimit() throws Exception {
MockHTTPClient httpClient = new MockHTTPClient(FEED_WITH_ENTRIES_XML);
FeedReaderClient client = new HTTPFeedReaderClient(httpClient);
client.getFeedEntriesFromSeq(getMockUri(), 1, 1);
assertTrue(httpClient.getLastRequest().getURI().toString().contains("limit=1"));
}
@Test
public void testInvalidEntries() throws Exception {
// Valid XML, invalid response
MockHTTPClient httpClient = new MockHTTPClient("<invalid></invalid>");
HTTPFeedReaderClient client = new HTTPFeedReaderClient(httpClient);
try {
client.getFeedEntriesFromSeq(getMockUri(),1 ,1);
fail("no error");
} catch (HTTPFeedReaderClient.FeedReaderClientException e) {
}
}
@Test
public void testInvalidEntriesNotXML() throws Exception {
MockHTTPClient httpClient = new MockHTTPClient("invalid");
HTTPFeedReaderClient client = new HTTPFeedReaderClient(httpClient);
try {
client.getFeedEntriesFromSeq(getMockUri(),1 ,1);
fail("no error");
} catch (HTTPFeedReaderClient.FeedReaderClientException e) {
}
}
@Test
public void testAdditionalParamsFeed() throws Exception {
MockHTTPClient httpClient = new MockHTTPClient(FEED_WITH_ENTRIES_XML);
HTTPFeedReaderClient client = new HTTPFeedReaderClient(httpClient);
client = client.withAdditionalParameter(new KeyValuePair("foo", "bar"));
client.getFeedEntriesFromSeq(getMockUri(), 1, 1);
hasKeyValuePair(new KeyValuePair("foo", "bar"), httpClient.getLastRequest().getURI());
}
@Test
public void testAdditionalParamsSingle() throws Exception {
MockHTTPClient httpClient = new MockHTTPClient(SINGLE_ENTRY);
HTTPFeedReaderClient client = new HTTPFeedReaderClient(httpClient);
client = client.withAdditionalParameter(new KeyValuePair("foo", "bar"));
client.getFeedDocument(getMockUri());
hasKeyValuePair(new KeyValuePair("foo", "bar"), httpClient.getLastRequest().getURI());
}
private void hasKeyValuePair(KeyValuePair original, URI uri) {
for (NameValuePair pair : URLEncodedUtils.parse(uri, "utf-8")) {
if (pair.getName().equals(original.getKey())) {
if (pair.getValue().equals(original.getValue())) {
return;
} else {
throw new RuntimeException("Invalid value " + pair.getValue());
}
}
}
throw new RuntimeException("Key " + original.getKey() + " not found");
}
private URI getMockUri() {
try {
return new URI("http://www.luomus.fi");
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
private class MockHTTPClient extends HttpClientService {
private boolean error = false;
private final String response;
private HttpUriRequest lastRequest = null;
public MockHTTPClient(String response) {
this.response = response;
}
@Override
public void close() {
}
@Override
public Document contentAsDocument(HttpUriRequest request) throws IOException {
return new XMLReader().parse(getResponseForRequest(request));
}
@Override
public String contentAsString(HttpUriRequest request) throws IOException {
return getResponseForRequest(request);
}
private String getResponseForRequest(HttpUriRequest request) throws IOException {
if (error) {
throw new IOException();
}
this.lastRequest = request;
return response;
}
private HttpUriRequest getLastRequest() {
return lastRequest;
}
private void setError(boolean error) {
this.error = error;
}
}
}