/*
* ToroDB
* Copyright © 2014 8Kdata Technology (www.8kdata.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.torodb.metainfo.cache.mvcc;
import static org.mockito.Mockito.spy;
import com.torodb.core.TableRefFactory;
import com.torodb.core.impl.TableRefFactoryImpl;
import com.torodb.core.transaction.metainf.FieldType;
import com.torodb.core.transaction.metainf.ImmutableMetaCollection;
import com.torodb.core.transaction.metainf.ImmutableMetaDatabase;
import com.torodb.core.transaction.metainf.ImmutableMetaDocPart;
import com.torodb.core.transaction.metainf.ImmutableMetaField;
import com.torodb.core.transaction.metainf.ImmutableMetaScalar;
import com.torodb.core.transaction.metainf.ImmutableMetaSnapshot;
import com.torodb.core.transaction.metainf.MutableMetaDocPart;
import com.torodb.core.transaction.metainf.MutableMetaSnapshot;
import com.torodb.core.transaction.metainf.UnmergeableException;
import com.torodb.core.transaction.metainf.WrapperMutableMetaSnapshot;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.MockSettings;
import org.mockito.internal.creation.MockSettingsImpl;
import java.util.Collections;
/**
*
* @author gortiz
*/
@SuppressWarnings({"unused", "rawtypes"})
public class SnapshotMergerTest {
private static final TableRefFactory tableRefFactory = new TableRefFactoryImpl();
private static ImmutableMetaSnapshot currentSnapshot;
private ImmutableMetaSnapshot.Builder snapshotBuilder;
private static final MockSettings SETTINGS = new MockSettingsImpl().defaultAnswer((t) -> {
throw new AssertionError("Method " + t.getMethod() + " was not expected to be called");
});
public SnapshotMergerTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
currentSnapshot = new ImmutableMetaSnapshot.Builder()
.put(new ImmutableMetaDatabase.Builder("dbName1", "dbId1")
.put(new ImmutableMetaCollection.Builder("colName1", "colId1")
.put(new ImmutableMetaDocPart.Builder(tableRefFactory.createRoot(), "docPartId1")
.put(new ImmutableMetaField("fieldName1", "fieldId1", FieldType.INTEGER))
.put(new ImmutableMetaScalar("scalarId1", FieldType.INTEGER))
)
.build()
).build()
).build();
}
@Before
public void setup() {
snapshotBuilder = spy(new ImmutableMetaSnapshot.Builder(currentSnapshot));
}
/**
* Fails if the checker do not allow idempotency
*
* @throws Exception
*/
@Test
public void testIdempotency() throws Exception {
SnapshotMerger merger;
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
MutableMetaDocPart metaDocPart = changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1");
metaDocPart.addMetaField("fieldName1", "fieldId1", FieldType.INTEGER);
metaDocPart.addMetaScalar("scalarId1", FieldType.INTEGER);
merger = new SnapshotMerger(currentSnapshot, changedSnapshot);
merger.merge();
}
/**
* Test that an exception is thrown on database name conflicts
*
* @throws Exception
*/
@Test
public void testDatabaseNameConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName2", "dbId1");
try {
new SnapshotMerger(currentSnapshot, changedSnapshot)
.merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on database id conflicts
*
* @throws Exception
*/
@Test
public void testDatabaseIdConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId2");
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on collection name conflicts
*
* @throws Exception
*/
@Test
public void testCollectionNameConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName2", "colId1");
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on collection id conflicts
*
* @throws Exception
*/
@Test
public void testCollectionIdConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId2");
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on doc part table ref conflicts
*
* @throws Exception
*/
@Test
public void testDocPartRefConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createChild(tableRefFactory.createRoot(), "anotherTRef"),
"docPartId1");
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on doc part id conflicts
*
* @throws Exception
*/
@Test
public void testDocPartIdConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId2");
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on field name and type conflicts
*
* @throws Exception
*/
@Test
public void testFieldNameAndTypeConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaField("fieldName1", "fieldId1", FieldType.TIME);
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(Collections
.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaField("fieldName2", "fieldId1", FieldType.INTEGER);
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on field id conflicts
*
* @throws Exception
*/
@Test
public void testFieldIdConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaField("fieldName1", "fieldId2", FieldType.INTEGER);
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that no exception is thrown when creating a new field that shares type but not name with a
* previous one.
*
* @throws Exception
*/
@Test
public void testField_differentName() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaField("fieldName2", "fieldId4", FieldType.INTEGER);
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
}
/**
* Test that no exception is thrown when creating a new field that shares name but not type with a
* previous one.
*
* @throws Exception
*/
@Test
public void testField_differentType() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaField("fieldName1", "fieldId4", FieldType.TIME);
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
}
/**
* Test that no exception is thrown when creating a new field with different id, name and type
*
* @throws Exception
*/
@Test
public void testField_different() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaField("fieldName10", "fieldId20", FieldType.CHILD);
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
}
/**
* Test that an exception is thrown on scalar id conflicts
*
* @throws Exception
*/
@Test
public void testScalarIdConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaScalar("scalarId1", FieldType.LONG);
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that an exception is thrown on scalar type conflicts
*
* @throws Exception
*/
@Test
public void testScalarTypeConflict() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaScalar("fieldId2", FieldType.INTEGER);
try {
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
Assert.fail("A " + UnmergeableException.class.getSimpleName() + " was expected to be thrown");
} catch (UnmergeableException ex) {
}
}
/**
* Test that no exception is thrown when creating a new scalar with different id and type
*
* @throws Exception
*/
@Test
public void testScalar_different() throws Exception {
MutableMetaSnapshot changedSnapshot = new WrapperMutableMetaSnapshot(new ImmutableMetaSnapshot(
Collections.emptyMap()));
changedSnapshot.addMetaDatabase("dbName1", "dbId1")
.addMetaCollection("colName1", "colId1")
.addMetaDocPart(tableRefFactory.createRoot(), "docPartId1")
.addMetaScalar("fieldId20", FieldType.LONG);
new SnapshotMerger(currentSnapshot, changedSnapshot).merge();
}
}