/*
* Copyright 2012, Facebook, Inc.
*
* 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.facebook.LinkBench;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
import junit.framework.TestCase;
import org.junit.Test;
/**
* This test implements unit tests that *all* implementations of NodeStore
* should pass.
*
* Different implementations of NodeStore will require different configuration
* and different setups for testing, so in order to test out a particular
* NodeStore implementation, you can subclass this test and implement the
* required abstract methods so that the test store is initialized correctly
* and all required configuration properties are filled in.
*
* @author tarmstrong
*/
public abstract class NodeStoreTestBase extends TestCase {
protected String testDB = "linkbench_unittestdb";
protected abstract void initNodeStore(Properties props)
throws Exception, IOException;
protected abstract NodeStore getNodeStoreHandle(boolean initialized)
throws Exception, IOException;
protected Properties basicProps() {
Properties props = new Properties();
props.setProperty(Config.DBID, testDB);
return props;
}
@Override
public void setUp() throws Exception {
super.setUp();
Properties props = basicProps();
// Set up db
initNodeStore(props);
getNodeStoreHandle(true).resetNodeStore(testDB, 0);
}
@Test
public void testIDAlloc() throws IOException, Exception {
int now = (int)(System.currentTimeMillis()/1000L);
NodeStore store = getNodeStoreHandle(true);
final int nodeType = 2048;
final long initId = 4; // We always start counting from 4 at Facebook
store.resetNodeStore(testDB, initId); // Start from clean store
byte data[] = new byte[] {0xb, 0xe, 0xa, 0x5, 0x7};
Node test = new Node(-1, nodeType, 1, now, data);
long id = store.addNode(testDB, test);
// Check id allocated
assertEquals("expected first ID allocated after reset", initId, id);
assertEquals("addNode should not modify arguments", -1, test.id);
test.id = id;
// Allocate another
id = store.addNode(testDB, test);
test.id = id;
long secondId = initId + 1;
assertEquals("expected second ID allocated after reset", secondId, id);
// Check retrieval
Node fetched = store.getNode(testDB, nodeType, secondId);
assertNotSame("Fetched nodes should not alias", fetched, test);
assertEquals("Check fetched node" + fetched + ".equals(" + test + ")",
test, fetched); // but should have same data
// Check deletion
assertTrue(store.deleteNode(testDB, nodeType, secondId));
assertNull(store.getNode(testDB, nodeType, secondId));
// Delete non-existent data
assertFalse("Deleting non-existent node should fail",
store.deleteNode(testDB, nodeType, 8));
int otherType = nodeType + 1;
assertFalse("Node should not be deleted if types don't match",
store.deleteNode(testDB, otherType, initId));
// Check reset works right
long newInitId = initId - 1;
store.resetNodeStore(testDB, newInitId);
assertNull("Nodes should be deleted after reset",
store.getNode(testDB, nodeType, newInitId));
assertEquals("Correct ID after second reset", newInitId,
store.addNode(testDB, test));
assertEquals("Correct ID after second reset", newInitId + 1,
store.addNode(testDB, test));
assertNotNull("Added node should exist",
store.getNode(testDB, nodeType, newInitId));
assertNotNull("Added node should exist",
store.getNode(testDB, nodeType, newInitId + 1));
}
@Test
public void testUpdate() throws IOException, Exception {
NodeStore store = getNodeStoreHandle(true);
store.resetNodeStore(testDB, 0);
Node test = new Node(-1, 1234, 3, 3, "the quick brown fox".getBytes());
test.id = store.addNode(testDB, test);
test.data = "jumped over the lazy dog".getBytes();
assertTrue(store.updateNode(testDB, test));
Node test2 = store.getNode(testDB, test.type, test.id);
assertNotNull(test2);
assertTrue(test.equals(test2));
}
@Test
public void testBinary() throws IOException, Exception {
byte data[] = new byte[4096];
for (int i = 0; i < data.length; i++) {
data[i] = (byte)(i % 256);
}
NodeStore store = getNodeStoreHandle(true);
store.resetNodeStore(testDB, 0);
Node test = new Node(-1, 1234, 3, 3, data);
test.id = store.addNode(testDB, test);
Node test2 = store.getNode(testDB, test.type, test.id);
assertNotNull(test2);
assertTrue(Arrays.equals(data, test2.data));
byte data2[] = new byte[data.length * 2];
for (int i = 0; i < data2.length; i++) {
data2[i] = (byte)((i + 52) % 256);
}
test.data = data2;
assertTrue(store.updateNode(testDB, test));
Node test3 = store.getNode(testDB, test.type, test.id);
assertNotNull(test3);
assertTrue(Arrays.equals(data2, test3.data));
}
}