blob: 7e4a67ac3f4973e2967d8676dd72286773ae8480 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.cloud;
import java.lang.invoke.MethodHandles;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.apache.lucene.util.TestUtil;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.schema.SchemaRequest.Field;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.schema.SchemaResponse.FieldResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.search.TestPseudoReturnFields;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
/**
* @see TestPseudoReturnFields
* @see TestRandomFlRTGCloud
*/
public class TestCloudPseudoReturnFields extends SolrCloudTestCase {
private static final String DEBUG_LABEL = MethodHandles.lookup().lookupClass().getName();
private static final String COLLECTION_NAME = DEBUG_LABEL + "_collection";
/** A basic client for operations at the cloud level, default collection will be set */
private static CloudSolrClient CLOUD_CLIENT;
/** One client per node */
private static final ArrayList<HttpSolrClient> CLIENTS = new ArrayList<>(5);
@BeforeClass
private static void createMiniSolrCloudCluster() throws Exception {
// multi replicas should matter...
final int repFactor = usually() ? 1 : 2;;
// ... but we definitely want to ensure forwarded requests to other shards work ...
final int numShards = 2;
// ... including some forwarded requests from nodes not hosting a shard
final int numNodes = 1 + (numShards * repFactor);
final String configName = DEBUG_LABEL + "_config-set";
final Path configDir = Paths.get(TEST_HOME(), "collection1", "conf");
configureCluster(numNodes).addConfig(configName, configDir).configure();
Map<String, String> collectionProperties = new HashMap<>();
collectionProperties.put("config", "solrconfig-tlog.xml");
collectionProperties.put("schema", "schema-psuedo-fields.xml");
CollectionAdminRequest.createCollection(COLLECTION_NAME, configName, numShards, repFactor)
.setProperties(collectionProperties)
.process(cluster.getSolrClient());
CLOUD_CLIENT = cluster.getSolrClient();
CLOUD_CLIENT.setDefaultCollection(COLLECTION_NAME);
waitForRecoveriesToFinish(CLOUD_CLIENT);
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
CLIENTS.add(getHttpSolrClient(jetty.getBaseUrl() + "/" + COLLECTION_NAME + "/"));
}
assertEquals(0, CLOUD_CLIENT.add(sdoc("id", "42", "val_i", "1", "ssto", "X", "subject", "aaa")).getStatus());
assertEquals(0, CLOUD_CLIENT.add(sdoc("id", "43", "val_i", "9", "ssto", "X", "subject", "bbb")).getStatus());
assertEquals(0, CLOUD_CLIENT.add(sdoc("id", "44", "val_i", "4", "ssto", "X", "subject", "aaa")).getStatus());
assertEquals(0, CLOUD_CLIENT.add(sdoc("id", "45", "val_i", "6", "ssto", "X", "subject", "aaa")).getStatus());
assertEquals(0, CLOUD_CLIENT.add(sdoc("id", "46", "val_i", "3", "ssto", "X", "subject", "ggg")).getStatus());
assertEquals(0, CLOUD_CLIENT.commit().getStatus());;
}
@Before
private void addUncommittedDoc99() throws Exception {
// uncommitted doc in transaction log at start of every test
// Even if an RTG causes ulog to re-open realtime searcher, next test method
// will get another copy of doc 99 in the ulog
assertEquals(0, CLOUD_CLIENT.add(sdoc("id", "99", "val_i", "1", "ssto", "X",
"subject", "uncommitted")).getStatus());
}
@AfterClass
private static void afterClass() throws Exception {
if (null != CLOUD_CLIENT) {
CLOUD_CLIENT.close();
CLOUD_CLIENT = null;
}
for (HttpSolrClient client : CLIENTS) {
client.close();
}
CLIENTS.clear();
}
public void testMultiValued() throws Exception {
// the response writers used to consult isMultiValued on the field
// but this doesn't work when you alias a single valued field to
// a multi valued field (the field value is copied first, then
// if the type lookup is done again later, we get the wrong thing). SOLR-4036
// score as psuedo field - precondition checks
for (String name : new String[] {"score", "val_ss"}) {
try {
FieldResponse frsp = new Field(name, params("includeDynamic","true",
"showDefaults","true")).process(CLOUD_CLIENT);
assertNotNull("Test depends on a (dynamic) field matching '"+name+"', Null response", frsp);
assertEquals("Test depends on a (dynamic) field matching '"+name+"', bad status: " + frsp.toString(),
0, frsp.getStatus());
assertNotNull("Test depends on a (dynamic) field matching '"+name+
"', schema was changed out from under us? ... " + frsp.toString(), frsp.getField());
assertEquals("Test depends on a multivalued dynamic field matching '"+name+
"', schema was changed out from under us? ... " + frsp.toString(),
Boolean.TRUE, frsp.getField().get("multiValued"));
} catch (SolrServerException e) {
assertEquals("Couldn't fetch field for '"+name+"' ... schema changed out from under us?",
null, e);
}
}
SolrDocument doc = null;
// score as psuedo field
doc = assertSearchOneDoc(params("q","*:*", "fq", "id:42", "fl","id,score,val_ss,val2_ss"));
assertEquals("42", doc.getFieldValue("id"));
assertEquals(1.0F, doc.getFieldValue("score"));
assertEquals(""+doc, 2, doc.size()); // no value for val2_ss or val_ss ... yet...
// TODO: update this test & TestPseudoReturnFields to index docs using a (multivalued) "val_ss" instead of "ssto"
//
// that way we can first sanity check a single value in a multivalued field is returned correctly
// as a "List" of one element, *AND* then we could be testing that a (single valued) psuedo-field correctly
// overrides that actual (real) value in a multivalued field (ie: not returning a an List)
//
// (NOTE: not doing this yet due to how it will impact most other tests, many of which are currently
// @AwaitsFix'ed)
//
//assertTrue(doc.getFieldValue("val_ss").getClass().toString(),
// doc.getFieldValue("val_ss") instanceof List);
// single value int using alias that matches multivalued dynamic field
doc = assertSearchOneDoc(params("q","id:42", "fl","val_ss:val_i, val2_ss:10"));
assertEquals(""+doc, 2, doc.size());
assertEquals(""+doc, 1, doc.getFieldValue("val_ss"));
assertEquals(""+doc, 10L, doc.getFieldValue("val2_ss"));
}
public void testMultiValuedRTG() throws Exception {
SolrDocument doc = null;
// check same results as testMultiValued via RTG (committed doc)
doc = getRandClient(random()).getById("42", params("fl","val_ss:val_i, val2_ss:10, subject"));
assertEquals(""+doc, 3, doc.size());
assertEquals(""+doc, 1, doc.getFieldValue("val_ss"));
assertEquals(""+doc, 10L, doc.getFieldValue("val2_ss"));
assertEquals(""+doc, "aaa", doc.getFieldValue("subject"));
// also check real-time-get from transaction log (uncommitted doc)
doc = getRandClient(random()).getById("99", params("fl","val_ss:val_i, val2_ss:10, subject"));
assertEquals(""+doc, 3, doc.size());
assertEquals(""+doc, 1, doc.getFieldValue("val_ss"));
assertEquals(""+doc, 10L, doc.getFieldValue("val2_ss"));
assertEquals(""+doc, "uncommitted", doc.getFieldValue("subject"));
}
public void testAllRealFields() throws Exception {
for (String fl : TestPseudoReturnFields.ALL_REAL_FIELDS) {
SolrDocumentList docs = assertSearch(params("q", "*:*", "rows", "10", "fl",fl));
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(fl + " => " + doc, 5, doc.size());
assertTrue(fl + " => " + doc, doc.getFieldValue("id") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(fl + " => " + doc, doc.getFieldValue("subject") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("ssto") instanceof String); // TODO: val_ss: List<String>
}
}
}
public void testAllRealFieldsRTG() throws Exception {
// shouldn't matter if we use RTG (committed or otherwise)
for (String fl : TestPseudoReturnFields.ALL_REAL_FIELDS) {
for (int i : Arrays.asList(42, 43, 44, 45, 46, 99)) {
SolrDocument doc = getRandClient(random()).getById(""+i, params("fl",fl));
assertEquals(fl + " => " + doc, 5, doc.size());
assertTrue(fl + " => " + doc, doc.getFieldValue("id") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(fl + " => " + doc, doc.getFieldValue("subject") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("ssto") instanceof String); // TODO: val_ss: List<String>
}
}
}
public void testFilterAndOneRealFieldRTG() throws Exception {
SolrParams params = params("fl","id,val_i",
"fq","{!field f='subject' v=$my_var}",
"my_var","uncommitted");
SolrDocumentList docs = getRandClient(random()).getById(Arrays.asList("42","99"), params);
final String msg = params + " => " + docs;
assertEquals(msg, 1, docs.size());
assertEquals(msg, 1, docs.getNumFound());
SolrDocument doc = docs.get(0);
assertEquals(msg, 2, doc.size());
assertEquals(msg, "99", doc.getFieldValue("id"));
assertEquals(msg, 1, doc.getFieldValue("val_i"));
}
public void testScoreAndAllRealFields() throws Exception {
for (String fl : TestPseudoReturnFields.SCORE_AND_REAL_FIELDS) {
SolrDocumentList docs = assertSearch(params("q", "*:*", "rows", "10", "fl",fl));
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(fl + " => " + doc, 6, doc.size());
assertTrue(fl + " => " + doc, doc.getFieldValue("id") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("score") instanceof Float);
assertTrue(fl + " => " + doc, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(fl + " => " + doc, doc.getFieldValue("subject") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("ssto") instanceof String); // TODO: val_ss: List<String>
}
}
}
public void testScoreAndAllRealFieldsRTG() throws Exception {
// also shouldn't matter if we use RTG (committed or otherwise) .. score should be ignored
for (String fl : TestPseudoReturnFields.SCORE_AND_REAL_FIELDS) {
for (int i : Arrays.asList(42, 43, 44, 45, 46, 99)) {
SolrDocument doc = getRandClient(random()).getById(""+i, params("fl",fl));
assertEquals(fl + " => " + doc, 5, doc.size());
assertTrue(fl + " => " + doc, doc.getFieldValue("id") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(fl + " => " + doc, doc.getFieldValue("subject") instanceof String);
assertTrue(fl + " => " + doc, doc.getFieldValue("ssto") instanceof String); // TODO: val_ss: List<String>
}
}
}
public void testScoreAndExplicitRealFields() throws Exception {
SolrDocumentList docs = null;
SolrDocument doc = null;
for (SolrParams p : Arrays.asList(params("q","*:*", "rows", "1", "fl","score,val_i"),
params("q","*:*", "rows", "1", "fl","score", "fl","val_i"))) {
docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
doc = docs.get(0); // doesn't really matter which one
assertEquals(p + " => " + doc, 2, doc.size());
assertTrue(p + " => " + doc, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(p + " => " + doc, doc.getFieldValue("score") instanceof Float);
}
docs = assertSearch(params("q","*:*", "rows", "1", "fl","val_i"));
assertEquals("" + docs, 5, docs.getNumFound());
doc = docs.get(0); // doesn't really matter which one
assertEquals("" + doc, 1, doc.size());
assertTrue("" + doc, doc.getFieldValue("val_i") instanceof Integer);
}
public void testScoreAndExplicitRealFieldsRTG() throws Exception {
SolrDocumentList docs = null;
SolrDocument doc = null;
// shouldn't matter if we use RTG (committed or otherwise) .. score should be ignored
for (int i : Arrays.asList(42, 43, 44, 45, 46, 99)) {
for (SolrParams p : Arrays.asList(params("fl","score,val_i"),
params("fl","score", "fl","val_i"))) {
doc = getRandClient(random()).getById(""+i, p);
assertEquals(p + " => " + doc, 1, doc.size());
assertTrue(p + " => " + doc, doc.getFieldValue("val_i") instanceof Integer);
}
}
}
public void testFunctions() throws Exception {
SolrDocumentList docs = assertSearch(params("q","*:*","rows","1","fl","log(val_i)"));
assertEquals(""+docs, 5, docs.getNumFound());
SolrDocument doc = docs.get(0); // doesn't really matter which one
assertEquals(""+doc, 1, doc.size());
assertTrue(""+doc, doc.getFieldValue("log(val_i)") instanceof Double);
for (SolrParams p : Arrays.asList(params("q","*:*", "rows", "1", "fl","log(val_i),abs(val_i)"),
params("q","*:*", "rows", "1", "fl","log(val_i)", "fl","abs(val_i)"))) {
docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
doc = docs.get(0); // doesn't really matter which one
assertEquals(p + " => " + doc, 2, doc.size());
assertTrue(p + " => " + doc, doc.getFieldValue("log(val_i)") instanceof Double);
assertTrue(p + " => " + doc, doc.getFieldValue("abs(val_i)") instanceof Float);
}
}
public void testFunctionsRTG() throws Exception {
// if we use RTG (committed or otherwise) functions should behave the same
for (String id : Arrays.asList("42","99")) {
for (SolrParams p : Arrays.asList(params("fl","log(val_i),abs(val_i)"),
params("fl","log(val_i)","fl", "abs(val_i)"))) {
SolrDocument doc = getRandClient(random()).getById(id, p);
String msg = id + "," + p + " => " + doc;
assertEquals(msg, 2, doc.size());
assertTrue(msg, doc.getFieldValue("log(val_i)") instanceof Double);
assertTrue(msg, doc.getFieldValue("abs(val_i)") instanceof Float);
// true for both these specific docs
assertEquals(msg, 0.0D, doc.getFieldValue("log(val_i)"));
assertEquals(msg, 1.0F, doc.getFieldValue("abs(val_i)"));
}
}
}
public void testFunctionsAndExplicit() throws Exception {
for (SolrParams p : Arrays.asList(params("q","*:*", "rows", "1", "fl","log(val_i),val_i"),
params("q","*:*", "rows", "1", "fl","log(val_i)", "fl","val_i"))) {
SolrDocumentList docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
SolrDocument doc = docs.get(0); // doesn't really matter which one
assertEquals(p + " => " + doc, 2, doc.size());
assertTrue(p + " => " + doc, doc.getFieldValue("log(val_i)") instanceof Double);
assertTrue(p + " => " + doc, doc.getFieldValue("val_i") instanceof Integer);
}
}
public void testFunctionsAndExplicitRTG() throws Exception {
// shouldn't matter if we use RTG (committed or otherwise)
for (String id : Arrays.asList("42","99")) {
for (SolrParams p : Arrays.asList(params("fl","log(val_i),val_i"),
params("fl","log(val_i)","fl","val_i"))) {
SolrDocument doc = getRandClient(random()).getById(id, p);
String msg = id + "," + p + " => " + doc;
assertEquals(msg, 2, doc.size());
assertTrue(msg, doc.getFieldValue("log(val_i)") instanceof Double);
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
// true for both these specific docs
assertEquals(msg, 0.0D, doc.getFieldValue("log(val_i)"));
assertEquals(msg, 1, doc.getFieldValue("val_i"));
}
}
}
public void testFunctionsAndScore() throws Exception {
for (SolrParams p : Arrays.asList(params("fl","log(val_i),score"),
params("fl","log(val_i)","fl","score"))) {
SolrDocumentList docs = assertSearch(SolrParams.wrapDefaults(p, params("q", "*:*", "rows", "10")));
assertEquals(p + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(p + " => " + doc, 2, doc.size());
assertTrue(p + " => " + doc, doc.getFieldValue("score") instanceof Float);
assertTrue(p + " => " + doc, doc.getFieldValue("log(val_i)") instanceof Double);
}
}
for (SolrParams p : Arrays.asList(params("fl","log(val_i),abs(val_i),score"),
params("fl","log(val_i),abs(val_i)","fl","score"),
params("fl","log(val_i)","fl","abs(val_i),score"),
params("fl","log(val_i)","fl","abs(val_i)","fl","score"))) {
SolrDocumentList docs = assertSearch(SolrParams.wrapDefaults(p, params("q", "*:*", "rows", "10")));
assertEquals(p + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(p + " => " + doc, 3, doc.size());
assertTrue(p + " => " + doc, doc.getFieldValue("score") instanceof Float);
assertTrue(p + " => " + doc, doc.getFieldValue("abs(val_i)") instanceof Float);
assertTrue(p + " => " + doc, doc.getFieldValue("log(val_i)") instanceof Double);
}
}
}
public void testFunctionsAndScoreRTG() throws Exception {
// if we use RTG (committed or otherwise) score should be ignored
for (String id : Arrays.asList("42","99")) {
for (SolrParams p : Arrays.asList(params("fl","score","fl","log(val_i)","fl","abs(val_i)"),
params("fl","score","fl","log(val_i),abs(val_i)"),
params("fl","score,log(val_i)","fl","abs(val_i)"),
params("fl","score,log(val_i),abs(val_i)"))) {
SolrDocument doc = getRandClient(random()).getById(id, p);
String msg = id + "," + p + " => " + doc;
assertEquals(msg, 2, doc.size());
assertTrue(msg, doc.getFieldValue("log(val_i)") instanceof Double);
assertTrue(msg, doc.getFieldValue("abs(val_i)") instanceof Float);
// true for both these specific docs
assertEquals(msg, 0.0D, doc.getFieldValue("log(val_i)"));
assertEquals(msg, 1.0F, doc.getFieldValue("abs(val_i)"));
}
}
}
public void testGlobs() throws Exception {
SolrDocumentList docs = assertSearch(params("q", "*:*", "rows", "10", "fl","val_*"));
assertEquals(5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(doc.toString(), 1, doc.size());
assertTrue(doc.toString(), doc.getFieldValue("val_i") instanceof Integer);
}
for (SolrParams p : Arrays.asList(params("q", "*:*", "rows", "10", "fl","val_*,subj*,ss*"),
params("q", "*:*", "rows", "10", "fl","val_*","fl","subj*,ss*"),
params("q", "*:*", "rows", "10", "fl","val_*","fl","subj*","fl","ss*"))) {
docs = assertSearch(p);
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = p + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
assertTrue(msg, doc.getFieldValue("ssto") instanceof String); // TODO: val_ss: List<String>
assertEquals(msg, "X", doc.getFieldValue("ssto"));
}
}
}
public void testGlobsRTG() throws Exception {
// behavior shouldn't matter if we are committed or uncommitted
for (String id : Arrays.asList("42","99")) {
SolrDocument doc = getRandClient(random()).getById(id, params("fl","val_*"));
String msg = id + ": fl=val_* => " + doc;
assertEquals(msg, 1, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertEquals(msg, 1, doc.getFieldValue("val_i"));
for (SolrParams p : Arrays.asList(params("fl","val_*,subj*,ss*"),
params("fl","val_*","fl","subj*,ss*"))) {
doc = getRandClient(random()).getById(id, p);
msg = id + ": " + p + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertEquals(msg, 1, doc.getFieldValue("val_i"));
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
// NOTE: 'subject' is diff between two docs
assertTrue(msg, doc.getFieldValue("ssto") instanceof String); // TODO: val_ss: List<String>
assertEquals(msg, "X", doc.getFieldValue("ssto"));
}
}
}
public void testGlobsAndExplicit() throws Exception {
SolrDocumentList docs = assertSearch(params("q", "*:*", "rows", "10", "fl","val_*,id"));
assertEquals(5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(doc.toString(), 2, doc.size());
assertTrue(doc.toString(), doc.getFieldValue("val_i") instanceof Integer);
assertTrue(doc.toString(), doc.getFieldValue("id") instanceof String);
}
for (SolrParams p : Arrays.asList(params("q", "*:*", "rows", "10", "fl","val_*,subj*,id"),
params("q", "*:*", "rows", "10", "fl","val_*","fl","subj*","fl","id"),
params("q", "*:*", "rows", "10", "fl","val_*","fl","subj*,id"))) {
docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = p + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
assertTrue(msg, doc.getFieldValue("id") instanceof String);
}
}
}
public void testGlobsAndExplicitRTG() throws Exception {
// behavior shouldn't matter if we are committed or uncommitted
for (String id : Arrays.asList("42","99")) {
SolrDocument doc = getRandClient(random()).getById(id, params("fl","val_*,id"));
String msg = id + ": fl=val_*,id => " + doc;
assertEquals(msg, 2, doc.size());
assertTrue(msg, doc.getFieldValue("id") instanceof String);
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertEquals(msg, 1, doc.getFieldValue("val_i"));
for (SolrParams p : Arrays.asList(params("fl","val_*,subj*,id"),
params("fl","val_*","fl","subj*","fl","id"),
params("fl","val_*","fl","subj*,id"))) {
doc = getRandClient(random()).getById(id, p);
msg = id + ": " + p + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertEquals(msg, 1, doc.getFieldValue("val_i"));
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
assertTrue(msg, doc.getFieldValue("id") instanceof String);
}
}
}
public void testGlobsAndScore() throws Exception {
SolrDocumentList docs = assertSearch(params("q", "*:*", "rows", "10", "fl","val_*,score"));
assertEquals(5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(doc.toString(), 2, doc.size());
assertTrue(doc.toString(), doc.getFieldValue("val_i") instanceof Integer);
assertTrue(doc.toString(), doc.getFieldValue("score") instanceof Float);
}
for (SolrParams p : Arrays.asList(params("q", "*:*", "rows", "10", "fl","val_*,subj*,score"),
params("q", "*:*", "rows", "10", "fl","val_*","fl","subj*","fl","score"),
params("q", "*:*", "rows", "10", "fl","val_*","fl","subj*,score"))) {
docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = p + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
assertTrue(msg, doc.getFieldValue("score") instanceof Float);
}
}
}
public void testGlobsAndScoreRTG() throws Exception {
// behavior shouldn't matter if we are committed or uncommitted, score should be ignored
for (String id : Arrays.asList("42","99")) {
SolrDocument doc = getRandClient(random()).getById(id, params("fl","val_*,score"));
String msg = id + ": fl=val_*,score => " + doc;
assertEquals(msg, 1, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertEquals(msg, 1, doc.getFieldValue("val_i"));
for (SolrParams p : Arrays.asList(params("fl","val_*,subj*,score"),
params("fl","val_*","fl","subj*","fl","score"),
params("fl","val_*","fl","subj*,score"))) {
doc = getRandClient(random()).getById(id, p);
msg = id + ": " + p + " => " + doc;
assertEquals(msg, 2, doc.size());
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertEquals(msg, 1, doc.getFieldValue("val_i"));
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
}
}
}
public void testAugmenters() throws Exception {
SolrDocumentList docs = assertSearch(params("q", "*:*", "rows", "10", "fl","[docid]"));
assertEquals(5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
assertEquals(doc.toString(), 1, doc.size());
assertTrue(doc.toString(), doc.getFieldValue("[docid]") instanceof Integer);
}
for (SolrParams p : Arrays.asList(params("q","*:*", "fl","[docid],[shard],[explain],x_alias:[value v=10 t=int]"),
params("q","*:*", "fl","[docid],[shard]","fl","[explain],x_alias:[value v=10 t=int]"),
params("q","*:*", "fl","[docid]","fl","[shard]","fl","[explain]","fl","x_alias:[value v=10 t=int]"))) {
docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = p + " => " + doc;
assertEquals(msg, 4, doc.size());
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, doc.getFieldValue("[shard]") instanceof String);
assertTrue(msg, doc.getFieldValue("[explain]") instanceof String);
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
}
}
}
public void testDocIdAugmenterRTG() throws Exception {
// for an uncommitted doc, we should get -1
for (String id : Arrays.asList("42","99")) {
SolrDocument doc = getRandClient(random()).getById(id, params("fl","[docid]"));
String msg = id + ": fl=[docid] => " + doc;
assertEquals(msg, 1, doc.size());
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, -1 <= ((Integer)doc.getFieldValue("[docid]")).intValue());
}
}
public void testAugmentersRTG() throws Exception {
// behavior shouldn't matter if we are committed or uncommitted
for (String id : Arrays.asList("42","99")) {
for (SolrParams p : Arrays.asList
(params("fl","[docid],[shard],[explain],x_alias:[value v=10 t=int]"),
params("fl","[docid],[shard]","fl","[explain],x_alias:[value v=10 t=int]"),
params("fl","[docid]","fl","[shard]","fl","[explain]","fl","x_alias:[value v=10 t=int]"))) {
SolrDocument doc = getRandClient(random()).getById(id, p);
String msg = id + ": " + p + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("[shard]") instanceof String);
// RTG: [explain] should be ignored
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, -1 <= ((Integer)doc.getFieldValue("[docid]")).intValue());
}
}
}
public void testAugmentersAndExplicit() throws Exception {
for (SolrParams p : Arrays.asList(params("q", "*:*", "fl","id,[docid],[explain],x_alias:[value v=10 t=int]"),
params("q", "*:*", "fl","id","fl","[docid],[explain],x_alias:[value v=10 t=int]"),
params("q", "*:*", "fl","id","fl","[docid]","fl","[explain]","fl","x_alias:[value v=10 t=int]"))) {
SolrDocumentList docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = p + " => " + doc;
assertEquals(msg, 4, doc.size());
assertTrue(msg, doc.getFieldValue("id") instanceof String);
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, doc.getFieldValue("[explain]") instanceof String);
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
}
}
}
public void testAugmentersAndExplicitRTG() throws Exception {
// behavior shouldn't matter if we are committed or uncommitted
for (String id : Arrays.asList("42","99")) {
for (SolrParams p : Arrays.asList(params("fl","id,[docid],[explain],x_alias:[value v=10 t=int]"),
params("fl","id,[docid]","fl","[explain],x_alias:[value v=10 t=int]"),
params("fl","id","fl","[docid]","fl","[explain]","fl","x_alias:[value v=10 t=int]"))) {
SolrDocument doc = getRandClient(random()).getById(id, p);
String msg = id + ": " + p + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("id") instanceof String);
// RTG: [explain] should be missing (ignored)
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, -1 <= ((Integer)doc.getFieldValue("[docid]")).intValue());
}
}
}
public void testAugmentersAndScore() throws Exception {
SolrParams params = params("q","*:*", "fl","[docid],x_alias:[value v=10 t=int],score");
SolrDocumentList docs = assertSearch(params);
assertEquals(params + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = params + " => " + doc;
assertEquals(msg, 3, doc.size());
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
assertTrue(msg, doc.getFieldValue("score") instanceof Float);
}
for (SolrParams p : Arrays.asList(params("q","*:*","fl","[docid],x_alias:[value v=10 t=int],[explain],score"),
params("q","*:*","fl","[docid]","fl","x_alias:[value v=10 t=int],[explain]","fl","score"),
params("q","*:*","fl","[docid]","fl","x_alias:[value v=10 t=int]","fl","[explain]","fl","score"))) {
docs = assertSearch(p);
assertEquals(p + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = p + " => " + doc;
assertEquals(msg, 4, doc.size());
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
assertTrue(msg, doc.getFieldValue("[explain]") instanceof String);
assertTrue(msg, doc.getFieldValue("score") instanceof Float);
}
}
}
public void testAugmentersAndScoreRTG() throws Exception {
// if we use RTG (committed or otherwise) score should be ignored
for (String id : Arrays.asList("42","99")) {
SolrDocument doc = getRandClient(random()).getById(id, params("fl","x_alias:[value v=10 t=int],score"));
String msg = id + " => " + doc;
assertEquals(msg, 1, doc.size());
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
for (SolrParams p : Arrays.asList(params("fl","d_alias:[docid],x_alias:[value v=10 t=int],[explain],score"),
params("fl","d_alias:[docid],x_alias:[value v=10 t=int],[explain]","fl","score"),
params("fl","d_alias:[docid]","fl","x_alias:[value v=10 t=int]","fl","[explain]","fl","score"))) {
doc = getRandClient(random()).getById(id, p);
msg = id + ": " + p + " => " + doc;
assertEquals(msg, 2, doc.size());
assertTrue(msg, doc.getFieldValue("x_alias") instanceof Integer);
assertEquals(msg, 10, doc.getFieldValue("x_alias"));
// RTG: [explain] and score should be missing (ignored)
assertTrue(msg, doc.getFieldValue("d_alias") instanceof Integer);
assertTrue(msg, -1 <= ((Integer)doc.getFieldValue("d_alias")).intValue());
}
}
}
public void testAugmentersGlobsExplicitAndScoreOhMy() throws Exception {
Random random = random();
// NOTE: 'ssto' is the missing one
final List<String> fl = Arrays.asList
("id","[docid]","[explain]","score","val_*","subj*");
final int iters = atLeast(random, 10);
for (int i = 0; i< iters; i++) {
Collections.shuffle(fl, random);
final SolrParams singleFl = params("q","*:*", "rows", "1","fl",String.join(",", fl));
final ModifiableSolrParams multiFl = params("q","*:*", "rows", "1");
for (String item : fl) {
multiFl.add("fl",item);
}
for (SolrParams params : Arrays.asList(singleFl, multiFl)) {
SolrDocumentList docs = assertSearch(params);
assertEquals(params + " => " + docs, 5, docs.getNumFound());
// shouldn't matter what doc we pick...
for (SolrDocument doc : docs) {
String msg = params + " => " + doc;
assertEquals(msg, 6, doc.size());
assertTrue(msg, doc.getFieldValue("id") instanceof String);
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, doc.getFieldValue("[explain]") instanceof String);
assertTrue(msg, doc.getFieldValue("score") instanceof Float);
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
}
}
}
}
public void testAugmentersGlobsExplicitAndScoreOhMyRTG() throws Exception {
Random random = random();
// NOTE: 'ssto' is the missing one
final List<String> fl = Arrays.asList
("id","[docid]","[explain]","score","val_*","subj*");
final int iters = atLeast(random, 10);
for (int i = 0; i< iters; i++) {
Collections.shuffle(fl, random);
final SolrParams singleFl = params("fl",String.join(",", fl));
final ModifiableSolrParams multiFl = params();
for (String item : fl) {
multiFl.add("fl",item);
}
// RTG behavior should be consistent, (committed or otherwise)
for (String id : Arrays.asList("42","99")) {
for (SolrParams params : Arrays.asList(singleFl, multiFl)) {
SolrDocument doc = getRandClient(random()).getById(id, params);
String msg = id + ": " + params + " => " + doc;
assertEquals(msg, 4, doc.size());
assertTrue(msg, doc.getFieldValue("id") instanceof String);
assertTrue(msg, doc.getFieldValue("val_i") instanceof Integer);
assertEquals(msg, 1, doc.getFieldValue("val_i"));
assertTrue(msg, doc.getFieldValue("subject") instanceof String);
assertTrue(msg, doc.getFieldValue("[docid]") instanceof Integer);
assertTrue(msg, -1 <= ((Integer)doc.getFieldValue("[docid]")).intValue());
// RTG: [explain] and score should be missing (ignored)
}
}
}
}
/**
* Given a set of query params, executes as a Query against a random SolrClient and
* asserts that exactly one document is returned
*/
public static SolrDocument assertSearchOneDoc(SolrParams p) throws Exception {
SolrDocumentList docs = assertSearch(p);
assertEquals("does not match exactly one doc: " + p.toString() + " => " + docs.toString(),
1, docs.getNumFound());
assertEquals("does not contain exactly one doc: " + p.toString() + " => " + docs.toString(),
1, docs.size());
return docs.get(0);
}
/**
* Given a set of query params, executes as a Query against a random SolrClient and
* asserts that at least 1 doc is matched and at least 1 doc is returned
*/
public static SolrDocumentList assertSearch(SolrParams p) throws Exception {
QueryResponse rsp = getRandClient(random()).query(p);
assertEquals("failed request: " + p.toString() + " => " + rsp.toString(), 0, rsp.getStatus());
assertTrue("does not match at least one doc: " + p.toString() + " => " + rsp.toString(),
1 <= rsp.getResults().getNumFound());
assertTrue("rsp does not contain at least one doc: " + p.toString() + " => " + rsp.toString(),
1 <= rsp.getResults().size());
return rsp.getResults();
}
/**
* returns a random SolrClient -- either a CloudSolrClient, or an HttpSolrClient pointed
* at a node in our cluster
*/
public static SolrClient getRandClient(Random rand) {
int numClients = CLIENTS.size();
int idx = TestUtil.nextInt(rand, 0, numClients);
return (idx == numClients) ? CLOUD_CLIENT : CLIENTS.get(idx);
}
public static void waitForRecoveriesToFinish(CloudSolrClient client) throws Exception {
assert null != client.getDefaultCollection();
AbstractDistribZkTestBase.waitForRecoveriesToFinish(client.getDefaultCollection(),
client.getZkStateReader(),
true, true, 330);
}
}