/*
* $HeadURL$
* $Id$
*
* Copyright (c) 2006-2010 by Public Library of Science
* http://plos.org
* http://ambraproject.org
*
* 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.ambraproject.service.syndication;
import org.ambraproject.action.BaseTest;
import org.ambraproject.service.article.NoSuchArticleIdException;
import org.ambraproject.models.Article;
import org.ambraproject.models.Journal;
import org.ambraproject.models.Syndication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
/**
* @author Scott Sterling
* @author Alex Kudlick
*/
@ContextConfiguration(locations = "SyndicationServerTest-context.xml")
public class SyndicationServiceTest extends BaseTest {
@Autowired
protected SyndicationService syndicationService;
@DataProvider(name = "storedSyndications")
public Object[][] getStoredSyndications() {
String doi = "id:test-article-1";
Article article = new Article();
article.setDoi(doi);
dummyDataStore.store(article);
Syndication pmc = new Syndication();
pmc.setDoi(doi);
pmc.setTarget("PMC");
pmc.setSubmissionCount(1);
pmc.setStatus(Syndication.STATUS_IN_PROGRESS);
pmc.setErrorMessage("hello");
dummyDataStore.store(pmc);
Syndication ebsco = new Syndication();
ebsco.setDoi(doi);
ebsco.setTarget("EBSCO");
ebsco.setSubmissionCount(10);
ebsco.setStatus(Syndication.STATUS_FAILURE);
ebsco.setErrorMessage("ERROR ERROR");
dummyDataStore.store(ebsco);
return new Object[][]{
{doi, "PMC", pmc},
{doi, "EBSCO", ebsco}
};
}
@Test(dataProvider = "storedSyndications")
public void testGetSyndication(String articleId, String target, Syndication original) throws URISyntaxException {
Syndication syndication = syndicationService.getSyndication(articleId, target);
assertNotNull(syndication, "returned null syndication");
compareSyndications(syndication, original);
}
@Test(expectedExceptions = {NoSuchArticleIdException.class})
public void testShouldFailIfNoArticle() throws NoSuchArticleIdException {
syndicationService.createSyndications("id:article-does-not-exist");
}
@Test(expectedExceptions = {SyndicationException.class})
public void testShouldFailIfNoArchiveName() throws NoSuchArticleIdException {
Article article = new Article();
article.setDoi("doi");
dummyDataStore.store(article);
syndicationService.syndicate("doi", "FOO");
}
/**
* Test the updateSyndication() method by setting a Syndication's <code>status</code> to the "failure" constant.
*/
@Test(dataProvider = "storedSyndications",
dependsOnMethods = {"testGetSyndication", "testUpdateSyndicationUpdateToPending"}, alwaysRun = true)
public void testUpdateSyndicationToFailure(String articleId, String target,
Syndication original) throws URISyntaxException {
Long testStart = new Date().getTime();
String errorMessage = "a new error message";
Syndication syndication = syndicationService.updateSyndication(articleId, target,
Syndication.STATUS_FAILURE, errorMessage);
assertNotNull(syndication, "returned null syndication");
assertEquals(syndication.getStatus(), Syndication.STATUS_FAILURE, "Syndication didn't get status updated");
assertEquals(syndication.getErrorMessage(), errorMessage, "syndication didn't get error message updated");
assertNotNull(syndication.getLastModified(), "Syndication didn't get last modified timestamp set");
assertTrue(syndication.getLastModified().getTime() >= testStart, "last modified timestamp wasn't after the " +
"testStart");
//Check that none of the other properties got messed with
assertEquals(syndication.getDoi(), original.getDoi(), "syndication had article id changed");
assertEquals(syndication.getSubmissionCount(), original.getSubmissionCount(), "syndication had submission count changed");
assertEquals(syndication.getTarget(), original.getTarget(), "syndication had target changed");
assertMatchingDates(syndication.getCreated(), original.getCreated());
}
/**
* Test the updateSyndication() method by setting a Syndication's <code>status</code> to the "pending" constant. This
* update should fail, so the resulting Syndication is the same.
*/
@Test(dataProvider = "storedSyndications", dependsOnMethods = {"testGetSyndication"}, alwaysRun = true)
public void testUpdateSyndicationUpdateToPending(String articleId, String target, Syndication original) {
Syndication syndication = syndicationService.updateSyndication(articleId, target, Syndication.STATUS_PENDING, null);
//The only things that should change are status and error message
original.setStatus(Syndication.STATUS_PENDING);
original.setErrorMessage(null);
compareSyndications(syndication, original);
}
@DataProvider(name = "articleNoSyndications")
public Object[][] getArticleWithNoSyndications() {
Article article = new Article();
article.setDoi("id:test-doi-no-syndications");
article.setArchiveName("archive");
dummyDataStore.store(article);
return new Object[][]{
{article.getDoi(), new String[]{"FOO", "BAR"}}
};
}
/**
* Test the createSyndication() method for an Article which has no associated Syndication objects.
*/
@Test(dataProvider = "articleNoSyndications")
public void testCreateSyndicationsNoExistingSyndications(String articleId, String[] expectedTargets) throws
NoSuchArticleIdException {
Long testStart = new Date().getTime();
List<Syndication> syndications = syndicationService.createSyndications(articleId);
assertNotNull(syndications, "returned null list of syndications");
assertEquals(syndications.size(), expectedTargets.length, "returned incorrect number of syndications");
for (int i = 0; i < syndications.size(); i++) {
Syndication syndication = syndications.get(i);
assertNotNull(syndication, "returned null syndication");
assertEquals(syndication.getDoi(), articleId, "returned syndication with incorrect doi");
assertEquals(syndication.getTarget(), expectedTargets[i], "returned syndication with incorrect target");
assertTrue(syndication.getCreated().getTime() >= testStart, "syndication didn't get create timestamp set");
assertEquals(syndication.getStatus(), Syndication.STATUS_PENDING, "syndication didn't get correct status");
}
}
@DataProvider(name = "articleWithSyndications")
public Object[][] getArticleWithSyndications() {
Article article = new Article();
String doi = "id:article-with-syndications";
article.setDoi(doi);
article.setArchiveName("archive");
dummyDataStore.store(article);
Syndication syndication = new Syndication();
syndication.setDoi(doi);
syndication.setStatus(Syndication.STATUS_IN_PROGRESS);
syndication.setLastModified(new Date());
syndication.setTarget("FOO");
dummyDataStore.store(syndication);
return new Object[][]{
{doi, new String[]{"FOO", "BAR"}, new Syndication[]{syndication}}
};
}
/**
* Test the createSyndication() method for an Article which already has some associated Syndication objects. Expects
* the existing syndications to be for targets that appear before the new ones
*/
@Test(dataProvider = "articleWithSyndications")
public void testCreateSyndicationsWithExistingSyndications(String articleId, String[] expectedTargets, Syndication[] existingSyndications)
throws URISyntaxException, NoSuchArticleIdException {
Long testStart = new Date().getTime();
List<Syndication> syndications = syndicationService.createSyndications(articleId);
assertNotNull(syndications, "returned null list of syndications");
assertEquals(syndications.size(), expectedTargets.length, "returned incorrect number of syndications");
for (int i = 0; i < existingSyndications.length; i++) {
compareSyndications(syndications.get(i), existingSyndications[i]);
}
//new syndications
for (int i = existingSyndications.length; i < syndications.size(); i++) {
Syndication syndication = syndications.get(i);
assertNotNull(syndication, "returned null syndication");
assertEquals(syndication.getDoi(), articleId, "returned syndication with incorrect target");
assertEquals(syndication.getTarget(), expectedTargets[i], "returned syndication with incorrect target");
assertTrue(syndication.getCreated().getTime() >= testStart, "syndication didn't get create timestamp updated");
assertEquals(syndication.getStatus(), Syndication.STATUS_PENDING, "syndication didn't get correct status");
}
}
@DataProvider(name = "failedAndInProgressSyndications")
public Object[][] getFailedAndInProgressSyndications() {
String journalKey = "PLoSBio";
Journal journal = new Journal();
journal.setJournalKey(journalKey);
journal.seteIssn("111-120-56");
dummyDataStore.store(journal);
Article article = new Article();
article.seteIssn(journal.geteIssn());
String articleId = "id:test-article-for-failed-and-in-progress";
article.setDoi(articleId);
dummyDataStore.store(article);
Syndication failed = new Syndication();
failed.setStatus(Syndication.STATUS_FAILURE);
failed.setDoi(article.getDoi());
failed.setSubmissionCount(1);
failed.setLastModified(new Date());
failed.setTarget("FOO1");
dummyDataStore.store(failed);
Syndication inProgress = new Syndication();
inProgress.setStatus(Syndication.STATUS_IN_PROGRESS);
inProgress.setDoi(article.getDoi());
inProgress.setSubmissionCount(1);
inProgress.setLastModified(new Date());
inProgress.setTarget("FOO2");
dummyDataStore.store(inProgress);
Syndication successful = new Syndication();
successful.setStatus(Syndication.STATUS_SUCCESS);
successful.setDoi(article.getDoi());
successful.setSubmissionCount(10);
successful.setLastModified(new Date());
successful.setTarget("FOO3");
dummyDataStore.store(successful);
Calendar oldDate = Calendar.getInstance();
oldDate.add(Calendar.YEAR, -1);
Syndication old = new Syndication();
old.setStatus(Syndication.STATUS_FAILURE);
old.setSubmissionCount(10);
old.setDoi(article.getDoi());
old.setLastModified(oldDate.getTime());
old.setTarget("FOO4");
dummyDataStore.store(old);
return new Object[][]{
{journalKey, new Syndication[]{failed, inProgress}}
};
}
@Test(dataProvider = "failedAndInProgressSyndications")
public void testGetFailedAndInProgressSyndications(String journalKey, Syndication[] expectedSyndications) throws URISyntaxException {
List<Syndication> list = syndicationService.getFailedAndInProgressSyndications(journalKey);
assertNotNull(list, "returned null syndication list");
assertEquals(list.size(), expectedSyndications.length, "returned incorrect number of syndications");
for (Syndication syndication : list) {
boolean foundMatch = false;
for (Syndication expected : expectedSyndications) {
if (expected.getTarget().equals(syndication.getTarget())) {
foundMatch = true;
compareSyndications(syndication, expected);
break;
}
}
assertTrue(foundMatch, "returned an unexpected syndication with target: " + syndication.getTarget());
}
}
@DataProvider(name = "articleForSyndication")
public Object[][] getArticleForSyndication() {
Article article = new Article();
String articleId = "id:article-for-syndication";
article.setArchiveName("archive.zip");
article.setDoi(articleId);
dummyDataStore.store(article);
Syndication previousSyndication = new Syndication();
previousSyndication.setStatus(Syndication.STATUS_IN_PROGRESS);
previousSyndication.setSubmissionCount(1);
previousSyndication.setDoi(article.getDoi());
previousSyndication.setTarget("FOO");
dummyDataStore.store(previousSyndication);
return new Object[][]{
{articleId, "FOO", 1},
{articleId, "BAR", 0}
};
}
/**
* Test the syndicate() method. Simulates the successful creation of a message and the pushing of that message to the
* plos-queue functionality.
*/
@Test(dataProvider = "articleForSyndication")
public void testSyndicate(String articleId, String target, int previousSubmissionCount) throws Exception {
Long testStart = new Date().getTime();
Syndication syndication = syndicationService.syndicate(articleId, target);
assertNotNull(syndication, "returned null syndication");
assertEquals(syndication.getDoi(), articleId, "syndication had incorrect article id");
assertEquals(syndication.getTarget(), target, "syndication had incorrect target");
assertEquals(syndication.getSubmissionCount(), previousSubmissionCount + 1, "syndication didn't get submission count updated");
assertNotNull(syndication.getCreated(), "syndication had null create timestamp");
assertNotNull(syndication.getLastSubmitTimestamp(), "syndication didn't get submit timestamp set");
assertTrue(syndication.getLastSubmitTimestamp().getTime() >= testStart,
"syndication didn't have submit timestamp set to be after test start");
if (previousSubmissionCount == 0) {
//syndication should've been created during the test
assertTrue(syndication.getCreated().getTime() >= testStart, "syndication didn't get create timestamp set " +
"correctly");
} else {
assertTrue(syndication.getCreated().getTime() <= testStart, "syndication had create timestamp changed");
}
assertEquals(syndication.getStatus(), Syndication.STATUS_IN_PROGRESS, "syndication didn't get status set correctly");
}
@DataProvider(name = "articleWithSyndicationsToQuery")
public Object[][] getArticleWithSyndicationsToQuery() {
String articleId = "id:article-with-syndications-to-query";
Article article = new Article();
article.setDoi(articleId);
dummyDataStore.store(article);
List<String> expectedTargets = new ArrayList<String>(2);
Syndication syndication1 = new Syndication();
syndication1.setDoi(article.getDoi());
syndication1.setTarget("FOO10000");
dummyDataStore.store(syndication1);
expectedTargets.add(syndication1.getTarget());
Syndication syndication2 = new Syndication();
syndication2.setDoi(article.getDoi());
syndication2.setTarget("FOO10001");
dummyDataStore.store(syndication2);
expectedTargets.add(syndication2.getTarget());
return new Object[][]{
{articleId, expectedTargets}
};
}
@Test(dataProvider = "articleWithSyndicationsToQuery")
public void testGetSyndications(String articleId, List<String> expectedTargets) throws NoSuchArticleIdException {
List<Syndication> syndications = syndicationService.getSyndications(articleId);
assertNotNull(syndications, "returned null list of syndications");
assertEquals(syndications.size(), expectedTargets.size(), "returned incorrect number of syndications");
for (Syndication syndication : syndications) {
assertNotNull(syndication, "returned null syndication");
assertEquals(syndication.getDoi(), articleId, "syndication had incorrect article id");
assertTrue(expectedTargets.contains(syndication.getTarget()),
"returned syndication for unexpected target: " + syndication.getTarget());
}
}
private void compareSyndications(Syndication actual, Syndication expected) {
assertEquals(actual.getDoi(), expected.getDoi(), "syndication had incorrect article id");
assertEquals(actual.getStatus(), expected.getStatus(), "syndication had incorrect status");
assertEquals(actual.getErrorMessage(), expected.getErrorMessage(), "syndication had incorrect error message");
assertEquals(actual.getSubmissionCount(), expected.getSubmissionCount(), "syndication had incorrect submission count");
assertEquals(actual.getTarget(), expected.getTarget(), "syndication had incorrect target");
assertMatchingDates(actual.getLastModified(), expected.getLastModified());
assertMatchingDates(actual.getCreated(), expected.getCreated());
}
}