edu.umass.cs.gnsclient.console.ConsoleBasedTest.java Source code

Java tutorial

Introduction

Here is the source code for edu.umass.cs.gnsclient.console.ConsoleBasedTest.java

Source

/*
 *
 *  Copyright (c) 2015 University of Massachusetts
 *
 *  Licensed 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.
 *
 *  Initial developer(s): Emmanuel Cecchet
 *
 */
package edu.umass.cs.gnsclient.console;

import java.io.IOException;
import java.io.StringWriter;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import jline.ConsoleReader;

import org.apache.commons.lang3.StringUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import edu.umass.cs.gnsclient.client.GNSClientConfig;
import java.io.ByteArrayInputStream;
import static org.junit.Assert.fail;

/**
 * This class defines a ConsoleBasedTest
 *
 * @author <a href="mailto:cecchet@cs.umass.edu">Emmanuel Cecchet</a>
 * @version 1.0
 */
public class ConsoleBasedTest {

    private static final String GNS_CLI_PROMPT = "GNS CLI";
    private static final String ACCOUNT = "test_account@localhost";
    private static final String PASSWORD = "password";
    private static final String GROUP_GUID = "test_group";
    private static final String GUID1 = "test_guid1";
    private static final String GUID2 = "test_guid2";
    private static final String FIELD1 = "test_field1";
    private static final String VALUE1 = "1234567890";
    private static final String VALUE2 = "value2";

    /**
     * Used to access the test method name in output messages
     */
    @Rule
    public TestName testName = new TestName();

    /**
     * Test account GUID creation and deletion
     */
    @Test
    public void testAccountGuidCreateDelete() {
        String inCommands;
        String expectedOutput;

        inCommands = "account_create " + ACCOUNT + " " + PASSWORD + "\n";
        //inCommands += "account_verify " + ACCOUNT + " " + createVerificationCode(ACCOUNT) + "\n";
        inCommands += "account_delete " + ACCOUNT + "\n";

        expectedOutput = "Created an account with GUID .*\n";
        //expectedOutput += ACCOUNT + " is not verified.\n";
        //expectedOutput += "Account verified.\n";
        expectedOutput += "Removed account GUID .*\n";

        runCommandsInConsole(inCommands, expectedOutput, true, false);
    }

    /**
     * Repeat testAccountGuidCreateDelete 5 times.
     */
    @Test
    public void test5AccountGuidCreateDelete() {
        for (int i = 0; i < 5; i++) {
            testAccountGuidCreateDelete();
        }
    }

    /**
     * Create an account GUID and set it as default using guid_use
     */
    @Test
    public void testCreateAndSetDefaultGuid() {
        String inCommands;
        String expectedOutput;

        inCommands = "account_create " + ACCOUNT + " " + PASSWORD + "\n";
        //inCommands += "account_verify " + ACCOUNT + " " + createVerificationCode(ACCOUNT) + "\n";
        inCommands += "set_default_guid " + ACCOUNT + "\n";

        expectedOutput = "Created an account with GUID .*\n";
        //expectedOutput += ACCOUNT + " is not verified.\n";
        //expectedOutput += "Account verified.\n";
        expectedOutput += "Looking up alias " + ACCOUNT + " GUID and certificates...\n";
        expectedOutput += "Default GUID set to " + ACCOUNT + "\n";

        runCommandsInConsole(inCommands, expectedOutput, true, false);
    }

