candr.yoclip.ParserTest.java Source code

Java tutorial

Introduction

Here is the source code for candr.yoclip.ParserTest.java

Source

/*
 * 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 candr.yoclip;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.StrBuilder;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Test;
import org.mockito.Mockito;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;

/**
 * {@link Parser} unit tests.
 */
@SuppressWarnings("unchecked")
public class ParserTest {

    @Test()
    public void init() {
        final ParserOption<ParserTest> mockOptionProperty = createMockOptionProperty("s");
        final List<ParserOption<ParserTest>> parameters = Arrays.asList(mockOptionProperty);

        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        when(mockParserOptions.get()).thenReturn(parameters);

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        assertThat("property matchers empty", testCase.getPropertyMatchers().isEmpty(), is(false));
    }

    @Test(expected = IllegalArgumentException.class)
    public void initWithNullParserOptions() {
        new Parser<ParserTest>((ParserOptions<ParserTest>) null, createMockParserHelpFactory());
    }

    @Test(expected = IllegalArgumentException.class)
    public void initWithNullHelpFactory() {
        new Parser<ParserTest>(createMockParserParameters(), null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void initWithNullClass() {
        new Parser<ParserTest>((Class<ParserTest>) null);
    }

    @Test
    public void usage() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();

        final String mockedUsage = "mock help factory usage";
        final ParserHelpFactory<ParserTest> mockParserHelpFactory = createMockParserHelpFactory();
        when(mockParserHelpFactory.createUsage(mockParserOptions)).thenReturn(mockedUsage);

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions, mockParserHelpFactory);
        assertThat("default usage", testCase.getUsage(), is(mockedUsage));

        final String customUsage = "custom usage";
        testCase.setUsage(customUsage);
        assertThat("custom usage", testCase.getUsage(), is(customUsage));

        testCase.setUsage(null);
        assertThat("null usage", testCase.getUsage(), is(mockedUsage));

        testCase.setUsage("");
        assertThat("empty usage", testCase.getUsage(), is(mockedUsage));
    }

    @Test
    public void help() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        when(mockParserOptions.getName()).thenReturn("testCase");

