/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*
* $Id: FilerTestBase.java 541504 2007-05-25 01:43:39Z vgritsenko $
*/
package org.apache.xindice.core.filer;
import org.apache.xindice.core.data.Key;
import org.apache.xindice.core.data.Record;
import org.apache.xindice.core.data.RecordSet;
import org.apache.xindice.core.data.Value;
import org.apache.xindice.util.Configuration;
import org.apache.xindice.xml.dom.DOMParser;
import junit.framework.TestCase;
import java.io.File;
import java.util.List;
import java.util.Vector;
/**
* Base class for filer test cases
*
* @version $Revision: 541504 $, $Date: 2007-05-24 21:43:39 -0400 (Thu, 24 May 2007) $
* @author <a href="mailto:kstaken@xmldatabases.org">Kimbro Staken</a>
* @author <a href="mailto:vladimir@apache.org">Vladimir R. Bossicard</a>
* @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
*/
public abstract class FilerTestBase extends TestCase {
public static final String TEST_COLLECTION_NAME = "tests";
public static final Key TEST_KEY = new Key("test.xml");
public static final Value TEST_VALUE = new Value("<test><test></test><test>Just a test</test></test>");
public static final Value TEST_VALUE_2 = new Value("<test><test></test><test>Just a test 2</test></test>");
public static final Value TEST_VALUE_3 = new Value("<test><test></test><test>Just a test 3</test></test>");
private static final File ROOT = new File(TEST_COLLECTION_NAME);
/**
* Key size for the testLargeKey. FSFiler and HashFiler will set smaller value
* for their tests.
*/
protected int LARGE_KEY_SIZE = 8192 + 32;
protected Filer filer;
private String testName;
public FilerTestBase(String name, Filer filer) {
super(name);
this.filer = filer;
// After teardown filer is null and getName still can be called
testName = this.filer.getName() + " " + super.getName();
}
public void setUp() throws Exception {
ROOT.mkdir();
filer.setLocation(ROOT, TEST_COLLECTION_NAME);
// FSFiler needs location attribute
String config = "<filer location='" + TEST_COLLECTION_NAME + "' " +
"pagecount='128' pagesize='4096'/>";
filer.setConfig(new Configuration(DOMParser.toDocument(config)));
if (!filer.exists()) {
filer.create();
}
filer.open();
RecordSet set = filer.getRecordSet();
while (set.hasMoreRecords()) {
Key key = set.getNextKey();
filer.deleteRecord(key);
}
assertEquals(0, filer.getRecordCount());
}
protected void tearDown() throws Exception {
if (filer != null) {
filer.close();
}
filer = null;
String[] files = ROOT.list();
for (int i = 0; i < files.length; i++) {
assertTrue(new File(ROOT, files[i]).delete());
}
ROOT.delete();
super.tearDown();
}
public String getName() {
return testName;
}
public void testSuccessWriteRecord() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
Record result = filer.readRecord(TEST_KEY, false);
assertEquals(TEST_VALUE, result.getValue());
RecordSet set = filer.getRecordSet();
assertEquals(result.getValue(), set.getNextRecord().getValue());
assertFalse(set.hasMoreRecords());
filer.deleteRecord(TEST_KEY);
assertEquals(0, filer.getRecordCount());
}
public void testFailReadDeletedRecord() throws Exception {
Record result = filer.readRecord(TEST_KEY, false);
assertNull(result);
}
public void testFailWriteRecordNullKey() throws Exception {
try {
filer.writeRecord(null, TEST_VALUE);
fail("Expecting FilerException");
} catch (FilerException e) {
// Ok
}
}
public void testFailWriteRecordNullValue() throws Exception {
try {
filer.writeRecord(TEST_KEY, null);
fail("Expecting FilerException");
} catch (FilerException e) {
// Ok
}
}
public void testFailWriteRecordNullValueKey() throws Exception {
try {
filer.writeRecord(null, null);
fail("Expecting FilerException");
} catch (FilerException e) {
// Ok
}
}
public void testReadRecord() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// Valid key
Record result = filer.readRecord(TEST_KEY, false);
assertEquals(TEST_VALUE, result.getValue());
}
public void testFailReadRecordNullKey() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// Null key
Record result = filer.readRecord(null, false);
assertNull(result);
}
public void testFailReadRecordEmptyKey() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// Empty key
Record result = filer.readRecord(new Key(""), false);
assertNull(result);
}
public void testFailReadRecordUnknownKey() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// Non-existant key
Record result = filer.readRecord(new Key("non-existant-key"), false);
assertNull(result);
}
public void testDeleteRecord() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// Valid key
filer.deleteRecord(TEST_KEY);
assertEquals(0, filer.getRecordCount());
Record result = filer.readRecord(TEST_KEY, false);
assertNull(result);
}
public void testDeleteRecordNullKey() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// These should all just fail silently.
assertFalse(filer.deleteRecord(null));
assertEquals(1, filer.getRecordCount());
}
public void testDeleteRecordEmptyKey() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// These should all just fail silently.
assertFalse(filer.deleteRecord(new Key("")));
assertEquals(1, filer.getRecordCount());
}
public void testDeleteRecordWrongKey() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
assertEquals(1, filer.getRecordCount());
// These should all just fail silently.
assertFalse(filer.deleteRecord(new Key("non-existant-key")));
assertEquals(1, filer.getRecordCount());
}
public void testGetRecordCount() throws Exception {
assertEquals(0, filer.getRecordCount());
filer.writeRecord(TEST_KEY, TEST_VALUE);
filer.writeRecord(new Key("test1"), TEST_VALUE);
filer.writeRecord(new Key("test2"), TEST_VALUE);
assertEquals(3, filer.getRecordCount());
filer.writeRecord(new Key("test3"), TEST_VALUE);
assertEquals(4, filer.getRecordCount());
assertTrue(filer.deleteRecord(new Key("test3")));
assertEquals(3, filer.getRecordCount());
assertTrue(filer.deleteRecord(TEST_KEY));
assertTrue(filer.deleteRecord(new Key("test1")));
assertTrue(filer.deleteRecord(new Key("test2")));
assertEquals(0, filer.getRecordCount());
}
public void testGetRecordSet() throws Exception {
filer.writeRecord(TEST_KEY, TEST_VALUE);
filer.writeRecord(new Key("test2"), TEST_VALUE_2);
filer.writeRecord(new Key("test3"), TEST_VALUE_3);
RecordSet result = filer.getRecordSet();
assertNotNull(result);
List results = new Vector();
while (result.hasMoreRecords()) {
results.add(result.getNextRecord().getValue());
}
assertEquals(3, results.size());
assertTrue(results.contains(TEST_VALUE));
assertTrue(results.contains(TEST_VALUE_2));
assertTrue(results.contains(TEST_VALUE_3));
assertTrue(filer.deleteRecord(TEST_KEY));
assertTrue(filer.deleteRecord(new Key("test2")));
assertTrue(filer.deleteRecord(new Key("test3")));
result = filer.getRecordSet();
assertTrue(!result.hasMoreRecords());
}
public void testInsertManyDocuments() throws Exception {
int iterations = 1000;
for (int i = 0; i < iterations; i++) {
filer.writeRecord(new Key("key" + i), TEST_VALUE);
}
assertTrue(filer.getRecordCount() == iterations);
for (int i = 0; i < iterations; i++) {
assertTrue(filer.deleteRecord(new Key("key" + i)));
}
assertTrue(filer.getRecordCount() == 0);
RecordSet result = filer.getRecordSet();
assertTrue(!result.hasMoreRecords());
}
public void testConcurrentInsert() throws Exception {
assertEquals(0, filer.getRecordCount());
final Object go = new Object();
final int THREADS = 30;
final int ITERATIONS = 65;
Thread[] threads = new Thread[THREADS];
for (int i = 0; i < THREADS; i++) {
final int threadID = i;
threads[i] = new Thread() {
public void run() {
synchronized (go) {
try {
go.wait();
} catch (InterruptedException e) { /* ignored */ }
}
for (int ii = 0; ii < ITERATIONS; ii++) {
Key key = new Key("T" + threadID + "I" + ii);
Value value = new Value("<test thread=\"" + threadID + "\" iteration=\"" + ii + "\"/>");
try {
filer.writeRecord(key, value);
} catch (Exception e) {
e.printStackTrace();
}
}
// System.out.println(this.getName() + " done.");
}
};
threads[i].setName("FilerTest" + i);
threads[i].start();
}
// Start all the threads at once
Thread.sleep(250);
synchronized (go) {
go.notifyAll();
}
for (int i = 0; i < THREADS; i++) {
threads[i].join();
}
// Check results
assertEquals(THREADS * ITERATIONS, filer.getRecordCount());
for (int i = 0; i < THREADS; i++) {
for (int ii = 0; ii < ITERATIONS; ii++) {
Key key = new Key("T" + i + "I" + ii);
Value value = new Value("<test thread=\"" + i + "\" iteration=\"" + ii + "\"/>");
Record record = filer.readRecord(key, false);
assertNotNull("Record with key '" + key + "' was not found",
record);
assertEquals("Expected record with key '" + key + "', found record with key '" + record.getKey() + "'",
key, record.getKey());
assertEquals("Expected record with value '" + value + "', found record with value '" + record.getValue() + "'",
value, record.getValue());
}
}
}
public void testConcurrentSameInsert() throws Exception {
assertTrue(filer.getRecordCount() == 0);
final int THREADS = 10;
final int ITERATIONS = 5;
Thread[] threads = new Thread[THREADS];
for (int i = 0; i < THREADS; i++) {
threads[i] = new Thread() {
public void run() {
for (int ii = 0; ii < ITERATIONS; ii++) {
Key key = new Key("key");
Value value = new Value("<test document/>");
try {
filer.writeRecord(key, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
threads[i].setName("FilerTest" + i);
}
// Start all the threads at once
for (int i = 0; i < THREADS; i++) {
threads[i].start();
}
Thread.sleep(100);
for (int i = 0; i < THREADS; i++) {
threads[i].join();
}
filer.flush();
// Check results
assertEquals(1, filer.getRecordCount());
Key key = new Key("key");
Value value = new Value("<test document/>");
Record record = filer.readRecord(key, false);
assertNotNull("Record with key '" + key + "' was not found", record);
assertEquals("Expected record with key '" + key + "', found record with key '" + record.getKey() + "'",
key, record.getKey());
assertEquals("Expected record with value '" + value + "', found record with value '" + record.getValue() + "'",
value, record.getValue());
}
public void testLargeKey() throws Exception {
assertTrue(filer.getRecordCount() == 0);
StringBuffer sb = new StringBuffer(LARGE_KEY_SIZE);
sb.append("KEY");
for (int k = 0; k < LARGE_KEY_SIZE - 3; k++) {
sb.append('0');
}
final Key key = new Key(sb.toString());
final Value value = new Value("<test/>");
filer.writeRecord(key, value);
assertEquals(filer.getRecordCount(), 1);
Record record = filer.readRecord(key, false);
assertNotNull("Record with key '" + key + "' was not found",
record);
assertEquals("Expected record with key '" + key + "', found record with key '" + record.getKey() + "'",
key, record.getKey());
assertEquals("Expected record with value '" + value + "', found record with value '" + record.getValue() + "'",
value, record.getValue());
}
}