    /**
     * Test GUID creation and deletion
     */
    @Test
    public void testField() {
        String inCommands;
        String expectedOutput;

        inCommands = "field_create " + FIELD1 + "\n";
        inCommands += "field_write " + FIELD1 + " " + VALUE1 + "\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_delete " + FIELD1 + "\n";
        inCommands += "field_create " + FIELD1 + " zero\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_append " + FIELD1 + " one\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_set 1 " + FIELD1 + " two\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_clear " + FIELD1 + "\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_delete " + FIELD1 + "\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_write " + FIELD1 + " " + VALUE1 + "\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_write " + FIELD1 + " " + VALUE2 + "\n";
        inCommands += "field_read " + FIELD1 + "\n";
        inCommands += "field_delete " + FIELD1 + "\n";

        expectedOutput = "New field " + FIELD1 + " created with value ''.*\n";
        expectedOutput += "Value '" + VALUE1 + "' written to field " + FIELD1 + " for GUID .*\n";
        expectedOutput += Pattern.quote("[\"" + VALUE1 + "\"]") + ".*\n";
        expectedOutput += "Field " + FIELD1 + " removed from GUID .*\n";
        expectedOutput += "New field " + FIELD1 + " created with value 'zero'.*\n";
        expectedOutput += Pattern.quote("[\"zero\"]") + ".*\n";
        expectedOutput += "Value 'one' appended to field " + FIELD1 + " for GUID .*\n";
        expectedOutput += Pattern.quote("[\"zero\",\"one\"]") + ".*\n";
        expectedOutput += "Value 'two' written at index 1 of field " + FIELD1 + " for GUID .*\n";
        expectedOutput += Pattern.quote("[\"zero\",\"two\"]") + ".*\n";
        expectedOutput += "Field " + FIELD1 + " cleared.*\n";
        expectedOutput += Pattern.quote("[]") + ".*\n";
        expectedOutput += "Field " + FIELD1 + " removed from GUID .*\n";
        expectedOutput += Pattern.quote(
                "Failed to access GNS ( edu.umass.cs.gnsclient.exceptions.GnsException: General command failure: +GENERICEERROR+)")
                + ".*\n";
        expectedOutput += "Value '" + VALUE1 + "' written to field " + FIELD1 + " for GUID .*\n";
        expectedOutput += Pattern.quote("[\"" + VALUE1 + "\"]") + ".*\n";
        expectedOutput += "Value '" + VALUE2 + "' written to field " + FIELD1 + " for GUID .*\n";
        expectedOutput += Pattern.quote("[\"" + VALUE2 + "\"]") + ".*\n";
        expectedOutput += "Field " + FIELD1 + " removed from GUID .*\n";

        runCommandsInConsole(inCommands, expectedOutput, true, true);
    }

    /**
     * Test groups GUIDs and membership
     */
    @Test
    public void testGroupGuid() {
        String inCommands;
        String expectedOutput;

        // Create GUIDs
        inCommands = "guid_create " + GROUP_GUID + "\n";
        inCommands += "guid_create " + GUID1 + "\n";
        inCommands += "guid_create " + GUID2 + "\n";

        // Check and approve membership requestsa
        inCommands += "guid_use " + GROUP_GUID + "\n";
        inCommands += "group_member_list " + GROUP_GUID + "\n";
        inCommands += "group_member_add " + GUID1 + "\n";
        inCommands += "group_member_list\n";
        inCommands += "group_member_add " + GROUP_GUID + " " + GUID2 + "\n";
        inCommands += "group_member_list " + GROUP_GUID + "\n";

        // Remove a member
        inCommands += "group_member_remove " + GROUP_GUID + " " + GUID2 + "\n";
        inCommands += "group_member_list " + GROUP_GUID + "\n";

        // Cleanup GUIDs
        inCommands += "guid_delete " + GUID2 + "\n";
        inCommands += "guid_delete " + GUID1 + "\n";
        inCommands += "guid_delete " + GROUP_GUID + "\n";

        expectedOutput = "Looking for alias " + GROUP_GUID + " GUID and certificates...\n";
        expectedOutput += "Generating new GUID and keys for account .*\n";
        expectedOutput += "Created GUID .*\n";
        expectedOutput += "Looking for alias " + GUID1 + " GUID and certificates...\n";
        expectedOutput += "Generating new GUID and keys for account .*\n";
        expectedOutput += "Created GUID .*\n";
        expectedOutput += "Looking for alias " + GUID2 + " GUID and certificates...\n";
        expectedOutput += "Generating new GUID and keys for account .*\n";
        expectedOutput += "Created GUID .*\n";

        expectedOutput += "Looking up alias " + GROUP_GUID + " GUID and certificates...\n";
        expectedOutput += "Current GUID set to " + GROUP_GUID + ".*\n";
        expectedOutput += "Members in group .*\n";
        expectedOutput += "GUID " + GUID1 + " added to group .*\n";
        expectedOutput += "Members in group .*\n";
        expectedOutput += "0: " + GUID1 + ".*\n";
        expectedOutput += "GUID " + GUID2 + " added to group .*\n";
        expectedOutput += "Members in group .*\n";
        expectedOutput += "0: " + GUID1 + ".*\n";
        expectedOutput += "1: " + GUID2 + ".*\n";
        expectedOutput += "GUID " + GUID2 + " removed from group .*\n";
        expectedOutput += "Members in group .*\n";
        expectedOutput += "0: " + GUID1 + ".*\n";

        expectedOutput += "Looking up alias " + GUID2 + " certificates...\n";
        expectedOutput += "Alias " + GUID2 + " removed from GNS.\n";
        expectedOutput += "Keys for " + GUID2 + " removed from local repository..*\n";
        expectedOutput += "Looking up alias " + GUID1 + " certificates...\n";
        expectedOutput += "Alias " + GUID1 + " removed from GNS.\n";
        expectedOutput += "Keys for " + GUID1 + " removed from local repository..*\n";
        expectedOutput += "Looking up alias " + GROUP_GUID + " certificates...\n";
        expectedOutput += "Alias " + GROUP_GUID + " removed from GNS.\n";
        expectedOutput += "Keys for " + GROUP_GUID + " removed from local repository..*\n";

        runCommandsInConsole(inCommands, expectedOutput, true, true);
    }

