| /* |
| 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 |
| |
| https://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.commons.cli; |
| |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertFalse; |
| import static org.junit.jupiter.api.Assertions.assertThrows; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.stream.Stream; |
| |
| import org.junit.jupiter.api.BeforeAll; |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.params.ParameterizedTest; |
| import org.junit.jupiter.params.provider.Arguments; |
| import org.junit.jupiter.params.provider.MethodSource; |
| |
| class OptionValidatorTest { |
| |
| /* |
| * Exemplars of various types of characters |
| */ |
| |
| private static final String LETTERS = "a\u00D1"; // a and Ñ |
| |
| // '\u0660' through '\u0669', Arabic-Indic digits, '\u06F0' through '\u06F9', |
| // Extended Arabic-Indic digits |
| // '\u0966' through '\u096F', Devanagari digits, '\uFF10' through '\uFF19', |
| // Fullwidth digits |
| private static final String DIGITS = "1\u0661\u06f2\u0968\uFF14"; |
| |
| private static final String CURRENCY = "€$"; |
| |
| // this is the complete puncutation set do not modify it as Character.isJavaIdentifierPart filters |
| // the good and bad ones out in the setup. |
| private static final String PUNCTUATION = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; |
| |
| private static final String COMBINING_MARK = "\u0303"; |
| |
| private static final String NON_SPACING_MARK = "\u0CBF"; |
| |
| private static final String IDENTIFIER_IGNORABLE = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008"; |
| |
| private static String acceptablePunctuation; |
| |
| private static String notAcceptablePunctuation; |
| |
| private static String additionalOptonChars; |
| private static String additionalLongChars; |
| |
| private static String firstChars; |
| private static String notFirstChars; |
| |
| private static String restChars; |
| private static String notRestChars; |
| |
| private static Stream<Arguments> optionParameters() { |
| |
| final List<Arguments> args = new ArrayList<>(); |
| |
| args.add(Arguments.of("CamelCase", true, "Camel case error")); |
| args.add(Arguments.of("Snake_case", true, "Snake case error")); |
| args.add(Arguments.of("_leadingUnderscore", true, "Leading underscore error")); |
| args.add(Arguments.of("kabob-case", true, "Kabob case error")); |
| args.add(Arguments.of("-leadingDash", false, "Leading dash error")); |
| args.add(Arguments.of("lowercase", true, "Lower case error")); |
| args.add(Arguments.of("UPPERCASE", true, "Upper case error")); |
| |
| // build passing test cases |
| for (final char c : firstChars.toCharArray()) { |
| final String s = String.format("%sMoreText", c); |
| args.add(Arguments.of(s, true, String.format("testing: First character '%s'", c))); |
| } |
| |
| for (final char c : restChars.toCharArray()) { |
| final String s = String.format("Some%sText", c); |
| args.add(Arguments.of(s, true, String.format("testing: Middle character '%s'", c))); |
| } |
| |
| // build failing test cases |
| for (final char c : notFirstChars.toCharArray()) { |
| final String s = String.format("%sMoreText", c); |
| args.add(Arguments.of(s, false, String.format("testing: Bad first character '%s'", c))); |
| } |
| |
| for (final char c : notRestChars.toCharArray()) { |
| final String s = String.format("Some%sText", c); |
| args.add(Arguments.of(s, false, String.format("testing: Bad middle character '%s'", c))); |
| } |
| |
| return args.stream(); |
| } |
| |
| @BeforeAll |
| public static void setup() { |
| StringBuilder sb = new StringBuilder(); |
| final StringBuilder sb2 = new StringBuilder(); |
| int idx; |
| |
| for (final char c : PUNCTUATION.toCharArray()) { |
| if (Character.isJavaIdentifierPart(c)) { |
| sb.append(c); |
| } else { |
| sb2.append(c); |
| } |
| } |
| acceptablePunctuation = sb.toString(); |
| notAcceptablePunctuation = sb2.toString(); |
| |
| sb = new StringBuilder(); |
| for (final char c : OptionValidator.ADDITIONAL_LONG_CHARS) { |
| sb.append(c); |
| } |
| additionalLongChars = sb.toString(); |
| |
| sb = new StringBuilder(); |
| for (final char c : OptionValidator.ADDITIONAL_OPTION_CHARS) { |
| sb.append(c); |
| } |
| additionalOptonChars = sb.toString(); |
| |
| final String javaIdentifierPart = LETTERS + DIGITS + CURRENCY + acceptablePunctuation + COMBINING_MARK |
| + NON_SPACING_MARK + IDENTIFIER_IGNORABLE; |
| |
| firstChars = additionalOptonChars + javaIdentifierPart; |
| |
| sb = new StringBuilder(notAcceptablePunctuation).append(additionalLongChars); |
| for (final char c : OptionValidator.ADDITIONAL_OPTION_CHARS) { |
| while ((idx = sb.indexOf(Character.toString(c))) > -1) { |
| sb.deleteCharAt(idx); |
| } |
| } |
| notFirstChars = sb.toString(); |
| |
| restChars = additionalLongChars + javaIdentifierPart; |
| sb = new StringBuilder(notAcceptablePunctuation).append(additionalOptonChars); |
| for (final char c : OptionValidator.ADDITIONAL_LONG_CHARS) { |
| while ((idx = sb.indexOf(Character.toString(c))) > -1) { |
| sb.deleteCharAt(idx); |
| } |
| } |
| notRestChars = sb.toString(); |
| |
| } |
| |
| @Test |
| void testExclusivity() { |
| /* since we modify acceptable chars by add and removing ADDITIONAL* chars we must verify that they do not exist in the |
| * base javaIdentiferPart that is used in OptionValidator to validate basic characters */ |
| for (final char c : OptionValidator.ADDITIONAL_LONG_CHARS) { |
| assertFalse(Character.isJavaIdentifierPart(c), () -> String.format("'%s' should not be in 'ADDITIONAL_LONG_CHARS", c)); |
| } |
| for (final char c : OptionValidator.ADDITIONAL_OPTION_CHARS) { |
| assertFalse(Character.isJavaIdentifierPart(c), () -> String.format("'%s' should not be in 'ADDITIONAL_OPTION_CHARS", c)); |
| } |
| } |
| |
| @ParameterizedTest(name = "{2}") |
| @MethodSource("optionParameters") |
| void testValidate(final String str, final boolean expected, final String name) { |
| if (expected) { |
| assertEquals(str, OptionValidator.validate(str)); |
| } else { |
| assertThrows(IllegalArgumentException.class, () -> OptionValidator.validate(str)); |
| } |
| } |
| } |