package com.constellio.data.dao.services.records;
import static com.constellio.sdk.tests.TestUtils.asList;
import static com.constellio.sdk.tests.TestUtils.asStringObjectMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.data.MapEntry.entry;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.constellio.data.dao.dto.records.RecordDTO;
import com.constellio.data.dao.dto.records.RecordDeltaDTO;
import com.constellio.data.dao.dto.records.RecordsFlushing;
import com.constellio.data.dao.dto.records.TransactionDTO;
import com.constellio.data.dao.services.bigVault.RecordDaoException;
import com.constellio.data.dao.services.bigVault.RecordDaoException.NoSuchRecordWithId;
import com.constellio.data.dao.services.bigVault.RecordDaoException.OptimisticLocking;
import com.constellio.data.dao.services.bigVault.RecordDaoRuntimeException.ReferenceToNonExistentIndex;
import com.constellio.data.dao.services.bigVault.solr.BigVaultRuntimeException;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.TestUtils.MapBuilder;
import com.constellio.sdk.tests.annotations.LoadTest;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BigVaultRecordDaoRealTest extends ConstellioTest {
public static final String singleReferenceFieldCode = "refId_s";
public static final String parentReferenceFieldCode = "parentRefPId_s";
public static final String multipleReferencesFieldCode = "refId_ss";
private static final String ID_FIELD = "id";
private final String aContentId = "aContentId";
private final String savedMetadataFieldName = "savedField_s";
private final String initialValue = "initialValue";
private final String modifiedValue = "modifiedValue";
LocalDateTime aDateTime = aDateTime();
LocalDateTime anotherDateTime = aDateTime();
LocalDate aDate = aDate();
LocalDate anotherDate = aDate();
private RecordDao recordDao;
@Before
public void setup() {
recordDao = getDataLayerFactory().newRecordDao();
Map<String, Object> fields = new HashMap<>();
fields.put(savedMetadataFieldName, initialValue);
}
@Test
public void __prepareTests__()
throws Exception {
}
@Test(expected = OptimisticLocking.class)
public void givenRecordAlreadyInStoreWhenAddingRecordThenExceptionThrown()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("title_s", "test");
RecordDTO record = new RecordDTO("1", 1, null, fields);
add(record);
}
@Test
@LoadTest
public void whenAddingAndSearchingMultipleTimesWithDifferentDaoThenCanHandleLoad()
throws Exception {
for (int i = 0; i < 100; i++) {
recordDao = getDataLayerFactory().newRecordDao();
add(newRecordWithTitle("record #" + i));
assertThat(recordDao.documentsCount()).isEqualTo(i + 1);
}
}
private RecordDTO newRecordWithTitle(String title) {
String id = UUID.randomUUID().toString();
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("title_s", title);
fields.put("schema_s", "zeSchemaType_default");
RecordDTO record = new RecordDTO(nextID(), -1, null, fields);
return record;
}
private RecordDTO newRecordWithSingleReference(String referencedId) {
String id = UUID.randomUUID().toString();
Map<String, Object> fields = new HashMap<String, Object>();
fields.put(singleReferenceFieldCode, referencedId);
fields.put("schema_s", "zeSchemaType_default");
RecordDTO record = new RecordDTO(nextID(), -1, null, fields);
return record;
}
private RecordDTO newRecordWithSingleReferenceAndParentReference(String referencedId, String parentId) {
String id = UUID.randomUUID().toString();
Map<String, Object> fields = new HashMap<String, Object>();
fields.put(singleReferenceFieldCode, referencedId);
fields.put(parentReferenceFieldCode, parentId);
fields.put("schema_s", "zeSchemaType_default");
RecordDTO record = new RecordDTO(nextID(), -1, null, fields);
return record;
}
private RecordDTO newRecordWithMultipleReferences(List<String> referencedId) {
String id = UUID.randomUUID().toString();
Map<String, Object> fields = new HashMap<String, Object>();
fields.put(multipleReferencesFieldCode, referencedId);
fields.put("schema_s", "zeSchemaType_default");
RecordDTO record = new RecordDTO(nextID(), -1, null, fields);
return record;
}
@Test
@LoadTest
public void whenAddingAndSearchingMultipleTimesWithSameDaoThenCanHandleLoad()
throws Exception {
for (int i = 0; i < 100; i++) {
add(newRecordWithTitle("record #" + i));
assertThat(recordDao.documentsCount()).isEqualTo(i + 1);
}
}
@Test
public void whenAddingRecordThenCanBeRetreivedWithHisNewId()
throws Exception {
RecordDTO record = newRecordWithTitle("test");
add(record);
assertEquals(record.getFields().get("title_s"), recordDao.get(record.getId()).getFields().get("title_s"));
}
@Test(expected = ReferenceToNonExistentIndex.class)
public void whenAddingRecordWithReferenceToNonExistentIndexThenOptimisticLocking()
throws Exception {
RecordDTO record = newRecordWithSingleReference("idOfNonExistentIndex");
add(record);
}
@Test(expected = ReferenceToNonExistentIndex.class)
public void whenAddingRecordWithReferenceToExistingIndexThenExceptionThrown()
throws Exception {
RecordDTO record = newRecordWithSingleReference("idOfNonExistentIndex");
add(record);
}
@Test(expected = ReferenceToNonExistentIndex.class)
public void whenAddingRecordWithMultipleReferencesToNonExistentIndexesThenOptimisticLocking()
throws Exception {
RecordDTO record = newRecordWithMultipleReferences(Arrays.asList("idOfNonExistentIndex", "idOfAnotherNonExistentIndex"));
add(record);
}
@Test
public void whenAddingRecordWithReferenceToNonExistentIndexGivenValidationSkippedThenCanRetrieveRecord()
throws Exception {
RecordDTO record = newRecordWithSingleReference("idOfNonExistentIndex");
recordDao.execute(new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW, Arrays.asList(record),
new ArrayList<RecordDeltaDTO>(), new ArrayList<RecordDTO>(), new ArrayList<SolrParams>(), new HashSet<String>(),
true, false));
assertEquals(record.getFields().get("title_s"), recordDao.get(record.getId()).getFields().get("title_s"));
}
@Test
public void whenAddingRecordWithAValidReferenceThenItsActiveIndexCanBeRetrievedWithItsId()
throws Exception {
RecordDTO referencedRecord = newRecordWithTitle("referencedRecord");
RecordDTO record = newRecordWithSingleReference(referencedRecord.getId());
add(referencedRecord);
add(record);
assertEquals("index", recordDao.get("idx_act_" + record.getId()).getFields().get("type_s"));
}
@Test(expected = NoSuchRecordWithId.class)
public void givenValidRecordWhenLogicallyDeletingThenItsActiveIndexIsDeleted()
throws Exception {
RecordDTO record = givenSavedRecordWithInitialValidReferencesValue();
assertThat(recordDao.get("idx_act_" + record.getId())).isNotNull();
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put("deleted_s", Boolean.TRUE);
record = updateFieldsAndGetNewRecordDTO(record, modifiedFields);
recordDao.get("idx_act_" + record.getId());
}
@Test
public void whenAddingRecordWithMultipleValidReferencesThenItsActiveIndexCanBeRetrievedWithItsId()
throws Exception {
RecordDTO referencedRecord1 = newRecordWithTitle("referencedRecord1");
RecordDTO referencedRecord2 = newRecordWithTitle("referencedRecord2");
RecordDTO record = newRecordWithMultipleReferences(Arrays.asList(referencedRecord1.getId(), referencedRecord2.getId()));
add(referencedRecord1);
add(referencedRecord2);
add(record);
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord1.getId()).getFields().get("refs_d"));
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord2.getId()).getFields().get("refs_d"));
}
@Test
public void whenAddingRecordWithParentsThenItsAncestorsAreAddedTo()
throws Exception {
RecordDTO record = newRecordWithParentPaths(Arrays.asList("parent1/parent11", "parent2"));
add(record);
assertThat((List) recordDao.get("idx_rfc_" + record.getId()).getFields().get("ancestors_ss"))
.containsOnly("parent1", "parent11", "parent2");
}
private RecordDTO newRecordWithParentPaths(List<String> parents) {
String id = UUID.randomUUID().toString();
List<String> paths = new ArrayList<>();
for (String parentPath : parents) {
paths.add(parentPath + "/" + id);
}
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("path_ss", paths);
fields.put("schema_s", "zeSchemaType_default");
RecordDTO record = new RecordDTO(nextID(), -1, null, fields);
return record;
}
@Test
public void whenAddingRecordWithMultipleValidReferencesThenTheirReferenceCountersHaveValue1()
throws Exception {
RecordDTO referencedRecord1 = newRecordWithTitle("referencedRecord1");
RecordDTO referencedRecord2 = newRecordWithTitle("referencedRecord2");
RecordDTO record = newRecordWithMultipleReferences(Arrays.asList(referencedRecord1.getId(), referencedRecord2.getId()));
add(referencedRecord1);
add(referencedRecord2);
add(record);
assertEquals("index", recordDao.get("idx_act_" + record.getId()).getFields().get("type_s"));
}
@Test
public void whenAddingRecordWithAValidReferenceAndAParentReferenceThenReferencedCounterHasValue1ButParentHasValueZero()
throws Exception {
RecordDTO referencedRecord = newRecordWithTitle("referencedRecord");
RecordDTO parentRecord = newRecordWithTitle("parentRecord");
RecordDTO record = newRecordWithSingleReferenceAndParentReference(referencedRecord.getId(), parentRecord.getId());
add(referencedRecord);
add(parentRecord);
add(record);
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord.getId()).getFields().get("refs_d"));
assertEquals(0.0, recordDao.get("idx_rfc_" + parentRecord.getId()).getFields().get("refs_d"));
}
@Test
public void whenAddingTwoRecordsWithAValidReferenceThenReferencedCounterHasValue1ButParentHasValueZero()
throws Exception {
RecordDTO referencedRecord = newRecordWithTitle("referencedRecord");
RecordDTO record = newRecordWithSingleReference(referencedRecord.getId());
add(referencedRecord);
add(record);
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord.getId()).getFields().get("refs_d"));
RecordDTO record2 = newRecordWithSingleReference(referencedRecord.getId());
add(record2);
assertEquals(2.0, recordDao.get("idx_rfc_" + referencedRecord.getId()).getFields().get("refs_d"));
}
@Test
public void whenAddingRecordWithContentThenPersistContentId()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("content_s", aContentId);
add(new RecordDTO("zeId", -1, null, fields));
RecordDTO savedRecord = recordDao.get("zeId");
assertThat((String) savedRecord.getFields().get("content_s")).isEqualTo(aContentId);
}
@Test(expected = BigVaultRuntimeException.class)
public void whenAddingRecordWithIncorrectFieldThenException()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("content_d", "thisIsNotANumber");
add(new RecordDTO(nextID(), -1, null, fields));
}
@Test
public void whenStoringIntegersThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_i", 1);
fields.put("field_is", Arrays.asList(1));
fields.put("fields_is", Arrays.asList(1, 2));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringStringsThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_s", "1");
fields.put("field_ss", Arrays.asList("1"));
fields.put("fields_ss", Arrays.asList("1", "1", "2", "3"));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringStringsThenCanRetrieveThem2()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_s", "1");
fields.put("field_ss", Arrays.asList("1"));
fields.put("fields_ss", Arrays.asList("1", "2", "2", "3"));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringLongsThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_l", 1l);
fields.put("field_ls", Arrays.asList(1l));
fields.put("fields_ls", Arrays.asList(1l, 2l, 2l, 3l));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringTextsThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_t", "2");
fields.put("field_txt", Arrays.asList("2"));
fields.put("fields_txt", Arrays.asList("2", "3"));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringFrenchTextsThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_t_fr", "banane");
fields.put("field_txt_fr", Arrays.asList("banane"));
fields.put("fields_txt_fr", Arrays.asList("banane", "pomme"));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertThat(record.getFields()).doesNotContainKey("field_t_fr");
assertThat(record.getFields()).doesNotContainKey("field_txt_fr");
assertThat(record.getFields()).doesNotContainKey("fields_txt_fr");
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_t_fr:banane"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_txt_fr:banane"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_fr:banane"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_fr:pomme"))).hasSize(1);
}
@Test
public void whenStoringEnglishTextsThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_t_en", "banana");
fields.put("field_txt_en", Arrays.asList("banana"));
fields.put("fields_txt_en", Arrays.asList("banana", "apple"));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertThat(record.getFields()).doesNotContainKey("field_t_en");
assertThat(record.getFields()).doesNotContainKey("field_txt_en");
assertThat(record.getFields()).doesNotContainKey("fields_txt_en");
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_t_en:banana"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_txt_en:banana"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_en:banana"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_en:apple"))).hasSize(1);
}
@Test
public void whenStoringBooleansThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_s", true);
fields.put("field_ss", Arrays.asList(true));
fields.put("fields_ss", Arrays.asList(true, false));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringFloatsThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_f", 1.1f);
fields.put("field_fs", Arrays.asList(2.2f));
fields.put("fields_fs", Arrays.asList(2.2f, 3.3f));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringDateTimesThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_dt", aDateTime);
fields.put("field_dts", Arrays.asList(aDateTime, anotherDateTime));
fields.put("fields_dts", Arrays.asList(aDateTime, anotherDateTime));
fields.put("fields3_dts", null);
fields.put("fields4_dts", Arrays.asList(null, null));
fields.put("fields5_dts", Arrays.asList(null, aDateTime));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
fields.put("fields4_dts", null);
assertSameFields(record, fields);
}
@Test
public void whenStoringOldDateTimesThenCanRetrieveThem()
throws Exception {
LocalDateTime date1 = new LocalDateTime(500, 1, 2, 0, 0, 0, 0);
LocalDateTime date2 = new LocalDateTime(1800, 1, 2, 0, 0, 0, 0);
LocalDateTime date3 = new LocalDateTime(1899, 1, 2, 0, 0, 0, 0);
LocalDateTime date4 = new LocalDateTime(1900, 1, 2, 3, 4, 5, 6);
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_dt", date1);
fields.put("field_dts", Arrays.asList(date1, date2, date3, date4));
fields.put("fields_dts", Arrays.asList(date1, date2, date3, date4));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringDatesThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_da", aDate);
fields.put("field2_da", null);
fields.put("field_das", Arrays.asList(aDate, anotherDate));
fields.put("fields_das", Arrays.asList(aDate, anotherDate));
fields.put("fields3_das", null);
fields.put("fields4_das", Arrays.asList(null, null));
fields.put("fields5_das", Arrays.asList(null, aDate));
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
fields.put("fields4_das", null);
assertSameFields(record, fields);
}
@Test
public void whenStoringOldDatesThenCanRetrieveThem()
throws Exception {
LocalDate date1 = new LocalDate(500, 1, 2);
LocalDate date2 = new LocalDate(1800, 1, 2);
LocalDate date3 = new LocalDate(1899, 1, 2);
LocalDate date4 = new LocalDate(1900, 1, 2);
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_da", date1);
fields.put("field2_da", null);
fields.put("field_das", Arrays.asList(date1, date2, date3, date4));
fields.put("fields_das", Arrays.asList(date1, date2, date3, date4));
fields.put("fields3_das", null);
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringDoublesThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_d", 1.1);
fields.put("field_ds", Arrays.asList(2.2));
fields.put("fields_ds", Arrays.asList(2.2, 3.3));
fields.put("field5_d", null);
RecordDTO record = saveRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringIntegersWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_i", 1);
fields.put("field_is", Arrays.asList(1));
fields.put("fields_is", Arrays.asList(1, 2));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringStringsWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_s", "1");
fields.put("field_ss", Arrays.asList("1"));
fields.put("fields_ss", Arrays.asList("1", "2"));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringStringsWhileUpdatingThenCanRetrieveThem2()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_s", "1");
fields.put("field_ss", Arrays.asList("1"));
fields.put("fields_ss", Arrays.asList("1", "2"));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringNullStringsWhileUpdatingThenNoValues()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_s", null);
fields.put("fields_ss", null);
fields.put("field2_ss", Arrays.asList((String) null));
fields.put("field3_ss", Arrays.asList("value", null));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertThat(record.getFields().get("field_s")).isNull();
assertThat(record.getFields().get("fields_s")).isNull();
assertThat(record.getFields().get("field2_ss")).isNull();
assertThat(record.getFields().get("field3_ss")).isEqualTo(Arrays.asList("value", null));
}
@Test
public void whenStoringLongsWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_l", 1l);
fields.put("field_ls", Arrays.asList(1l));
fields.put("fields_ls", Arrays.asList(1l, 2l));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringTextsWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_t", "1");
fields.put("field2_t", null);
fields.put("field_txt", Arrays.asList("2"));
fields.put("fields_txt", Arrays.asList("2", "3"));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenLoadingARecordWith__NULL__InTextFieldsThenConsideredAsNull()
throws Exception {
givenDisabledAfterTestValidations();
SolrInputDocument solrInputDocument = new SolrInputDocument();
solrInputDocument.setField("id", "zeId");
solrInputDocument.setField("field1_t", "__NULL__");
solrInputDocument.setField("field2_t", asList("__NULL__"));
solrInputDocument.setField("field3_txt", "__NULL__");
solrInputDocument.setField("field4_txt", asList("__NULL__"));
solrInputDocument.setField("field5_t", "value1");
solrInputDocument.setField("field6_txt", asList("value2", "value3"));
SolrClient solrClient = recordDao.getBigVaultServer().getNestedSolrServer();
solrClient.add(solrInputDocument);
solrClient.commit();
RecordDTO record = recordDao.get("zeId");
assertThat(record.getFields())
.doesNotContainKey("field1_t")
.doesNotContainKey("field2_t")
.doesNotContainKey("field3_txt")
.doesNotContainKey("field4_txt")
.contains(
entry("id", "zeId"),
entry("field5_t", "value1"),
entry("field6_txt", asList("value2", "value3"))
);
}
@Test
public void whenStoringFrenchTextsWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_t_fr", "banane");
fields.put("field_txt_fr", Arrays.asList("banane"));
fields.put("fields_txt_fr", Arrays.asList("banane", "pomme"));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertThat(record.getFields()).doesNotContainKey("field_t_fr");
assertThat(record.getFields()).doesNotContainKey("field_txt_fr");
assertThat(record.getFields()).doesNotContainKey("fields_txt_fr");
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_t_fr:banane"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_txt_fr:banane"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_fr:banane"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_fr:pomme"))).hasSize(1);
}
@Test
public void whenStoringEnglishTextsWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_t_en", "banana");
fields.put("field_txt_en", Arrays.asList("banana"));
fields.put("fields_txt_en", Arrays.asList("banana", "apple"));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertThat(record.getFields()).doesNotContainKey("field_t_en");
assertThat(record.getFields()).doesNotContainKey("field_txt_en");
assertThat(record.getFields()).doesNotContainKey("fields_txt_en");
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_t_en:banana"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "field_txt_en:banana"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_en:banana"))).hasSize(1);
assertThat(recordDao.searchQuery(new ModifiableSolrParams().set("q", "fields_txt_en:apple"))).hasSize(1);
}
@Test
public void whenStoringBooleansWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_s", true);
fields.put("field_ss", Arrays.asList(true));
fields.put("fields_ss", Arrays.asList(true, false));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringFloatsWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_f", 1.1f);
fields.put("field_fs", Arrays.asList(2.2f));
fields.put("fields_fs", Arrays.asList(2.2f, 3.3f));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringDateTimesWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_dt", aDateTime);
fields.put("field_dts", Arrays.asList(aDateTime, anotherDateTime));
fields.put("fields_dts", Arrays.asList(aDateTime, anotherDateTime));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringDatesWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_da", aDate);
fields.put("field_das", Arrays.asList(aDate, anotherDate));
fields.put("fields_das", Arrays.asList(aDate, anotherDate));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
@Test
public void whenStoringDoublesWhileUpdatingThenCanRetrieveThem()
throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
fields.put("field_d", 1.1);
fields.put("field_ds", Arrays.asList(2.2));
fields.put("fields_ds", Arrays.asList(2.2, 3.3));
RecordDTO record = updateRecordWithFieldsAndLoadItFromStore(fields);
assertSameFields(record, fields);
}
private void assertSameFields(RecordDTO record, Map<String, Object> fields) {
int size = 0;
for (Map.Entry<String, Object> entry : fields.entrySet()) {
Object expected = entry.getValue();
Object was = record.getFields().get(entry.getKey());
assertThat(was).describedAs("Field " + entry.getKey()).isEqualTo(expected);
if (expected != null) {
size++;
}
}
Map<String, Object> recordFieldsWithoutSysS = new HashMap<>(record.getFields());
recordFieldsWithoutSysS.remove("sys_s");
recordFieldsWithoutSysS.remove("id");
recordFieldsWithoutSysS.remove("_version_");
recordFieldsWithoutSysS.remove("collection_s");
assertThat(recordFieldsWithoutSysS.size()).isEqualTo(size);
}
private RecordDTO saveRecordWithFieldsAndLoadItFromStore(Map<String, Object> fields)
throws OptimisticLocking {
return saveRecordWithFieldsAndLoadItFromStore(fields, "zeId");
}
private RecordDTO saveRecordWithFieldsAndLoadItFromStore(Map<String, Object> fields, String id)
throws OptimisticLocking {
RecordDTO recordToSave = new RecordDTO(id, -1, null, fields);
add(recordToSave);
try {
return recordDao.get(id);
} catch (NoSuchRecordWithId e) {
throw new RuntimeException(e);
}
}
private RecordDTO updateRecordWithFieldsAndLoadItFromStore(Map<String, Object> fields)
throws Exception {
Map<String, Object> initialValues = new HashMap<>();
initialValues.put("collection_s", zeCollection);
RecordDTO recordToSave = new RecordDTO(nextID(), -1, null, initialValues);
add(recordToSave);
try {
RecordDTO recordDTO = recordDao.get(recordToSave.getId());
RecordDeltaDTO recordDeltaDTO = new RecordDeltaDTO(recordDTO, fields, recordDTO.getFields());
update(recordDeltaDTO);
return recordDao.get(recordDTO.getId());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Test
public void whenUpdatingRecordWithNewFieldsThenNewFieldsAddedCorrectly()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
assertThat(recordDTO.getFields()).containsEntry(savedMetadataFieldName, initialValue);
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put("aField_s", "aValue");
modifiedFields.put("aField_d", 42.0);
recordDTO = updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
assertThat(recordDTO.getFields()).containsEntry(savedMetadataFieldName, initialValue).containsEntry("aField_s", "aValue")
.containsEntry("aField_d", 42.0);
}
@Test
public void whenUpdatingRecordWithRemovedFieldsThenFieldsRemovedCorrectly()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
assertThat(recordDTO.getFields()).containsEntry(savedMetadataFieldName, initialValue);
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(savedMetadataFieldName, null);
modifiedFields.put("aField_d", 42.0);
recordDTO = updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
assertThat(recordDTO.getFields()).doesNotContainKey(savedMetadataFieldName).containsEntry("aField_d", 42.0);
}
@Test
public void whenUpdatingRecordWithModifiedFieldThenFieldModifiedCorrectly()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
assertThat(recordDTO.getFields()).containsEntry(savedMetadataFieldName, initialValue);
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(savedMetadataFieldName, modifiedValue);
modifiedFields.put("aField_d", 42.0);
recordDTO = updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
assertThat(recordDTO.getFields()).containsEntry(savedMetadataFieldName, modifiedValue).containsEntry("aField_d", 42.0);
}
@Test(expected = ReferenceToNonExistentIndex.class)
public void whenUpdatingRecordWithModifiedReferenceFieldBecomingInvalidThenOptimisticLocking()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValidReferenceValue();
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(singleReferenceFieldCode, "anInvalidId");
updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
}
@Test(expected = ReferenceToNonExistentIndex.class)
public void whenUpdatingRecordWithModifiedReferencesFieldBecomingInvalidThenOptimisticLocking()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValidReferencesValue();
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(multipleReferencesFieldCode, Arrays.asList("anInvalidId"));
updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
}
@Test
public void whenUpdatingRecordWithModifiedReferencesFieldRemainingValidThenNoProblem()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValidReferencesValue();
Map<String, Object> modifiedFields = new HashMap<>();
RecordDTO referencedRecord3 = newRecordWithTitle("referencedRecord3");
add(referencedRecord3);
referencedRecord3 = recordDao.get(referencedRecord3.getId());
modifiedFields.put(multipleReferencesFieldCode, Arrays.asList(referencedRecord3.getId()));
RecordDTO postChangeRecord = updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
assertThat((List) postChangeRecord.getFields().get(multipleReferencesFieldCode)).contains(referencedRecord3.getId());
}
@Test
public void whenAddingTwoRecordsWithAValidReferenceAndModifyingToReferenceSameRecordThenReferencedCounterHasValue2()
throws Exception {
RecordDTO referencedRecord1 = newRecordWithTitle("referencedRecord");
RecordDTO referencedRecord2 = newRecordWithTitle("referencedRecord2");
RecordDTO record = newRecordWithSingleReference(referencedRecord1.getId());
add(referencedRecord1);
add(referencedRecord2);
add(record);
RecordDTO record2 = newRecordWithSingleReference(referencedRecord2.getId());
add(record2);
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord1.getId()).getFields().get("refs_d"));
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord2.getId()).getFields().get("refs_d"));
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(singleReferenceFieldCode, referencedRecord1.getId());
record2 = recordDao.get(record2.getId());
updateFieldsAndGetNewRecordDTO(record2, modifiedFields);
assertEquals(2.0, recordDao.get("idx_rfc_" + referencedRecord1.getId()).getFields().get("refs_d"));
assertEquals(0.0, recordDao.get("idx_rfc_" + referencedRecord2.getId()).getFields().get("refs_d"));
}
@Test
public void whenAddingTwoRecordsWithValidReferencesAndModifyingToReferenceSameRecordThenReferencedCounterHasValue2()
throws Exception {
RecordDTO referencedRecord1 = newRecordWithTitle("referencedRecord");
RecordDTO referencedRecord2 = newRecordWithTitle("referencedRecord2");
RecordDTO record = newRecordWithMultipleReferences(Arrays.asList(referencedRecord1.getId()));
add(referencedRecord1);
add(referencedRecord2);
add(record);
RecordDTO record2 = newRecordWithMultipleReferences(Arrays.asList(referencedRecord1.getId()));
add(record2);
assertEquals(2.0, recordDao.get("idx_rfc_" + referencedRecord1.getId()).getFields().get("refs_d"));
assertEquals(0.0, recordDao.get("idx_rfc_" + referencedRecord2.getId()).getFields().get("refs_d"));
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(multipleReferencesFieldCode, Arrays.asList(referencedRecord2.getId()));
record2 = recordDao.get(record2.getId());
updateFieldsAndGetNewRecordDTO(record2, modifiedFields);
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord1.getId()).getFields().get("refs_d"));
assertEquals(1.0, recordDao.get("idx_rfc_" + referencedRecord2.getId()).getFields().get("refs_d"));
}
private RecordDTO givenSavedRecordWithInitialValidReferenceValue()
throws OptimisticLocking, NoSuchRecordWithId {
RecordDTO referencedRecord = newRecordWithTitle("referencedRecord");
RecordDTO record = newRecordWithSingleReference(referencedRecord.getId());
add(referencedRecord);
add(record);
return recordDao.get(record.getId());
}
private RecordDTO givenSavedRecordWithInitialValidReferencesValue()
throws OptimisticLocking, NoSuchRecordWithId {
RecordDTO referencedRecord1 = newRecordWithTitle("referencedRecord1");
RecordDTO referencedRecord2 = newRecordWithTitle("referencedRecord2");
RecordDTO record = newRecordWithMultipleReferences(Arrays.asList(referencedRecord1.getId(), referencedRecord2.getId()));
add(referencedRecord1);
add(referencedRecord2);
add(record);
return recordDao.get(record.getId());
}
@Test()
public void whenUpdatingRecordWithOldVersionThenOptimisticLockingException()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
assertThat(recordDTO.getFields()).containsEntry(savedMetadataFieldName, initialValue);
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(savedMetadataFieldName, modifiedValue);
modifiedFields.put("aField_d", 42.0);
updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
try {
recordDTO = updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
fail("RecordDaoException.OptimisticLocking expected");
} catch (RecordDaoException.OptimisticLocking e) {
assertThat(e.getId()).isEqualTo(recordDTO.getId());
assertThat(e.getVersion()).isEqualTo(recordDTO.getVersion());
}
}
@Test(expected = BigVaultRuntimeException.class)
public void whenUpdatingRecordWithInvalidFieldThenException()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
Map<String, Object> modifiedFields = new HashMap<>();
modifiedFields.put(savedMetadataFieldName, modifiedValue);
modifiedFields.put("aField_d", "thisIsNotANumber");
updateFieldsAndGetNewRecordDTO(recordDTO, modifiedFields);
}
private RecordDTO updateFieldsAndGetNewRecordDTO(RecordDTO recordDTO, Map<String, Object> modifiedFields)
throws Exception {
update(new RecordDeltaDTO(recordDTO, modifiedFields, recordDTO.getFields()));
return recordDao.get(recordDTO.getId());
}
private RecordDTO givenSavedRecordWithInitialValueInSavedMetadataFieldName()
throws OptimisticLocking {
return givenSavedRecordWithValueInSavedMetadataFieldName(initialValue);
}
private RecordDTO givenSavedRecordWithValueInSavedMetadataFieldName(String value)
throws OptimisticLocking {
Map<String, Object> fields = new HashMap<>();
fields.put(savedMetadataFieldName, value);
String id = UUID.randomUUID().toString();
RecordDTO savedRecord = new RecordDTO(id, -1, null, fields);
add(savedRecord);
try {
return recordDao.get(id);
} catch (NoSuchRecordWithId e) {
throw new RuntimeException(e);
}
}
@Test
public void whenUpdatingWithRecordDTOWithoutModificationsThenDocumentNotModified()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
update(new RecordDeltaDTO(recordDTO, new HashMap<String, Object>(), recordDTO.getFields()));
RecordDTO modifiedRecordDTO = recordDao.get(recordDTO.getId());
assertThat(modifiedRecordDTO.getFields().get(savedMetadataFieldName)).isEqualTo(
recordDTO.getFields().get(savedMetadataFieldName));
assertThat(modifiedRecordDTO.getFields()).isEqualTo(recordDTO.getFields());
assertThat(modifiedRecordDTO.getVersion()).isEqualTo(recordDTO.getVersion());
}
@Test
public void whenUpdatingWithRecordDTOWithoutModificationsThenDocumentNewVersionAndSameValues()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
update(new RecordDeltaDTO(recordDTO, asStringObjectMap(savedMetadataFieldName, initialValue), recordDTO.getFields()));
RecordDTO modifiedRecordDTO = recordDao.get(recordDTO.getId());
assertThat(modifiedRecordDTO.getFields().get(savedMetadataFieldName)).isEqualTo(
recordDTO.getFields().get(savedMetadataFieldName));
assertThat(modifiedRecordDTO.getVersion()).isNotEqualTo(recordDTO.getVersion());
}
@Test
public void givenOptimisticLockingWhenUpdatingRecordThenChangesNotConserved()
throws Exception {
RecordDTO recordDTO = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
RecordDTO dto = recordDao.get(recordDTO.getId());
assertThat(dto.getFields().get(savedMetadataFieldName)).isEqualTo(initialValue);
update(new RecordDeltaDTO(recordDTO, asStringObjectMap("anotherField_d", 1.1), recordDTO.getFields()));
long secondVersion = recordDao.get(recordDTO.getId()).getVersion();
dto = recordDao.get(recordDTO.getId());
assertThat(dto.getFields().get(savedMetadataFieldName)).isEqualTo(initialValue);
try {
update(new RecordDeltaDTO(recordDTO, asStringObjectMap(savedMetadataFieldName, modifiedValue),
recordDTO.getFields()));
fail("Optimsitic locking expected");
} catch (RecordDaoException.OptimisticLocking e) {
dto = recordDao.get(recordDTO.getId());
assertThat(dto.getFields().get(savedMetadataFieldName)).isEqualTo(initialValue);
assertThat(dto.getVersion()).isEqualTo(secondVersion);
}
}
@Test
public void whenExecutingTransactionThenAllModificationsApplied()
throws Exception {
RecordDTO firstAlreadySavedRecord = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
RecordDTO secondAlreadySavedRecord = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
long initialDocumentsCount = recordDao.documentsCount();
RecordDTO firstAddedRecord = new RecordDTO(nextID(), asStringObjectMap(savedMetadataFieldName, "firstAdded"));
RecordDTO secondAddedRecord = new RecordDTO(nextID(), asStringObjectMap(savedMetadataFieldName, "secondAdded"));
RecordDeltaDTO firstUpdatedRecord = new RecordDeltaDTO(firstAlreadySavedRecord, asStringObjectMap(savedMetadataFieldName,
"firstModified"), firstAddedRecord.getFields());
RecordDeltaDTO secondUpdatedRecord = new RecordDeltaDTO(secondAlreadySavedRecord, asStringObjectMap(
savedMetadataFieldName, "secondModified"), secondAddedRecord.getFields());
TransactionDTO transaction = new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW,
asList(firstAddedRecord, secondAddedRecord), asList(firstUpdatedRecord, secondUpdatedRecord));
recordDao.execute(transaction);
RecordDTO firstModifiedRecord = recordDao.get(firstAlreadySavedRecord.getId());
RecordDTO secondModifiedRecord = recordDao.get(secondAlreadySavedRecord.getId());
assertThat(recordDao.documentsCount()).isEqualTo(initialDocumentsCount + 2);
assertThat(firstAddedRecord.getFields().get(savedMetadataFieldName)).isEqualTo("firstAdded");
assertThat(secondAddedRecord.getFields().get(savedMetadataFieldName)).isEqualTo("secondAdded");
assertThat(firstModifiedRecord.getFields().get(savedMetadataFieldName)).isEqualTo("firstModified");
assertThat(secondModifiedRecord.getFields().get(savedMetadataFieldName)).isEqualTo("secondModified");
}
private String nextID() {
return UUID.randomUUID().toString();
}
private void updateRecordChangingItsVersion(RecordDTO recordDTO)
throws Exception {
RecordDTO zeRecord = recordDao.get(recordDTO.getId());
update(new RecordDeltaDTO(zeRecord, asStringObjectMap("anotaTrivialField_s", 1.1), zeRecord.getFields()));
}
private void add(RecordDTO recordDTO)
throws OptimisticLocking {
recordDao.execute(new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW, Arrays.asList(recordDTO),
new ArrayList<RecordDeltaDTO>()));
}
private void update(RecordDeltaDTO recordDeltaDTO)
throws OptimisticLocking {
recordDao.execute(new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW, new ArrayList<RecordDTO>(),
Arrays.asList(recordDeltaDTO)));
}
@Test
public void givenExceptionWhenExecutingTransactionThenNoModificationsApplied_run1()
throws Exception {
givenExceptionWhenExecutingTransactionThenNoModificationsApplied();
}
@Test
public void givenExceptionWhenExecutingTransactionThenNoModificationsApplied_run2()
throws Exception {
givenExceptionWhenExecutingTransactionThenNoModificationsApplied();
}
@Test
public void givenExceptionWhenExecutingTransactionThenNoModificationsApplied_run3()
throws Exception {
givenExceptionWhenExecutingTransactionThenNoModificationsApplied();
}
@Test
public void givenExceptionWhenExecutingTransactionThenNoModificationsApplied_run4()
throws Exception {
givenExceptionWhenExecutingTransactionThenNoModificationsApplied();
}
@Test
public void givenExceptionWhenExecutingTransactionThenNoModificationsApplied_run5()
throws Exception {
givenExceptionWhenExecutingTransactionThenNoModificationsApplied();
}
private void givenExceptionWhenExecutingTransactionThenNoModificationsApplied()
throws Exception {
List<SolrParams> deleteByQueries = asList((SolrParams) new ModifiableSolrParams().set("q", "savedField_s:666"));
RecordDTO firstAlreadySavedRecord = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
RecordDTO secondAlreadySavedRecord = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
RecordDTO thirdAlreadySavedRecordWhichIsDeletedById = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
RecordDTO fourthAlreadySavedRecordWhichIsDeletedById = givenSavedRecordWithInitialValueInSavedMetadataFieldName();
RecordDTO fifthAlreadySavedRecordWhichIsDeletedByQuery = givenSavedRecordWithValueInSavedMetadataFieldName("666");
updateRecordChangingItsVersion(firstAlreadySavedRecord);
printTimeElapsedSinceLastCall("1");
long initialDocumentsCount = recordDao.documentsCount();
RecordDTO firstAddedRecord = new RecordDTO(nextID(), asStringObjectMap(savedMetadataFieldName, "firstAdded"));
RecordDTO secondAddedRecord = new RecordDTO(nextID(), asStringObjectMap(savedMetadataFieldName, "secondAdded"));
RecordDeltaDTO firstUpdatedRecord = new RecordDeltaDTO(firstAlreadySavedRecord, asStringObjectMap(savedMetadataFieldName,
"firstModified"), firstAddedRecord.getFields());
RecordDeltaDTO secondUpdatedRecord = new RecordDeltaDTO(secondAlreadySavedRecord, asStringObjectMap(
savedMetadataFieldName, "secondModified"), secondAddedRecord.getFields());
TransactionDTO transaction = new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW,
asList(firstAddedRecord, secondAddedRecord), asList(firstUpdatedRecord, secondUpdatedRecord),
asList(thirdAlreadySavedRecordWhichIsDeletedById, fourthAlreadySavedRecordWhichIsDeletedById), deleteByQueries);
printTimeElapsedSinceLastCall("2");
try {
recordDao.execute(transaction);
fail("Optimistic locking expteced");
} catch (RecordDaoException.OptimisticLocking e) {
// OK
}
updateRecordChangingItsVersion(firstAlreadySavedRecord);
printTimeElapsedSinceLastCall("3");
secondAlreadySavedRecord = recordDao.get(secondAlreadySavedRecord.getId());
thirdAlreadySavedRecordWhichIsDeletedById = recordDao.get(thirdAlreadySavedRecordWhichIsDeletedById.getId());
fourthAlreadySavedRecordWhichIsDeletedById = recordDao.get(fourthAlreadySavedRecordWhichIsDeletedById.getId());
secondUpdatedRecord = new RecordDeltaDTO(secondAlreadySavedRecord, asStringObjectMap(
savedMetadataFieldName, "secondModified"), secondAddedRecord.getFields());
assertThat(getFieldValue(secondAlreadySavedRecord.getId(), savedMetadataFieldName)).isEqualTo(initialValue);
assertThat(getFieldValue(secondUpdatedRecord.getId(), savedMetadataFieldName)).isEqualTo(initialValue);
assertThat(recordDao.documentsCount()).isEqualTo(initialDocumentsCount);
assertThat(hasRecord(firstAddedRecord.getId())).isFalse();
assertThat(hasRecord(secondAddedRecord.getId())).isFalse();
assertThat(hasRecord(thirdAlreadySavedRecordWhichIsDeletedById.getId())).isTrue();
assertThat(hasRecord(fourthAlreadySavedRecordWhichIsDeletedById.getId())).isTrue();
assertThat(hasRecord(fifthAlreadySavedRecordWhichIsDeletedByQuery.getId())).isTrue();
printTimeElapsedSinceLastCall("4");
//Let's do the same transaction without the document with optimistic locking and verify that it is correct
transaction = new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW,
asList(firstAddedRecord, secondAddedRecord), asList(secondUpdatedRecord),
asList(thirdAlreadySavedRecordWhichIsDeletedById, fourthAlreadySavedRecordWhichIsDeletedById), deleteByQueries);
recordDao.execute(transaction);
printTimeElapsedSinceLastCall("5");
assertThat(getFieldValue(secondUpdatedRecord.getId(), savedMetadataFieldName)).isEqualTo("secondModified");
printTimeElapsedSinceLastCall("5a");
assertThat(recordDao.documentsCount()).isEqualTo(initialDocumentsCount - 1);
printTimeElapsedSinceLastCall("5b");
assertThat(hasRecord(firstAddedRecord.getId())).isTrue();
printTimeElapsedSinceLastCall("5c");
assertThat(hasRecord(secondAddedRecord.getId())).isTrue();
printTimeElapsedSinceLastCall("5d");
assertThat(hasRecord(thirdAlreadySavedRecordWhichIsDeletedById.getId())).isFalse();
printTimeElapsedSinceLastCall("5e");
assertThat(hasRecord(fourthAlreadySavedRecordWhichIsDeletedById.getId())).isFalse();
printTimeElapsedSinceLastCall("5f");
assertThat(hasRecord(fifthAlreadySavedRecordWhichIsDeletedByQuery.getId())).isFalse();
printTimeElapsedSinceLastCall("6");
}
@Test
public void givenDeleteByQueryCalledThenDeleteOnlyTargettedRecords()
throws Exception {
Map<String, Object> fieldWith42 = new HashMap();
fieldWith42.put("afield_s", 42);
Map<String, Object> fieldWith42AndChuckNorris = new HashMap();
fieldWith42AndChuckNorris.put("afield_s", 42);
fieldWith42AndChuckNorris.put("anotherfield_s", "ChuckNorris");
Map<String, Object> fieldWith28AndChuckNorris = new HashMap();
fieldWith28AndChuckNorris.put("afield_s", 28);
fieldWith28AndChuckNorris.put("anotherfield_s", "ChuckNorris");
RecordDTO record1 = saveRecordWithFieldsAndLoadItFromStore(fieldWith42, "1");
RecordDTO record2 = saveRecordWithFieldsAndLoadItFromStore(fieldWith42AndChuckNorris, "2");
RecordDTO record3 = saveRecordWithFieldsAndLoadItFromStore(fieldWith28AndChuckNorris, "3");
assertThat(hasRecord(record1.getId())).isTrue();
assertThat(hasRecord(record2.getId())).isTrue();
assertThat(hasRecord(record3.getId())).isTrue();
ModifiableSolrParams solrParams = new ModifiableSolrParams();
solrParams.set("q", "afield_s:42");
solrParams.set("fq", "anotherfield_s:ChuckNorris");
recordDao.execute(new TransactionDTO(RecordsFlushing.NOW).withDeletedByQueries(solrParams));
assertThat(hasRecord(record1.getId())).isTrue();
assertThat(hasRecord(record2.getId())).isFalse();
assertThat(hasRecord(record3.getId())).isTrue();
solrParams = new ModifiableSolrParams();
solrParams.set("q", "*:*");
solrParams.set("fq", "anotherfield_s:ChuckNorris");
recordDao.execute(new TransactionDTO(RecordsFlushing.NOW).withDeletedByQueries(solrParams));
assertThat(hasRecord(record1.getId())).isTrue();
assertThat(hasRecord(record2.getId())).isFalse();
assertThat(hasRecord(record3.getId())).isFalse();
solrParams = new ModifiableSolrParams();
solrParams.set("q", "afield_s:42");
recordDao.execute(new TransactionDTO(RecordsFlushing.NOW).withDeletedByQueries(solrParams));
assertThat(hasRecord(record1.getId())).isFalse();
assertThat(hasRecord(record2.getId())).isFalse();
assertThat(hasRecord(record3.getId())).isFalse();
}
@Test
public void givenDeleteByIdCalledThenDeleteOnlyTargettedRecords()
throws Exception {
Map<String, Object> fieldWith42 = new HashMap();
fieldWith42.put("afield_s", 42);
Map<String, Object> fieldWith42AndChuckNorris = new HashMap();
fieldWith42AndChuckNorris.put("afield_s", 42);
fieldWith42AndChuckNorris.put("anotherfield_s", "ChuckNorris");
Map<String, Object> fieldWith28AndChuckNorris = new HashMap();
fieldWith28AndChuckNorris.put("afield_s", 28);
fieldWith28AndChuckNorris.put("anotherfield_s", "ChuckNorris");
RecordDTO record1 = saveRecordWithFieldsAndLoadItFromStore(fieldWith42, "1");
RecordDTO record2 = saveRecordWithFieldsAndLoadItFromStore(fieldWith42AndChuckNorris, "2");
RecordDTO record3 = saveRecordWithFieldsAndLoadItFromStore(fieldWith28AndChuckNorris, "3");
assertThat(hasRecord(record1.getId())).isTrue();
assertThat(hasRecord(record2.getId())).isTrue();
assertThat(hasRecord(record3.getId())).isTrue();
List<RecordDTO> newRecords = new ArrayList<>();
List<RecordDeltaDTO> modifiedRecords = new ArrayList<>();
List<RecordDTO> deletedRecords = Arrays.asList(record1, record3);
List<SolrParams> deletedRecordsByQuery = new ArrayList<>();
TransactionDTO transactionDTO = new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW, newRecords,
modifiedRecords, deletedRecords, deletedRecordsByQuery);
recordDao.execute(transactionDTO);
assertThat(hasRecord(record1.getId())).isFalse();
assertThat(hasRecord(record2.getId())).isTrue();
assertThat(hasRecord(record3.getId())).isFalse();
}
@Test(expected = NoSuchRecordWithId.class)
public void whenDeletingRecordsThenAllReferencesDecrementedAndItsRefCountIsDeleted()
throws Exception {
RecordDTO referencedRecord1 = newRecordWithTitle("referencedRecord1");
RecordDTO referencedRecord2 = newRecordWithTitle("referencedRecord2");
RecordDTO record = newRecordWithMultipleReferences(Arrays.asList(referencedRecord1.getId(), referencedRecord2.getId()));
add(referencedRecord1);
add(referencedRecord2);
add(record);
TransactionDTO transactionDTO = new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW,
new ArrayList<RecordDTO>(), new ArrayList<RecordDeltaDTO>(), Arrays.asList(record), new ArrayList<SolrParams>());
recordDao.execute(transactionDTO);
assertEquals(0.0, recordDao.get("idx_rfc_" + referencedRecord1.getId()).getFields().get("refs_d"));
assertEquals(0.0, recordDao.get("idx_rfc_" + referencedRecord2.getId()).getFields().get("refs_d"));
recordDao.get("idx_rfc_" + record.getId());
}
private String getFieldValue(String id, String field) {
try {
return (String) recordDao.get(id).getFields().get(field);
} catch (NoSuchRecordWithId noSuchRecordWithId) {
throw new RuntimeException(noSuchRecordWithId);
}
}
private boolean hasRecord(String id) {
try {
recordDao.get(id);
return true;
} catch (NoSuchRecordWithId noSuchRecordWithId) {
return false;
}
}
private MapBuilder<String, Object> buildParamMapWith(String collection, String schema) {
return MapBuilder.with("collection_s", (Object) collection).andWith("schema_s", schema);
}
}