    /**
     * Test GUID creation and deletion
     */
    @Test
    public void testGuidCreateDelete() {
        String inCommands;
        String expectedOutput;

        inCommands = "guid_create " + GUID1 + "\n";
        inCommands += "guid_delete " + GUID1 + "\n";

        expectedOutput = "Looking for alias " + GUID1 + " GUID and certificates...\n";
        expectedOutput += "Generating new GUID and keys for account .*\n";
        expectedOutput += "Created GUID .*\n";
        expectedOutput += "Looking up alias " + GUID1 + " certificates...\n";
        expectedOutput += "Alias " + GUID1 + " removed from GNS.\n";
        expectedOutput += "Keys for " + GUID1 + " removed from local repository..*\n";

        runCommandsInConsole(inCommands, expectedOutput, true, true);
    }

    /**
     * Test GUID creation and deletion 5 times
     */
    @Test
    public void test5GuidCreateDelete() {
        for (int i = 0; i < 5; i++) {
            testGuidCreateDelete();
        }
    }

    /**
     * Test account GUID creation and deletion
     */
    @Test
    public void testAccountGuidDelete() {
        String inCommands;
        String expectedOutput;

        inCommands = "account_delete " + ACCOUNT + "\n";

        expectedOutput = "Removed account GUID .*\n";

        runCommandsInConsole(inCommands, expectedOutput, true, false);
    }

