/* * Copyright 2015 Red Hat, Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. * * * Copyright (c) 2015 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. * */ package io.vertx.ext.shell.command.base; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.eventbus.DeliveryOptions; import io.vertx.core.eventbus.EventBus; import io.vertx.core.eventbus.Message; import io.vertx.core.http.CaseInsensitiveHeaders; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.ext.shell.Shell; import io.vertx.ext.shell.ShellServer; import io.vertx.ext.shell.system.ExecStatus; import io.vertx.ext.shell.system.Job; import io.vertx.ext.shell.term.Pty; import io.vertx.ext.unit.Async; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.VertxUnitRunner; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import sun.misc.BASE64Encoder; import java.util.Arrays; import java.util.Collections; /** * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */ @RunWith(VertxUnitRunner.class) public class BusTest { Vertx vertx; ShellServer server; @Before public void before(TestContext context) throws Exception { vertx = Vertx.vertx(); server = ShellServer.create(vertx).registerCommandResolver(new BaseCommandPack(vertx)).listen(context.asyncAssertSuccess()); } @After public void after(TestContext context) { vertx.close(context.asyncAssertSuccess()); } @Test public void testBusSend(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send the_address the_message", msg -> { context.assertEquals("the_message", msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendHeader(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --header=foo:bar the_address the_message", msg -> { context.assertEquals("the_message", msg.body()); context.assertEquals(Collections.singleton("foo"), msg.headers().names()); context.assertEquals(Collections.singletonList("bar"), msg.headers().getAll("foo")); consumerAsync.complete(); }); } @Test public void testBusSendHeaders(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --header=foo:bar1 --header=foo:bar2 the_address the_message", msg -> { context.assertEquals("the_message", msg.body()); context.assertEquals(Collections.singleton("foo"), msg.headers().names()); context.assertEquals(Arrays.asList("bar1", "bar2"), msg.headers().getAll("foo")); consumerAsync.complete(); }); } @Test public void testBusSendReply(TestContext context) { Async consumerAsync = context.async(); String result = assertBusSend(context, "bus-send --reply the_address the_message", msg -> { msg.reply("the_reply"); context.assertEquals("the_message", msg.body()); consumerAsync.complete(); }); context.assertEquals("Reply: <the_reply>\n", result); } @Test public void testBusSendReplyTimeout(TestContext context) { Async consumerAsync = context.async(); String result = assertBusSend(context, "bus-send --reply --timeout 50 the_address the_message", msg -> { context.assertEquals("the_message", msg.body()); consumerAsync.complete(); }); context.assertEquals("Error: Timed out after waiting 50(ms) for a reply. address: 1\n", result); } @Test public void testBusSendReplyVerbose(TestContext context) { Async consumerAsync = context.async(); String result = assertBusSend(context, "bus-send --reply --verbose the_address the_message", msg -> { msg.reply("the_reply", new DeliveryOptions().addHeader("header_name", "header_value_1").addHeader("header_name", "header_value_2")); context.assertEquals("the_message", msg.body()); consumerAsync.complete(); }); context.assertEquals("Reply address: null\nReply header header_name:[header_value_1, header_value_2]\nReply: <the_reply>\n", result); } @Test public void testBusSendNull(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send the_address", msg -> { context.assertEquals(null, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendString(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type STRING the_address hello_string", msg -> { context.assertEquals("hello_string", msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendBoolean(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type BOOLEAN the_address true", msg -> { context.assertEquals(true, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendByte(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type BYTE the_address 123", msg -> { context.assertEquals((byte)123, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendShort(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type SHORT the_address 1234", msg -> { context.assertEquals((short)1234, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendInteger(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type INTEGER the_address 12345678", msg -> { context.assertEquals(12345678, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendLong(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type LONG the_address 12345678", msg -> { context.assertEquals(12345678L, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendFloat(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type FLOAT the_address 0.12", msg -> { context.assertEquals(0.12f, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendDouble(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type DOUBLE the_address 0.1234", msg -> { context.assertEquals(0.1234D, msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendCharacter(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type CHARACTER the_address A", msg -> { context.assertEquals('A', msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendJsonObject(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type JSON_OBJECT the_address '{\"foo\":\"foo_value\",\"bar\":3}'", msg -> { context.assertEquals(new JsonObject().put("foo", "foo_value").put("bar", 3), msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendArrayObject(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type JSON_ARRAY the_address '[\"foo\",3]'", msg -> { context.assertEquals(new JsonArray().add("foo").add(3), msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendBuffer(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type BUFFER the_address hello_world", msg -> { context.assertEquals(Buffer.buffer("hello_world"), msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendHex(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type HEX the_address 001FFF", msg -> { context.assertEquals(Buffer.buffer(new byte[]{0,31,-1}), msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendBase64(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type BASE64 the_address " + new BASE64Encoder().encode(new byte[]{0,31,-1}), msg -> { context.assertEquals(Buffer.buffer(new byte[]{0,31,-1}), msg.body()); consumerAsync.complete(); }); } @Test public void testBusSendNegativeLong(TestContext context) { Async consumerAsync = context.async(); assertBusSend(context, "bus-send --type LONG the_address -12345678", msg -> { context.assertEquals(-12345678L, msg.body()); consumerAsync.complete(); }); } private <T> String assertBusSend(TestContext context, String cmd, Handler<Message<T>> handler) { Async terminatedLatch = context.async(); vertx.eventBus().consumer("the_address", handler); Shell shell = server.createShell(); Pty pty = Pty.create(); StringBuffer result = new StringBuffer(); pty.stdoutHandler(result::append); Job job = shell.createJob(cmd).setTty(pty.slave()); job.statusUpdateHandler(status -> { if (status == ExecStatus.TERMINATED) { terminatedLatch.complete(); } }); job.run(); terminatedLatch.awaitSuccess(5000); return result.toString(); } @Test public void testBusTail(TestContext context) { EventBus eb = vertx.eventBus(); assertBusTail(context, "bus-tail the_address1 the_address2", () -> { eb.send("the_address1", "the_message1"); eb.send("the_address2", "the_message2"); eb.send("the_address1", "the_message3"); }, "the_address1:the_message1\nthe_address2:the_message2\nthe_address1:the_message3\n"); } @Test public void testBusTailVerbose(TestContext context) { EventBus eb = vertx.eventBus(); assertBusTail(context, "bus-tail --verbose the_address", () -> { eb.send("the_address", "the_message", new DeliveryOptions().setHeaders(new CaseInsensitiveHeaders()).addHeader("header_name", "header_value")); }, "the_address:\nReply address: null\nHeader header_name:[header_value]\nthe_message\n"); } private void assertBusTail(TestContext context, String cmd, Runnable send, String expected) { Async runningLatch = context.async(); Shell shell = server.createShell(); Pty pty = Pty.create(); StringBuffer result = new StringBuffer(); pty.stdoutHandler(result::append); Job job = shell.createJob(cmd).setTty(pty.slave()); job.statusUpdateHandler(status -> { if (status == ExecStatus.RUNNING) { runningLatch.complete(); } }); job.run(); runningLatch.awaitSuccess(5000); send.run(); long now = System.currentTimeMillis(); while (result.length() < expected.length()) { context.assertTrue(System.currentTimeMillis() - now < 2000); } context.assertEquals(expected, result.toString()); } }