Browse code

FEATBL-880 Test: add some tests

Enguerran Colson authored on 04/10/2019 15:18:59
Showing 9 changed files
... ...
@@ -7,7 +7,9 @@ Bundle-Vendor: bluemind.net
7 7
 Require-Bundle: org.eclipse.core.runtime,
8 8
  net.bluemind.sds.proxy;bundle-version="4.1.0",
9 9
  net.bluemind.lib.vertx,
10
- org.junit
10
+ org.junit,
11
+ net.bluemind.network.topology,
12
+ com.google.guava
11 13
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
12 14
 Automatic-Module-Name: net.bluemind.sds.proxy.tests
13 15
 Bundle-ActivationPolicy: lazy
14 16
new file mode 100644
... ...
@@ -0,0 +1,52 @@
1
+package net.bluemind.sds.proxy.tests;
2
+
3
+import static org.junit.Assert.assertEquals;
4
+import static org.junit.Assert.assertFalse;
5
+import static org.junit.Assert.assertTrue;
6
+
7
+import org.junit.Test;
8
+import org.vertx.java.core.json.JsonObject;
9
+
10
+import net.bluemind.sds.proxy.events.JsonHelper;
11
+
12
+public class JSONHelperTest {
13
+
14
+	@Test
15
+	public void validJSON() {
16
+		String[] fieldNames = new String[] { "prop1", "prop2" };
17
+		JsonObject json = new JsonObject().putString("prop1", "val").putString("prop2", "value");
18
+		assertTrue(JsonHelper.isValidJson(json, fieldNames));
19
+	}
20
+
21
+	@Test
22
+	public void missingProp() {
23
+		String[] fieldNames = new String[] { "prop1", "prop2" };
24
+		JsonObject json = new JsonObject().putString("prop1", "val");
25
+		assertFalse(JsonHelper.isValidJson(json, fieldNames));
26
+	}
27
+
28
+	@Test
29
+	public void unnecessaryProp() {
30
+		String[] fieldNames = new String[] { "prop1", "prop2" };
31
+		JsonObject json = new JsonObject().putString("prop1", "val").putString("prop2", "val").putString("prop3",
32
+				"val");
33
+		assertTrue(JsonHelper.isValidJson(json, fieldNames));
34
+	}
35
+
36
+	@Test
37
+	public void nullString() {
38
+		assertEquals(new JsonObject(), JsonHelper.getJsonFromString(null));
39
+	}
40
+
41
+	@Test
42
+	public void emptyString() {
43
+		assertEquals(new JsonObject(), JsonHelper.getJsonFromString(""));
44
+	}
45
+
46
+	@Test
47
+	public void validJsonString() {
48
+		assertEquals(new JsonObject().putString("prop1", "value"),
49
+				JsonHelper.getJsonFromString("{\"prop1\": \"value\"}"));
50
+	}
51
+
52
+}
0 53
new file mode 100644
... ...
@@ -0,0 +1,127 @@
1
+package net.bluemind.sds.proxy.tests;
2
+
3
+import static org.junit.Assert.assertEquals;
4
+
5
+import java.util.List;
6
+import java.util.concurrent.CompletableFuture;
7
+import java.util.concurrent.ExecutionException;
8
+import java.util.concurrent.TimeUnit;
9
+import java.util.concurrent.TimeoutException;
10
+
11
+import org.junit.Before;
12
+import org.junit.Test;
13
+import org.vertx.java.core.buffer.Buffer;
14
+import org.vertx.java.core.http.HttpClient;
15
+import org.vertx.java.core.json.JsonObject;
16
+
17
+import com.google.common.collect.Lists;
18
+
19
+import net.bluemind.core.container.model.ItemValue;
20
+import net.bluemind.lib.vertx.VertxPlatform;
21
+import net.bluemind.network.topology.Topology;
22
+import net.bluemind.server.api.Server;
23
+
24
+public class SdsCyrusValidationTests {
25
+
26
+	@Before
27
+	public void before() throws InterruptedException, ExecutionException, TimeoutException {
28
+		populateTopology();
29
+		startVerticles();
30
+	}
31
+
32
+	private void startVerticles() throws InterruptedException, ExecutionException, TimeoutException {
33
+		CompletableFuture<Void> startResult = new CompletableFuture<>();
34
+		VertxPlatform.spawnVerticles(spawnResult -> {
35
+			if (spawnResult.succeeded()) {
36
+				startResult.complete(null);
37
+			} else {
38
+				startResult.completeExceptionally(spawnResult.cause());
39
+			}
40
+		});
41
+		startResult.get(20, TimeUnit.SECONDS);
42
+	}
43
+
44
+	private void populateTopology() {
45
+		Server server = new Server();
46
+		server.ip = "127.0.0.1";
47
+		server.name = "localhost";
48
+		server.tags = Lists.newArrayList("bm/core");
49
+		ItemValue<Server> core = ItemValue.create(server.ip, server);
50
+		List<ItemValue<Server>> servers = Lists.newArrayList(core);
51
+		Topology.update(servers);
52
+	}
53
+
54
+	@Test
55
+	public void headCallNoPayload() throws InterruptedException, ExecutionException, TimeoutException {
56
+		HttpClient client = VertxPlatform.getVertx().createHttpClient().setHost("127.0.0.1").setPort(8091);
57
+		CompletableFuture<Integer> async = new CompletableFuture<>();
58
+		client.head("/mailbox", resp -> {
59
+			async.complete(resp.statusCode());
60
+		}).setChunked(true).end();
61
+
62
+		int httpStatus = async.get(5, TimeUnit.SECONDS);
63
+		assertEquals(403, httpStatus);
64
+	}
65
+
66
+	@Test
67
+	public void headCallInvalidPayload() throws InterruptedException, ExecutionException, TimeoutException {
68
+		JsonObject payload = new JsonObject().putString("invalidproperty", "anyvalue");
69
+
70
+		HttpClient client = VertxPlatform.getVertx().createHttpClient().setHost("127.0.0.1").setPort(8091);
71
+		CompletableFuture<Integer> asyncStatusCode = new CompletableFuture<Integer>();
72
+
73
+		client.head("/mailbox", resp -> {
74
+			asyncStatusCode.complete(resp.statusCode());
75
+		}).setChunked(true).write(new Buffer(payload.encode())).end();
76
+
77
+		int statusCode = asyncStatusCode.get(5, TimeUnit.SECONDS);
78
+		assertEquals(403, statusCode);
79
+	}
80
+
81
+	@Test
82
+	public void headCallMissingPartition() throws InterruptedException, ExecutionException, TimeoutException {
83
+		JsonObject payload = new JsonObject().putString("mailbox", "mailboxvalue");
84
+
85
+		HttpClient client = VertxPlatform.getVertx().createHttpClient().setHost("127.0.0.1").setPort(8091);
86
+		CompletableFuture<Integer> asyncStatusCode = new CompletableFuture<Integer>();
87
+
88
+		client.head("/mailbox", resp -> {
89
+			asyncStatusCode.complete(resp.statusCode());
90
+		}).setChunked(true).write(new Buffer(payload.encode())).end();
91
+
92
+		int statusCode = asyncStatusCode.get(5, TimeUnit.SECONDS);
93
+		assertEquals(403, statusCode);
94
+	}
95
+
96
+	@Test
97
+	public void headCallMissingMailbox() throws InterruptedException, ExecutionException, TimeoutException {
98
+		JsonObject payload = new JsonObject().putString("partition", "partitionvalue");
99
+
100
+		HttpClient client = VertxPlatform.getVertx().createHttpClient().setHost("127.0.0.1").setPort(8091);
101
+		CompletableFuture<Integer> asyncStatusCode = new CompletableFuture<Integer>();
102
+
103
+		client.head("/mailbox", resp -> {
104
+			asyncStatusCode.complete(resp.statusCode());
105
+		}).setChunked(true).write(new Buffer(payload.encode())).end();
106
+
107
+		int statusCode = asyncStatusCode.get(5, TimeUnit.SECONDS);
108
+		assertEquals(403, statusCode);
109
+	}
110
+
111
+	@Test
112
+	public void headCallValidPayload() throws InterruptedException, ExecutionException, TimeoutException {
113
+		JsonObject payload = new JsonObject()//
114
+				.putString("mailbox", "mailboxvalue")//
115
+				.putString("partition", "partitionvalue");
116
+
117
+		HttpClient client = VertxPlatform.getVertx().createHttpClient().setHost("127.0.0.1").setPort(8091);
118
+		CompletableFuture<Integer> asyncStatusCode = new CompletableFuture<Integer>();
119
+
120
+		client.head("/mailbox", resp -> {
121
+			asyncStatusCode.complete(resp.statusCode());
122
+		}).setChunked(true).write(new Buffer(payload.encode())).end();
123
+
124
+		int statusCode = asyncStatusCode.get(5, TimeUnit.SECONDS);
125
+		assertEquals(200, statusCode);
126
+	}
127
+}
... ...
@@ -20,10 +20,11 @@ Require-Bundle: org.eclipse.core.runtime,
20 20
  net.bluemind.core.rest,
