Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.tradefed.util;
     18 
     19 import com.android.tradefed.util.IEmail.Message;
     20 
     21 import junit.framework.TestCase;
     22 
     23 import java.io.ByteArrayOutputStream;
     24 import java.io.IOException;
     25 import java.io.InputStream;
     26 import java.io.OutputStream;
     27 import java.util.HashMap;
     28 import java.util.Map;
     29 
     30 public class EmailTest extends TestCase {
     31     private TestEmail mEmail = null;
     32 
     33     /**
     34      * A mock class to let us capture the data that is passed to the process on stdin
     35      */
     36     class TestProcess extends Process {
     37         OutputStream mOutputStream = null;
     38 
     39         TestProcess(OutputStream stream) {
     40             mOutputStream = stream;
     41         }
     42 
     43         @Override
     44         public OutputStream getOutputStream() {
     45             return mOutputStream;
     46         }
     47 
     48         // Add stubs for all the abstract methods
     49         class StubInputStream extends InputStream {
     50             @Override
     51             public int read() {return 0;}
     52         }
     53 
     54         @Override
     55         public void destroy() {}
     56         @Override
     57         public int exitValue() {return 0;}
     58         @Override
     59         public int waitFor() {return 0;}
     60         @Override
     61         public InputStream getInputStream() {
     62             return new StubInputStream();
     63         }
     64         @Override
     65         public InputStream getErrorStream() {
     66             return new StubInputStream();
     67         }
     68     }
     69 
     70     /**
     71      * A mock class that doesn't actually run anything, but instead returns a mock Process to
     72      * capture the data that would be passed _to_ the process on stdin.  Java's naming of these
     73      * methods is insane.
     74      */
     75     class TestEmail extends Email {
     76         ByteArrayOutputStream mOutputStream = null;
     77 
     78         TestEmail() {
     79             mOutputStream = new ByteArrayOutputStream();
     80         }
     81 
     82         public String getMailerData() {
     83             return mOutputStream.toString();
     84         }
     85 
     86         @Override
     87         Process run(String[] cmd) {
     88             return new TestProcess(mOutputStream);
     89         }
     90     }
     91 
     92     @Override
     93     public void setUp() throws Exception {
     94         super.setUp();
     95 
     96         mEmail = new TestEmail();
     97     }
     98 
     99     /**
    100      * Ensure that IllegalArgumentException is thrown when a message without a destination address
    101      * is sent.  Note that the address is not validated in any way (it could even be null)
    102      */
    103     public void testSendInval_destination() throws IOException {
    104         Message msg = new Message();
    105         msg.setSubject("subject");
    106         msg.setBody("body");
    107 
    108         try {
    109             mEmail.send(msg);
    110             fail("IllegalArgumentException not thrown");
    111         } catch (IllegalArgumentException e) {
    112             // expected
    113         }
    114     }
    115 
    116     /**
    117      * Ensure that IllegalArgumentException is thrown when a message without a subject is sent.
    118      */
    119     public void testSendInval_subject() throws IOException {
    120         Message msg = new Message("dest (at) ination.com", null, "body");
    121         try {
    122             mEmail.send(msg);
    123             fail("IllegalArgumentException not thrown");
    124         } catch (IllegalArgumentException e) {
    125             // expected
    126         }
    127     }
    128 
    129     /**
    130      * Ensure that IllegalArgumentException is thrown when a message without a body is sent.
    131      */
    132     public void testSendInval_body() throws IOException {
    133         Message msg = new Message("dest (at) ination.com", "subject", null);
    134         try {
    135             mEmail.send(msg);
    136             fail("IllegalArgumentException not thrown");
    137         } catch (IllegalArgumentException e) {
    138             // expected
    139         }
    140     }
    141 
    142     /**
    143      * Ensure that the email body is passed correctly to the mailer program's standard input
    144      */
    145     public void testSend_simple() throws IOException {
    146         final Message msg = new Message("dest (at) ination.com", "subject", "body");
    147         msg.setSender("or (at) igin.com");
    148         mEmail.send(msg);
    149 
    150         final Map<String, String> headers = new HashMap<String, String>();
    151         final String body = extractBody(mEmail.getMailerData(), headers);
    152 
    153         assertEquals("body", body);
    154         assertEquals("or (at) igin.com", headers.get("From"));
    155         assertEquals("dest (at) ination.com", headers.get("To"));
    156         assertEquals("subject", headers.get("Subject"));
    157         assertEquals(Message.PLAIN, headers.get("Content-type"));
    158         assertEquals(4, headers.size());
    159     }
    160 
    161     /**
    162      * Make sure that the HTML flag is passed along correctly
    163      */
    164     public void testSend_htmlEmail() throws IOException {
    165         final String expectedBody = "<html><body>le body</body></html>";
    166         final Message msg = new Message("dest (at) ination.com", "subject", expectedBody);
    167         msg.setHtml(true);
    168         mEmail.send(msg);
    169 
    170         final Map<String, String> headers = new HashMap<String, String>();
    171         final String body = extractBody(mEmail.getMailerData(), headers);
    172 
    173         assertEquals(expectedBody, body);
    174         assertEquals(Message.HTML, headers.get("Content-type"));
    175     }
    176 
    177     /**
    178      * Ensure that the email is sent correctly even if the message has an empty (but present)
    179      * subject
    180      */
    181     public void testSend_emptySubject() throws IOException {
    182         Message msg = new Message("dest (at) ination.com", "", "body");
    183         mEmail.send(msg);
    184         assertTrue("body".equals(extractBody(mEmail.getMailerData())));
    185     }
    186 
    187     /**
    188      * Ensure that the email is sent correctly even if the message has an empty (but present) body.
    189      */
    190     public void testSend_emptyBody() throws IOException {
    191         Message msg = new Message("dest (at) ination.com", "subject", "");
    192         mEmail.send(msg);
    193         assertTrue("".equals(extractBody(mEmail.getMailerData())));
    194     }
    195 
    196     /**
    197      * A short functional test to send an email somewhere.  Intended to be manually enabled with
    198      * appropriate email addresses to verify that Email functionality is working after changes.
    199      * Not enabled by default because the particular addresses to use will depend on the environment
    200      */
    201     @SuppressWarnings("unused")
    202     public void _manual_testFuncSend() throws IOException {
    203         final String sender = null;
    204         final String[] to = {"RECIPIENT"};
    205         final String[] cc = {};
    206         final String[] bcc = {};
    207 
    208         final String subject = "This is a TF test email";
    209         final String body = "<html><body><h1>What do we want?!</h1><h2>Time travel!</h2>" +
    210                 "When do we want it?<span style=\"display:block;color:blue;font-weight:bold\">" +
    211                 "it's irrelevant!</span></body></html>";
    212         final String contentType = Message.HTML;
    213 
    214         final Message msg = new Message();
    215         msg.setSubject(subject);
    216         msg.setBody(body);
    217         msg.setContentType(contentType);
    218         if (sender != null) {
    219             msg.setSender(sender);
    220         }
    221         for (String addr : to) {
    222             msg.addTo(addr);
    223         }
    224         for (String addr : cc) {
    225             msg.addCc(addr);
    226         }
    227         for (String addr : bcc) {
    228             msg.addBcc(addr);
    229         }
    230 
    231         final IEmail mailer = new Email();
    232         mailer.send(msg);
    233     }
    234 
    235     private String extractBody(String data) {
    236         return extractBody(data, null);
    237     }
    238 
    239     /**
    240      * Helper function that takes a full email and splits it into the headers and the body.
    241      * Optionally returns the headers via the second arg
    242      */
    243     private String extractBody(String data, Map<String, String> headers) {
    244         final String[] pieces = data.split(Email.CRLF + Email.CRLF, 2);
    245         if (headers != null) {
    246             for (String header : pieces[0].split(Email.CRLF)) {
    247                 final String[] halves = header.split(": ", 2);
    248                 final String key = halves[0];
    249                 final String val = halves.length == 2 ? halves[1] : null;
    250 
    251                 headers.put(key, val);
    252             }
    253         }
    254 
    255         if (pieces.length < 2) {
    256             return null;
    257         } else {
    258             return pieces[1];
    259         }
    260     }
    261 }
    262 
    263