1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.beanutils.converters;
19  
20  import org.apache.commons.beanutils.ConvertUtils;
21  import org.apache.commons.beanutils.ConversionException;
22  
23  import junit.framework.TestCase;
24  
25  /***
26   * Test conversions of String[]->boolean[] and String->boolean[].
27   *
28   * <p>Note that the tests here don't rigorously test conversions of individual
29   * strings to booleans, as the BooleanArrayConverter class uses a
30   * BooleanConverter instance to do those conversions, and the BooleanConverter
31   * class has its own unit tests. Here, the tests focus on the array-related
32   * behaviour.</p>
33   */
34  public class BooleanArrayConverterTestCase extends TestCase {
35  
36      public static final String[] STANDARD_TRUES = new String[] {
37              "yes", "y", "true", "on", "1"
38          };
39  
40      public static final String[] STANDARD_FALSES = new String[] {
41              "no", "n", "false", "off", "0"
42          };
43  
44  
45      public BooleanArrayConverterTestCase(String name) {
46          super(name);
47      }
48  
49      /***
50       * Check that an object of type String[] with valid boolean string
51       * values gets converted nicely.
52       */
53      public void testStandardStringArrayConversion() {
54          String[] values = {
55              "true", "false", 
56              "yes", "no",
57              "y", "n",
58              "1", "0",
59          };
60          
61          BooleanArrayConverter converter = new BooleanArrayConverter();
62          boolean[] results = (boolean[]) converter.convert(null, values);
63  
64          assertNotNull(results);
65          assertEquals(8, results.length);
66          assertTrue(results[0]);
67          assertFalse(results[1]);
68          assertTrue(results[2]);
69          assertFalse(results[3]);
70          assertTrue(results[4]);
71          assertFalse(results[5]);
72          assertTrue(results[6]);
73          assertFalse(results[7]);
74      }
75  
76      /***
77       * Check that an object whose toString method returns a list of boolean
78       * values gets converted nicely.
79       */
80      public void testStandardStringConversion() {
81          BooleanArrayConverter converter = new BooleanArrayConverter();
82  
83          StringBuffer input = new StringBuffer();
84          boolean[] results;
85  
86          // string has {}
87          input.setLength(0);
88          input.append("{true, 'yes', Y, 1, 'FALSE', \"no\", 'n', 0}");
89          results = (boolean[]) converter.convert(null, input);
90  
91          assertNotNull(results);
92          assertEquals(8, results.length);
93          assertTrue(results[0]);
94          assertTrue(results[1]);
95          assertTrue(results[2]);
96          assertTrue(results[3]);
97          assertFalse(results[4]);
98          assertFalse(results[5]);
99          assertFalse(results[6]);
100         assertFalse(results[7]);
101 
102         // string does not have {}
103         input.setLength(0);
104         input.append("'falsE', 'no', 'N', 0, \"truE\", yeS, 'y', '1'");
105         results = (boolean[]) converter.convert(null, input);
106 
107         assertNotNull(results);
108         assertEquals(8, results.length);
109         assertFalse(results[0]);
110         assertFalse(results[1]);
111         assertFalse(results[2]);
112         assertFalse(results[3]);
113         assertTrue(results[4]);
114         assertTrue(results[5]);
115         assertTrue(results[6]);
116         assertTrue(results[7]);
117 
118         // string has only one element, non-quoted
119         input.setLength(0);
120         input.append("y");
121         results = (boolean[]) converter.convert(null, input);
122 
123         assertNotNull(results);
124         assertEquals(1, results.length);
125         assertTrue(results[0]);
126 
127         // string has only one element, quoted with ".
128         input.setLength(0);
129         input.append("\"1\"");
130         results = (boolean[]) converter.convert(null, input);
131 
132         assertNotNull(results);
133         assertEquals(1, results.length);
134         assertTrue(results[0]);
135 
136         // string has only one element, quoted with '
137         // Here we also pass an object of type String rather than the 
138         // StringBuffer
139         results = (boolean[]) converter.convert(null, "'yes'");
140 
141         assertNotNull(results);
142         assertEquals(1, results.length);
143         assertTrue(results[0]);
144 
145     }
146 
147     /***
148      * Check that the user can specify non-standard true/false values by
149      * providing a customised BooleanConverter.
150      */
151     public void testAdditionalStrings() {
152         String[] trueStrings = {"sure"};
153         String[] falseStrings = {"nope"};
154         BooleanConverter bc = new BooleanConverter(
155             trueStrings, falseStrings, BooleanConverter.NO_DEFAULT);
156         BooleanArrayConverter converter = new BooleanArrayConverter(
157             bc, BooleanArrayConverter.NO_DEFAULT);
158         
159         boolean[] results = (boolean[]) converter.convert(null, "NOPE, sure, sure");
160         assertNotNull(results);
161         assertEquals(3, results.length);
162         assertFalse(results[0]);
163         assertTrue(results[1]);
164         assertTrue(results[2]);
165         
166         try {
167             // the literal string 'true' should no longer be recognised as
168             // a true value..
169             converter.convert(null, "true");
170             fail("Converting invalid string should have generated an exception");
171         } catch(Exception ex) {
172             // ok, expected
173         }
174     }
175 
176     /***
177      * Check that when the input string cannot be split into a String[], and
178      * there is no default value then an exception is thrown.
179      */
180     public void testInvalidStringWithoutDefault() {
181         BooleanArrayConverter converter = new BooleanArrayConverter();
182         try {
183             converter.convert(null, "true!");
184             fail("Converting invalid string should have generated an exception");
185         } catch (ConversionException expected) {
186             // Exception is successful test
187         }
188     }
189 
190     /***
191      * Check that when the input string cannot be split into a String[], and
192      * there is a default value then that default is returned.
193      */
194     public void testInvalidStringWithDefault() {
195         boolean[] defaults = new boolean[1];
196         BooleanArrayConverter converter = new BooleanArrayConverter(defaults);
197         Object o = converter.convert(null, "true!");
198         assertSame("Unexpected object returned for failed conversion", o, defaults);
199     }
200 
201     /***
202      * Check that when one of the elements in a comma-separated string is not
203      * a valid boolean, and there is no default value then an exception is thrown.
204      */
205     public void testInvalidElementWithoutDefault() {
206         BooleanArrayConverter converter = new BooleanArrayConverter();
207         try {
208             converter.convert(null, "true,bogus");
209             fail("Converting invalid string should have generated an exception");
210         } catch (ConversionException expected) {
211             // Exception is successful test
212         }
213     }
214 
215     /***
216      * Check that when one of the elements in a comma-separated string is not
217      * a valid boolean, and there is a default value then the default value
218      * is returned.
219      * <p>
220      * Note that the default value is for the complete array object returned,
221      * not for the failed element.
222      */
223     public void testInvalidElementWithDefault() {
224         boolean[] defaults = new boolean[1];
225         BooleanArrayConverter converter = new BooleanArrayConverter(defaults);
226         Object o = converter.convert(null, "true,bogus");
227         assertSame("Unexpected object returned for failed conversion", o, defaults);
228     }
229     
230     /***
231      * Check that when a custom BooleanConverter is used, and that converter
232      * has a (per-element) default, then that element (and just that element)
233      * is assigned the default value.
234      * <p>
235      * With the standard BooleanArrayConverter, if <i>any</i> of the elements
236      * in the array are bad, then the array-wide default value is returned.
237      * However by specifying a custom BooleanConverter which has a per-element
238      * default, the unrecognised elements get that per-element default but the
239      * others are converted as expected.
240      */
241     public void testElementDefault() {
242         boolean[] defaults = new boolean[1];
243         BooleanConverter bc = new BooleanConverter(Boolean.TRUE);
244         BooleanArrayConverter converter = new BooleanArrayConverter(bc, defaults);
245         boolean[] results = (boolean[]) converter.convert(null, "true,bogus");
246         
247         assertEquals(2, results.length);
248         assertTrue(results[0]);
249         assertTrue(results[1]);
250     }
251     
252     /***
253      * Check that registration of a custom converter works.
254      */
255     public void testRegistration() {
256         String[] trueStrings = {"sure"};
257         String[] falseStrings = {"nope"};
258         BooleanConverter bc = new BooleanConverter(
259             trueStrings, falseStrings, BooleanConverter.NO_DEFAULT);
260 
261         BooleanArrayConverter converter = new BooleanArrayConverter(
262             bc, BooleanArrayConverter.NO_DEFAULT);
263             
264         ConvertUtils.register(converter, BooleanArrayConverter.MODEL);
265         boolean[] sample = new boolean[0];
266         boolean[] results = (boolean[]) ConvertUtils.convert("sure,nope", sample.getClass());
267         
268         assertEquals(2, results.length);
269         assertTrue(results[0]);
270         assertFalse(results[1]);
271     }
272 }