/*
* $HeadURL$
* $Id$
* Copyright (c) 2006-2011 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.0Unless 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.article;
import org.ambraproject.ApplicationException;
import org.ambraproject.action.BaseTest;
import org.ambraproject.models.Article;
import org.ambraproject.models.ArticleAsset;
import org.apache.commons.io.IOUtils;
import org.apache.tika.Tika;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
/**
* @author Alex Kudick 12/29/11
*/
public class ArticleAssetServiceTest extends BaseTest {
@Autowired
protected ArticleAssetService articleAssetService;
@DataProvider(name = "articleAssets")
public Object[][] getArticleAssets() {
Article article = new Article();
article.setDoi("id:test-doi-for-assets");
article.setState(Article.STATE_UNPUBLISHED); //use admin auth id to retrieve
article.setAssets(new ArrayList<ArticleAsset>(2));
ArticleAsset asset1 = new ArticleAsset();
asset1.setDoi("id:test-doi-for-assets.t001");
asset1.setExtension("foo");
asset1.setContentType("application/pdf");
asset1.setDescription("A FOO asset");
asset1.setSize(1032587L);
article.getAssets().add(asset1);
ArticleAsset asset2 = new ArticleAsset();
asset2.setDoi("id:test-doi-for-assets.t002");
asset2.setExtension("bar");
asset2.setContentType("tif");
asset2.setDescription("A Bar asset");
asset2.setSize(92473587L);
article.getAssets().add(asset2);
dummyDataStore.store(article); //cascade to the assets
return new Object[][]{
{asset1.getDoi(), asset1.getExtension(), asset1},
{asset2.getDoi(), asset2.getExtension(), asset2}
};
}
//This tests the bad method of getAsset that just returns the first instance of an asset with the given doi
@Test(dataProvider = "articleAssets")
public void testGetSingleAsset(String assetUri, String notUsed, ArticleAsset expectedAsset) throws NoSuchObjectIdException {
ArticleAsset asset = articleAssetService.getSuppInfoAsset(assetUri, DEFAULT_ADMIN_AUTHID);
assertNotNull(asset, "returned null article asset");
compareAssets(asset, expectedAsset);
}
@Test(dataProvider = "articleAssets")
public void testGetAsset(String assetUri, String extension, ArticleAsset expectedAsset) throws NoSuchObjectIdException {
ArticleAsset asset = articleAssetService.getArticleAsset(assetUri, extension, DEFAULT_ADMIN_AUTHID);
assertNotNull(asset, "returned null article asset");
compareAssets(asset, expectedAsset);
}
@DataProvider(name = "badArticleAssets")
public Object[][] getBadArticleAssets() {
Article notYetPublished = new Article();
notYetPublished.setDoi("id:unpubbed-doi-for-assets");
notYetPublished.setState(Article.STATE_UNPUBLISHED);
notYetPublished.setAssets(new ArrayList<ArticleAsset>(1));
ArticleAsset asset1 = new ArticleAsset();
asset1.setDoi("id:unpubbed-doi-for-assets.t001");
asset1.setExtension("foo");
notYetPublished.getAssets().add(asset1);
Article deliberatelyUnpublished = new Article();
deliberatelyUnpublished.setDoi("id:disable-doi-for-assets");
deliberatelyUnpublished.setState(Article.STATE_DISABLED);
deliberatelyUnpublished.setAssets(new ArrayList<ArticleAsset>(1));
ArticleAsset asset2 = new ArticleAsset();
asset2.setDoi("id:disabled-doi-for-assets.t002");
asset2.setExtension("bar");
deliberatelyUnpublished.getAssets().add(asset2);
dummyDataStore.store(notYetPublished); //cascade to the assets
return new Object[][]{
//users shouldn't see unpublished asset
{asset1.getDoi(), asset1.getExtension(), DEFAULT_USER_AUTHID},
//even admins shouldn't see disabled asset
{asset2.getDoi(), asset2.getExtension(), DEFAULT_ADMIN_AUTHID}
};
}
@Test(dataProvider = "badArticleAssets", expectedExceptions = {NoSuchObjectIdException.class})
public void testShouldFailForUnpublishedArticles(String assetUri, String extension, String authId) throws NoSuchObjectIdException {
articleAssetService.getArticleAsset(assetUri, extension, authId);
}
@DataProvider(name = "articleXmlAndPdf")
public Object[][] getArticleXmlAndPdf() {
Article article = new Article();
article.setDoi("id:doi-for-getXmlAndPdf");
article.setAssets(new ArrayList<ArticleAsset>(2));
ArticleAsset xml = new ArticleAsset();
xml.setContentType("text/xml");
xml.setExtension("XML");
xml.setDoi("id:doi-for-getXmlAndPdf");
article.getAssets().add(xml);
ArticleAsset pdf = new ArticleAsset();
pdf.setContentType("application/pdf");
pdf.setExtension("PDF");
pdf.setDoi("id:doi-for-getXmlAndPdf");
article.getAssets().add(pdf);
dummyDataStore.store(article);
return new Object[][]{
{article.getDoi(), xml, pdf}
};
}
@Test(dataProvider = "articleXmlAndPdf")
public void testGetArticleXmlAndPdf(String doi, ArticleAsset xml, ArticleAsset pdf) throws NoSuchObjectIdException {
List<ArticleAsset> articleXmlAndPdf = (List<ArticleAsset>) articleAssetService.getArticleXmlAndPdf(doi, DEFAULT_ADMIN_AUTHID);
assertNotNull(articleXmlAndPdf, "returned null list for xml and pdf");
assertEquals(articleXmlAndPdf.size(), 2, "returned incorrect number of assets");
//sort the list so it's in PDF, XML order
Collections.sort(articleXmlAndPdf, new Comparator<ArticleAsset>() {
@Override
public int compare(ArticleAsset articleAsset, ArticleAsset articleAsset1) {
return articleAsset.getExtension().compareTo(articleAsset1.getExtension());
}
});
compareAssets(articleXmlAndPdf.get(0), pdf);
compareAssets(articleXmlAndPdf.get(1), xml);
}
@DataProvider(name = "badXmlAndPdf")
public Object[][] getUnpubbedArticles() {
Article notYetPubbed = new Article();
notYetPubbed.setState(Article.STATE_UNPUBLISHED);
notYetPubbed.setDoi("id:not-yet-pubbed-for-xmlandpdf");
Article deliberatelyUnpubbed = new Article();
deliberatelyUnpubbed.setDoi("id:unpubbed-for-xml-and-pdf");
deliberatelyUnpubbed.setState(Article.STATE_DISABLED);
dummyDataStore.store(notYetPubbed);
dummyDataStore.store(deliberatelyUnpubbed);
return new Object[][]{
{notYetPubbed.getDoi(), DEFAULT_USER_AUTHID},
{deliberatelyUnpubbed.getDoi(), DEFAULT_ADMIN_AUTHID}
};
}
@Test(dataProvider = "badXmlAndPdf", expectedExceptions = {NoSuchObjectIdException.class})
public void testXmlAndPdfFailsForUnpublishedArticles(String doi, String authId) throws NoSuchObjectIdException {
articleAssetService.getArticleXmlAndPdf(doi, authId);
}
@DataProvider(name = "figuresTables")
public Object[][] getFiguresTables() {
Article article = new Article();
article.setDoi("id:doi-for-fig-table-method");
article.setState(Article.STATE_UNPUBLISHED); //use admin auth id to retrieve
article.setAssets(new ArrayList<ArticleAsset>(5));
ArticleAsset asset1 = new ArticleAsset();
asset1.setContextElement("fig");
asset1.setDoi("id:doi-for-fig-table-method.t001");
asset1.setExtension("png_s");
asset1.setTitle("some title");
article.getAssets().add(asset1);
ArticleAsset asset2 = new ArticleAsset();
asset2.setContextElement("fig");
asset2.setDoi("id:doi-for-fig-table-method.t001");
asset2.setExtension("png_m");
asset2.setTitle("some title");
article.getAssets().add(asset2);
ArticleAsset asset3 = new ArticleAsset();
asset3.setContextElement("table-wrap");
asset3.setDoi("id:doi-for-fig-table-method.t002");
asset3.setExtension("png_s");
asset3.setTitle("some other title");
article.getAssets().add(asset3);
ArticleAsset asset4 = new ArticleAsset();
asset4.setContextElement("table-wrap");
asset4.setDoi("id:doi-for-fig-table-method.t002");
asset4.setExtension("png_m");
asset4.setTitle("some other title");
article.getAssets().add(asset4);
ArticleAsset notAFigureOrTable = new ArticleAsset();
notAFigureOrTable.setContextElement("body");
notAFigureOrTable.setDoi("id:doi-for-fig-table-method");
notAFigureOrTable.setExtension("XML");
article.getAssets().add(notAFigureOrTable);
dummyDataStore.store(article);
//1 and 2 have same doi, 3 and 4 have same doi
//so the method should only return two asset wrappers
ArticleAssetWrapper wrapper1 = new ArticleAssetWrapper(asset1, "png_s", "png_m", "png_l");
ArticleAssetWrapper wrapper2 = new ArticleAssetWrapper(asset3, "png_s", "png_m", "png_l");
return new Object[][]{
{article.getDoi(), new ArticleAssetWrapper[]{wrapper1, wrapper2}}
};
}
@Test(dataProvider = "figuresTables")
public void testListFiguresTables(String articleDoi, ArticleAssetWrapper[] expectedAssets) throws NoSuchArticleIdException {
ArticleAssetWrapper[] assetWrappers = articleAssetService.listFiguresTables(articleDoi, DEFAULT_ADMIN_AUTHID);
assertNotNull(assetWrappers, "returned null array of asset wrappers");
assertEquals(assetWrappers, expectedAssets, "returned incorrect asset wrappers");
}
@DataProvider(name = "badArticles")
public Object[][] getBadArticles() {
Article unpubbed = new Article();
unpubbed.setDoi("id:unpubbedForListFiguresTables");
unpubbed.setState(Article.STATE_UNPUBLISHED);
dummyDataStore.store(unpubbed);
Article disabled = new Article();
disabled.setDoi("id:disabledForListFiguresTables");
disabled.setState(Article.STATE_DISABLED);
dummyDataStore.store(disabled);
return new Object[][]{
{unpubbed.getDoi(), DEFAULT_USER_AUTHID},
{disabled.getDoi(), DEFAULT_ADMIN_AUTHID}
};
}
@Test(dataProvider = "badArticles", expectedExceptions = {NoSuchArticleIdException.class})
public void testListFiguresTablesOnUnpubbedArticle(String doi, String authId) throws NoSuchArticleIdException {
articleAssetService.listFiguresTables(doi, authId);
}
@Test
public void testGetArticleID() {
Article article = new Article();
article.setDoi("id:test-article-for-asset-get-id");
article.setAssets(new ArrayList<ArticleAsset>(1));
article.getAssets().add(new ArticleAsset());
article.getAssets().get(0).setDoi("id:test-asset-for-get-id");
article.getAssets().get(0).setExtension("foo");
Long articleID = Long.valueOf(dummyDataStore.store(article));
Long result = articleAssetService.getArticleID(article.getAssets().get(0));
assertEquals(result, articleID, "Article Asset service returned incorrect id");
}
//This is a difficult method to have expected results for, but at least we can check that the output is a ppt file
@Test
public void testGetPowerpointSlide() throws IOException, NoSuchObjectIdException, NoSuchArticleIdException, ApplicationException {
//save the article first
setUpArticleForImageFromFilestore();
InputStream inputStream = null;
Tika tika = new Tika();
try {
inputStream = articleAssetService.getPowerPointSlide(IMAGE_DOI_IN_FILESTORE, DEFAULT_ADMIN_AUTHID);
assertNotNull(inputStream, "Returned null input stream");
//read the content type from the bytes of the input stream
assertEquals(tika.detect(inputStream), "application/x-tika-msoffice", "powerpoint file had incorrect type");
} finally {
if (inputStream != null) {
IOUtils.closeQuietly(inputStream);
}
}
}
}