| /* |
| * 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.metron.stellar.common.shell.cli; |
| |
| import com.google.common.collect.Iterables; |
| import org.jboss.aesh.complete.CompleteOperation; |
| import org.jboss.aesh.console.AeshContext; |
| import org.jboss.aesh.console.ConsoleOperation; |
| import org.jboss.aesh.console.operator.ControlOperator; |
| import org.jboss.aesh.console.settings.DefaultAeshContext; |
| import org.junit.jupiter.api.AfterEach; |
| import org.junit.jupiter.api.BeforeEach; |
| import org.junit.jupiter.api.Test; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.PrintStream; |
| import java.nio.charset.StandardCharsets; |
| import java.util.List; |
| |
| import static org.junit.jupiter.api.Assertions.*; |
| |
| /** |
| * Tests the StellarShell class. |
| */ |
| public class StellarShellTest { |
| |
| private StellarShell stellarShell; |
| private ByteArrayOutputStream out; |
| private ByteArrayOutputStream err; |
| |
| @BeforeEach |
| public void setup() throws Exception { |
| |
| out = new ByteArrayOutputStream(); |
| err = new ByteArrayOutputStream(); |
| |
| // setup streams so that we can capture stdout |
| System.setOut(new PrintStream(out, false, StandardCharsets.UTF_8.name())); |
| System.setErr(new PrintStream(err, false, StandardCharsets.UTF_8.name())); |
| |
| String[] args = new String[0]; |
| stellarShell = new StellarShell(args); |
| } |
| |
| @AfterEach |
| public void cleanUp() { |
| System.setOut(null); |
| System.setErr(null); |
| } |
| |
| /** |
| * @return The data written to stdout during the test (with newlines stripped out to simplify comparisons.) |
| */ |
| private String stdout() { |
| return out.toString().replace(System.lineSeparator(), ""); |
| } |
| |
| /** |
| * @return The data written to stdout during the test. |
| */ |
| private String stdoutWithNewlines() { |
| return out.toString(); |
| } |
| |
| |
| /** |
| * @return The data written to stderr during the test. |
| */ |
| private String stderr() { |
| return err.toString().replace(System.lineSeparator(), ""); |
| } |
| |
| /** |
| * @param buffer |
| * @return A ConsoleOperation that that StellarShell uses to drive input. |
| */ |
| private ConsoleOperation createOp(String buffer) { |
| return new ConsoleOperation(ControlOperator.APPEND_OUT, buffer); |
| } |
| |
| @Test |
| public void testExecuteStellar() throws Exception { |
| stellarShell.execute(createOp("2 + 2")); |
| assertEquals("4", stdout()); |
| } |
| |
| @Test |
| public void testBackslashInStrings() throws Exception { |
| stellarShell.execute(createOp("SPLIT('foo\\\\bar', '\\\\')")); |
| assertEquals("[foo, bar]", stdout()); |
| } |
| |
| /** |
| * Ensure that Stellar lists are displayed correctly in the REPL. |
| */ |
| @Test |
| public void testExecuteWithStellarList() throws Exception { |
| stellarShell.execute(createOp("[1,2,3,4,5]")); |
| assertEquals("[1, 2, 3, 4, 5]", stdout()); |
| } |
| |
| /** |
| * Ensure that Stellar maps are displayed correctly in the REPL. |
| */ |
| @Test |
| public void testExecuteWithStellarMap() throws Exception { |
| stellarShell.execute(createOp("{ 'foo':2, 'key':'val' }")); |
| assertEquals("{foo=2, key=val}", stdout()); |
| } |
| |
| /** |
| * Ensure that 'bad' Stellar code is handled correctly by the REPL. |
| */ |
| @Test |
| public void testExecuteBadStellar() throws Exception { |
| stellarShell.execute(createOp("2 + ")); |
| final String expected = "[!] Unable to parse: 2 + "; |
| assertTrue(stdout().startsWith(expected)); |
| } |
| |
| /** |
| * The REPL should handle if no value is returned. Some Stellar expressions |
| * will result in no value. |
| */ |
| @Test |
| public void testExecuteNoop() throws Exception { |
| stellarShell.execute(createOp("x")); |
| assertEquals("", stdout()); |
| } |
| |
| /** |
| * The REPL should handle if the user chooses to quit. |
| */ |
| @Test |
| public void testQuit() throws Exception { |
| stellarShell.execute(createOp("quit")); |
| |
| // the console should not be running |
| assertFalse(stellarShell.getConsole().isRunning()); |
| } |
| |
| /** |
| * The REPL should handle if the user chooses to quit. |
| */ |
| @Test |
| public void testStart() throws Exception { |
| |
| StellarShell.main(new String[0]); |
| |
| // we should see the welcome prompt |
| assertTrue(stdoutWithNewlines().contains(StellarShell.WELCOME)); |
| } |
| |
| /** |
| * The REPL should support auto-completion. |
| */ |
| @Test |
| public void testAutoComplete() throws Exception { |
| |
| // the user's input that needs auto-completed |
| final String buffer = "TO_"; |
| |
| // the cursor is at the end of the buffer |
| int cursor = buffer.length(); |
| |
| // ask the shell to auto-complete |
| AeshContext context = new DefaultAeshContext(); |
| CompleteOperation op = new CompleteOperation(context, buffer, cursor); |
| stellarShell.complete(op); |
| |
| // we should have some auto-complete candidates |
| List<String> candidates = op.getFormattedCompletionCandidates(); |
| assertTrue(candidates.size() > 0); |
| |
| // validate each candidate |
| for(String candidate: candidates) { |
| String completion = buffer + candidate; |
| |
| // the auto-complete should include an open paren |
| assertEquals("(", completion.substring(completion.length() - 1)); |
| |
| // the candidate should be a valid, defined function |
| String function = completion.substring(0, completion.length() - 1); |
| Iterable<String> allFunctions = stellarShell.getExecutor().getFunctionResolver().getFunctions(); |
| String definedFunction = Iterables.find(allFunctions, (fn) -> fn.equals(function)); |
| assertEquals(function, definedFunction); |
| } |
| } |
| } |