    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 }