001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.cli2.option; 018 019import java.io.BufferedReader; 020import java.io.IOException; 021import java.io.PrintWriter; 022import java.io.StringReader; 023import java.io.StringWriter; 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.HashSet; 027import java.util.List; 028import java.util.Set; 029 030import org.apache.commons.cli2.CLITestCase; 031import org.apache.commons.cli2.CommandLine; 032import org.apache.commons.cli2.DisplaySetting; 033import org.apache.commons.cli2.Group; 034import org.apache.commons.cli2.OptionException; 035import org.apache.commons.cli2.builder.ArgumentBuilder; 036import org.apache.commons.cli2.builder.DefaultOptionBuilder; 037import org.apache.commons.cli2.builder.GroupBuilder; 038import org.apache.commons.cli2.commandline.Parser; 039import org.apache.commons.cli2.util.HelpFormatter; 040 041 042/** 043 * Test to exercise nested groups developed to demonstrate bug 32533 044 */ 045public class NestedGroupTest extends CLITestCase { 046 private static final String[] EXPECTED_USAGE = new String[] { 047 "Usage: ", 048 " [-h -k -e|-d -b|-3 -f <file>|-s <string>] ", 049 "encryptionService ", 050 " -h (--help) Print this message ", 051 " -k (--key) Encryption key ", 052 " Action Action ", 053 " -e (--encrypt) Encrypt input ", 054 " -d (--decrypt) Decrypt input ", 055 " Algorithm Encryption Algorithm ", 056 " -b (--blowfish) Blowfish ", 057 " -3 (--3DES) Triple DES ", 058 " Input Input ", 059 " -f (--file) file Input file ", 060 " -s (--string) string Input string " 061 }; 062 063 final static DefaultOptionBuilder obuilder = new DefaultOptionBuilder(); 064 final static ArgumentBuilder abuilder = new ArgumentBuilder(); 065 final static GroupBuilder gbuilder = new GroupBuilder(); 066 067 static Group buildActionGroup() { 068 return gbuilder.withName("Action").withDescription("Action") 069 .withMinimum(1).withMaximum(1) 070 .withOption(obuilder.withId(5).withShortName("e") 071 .withLongName("encrypt") 072 .withDescription("Encrypt input") 073 .create()) 074 .withOption(obuilder.withId(6).withShortName("d") 075 .withLongName("decrypt") 076 .withDescription("Decrypt input") 077 .create()).create(); 078 } 079 080 static Group buildAlgorithmGroup() { 081 return gbuilder.withName("Algorithm") 082 .withDescription("Encryption Algorithm").withMaximum(1) 083 .withOption(obuilder.withId(0).withShortName("b") 084 .withLongName("blowfish") 085 .withDescription("Blowfish").create()) 086 .withOption(obuilder.withId(1).withShortName("3") 087 .withLongName("3DES") 088 .withDescription("Triple DES") 089 .create()).create(); 090 } 091 092 static Group buildInputGroup() { 093 return gbuilder.withName("Input").withDescription("Input").withMinimum(1) 094 .withMaximum(1) 095 .withOption(obuilder.withId(2).withShortName("f") 096 .withLongName("file") 097 .withDescription("Input file") 098 .withArgument(abuilder.withName( 099 "file").withMinimum(1).withMaximum(1).create()).create()) 100 .withOption(obuilder.withId(3).withShortName("s") 101 .withLongName("string") 102 .withDescription("Input string") 103 .withArgument(abuilder.withName( 104 "string").withMinimum(1).withMaximum(1).create()).create()) 105 .create(); 106 } 107 108 static Group buildEncryptionServiceGroup(Group[] nestedGroups) { 109 gbuilder.withName("encryptionService") 110 .withOption(obuilder.withId(4).withShortName("h") 111 .withLongName("help") 112 .withDescription("Print this message") 113 .create()).withOption(obuilder.withShortName( 114 "k").withLongName("key").withDescription("Encryption key") 115 .create()); 116 117 for (int i = 0; i < nestedGroups.length; i++) { 118 gbuilder.withOption(nestedGroups[i]); 119 } 120 121 return gbuilder.create(); 122 } 123 124 public void testNestedGroup() 125 throws OptionException { 126 final String[] args = { 127 "-eb", 128 "--file", 129 "/tmp/filename.txt" 130 }; 131 132 Group[] nestedGroups = { 133 buildActionGroup(), 134 buildAlgorithmGroup(), 135 buildInputGroup() 136 }; 137 138 Parser parser = new Parser(); 139 parser.setGroup(buildEncryptionServiceGroup(nestedGroups)); 140 141 CommandLine commandLine = parser.parse(args); 142 143 assertTrue("/tmp/filename.txt".equals(commandLine.getValue("-f"))); 144 assertTrue(commandLine.hasOption("-e")); 145 assertTrue(commandLine.hasOption("-b")); 146 assertFalse(commandLine.hasOption("-d")); 147 } 148 149 public void testNestedGroupHelp() { 150 checkNestedGroupHelp(new HelpFormatter(), EXPECTED_USAGE); 151 } 152 153 public void testNestedGroupHelpOptional() 154 { 155 HelpFormatter helpFormatter = new HelpFormatter(); 156 Set dispOptions = new HashSet(helpFormatter.getFullUsageSettings()); 157 dispOptions.add(DisplaySetting.DISPLAY_OPTIONAL_CHILD_GROUP); 158 List expLines = new ArrayList(Arrays.asList(EXPECTED_USAGE)); 159 expLines.set(1," [-h -k -e|-d [-b|-3] -f <file>|-s <string>] "); 160 helpFormatter.setFullUsageSettings(dispOptions); 161 checkNestedGroupHelp(helpFormatter, (String[]) expLines 162 .toArray(new String[expLines.size()])); 163 } 164 165 private void checkNestedGroupHelp(HelpFormatter helpFormatter, String[] expected) { 166 Group[] nestedGroups = { 167 buildActionGroup(), 168 buildAlgorithmGroup(), 169 buildInputGroup() 170 }; 171 helpFormatter.setGroup(buildEncryptionServiceGroup(nestedGroups)); 172 173 final StringWriter out = new StringWriter(); 174 helpFormatter.setPrintWriter(new PrintWriter(out)); 175 176 try { 177 helpFormatter.print(); 178 179 final BufferedReader bufferedReader = new BufferedReader(new StringReader( 180 out.toString())); 181 182 List actual = new ArrayList(expected.length); 183 String input; 184 185 while ((input = bufferedReader.readLine()) != null) { 186 actual.add(input); 187 } 188 189 // Show they are the same number of lines 190 assertEquals("Help text lines should be " + expected.length, 191 actual.size(), expected.length); 192 193 for (int i = 0; i < expected.length; i++) { 194 if (!expected[i].equals(actual.get(i))) { 195 for (int x = 0; x < expected.length; i++) { 196 System.out.println(" " + expected[i]); 197 System.out.println((expected[i].equals(actual.get(i)) 198 ? "== " 199 : "!= ") + actual.get(i)); 200 } 201 } 202 203 assertEquals(expected[i], actual.get(i)); 204 } 205 } 206 catch (IOException e) { 207 fail(e.getLocalizedMessage()); 208 } 209 } 210}