/*******************************************************************************
* Copyright (c) 2015 IBM Corp.
*
* 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 com.ibm.ws.lars.rest;
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 java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.Arrays;
import javax.ws.rs.core.UriInfo;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import com.ibm.ws.lars.rest.exceptions.AssetPersistenceException;
import com.ibm.ws.lars.rest.exceptions.InvalidIdException;
import com.ibm.ws.lars.rest.exceptions.InvalidJsonAssetException;
import com.ibm.ws.lars.rest.exceptions.NonExistentArtefactException;
import com.ibm.ws.lars.rest.injection.AssetServiceLayerInjection;
import com.ibm.ws.lars.rest.model.Asset;
import com.ibm.ws.lars.rest.model.AssetCursor;
import com.ibm.ws.lars.rest.model.Attachment;
import com.ibm.ws.lars.rest.model.RepositoryObject;
import com.ibm.ws.lars.rest.model.RepositoryResourceLifecycleException;
import com.ibm.ws.lars.testutils.BasicChecks;
/**
*
*/
public class AssetServiceLayerTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
private static final String TEST_USERNAME = "testUser";
private Asset simpleObject;
private Asset assetWithState;
// private Asset complexObject;
private Attachment attachmentWithContent;
private byte[] attachmentContent;
private UriInfo dummyUriInfo;
private AssetServiceLayer service;
Persistor memoryPersistor = new MemoryPersistor();
@Before
public void setUp() throws Exception {
assetWithState = Asset.deserializeAssetFromJson("{\"state\":\"published\",\"name\":\"foo\"}");
// complexObject = Asset.deserializeAssetFromJson("{\"state\":\"draft\",\"name\":\"foo\", \"arrayField\": " + jsonArray + "}");
simpleObject = Asset.deserializeAssetFromJson("{\"name\":\"foo\"}");
attachmentWithContent = Attachment.jsonToAttachment("{\"aField\":\"foo\"}");
attachmentContent = "I am some very simple content for the attachment!".getBytes();
service = new AssetServiceLayer();
AssetServiceLayerInjection.setConfiguration(service, new Configuration());
AssetServiceLayerInjection.setPersistenceBean(service, memoryPersistor);
dummyUriInfo = new DummyUriInfo(new URI("http://localhost:9080/ma/v1/"));
}
@Test
public void badStateTransitionTest() throws InvalidJsonAssetException, NonExistentArtefactException, RepositoryResourceLifecycleException {
thrown.expect(RepositoryResourceLifecycleException.class);
thrown.expectMessage("Invalid action approve performed on the asset with state draft");
Asset simpleAsset = service.createAsset(simpleObject, TEST_USERNAME);
service.updateAssetState(Asset.StateAction.APPROVE, simpleAsset.get_id());
}
@Test
public void lifeCycleTest() throws Exception {
Asset asset = service.createAsset(assetWithState, TEST_USERNAME);
assertEquals("State should have been overwritten with draft", "draft", asset.getProperty("state"));
// TODO: Is it possible to check the actual date is correct?
assertNotNull("created date should not be null", asset.getCreatedOn());
String lastUpdated = asset.getLastUpdatedOn();
assertNotNull("updated date should not be null", lastUpdated);
assertEquals("CreatedBy user is wrong", TEST_USERNAME, asset.getCreatedBy());
String id = asset.get_id();
Asset gotAsset = service.retrieveAsset(id, dummyUriInfo);
assertEquals("The id of the asset has changed", id, gotAsset.get_id());
AssetCursor assets = service.retrieveAllAssets();
assertEquals("Too many assets", 1, assets.size());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// do nothing. Just to make sure the time stamp is different after the update
}
service.updateAssetState(Asset.StateAction.PUBLISH, id);
Asset updatedAsset = service.retrieveAsset(id, dummyUriInfo);
assertEquals("Wrong state", Asset.State.AWAITING_APPROVAL, updatedAsset.getState());
String newUpdatedDate = updatedAsset.getLastUpdatedOn();
assertFalse("The last updated date should have been updated", lastUpdated.equals(newUpdatedDate));
Asset simpleAsset = service.createAsset(simpleObject, TEST_USERNAME);
Asset simpleGotAsset = service.retrieveAsset(simpleAsset.get_id(), dummyUriInfo);
assertEquals("Wrong state", Asset.State.DRAFT, simpleGotAsset.getState());
AssetCursor lotsOfAssets = service.retrieveAllAssets();
assertEquals("Wrong number of assets found", 2, lotsOfAssets.size());
service.deleteAsset(id);
service.deleteAsset(simpleGotAsset.get_id());
AssetCursor emptyAssets = service.retrieveAllAssets();
assertEquals("There should be no assets stored", 0, emptyAssets.size());
}
/**
* Tests creating and retrieving an attachment with no content.
*/
@Test
public void testAddAttachmentNoContent() throws Exception {
String attachmentJSON = "{\"url\":\"http://example.com\", \"linkType\":\"direct\"}";
Asset asset = Asset.deserializeAssetFromJson("{\"name\":\"Mr Asset\"}");
Asset returnedAsset = service.createAsset(asset, TEST_USERNAME);
Attachment unalteredAttachment = Attachment.jsonToAttachment(attachmentJSON);
Attachment attachment = Attachment.jsonToAttachment(attachmentJSON);
Attachment returnedAttachment = service.createAttachmentNoContent(returnedAsset.get_id(), "Mr Attachment", attachment, dummyUriInfo);
assertEquals("Attachment should have assetId set correctly", returnedAsset.get_id(), returnedAttachment.getAssetId());
returnedAttachment.getProperties().remove(Attachment.ASSET_ID);
assertNull("Attachment with no uploaded content should not have any data stored in gridFS", returnedAttachment.getGridFSId());
assertNotNull("Attachment should have an id", returnedAttachment.get_id());
returnedAttachment.getProperties().remove(RepositoryObject._ID);
assertNotNull("Attachment should have uploadOn", returnedAttachment.getUploadOn());
returnedAttachment.getProperties().remove(Attachment.UPLOAD_ON);
assertEquals("Attachment should have the specified name", "Mr Attachment", returnedAttachment.getName());
returnedAttachment.getProperties().remove(Attachment.NAME);
assertEquals(unalteredAttachment, returnedAttachment);
}
/**
* Verifies that an exception is thrown when we attachment to create an attachment with no
* content and no url.
*/
@Test
public void testAddAttachmentNoContentNoUrl() throws InvalidJsonAssetException, AssetPersistenceException, NonExistentArtefactException {
thrown.expect(InvalidJsonAssetException.class);
thrown.expectMessage("The URL of the supplied attachment was null");
String attachmentJSON = "{\"foo\":\"bar\"}";
Asset asset = Asset.deserializeAssetFromJson("{\"name\":\"Mr Asset\"}");
Asset returnedAsset = service.createAsset(asset, TEST_USERNAME);
Attachment attachment = Attachment.jsonToAttachment(attachmentJSON);
service.createAttachmentNoContent(returnedAsset.get_id(), "Mr Attachment", attachment, dummyUriInfo);
}
/**
* Verifies that an exception is thrown when we attachment to create an attachment with no
* content and no linkType.
*/
@Test
public void testAddAttachmentNoContentNoLinkType() throws InvalidJsonAssetException, AssetPersistenceException, NonExistentArtefactException {
thrown.expect(InvalidJsonAssetException.class);
thrown.expectMessage("The link type for the attachment was not set.");
String attachmentJSON = "{\"url\":\"http://example.com\"}";
Asset asset = Asset.deserializeAssetFromJson("{\"name\":\"Mr Asset\"}");
Asset returnedAsset = service.createAsset(asset, TEST_USERNAME);
Attachment attachment = Attachment.jsonToAttachment(attachmentJSON);
service.createAttachmentNoContent(returnedAsset.get_id(), "Mr Attachment", attachment, dummyUriInfo);
}
/**
* Verifies that an exception is thrown when we attempt to create an attachment with no content
* and a linkType that is not valid.
*/
@Test
public void testAddAttachmentNoContentBadLinkType() throws InvalidJsonAssetException, AssetPersistenceException, NonExistentArtefactException {
thrown.expect(InvalidJsonAssetException.class);
thrown.expectMessage("The link type for the attachment was set to an invalid value: Foobar");
String attachmentJSON = "{\"url\":\"http://example.com\"}";
Asset asset = Asset.deserializeAssetFromJson("{\"name\":\"Mr Asset\"}");
Asset returnedAsset = service.createAsset(asset, TEST_USERNAME);
Attachment attachment = Attachment.jsonToAttachment(attachmentJSON);
attachment.setLinkType("Foobar");
service.createAttachmentNoContent(returnedAsset.get_id(), "Mr Attachment", attachment, dummyUriInfo);
}
/**
* Tests creating and retrieving an attachment with content.
*/
@Test
public void testAddAttachmentWithContent() throws Exception {
Asset assetToCreate = new Asset(simpleObject);
Asset returnedAsset = service.createAsset(assetToCreate, TEST_USERNAME);
Attachment attachmentToCreate = new Attachment(attachmentWithContent);
Attachment createdAttachment = service.createAttachmentWithContent(returnedAsset.get_id(),
"AttachmentWithContent.txt",
attachmentToCreate,
"text/plain",
new ByteArrayInputStream(attachmentContent),
dummyUriInfo);
Attachment returnedAttachment = service.retrieveAttachmentMetadata(returnedAsset.get_id(), createdAttachment.get_id(), dummyUriInfo);
assertEquals("Attachment with content should have correct URL", "http://localhost:9080/ma/v1/assets/" + returnedAsset.get_id() +
"/attachments/" + returnedAttachment.get_id() + "/" +
"AttachmentWithContent.txt",
returnedAttachment.getUrl());
returnedAttachment.getProperties().remove(Attachment.URL);
assertEquals("Attachment should have assetId set correctly", returnedAsset.get_id(), returnedAttachment.getAssetId());
returnedAttachment.getProperties().remove(Attachment.ASSET_ID);
assertNotNull("Attachment should have an id", returnedAttachment.get_id());
returnedAttachment.getProperties().remove(RepositoryObject._ID);
assertEquals("Attachment should have the correct name", "AttachmentWithContent.txt", returnedAttachment.getName());
returnedAttachment.getProperties().remove(Attachment.NAME);
assertNotNull("Attachment should have uploadOn", returnedAttachment.getUploadOn());
returnedAttachment.getProperties().remove(Attachment.UPLOAD_ON);
assertEquals("Attachment should have contentType set correctly", "text/plain", returnedAttachment.getContentType());
returnedAttachment.getProperties().remove(Attachment.CONTENT_TYPE);
assertNotNull("Attachment should have gridFSId", returnedAttachment.getGridFSId());
returnedAttachment.getProperties().remove(Attachment.GRIDFS_ID);
assertEquals("Attachment should have correct size", attachmentContent.length, returnedAttachment.getSize());
returnedAttachment.getProperties().remove(Attachment.SIZE);
assertEquals("Returned attachment should have same contents that were POSTed", attachmentWithContent, returnedAttachment);
try (InputStream is = service.retrieveAttachmentContent(returnedAsset.get_id(), createdAttachment.get_id(), "AttachmentWithContent.txt", dummyUriInfo)
.getContentStream()) {
byte[] returnedContent = BasicChecks.slurp(is);
assertTrue(Arrays.equals(attachmentContent, returnedContent));
}
Asset fetchedAsset = service.retrieveAsset(returnedAsset.get_id(), dummyUriInfo);
assertEquals(fetchedAsset.getAttachments().get(0), createdAttachment);
}
/**
* Verifies that an exceptino is thrown when we attempt to create an attachment that has both
* content and a url.
*/
@Test
public void testAddAttachmentWithContentAndUrl() throws Exception {
thrown.expect(InvalidJsonAssetException.class);
thrown.expectMessage("An attachment should not have the URL set if it is created with content");
Asset assetToCreate = new Asset(simpleObject);
Asset returnedAsset = service.createAsset(assetToCreate, TEST_USERNAME);
Attachment attachmentToCreate = new Attachment(attachmentWithContent);
attachmentToCreate.setUrl("foobar");
service.createAttachmentWithContent(returnedAsset.get_id(), "AttachmentWithContent.txt", attachmentToCreate, "text/plain",
new ByteArrayInputStream(attachmentContent), dummyUriInfo);
}
/**
* Verifies that an exception is thrown when we attempt to create an attachment with both
* content and a linkType.
*/
@Test
public void testAddAttachmentWithContentAndLinkType() throws Exception {
thrown.expect(InvalidJsonAssetException.class);
thrown.expectMessage("The link type must not be set for an attachment with content");
Asset assetToCreate = new Asset(simpleObject);
Asset returnedAsset = service.createAsset(assetToCreate, TEST_USERNAME);
Attachment attachmentToCreate = new Attachment(attachmentWithContent);
attachmentToCreate.setLinkType("foobar");
service.createAttachmentWithContent(returnedAsset.get_id(), "AttachmentWithContent.txt", attachmentToCreate, "text/plain",
new ByteArrayInputStream(attachmentContent), dummyUriInfo);
}
/**
* Tests that an exception is thrown if an attachment is created with an invalid parent asset
* id.
*
* @throws InvalidJsonAssetException
* @throws NonExistentArtefactException
* @throws AssetPersistenceException
*/
@Test
public void testAddAttachmentInvalidAssetId() throws InvalidJsonAssetException, NonExistentArtefactException, AssetPersistenceException {
thrown.expect(NonExistentArtefactException.class);
thrown.expectMessage("The parent asset for this attachment (id=FFFFFFFFFFFFFFFF) does not exist in the repository.");
String attachmentJSON = "{\"url\":\"http://example.com\", \"linkType\":\"direct\"}";
Attachment attachment = Attachment.jsonToAttachment(attachmentJSON);
service.createAttachmentNoContent("FFFFFFFFFFFFFFFF", "Mr Attachment", attachment, dummyUriInfo);
}
/**
* Verifies that an exception is thrown when we attempt to retrieve an asset that does not
* exist.
*/
@Test(expected = NonExistentArtefactException.class)
public void testRetrieveNonExistentAsset() throws NonExistentArtefactException {
service.retrieveAsset("0123456789", dummyUriInfo);
}
/**
* Verifies that an exception is thrown when we attempt to retrieve an attachment that does not
* exist.
*/
@Test(expected = NonExistentArtefactException.class)
public void testRetrieveNonExistentAttachment() throws NonExistentArtefactException, InvalidIdException {
service.retrieveAttachmentMetadata("01234", "67864", dummyUriInfo);
}
@Test(expected = NonExistentArtefactException.class)
public void testRetrieveNonExistentAttachmentContent() throws NonExistentArtefactException, InvalidIdException {
service.retrieveAttachmentContent("01234", "67864", "a name that does not exist.", dummyUriInfo);
}
}