This is an automated email from the ASF dual-hosted git repository.

gerlowskija pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new f6f58c0  SOLR-15490: /cluster v2 API parameter mapping tests (#204)
f6f58c0 is described below

commit f6f58c08cb2c52e30c06b916b8d984ff2ec92173
Author: Jason Gerlowski <[email protected]>
AuthorDate: Fri Jul 9 11:09:57 2021 +0000

    SOLR-15490: /cluster v2 API parameter mapping tests (#204)
    
    This commit adds unit tests that validate the parameter mapping for a
    number of v2 APIs under the /cluster path.
---
 .../java/org/apache/solr/handler/ClusterAPI.java   |  33 +--
 .../org/apache/solr/handler/CollectionsAPI.java    |   5 +-
 .../solr/handler/V2ClusterAPIMappingTest.java      | 241 +++++++++++++++++++++
 .../handler/admin/V2CollectionsAPIMappingTest.java |   7 +
 4 files changed, 272 insertions(+), 14 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java 
b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
index 334dbde..3f64032 100644
--- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
@@ -20,6 +20,7 @@ package org.apache.solr.handler;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.google.common.collect.Maps;
 import org.apache.solr.api.Command;
 import org.apache.solr.api.EndPoint;
 import org.apache.solr.api.PayloadObj;
@@ -30,6 +31,7 @@ import org.apache.solr.cloud.ConfigSetCmds;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.annotation.JsonProperty;
 import org.apache.solr.common.cloud.ClusterProperties;
+import org.apache.solr.common.params.CollectionParams;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ConfigSetParams;
 import org.apache.solr.common.params.DefaultSolrParams;
@@ -47,10 +49,8 @@ import static 
org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
 import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
 import static org.apache.solr.client.solrj.SolrRequest.METHOD.PUT;
 import static 
org.apache.solr.cloud.api.collections.CollectionHandlingUtils.REQUESTID;
-import static 
org.apache.solr.common.params.CollectionParams.CollectionAction.ADDROLE;
-import static 
org.apache.solr.common.params.CollectionParams.CollectionAction.CLUSTERPROP;
-import static 
org.apache.solr.common.params.CollectionParams.CollectionAction.OVERSEERSTATUS;
-import static 
org.apache.solr.common.params.CollectionParams.CollectionAction.REMOVEROLE;
+import static org.apache.solr.common.params.CollectionParams.ACTION;
+import static 
org.apache.solr.common.params.CollectionParams.CollectionAction.*;
 import static org.apache.solr.core.RateLimiterConfig.RL_CONFIG_KEY;
 import static 
org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
 import static 
org.apache.solr.security.PermissionNameProvider.Name.COLL_READ_PERM;
@@ -76,29 +76,33 @@ public class ClusterAPI {
       path = "/cluster/aliases",
       permission = COLL_READ_PERM)
   public void aliases(SolrQueryRequest req, SolrQueryResponse rsp) throws 
Exception {
-    CollectionsHandler.CollectionOperation.LISTALIASES_OP.execute(req, rsp, 
getCoreContainer().getCollectionsHandler());
+    final Map<String, Object> v1Params = Maps.newHashMap();
+    v1Params.put(ACTION, 
CollectionParams.CollectionAction.LISTALIASES.lowerName);
+    collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
   }
 
   @EndPoint(method = GET,
       path = "/cluster/overseer",
       permission = COLL_READ_PERM)
   public void getOverseerStatus(SolrQueryRequest req, SolrQueryResponse rsp) 
throws Exception {
-    
getCoreContainer().getCollectionsHandler().handleRequestBody(wrapParams(req, 
"action", OVERSEERSTATUS.toString()), rsp);
+    collectionsHandler.handleRequestBody(wrapParams(req, "action", 
OVERSEERSTATUS.lowerName), rsp);
   }
 
   @EndPoint(method = GET,
       path = "/cluster",
       permission = COLL_READ_PERM)
   public void getCluster(SolrQueryRequest req, SolrQueryResponse rsp) throws 
Exception {
-    CollectionsHandler.CollectionOperation.LIST_OP.execute(req, rsp, 
getCoreContainer().getCollectionsHandler());
+    collectionsHandler.handleRequestBody(wrapParams(req, "action", 
LIST.lowerName), rsp);
   }
 
   @EndPoint(method = DELETE,
       path = "/cluster/command-status/{id}",
       permission = COLL_EDIT_PERM)
   public void deleteCommandStatus(SolrQueryRequest req, SolrQueryResponse rsp) 
throws Exception {
-    wrapParams(req, REQUESTID, req.getPathTemplateValues().get("id"));
-    CollectionsHandler.CollectionOperation.DELETESTATUS_OP.execute(req, rsp, 
collectionsHandler);
+    final Map<String, Object> v1Params = Maps.newHashMap();
+    v1Params.put(ACTION, DELETESTATUS.lowerName);
+    v1Params.put(REQUESTID, req.getPathTemplateValues().get("id"));
+    collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
   }
 
   @EndPoint(method = DELETE,
@@ -116,7 +120,8 @@ public class ClusterAPI {
       path = "/cluster/configs",
       permission = CONFIG_READ_PERM)
   public void listConfigSet(SolrQueryRequest req, SolrQueryResponse rsp) 
throws Exception {
-    ConfigSetsHandler.ConfigSetOperation.LIST_OP.call(req, rsp, 
configSetsHandler);
+    req = wrapParams(req, "action", 
ConfigSetParams.ConfigSetAction.LIST.toString());
+    configSetsHandler.handleRequestBody(req, rsp);
   }
 
   @EndPoint(method = POST,
@@ -129,7 +134,7 @@ public class ClusterAPI {
     @SuppressWarnings("unchecked")
     public void create(PayloadObj<CreateConfigPayload> obj) throws Exception {
       Map<String, Object> mapVals = obj.get().toMap(new HashMap<>());
-      Map<String,Object> customProps = (Map<String, Object>) 
mapVals.remove("properties");
+      Map<String,Object> customProps = obj.get().properties;
       if(customProps!= null) {
         customProps.forEach((k, o) -> 
mapVals.put(ConfigSetCmds.CONFIG_SET_PROPERTY_PREFIX + k, o));
       }
@@ -189,8 +194,10 @@ public class ClusterAPI {
       path = "/cluster/command-status/{id}",
       permission = COLL_READ_PERM)
   public void getCommandStatus(SolrQueryRequest req, SolrQueryResponse rsp) 
throws Exception {
-    wrapParams(req, REQUESTID, req.getPathTemplateValues().get("id"));
-    CollectionsHandler.CollectionOperation.REQUESTSTATUS_OP.execute(req, rsp, 
collectionsHandler);
+    final Map<String, Object> v1Params = Maps.newHashMap();
+    v1Params.put(ACTION, REQUESTSTATUS.lowerName);
+    v1Params.put(REQUESTID, req.getPathTemplateValues().get("id"));
+    collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
   }
 
   @EndPoint(method = GET,
diff --git a/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java 
b/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java
index 1b1abf1..a071d0a 100644
--- a/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java
@@ -17,6 +17,7 @@
 
 package org.apache.solr.handler;
 
+import com.google.common.collect.Maps;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.solr.api.Command;
 import org.apache.solr.api.EndPoint;
@@ -76,7 +77,9 @@ public class CollectionsAPI {
       method = GET,
       permission = COLL_READ_PERM)
   public void getCollections(SolrQueryRequest req, SolrQueryResponse rsp) 
throws Exception {
-    CollectionsHandler.CollectionOperation.LIST_OP.execute(req, rsp, 
collectionsHandler);
+      final Map<String, Object> v1Params = Maps.newHashMap();
+      v1Params.put(ACTION, CollectionAction.LIST.toLower());
+      collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
   }
 
     @EndPoint(
diff --git 
a/solr/core/src/test/org/apache/solr/handler/V2ClusterAPIMappingTest.java 
b/solr/core/src/test/org/apache/solr/handler/V2ClusterAPIMappingTest.java
new file mode 100644
index 0000000..e9a8cd1
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/V2ClusterAPIMappingTest.java
@@ -0,0 +1,241 @@
+/*
+ * 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.handler;
+
+import com.google.common.collect.Maps;
+import org.apache.solr.api.Api;
+import org.apache.solr.api.ApiBag;
+import org.apache.solr.cloud.ConfigSetCmds;
+import org.apache.solr.common.params.CollectionParams;
+import org.apache.solr.common.params.ConfigSetParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.CommandOperation;
+import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.handler.admin.CollectionsHandler;
+import org.apache.solr.handler.admin.ConfigSetsHandler;
+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.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static 
org.apache.solr.cloud.api.collections.CollectionHandlingUtils.REQUESTID;
+import static org.apache.solr.common.params.CommonParams.ACTION;
+import static org.apache.solr.common.params.CommonParams.NAME;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+/**
+ * Unit tests for the v2 to v1 API mappings found in {@link ClusterAPI}
+ */
+public class V2ClusterAPIMappingTest {
+  private ApiBag apiBag;
+  private ArgumentCaptor<SolrQueryRequest> queryRequestCaptor;
+  private CollectionsHandler mockCollectionsHandler;
+  private ConfigSetsHandler mockConfigSetHandler;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Before
+  public void setupApiBag() throws Exception {
+    mockCollectionsHandler = mock(CollectionsHandler.class);
+    mockConfigSetHandler = mock(ConfigSetsHandler.class);
+    queryRequestCaptor = ArgumentCaptor.forClass(SolrQueryRequest.class);
+
+    apiBag = new ApiBag(false);
+    final ClusterAPI clusterAPI = new ClusterAPI(mockCollectionsHandler, 
mockConfigSetHandler);
+    apiBag.registerObject(clusterAPI);
+    apiBag.registerObject(clusterAPI.commands);
+    apiBag.registerObject(clusterAPI.configSetCommands);
+  }
+
+  @Test
+  public void testAsyncCommandStatusAllParams() throws Exception {
+    final SolrParams v1Params = 
captureConvertedV1Params("/cluster/command-status/someId", "GET", null);
+
+    assertEquals(CollectionParams.CollectionAction.REQUESTSTATUS.lowerName, 
v1Params.get(ACTION));
+    assertEquals("someId", v1Params.get(REQUESTID));
+  }
+
+  @Test
+  public void testClusterAliasesAllParams() throws Exception {
+    final SolrParams v1Params = captureConvertedV1Params("/cluster/aliases", 
"GET", null);
+
+    assertEquals(CollectionParams.CollectionAction.LISTALIASES.lowerName, 
v1Params.get(ACTION));
+  }
+
+  @Test
+  public void testClusterOverseerAllParams() throws Exception {
+    final SolrParams v1Params = captureConvertedV1Params("/cluster/overseer", 
"GET", null);
+
+    assertEquals(CollectionParams.CollectionAction.OVERSEERSTATUS.lowerName, 
v1Params.get(ACTION));
+  }
+
+  @Test
+  public void testListClusterAllParams() throws Exception {
+    final SolrParams v1Params = captureConvertedV1Params("/cluster", "GET", 
null);
+
+    assertEquals(CollectionParams.CollectionAction.LIST.lowerName, 
v1Params.get(ACTION));
+  }
+
+  @Test
+  public void testDeleteCommandStatusAllParams() throws Exception {
+    final SolrParams v1Params = 
captureConvertedV1Params("/cluster/command-status/someId", "DELETE", null);
+
+    assertEquals(CollectionParams.CollectionAction.DELETESTATUS.lowerName, 
v1Params.get(ACTION));
+    assertEquals("someId", v1Params.get(REQUESTID));
+  }
+
+  // TODO This should probably really get its own class.
+  @Test
+  public void testDeleteConfigetAllParams() throws Exception {
+    final SolrParams v1Params = 
captureConvertedConfigsetV1Params("/cluster/configs/someConfigset", "DELETE", 
null);
+
+    assertEquals(ConfigSetParams.ConfigSetAction.DELETE.toString(), 
v1Params.get(ACTION));
+    assertEquals("someConfigset", v1Params.get(NAME));
+  }
+
+  @Test
+  public void testListConfigsetsAllParams() throws Exception {
+    final SolrParams v1Params = 
captureConvertedConfigsetV1Params("/cluster/configs", "GET", null);
+
+    assertEquals(ConfigSetParams.ConfigSetAction.LIST.toString(), 
v1Params.get(ACTION));
+  }
+
+  @Test
+  public void testCreateConfigsetAllParams() throws Exception {
+    final SolrParams v1Params = 
captureConvertedConfigsetV1Params("/cluster/configs", "POST",
+            "{'create': {" +
+                    "'name': 'new_configset_name', " +
+                    "'baseConfigSet':'some_existing_configset', " +
+                    "'properties': {'prop1': 'val1', 'prop2': 'val2'}}}");
+
+    assertEquals(ConfigSetParams.ConfigSetAction.CREATE.toString(), 
v1Params.get(ACTION));
+    assertEquals("new_configset_name", v1Params.get(NAME));
+    assertEquals("some_existing_configset", 
v1Params.get(ConfigSetCmds.BASE_CONFIGSET));
+    assertEquals("val1", v1Params.get("configSetProp.prop1"));
+    assertEquals("val2", v1Params.get("configSetProp.prop2"));
+  }
+
+  @Test
+  public void testUploadConfigsetAllParams() throws Exception {
+    final SolrParams v1Params = 
captureConvertedConfigsetV1Params("/cluster/configs/someConfigSetName", "PUT", 
null);
+
+    assertEquals(ConfigSetParams.ConfigSetAction.UPLOAD.toString(), 
v1Params.get(ACTION));
+    assertEquals("someConfigSetName", v1Params.get(NAME));
+    // Why does ClusterAPI set the values below as defaults?  They disagree 
with the v1 defaults in
+    // ConfigSetsHandler.handleConfigUploadRequest
+    assertEquals(true, v1Params.getPrimitiveBool(ConfigSetParams.OVERWRITE));
+    assertEquals(false, v1Params.getPrimitiveBool(ConfigSetParams.CLEANUP));
+  }
+
+  @Test
+  public void testAddFileToConfigsetAllParams() throws Exception {
+    final SolrParams v1Params = 
captureConvertedConfigsetV1Params("/cluster/configs/someConfigSetName/some/file/path",
 "PUT", null);
+
+    assertEquals(ConfigSetParams.ConfigSetAction.UPLOAD.toString(), 
v1Params.get(ACTION));
+    assertEquals("someConfigSetName", v1Params.get(NAME));
+    assertEquals("/some/file/path", v1Params.get(ConfigSetParams.FILE_PATH)); 
// Note the leading '/' that makes the path appear absolute
+    assertEquals(true, v1Params.getPrimitiveBool(ConfigSetParams.OVERWRITE));
+    assertEquals(false, v1Params.getPrimitiveBool(ConfigSetParams.CLEANUP));
+  }
+
+  @Test
+  public void testAddRoleAllParams() throws Exception {
+    final SolrParams v1Params = captureConvertedV1Params("/cluster", "POST",
+            "{'add-role': {" +
+                    "'node': 'some_node_name', " +
+                    "'role':'some_role'}}");
+
+    assertEquals(CollectionParams.CollectionAction.ADDROLE.toString(), 
v1Params.get(ACTION));
+    assertEquals("some_node_name", v1Params.get("node"));
+    assertEquals("some_role", v1Params.get("role"));
+  }
+
+  @Test
+  public void testRemoveRoleAllParams() throws Exception {
+    final SolrParams v1Params = captureConvertedV1Params("/cluster", "POST",
+            "{'remove-role': {" +
+                    "'node': 'some_node_name', " +
+                    "'role':'some_role'}}");
+
+    assertEquals(CollectionParams.CollectionAction.REMOVEROLE.toString(), 
v1Params.get(ACTION));
+    assertEquals("some_node_name", v1Params.get("node"));
+    assertEquals("some_role", v1Params.get("role"));
+  }
+
+  @Test
+  public void testSetPropertyAllParams() throws Exception {
+    final SolrParams v1Params = captureConvertedV1Params("/cluster", "POST",
+            "{'set-property': {" +
+                    "'name': 'some_prop_name', " +
+                    "'val':'some_value'}}");
+
+    assertEquals(CollectionParams.CollectionAction.CLUSTERPROP.toString(), 
v1Params.get(ACTION));
+    assertEquals("some_prop_name", v1Params.get(NAME));
+    assertEquals("some_value", v1Params.get("val"));
+  }
+
+  private SolrParams captureConvertedV1Params(String path, String method, 
String v2RequestBody) throws Exception {
+    return doCaptureParams(path, method, v2RequestBody, 
mockCollectionsHandler);
+  }
+
+  private SolrParams captureConvertedConfigsetV1Params(String path, String 
method, String v2RequestBody) throws Exception {
+    return doCaptureParams(path, method, v2RequestBody, mockConfigSetHandler);
+  }
+
+  private SolrParams doCaptureParams(String path, String method, String 
v2RequestBody, RequestHandlerBase mockHandler) throws Exception {
+    final HashMap<String, String> parts = new HashMap<>();
+    final Api api = apiBag.lookup(path, method, parts);
+    final SolrQueryResponse rsp = new SolrQueryResponse();
+    final LocalSolrQueryRequest req = new LocalSolrQueryRequest(null, 
Maps.newHashMap()) {
+      @Override
+      public List<CommandOperation> getCommands(boolean validateInput) {
+        if (v2RequestBody == null) return Collections.emptyList();
+        return ApiBag.getCommandOperations(new 
ContentStreamBase.StringStream(v2RequestBody), api.getCommandSchema(), true);
+      }
+
+      @Override
+      public Map<String, String> getPathTemplateValues() {
+        return parts;
+      }
+
+      @Override
+      public String getHttpMethod() {
+        return method;
+      }
+    };
+
+
+    api.call(req, rsp);
+    verify(mockHandler).handleRequestBody(queryRequestCaptor.capture(), any());
+    return queryRequestCaptor.getValue().getParams();
+  }
+}
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
 
b/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
index 689073c..a2b0c85 100644
--- 
a/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
+++ 
b/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
@@ -132,6 +132,13 @@ public class V2CollectionsAPIMappingTest extends 
SolrTestCaseJ4 {
     }
 
     @Test
+    public void testListCollectionsAllProperties() throws Exception {
+        final SolrParams v1Params = captureConvertedV1Params("/collections", 
"GET", null);
+
+        assertEquals(CollectionParams.CollectionAction.LIST.lowerName, 
v1Params.get(ACTION));
+    }
+
+    @Test
     public void testCreateAliasAllProperties() throws Exception {
         final SolrParams v1Params = captureConvertedV1Params("/collections", 
"POST",
                 "{'create-alias': {" +

Reply via email to