diff options
Diffstat (limited to 'clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/StateRestAPITest.java')
-rw-r--r-- | clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/StateRestAPITest.java | 442 |
1 files changed, 270 insertions, 172 deletions
diff --git a/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/StateRestAPITest.java b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/StateRestAPITest.java index d0378dd9065..47b12f883ff 100644 --- a/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/StateRestAPITest.java +++ b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/StateRestAPITest.java @@ -1,22 +1,35 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.clustercontroller.utils.staterestapi; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation; import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncUtils; import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequest; import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpResult; -import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.*; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.DeadlineExceededException; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InternalFailure; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidContentException; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidOptionValueException; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.OperationNotSupportedForUnitException; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.OtherMasterException; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.UnknownMasterException; import com.yahoo.vespa.clustercontroller.utils.staterestapi.server.RestApiHandler; import com.yahoo.vespa.clustercontroller.utils.test.TestTransport; -import org.codehaus.jettison.json.JSONObject; import org.junit.jupiter.api.Test; import java.util.Optional; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class StateRestAPITest { + private static final ObjectMapper mapper = new ObjectMapper(); + private static void populateDummyBackend(DummyBackend backend) { backend.addCluster(new DummyBackend.Cluster("foo") .addNode(new DummyBackend.Node("1") @@ -61,14 +74,15 @@ public class StateRestAPITest { if (!op.isSuccess()) { // Don't call getCause() unless it fails assertTrue(op.isSuccess(), op.getCause().toString()); } - assertTrue(op.getResult() != null); + assertNotNull(op.getResult()); return op.getResult(); } - private JSONObject executeOkJsonRequest(HttpRequest request) { + + private JsonNode executeOkJsonRequest(HttpRequest request) { HttpResult result = execute(request); assertEquals(200, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); - return (JSONObject) result.getContent(); + return (JsonNode) result.getContent(); } @Test @@ -77,11 +91,18 @@ public class StateRestAPITest { HttpResult result = execute(new HttpRequest().setPath("/cluster/v2")); assertEquals(200, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); - String expected = "{\"cluster\": {\n" - + " \"foo\": {\"link\": \"\\/cluster\\/v2\\/foo\"},\n" - + " \"bar\": {\"link\": \"\\/cluster\\/v2\\/bar\"}\n" - + "}}"; - assertEquals(expected, ((JSONObject) result.getContent()).toString(2)); + assertEquals(""" + { + "cluster" : { + "foo" : { + "link" : "/cluster/v2/foo" + }, + "bar" : { + "link" : "/cluster/v2/bar" + } + } + }""", + ((JsonNode) result.getContent()).toPrettyString()); } @Test @@ -90,11 +111,18 @@ public class StateRestAPITest { HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo")); assertEquals(200, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); - String expected = "{\"node\": {\n" - + " \"1\": {\"link\": \"\\/cluster\\/v2\\/foo\\/1\"},\n" - + " \"3\": {\"link\": \"\\/cluster\\/v2\\/foo\\/3\"}\n" - + "}}"; - assertEquals(expected, ((JSONObject) result.getContent()).toString(2)); + assertEquals(""" + { + "node" : { + "1" : { + "link" : "/cluster/v2/foo/1" + }, + "3" : { + "link" : "/cluster/v2/foo/3" + } + } + }""", + ((JsonNode) result.getContent()).toPrettyString()); } @Test @@ -103,118 +131,170 @@ public class StateRestAPITest { HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3")); assertEquals(200, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); - String expected = "{\n" - + " \"attributes\": {\"group\": \"mygroup\"},\n" - + " \"state\": {\"current\": {\n" - + " \"state\": \"up\",\n" - + " \"reason\": \"\"\n" - + " }},\n" - + " \"metrics\": {\"doc-count\": 8}\n" - + "}"; - assertEquals(expected, ((JSONObject) result.getContent()).toString(2)); + String expected = """ + { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "up", + "reason" : "" + } + }, + "metrics" : { + "doc-count" : 8 + } + }"""; + assertEquals(expected, ((JsonNode) result.getContent()).toPrettyString()); } @Test void testRecursiveMode() throws Exception { setupDummyStateApi(); { - JSONObject json = executeOkJsonRequest( + JsonNode json = executeOkJsonRequest( new HttpRequest().setPath("/cluster/v2").addUrlOption("recursive", "true")); - String expected = - "{\"cluster\": {\n" + - " \"foo\": {\"node\": {\n" + - " \"1\": {\n" + - " \"attributes\": {\"group\": \"mygroup\"},\n" + - " \"state\": {\"current\": {\n" + - " \"state\": \"initializing\",\n" + - " \"reason\": \"\"\n" + - " }},\n" + - " \"metrics\": {\"doc-count\": 5}\n" + - " },\n" + - " \"3\": {\n" + - " \"attributes\": {\"group\": \"mygroup\"},\n" + - " \"state\": {\"current\": {\n" + - " \"state\": \"up\",\n" + - " \"reason\": \"\"\n" + - " }},\n" + - " \"metrics\": {\"doc-count\": 8}\n" + - " }\n" + - " }},\n" + - " \"bar\": {\"node\": {\"2\": {\n" + - " \"attributes\": {\"group\": \"mygroup\"},\n" + - " \"state\": {\"current\": {\n" + - " \"state\": \"down\",\n" + - " \"reason\": \"\"\n" + - " }},\n" + - " \"metrics\": {\"doc-count\": 0}\n" + - " }}}\n" + - "}}"; - assertEquals(expected, json.toString(2)); + assertEquals(""" + { + "cluster" : { + "foo" : { + "node" : { + "1" : { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "initializing", + "reason" : "" + } + }, + "metrics" : { + "doc-count" : 5 + } + }, + "3" : { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "up", + "reason" : "" + } + }, + "metrics" : { + "doc-count" : 8 + } + } + } + }, + "bar" : { + "node" : { + "2" : { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "down", + "reason" : "" + } + }, + "metrics" : { + "doc-count" : 0 + } + } + } + } + } + }""", + json.toPrettyString()); } { - JSONObject json = executeOkJsonRequest( - new HttpRequest().setPath("/cluster/v2").addUrlOption("recursive", "1")); - String expected = - "{\"cluster\": {\n" + - " \"foo\": {\"node\": {\n" + - " \"1\": {\"link\": \"\\/cluster\\/v2\\/foo\\/1\"},\n" + - " \"3\": {\"link\": \"\\/cluster\\/v2\\/foo\\/3\"}\n" + - " }},\n" + - " \"bar\": {\"node\": {\"2\": {\"link\": \"\\/cluster\\/v2\\/bar\\/2\"}}}\n" + - "}}"; - // Verify that the actual link does not contain backslash. It's just an artifact of - // jettison json output. - assertEquals("/cluster/v2/foo/1", - json.getJSONObject("cluster").getJSONObject("foo").getJSONObject("node") - .getJSONObject("1").getString("link")); - assertEquals(expected, json.toString(2)); + JsonNode json = executeOkJsonRequest(new HttpRequest().setPath("/cluster/v2").addUrlOption("recursive", "1")); + assertEquals(""" + { + "cluster" : { + "foo" : { + "node" : { + "1" : { + "link" : "/cluster/v2/foo/1" + }, + "3" : { + "link" : "/cluster/v2/foo/3" + } + } + }, + "bar" : { + "node" : { + "2" : { + "link" : "/cluster/v2/bar/2" + } + } + } + } + }""", + json.toPrettyString()); } { - JSONObject json = executeOkJsonRequest( - new HttpRequest().setPath("/cluster/v2/foo").addUrlOption("recursive", "1")); - String expected = - "{\"node\": {\n" + - " \"1\": {\n" + - " \"attributes\": {\"group\": \"mygroup\"},\n" + - " \"state\": {\"current\": {\n" + - " \"state\": \"initializing\",\n" + - " \"reason\": \"\"\n" + - " }},\n" + - " \"metrics\": {\"doc-count\": 5}\n" + - " },\n" + - " \"3\": {\n" + - " \"attributes\": {\"group\": \"mygroup\"},\n" + - " \"state\": {\"current\": {\n" + - " \"state\": \"up\",\n" + - " \"reason\": \"\"\n" + - " }},\n" + - " \"metrics\": {\"doc-count\": 8}\n" + - " }\n" + - "}}"; - assertEquals(expected, json.toString(2)); + JsonNode json = executeOkJsonRequest( new HttpRequest().setPath("/cluster/v2/foo").addUrlOption("recursive", "1")); + assertEquals(""" + { + "node" : { + "1" : { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "initializing", + "reason" : "" + } + }, + "metrics" : { + "doc-count" : 5 + } + }, + "3" : { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "up", + "reason" : "" + } + }, + "metrics" : { + "doc-count" : 8 + } + } + } + }""", json.toPrettyString()); } { - JSONObject json = executeOkJsonRequest( - new HttpRequest().setPath("/cluster/v2/foo").addUrlOption("recursive", "false")); - String expected = - "{\"node\": {\n" + - " \"1\": {\"link\": \"\\/cluster\\/v2\\/foo\\/1\"},\n" + - " \"3\": {\"link\": \"\\/cluster\\/v2\\/foo\\/3\"}\n" + - "}}"; - assertEquals(expected, json.toString(2)); + JsonNode json = executeOkJsonRequest( new HttpRequest().setPath("/cluster/v2/foo").addUrlOption("recursive", "false")); + assertEquals(""" + { + "node" : { + "1" : { + "link" : "/cluster/v2/foo/1" + }, + "3" : { + "link" : "/cluster/v2/foo/3" + } + } + }""", json.toPrettyString()); } } private String retireAndExpectHttp200Response(Optional<String> responseWait) throws Exception { - JSONObject json = new JSONObject() - .put("state", new JSONObject() - .put("current", new JSONObject() - .put("state", "retired") - .put("reason", "No reason"))) - .put("condition", "FORCE"); - if (responseWait.isPresent()) { - json.put("response-wait", responseWait.get()); - } + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); + json.putObject("state").putObject("current").put("state", "retired").put("reason", "No reason"); + json.put("condition", "FORCE"); + responseWait.ifPresent(wait -> json.put("response-wait", wait)); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(200, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); @@ -227,44 +307,56 @@ public class StateRestAPITest { void testSetNodeState() throws Exception { setupDummyStateApi(); { - JSONObject json = new JSONObject().put("state", new JSONObject() - .put("current", new JSONObject() - .put("state", "retired") - .put("reason", "No reason"))); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); + json.putObject("state").putObject("current").put("state", "retired").put("reason", "No reason"); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(200, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); } { - JSONObject json = executeOkJsonRequest(new HttpRequest().setPath("/cluster/v2/foo/3")); - String expected = "{\n" - + " \"attributes\": {\"group\": \"mygroup\"},\n" - + " \"state\": {\"current\": {\n" - + " \"state\": \"retired\",\n" - + " \"reason\": \"No reason\"\n" - + " }},\n" - + " \"metrics\": {\"doc-count\": 8}\n" - + "}"; - assertEquals(expected, json.toString(2), json.toString(2)); + JsonNode json = executeOkJsonRequest(new HttpRequest().setPath("/cluster/v2/foo/3")); + assertEquals(""" + { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "retired", + "reason" : "No reason" + } + }, + "metrics" : { + "doc-count" : 8 + } + }""", + json.toPrettyString()); } { - JSONObject json = new JSONObject().put("state", new JSONObject() - .put("current", new JSONObject())); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); + json.putObject("state").putObject("current"); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(200, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); } { - JSONObject json = executeOkJsonRequest(new HttpRequest().setPath("/cluster/v2/foo/3")); - String expected = "{\n" - + " \"attributes\": {\"group\": \"mygroup\"},\n" - + " \"state\": {\"current\": {\n" - + " \"state\": \"up\",\n" - + " \"reason\": \"\"\n" - + " }},\n" - + " \"metrics\": {\"doc-count\": 8}\n" - + "}"; - assertEquals(expected, json.toString(2), json.toString(2)); + JsonNode json = executeOkJsonRequest(new HttpRequest().setPath("/cluster/v2/foo/3")); + assertEquals(""" + { + "attributes" : { + "group" : "mygroup" + }, + "state" : { + "current" : { + "state" : "up", + "reason" : "" + } + }, + "metrics" : { + "doc-count" : 8 + } + }""", + json.toPrettyString()); } } @@ -273,19 +365,21 @@ public class StateRestAPITest { setupDummyStateApi(); { String result = retireAndExpectHttp200Response(Optional.of("wait-until-cluster-acked")); - assertEquals(result, - "JSON: {\n" + - " \"wasModified\": true,\n" + - " \"reason\": \"DummyStateAPI wait-until-cluster-acked call\"\n" + - "}"); + assertEquals(""" + JSON: { + "wasModified" : true, + "reason" : "DummyStateAPI wait-until-cluster-acked call" + }""", + result); } { String result = retireAndExpectHttp200Response(Optional.of("no-wait")); - assertEquals(result, - "JSON: {\n" + - " \"wasModified\": true,\n" + - " \"reason\": \"DummyStateAPI no-wait call\"\n" + - "}"); + assertEquals(""" + JSON: { + "wasModified" : true, + "reason" : "DummyStateAPI no-wait call" + }""", + result); } } @@ -293,11 +387,12 @@ public class StateRestAPITest { void set_node_state_response_wait_type_is_cluster_acked_by_default() throws Exception { setupDummyStateApi(); String result = retireAndExpectHttp200Response(Optional.empty()); - assertEquals(result, - "JSON: {\n" + - " \"wasModified\": true,\n" + - " \"reason\": \"DummyStateAPI wait-until-cluster-acked call\"\n" + - "}"); + assertEquals(""" + JSON: { + "wasModified" : true, + "reason" : "DummyStateAPI wait-until-cluster-acked call" + }""", + result); } @Test @@ -314,7 +409,7 @@ public class StateRestAPITest { HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/1234")); assertEquals(404, result.getHttpReturnCode(), result.toString(true)); assertEquals("No such resource 'foo/1234'.", result.getHttpReturnCodeDescription(), result.toString(true)); - String expected = "{\"message\":\"No such resource 'foo\\/1234'.\"}"; + String expected = "{\"message\":\"No such resource 'foo/1234'.\"}"; assertEquals(expected, result.getContent().toString()); } } @@ -442,7 +537,7 @@ public class StateRestAPITest { void testInvalidJsonInSetStateRequest() throws Exception { setupDummyStateApi(); { - JSONObject json = new JSONObject(); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(400, result.getHttpReturnCode(), result.toString(true)); assertEquals("Content of HTTP request had invalid data", result.getHttpReturnCodeDescription(), result.toString(true)); @@ -450,7 +545,7 @@ public class StateRestAPITest { assertTrue(result.getContent().toString().contains("Set state requests must contain a state object"), result.toString(true)); } { - JSONObject json = new JSONObject().put("state", 5); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()).put("state", 5); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(400, result.getHttpReturnCode(), result.toString(true)); assertEquals("Content of HTTP request had invalid data", result.getHttpReturnCodeDescription(), result.toString(true)); @@ -458,8 +553,8 @@ public class StateRestAPITest { assertTrue(result.getContent().toString().contains("value of state is not a json object"), result.toString(true)); } { - JSONObject json = new JSONObject().put("state", new JSONObject() - .put("current", 5)); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); + json.putObject("state").put("current", 5); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(400, result.getHttpReturnCode(), result.toString(true)); assertEquals("Content of HTTP request had invalid data", result.getHttpReturnCodeDescription(), result.toString(true)); @@ -467,8 +562,8 @@ public class StateRestAPITest { assertTrue(result.getContent().toString().contains("value of state->current is not a json object"), result.toString(true)); } { - JSONObject json = new JSONObject().put("state", new JSONObject() - .put("current", new JSONObject().put("state", 5))); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); + json.putObject("state").putObject("current").put("state", 5); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(400, result.getHttpReturnCode(), result.toString(true)); assertEquals("Content of HTTP request had invalid data", result.getHttpReturnCodeDescription(), result.toString(true)); @@ -476,8 +571,8 @@ public class StateRestAPITest { assertTrue(result.getContent().toString().contains("value of state->current->state is not a string"), result.toString(true)); } { - JSONObject json = new JSONObject().put("state", new JSONObject() - .put("current", new JSONObject().put("state", "down").put("reason", 5))); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); + json.putObject("state").putObject("current").put("state", "down").put("reason", 5); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(400, result.getHttpReturnCode(), result.toString(true)); assertEquals("Content of HTTP request had invalid data", result.getHttpReturnCodeDescription(), result.toString(true)); @@ -486,24 +581,27 @@ public class StateRestAPITest { } { String result = retireAndExpectHttp400Response("Non existing condition", "no-wait"); - assertEquals(result, - "JSON: {\"message\": \"Invalid value for condition: 'Non existing condition', expected one of 'force', 'safe'\"}"); + assertEquals(""" + JSON: { + "message" : "Invalid value for condition: 'Non existing condition', expected one of 'force', 'safe'" + }""", + result); } { String result = retireAndExpectHttp400Response("FORCE", "banana"); - assertEquals(result, - "JSON: {\"message\": \"Invalid value for response-wait: 'banana', expected one of 'wait-until-cluster-acked', 'no-wait'\"}"); + assertEquals(""" + JSON: { + "message" : "Invalid value for response-wait: 'banana', expected one of 'wait-until-cluster-acked', 'no-wait'" + }""", + result); } } private String retireAndExpectHttp400Response(String condition, String responseWait) throws Exception { - JSONObject json = new JSONObject() - .put("state", new JSONObject() - .put("current", new JSONObject() - .put("state", "retired") - .put("reason", "No reason"))) - .put("condition", condition) - .put("response-wait", responseWait); + ObjectNode json = new ObjectNode(mapper.getNodeFactory()); + json.putObject("state").putObject("current").put("state", "retired").put("reason", "No reason"); + json.put("condition", condition); + json.put("response-wait", responseWait); HttpResult result = execute(new HttpRequest().setPath("/cluster/v2/foo/3").setPostContent(json)); assertEquals(400, result.getHttpReturnCode(), result.toString(true)); assertEquals("application/json", result.getHeader("Content-Type"), result.toString(true)); |