21 21
  net.bluemind.core.rest.http,
22 22
  net.bluemind.network.topology,
23
- net.bluemind.backend.mail.replica.api
23
+ net.bluemind.backend.mail.replica.api,
24
+ net.bluemind.config
24 25
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
25 26
 Automatic-Module-Name: net.bluemind.sds.proxy
26 27
 Bundle-ActivationPolicy: lazy
27 28
 Export-Package: net.bluemind.sds.proxy.dto,
29
+ net.bluemind.sds.proxy.events,
28 30
  net.bluemind.sds.proxy.store
29
-Import-Package: net.bluemind.config
... ...
@@ -33,7 +33,6 @@ import org.vertx.java.core.http.RouteMatcher;
33 33
 import org.vertx.java.core.json.JsonObject;
34 34
 import org.vertx.java.platform.Verticle;
35 35
 
36
-import com.google.common.base.Strings;
37 36
 import com.netflix.spectator.api.Id;
38 37
 import com.netflix.spectator.api.Registry;
39 38
 
... ...
@@ -115,25 +114,24 @@ public class SdsProxyHttpVerticle extends Verticle {
115 114
 	}
116 115
 
117 116
 	private void validateMailbox(HttpServerRequest request) {
118
-		request.bodyHandler(buffer -> {
119
-			if (Strings.isNullOrEmpty(buffer.toString())) {
120
-				request.response().setStatusCode(403).end();
121
-			}
122
-
123
-			JsonObject json = new JsonObject(buffer.toString());
117
+		HttpServerRequest req = Requests.wrap(request);
118
+		req.bodyHandler(payload -> {
124 119
 
125
-			vertx.eventBus().sendWithTimeout(SdsAddresses.VALIDATION, json, 3000, result -> {
126
-				if (result.failed()) {
127
-					request.response().setStatusCode(200).end();
128
-				} else {
129
-					if ((boolean) result.result().body()) {
130
-						request.response().setStatusCode(200).end();
131
-					} else {
132
-						request.response().setStatusCode(403).end();
133
-					}
134
-				}
120
+			vertx.eventBus().sendWithTimeout(SdsAddresses.VALIDATION, payload, 3000,
121
+					(AsyncResult<Message<Boolean>> result) -> {
122
+						if (result.failed()) {
123
+							logger.info("Unable to get a result, accept by default");
124
+							request.response().setStatusCode(200).end();
125
+						} else {
126
+							boolean isAccepted = result.result().body();
127
+							if (isAccepted) {
128
+								request.response().setStatusCode(200).end();
129
+							} else {
130
+								request.response().setStatusCode(403).end();
131
+							}
132
+						}
135 133
 
136
-			});
134
+					});
137 135
 		});
138 136
 	}
139 137
 
140 138
new file mode 100644
... ...
@@ -0,0 +1,19 @@
1
+package net.bluemind.sds.proxy.events;
2
+
3
+import java.util.Arrays;
4
+
5
+import org.vertx.java.core.json.JsonObject;
6
+
7
+import com.google.common.base.Strings;
8
+
9
+public class JsonHelper {
10
+
11
+	public static boolean isValidJson(JsonObject json, String... fieldNames) {
12
+		return Arrays.stream(fieldNames).map(fieldName -> json.containsField(fieldName)).reduce(true,
13
+				(acc, value) -> acc && value);
14
+	}
15
+
16
+	public static JsonObject getJsonFromString(String payload) {
17
+		return Strings.isNullOrEmpty(payload) ? new JsonObject() : new JsonObject(payload);
18
+	}
19
+}
... ...
@@ -4,6 +4,7 @@ import java.util.Optional;
4 4
 
5 5
 import org.slf4j.Logger;
6 6
 import org.slf4j.LoggerFactory;
7
+import org.vertx.java.core.buffer.Buffer;
7 8
 import org.vertx.java.core.eventbus.Message;
8 9
 import org.vertx.java.core.json.JsonObject;
9 10
 import org.vertx.java.platform.Verticle;
... ...
@@ -41,19 +42,25 @@ public class SdsCyrusValidationHandlerVerticle extends Verticle {
41 42
 	public void start() {
42 43
 		cli = getProvider();
43 44
 
44
-		vertx.eventBus().registerHandler(SdsAddresses.VALIDATION, (Message<JsonObject> message) -> {
45
-			JsonObject json = message.body();
46
-			String mailbox = json.getString("mailbox");
47
-			String partition = json.getString("partition");
45
+		vertx.eventBus().registerHandler(SdsAddresses.VALIDATION, (Message<Buffer> message) -> {
46
+			JsonObject json = JsonHelper.getJsonFromString(message.body().toString());
48 47
 
49
-			cli.prevalidate(mailbox, partition).thenAccept((Boolean result) -> {
50
-				logger.info("BM Core {} creation of {}/{}", result ? "approves" : "rejects", partition, mailbox);
51
-				message.reply(result);
52
-			}).exceptionally(ex -> {
53
-				logger.error("Unable to get approval of {}/{}: {}", partition, mailbox, ex.getMessage());
54
-				message.fail(CORE_EXCEPTION, ex.getMessage());
55
-				return null;
56
-			});
48
+			if (JsonHelper.isValidJson(json, "mailbox", "partition")) {
49
+				String mailbox = json.getString("mailbox");
50
+				String partition = json.getString("partition");
51
+
52
+				cli.prevalidate(mailbox, partition).thenAccept((Boolean result) -> {
53
+					logger.info("BM Core {} creation of {}/{}", result ? "approves" : "rejects", partition, mailbox);
54
+					message.reply(result);
55
+				}).exceptionally(ex -> {
56
+					logger.error("Unable to get approval of {}/{}: {}", partition, mailbox, ex.getMessage());
57
+					message.fail(CORE_EXCEPTION, ex.getMessage());
58
+					return null;
59
+				});
60
+			} else {
61
+				logger.error("Invalid payload: {}", json);
62
+				message.reply(false);
63
+			}
57 64
 		});
58 65
 	}
59 66
 
60 67
new file mode 100644
... ...
@@ -0,0 +1,52 @@
1
+package net.bluemind.backend.mail.replica.service.tests;
2
+
3
+import static org.junit.Assert.assertFalse;
4
+
5
+import java.util.concurrent.CompletableFuture;
6
+import java.util.concurrent.ExecutionException;
7
+import java.util.concurrent.TimeUnit;
8
+import java.util.concurrent.TimeoutException;
9
+
10
+import org.junit.Before;
11
+import org.junit.Test;
12
+
13
+import net.bluemind.backend.mail.replica.api.ICyrusValidation;
14
+import net.bluemind.core.api.fault.ServerFault;
15
+import net.bluemind.core.context.SecurityContext;
16
+import net.bluemind.core.rest.ServerSideServiceProvider;
17
+import net.bluemind.lib.vertx.VertxPlatform;
18
+
19
+public class CyrusValidationServiceTests {
20
+	private SecurityContext domainAdminSecurityContext;
21
+
22
+	@Before
23
+	public void before() throws InterruptedException, ExecutionException, TimeoutException {
24
+		CompletableFuture<Void> startResult = new CompletableFuture<>();
25
+		VertxPlatform.spawnVerticles(spawnResult -> {
26
+			if (spawnResult.succeeded()) {
27
+				startResult.complete(null);
28
+			} else {
29
+				startResult.completeExceptionally(spawnResult.cause());
30
+			}
31
+		});
32
+		startResult.get(20, TimeUnit.SECONDS);
33
+	}
34
+
35
+	private ICyrusValidation getService(SecurityContext context) {
36
+		return ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(ICyrusValidation.class);
37
+	}
38
+
39
+	@Test
40
+	public void emailDefaultIsNotValid() {
41
+		ICyrusValidation cli = getService(domainAdminSecurityContext);
42
+		boolean result = cli.prevalidate("default", "");
43
+		assertFalse(result);
44
+	}
45
+
46
+	@Test(expected = ServerFault.class)
47
+	public void emailNullIsNotValid() {
48
+		ICyrusValidation cli = getService(domainAdminSecurityContext);
49
+		boolean result = cli.prevalidate(null, "");
50
+		assertFalse(result);
51
+	}
52
+}
... ...
@@ -3,7 +3,11 @@ package net.bluemind.backend.mail.replica.service.internal;
3 3
 import org.slf4j.Logger;
4 4
 import org.slf4j.LoggerFactory;
5 5
 
6
+import com.google.common.base.Strings;
7
+
6 8
 import net.bluemind.backend.mail.replica.api.ICyrusValidation;
9
+import net.bluemind.core.api.fault.ErrorCode;
10
+import net.bluemind.core.api.fault.ServerFault;
7 11
 
8 12
 public class CyrusValidationService implements ICyrusValidation {
9 13
 	private static final Logger logger = LoggerFactory.getLogger(CyrusValidationService.class);
... ...
@@ -11,6 +15,9 @@ public class CyrusValidationService implements ICyrusValidation {
11 15
 	@Override
12 16
 	public boolean prevalidate(String mailbox, String partition) {
13 17
 		logger.info("Cyrus Validation Service - prevalidate {}/{}", partition, mailbox);
18
+		if (Strings.isNullOrEmpty(mailbox)) {
19
+			throw new ServerFault("Null or empty mailbox name", ErrorCode.INVALID_MAILBOX_NAME);
20
+		}
14 21
 		boolean result = true;
15 22
 		switch (mailbox) {
16 23
 		case "default":