blob: 290119fd20ed0b7acd3f88c61e020af2c72e09bd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2011 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.tests.services.datalocation;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.storagemanager.ManagedOutputStream;
import org.eclipse.osgi.storagemanager.StorageManager;
import org.eclipse.osgi.tests.OSGiTest;
public class StreamManagerTests extends OSGiTest {
StorageManager manager1;
StorageManager manager2;
File base;
String reliableFile;
/**
* Constructs a test case with the given name.
*/
public StreamManagerTests(String name) {
super(name);
}
public static Test suite() {
return new TestSuite(StreamManagerTests.class);
}
protected void setUp() throws Exception {
super.setUp();
base = new File(Platform.getConfigurationLocation().getURL().getPath(), "StreamManagerTests");
manager1 = null;
manager2 = null;
reliableFile = System.getProperty("osgi.useReliableFiles");
}
protected void tearDown() throws Exception {
super.tearDown();
if (manager1 != null)
manager1.close();
if (manager2 != null)
manager2.close();
rm(base);
if (reliableFile == null)
System.getProperties().remove("osgi.useReliableFiles");
else
System.setProperty("osgi.useReliableFiles", reliableFile);
}
private void rm(File folder) {
if (folder.isDirectory()) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
rm(file);
}
}
}
folder.delete();
}
private String getInputStreamContents(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
byte[] data = new byte[64];
int len;
try {
while ((len = is.read(data)) != -1) {
sb.append(new String(data, 0, len));
}
} finally {
is.close();
}
return sb.toString();
}
void writeToFile(File file, String str) throws IOException {
FileOutputStream fos = new FileOutputStream(file);
try {
fos.write(str.getBytes());
fos.flush();
fos.getFD().sync();
} finally {
fos.close();
}
}
/**
* This tests that FM will keep a backup version of a reliableFile and that
* corrupting the reliableFile will recover the previous contents.
*
*/
public void testReliableFile() {
String fileName = "testReliableFile.txt";
File file1 = new File(base, fileName + ".1");
File file2 = new File(base, fileName + ".2");
File file3 = new File(base, fileName + ".3");
String contents1 = "test reliable file cOntents #1";
String contents2 = "test reliable file cOntents #2";
try {
System.setProperty("osgi.useReliableFiles", "true"); // force reliable files
manager1 = new StorageManager(base, null);
manager1.open(true);
ManagedOutputStream fmos = manager1.getOutputStream(fileName);
assertNotNull(fmos);
fmos.write(contents1.getBytes());
fmos.close();
// Write verion2 of the file
fmos = manager1.getOutputStream(fileName);
assertNotNull(fmos);
fmos.write(contents2.getBytes());
fmos.close();
assertTrue(file1.exists());
assertTrue(file2.exists());
assertTrue(!file3.exists());
manager1.close();
manager1 = null;
//now, open new manager, verify file contents are #2
System.setProperty("osgi.useReliableFiles", "true"); // force reliable files
manager2 = new StorageManager(base, null);
manager2.open(true);
InputStream is = manager2.getInputStream(fileName);
assertNotNull(is);
assertEquals(contents2, getInputStreamContents(is));
manager2.close();
manager2 = null;
// need to sleep, FAT32 doesn't have too fine granularity in timestamps
try {
Thread.sleep(5000);
} catch (InterruptedException e) {/*ignore*/
}
//now, corrupt version 2 of the file
RandomAccessFile raf = new RandomAccessFile(file2, "rw");
raf.seek(20);
raf.write('0'); // change 'O' to '0'
raf.close();
System.setProperty("osgi.useReliableFiles", "true"); // force reliable files
manager1 = new StorageManager(base, null);
manager1.open(true);
//request any valid stream available
is = manager1.getInputStream(fileName);
assertNotNull(is);
assertEquals(contents1, getInputStreamContents(is));
//now request only the primary file
try {
InputStream[] isSet = manager1.getInputStreamSet(new String[] {fileName});
for (InputStream set : isSet) {
if (set != null) {
set.close();
}
}
fail("getInputStreamSet was successful");
} catch (IOException e) {
//good
}
//now, corrupt version 1 of the file
raf = new RandomAccessFile(file1, "rw");
raf.seek(20);
raf.write('0'); // change 'O' to '0'
raf.close();
// get input stream should fail
try {
is = manager1.getInputStream(fileName);
fail("get input stream succedded");
} catch (IOException e) {
//good
}
manager1.close();
manager1 = null;
} catch (IOException e) {
fail("unexepected exception", e);
} finally {
System.setProperty("osgi.useReliableFiles", "false"); // force reliable files off
}
}
public void testBigReliableFile() {
String fileName = getName() + ".txt";
try {
System.setProperty("osgi.useReliableFiles", "true"); // force reliable files
manager1 = new StorageManager(base, null);
manager1.open(true);
try (ManagedOutputStream fmos = manager1.getOutputStream(fileName)) {
assertNotNull(fmos);
try (DataOutputStream bufferedOut = new DataOutputStream(new BufferedOutputStream(fmos))) {
// 200 K of integers (200 * 1024 / 4)
for (int i = 0; i < (200 * 1024 / 4); i++)
bufferedOut.writeInt(i);
}
}
manager1.close();
manager1 = null;
//now, open new manager, verify file contents are there
System.setProperty("osgi.useReliableFiles", "true"); // force reliable files
manager2 = new StorageManager(base, null);
manager2.open(true);
try (InputStream is = manager2.getInputStream(fileName)) {
assertNotNull(is);
try (DataInputStream bufferedIn = new DataInputStream(new BufferedInputStream(is))) {
for (int i = 0; i < (200 * 1024 / 4); i++)
assertEquals("Wrong content found", i, bufferedIn.readInt());
}
}
manager2.close();
manager2 = null;
} catch (IOException e) {
fail("unexepected exception", e);
}
}
/**
* This tests if migration from a prior (non-ReliableFile) .fileTable
* to the current .fileTable is correct.
*
*/
public void testMigration() {
File testDir = new File(base, "testMigrationManager");
File managerDir = new File(testDir, ".manager");
String fileName = "testMigration.txt";
File file2 = new File(testDir, fileName + ".2");
File file5 = new File(testDir, fileName + ".5");
File fileTable = new File(managerDir, ".fileTable");
File fileTable1 = new File(managerDir, ".fileTable.1");
File fileTable2 = new File(managerDir, ".fileTable.2");
File fileTable3 = new File(managerDir, ".fileTable.3");
String contents1 = "test reliable file contents #1";
String contents2 = "test reliable file contents #2";
String contents3 = "test reliable file contents #3";
try {
// create a .fileTable and a normal file
managerDir.mkdirs();
writeToFile(fileTable, "#safe table\n" + fileName + "=2\n");
writeToFile(file2, contents1);
manager1 = new StorageManager(testDir, null);
manager1.open(true);
File test = manager1.lookup(fileName, false);
assertNotNull(test);
assertTrue(test.exists());
// update a new file
File testFile = manager1.createTempFile(fileName);
writeToFile(testFile, contents2);
manager1.update(new String[] {fileName}, new String[] {testFile.getName()});
// again
testFile = manager1.createTempFile(fileName);
writeToFile(testFile, contents3);
manager1.update(new String[] {fileName}, new String[] {testFile.getName()});
// again
testFile = manager1.createTempFile(fileName);
writeToFile(testFile, contents1);
manager1.update(new String[] {fileName}, new String[] {testFile.getName()});
manager1.close();
manager1 = null;
String[] files = managerDir.list();
assertEquals(4, files.length);
//original file never gets deleted
assertTrue(fileTable.exists());
//behaves like a reliableFile?
assertFalse(fileTable1.exists());
assertTrue(fileTable2.exists());
assertTrue(fileTable3.exists());
//files are as expected?
files = testDir.list();
assertEquals(2, files.length);
assertTrue(file5.exists());
manager2 = new StorageManager(testDir, null);
manager2.open(true);
testFile = manager2.lookup(fileName, false);
assertNotNull(testFile);
assertTrue(testFile.exists());
assertTrue(testFile.getName().endsWith(".5"));
manager2.close();
manager2 = null;
} catch (IOException e) {
fail("unexepected exception", e);
}
}
/**
* This tests that an output stream abort behave as expected.
*
*/
public void testAbort() {
testAbort(true);
testAbort(false);
}
private void testAbort(boolean reliable) {
String fileName;
if (reliable)
fileName = "abortFileReliable.txt";
else
fileName = "abortFileStd.txt";
File file1 = new File(base, fileName + ".1");
File file2 = new File(base, fileName + ".2");
File file3 = new File(base, fileName + ".3");
String contents1 = "test reliable file contents #1";
String contents2 = "test reliable file contents #2";
try {
System.setProperty("osgi.useReliableFiles", "true"); // force reliable files
manager1 = new StorageManager(base, null);
manager1.open(true);
//create version 1
ManagedOutputStream smos = manager1.getOutputStream(fileName);
smos.write(contents1.getBytes());
smos.close();
//start creating version 2
smos = manager1.getOutputStream(fileName);
smos.write(contents2.getBytes());
smos.abort();
smos.close(); // shouldn't cause exception, check!
// now see if we're still on version #1
assertEquals(1, manager1.getId(fileName));
// check contents also
InputStream is = manager1.getInputStream(fileName);
assertNotNull(is);
assertEquals(contents1, getInputStreamContents(is));
manager1.close();
manager1 = null;
// open a new manager & check the same thing to ensure the database is correct
System.setProperty("osgi.useReliableFiles", "true"); // force reliable files
manager2 = new StorageManager(base, null);
manager2.open(true);
//create version 1
// now see if we're still on version #1
assertEquals(1, manager2.getId(fileName));
// check contents also
is = manager2.getInputStream(fileName);
assertNotNull(is);
assertEquals(contents1, getInputStreamContents(is));
manager2.close();
manager2 = null;
assertTrue(file1.exists());
assertFalse(file2.exists());
assertFalse(file3.exists());
} catch (IOException e) {
fail("unexepected exception", e);
}
}
/**
* This tests if getting an output stream-set work properly.
*
*/
public void testGetOutputStreamSet() {
testGetOutputStreamSet(true);
testGetOutputStreamSet(false);
}
private void testGetOutputStreamSet(boolean reliable) {
File mgrDir;
if (reliable)
mgrDir = new File(base, "getSetReliable");
else
mgrDir = new File(base, "getSetStd");
String fileName1 = "testSet1.txt";
String fileName2 = "testSet2.txt";
File file1_1 = new File(mgrDir, fileName1 + ".1");
File file1_2 = new File(mgrDir, fileName1 + ".2");
File file2_1 = new File(mgrDir, fileName2 + ".1");
File file2_2 = new File(mgrDir, fileName2 + ".2");
String contents1 = "test reliable file contents #1";
String contents2 = "test reliable file contents #2";
try {
System.setProperty("osgi.useReliableFiles", reliable ? "true" : "false"); // force reliable files
manager1 = new StorageManager(mgrDir, null);
manager1.open(true);
ManagedOutputStream[] outs = manager1.getOutputStreamSet(new String[] {fileName1, fileName2});
assertNotNull(outs);
assertEquals(2, outs.length);
outs[0].write(contents1.getBytes());
outs[1].write(contents2.getBytes());
outs[1].close();
assertFalse(file1_1.exists());
assertFalse(file2_1.exists());
outs[0].close();
assertTrue(file1_1.exists());
assertTrue(file2_1.exists());
outs = manager1.getOutputStreamSet(new String[] {fileName1, fileName2});
assertNotNull(outs);
outs[0].write("new data #1".getBytes());
outs[1].write("new data #2".getBytes());
outs[0].close();
assertFalse(file1_2.exists());
assertFalse(file2_2.exists());
outs[1].close();
assertTrue(file1_2.exists());
assertTrue(file2_2.exists());
manager1.close();
manager1 = null;
if (reliable) {
// verify FM thinks they are reliable
assertTrue(file1_1.exists());
assertTrue(file2_1.exists());
} else {
// verify FM thinks they are not reliable
assertFalse(file1_1.exists());
assertFalse(file2_1.exists());
}
} catch (IOException e) {
fail("unexepected exception", e);
}
}
/**
* This tests if aborting a managed stream-set works as expected
*
*/
public void testAbortStreamSet() {
testAbortSet(true);
testAbortSet(false);
}
private void testAbortSet(boolean reliable) {
File mgrDir;
if (reliable)
mgrDir = new File(base, "abortSetReliable");
else
mgrDir = new File(base, "abortSetStd");
String fileName1 = "test1.txt";
String fileName2 = "test2.txt";
String fileName3 = "test3.txt";
String fileName4 = "test4.txt";
String contents1 = "test reliable file contents #1";
String contents2 = "test reliable file contents #2";
try {
mgrDir.mkdirs();
String[] list = mgrDir.list();
assertEquals(0, list.length);
System.setProperty("osgi.useReliableFiles", reliable ? "true" : "false"); // force reliable files
manager1 = new StorageManager(mgrDir, null);
manager1.open(true);
ManagedOutputStream[] outs = manager1.getOutputStreamSet(new String[] {fileName1, fileName2, fileName3, fileName4});
assertNotNull(outs);
outs[0].write(contents1.getBytes());
outs[1].write(contents2.getBytes());
outs[2].write(contents2.getBytes());
outs[3].write(contents1.getBytes());
//sanity check
list = mgrDir.list();
assertEquals(5, list.length);
outs[2].close();
outs[1].abort();
outs[0].close(); //noop
outs[3].close(); //noop
outs[2].close(); //noop
outs[1].close(); //noop
list = mgrDir.list();
assertEquals(1, list.length);
assertNull(manager1.lookup(fileName1, false));
assertNull(manager1.lookup(fileName2, false));
assertNull(manager1.lookup(fileName3, false));
assertNull(manager1.lookup(fileName4, false));
manager1.close();
manager1 = null;
// open a new manager & check the same thing to ensure the database is correct
System.setProperty("osgi.useReliableFiles", reliable ? "true" : "false"); // force reliable files
manager2 = new StorageManager(mgrDir, null);
manager2.open(true);
//create version 1
assertNull(manager2.lookup(fileName1, false));
assertNull(manager2.lookup(fileName2, false));
assertNull(manager2.lookup(fileName3, false));
assertNull(manager2.lookup(fileName4, false));
list = mgrDir.list();
assertEquals(1, list.length);
manager2.close();
manager2 = null;
} catch (IOException e) {
fail("unexepected exception", e);
}
}
}