    /**
     * Run inCommands commands through the CLI and compare the output with
     * expectedOutput. Can also check if a default GNS and/or GUID have been set.
     *
     * @param inCommands list of console commands separated by '\n'
     * @param expectedOutput list of expected console output (can use Java regular
     * expressions, each line separated by '\n')
     * @param requireDefaultGns check if a default GNS has been defined (will
     * error out if not)
     * @param requireDefaultAccountGuid check if a default GUID has been defined
     * (will error out if not)
     */
    protected void runCommandsInConsole(String inCommands, String expectedOutput, boolean requireDefaultGns,
            boolean requireDefaultAccountGuid) {
        boolean success = false;
        StringWriter output = new StringWriter();
        try {
            ConsoleReader consoleReader = new ConsoleReader(new ByteArrayInputStream(inCommands.getBytes("UTF-8")),
                    output);
            ConsoleModule module = new ConsoleModule(consoleReader);
            module.printString("GNS Client Version: " + GNSClientConfig.readBuildVersion() + "\n");

            // Run the commands
            module.handlePrompt();

            // Check the output
            StringTokenizer expected = new StringTokenizer(expectedOutput, "\n");
            StringTokenizer actual = new StringTokenizer(output.toString(), "\n");

            if (!actual.hasMoreTokens()) {
                fail("No console output");
            }

            if (!actual.nextToken().startsWith("GNS Client Version")) {
                fail("Unexpected console output, should start with 'GNS Client Version'");
            }

            // Check that default GNS defaults is set
            if (requireDefaultGns) {
                if (!actual.hasMoreTokens()) {
                    fail("Default GNS not set");
                }
                String defaultGns = actual.nextToken();
                if ("Default GNS: null".equals(defaultGns)) {
                    fail("Default GNS not set");
                }
                if (!defaultGns.startsWith("Default GNS: ")) {
                    fail("Unexpected console output, should start with 'Default GNS: '");
                }

                // Check GNS Connectivity .
                if (!actual.hasMoreTokens()) {
                    fail("No console output during GNS connectivity check");
                }

                if (!actual.nextToken().startsWith("Checking GNS connectivity")) {
                    fail("Unexpected console output during GNS connectivity check");
                }
                if (!actual.hasMoreTokens()) {
                    fail("No console output during GNS connectivity check");
                }
                if (!actual.nextToken().startsWith("Connected to GNS")) {
                    fail("Default GNS is not reachable");
                }
            } else { // Consume lines until we connected or not to a default GNS
                while (actual.hasMoreTokens()) {
                    String line = actual.nextToken();
                    if (line.startsWith("Connected to GNS") || line.startsWith("Failed to connect to GNS")
                            || line.startsWith("Couldn't connect to default GNS")) {
                        break;
                    }
                }
            }

            if (requireDefaultAccountGuid) {
                // Check default GUID
                if (!actual.hasMoreTokens()) {
                    fail("Default GUID not set");
                }
                String defaultGuid = actual.nextToken();
                if (defaultGuid.matches("Default GUID: null")) {
                    fail("Default GUID not set");
                }
                if (!actual.hasMoreTokens()) {
                    fail("Default GUID not set");
                }
                defaultGuid = actual.nextToken();
                if (!defaultGuid.matches("Looking up alias .*")) {
                    fail("Unexpected console output, should start with 'Looking up alias'");
                }
                if (!actual.hasMoreTokens()) {
                    fail("Default GUID not set");
                }
                if (!actual.nextToken().startsWith("Current GUID set to ")) {
                    fail("Default GUID not set or not valid");
                }
                if (!actual.hasMoreTokens()) {
                    fail("Default GUID not set or not valid");
                }

                // Next should be the console prompt
                if (!actual.nextToken().startsWith(GNS_CLI_PROMPT)) {
                    fail("Default GUID not properly set, expected console prompt");
                }
            } else {
                // Consume all input until first prompt
                while (actual.hasMoreTokens() && !actual.nextToken().startsWith(GNS_CLI_PROMPT))
                    ;
            }

            // Diff outputs
            while (expected.hasMoreTokens()) {
                String nextExpected = expected.nextToken();
                String nextActual = null;
                if (actual.hasMoreTokens()) { // Skip command line prompts to get real output
                    nextActual = actual.nextToken();
                    while (nextActual.startsWith(GNS_CLI_PROMPT) && actual.hasMoreTokens()) {
                        nextActual = actual.nextToken();
                    }
                    // Treat expected as a regular expression
                    if (!nextActual.matches("(?s)" + nextExpected)) {
                        if (StringUtils.getLevenshteinDistance(nextActual, nextExpected) < 5) {
                            for (int i = 0; i < nextActual.length(); i++) {
                                final char actualChar = nextActual.charAt(i);
                                if (i < expectedOutput.length()) {
                                    final char expectedChar = nextExpected.charAt(i);
                                    if (actualChar != expectedChar) {
                                        System.out.println("Character " + i + " differs: " + ((int) actualChar)
                                                + " vs expected " + ((int) expectedChar) + " - " + actualChar + "<>"
                                                + expectedChar + "\n");
                                    }
                                } else {
                                    System.out.println("Character " + i + " is extra: " + ((int) actualChar) + " - "
                                            + actualChar);
                                }
                            }
                        }
                        fail("Got     : '" + nextActual + "'\n" + "Expected: '" + nextExpected + "'\n");
                    }
                } else {
                    fail("Missing expected output: " + nextExpected);
                }
            }

            // Check extra output
            while (actual.hasMoreTokens()) {
                String nextActual = actual.nextToken();
                while (nextActual.startsWith(GNS_CLI_PROMPT) && actual.hasMoreTokens()) {
                    nextActual = actual.nextToken();
                }
                if (!nextActual.startsWith(GNS_CLI_PROMPT)) {
                    fail("Extra output: " + actual.nextToken());
                }
            }

            success = true;
        } catch (IOException e) {
            fail("Error during console execution " + e);
        } finally {
            if (!success) {
                System.out.println("**** COMPLETE OUTPUT for " + testName.getMethodName() + " ****");
                System.out.println(output.toString());
            }
        }
    }
}