[MNT-20179] Integration Test + some test refactor

This commit is contained in:
agazzarini
2019-05-07 14:49:40 +02:00
parent 6121877e71
commit ba2e80874e
14 changed files with 238 additions and 199 deletions

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2005-2017 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.dataload;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.common.SolrInputDocument;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Random;
public class Loader {
public static void main(String args[]) throws Exception {
int num = Integer.parseInt(args[0]);
int start = Integer.parseInt(args[1]);
//String url = "http://localhost:8985/solr/joel";
String url = "http://localhost:8983/solr/collection1";
HttpSolrClient client = new HttpSolrClient(url);
UpdateRequest request = new UpdateRequest();
int i = start;
LocalDateTime localDate = LocalDateTime.now();
Random rand = new Random();
for(i=start; i<num+start; i++) {
String s = rand.nextInt(1000)+"helloworld123";
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", i);
doc.addField("test_s", s);
doc.addField("test_t", "hello world we love you");
int year = rand.nextInt(50);
int month = rand.nextInt(12);
int day = rand.nextInt(30);
float f = rand.nextFloat();
doc.addField("year_i", Integer.toString(year));
doc.addField("month_i", Integer.toString(month));
doc.addField("day_i", Integer.toString(day));
doc.addField("price_f", Float.toString(f));
LocalDateTime randomDate = localDate.plusDays(rand.nextInt(1000));
doc.addField("date_dt", DateTimeFormatter.ISO_INSTANT.format(randomDate.toInstant(ZoneOffset.UTC)));
doc.addField("epoch_l", randomDate.atZone(ZoneOffset.UTC).toInstant().toEpochMilli());
request.add(doc);
if(i % 5000 == 0) {
request.process(client);
client.commit();
request = new UpdateRequest();
}
for(int l=0; l<5; l++) {
String ps = "product"+rand.nextInt(35);
doc.addField("prod_ss",ps);
}
}
if((i % 5000) != 0) {
request.process(client);
client.commit();
}
client.close();
}
}

View File

@@ -18,6 +18,8 @@
*/ */
package org.alfresco.solr; package org.alfresco.solr;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
import static junit.framework.TestCase.assertNotNull; import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue; import static junit.framework.TestCase.assertTrue;
import static org.alfresco.repo.search.adaptor.lucene.QueryConstants.FIELD_ACLID; import static org.alfresco.repo.search.adaptor.lucene.QueryConstants.FIELD_ACLID;
@@ -68,6 +70,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.index.shard.ShardState;
import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -86,11 +89,11 @@ import org.alfresco.solr.client.StringPropertyValue;
import org.alfresco.solr.client.Transaction; import org.alfresco.solr.client.Transaction;
import org.alfresco.util.ISO9075; import org.alfresco.util.ISO9075;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.SolrTestCaseJ4.XmlDoc; import org.apache.solr.SolrTestCaseJ4.XmlDoc;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.XML; import org.apache.solr.common.util.XML;
import org.apache.solr.core.CoreContainer; import org.apache.solr.core.CoreContainer;
@@ -108,6 +111,8 @@ import org.apache.solr.update.CommitUpdateCommand;
public class AlfrescoSolrUtils public class AlfrescoSolrUtils
{ {
public static final String TEST_NAMESPACE = "http://www.alfresco.org/test/solrtest"; public static final String TEST_NAMESPACE = "http://www.alfresco.org/test/solrtest";
public static long MAX_WAIT_TIME = 80000;
/** /**
* Get transaction. * Get transaction.
* @param deletes * @param deletes
@@ -884,5 +889,40 @@ public class AlfrescoSolrUtils
assertTrue("There must be a searcher for "+coreName, ((Integer)coreSummary.get("Number of Searchers")) > 0); assertTrue("There must be a searcher for "+coreName, ((Integer)coreSummary.get("Number of Searchers")) > 0);
} }
/**
* Asserts that the input {@link ShardState} and the CoreAdmin.SUMMARY response give the same information.
*
* @param state the {@link ShardState} instance.
* @param core the target {@link SolrCore} instance.
*/
public static void assertShardAndCoreSummaryConsistency(ShardState state, SolrCore core) {
SolrParams params =
new ModifiableSolrParams()
.add(CoreAdminParams.CORE, core.getName())
.add(CoreAdminParams.ACTION, "SUMMARY");
SolrQueryRequest request = new LocalSolrQueryRequest(core, params);
SolrQueryResponse response = new SolrQueryResponse();
coreAdminHandler(core).handleRequest(request, response);
NamedList<?> summary =
ofNullable(response.getValues())
.map(values -> values.get("Summary"))
.map(NamedList.class::cast)
.map(values -> values.get(core.getName()))
.map(NamedList.class::cast)
.orElseGet(NamedList::new);
assertEquals(state.getLastIndexedChangeSetId(), summary.get("Id for last Change Set in index"));
assertEquals(state.getLastIndexedChangeSetCommitTime(), summary.get("Last Index Change Set Commit Time"));
assertEquals(state.getLastIndexedTxCommitTime(), summary.get("Last Index TX Commit Time"));
assertEquals(state.getLastIndexedTxId(), summary.get("Id for last TX in index"));
}
public static AlfrescoCoreAdminHandler coreAdminHandler(SolrCore core) {
return of(core).map(SolrCore::getCoreContainer)
.map(CoreContainer::getMultiCoreHandler)
.map(AlfrescoCoreAdminHandler.class::cast)
.orElseThrow(() -> new IllegalStateException("Cannot retrieve the Core Admin Handler on this test core."));
}
} }

