/* * Copyright (c) 2013-2017 Cinchapi 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.cinchapi.concourse.server.storage.db; import java.io.File; import java.lang.reflect.Field; import java.util.Iterator; import java.util.List; import java.util.Set; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import com.cinchapi.concourse.server.io.FileSystem; import com.cinchapi.concourse.server.model.PrimaryKey; import com.cinchapi.concourse.server.model.Text; import com.cinchapi.concourse.server.model.Value; import com.cinchapi.concourse.server.storage.Store; import com.cinchapi.concourse.server.storage.StoreTest; import com.cinchapi.concourse.server.storage.db.Database; import com.cinchapi.concourse.server.storage.db.Revision; import com.cinchapi.concourse.server.storage.temp.Write; import com.cinchapi.concourse.test.Variables; import com.cinchapi.concourse.thrift.Operator; import com.cinchapi.concourse.thrift.TObject; import com.cinchapi.concourse.time.Time; import com.cinchapi.concourse.util.Convert; import com.cinchapi.concourse.util.TestData; import com.google.common.collect.Sets; /** * Unit tests for the {@link Database}. * * @author Jeff Nelson */ public class DatabaseTest extends StoreTest { private String current; @Test public void testDatabaseRemovesUnbalancedBlocksOnStartup() throws Exception { Database db = (Database) store; db.accept(Write.add(TestData.getString(), TestData.getTObject(), TestData.getLong())); db.triggerSync(); db.stop(); FileSystem.deleteDirectory(current + File.separator + "csb"); FileSystem.mkdirs(current + File.separator + "csb"); db = new Database(db.getBackingStore()); // simulate server restart db.start(); Field cpb = db.getClass().getDeclaredField("cpb"); Field csb = db.getClass().getDeclaredField("csb"); Field ctb = db.getClass().getDeclaredField("ctb"); cpb.setAccessible(true); csb.setAccessible(true); ctb.setAccessible(true); Assert.assertEquals(1, ((List<?>) ctb.get(db)).size()); Assert.assertEquals(1, ((List<?>) csb.get(db)).size()); Assert.assertEquals(1, ((List<?>) cpb.get(db)).size()); } @Test(expected = UnsupportedOperationException.class) public void testGetAllRecords() { Database db = (Database) store; db.getAllRecords(); } @Test public void testDatabaseAppendsToCachedPartialPrimaryRecords() { Database db = (Database) store; String key = TestData.getString(); long record = TestData.getLong(); int count = TestData.getScaleCount(); for (int i = 0; i < count; i++) { db.accept(Write.add(key, Convert.javaToThrift(i), record)); } db.select(key, record); int increase = TestData.getScaleCount(); db.accept( Write.add(key, Convert.javaToThrift(count * increase), record)); Assert.assertTrue(db.select(key, record) .contains(Convert.javaToThrift(count * increase))); } @Test public void testDatabaseAppendsToCachedSecondaryRecords() { Database db = (Database) store; String key = TestData.getString(); TObject value = TestData.getTObject(); int count = TestData.getScaleCount(); for (int i = 0; i < count; i++) { db.accept(Write.add(key, value, i)); } db.find(key, Operator.EQUALS, value); int increase = TestData.getScaleCount(); db.accept(Write.add(key, value, count * increase)); Assert.assertTrue(db.find(key, Operator.EQUALS, value) .contains((long) count * increase)); } @Test @Ignore public void testOnDiskStreamingIterator() { Database db = (Database) store; int count = TestData.getScaleCount() * 5; Set<Revision<PrimaryKey, Text, Value>> expected = Sets .newLinkedHashSetWithExpectedSize(count); for (int i = 0; i < count; ++i) { Write write = Write.add(TestData.getSimpleString(), TestData.getTObject(), i); db.accept(write); Revision<PrimaryKey, Text, Value> revision = Revision .createPrimaryRevision(write.getRecord(), write.getKey(), write.getValue(), write.getVersion(), write.getType()); expected.add(revision); Variables.register("expected_" + i, revision); if(i % 100 == 0) { db.triggerSync(); } } db.triggerSync(); Iterator<Revision<PrimaryKey, Text, Value>> it = Database .onDiskStreamingIterator(db.getBackingStore()); Iterator<Revision<PrimaryKey, Text, Value>> it2 = expected.iterator(); int i = 0; while (it.hasNext()) { Revision<PrimaryKey, Text, Value> actual = it.next(); Assert.assertEquals(it2.next(), actual); Variables.register("actual_" + i, actual); ++i; } } @Override protected void add(String key, TObject value, long record) { if(!store.verify(key, value, record)) { ((Database) store).accept(Write.add(key, value, record)); } } @Override protected void cleanup(Store store) { FileSystem.deleteDirectory(current); } @Override protected Database getStore() { current = TestData.DATA_DIR + File.separator + Time.now(); return new Database(current); } @Override protected void remove(String key, TObject value, long record) { if(store.verify(key, value, record)) { ((Database) store).accept(Write.remove(key, value, record)); } } }