        final ParserHelpFactory<ParserTest> mockParserHelpFactory = createMockParserHelpFactory();

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions, mockParserHelpFactory);
        testCase.setUsage("unit tests");

        final String defaultHelp = new StrBuilder().appendln("Usage: testCase unit tests").toString();
        assertThat("default help", testCase.getHelp(), is(defaultHelp));

        testCase.setHelp("one");
        assertThat("one help", testCase.getHelp(), is("one"));

        testCase.setHelp("one", "two");
        assertThat("two help", testCase.getHelp(), is(new StrBuilder().appendln("one").append("two").toString()));

        testCase.setHelp();
        assertThat("no help", testCase.getHelp(), is(defaultHelp));
    }

    @Test
    public void width() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        assertThat("default width", testCase.getWidth(), is(Parser.DEFAULT_WIDTH));

        testCase.setWidth(100);
        assertThat("custom width", testCase.getWidth(), is(100));

        testCase.setWidth(Parser.MINIMUM_WIDTH - 1);
        assertThat("minimum width", testCase.getWidth(), is(Parser.MINIMUM_WIDTH));
    }

    @Test
    public void spaceBeforeHeader() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        assertThat("default space before header", testCase.isSpaceBeforeHeader(), is(true));

        testCase.setSpaceBeforeHeader(false);
        assertThat("turn off space before header", testCase.isSpaceBeforeHeader(), is(false));

        testCase.setSpaceBeforeHeader(true);
        assertThat("turn on space before header", testCase.isSpaceBeforeHeader(), is(true));
    }

    @Test
    public void spaceBetweenOptionDescriptions() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        assertThat("default space between option descriptions", testCase.isSpaceBetweenOptionDescriptions(),
                is(true));

        testCase.setSpaceBetweenOptionDescriptions(false);
        assertThat("turn off space between option descriptions", testCase.isSpaceBetweenOptionDescriptions(),
                is(false));

        testCase.setSpaceBetweenOptionDescriptions(true);
        assertThat("turn on space between option descriptions", testCase.isSpaceBetweenOptionDescriptions(),
                is(true));
    }

    @Test
    public void spaceBeforeTrailer() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        assertThat("default space before trailer", testCase.isSpaceBeforeTrailer(), is(true));

        testCase.setSpaceBeforeTrailer(false);
        assertThat("turn off space before trailer", testCase.isSpaceBeforeTrailer(), is(false));

        testCase.setSpaceBeforeTrailer(true);
        assertThat("turn on space before trailer", testCase.isSpaceBeforeTrailer(), is(true));
    }

    @Test
    public void propertyPattern() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters("+", " ");

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        final String expectedPropertyPattern = "P([\\p{Alnum}*$._-]+=\\p{Graph}+)";
        assertThat("property pattern", testCase.getPropertyPattern("P"), is(expectedPropertyPattern));

        final Matcher matcher = Pattern.compile(expectedPropertyPattern).matcher("");
        assertThat("Pkey=value", matcher.reset("Pkey=value").matches(), is(true));
        assertThat("Pkey.key=value*$._-!@#%^&()+={}[]<>,?/",
                matcher.reset("Pkey.key=value*$._-!@#%^&()+={}[]<>,?/").matches(), is(true));
        assertThat("Pkey", matcher.reset("Pkey").matches(), is(false));
        assertThat("Pkey=", matcher.reset("Pkey=").matches(), is(false));
        assertThat("Pkey_key=value", matcher.reset("Pkey_key=value").matches(), is(true));
        assertThat("Pkey-key=value", matcher.reset("Pkey-key=value").matches(), is(true));
        assertThat("Pkey$key=value", matcher.reset("Pkey$key=value").matches(), is(true));
        assertThat("Pkey*key=value", matcher.reset("Pkey*key=value").matches(), is(true));
    }

    @Test
    public void parse() {

        final ParserOption<ParserTest> mockHelpOption = createMockOption("h");
        when(mockHelpOption.isHelp()).thenReturn(true);

        final ParserOption<ParserTest> mockOption = createMockOption("o");
        when(mockOption.isRequired()).thenReturn(true);

        final ParserOption<ParserTest> mockOptionProperty = createMockOptionProperty("P");
        final ParserOption<ParserTest> mockArguments = createMockArguments();

        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters("-", "=");
        when(mockParserOptions.get())
                .thenReturn(Arrays.asList(mockHelpOption, mockOption, mockOptionProperty, mockArguments));
        when(mockParserOptions.get("h")).thenReturn(mockHelpOption);
        when(mockParserOptions.get("o")).thenReturn(mockOption);
        when(mockParserOptions.get("P")).thenReturn(mockOptionProperty);
        when(mockParserOptions.get(ParserOptions.ARGUMENTS_KEY)).thenReturn(mockArguments);
        when(mockParserOptions.getArguments()).thenReturn(mockArguments);

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        ParseResult<ParserTest> parseResult = testCase.parse(this, "-h");
        assertThat("parse help", parseResult.isParseError(), is(false));
        verify(mockHelpOption).setOption(this, Boolean.TRUE.toString());
        verify(mockOption, never()).setOption(Mockito.any(ParserTest.class), Mockito.anyString());
        verify(mockOptionProperty, never()).setOption(Mockito.any(ParserTest.class), Mockito.anyString());
        verify(mockArguments, never()).setOption(Mockito.any(ParserTest.class), Mockito.anyString());

        parseResult = testCase.parse(this, "-o");
        assertThat("parse option", parseResult.isParseError(), is(false));
        verify(mockHelpOption, times(1)).setOption(this, Boolean.TRUE.toString());
        verify(mockOption).setOption(this, Boolean.TRUE.toString());
        verify(mockOptionProperty, never()).setOption(Mockito.any(ParserTest.class), Mockito.anyString());
        verify(mockArguments, never()).setOption(Mockito.any(ParserTest.class), Mockito.anyString());

        parseResult = testCase.parse(this, "-o", "-Pkey=value");
        assertThat("parse option", parseResult.isParseError(), is(false));
        verify(mockHelpOption, times(1)).setOption(this, Boolean.TRUE.toString());
        verify(mockOption, times(2)).setOption(this, Boolean.TRUE.toString());
        verify(mockOptionProperty).setOption(this, "key=value");
        verify(mockArguments, never()).setOption(Mockito.any(ParserTest.class), Mockito.anyString());

        parseResult = testCase.parse(this, "-o", "arg");
        assertThat("parse option", parseResult.isParseError(), is(false));
        verify(mockHelpOption, times(1)).setOption(this, Boolean.TRUE.toString());
        verify(mockOption, times(3)).setOption(this, Boolean.TRUE.toString());
        verify(mockOptionProperty, times(1)).setOption(this, "key=value");
        verify(mockArguments).setOption(this, "arg");

        // missing required parameter -o
        parseResult = testCase.parse(this, "arg");
        assertThat("parse option", parseResult.isParseError(), is(true));
        verify(mockHelpOption, times(1)).setOption(this, Boolean.TRUE.toString());
        verify(mockOption, times(3)).setOption(this, Boolean.TRUE.toString());
        verify(mockOptionProperty, times(1)).setOption(this, "key=value");
        verify(mockArguments, times(1)).setOption(this, "arg");
    }

    @Test
    public void verifyParse() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        List<ParsedOption<ParserTest>> parsedOptions = Collections.emptyList();
        ParseResult<ParserTest> parseResult = new ParseResult<ParserTest>(this);
        testCase.verifyParse(parseResult, parsedOptions);
        assertThat("empty parsed parameters", parseResult.isParseError(), is(false));

        parsedOptions = Arrays.asList(new ParsedOption<ParserTest>("error"));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForParseError(parseResult, parsedOptions);
        assertThat("parsed parameters with error", parseResult.isParseError(), is(true));

        final ParserOption<ParserTest> mockOption = createMockOption("o");
        when(mockOption.toString()).thenReturn("duplicate");
        parsedOptions = Arrays.asList(new ParsedOption<ParserTest>(mockOption, null),
                new ParsedOption<ParserTest>(mockOption, null));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForDuplicateParameters(parseResult, parsedOptions);
        assertThat("parsed parameters with duplicate option", parseResult.isParseError(), is(true));

        final ParserOption<ParserTest> mockArgument = createMockArguments();
        when(mockArgument.isRequired()).thenReturn(true);
        when(mockParserOptions.get()).thenReturn(Arrays.asList(mockArgument));

        parsedOptions = Collections.emptyList();
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForRequiredParameters(parseResult, parsedOptions);
        assertThat("parse parameters missing required argument", parseResult.isParseError(), is(true));

    }

    @Test
    public void checkForParseError() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        List<ParsedOption<ParserTest>> parsedOptions = Collections.emptyList();
        ParseResult<ParserTest> parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForParseError(parseResult, parsedOptions);
        assertThat("empty parsed parameters", parseResult.isParseError(), is(false));

        parsedOptions = Arrays.asList(new ParsedOption<ParserTest>(createMockOption("o"), null));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForParseError(parseResult, parsedOptions);
        assertThat("parsed parameters no error", parseResult.isParseError(), is(false));

        parsedOptions = Arrays.asList(new ParsedOption<ParserTest>(createMockOption("o"), null),
                new ParsedOption<ParserTest>("error"));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForParseError(parseResult, parsedOptions);
        assertThat("parsed parameters with error", parseResult.isParseError(), is(true));
    }

    @Test
    public void checkForDuplicateParameters() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        List<ParsedOption<ParserTest>> parsedOptions = Collections.emptyList();
        ParseResult<ParserTest> parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForDuplicateParameters(parseResult, parsedOptions);
        assertThat("empty parsed parameters", parseResult.isParseError(), is(false));

        parsedOptions = Arrays.asList(new ParsedOption<ParserTest>(createMockOption("o"), null),
                new ParsedOption<ParserTest>(createMockOptionProperty("P"), null),
                new ParsedOption<ParserTest>(createMockOptionProperty("P"), null),
                new ParsedOption<ParserTest>(createMockArguments(), null),
                new ParsedOption<ParserTest>(createMockArguments(), null));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForDuplicateParameters(parseResult, parsedOptions);
        assertThat("multiple option property and argument parsed parameters", parseResult.isParseError(),
                is(false));

        final ParserOption<ParserTest> mockOption = createMockOption("o");
        when(mockOption.toString()).thenReturn("duplicate");
        parsedOptions = Arrays.asList(new ParsedOption<ParserTest>(mockOption, null),
                new ParsedOption<ParserTest>(mockOption, null));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForDuplicateParameters(parseResult, parsedOptions);
        assertThat("duplicate option parsed parameters", parseResult.isParseError(), is(true));
    }

    @Test
    public void checkForRequiredParameters() {
        final ParserOption<ParserTest> mockOption = createMockOption("o");
        final ParserOption<ParserTest> mockArgument = createMockArguments();

        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters("+", "=");
        when(mockParserOptions.get()).thenReturn(Arrays.asList(mockOption, mockArgument));
        when(mockParserOptions.getArguments()).thenReturn(mockArgument);

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        ParseResult<ParserTest> parseResult = new ParseResult<ParserTest>(this);
        final List<ParsedOption<ParserTest>> parsedOptions = new LinkedList<ParsedOption<ParserTest>>();
        testCase.checkForRequiredParameters(parseResult, parsedOptions);
        assertThat("empty parsed parameters", parseResult.isParseError(), is(false));

        parsedOptions.add(new ParsedOption<ParserTest>(mockOption, null));
        parsedOptions.add(new ParsedOption<ParserTest>(mockArgument, null));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForRequiredParameters(parseResult, parsedOptions);
        assertThat("no required parameters", parseResult.isParseError(), is(false));

        parsedOptions.clear();
        when(mockOption.isRequired()).thenReturn(true);
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForRequiredParameters(parseResult, parsedOptions);
        assertThat("missing required parameter", parseResult.isParseError(), is(true));

        parsedOptions.add(new ParsedOption<ParserTest>(mockOption, null));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForRequiredParameters(parseResult, parsedOptions);
        assertThat("has required parameter", parseResult.isParseError(), is(false));

        when(mockArgument.isRequired()).thenReturn(true);
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForRequiredParameters(parseResult, parsedOptions);
        assertThat("missing required argument", parseResult.isParseError(), is(true));

        parsedOptions.add(new ParsedOption<ParserTest>(mockArgument, null));
        parseResult = new ParseResult<ParserTest>(this);
        testCase.checkForRequiredParameters(parseResult, parsedOptions);
        assertThat("has required argument", parseResult.isParseError(), is(false));
    }

    @Test
    public void isOption() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters("+");

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        assertThat("option", testCase.isOption("+option"), is(true));
        assertThat("not option", testCase.isOption("not"), is(false));
    }

    @Test
    public void getParsedParameters() {
        final ParserOption<ParserTest> mockOption = createMockOption("o");
        final ParserOption<ParserTest> mockOptionProperty = createMockOptionProperty("p");
        final ParserOption<ParserTest> mockArguments = createMockArguments();
        final List<ParserOption<ParserTest>> parserOptions = Arrays.asList(mockOption, mockOptionProperty,
                mockArguments);

        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters("+", "=");
        when(mockParserOptions.get()).thenReturn(parserOptions);
        when(mockParserOptions.get("o")).thenReturn(mockOption);
        when(mockParserOptions.get("p")).thenReturn(mockOptionProperty);
        when(mockParserOptions.get(ParserOptions.ARGUMENTS_KEY)).thenReturn(mockArguments);
        when(mockParserOptions.getArguments()).thenReturn(mockArguments);

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        List<ParsedOption<ParserTest>> parsedOptions = testCase.getParsedParameters(new String[0]);
        assertThat("empty parameters list size", parsedOptions.size(), is(0));

        parsedOptions = testCase.getParsedParameters(new String[] { "+bad" });
        assertThat("bad parameter list size", parsedOptions.size(), is(1));
        assertThat("bad parameter parse error", parsedOptions.get(0).isError(), is(true));

        parsedOptions = testCase.getParsedParameters(new String[] { "+o" });
        assertThat("parser parameter list size", parsedOptions.size(), is(1));
        assertThat("parser parameter parser parameter", parsedOptions.get(0).getParserOption(), is(mockOption));

        parsedOptions = testCase.getParsedParameters(new String[] { "+p" });
        assertThat("parser property list size", parsedOptions.size(), is(1));
        assertThat("parser property parser parameter", parsedOptions.get(0).getParserOption(),
                is(mockOptionProperty));

        parsedOptions = testCase.getParsedParameters(new String[] { "foobar" });
        assertThat("parser arguments list size", parsedOptions.size(), is(1));
        assertThat("parser arguments parser parameter", parsedOptions.get(0).getParserOption(), is(mockArguments));
    }

    @Test
    public void getParsedOption() {
        final ParserOption<ParserTest> mockedOption = createMockOption("o");
        when(mockedOption.hasValue()).thenReturn(true);
        final List<ParserOption<ParserTest>> parserOptions = Arrays.asList(mockedOption);

        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters("+", "=");
        when(mockParserOptions.get()).thenReturn(parserOptions);
        when(mockParserOptions.get("o")).thenReturn(mockedOption);

        final Queue<String> parameters = new LinkedList<String>();
        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        assertThat("empty queue", testCase.getParsedOption(parameters), nullValue());

        parameters.add("+o=foobar");
        ParsedOption<ParserTest> parsedOption = testCase.getParsedOption(parameters);
        assertThat("+o error", parsedOption.isError(), is(false));
        assertThat("+o parser option", parsedOption.getParserOption(), is(mockedOption));
        assertThat("+o value", parsedOption.getValue(), is("foobar"));
        assertThat("queue size after parsed parameter", parameters.size(), is(0));

        parameters.add("+o=");
        parsedOption = testCase.getParsedOption(parameters);
        assertThat("+o missing value error", parsedOption.isError(), is(false));
        assertThat("+o missing value parser option", parsedOption.getParserOption(), is(mockedOption));
        assertThat("+o missing value not null", parsedOption.getValue(), nullValue());
        assertThat("queue size after missing value", parameters.size(), is(0));

        parameters.add("+o");
        parsedOption = testCase.getParsedOption(parameters);
        assertThat("+o missing separator error", parsedOption.isError(), is(false));
        assertThat("+o missing separator parser option", parsedOption.getParserOption(), is(mockedOption));
        assertThat("+o missing separator not null", parsedOption.getValue(), nullValue());
        assertThat("queue size after missing separator", parameters.size(), is(0));

        when(mockParserOptions.getSeparator()).thenReturn(" ");
        parameters.add("+o");
        parameters.add("foobar");
        parsedOption = testCase.getParsedOption(parameters);
        assertThat("+o whitespace error", parsedOption.isError(), is(false));
        assertThat("+o whitespace parser option", parsedOption.getParserOption(), is(mockedOption));
        assertThat("+o whitespace value", parsedOption.getValue(), is("foobar"));
        assertThat("+o whitespace queue size", parameters.size(), is(0));

        when(mockParserOptions.getSeparator()).thenReturn(" ");
        parameters.add("+o");
        parsedOption = testCase.getParsedOption(parameters);
        assertThat("+o whitespace missing value error", parsedOption.isError(), is(false));
        assertThat("+o whitespace missing value parser option", parsedOption.getParserOption(), is(mockedOption));
        assertThat("+o whitespace missing value not null", parsedOption.getValue(), nullValue());
        assertThat("+o whitespace queue size after missing value", parameters.size(), is(0));

        when(mockParserOptions.getSeparator()).thenReturn("=");
        when(mockedOption.hasValue()).thenReturn(false);
        parameters.add("+o=value");
        parsedOption = testCase.getParsedOption(parameters);
        assertThat("+o with value error", parsedOption.isError(), is(true));
        assertThat("+o with value parser option", parsedOption.getParserOption(), is(mockedOption));
        assertThat("+o with value error is null", parsedOption.getError(), notNullValue());
        assertThat("+o whitespace queue size after missing value", parameters.size(), is(0));

        parameters.add("+o");
        parsedOption = testCase.getParsedOption(parameters);
        assertThat("+o with boolean", parsedOption.isError(), is(false));
        assertThat("+o with boolean parser option", parsedOption.getParserOption(), is(mockedOption));
        assertThat("+o with boolean value", parsedOption.getValue(), is(Boolean.TRUE.toString()));
        assertThat("+o whitespace queue size after missing value", parameters.size(), is(0));
    }

    @Test
    public void setOption() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();

        final ParserOption<ParserTest> mockOption = createMockOption("o");
        final String expectedValue = "value";

        new Parser<ParserTest>(mockParserOptions, createMockParserHelpFactory()).setOption(this, mockOption,
                expectedValue);
        verify(mockOption).setOption(this, expectedValue);
    }

    @Test(expected = IllegalArgumentException.class)
    public void setOptionWithOptionProperty() {
        final ParserOption<ParserTest> mockOptionProperty = createMockOptionProperty("");
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        new Parser<ParserTest>(mockParserOptions, createMockParserHelpFactory()).setOption(this, mockOptionProperty,
                "");
    }

    @Test(expected = IllegalArgumentException.class)
    public void setOptionWithArguments() {
        final ParserOption<ParserTest> mockArguments = createMockArguments();
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        new Parser<ParserTest>(mockParserOptions, createMockParserHelpFactory()).setOption(this, mockArguments, "");
    }

    @Test
    public void getParsedOptionProperty() {
        final ParserOption<ParserTest> mockOptionProperty = createMockOptionProperty("T");
        final List<ParserOption<ParserTest>> parserOptions = Arrays.asList(mockOptionProperty);

        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters("++");
        when(mockParserOptions.get()).thenReturn(parserOptions);
        when(mockParserOptions.get("T")).thenReturn(mockOptionProperty);

        final Queue<String> parameters = new LinkedList<String>();

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        assertThat("empty queue", testCase.getParsedOptionProperty(parameters), nullValue());

        final String expectedArgument = "argument";
        parameters.add(expectedArgument);
        assertThat("parsed parameter with argument", testCase.getParsedOptionProperty(parameters), nullValue());
        assertThat("queue size after parsed parameter error", parameters.size(), is(1));

        parameters.clear();
        parameters.add("++Tfoo=bar");
        final ParsedOption<ParserTest> parsedOption = testCase.getParsedOptionProperty(parameters);
        assertThat("ParsedOption error", parsedOption.isError(), is(false));
        assertThat("parser option", parsedOption.getParserOption(), is(mockOptionProperty));
        assertThat("value", parsedOption.getValue(), is("foo=bar"));
        assertThat("queue size after parsed parameter", parameters.size(), is(0));

        parameters.add("++Dfoo=bar");
        assertThat("property not matched", testCase.getParsedOptionProperty(parameters), nullValue());
    }

    @Test
    public void setOptionProperty() {
        final ParserOptions<ParserTest> mockParameters = createMockParserParameters();

        final ParserOption<ParserTest> mockOptionProperty = createMockOptionProperty("");
        final String property = "property";

        new Parser<ParserTest>(mockParameters, createMockParserHelpFactory()).setOptionProperty(this,
                mockOptionProperty, property);
        verify(mockOptionProperty).setOption(this, property);
    }

    @Test(expected = IllegalArgumentException.class)
    public void setOptionPropertyWithoutOptionPropertyParameter() {
        final ParserOption<ParserTest> mockArguments = createMockArguments();
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        new Parser<ParserTest>(mockParserOptions, createMockParserHelpFactory()).setOptionProperty(this,
                mockArguments, null);
    }

    @Test
    public void getParsedArgument() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();

        final Queue<String> parameters = new LinkedList<String>();

        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());
        assertThat("empty queue", testCase.getParsedArgument(parameters), nullValue());

        final String expectedParameter = "argument parameter";
        parameters.add(expectedParameter);
        ParsedOption<ParserTest> parsedOption = testCase.getParsedArgument(parameters);
        assertThat("parsed parameter error", parsedOption.isError(), is(true));
        assertThat("queue size after parsed parameter error", parameters.size(), is(0));

        final ParserOption<ParserTest> mockArguments = createMockArguments();
        when(mockParserOptions.getArguments()).thenReturn(mockArguments);

        final String remainingParameter = "remaining parameter";
        parameters.add(expectedParameter);
        parameters.add(remainingParameter);
        parsedOption = testCase.getParsedArgument(parameters);
        assertThat("parsed parameter not error", parsedOption.isError(), is(false));
        assertThat("parser parameter", parsedOption.getParserOption(), is(mockArguments));
        assertThat("value", parsedOption.getValue(), is(expectedParameter));
        assertThat("queue size", parameters.size(), is(1));
        assertThat("remaining parameter", parameters.remove(), is(remainingParameter));
    }

    @Test
    public void setArguments() {
        final ParserOption<ParserTest> mockArguments = createMockArguments();

        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        final String expectedArgument = "argument";

        new Parser<ParserTest>(mockParserOptions, createMockParserHelpFactory()).setArguments(this, mockArguments,
                expectedArgument);
        verify(mockArguments).setOption(this, expectedArgument);
    }

    @Test(expected = IllegalArgumentException.class)
    public void setArgumentsWithoutArgumentParameter() {
        final ParserOption<ParserTest> mockOption = createMockOption();
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        new Parser<ParserTest>(mockParserOptions, createMockParserHelpFactory()).setArguments(this, mockOption,
                null);
    }

    @Test
    public void hasHelpParameter() {
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions,
                createMockParserHelpFactory());

        final List<ParsedOption<ParserTest>> parsedOptions = new LinkedList<ParsedOption<ParserTest>>();
        assertThat("empty parsed parameters", testCase.hasHelpParameter(this, parsedOptions), is(false));

        ParsedOption<ParserTest> parsedOption = new ParsedOption<ParserTest>("error");
        parsedOptions.add(parsedOption);
        assertThat("parsed parameters with error", testCase.hasHelpParameter(this, parsedOptions), is(false));

        final ParserOption<ParserTest> mockOption = createMockOption("help");
        when(mockOption.isHelp()).thenReturn(true);

        parsedOptions.clear();
        parsedOption = new ParsedOption<ParserTest>(mockOption, null);
        parsedOptions.add(parsedOption);
        assertThat("parsed parameters with help", testCase.hasHelpParameter(this, parsedOptions), is(true));
        verify(mockOption).setOption(this, Boolean.TRUE.toString());
    }

    @Test
    public void createHelp() {

        final ParserOption<ParserTest> mockOption = createMockOption("o");
        final ParserOption<ParserTest> mockOptionProperty = createMockOptionProperty("P");
        final ParserOption<ParserTest> mockArguments = createMockArguments();

        final String prefix = "-";
        final String separator = "=";
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters(prefix, separator);
        when(mockParserOptions.getName()).thenReturn("testCase");
        when(mockParserOptions.get()).thenReturn(Arrays.asList(mockOption, mockOptionProperty, mockArguments));
        when(mockParserOptions.get("o")).thenReturn(mockOption);
        when(mockParserOptions.get("P")).thenReturn(mockOptionProperty);
        when(mockParserOptions.get(ParserOptions.ARGUMENTS_KEY)).thenReturn(mockArguments);
        when(mockParserOptions.getArguments()).thenReturn(mockArguments);

        final ParserHelpFactory<ParserTest> mockParserHelpFactory = createMockParserHelpFactory();

        final String header = "header";
        when(mockParserHelpFactory.getHeaderDescription(mockParserOptions)).thenReturn(header);
        when(mockParserHelpFactory.wrap(header, Parser.MINIMUM_WIDTH)).thenReturn("wrapped header");

        final String trailer = "trailer";
        when(mockParserHelpFactory.getTrailerDescription(mockParserOptions)).thenReturn(trailer);
        when(mockParserHelpFactory.wrap(trailer, Parser.MINIMUM_WIDTH)).thenReturn("wrapped trailer");

        final Pair<String, String> oneDescription = ImmutablePair.of("one", "one description");
        when(mockParserHelpFactory.getOptionDescription(prefix, separator, mockOption)).thenReturn(oneDescription);
        when(mockParserHelpFactory.hangingIndentWrap("one   one description", 6, Parser.MINIMUM_WIDTH))
                .thenReturn("option");

        final Pair<String, String> twoDescription = ImmutablePair.of("two", "two description");
        when(mockParserHelpFactory.getOptionDescription(prefix, separator, mockOptionProperty))
                .thenReturn(twoDescription);
        when(mockParserHelpFactory.hangingIndentWrap("two   two description", 6, Parser.MINIMUM_WIDTH))
                .thenReturn("property");
        when(mockParserHelpFactory.getOptionPropertyDescriptions(mockOptionProperty)).thenReturn(
                Arrays.asList(Pair.of("prop1", "prop1 description"), Pair.of("prop2", "prop2 description")));
        when(mockParserHelpFactory.hangingIndentWrap("      'prop1' prop1 description", 6, Parser.MINIMUM_WIDTH))
                .thenReturn("  prop1");
        when(mockParserHelpFactory.hangingIndentWrap("      'prop2' prop2 description", 6, Parser.MINIMUM_WIDTH))
                .thenReturn("  prop2");

        final Pair<String, String> threeDescription = ImmutablePair.of("argument", "three description");
        when(mockParserHelpFactory.getOptionDescription(prefix, separator, mockArguments))
                .thenReturn(threeDescription);
        when(mockParserHelpFactory.hangingIndentWrap("argument three description", 6, Parser.MINIMUM_WIDTH))
                .thenReturn("argument");

        final String expectedFullHelp = new StrBuilder().appendln("Usage: testCase unit test").appendNewLine()
                .appendln("wrapped header").appendNewLine().appendln("option").appendNewLine().appendln("property")
                .appendNewLine().appendln("  prop1").appendNewLine().appendln("  prop2").appendNewLine()
                .appendln("argument").appendNewLine().appendln("wrapped trailer").toString();
        final Parser<ParserTest> testCase = new Parser<ParserTest>(mockParserOptions, mockParserHelpFactory);
        testCase.setUsage("unit test");
        testCase.setWidth(Parser.MINIMUM_WIDTH);

        String help = testCase.createHelp();
        assertThat("full help", help, is(expectedFullHelp));

    }

    @Test
    public void toStringTest() {
        final String expectedToString = "expected toString";
        final ParserOptions<ParserTest> mockParserOptions = createMockParserParameters();
        when(mockParserOptions.toString()).thenReturn(expectedToString);

        assertThat("toString", new Parser<ParserTest>(mockParserOptions, createMockParserHelpFactory()).toString(),
                is(expectedToString));
    }

    @Test
    public void integrationHelpTest() {
        final Parser<SharedTestCase> parser = new Parser<SharedTestCase>(SharedTestCase.class);
        System.out.print(parser.createHelp());
    }

    @SuppressWarnings("unchecked")
    private ParserOption<ParserTest> createMockOption(final String... names) {
        final ParserOption<ParserTest> parserOption = mock(ParserOption.class);
        when(parserOption.getNames()).thenReturn(names);
        return parserOption;
    }

    @SuppressWarnings("unchecked")
    private ParserOption<ParserTest> createMockOptionProperty(final String name) {
        final ParserOption<ParserTest> parserOption = mock(ParserOption.class);
        when(parserOption.getNames()).thenReturn(new String[] { name });
        when(parserOption.isProperties()).thenReturn(true);
        return parserOption;
    }

    @SuppressWarnings("unchecked")
    private ParserOption<ParserTest> createMockArguments() {
        final ParserOption<ParserTest> parserOption = mock(ParserOption.class);
        when(parserOption.isArguments()).thenReturn(true);
        return parserOption;
    }

    @SuppressWarnings("unchecked")
    private ParserOptions<ParserTest> createMockParserParameters(final String... prefixAndSeparator) {
        final String prefix = (prefixAndSeparator == null || prefixAndSeparator.length < 1) ? null
                : prefixAndSeparator[0];
        final String separator = (prefixAndSeparator == null || prefixAndSeparator.length < 2) ? null
                : prefixAndSeparator[1];
        final ParserOptions<ParserTest> mockParserOptions = mock(ParserOptions.class);
        if (!StringUtils.isEmpty(prefix)) {
            when(mockParserOptions.getPrefix()).thenReturn(prefix);
        }
        if (!StringUtils.isEmpty(separator)) {
            when(mockParserOptions.getSeparator()).thenReturn(separator);
        }
        return mockParserOptions;
    }

    @SuppressWarnings("unchecked")
    private ParserHelpFactory<ParserTest> createMockParserHelpFactory() {
        return mock(ParserHelpFactory.class);
    }
}