View File

@@ -16,10 +16,11 @@
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.alfresco.solr.query.afts; package org.alfresco.solr.dataload;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.stream.IntStream.range;
import static org.alfresco.model.ContentModel.ASSOC_CONTAINS; import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
import static org.alfresco.model.ContentModel.ASSOC_CHILDREN; import static org.alfresco.model.ContentModel.ASSOC_CHILDREN;
import static org.alfresco.model.ContentModel.PROP_NAME; import static org.alfresco.model.ContentModel.PROP_NAME;
@@ -28,6 +29,8 @@ import static org.alfresco.service.namespace.NamespaceService.CONTENT_MODEL_1_0_
import static org.alfresco.solr.AlfrescoSolrUtils.addNode; import static org.alfresco.solr.AlfrescoSolrUtils.addNode;
import static org.alfresco.solr.AlfrescoSolrUtils.createGUID; import static org.alfresco.solr.AlfrescoSolrUtils.createGUID;
import static org.alfresco.solr.AlfrescoSolrUtils.addStoreRoot; import static org.alfresco.solr.AlfrescoSolrUtils.addStoreRoot;
import static org.alfresco.solr.AlfrescoSolrUtils.getNode;
import static org.alfresco.solr.AlfrescoSolrUtils.getNodeMetaData;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -39,19 +42,27 @@ import org.alfresco.service.cmr.repository.datatype.Duration;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.solr.AlfrescoSolrConstants; import org.alfresco.solr.AlfrescoSolrConstants;
import org.alfresco.solr.AlfrescoSolrDataModel; import org.alfresco.solr.AlfrescoSolrDataModel;
import org.alfresco.solr.client.Acl;
import org.alfresco.solr.client.ContentPropertyValue; import org.alfresco.solr.client.ContentPropertyValue;
import org.alfresco.solr.client.MLTextPropertyValue; import org.alfresco.solr.client.MLTextPropertyValue;
import org.alfresco.solr.client.MultiPropertyValue; import org.alfresco.solr.client.MultiPropertyValue;
import org.alfresco.solr.client.Node;
import org.alfresco.solr.client.NodeMetaData;
import org.alfresco.solr.client.PropertyValue; import org.alfresco.solr.client.PropertyValue;
import org.alfresco.solr.client.StringPropertyValue; import org.alfresco.solr.client.StringPropertyValue;
import org.alfresco.solr.client.Transaction;
import org.alfresco.util.ISO9075; import org.alfresco.util.ISO9075;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.util.TestHarness; import org.apache.solr.util.TestHarness;
import java.util.AbstractMap;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
/** /**
* Test datasets provider. * Test datasets provider.
@@ -855,6 +866,14 @@ public class TestDataProvider implements AlfrescoSolrConstants
return testProperties; return testProperties;
} }
public static Map.Entry<List<Node>, List<NodeMetaData>> nSampleNodesWithSampleContent(Acl acl, Transaction txn, int howManyNodes) {
List<Node> nodes = range(0, howManyNodes).mapToObj(index -> getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED)).collect(Collectors.toList());
List<NodeMetaData> metadata = nodes.stream().map(node -> getNodeMetaData(node, txn, acl, "mike", null, false)).collect(Collectors.toList());
return new AbstractMap.SimpleImmutableEntry<>(nodes, metadata);
}
public NodeRef newNodeRef() public NodeRef newNodeRef()
{ {
return new NodeRef(new StoreRef("workspace", "SpacesStore"), createGUID()); return new NodeRef(new StoreRef("workspace", "SpacesStore"), createGUID());

View File

@@ -19,7 +19,7 @@
package org.alfresco.solr.query.afts.qparser; package org.alfresco.solr.query.afts.qparser;
import org.alfresco.repo.search.adaptor.lucene.QueryConstants; import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.alfresco.util.ISO9075; import org.alfresco.util.ISO9075;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;

View File

@@ -30,7 +30,7 @@ import static org.alfresco.model.ContentModel.TYPE_THUMBNAIL;
import org.alfresco.repo.search.adaptor.lucene.QueryConstants; import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.alfresco.util.CachingDateFormat; import org.alfresco.util.CachingDateFormat;
import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4;
import org.junit.BeforeClass; import org.junit.BeforeClass;

View File

@@ -22,7 +22,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.solr.client.PropertyValue; import org.alfresco.solr.client.PropertyValue;
import org.alfresco.solr.client.StringPropertyValue; import org.alfresco.solr.client.StringPropertyValue;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;

View File

@@ -30,7 +30,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.solr.client.PropertyValue; import org.alfresco.solr.client.PropertyValue;
import org.alfresco.solr.client.StringPropertyValue; import org.alfresco.solr.client.StringPropertyValue;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;

View File

@@ -27,7 +27,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.solr.client.PropertyValue; import org.alfresco.solr.client.PropertyValue;
import org.alfresco.solr.client.StringPropertyValue; import org.alfresco.solr.client.StringPropertyValue;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;

View File

@@ -28,7 +28,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.solr.client.PropertyValue; import org.alfresco.solr.client.PropertyValue;
import org.alfresco.solr.client.StringPropertyValue; import org.alfresco.solr.client.StringPropertyValue;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;

View File

@@ -10,7 +10,7 @@ import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.solr.AlfrescoSolrDataModel; import org.alfresco.solr.AlfrescoSolrDataModel;
import org.alfresco.solr.SolrInformationServer; import org.alfresco.solr.SolrInformationServer;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase;
import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4;
import org.junit.BeforeClass; import org.junit.BeforeClass;

View File

@@ -1,6 +1,6 @@
package org.alfresco.solr.query.afts.requestHandler; package org.alfresco.solr.query.afts.requestHandler;
import org.alfresco.solr.query.afts.TestDataProvider; import org.alfresco.solr.dataload.TestDataProvider;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;

View File

@@ -19,7 +19,6 @@
package org.alfresco.solr.tracker; package org.alfresco.solr.tracker;
import org.alfresco.repo.index.shard.ShardState;
import org.alfresco.repo.search.adaptor.lucene.QueryConstants; import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
import org.alfresco.solr.AbstractAlfrescoSolrTests; import org.alfresco.solr.AbstractAlfrescoSolrTests;
import org.alfresco.solr.AlfrescoCoreAdminHandler; import org.alfresco.solr.AlfrescoCoreAdminHandler;
@@ -29,135 +28,98 @@ import org.alfresco.solr.client.AclReaders;
import org.alfresco.solr.client.Node; import org.alfresco.solr.client.Node;
import org.alfresco.solr.client.NodeMetaData; import org.alfresco.solr.client.NodeMetaData;
import org.alfresco.solr.client.Transaction; import org.alfresco.solr.client.Transaction;
import org.alfresco.solr.dataload.TestDataProvider;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.LegacyNumericRangeQuery; import org.apache.lucene.search.LegacyNumericRangeQuery;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.util.List;
import java.util.Map;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.Optional.of; import static java.util.Optional.of;
import static java.util.Optional.ofNullable; import static org.alfresco.solr.AlfrescoSolrUtils.MAX_WAIT_TIME;
import static org.alfresco.solr.AlfrescoSolrUtils.assertShardAndCoreSummaryConsistency;
import static org.alfresco.solr.AlfrescoSolrUtils.coreAdminHandler;
import static org.alfresco.solr.AlfrescoSolrUtils.getAcl; import static org.alfresco.solr.AlfrescoSolrUtils.getAcl;
import static org.alfresco.solr.AlfrescoSolrUtils.getAclChangeSet; import static org.alfresco.solr.AlfrescoSolrUtils.getAclChangeSet;
import static org.alfresco.solr.AlfrescoSolrUtils.getAclReaders; import static org.alfresco.solr.AlfrescoSolrUtils.getAclReaders;
import static org.alfresco.solr.AlfrescoSolrUtils.getNode;
import static org.alfresco.solr.AlfrescoSolrUtils.getNodeMetaData;
import static org.alfresco.solr.AlfrescoSolrUtils.getTransaction; import static org.alfresco.solr.AlfrescoSolrUtils.getTransaction;
import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet; import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet;
import static org.junit.Assert.assertEquals;
/**
* A partial state of {@link org.alfresco.solr.TrackerState} is exposed through two interfaces: AdminHandler.SUMMARY and
* {@link MetadataTracker#getShardState}.
*
* This test makes sure that state is consistent across the two mentioned approaches. That is, properties returned by the
* Core SUMMARY must have the same value of the same properties in the ShardState.
*
* @author agazzarini
*/
public class AlfrescoSolrTrackerStateTest extends AbstractAlfrescoSolrTests public class AlfrescoSolrTrackerStateTest extends AbstractAlfrescoSolrTests
{ {
private static long MAX_WAIT_TIME = 80000;
@BeforeClass @BeforeClass
public static void beforeClass() throws Exception public static void beforeClass() throws Exception
{ {
initAlfrescoCore("schema.xml"); initAlfrescoCore("schema.xml");
} }
private Acl acl;
@Before @Before
public void prepare() throws Exception public void prepare() throws Exception
{ {
AclChangeSet aclChangeSet = getAclChangeSet(1); AclChangeSet aclChangeSet = getAclChangeSet(1);
acl = getAcl(aclChangeSet);
Acl acl = getAcl(aclChangeSet);
Acl acl2 = getAcl(aclChangeSet); Acl acl2 = getAcl(aclChangeSet);
AclReaders aclReaders = getAclReaders(aclChangeSet, acl, singletonList("joel"), singletonList("phil"), null); AclReaders aclReaders = getAclReaders(aclChangeSet, acl, singletonList("joel"), singletonList("phil"), null);
AclReaders aclReaders2 = getAclReaders(aclChangeSet, acl2, singletonList("jim"), singletonList("phil"), null); AclReaders aclReaders2 = getAclReaders(aclChangeSet, acl2, singletonList("jim"), singletonList("phil"), null);
indexAclChangeSet(aclChangeSet, indexAclChangeSet(aclChangeSet, asList(acl, acl2), asList(aclReaders, aclReaders2));
asList(acl, acl2),
asList(aclReaders, aclReaders2));
// Check for the ACL state stamp.
BooleanQuery.Builder builder = new BooleanQuery.Builder(); BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!ACLTX")), BooleanClause.Occur.MUST)); builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!ACLTX")), BooleanClause.Occur.MUST));
builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_ACLTXID, aclChangeSet.getId(), aclChangeSet.getId() + 1, true, false), BooleanClause.Occur.MUST)); builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_ACLTXID, aclChangeSet.getId(), aclChangeSet.getId() + 1, true, false), BooleanClause.Occur.MUST));
BooleanQuery waitForQuery = builder.build(); BooleanQuery waitForQuery = builder.build();
waitForDocCount(waitForQuery, 1, MAX_WAIT_TIME); waitForDocCount(waitForQuery, 1, MAX_WAIT_TIME);
int howManyTestNodes = 4;
Transaction txn = getTransaction(0, howManyTestNodes);
Map.Entry<List<Node>, List<NodeMetaData>> data = TestDataProvider.nSampleNodesWithSampleContent(acl, txn, howManyTestNodes);
indexTransaction(txn, data.getKey(), data.getValue());
makeSureTransactionHasBeenIndexed(txn.getId());
makeSureNodesHaveBeenIndexed(data.getKey().size());
} }
@Test @Test
public void shardStateMustBeConsistentWithCoreSummaryStats() throws Exception @SuppressWarnings("deprecated")
public void shardStateMustBeConsistentWithCoreSummaryStats()
{ {
Transaction txn = getTransaction(0, 4);
Node node1 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
Node node2 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
Node node3 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
Node node4 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
NodeMetaData nodeMetaData1 = getNodeMetaData(node1, txn, acl, "mike", null, false);
NodeMetaData nodeMetaData2 = getNodeMetaData(node2, txn, acl, "mike", null, false);
NodeMetaData nodeMetaData3 = getNodeMetaData(node3, txn, acl, "mike", null, false);
NodeMetaData nodeMetaData4 = getNodeMetaData(node4, txn, acl, "mike", null, false);
indexTransaction(txn,
asList(node1, node2, node3, node4),
asList(nodeMetaData1, nodeMetaData2, nodeMetaData3, nodeMetaData4));
makeSureTransactionHasBeenIndexed(txn.getId());
makeSureNodesHaveBeenIndexed("mike", 4);
SolrCore core = getCore(); SolrCore core = getCore();
AlfrescoCoreAdminHandler adminHandler =
of(core).map(SolrCore::getCoreContainer)
.map(CoreContainer::getMultiCoreHandler)
.map(AlfrescoCoreAdminHandler.class::cast)
.orElseThrow(() -> new IllegalStateException("Cannot retrieve the Core Admin Handler on this test core."));
MetadataTracker tracker = MetadataTracker tracker =
of(adminHandler) of(coreAdminHandler(core))
.map(AlfrescoCoreAdminHandler::getTrackerRegistry) .map(AlfrescoCoreAdminHandler::getTrackerRegistry)
.map(registry -> registry.getTrackerForCore(core.getName(), MetadataTracker.class)) .map(registry -> registry.getTrackerForCore(core.getName(), MetadataTracker.class))
.orElseThrow(() -> new IllegalStateException("Cannot retrieve the Metadata tracker on this test core.")); .orElseThrow(() -> new IllegalStateException("Cannot retrieve the Metadata tracker on this test core."));
ShardState state = tracker.getShardState(); assertShardAndCoreSummaryConsistency(tracker.getShardState(), core);
SolrParams params =
new ModifiableSolrParams()
.add(CoreAdminParams.CORE, core.getName())
.add(CoreAdminParams.ACTION, "SUMMARY");
SolrQueryRequest request = new LocalSolrQueryRequest(core, params);
SolrQueryResponse response = new SolrQueryResponse();
adminHandler.handleRequest(request, response);
NamedList<?> summary =
ofNullable(response.getValues())
.map(values -> values.get("Summary"))
.map(NamedList.class::cast)
.map(values -> values.get(core.getName()))
.map(NamedList.class::cast)
.orElseGet(NamedList::new);
assertEquals(state.getLastIndexedChangeSetId(), summary.get("Id for last Change Set in index"));
assertEquals(state.getLastIndexedChangeSetCommitTime(), summary.get("Last Index Change Set Commit Time"));
assertEquals(state.getLastIndexedTxCommitTime(), summary.get("Last Index TX Commit Time"));
assertEquals(state.getLastIndexedTxId(), summary.get("Id for last TX in index"));
} }
private void makeSureTransactionHasBeenIndexed(long transactionId) throws Exception private void makeSureTransactionHasBeenIndexed(long transactionId) throws Exception
{ {
//Check for the TXN state stamp.
BooleanQuery.Builder builder = new BooleanQuery.Builder(); BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!TX")), BooleanClause.Occur.MUST)); builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!TX")), BooleanClause.Occur.MUST));
builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_TXID, transactionId, transactionId + 1, true, false), BooleanClause.Occur.MUST)); builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_TXID, transactionId, transactionId + 1, true, false), BooleanClause.Occur.MUST));
@@ -165,36 +127,14 @@ public class AlfrescoSolrTrackerStateTest extends AbstractAlfrescoSolrTests
waitForDocCount(waitForQuery, 1, MAX_WAIT_TIME); waitForDocCount(waitForQuery, 1, MAX_WAIT_TIME);
} }
/** private void makeSureNodesHaveBeenIndexed(int expectedCount) throws Exception
* Queries the index using a token from the (dummy) text produced by the test framework.
* Once the query returns a positive result we are sure the ContentTracker
*
* <ol>
* <li>
* Fetched the text content associated with the test nodes, from Alfresco
* </li>
* <li>
* Computed a fingerprint (using the retrieved text) for each node
* </li>
* <li>
* Updated the nodes definitions in the (Solr)ContentStore and in Solr
* </li>
* </ol>
*
* Last but not least, we are also making sure that CommitTracker executed its cycle as well (otherwise documents
* wouldn't be searchable).
*
* @param owner the #FIELD_OWNER which will be used as an additional required query clause.
* @throws Exception in case the MAX_WAIT_TIME is reached and the node is not in results.
*/
private void makeSureNodesHaveBeenIndexed(final String owner, final int expectedCount) throws Exception
{ {
waitForDocCount(new TermQuery(new Term(QueryConstants.FIELD_READER, "jim")), 1, MAX_WAIT_TIME); waitForDocCount(new TermQuery(new Term(QueryConstants.FIELD_READER, "jim")), 1, MAX_WAIT_TIME);
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", "world")), expectedCount, MAX_WAIT_TIME); waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", "world")), expectedCount, MAX_WAIT_TIME);
BooleanQuery.Builder builder = new BooleanQuery.Builder(); BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(new BooleanClause(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", "world")), BooleanClause.Occur.MUST)); builder.add(new BooleanClause(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", "world")), BooleanClause.Occur.MUST));
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_OWNER, owner)), BooleanClause.Occur.MUST)); builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_OWNER, "mike")), BooleanClause.Occur.MUST));
waitForDocCount(builder.build(), expectedCount, MAX_WAIT_TIME); waitForDocCount(builder.build(), expectedCount, MAX_WAIT_TIME);
} }
} }

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.solr.tracker;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.Optional.of;
import static org.alfresco.solr.AlfrescoSolrUtils.MAX_WAIT_TIME;
import static org.alfresco.solr.AlfrescoSolrUtils.assertShardAndCoreSummaryConsistency;
import static org.alfresco.solr.AlfrescoSolrUtils.coreAdminHandler;
import static org.alfresco.solr.AlfrescoSolrUtils.getAcl;
import static org.alfresco.solr.AlfrescoSolrUtils.getAclChangeSet;
import static org.alfresco.solr.AlfrescoSolrUtils.getAclReaders;
import static org.alfresco.solr.AlfrescoSolrUtils.getTransaction;
import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet;
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
import org.alfresco.solr.AlfrescoCoreAdminHandler;
import org.alfresco.solr.client.Acl;
import org.alfresco.solr.client.AclChangeSet;
import org.alfresco.solr.client.AclReaders;
import org.alfresco.solr.client.Node;
import org.alfresco.solr.client.NodeMetaData;
import org.alfresco.solr.client.Transaction;
import org.alfresco.solr.dataload.TestDataProvider;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.LegacyNumericRangeQuery;
import org.apache.lucene.search.TermQuery;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
import java.util.Map;
/**
* A partial state of {@link org.alfresco.solr.TrackerState} is exposed through two interfaces: AdminHandler.SUMMARY and
* {@link MetadataTracker#getShardState}.
* This test makes sure that state is consistent across the two mentioned approaches. That is, properties returned by the
* Core SUMMARY must have the same value of the same properties in the ShardState.
*
* Note that this is the distributed version of {@link AlfrescoSolrTrackerStateTest}.
*
* @author agazzarini
*/
public class DistributedAlfrescoSolrTrackerStateTest extends AbstractAlfrescoDistributedTest
{
@BeforeClass
private static void initData() throws Throwable
{
int howManyShards = 5;
int howManyNodes = 15;
initSolrServers(howManyShards, getClassName(),null);
AclChangeSet aclChangeSet = getAclChangeSet(1);
Acl acl = getAcl(aclChangeSet);
Acl acl2 = getAcl(aclChangeSet);
AclReaders aclReaders = getAclReaders(aclChangeSet, acl, singletonList("joel"), singletonList("phil"), null);
AclReaders aclReaders2 = getAclReaders(aclChangeSet, acl2, singletonList("jim"), singletonList("phil"), null);
indexAclChangeSet(aclChangeSet, asList(acl, acl2), asList(aclReaders, aclReaders2));
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!ACLTX")), BooleanClause.Occur.MUST));
builder.add(new BooleanClause(LongPoint.newExactQuery(QueryConstants.FIELD_S_ACLTXID, aclChangeSet.getId()), BooleanClause.Occur.MUST));
BooleanQuery waitForQuery = builder.build();
waitForDocCountAllCores(waitForQuery, 1, MAX_WAIT_TIME);
Transaction txn = getTransaction(0, howManyNodes);
Map.Entry<List<Node>, List<NodeMetaData>> data = TestDataProvider.nSampleNodesWithSampleContent(acl, txn, howManyNodes);
indexTransaction(txn, data.getKey(), data.getValue());
builder = new BooleanQuery.Builder();
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!TX")), BooleanClause.Occur.MUST));
builder.add(new BooleanClause(LongPoint.newExactQuery(QueryConstants.FIELD_S_TXID, txn.getId()), BooleanClause.Occur.MUST));
waitForQuery = builder.build();
waitForDocCountAllCores(waitForQuery, 1, MAX_WAIT_TIME);
waitForDocCountAllCores(new TermQuery(new Term(QueryConstants.FIELD_READER, "jim")), 1, MAX_WAIT_TIME);
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", "world")), howManyNodes, MAX_WAIT_TIME);
}
@AfterClass
private static void destroyData()
{
dismissSolrServers();
}
@Test
public void shardStateMustBeConsistentWithCoreSummaryStats()
{
putHandleDefaults();
getJettyCores(solrShards).forEach(core -> {
MetadataTracker tracker =
of(coreAdminHandler(core))
.map(AlfrescoCoreAdminHandler::getTrackerRegistry)
.map(registry -> registry.getTrackerForCore(core.getName(), MetadataTracker.class))
.orElseThrow(() -> new IllegalStateException("Cannot retrieve the Metadata tracker on this test core."));
assertShardAndCoreSummaryConsistency(tracker.getShardState(), core);
});
}
}

View File

@@ -118,7 +118,9 @@ public class DistributedDateMonthAlfrescoSolrTrackerTest extends AbstractAlfresc
Date[] dates = new Date[5]; Date[] dates = new Date[5];
Calendar cal = new GregorianCalendar(); Calendar cal = new GregorianCalendar();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
for (int i = 0; i < dates.length; i++) { for (int i = 0; i < dates.length; i++) {
cal.set(1980, i, 21); cal.set(1980, i, 21);
dates[i] = cal.getTime(); dates[i] = cal.getTime();
} }