/*
* Copyright 2012 Future Systems
*
* 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 org.krakenapps.confdb.file;
import static org.junit.Assert.*;
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.Inet4Address;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.krakenapps.confdb.CommitLog;
import org.krakenapps.confdb.Config;
import org.krakenapps.confdb.ConfigCollection;
import org.krakenapps.confdb.ConfigIterator;
import org.krakenapps.confdb.ConfigService;
public class ShrinkTest {
private File workingDir;
private FileConfigDatabase db;
private FileConfigCollection col1;
private FileConfigCollection col2;
private ConfigService conf;
@Before
public void start() throws IOException {
workingDir = new File(System.getProperty("user.dir"));
this.db = new FileConfigDatabase(workingDir, "testdb");
conf = new FileConfigService();
conf.ensureDatabase(db.getName());
this.col1 = (FileConfigCollection) db.ensureCollection("testcol1");
}
@After
public void teardown() throws IOException {
db.purge();
for (File f : new File(workingDir, "testdb").listFiles()) {
if (f.getName().startsWith("old_"))
f.delete();
}
}
// no exist manifest and changeset, import data
@Test
public void testEmptyImport() throws IOException, ParseException, JSONException {
db = new FileConfigDatabase(workingDir, "testdb");
col1 = (FileConfigCollection) db.ensureCollection("testcol1");
col1.add(createObject(100));
int rev = (int) db.getCommitLogs().get(0).getRev();
assertEquals(2, db.getCommitCount());
List<Object> oldDocs = getDocument("testcol1");
export(rev);
db.purge();
importData(rev);
List<Object> newDocs = getDocument("testcol1");
for (int index = 0; index < oldDocs.size(); index++) {
if (oldDocs.get(index) instanceof List)
break;
assertTrue(compareObject(oldDocs.get(index), newDocs.get(index)));
}
new File(db.getDbDirectory(), "export_" + rev + ".txt").delete();
}
// Exist manifest and changeset, import data
@Test
public void testExistImport() throws IOException, ParseException, JSONException {
for (int id = 0; id < 10; id++)
col1.add(createObject(id));
List<CommitLog> logs = db.getCommitLogs();
Comparator<CommitLog> comparator = new Comparator<CommitLog>() {
@Override
public int compare(CommitLog o1, CommitLog o2) {
Long rev1 = o1.getRev();
return rev1.compareTo(o2.getRev());
}
};
assertEquals(11, db.getCommitCount());
assertEquals(1, db.getManifest(null).getCollectionId("testcol1"));
Collections.sort(logs, comparator);
export((int) logs.get(logs.size() - 1).getRev());
db.purge();
this.col2 = (FileConfigCollection) db.ensureCollection("testcol2");
col2.add(createObject(20));
assertEquals(1, db.getCollectionNames().size());
assertTrue(db.getCollectionNames().contains("testcol2"));
assertFalse(db.getCollectionNames().contains("testcol1"));
importData((int) logs.get(logs.size() - 1).getRev());
assertEquals(1, db.getCollectionNames().size());
assertTrue(db.getCollectionNames().contains("testcol1"));
assertFalse(db.getCollectionNames().contains("testcol2"));
assertEquals(2, db.getManifest(null).getCollectionId("testcol1"));
importData((int) logs.get(logs.size() - 1).getRev());
new File(db.getDbDirectory(), "export_" + logs.get(logs.size() - 1).getRev() + ".txt").delete();
}
@Test
public void testCreateLogShrink() throws IOException {
for (int id = 0; id < 10; id++)
col1.add(createObject(id));
assertEquals(11, db.getCommitCount());
List<Object> oldDocs = getDocument("testcol1");
db.shrink(1);
assertEquals(1, db.getCommitCount());
List<Object> newDocs = getDocument("testcol1");
for (int index = 0; index < oldDocs.size(); index++) {
if (oldDocs.get(index) instanceof List)
break;
assertTrue(compareObject(oldDocs.get(index), newDocs.get(index)));
}
}
@Test
public void testUpdateLogShrink() throws IOException {
Config c = null;
for (int id = 0; id < 10; id++)
c = col1.add(createObject(id));
c.setDocument(createObject(150));
c.update();
List<Object> oldDocs = getDocument("testcol1");
assertEquals(12, db.getCommitCount());
db.shrink(1);
assertEquals(1, db.getCommitCount());
List<Object> newDocs = getDocument("testcol1");
for (int index = 0; index < oldDocs.size(); index++) {
if (oldDocs.get(index) instanceof List)
break;
assertTrue(compareObject(oldDocs.get(index), newDocs.get(index)));
}
}
@SuppressWarnings("unchecked")
private boolean compareObject(Object oldDoc, Object newDoc) {
Map<String, Object> oldMap = (Map<String, Object>) oldDoc;
Map<String, Object> newMap = (Map<String, Object>) newDoc;
if (!oldMap.get("int").equals(newMap.get("int")))
return false;
if (!oldMap.get("double").equals(newMap.get("double")))
return false;
if (!oldMap.get("float").equals(newMap.get("float")))
return false;
if (!oldMap.get("string").equals(newMap.get("string")))
return false;
if (!oldMap.get("date").toString().equals(newMap.get("date").toString()))
return false;
if (!oldMap.get("bool").equals(newMap.get("bool")))
return false;
if (!oldMap.get("ip4").equals(newMap.get("ip4")))
return false;
if (!oldMap.get("ip6").equals(newMap.get("ip6")))
return false;
if (!(oldMap.get("null") == null && newMap.get("null") == null))
return false;
if (!oldMap.get("long").equals(newMap.get("long")))
return false;
if (!(oldMap.get("byte") == null)) {
byte[] oldByte = (byte[]) oldMap.get("byte");
byte[] newByte = (byte[]) newMap.get("byte");
return Arrays.equals(oldByte, newByte);
}
return true;
}
private List<Object> getDocument(String name) {
List<Object> docs = new ArrayList<Object>();
ConfigCollection col = db.getCollection(name);
ConfigIterator it = col.findAll();
try {
while (it.hasNext()) {
Object doc = it.next().getDocument();
docs.add(doc);
}
} finally {
it.close();
}
docs.add(docs);
return docs;
}
private Object createObject(int id) throws UnknownHostException {
double doubleData = Math.PI;
float floatData = Float.MAX_VALUE;
String stringData = "test number " + id;
boolean boolData = (id % 2) == 0 ? true : false;
Date dateData = new Date();
Object nullData = null;
Inet4Address ip4Data = (Inet4Address) Inet4Address.getByName("172.0.0.1");
Inet6Address ip6Data = (Inet6Address) Inet6Address.getByName("1080:0:0:0:8:800:200C:417A");
Object o1 = "object1";
Object o2 = "object2";
long longData = Long.MAX_VALUE;
Short shortData = Short.MAX_VALUE;
Object[] os = new Object[2];
os[0] = o1;
os[1] = o2;
int[] i = new int[] { 1, 2, 3 };
Map<String, Object> m = new HashMap<String, Object>();
m.put("int", id);
m.put("double", doubleData);
m.put("float", floatData);
m.put("string", stringData);
m.put("bool", boolData);
m.put("date", dateData);
m.put("null", nullData);
m.put("ip4", ip4Data);
m.put("ip6", ip6Data);
m.put("byte", createByteArray());
m.put("object", os);
m.put("long", longData);
m.put("short", shortData);
m.put("int_array", i);
return m;
}
private Object createByteArray() {
byte[] binary = new byte[256];
byte b = Byte.MIN_VALUE;
int i = 0;
while (true) {
binary[i++] = b++;
if (b == Byte.MAX_VALUE)
break;
}
return binary;
}
private void export(int rev) throws IOException {
File exportFile = new File(System.getProperty("user.dir") + File.separatorChar + db.getName(), "export_" + rev + ".txt");
if (exportFile.exists())
exportFile.delete();
FileConfigDatabase fdb = new FileConfigDatabase(new File(System.getProperty("user.dir")), "testdb", rev);
OutputStream os = new FileOutputStream(exportFile);
fdb.exportData(os);
os.close();
}
private void importData(int rev) throws IOException {
InputStream is = new FileInputStream(new File(db.getDbDirectory(), "export_" + rev + ".txt"));
db.importData(is);
is.close();
}
}