package dk.kb.yggdrasil.bitmag;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.bitrepository.access.getchecksums.GetChecksumsClient;
import org.bitrepository.access.getchecksums.conversation.ChecksumsCompletePillarEvent;
import org.bitrepository.access.getfile.GetFileClient;
import org.bitrepository.access.getfileids.GetFileIDsClient;
import org.bitrepository.bitrepositoryelements.ChecksumDataForChecksumSpecTYPE;
import org.bitrepository.bitrepositoryelements.ChecksumSpecTYPE;
import org.bitrepository.bitrepositoryelements.ResponseCode;
import org.bitrepository.bitrepositoryelements.ResultingChecksums;
import org.bitrepository.client.eventhandler.CompleteEvent;
import org.bitrepository.client.eventhandler.ContributorCompleteEvent;
import org.bitrepository.client.eventhandler.ContributorEvent;
import org.bitrepository.client.eventhandler.ContributorFailedEvent;
import org.bitrepository.client.eventhandler.EventHandler;
import org.bitrepository.client.eventhandler.OperationFailedEvent;
import org.bitrepository.common.utils.CalendarUtils;
import org.bitrepository.common.utils.FileUtils;
import org.bitrepository.common.utils.SettingsUtils;
import org.bitrepository.modify.putfile.PutFileClient;
import org.bitrepository.protocol.FileExchange;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import dk.kb.yggdrasil.exceptions.ArgumentCheck;
import dk.kb.yggdrasil.exceptions.YggdrasilException;
/**
* Tests for {@link dk.kb.yggdrasil.bitmag.Bitrepository }
* Named BitrepositoryTester and not BitrepositoryTest to avoid inclusion in
* the set of unittests run by Maven.
*/
@RunWith(JUnit4.class)
public class BitrepositoryTest {
public static String MISSING_YAML_FILE = "src/test/resources/config/rabbitmq.yaml2";
public static String INCORRECT_YAML_FILE = "src/test/resources/config/rabbitmq.yml";
public static String OK_YAML_BITMAG_FILE = "src/test/resources/config/bitmag.yml";
@BeforeClass
public static void beforeClass() throws YggdrasilException, IOException {
System.setProperty("dk.kb.yggdrasil.runningmode", "test");
}
@Test(expected = ArgumentCheck.class)
public void testMissingYamlFile() throws Exception {
File missingConfigFile = new File(MISSING_YAML_FILE);
assertFalse(missingConfigFile.exists());
new Bitrepository(new BitrepositoryConfig(missingConfigFile));
}
// @Ignore
@Test(expected = YggdrasilException.class)
public void testIncorrectYamlFile() throws Exception {
File badConfigFile = new File(INCORRECT_YAML_FILE);
assertTrue(badConfigFile.exists());
new Bitrepository(new BitrepositoryConfig(badConfigFile));
}
@Test
public void testOkYamlFile() throws Exception {
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
// Assumes that Yggdrasil/config contains a directory "bitmag-development-settings"
// containing bitrepository 1.0 settings and with a keyfile named "client-16.pem"
assertTrue(okConfigFile.exists());
new BitrepositoryTestingAPI(okConfigFile);
}
// Apparently we cannot mock the PutFileClient.
@Ignore
@Test
public void testUpload() throws YggdrasilException, IOException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
PutFileClient mockClient = mock(PutFileClient.class);
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[6];
List<ContributorEvent> events = new ArrayList<ContributorEvent>();
for(String pillarID : SettingsUtils.getPillarIDsForCollection(collectionID)) {
ContributorEvent ce = new ContributorCompleteEvent(pillarID, collectionID);
events.add(ce);
eh.handleEvent(ce);
}
eh.handleEvent(new CompleteEvent(collectionID, events));
return null;
}
}).when(mockClient).putFile(anyString(), any(URL.class), anyString(), any(), any(), any(), any(EventHandler.class), anyString());
FileExchange fe = mock(FileExchange.class);
br.setPutFileClient(mockClient);
when(fe.putFile(any(File.class))).thenReturn(new URL("http://localhost:80/dav/test.txt"));
br.setFileExchange(fe);
String generatedName = "helloworld" + System.currentTimeMillis() + ".txt";
File payloadFile = getFileWithContents(generatedName, "Hello World".getBytes());
boolean success = br.uploadFile(payloadFile, "books");
assertTrue("Should have returned true for success, but failed", success);
payloadFile.delete();
}
@Test
public void testUploadOnUnknownCollection() throws YggdrasilException, IOException {
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
Bitrepository br = new BitrepositoryTestingAPI(okConfigFile);
String generatedName = "helloworld" + System.currentTimeMillis() + ".txt";
File payloadFile = getFileWithContents(generatedName, "Hello World".getBytes());
boolean success = br.uploadFile(payloadFile, "cars");
assertFalse("Shouldn't have returned true for success, but succeeded", success);
payloadFile.delete();
}
@Test
public void testGetFileSuccess() throws Exception {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
final String FILE_CONTENT = "Hello World";
GetFileClient mockClient = mock(GetFileClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[4];
eh.handleEvent(new CompleteEvent(collectionID, Arrays.asList()));
return null;
}
}).when(mockClient).getFileFromFastestPillar(anyString(), anyString(), any(), any(), any(), any());
br.setGetFileClient(mockClient);
// mock file-exchange
FileExchange fe = mock(FileExchange.class);
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
File out = (File) invocation.getArguments()[0];
FileOutputStream fos = new FileOutputStream(out);
fos.write(FILE_CONTENT.getBytes());
fos.flush();
fos.close();
return null;
}
}).when(fe).getFile(any(File.class), anyString());
when(fe.getURL(anyString())).thenReturn(new URL("http://localhost:80/dav/test.txt"));
br.setFileExchange(fe);
File fr = br.getFile("helloworld.txt", "books", null);
byte[] payloadReturned = getPayload(fr);
String helloWorldReturned = new String(payloadReturned, "UTF-8");
assertEquals(FILE_CONTENT, helloWorldReturned);
verify(fe).getURL(anyString());
verify(fe).getFile(any(File.class), anyString());
verifyNoMoreInteractions(fe);
verify(mockClient).getFileFromFastestPillar(anyString(), anyString(), any(), any(), any(), anyString());
verifyNoMoreInteractions(mockClient);
FileUtils.delete(fr);
}
@Test(expected = YggdrasilException.class)
public void testGetFileFailureOperation() throws Exception {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetFileClient mockClient = mock(GetFileClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[4];
eh.handleEvent(new OperationFailedEvent(collectionID, "Is intended to fail", Arrays.asList()));
return null;
}
}).when(mockClient).getFileFromFastestPillar(anyString(), anyString(), any(), any(), any(), any());
br.setGetFileClient(mockClient);
// mock file-exchange
FileExchange fe = mock(FileExchange.class);
when(fe.getURL(anyString())).thenReturn(new URL("http://localhost:80/dav/test.txt"));
br.setFileExchange(fe);
br.getFile("helloworld.txt", "books", null);
}
@Test(expected = YggdrasilException.class)
public void testGetFileFailuredDownload() throws Exception {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetFileClient mockClient = mock(GetFileClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[4];
eh.handleEvent(new CompleteEvent(collectionID, Arrays.asList()));
return null;
}
}).when(mockClient).getFileFromFastestPillar(anyString(), anyString(), any(), any(), any(), any());
br.setGetFileClient(mockClient);
// mock file-exchange
FileExchange fe = mock(FileExchange.class);
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
throw new IOException("Fail downloading file.");
}
}).when(fe).getFile(any(File.class), anyString());
when(fe.getURL(anyString())).thenReturn(new URL("http://localhost:80/dav/test.txt"));
br.setFileExchange(fe);
br.getFile("helloworld.txt", "books", null);
}
@Test(expected = YggdrasilException.class)
public void getFileFailureBadURL() throws Exception {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetFileClient mockClient = mock(GetFileClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[4];
eh.handleEvent(new CompleteEvent(collectionID, Arrays.asList()));
return null;
}
}).when(mockClient).getFileFromFastestPillar(anyString(), anyString(), any(), any(), any(), any());
br.setGetFileClient(mockClient);
// mock file-exchange
FileExchange fe = mock(FileExchange.class);
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
throw new IOException("Fail downloading file.");
}
}).when(fe).getFile(any(File.class), anyString());
when(fe.getURL(anyString())).thenReturn(new URL("http://localhost:80/dav/test.txt"));
br.setFileExchange(fe);
br.getFile("helloworld.txt", "books", null);
}
@Test
public void testGetChecksumsSuccessEmptyResults() throws YggdrasilException, IOException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
String fileid = "The ID of the file";
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetChecksumsClient mockClient = mock(GetChecksumsClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[5];
eh.handleEvent(new CompleteEvent(collectionID, Arrays.asList()));
return null;
}
}).when(mockClient).getChecksums(anyString(), any(), anyString(), any(ChecksumSpecTYPE.class), any(), any(EventHandler.class), anyString());
br.setGetChecksumsClient(mockClient);
Map<String, ChecksumsCompletePillarEvent> res = br.getChecksums(fileid, "books");
verify(mockClient).getChecksums(anyString(), any(), anyString(), any(), any(), any(EventHandler.class), anyString());
verifyNoMoreInteractions(mockClient);
assertTrue("Should be empty.", res.isEmpty());
}
@Test
public void testGetChecksumsSuccessFullResults() throws YggdrasilException, IOException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
String fileid = "The ID of the file";
String collectionID = "books";
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetChecksumsClient mockClient = mock(GetChecksumsClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
ChecksumSpecTYPE checksumType = (ChecksumSpecTYPE) invocation.getArguments()[4];
EventHandler eh = (EventHandler) invocation.getArguments()[5];
ResultingChecksums resCs = new ResultingChecksums();
ChecksumDataForChecksumSpecTYPE csData = new ChecksumDataForChecksumSpecTYPE();
csData.setCalculationTimestamp(CalendarUtils.getNow());
csData.setChecksumValue("checksum".getBytes());
csData.setFileID(collectionID);
resCs.getChecksumDataItems().add(csData);
List<ContributorEvent> events = new ArrayList<ContributorEvent>();
for(String pillarID : SettingsUtils.getPillarIDsForCollection(collectionID)) {
ContributorEvent ce = new ChecksumsCompletePillarEvent(pillarID, collectionID, resCs, checksumType, false);
events.add(ce);
eh.handleEvent(ce);
}
eh.handleEvent(new CompleteEvent(collectionID, events));
return null;
}
}).when(mockClient).getChecksums(anyString(), any(), anyString(), any(ChecksumSpecTYPE.class), any(), any(EventHandler.class), anyString());
br.setGetChecksumsClient(mockClient);
Map<String, ChecksumsCompletePillarEvent> res = br.getChecksums(fileid, collectionID);
verify(mockClient).getChecksums(anyString(), any(), anyString(), any(), any(), any(EventHandler.class), anyString());
verifyNoMoreInteractions(mockClient);
assertFalse("Should not be empty.", res.isEmpty());
for(String pillarID : SettingsUtils.getPillarIDsForCollection(collectionID)) {
assertTrue(res.containsKey(pillarID));
assertNotNull(res.get(pillarID));
}
}
@Test
public void testGetChecksumsFailure() throws YggdrasilException, IOException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
String fileid = "The ID of the file";
String collectionID = "books";
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetChecksumsClient mockClient = mock(GetChecksumsClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[5];
List<ContributorEvent> events = new ArrayList<ContributorEvent>();
for(String pillarID : SettingsUtils.getPillarIDsForCollection(collectionID)) {
ContributorEvent ce = new ContributorFailedEvent(pillarID, collectionID, ResponseCode.FAILURE);
events.add(ce);
eh.handleEvent(ce);
}
eh.handleEvent(new OperationFailedEvent(collectionID, "Failure intended", events));
return null;
}
}).when(mockClient).getChecksums(anyString(), any(), anyString(), any(ChecksumSpecTYPE.class), any(), any(EventHandler.class), anyString());
br.setGetChecksumsClient(mockClient);
Map<String, ChecksumsCompletePillarEvent> res = br.getChecksums(fileid, collectionID);
verify(mockClient).getChecksums(anyString(), any(), anyString(), any(), any(), any(EventHandler.class), anyString());
verifyNoMoreInteractions(mockClient);
assertTrue("Should be empty.", res.isEmpty());
}
@Test
public void testGetFileIDsSuccess() throws YggdrasilException, IOException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
String fileid = "The ID of the file";
String collectionID = "books";
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetFileIDsClient mockClient = mock(GetFileIDsClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[4];
eh.handleEvent(new CompleteEvent(collectionID, Arrays.asList()));
return null;
}
}).when(mockClient).getFileIDs(anyString(), any(), anyString(), any(URL.class), any(EventHandler.class));
br.setGetFileIDsClient(mockClient);
boolean success = br.existsInCollection(fileid, collectionID);
assertTrue(success);
}
@Test
public void testGetFileIDsResponseFailure() throws YggdrasilException, IOException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
String fileid = "The ID of the file";
String collectionID = "books";
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
GetFileIDsClient mockClient = mock(GetFileIDsClient.class);
// Set the Complete action, when the event is called.
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String collectionID = (String) invocation.getArguments()[0];
EventHandler eh = (EventHandler) invocation.getArguments()[4];
List<ContributorEvent> events = new ArrayList<ContributorEvent>();
for(String pillarID : SettingsUtils.getPillarIDsForCollection(collectionID)) {
ContributorEvent ce = new ContributorFailedEvent(pillarID, collectionID, ResponseCode.FAILURE);
events.add(ce);
eh.handleEvent(ce);
}
eh.handleEvent(new OperationFailedEvent(collectionID, "Failure intended", events));
return null;
}
}).when(mockClient).getFileIDs(anyString(), any(), anyString(), any(URL.class), any(EventHandler.class));
br.setGetFileIDsClient(mockClient);
boolean success = br.existsInCollection(fileid, collectionID);
assertFalse(success);
}
@Test
public void testGetFileIDsCollectionFailure() throws YggdrasilException, IOException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
String fileid = "The ID of the file";
String collectionID = "NonExistingCollection";
BitrepositoryTestingAPI br = new BitrepositoryTestingAPI(okConfigFile);
boolean success = br.existsInCollection(fileid, collectionID);
assertFalse(success);
}
@Test
public void testGetCollections() throws YggdrasilException {
// if (TravisUtils.runningOnTravis()) {
// return;
// }
File okConfigFile = new File(OK_YAML_BITMAG_FILE);
Bitrepository br = new BitrepositoryTestingAPI(okConfigFile);
List<String> knownCols = br.getKnownCollections();
assertEquals(knownCols.size(), 5);
}
private File getFileWithContents(String packageId, byte[] payload) throws IOException {
File tempDir = new File("temporarydir");
if (tempDir.isFile()) {
fail("please remove file '" + tempDir.getAbsolutePath() + "'.");
}
tempDir.mkdirs();
File fr = new File(tempDir, packageId);
// Remove file if it exists
if (fr.exists()) {
fr.delete();
}
if (fr.exists()) {
fail("please remove file '" + fr.getAbsolutePath() + "'.");
}
OutputStream ous = new FileOutputStream(fr);
ous.write(payload);
ous.close();
return fr;
}
private byte[] getPayload(File fr) throws IOException {
InputStream is = new FileInputStream(fr);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b;
while ((b = is.read()) != -1) {
baos.write(b);
}
is.close();
baos.close();
return baos.toByteArray();
}
}