diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml b/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml index a735e434bc7..8b733074b08 100755 --- a/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml +++ b/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml @@ -132,6 +132,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java index f7b74d08af4..adcf03f104e 100644 --- a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java +++ b/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java @@ -17,7 +17,6 @@ package org.apache.solr.rest.schema; */ import org.apache.commons.io.FileUtils; -import org.apache.solr.AnalysisAfterCoreReloadTest; import org.apache.solr.util.RestTestBase; import org.eclipse.jetty.servlet.ServletHolder; import org.junit.After; @@ -28,14 +27,24 @@ import org.restlet.ext.servlet.ServerServlet; import java.io.File; import java.util.SortedMap; import java.util.TreeMap; +import java.util.regex.Pattern; public class TestManagedSchemaFieldResource extends RestTestBase { - + + private static File tmpSolrHome; + private static File tmpConfDir; + + private static final String collection = "collection1"; + private static final String confDir = collection + "/conf"; + + @Before public void before() throws Exception { createTempDir(); - String tmpSolrHome = TEMP_DIR + File.separator + AnalysisAfterCoreReloadTest.class.getSimpleName() + System.currentTimeMillis(); - FileUtils.copyDirectory(new File(TEST_HOME()), new File(tmpSolrHome).getAbsoluteFile()); + tmpSolrHome = new File( TEMP_DIR + File.separator + TestManagedSchemaFieldResource.class.getSimpleName() + + System.currentTimeMillis()); + tmpConfDir = new File(tmpSolrHome, confDir); + FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile()); final SortedMap extraServlets = new TreeMap(); final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class); @@ -45,7 +54,8 @@ public class TestManagedSchemaFieldResource extends RestTestBase { System.setProperty("managed.schema.mutable", "true"); System.setProperty("enable.update.log", "false"); - createJettyAndHarness(tmpSolrHome, "solrconfig-managed-schema.xml", "schema-rest.xml", "/solr", true, extraServlets); + createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-rest.xml", + "/solr", true, extraServlets); } @After @@ -61,22 +71,22 @@ public class TestManagedSchemaFieldResource extends RestTestBase { @Test public void testAddFieldBadFieldType() throws Exception { assertJPut("/schema/fields/newfield", - json( "{'type':'not_in_there_at_all','stored':'false'}" ), + json( "{'type':'not_in_there_at_all','stored':false}" ), "/error/msg==\"Field \\'newfield\\': Field type \\'not_in_there_at_all\\' not found.\""); } @Test public void testAddFieldMismatchedName() throws Exception { assertJPut("/schema/fields/newfield", - json( "{'name':'something_else','type':'text','stored':'false'}" ), + json( "{'name':'something_else','type':'text','stored':false}" ), "/error/msg=='///regex:newfield///'"); } @Test public void testAddFieldBadProperty() throws Exception { assertJPut("/schema/fields/newfield", - json( "{'type':'text','no_property_with_this_name':'false'}" ), - "/error/msg==\"java.lang.IllegalArgumentException: Invalid field property: no_property_with_this_name\""); + json( "{'type':'text','no_property_with_this_name':false}" ), + "/error/msg==\"java.lang.IllegalArgumentException: Invalid field property: no_property_with_this_name\""); } @Test @@ -87,8 +97,8 @@ public class TestManagedSchemaFieldResource extends RestTestBase { "/response/lst[@name='error']/int[@name='code'] = '404'"); assertJPut("/schema/fields/newfield", - json( "{'type':'text','stored':'false'}" ), - "/responseHeader/status==0"); + json("{'type':'text','stored':false}"), + "/responseHeader/status==0"); assertQ("/schema/fields/newfield?indent=on&wt=xml", "count(/response/lst[@name='field']) = 1", @@ -104,6 +114,122 @@ public class TestManagedSchemaFieldResource extends RestTestBase { "/response/result[@name='response']/doc/str[@name='id'][.='123']"); } + @Test + public void testAddFieldWithMulipleOptions() throws Exception { + assertQ("/schema/fields/newfield?indent=on&wt=xml", + "count(/response/lst[@name='field']) = 0", + "/response/lst[@name='responseHeader']/int[@name='status'] = '404'", + "/response/lst[@name='error']/int[@name='code'] = '404'"); + + assertJPut("/schema/fields/newfield", + json("{'type':'text_en','stored':true,'indexed':false}"), + "/responseHeader/status==0"); + + File managedSchemaFile = new File(tmpConfDir, "managed-schema"); + assertTrue(managedSchemaFile.exists()); + String managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8"); + Pattern newfieldStoredTrueIndexedFalsePattern + = Pattern.compile( ""); + assertTrue(newfieldStoredTrueIndexedFalsePattern.matcher(managedSchemaContents).find()); + + assertQ("/schema/fields/newfield?indent=on&wt=xml", + "count(/response/lst[@name='field']) = 1", + "/response/lst[@name='responseHeader']/int[@name='status'] = '0'", + "/response/lst[@name='field']/str[@name='name'] = 'newfield'", + "/response/lst[@name='field']/str[@name='type'] = 'text_en'", + "/response/lst[@name='field']/bool[@name='indexed'] = 'false'", + "/response/lst[@name='field']/bool[@name='stored'] = 'true'"); + + assertU(adoc("newfield", "value1 value2", "id", "1234")); + assertU(commit()); + + assertQ("/schema/fields/newfield2?indent=on&wt=xml", + "count(/response/lst[@name='field']) = 0", + "/response/lst[@name='responseHeader']/int[@name='status'] = '404'", + "/response/lst[@name='error']/int[@name='code'] = '404'"); + + assertJPut("/schema/fields/newfield2", + json("{'type':'text_en','stored':true,'indexed':true,'multiValued':true}"), + "/responseHeader/status==0"); + + managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8"); + Pattern newfield2StoredTrueIndexedTrueMultiValuedTruePattern + = Pattern.compile( ""); + assertTrue(newfield2StoredTrueIndexedTrueMultiValuedTruePattern.matcher(managedSchemaContents).find()); + + assertQ("/schema/fields/newfield2?indent=on&wt=xml", + "count(/response/lst[@name='field']) = 1", + "/response/lst[@name='responseHeader']/int[@name='status'] = '0'", + "/response/lst[@name='field']/str[@name='name'] = 'newfield2'", + "/response/lst[@name='field']/str[@name='type'] = 'text_en'", + "/response/lst[@name='field']/bool[@name='indexed'] = 'true'", + "/response/lst[@name='field']/bool[@name='stored'] = 'true'", + "/response/lst[@name='field']/bool[@name='multiValued'] = 'true'"); + + assertU(adoc("newfield2", "value1 value2", "newfield2", "value3 value4", "id", "5678")); + assertU(commit()); + + assertQ("/select?q=newfield2:value3", + "/response/lst[@name='responseHeader']/int[@name='status'] = '0'", + "/response/result[@name='response'][@numFound='1']", + "count(/response/result[@name='response']/doc) = 1", + "/response/result[@name='response']/doc/str[@name='id'][.='5678']"); + } + + @Test + public void testAddFieldCollectionWithMultipleOptions() throws Exception { + assertQ("/schema/fields?indent=on&wt=xml", + "count(/response/arr[@name='fields']/lst/str[@name]) > 0", // there are fields + "count(/response/arr[@name='fields']/lst/str[starts-with(@name,'newfield')]) = 0"); // but none named newfield* + + assertJPost("/schema/fields", + json("[{'name':'newfield','type':'text_en','stored':true,'indexed':false}]"), + "/responseHeader/status==0"); + + File managedSchemaFile = new File(tmpConfDir, "managed-schema"); + assertTrue(managedSchemaFile.exists()); + String managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8"); + Pattern newfieldStoredTrueIndexedFalsePattern + = Pattern.compile( ""); + assertTrue(newfieldStoredTrueIndexedFalsePattern.matcher(managedSchemaContents).find()); + + assertQ("/schema/fields?indent=on&wt=xml", + "/response/arr[@name='fields']/lst" + + "[str[@name='name']='newfield' and str[@name='type']='text_en'" + + " and bool[@name='stored']='true' and bool[@name='indexed']='false']"); + + assertU(adoc("newfield", "value1 value2", "id", "789")); + assertU(commit()); + + assertJPost("/schema/fields", + json("[{'name':'newfield2','type':'text_en','stored':true,'indexed':true,'multiValued':true}]"), + "/responseHeader/status==0"); + + managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8"); + Pattern newfield2StoredTrueIndexedTrueMultiValuedTruePattern + = Pattern.compile( ""); + assertTrue(newfield2StoredTrueIndexedTrueMultiValuedTruePattern.matcher(managedSchemaContents).find()); + + assertQ("/schema/fields?indent=on&wt=xml", + "/response/arr[@name='fields']/lst" + + "[str[@name='name']='newfield2' and str[@name='type']='text_en'" + + " and bool[@name='stored']='true' and bool[@name='indexed']='true' and bool[@name='multiValued']='true']"); + + assertU(adoc("newfield2", "value1 value2", "newfield2", "value3 value4", "id", "790")); + assertU(commit()); + + assertQ("/select?q=newfield2:value3", + "/response/lst[@name='responseHeader']/int[@name='status'] = '0'", + "/response/result[@name='response'][@numFound='1']", + "count(/response/result[@name='response']/doc) = 1", + "/response/result[@name='response']/doc/str[@name='id'][.='790']"); + } + + @Test public void testAddCopyField() throws Exception { assertQ("/schema/fields/newfield2?indent=on&wt=xml", @@ -111,15 +237,15 @@ public class TestManagedSchemaFieldResource extends RestTestBase { "/response/lst[@name='responseHeader']/int[@name='status'] = '404'", "/response/lst[@name='error']/int[@name='code'] = '404'"); - assertJPut("/schema/fields/fieldA", - "{\"type\":\"text\",\"stored\":\"false\"}", - "/responseHeader/status==0"); + assertJPut("/schema/fields/fieldA", + json("{'type':'text','stored':false}"), + "/responseHeader/status==0"); assertJPut("/schema/fields/fieldB", - "{\"type\":\"text\",\"stored\":\"false\", \"copyFields\":[\"fieldA\"]}", - "/responseHeader/status==0"); + json("{'type':'text','stored':false, 'copyFields':['fieldA']}"), + "/responseHeader/status==0"); assertJPut("/schema/fields/fieldC", - "{\"type\":\"text\",\"stored\":\"false\", \"copyFields\":\"fieldA\"}", - "/responseHeader/status==0"); + json("{'type':'text','stored':false, 'copyFields':'fieldA'}"), + "/responseHeader/status==0"); assertQ("/schema/fields/fieldB?indent=on&wt=xml", "count(/response/lst[@name='field']) = 1", @@ -132,12 +258,12 @@ public class TestManagedSchemaFieldResource extends RestTestBase { ); //fine to pass in empty list, just won't do anything assertJPut("/schema/fields/fieldD", - "{\"type\":\"text\",\"stored\":\"false\", \"copyFields\":[]}", - "/responseHeader/status==0"); + json("{'type':'text','stored':false, 'copyFields':[]}"), + "/responseHeader/status==0"); //some bad usages assertJPut("/schema/fields/fieldF", - "{\"type\":\"text\",\"stored\":\"false\", \"copyFields\":[\"some_nonexistent_field_ignore_exception\"]}", - "/error/msg==\"copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.\""); + json("{'type':'text','stored':false, 'copyFields':['some_nonexistent_field_ignore_exception']}"), + "/error/msg==\"copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.\""); } @Test @@ -153,8 +279,8 @@ public class TestManagedSchemaFieldResource extends RestTestBase { "/response/lst[@name='error']/int[@name='code'] = '404'"); assertJPost("/schema/fields", - "[{\"name\":\"newfield1\",\"type\":\"text\",\"stored\":\"false\"}," - +" {\"name\":\"newfield2\",\"type\":\"text\",\"stored\":\"false\"}]", + json( "[{'name':'newfield1','type':'text','stored':false}," + + " {'name':'newfield2','type':'text','stored':false}]"), "/responseHeader/status==0"); assertQ("/schema/fields/newfield1?indent=on&wt=xml", @@ -184,55 +310,60 @@ public class TestManagedSchemaFieldResource extends RestTestBase { @Test public void testPostCopy() throws Exception { assertJPost("/schema/fields", - json( "[{'name':'fieldA','type':'text','stored':'false'}," - + " {'name':'fieldB','type':'text','stored':'false'}," - + " {'name':'fieldC','type':'text','stored':'false', 'copyFields':['fieldB']}]" ), + json( "[{'name':'fieldA','type':'text','stored':false}," + + " {'name':'fieldB','type':'text','stored':false}," + + " {'name':'fieldC','type':'text','stored':false, 'copyFields':['fieldB']}]"), "/responseHeader/status==0"); assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldC", "count(/response/arr[@name='copyFields']/lst) = 1" ); assertJPost("/schema/fields", - "[{\"name\":\"fieldD\",\"type\":\"text\",\"stored\":\"false\"}," - + "{\"name\":\"fieldE\",\"type\":\"text\",\"stored\":\"false\"}," - + " {\"name\":\"fieldF\",\"type\":\"text\",\"stored\":\"false\", \"copyFields\":[\"fieldD\",\"fieldE\"]}," - + " {\"name\":\"fieldG\",\"type\":\"text\",\"stored\":\"false\", \"copyFields\":\"fieldD\"}"//single - + "]", + json( "[{'name':'fieldD','type':'text','stored':false}," + + " {'name':'fieldE','type':'text','stored':false}," + + " {'name':'fieldF','type':'text','stored':false, 'copyFields':['fieldD','fieldE']}," + + " {'name':'fieldG','type':'text','stored':false, 'copyFields':'fieldD'}]"),//single "/responseHeader/status==0"); assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldF", "count(/response/arr[@name='copyFields']/lst) = 2" ); //passing in an empty list is perfectly acceptable, it just won't do anything assertJPost("/schema/fields", - "[{\"name\":\"fieldX\",\"type\":\"text\",\"stored\":\"false\"}," - + "{\"name\":\"fieldY\",\"type\":\"text\",\"stored\":\"false\"}," - + " {\"name\":\"fieldZ\",\"type\":\"text\",\"stored\":\"false\", \"copyFields\":[]}]", - "/responseHeader/status==0"); + json( "[{'name':'fieldX','type':'text','stored':false}," + + " {'name':'fieldY','type':'text','stored':false}," + + " {'name':'fieldZ','type':'text','stored':false, 'copyFields':[]}]"), + "/responseHeader/status==0"); //some bad usages assertJPost("/schema/fields", - "[{\"name\":\"fieldH\",\"type\":\"text\",\"stored\":\"false\"}," - + "{\"name\":\"fieldI\",\"type\":\"text\",\"stored\":\"false\"}," - + " {\"name\":\"fieldJ\",\"type\":\"text\",\"stored\":\"false\", \"copyFields\":[\"some_nonexistent_field_ignore_exception\"]}]", - "/error/msg==\"copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.\""); + json( "[{'name':'fieldH','type':'text','stored':false}," + + " {'name':'fieldI','type':'text','stored':false}," + + " {'name':'fieldJ','type':'text','stored':false, 'copyFields':['some_nonexistent_field_ignore_exception']}]"), + "/error/msg=='copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.'"); } @Test public void testPostCopyFields() throws Exception { assertJPost("/schema/fields", - "[{\"name\":\"fieldA\",\"type\":\"text\",\"stored\":\"false\"}," - + "{\"name\":\"fieldB\",\"type\":\"text\",\"stored\":\"false\"}," - + "{\"name\":\"fieldC\",\"type\":\"text\",\"stored\":\"false\"}," - + "{\"name\":\"fieldD\",\"type\":\"text\",\"stored\":\"false\"}," - + " {\"name\":\"fieldE\",\"type\":\"text\",\"stored\":\"false\"}]", + json( "[{'name':'fieldA','type':'text','stored':false}," + + " {'name':'fieldB','type':'text','stored':false}," + + " {'name':'fieldC','type':'text','stored':false}," + + " {'name':'fieldD','type':'text','stored':false}," + + " {'name':'fieldE','type':'text','stored':false}]"), + "/responseHeader/status==0"); + assertJPost("/schema/copyfields", + json( "[{'source':'fieldA', 'dest':'fieldB'}," + + " {'source':'fieldD', 'dest':['fieldC', 'fieldE']}]"), "/responseHeader/status==0"); - assertJPost("/schema/copyfields", "[{\"source\":\"fieldA\", \"dest\":\"fieldB\"},{\"source\":\"fieldD\", \"dest\":[\"fieldC\", \"fieldE\"]}]", "/responseHeader/status==0"); assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldA", "count(/response/arr[@name='copyFields']/lst) = 1"); assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldD", "count(/response/arr[@name='copyFields']/lst) = 2"); - assertJPost("/schema/copyfields", "[{\"source\":\"some_nonexistent_field_ignore_exception\", \"dest\":[\"fieldA\"]}]", "/error/msg==\"copyField source :\\'some_nonexistent_field_ignore_exception\\' is not a glob and doesn\\'t match any explicit field or dynamicField.\""); - assertJPost("/schema/copyfields", "[{\"source\":\"fieldD\", \"dest\":[\"some_nonexistent_field_ignore_exception\"]}]", "/error/msg==\"copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.\""); + assertJPost("/schema/copyfields", + json("[{'source':'some_nonexistent_field_ignore_exception', 'dest':['fieldA']}]"), + "/error/msg=='copyField source :\\'some_nonexistent_field_ignore_exception\\' is not a glob and doesn\\'t match any explicit field or dynamicField.'"); + assertJPost("/schema/copyfields", + json("[{'source':'fieldD', 'dest':['some_nonexistent_field_ignore_exception']}]"), + "/error/msg=='copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.'"); } - }