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  package org.apache.commons.validator;
18  
19  import java.io.IOException;
20  
21  import junit.framework.Test;
22  import junit.framework.TestSuite;
23  
24  import org.xml.sax.SAXException;
25  
26  /***                                                       
27   * Performs Validation Test for e-mail validations.
28   *
29   *
30   * @version $Revision: 478560 $ $Date: 2006-11-23 13:09:27 +0000 (Thu, 23 Nov 2006) $
31   */
32  public class EmailTest extends TestCommon {
33  
34      /***
35       * The key used to retrieve the set of validation
36       * rules from the xml file.
37       */
38      protected static String FORM_KEY = "emailForm";
39  
40     /***
41      * The key used to retrieve the validator action.
42      */
43     protected static String ACTION = "email";
44  
45  
46     public EmailTest(String name) {                  
47         super(name);                                      
48     }                                                     
49  
50     /***
51      * Start the tests.
52      *
53      * @param theArgs the arguments. Not used
54      */
55     public static void main(String[] theArgs) {
56         junit.awtui.TestRunner.main(new String[] {EmailTest.class.getName()});
57     }
58  
59     /***
60      * @return a test suite (<code>TestSuite</code>) that includes all methods
61      *         starting with "test"
62      */
63     public static Test suite() {
64         // All methods starting with "test" will be executed in the test suite.
65         return new TestSuite(EmailTest.class);
66     }
67  
68     /***
69      * Load <code>ValidatorResources</code> from 
70      * validator-regexp.xml.
71      */
72     protected void setUp() throws IOException, SAXException {
73        loadResources("EmailTest-config.xml");
74     }
75  
76     protected void tearDown() {
77     }
78  
79     /***
80      * Tests the e-mail validation.
81      */
82     public void testEmail() throws ValidatorException {
83        // Create bean to run test on.
84        ValueBean info = new ValueBean();
85  
86        info.setValue("jsmith@apache.org");
87        valueTest(info, true);
88     }
89      
90     /***
91      * Tests the email validation with numeric domains.
92      */
93      public void testEmailWithNumericAddress() throws ValidatorException {
94          ValueBean info = new ValueBean();
95          info.setValue("someone@[216.109.118.76]");
96          valueTest(info, true);
97          info.setValue("someone@yahoo.com");
98          valueTest(info, true);
99      }
100 
101     /***
102      * Tests the e-mail validation.
103      */
104     public void testEmailExtension() throws ValidatorException {
105         // Create bean to run test on.
106         ValueBean info = new ValueBean();
107 
108         info.setValue("jsmith@apache.org");
109         valueTest(info, true);
110 
111         info.setValue("jsmith@apache.com");
112         valueTest(info, true);
113 
114         info.setValue("jsmith@apache.net");
115         valueTest(info, true);
116 
117         info.setValue("jsmith@apache.info");
118         valueTest(info, true);
119 
120         info.setValue("jsmith@apache.");
121         valueTest(info, false);
122 
123         info.setValue("jsmith@apache.c");
124         valueTest(info, false);
125         
126         info.setValue("someone@yahoo.museum");
127         valueTest(info, true);
128         
129         info.setValue("someone@yahoo.mu-seum");
130         valueTest(info, false);
131     }
132 
133    /***
134     * <p>Tests the e-mail validation with a dash in 
135     * the address.</p>
136     */
137    public void testEmailWithDash() throws ValidatorException {
138       // Create bean to run test on.
139       ValueBean info = new ValueBean();
140 
141       info.setValue("andy.noble@data-workshop.com");
142       valueTest(info, true);
143 
144       info.setValue("andy-noble@data-workshop.-com");
145        valueTest(info, false);
146        info.setValue("andy-noble@data-workshop.c-om");
147        valueTest(info,false);
148        info.setValue("andy-noble@data-workshop.co-m");
149        valueTest(info, false);
150 
151 
152    }
153 
154    /***
155     * Tests the e-mail validation with a dot at the end of 
156     * the address.
157     */
158    public void testEmailWithDotEnd() throws ValidatorException {
159       // Create bean to run test on.
160       ValueBean info = new ValueBean();
161 
162       info.setValue("andy.noble@data-workshop.com.");
163       valueTest(info, false);
164 
165    }
166 
167     /***
168      * Tests the e-mail validation with an RCS-noncompliant character in
169      * the address.
170      */
171     public void testEmailWithBogusCharacter() throws ValidatorException {
172         // Create bean to run test on.
173         ValueBean info = new ValueBean();
174 
175         info.setValue("andy.noble@\u008fdata-workshop.com");
176         valueTest(info, false);
177     
178         // The ' character is valid in an email username.
179         info.setValue("andy.o'reilly@data-workshop.com");
180         valueTest(info, true);
181         
182         // But not in the domain name.
183         info.setValue("andy@o'reilly.data-workshop.com");
184         valueTest(info, false);
185 
186         info.setValue("foo+bar@i.am.not.in.us.example.com");
187         valueTest(info, true);
188     }
189    
190    /***
191     * Tests the email validation with commas.
192     */
193     public void testEmailWithCommas() throws ValidatorException {
194         ValueBean info = new ValueBean();
195         info.setValue("joeblow@apa,che.org");
196         valueTest(info, false);
197         info.setValue("joeblow@apache.o,rg");
198         valueTest(info, false);
199         info.setValue("joeblow@apache,org");
200         valueTest(info, false);
201 
202     }
203    
204    /***
205     * Tests the email validation with spaces.
206     */
207     public void testEmailWithSpaces() throws ValidatorException {
208         ValueBean info = new ValueBean();
209         info.setValue("joeblow @apache.org");
210         valueTest(info, false);
211         info.setValue("joeblow@ apache.org");
212         valueTest(info, false);
213         info.setValue(" joeblow@apache.org");
214         valueTest(info, true);
215         info.setValue("joeblow@apache.org ");
216         valueTest(info, true);
217         info.setValue("joe blow@apache.org ");
218         valueTest(info, false);
219         info.setValue("joeblow@apa che.org ");
220         valueTest(info, false);
221 
222     }
223 
224    /***
225     * Tests the email validation with ascii control characters.
226     * (i.e. Ascii chars 0 - 31 and 127)
227     */
228     public void testEmailWithControlChars() throws ValidatorException {
229         EmailValidator validator = new EmailValidator();
230         for (char c = 0; c < 32; c++) {
231             assertFalse("Test control char " + ((int)c), validator.isValid("foo" + c + "bar@domain.com"));
232         }
233         assertFalse("Test control char 127", validator.isValid("foo" + ((char)127) + "bar@domain.com"));
234     }
235 
236     /***
237      * Write this test according to parts of RFC, as opposed to the type of character
238      * that is being tested.
239      *
240      * <p><b>FIXME</b>: This test fails so disable it with a leading _ for 1.1.4 release.
241      * The real solution is to fix the email parsing.
242      *
243      * @throws ValidatorException
244      */
245     public void _testEmailUserName() throws ValidatorException {
246         ValueBean info = new ValueBean();
247         info.setValue("joe1blow@apache.org");
248         valueTest(info, true);
249         info.setValue("joe$blow@apache.org");
250         valueTest(info, true);
251         info.setValue("joe-@apache.org");
252         valueTest(info, true);
253         info.setValue("joe_@apache.org");
254         valueTest(info, true);
255 
256         //UnQuoted Special characters are invalid
257 
258         info.setValue("joe.@apache.org");
259         valueTest(info, false);
260         info.setValue("joe+@apache.org");
261         valueTest(info, false);
262         info.setValue("joe!@apache.org");
263         valueTest(info, false);
264         info.setValue("joe*@apache.org");
265         valueTest(info, false);
266         info.setValue("joe'@apache.org");
267         valueTest(info, false);
268         info.setValue("joe(@apache.org");
269         valueTest(info, false);
270         info.setValue("joe)@apache.org");
271         valueTest(info, false);
272         info.setValue("joe,@apache.org");
273         valueTest(info, false);
274         info.setValue("joe%45@apache.org");
275         valueTest(info, false);
276         info.setValue("joe;@apache.org");
277         valueTest(info, false);
278         info.setValue("joe?@apache.org");
279         valueTest(info, false);
280         info.setValue("joe&@apache.org");
281         valueTest(info, false);
282         info.setValue("joe=@apache.org");
283         valueTest(info, false);
284 
285         //Quoted Special characters are valid
286         info.setValue("\"joe.\"@apache.org");
287         valueTest(info, true);
288         info.setValue("\"joe+\"@apache.org");
289         valueTest(info, true);
290         info.setValue("\"joe!\"@apache.org");
291         valueTest(info, true);
292         info.setValue("\"joe*\"@apache.org");
293         valueTest(info, true);
294         info.setValue("\"joe'\"@apache.org");
295         valueTest(info, true);
296         info.setValue("\"joe(\"@apache.org");
297         valueTest(info, true);
298         info.setValue("\"joe)\"@apache.org");
299         valueTest(info, true);
300         info.setValue("\"joe,\"@apache.org");
301         valueTest(info, true);
302         info.setValue("\"joe%45\"@apache.org");
303         valueTest(info, true);
304         info.setValue("\"joe;\"@apache.org");
305         valueTest(info, true);
306         info.setValue("\"joe?\"@apache.org");
307         valueTest(info, true);
308         info.setValue("\"joe&\"@apache.org");
309         valueTest(info, true);
310         info.setValue("\"joe=\"@apache.org");
311         valueTest(info, true);
312 
313     }
314 
315     /***
316      * These test values derive directly from RFC 822 &
317      * Mail::RFC822::Address & RFC::RFC822::Address perl test.pl
318      * For traceability don't combine these test values with other tests.
319      */
320     TestPair[] testEmailFromPerl = {
321         new TestPair("abigail@example.com", true),
322         new TestPair("abigail@example.com ", true),
323         new TestPair(" abigail@example.com", true),
324         new TestPair("abigail @example.com ", true),
325         new TestPair("*@example.net", true),
326         new TestPair("\"//\"\"@foo.bar", true),
327         new TestPair("fred&barny@example.com", true),
328         new TestPair("---@example.com", true),
329         new TestPair("foo-bar@example.net", true),
330         new TestPair("\"127.0.0.1\"@[127.0.0.1]", true),
331         new TestPair("Abigail <abigail@example.com>", true),
332         new TestPair("Abigail<abigail@example.com>", true),
333         new TestPair("Abigail<@a,@b,@c:abigail@example.com>", true),
334         new TestPair("\"This is a phrase\"<abigail@example.com>", true),
335         new TestPair("\"Abigail \"<abigail@example.com>", true),
336         new TestPair("\"Joe & J. Harvey\" <example @Org>", true),
337         new TestPair("Abigail <abigail @ example.com>", true),
338         new TestPair("Abigail made this <  abigail   @   example  .    com    >", true),
339         new TestPair("Abigail(the bitch)@example.com", true),
340         new TestPair("Abigail <abigail @ example . (bar) com >", true),
341         new TestPair("Abigail < (one)  abigail (two) @(three)example . (bar) com (quz) >", true),
342         new TestPair("Abigail (foo) (((baz)(nested) (comment)) ! ) < (one)  abigail (two) @(three)example . (bar) com (quz) >", true),
343         new TestPair("Abigail <abigail(fo//(o)@example.com>", true),
344         new TestPair("Abigail <abigail(fo//)o)@example.com> ", true),
345         new TestPair("(foo) abigail@example.com", true),
346         new TestPair("abigail@example.com (foo)", true),
347         new TestPair("\"Abi//\"gail\" <abigail@example.com>", true),
348         new TestPair("abigail@[example.com]", true),
349         new TestPair("abigail@[exa//[ple.com]", true),
350         new TestPair("abigail@[exa//]ple.com]", true),
351         new TestPair("\":sysmail\"@  Some-Group. Some-Org", true),
352         new TestPair("Muhammed.(I am  the greatest) Ali @(the)Vegas.WBA", true),
353         new TestPair("mailbox.sub1.sub2@this-domain", true),
354         new TestPair("sub-net.mailbox@sub-domain.domain", true),
355         new TestPair("name:;", true),
356         new TestPair("':;", true),
357         new TestPair("name:   ;", true),
358         new TestPair("Alfred Neuman <Neuman@BBN-TENEXA>", true),
359         new TestPair("Neuman@BBN-TENEXA", true),
360         new TestPair("\"George, Ted\" <Shared@Group.Arpanet>", true),
361         new TestPair("Wilt . (the  Stilt) Chamberlain@NBA.US", true),
362         new TestPair("Cruisers:  Port@Portugal, Jones@SEA;", true),
363         new TestPair("$@[]", true),
364         new TestPair("*()@[]", true),
365         new TestPair("\"quoted ( brackets\" ( a comment )@example.com", true),
366         new TestPair("\"Joe & J. Harvey\"//x0D//x0A     <ddd//@ Org>", true),
367         new TestPair("\"Joe &//x0D//x0A J. Harvey\" <ddd //@ Org>", true),
368         new TestPair("Gourmets:  Pompous Person <WhoZiWhatZit//@Cordon-Bleu>,//x0D//x0A" +
369             "        Childs//@WGBH.Boston, \"Galloping Gourmet\"//@//x0D//x0A" +
370             "        ANT.Down-Under (Australian National Television),//x0D//x0A" +
371             "        Cheapie//@Discount-Liquors;", true),
372         new TestPair("   Just a string", false),
373         new TestPair("string", false),
374         new TestPair("(comment)", false),
375         new TestPair("()@example.com", false),
376         new TestPair("fred(&)barny@example.com", false),
377         new TestPair("fred// barny@example.com", false),
378         new TestPair("Abigail <abi gail @ example.com>", false),
379         new TestPair("Abigail <abigail(fo(o)@example.com>", false),
380         new TestPair("Abigail <abigail(fo)o)@example.com>", false),
381         new TestPair("\"Abi\"gail\" <abigail@example.com>", false),
382         new TestPair("abigail@[exa]ple.com]", false),
383         new TestPair("abigail@[exa[ple.com]", false),
384         new TestPair("abigail@[exaple].com]", false),
385         new TestPair("abigail@", false),
386         new TestPair("@example.com", false),
387         new TestPair("phrase: abigail@example.com abigail@example.com ;", false),
388         new TestPair("invalid£char@example.com", false)
389     };
390 
391     /***
392      * Write this test based on perl Mail::RFC822::Address
393      * which takes its example email address directly from RFC822
394      * 
395      * @throws ValidatorException
396      * 
397      * FIXME This test fails so disable it with a leading _ for 1.1.4 release.
398      * The real solution is to fix the email parsing.
399      */
400     public void _testEmailFromPerl() throws ValidatorException {
401         ValueBean info = new ValueBean();
402         for (int index = 0; index < testEmailFromPerl.length; index++) {
403             info.setValue(testEmailFromPerl[index].item);
404             valueTest(info, testEmailFromPerl[index].valid);
405         }
406     }
407 
408    /***
409     * Utlity class to run a test on a value.
410     *
411     * @param info	Value to run test on.
412     * @param passed	Whether or not the test is expected to pass.
413     */
414    private void valueTest(ValueBean info, boolean passed) throws ValidatorException {
415       // Construct validator based on the loaded resources 
416       // and the form key
417       Validator validator = new Validator(resources, FORM_KEY);
418       // add the name bean to the validator as a resource 
419       // for the validations to be performed on.
420       validator.setParameter(Validator.BEAN_PARAM, info);
421 
422       // Get results of the validation.
423       ValidatorResults results = null;
424       
425       // throws ValidatorException, 
426       // but we aren't catching for testing 
427       // since no validation methods we use 
428       // throw this
429       results = validator.validate();
430       
431       assertNotNull("Results are null.", results);
432       
433       ValidatorResult result = results.getValidatorResult("value");
434 
435       assertNotNull(ACTION + " value ValidatorResult should not be null.", result);
436       assertTrue("Value "+info.getValue()+" ValidatorResult should contain the '" + ACTION +"' action.", result.containsAction(ACTION));
437       assertTrue("Value "+info.getValue()+"ValidatorResult for the '" + ACTION +"' action should have " + (passed ? "passed" : "failed") + ".", (passed ? result.isValid(ACTION) : !result.isValid(ACTION)));
438     }
439 }