1/*
2 * Copyright 2007 the original author or authors.
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 */
16package org.mockftpserver.test;
17
18import junit.framework.TestCase;
19import org.slf4j.Logger;
20import org.slf4j.LoggerFactory;
21import org.easymock.MockControl;
22import org.mockftpserver.core.MockFtpServerException;
23import org.mockftpserver.core.util.Assert;
24import org.mockftpserver.core.util.AssertFailedException;
25
26import java.io.File;
27import java.net.InetAddress;
28import java.net.UnknownHostException;
29import java.util.ArrayList;
30import java.util.Arrays;
31import java.util.Collections;
32import java.util.HashMap;
33import java.util.HashSet;
34import java.util.Iterator;
35import java.util.List;
36import java.util.Map;
37import java.util.Set;
38
39/**
40 * Abstract superclass for all project test classes
41 *
42 * @author Chris Mair
43 * @version $Revision$ - $Date$
44 */
45public abstract class AbstractTestCase extends TestCase {
46
47    private static final Logger LOG = LoggerFactory.getLogger(AbstractTestCase.class);
48    protected static final List EMPTY_LIST = Collections.EMPTY_LIST;
49    protected static final String[] EMPTY = new String[0];
50    protected static final InetAddress DEFAULT_HOST = inetAddress(null);
51
52    /**
53     * Constructor
54     */
55    public AbstractTestCase() {
56        super();
57    }
58
59    //-------------------------------------------------------------------------
60    // Manage EasyMock Control objects under the covers, and provide a syntax
61    // somewhat similar to EasyMock 2.2 for createMock, verify and replay.
62    //-------------------------------------------------------------------------
63
64    private Map mocks = new HashMap();
65
66    /**
67     * Create a new mock for the specified interface. Keep track of the associated control object
68     * under the covers to support the associated  method.
69     *
70     * @param interfaceToMock - the Class of the interface to be mocked
71     * @return the new mock
72     */
73    protected Object createMock(Class interfaceToMock) {
74        MockControl control = MockControl.createControl(interfaceToMock);
75        Object mock = control.getMock();
76        mocks.put(mock, control);
77        return mock;
78    }
79
80    /**
81     * Put the mock object into replay mode
82     *
83     * @param mock - the mock to set in replay mode
84     * @throws AssertFailedException - if mock is null
85     * @throws AssertFailedException - if mock is not a mock object created using {@link #createMock(Class)}
86     */
87    protected void replay(Object mock) {
88        control(mock).replay();
89    }
90
91    /**
92     * Put all mocks created with createMock() into replay mode.
93     */
94    protected void replayAll() {
95        for (Iterator iter = mocks.keySet().iterator(); iter.hasNext();) {
96            Object mock = iter.next();
97            replay(mock);
98        }
99    }
100
101    /**
102     * Verify the mock object
103     *
104     * @param mock - the mock to verify
105     * @throws AssertFailedException - if mock is null
106     * @throws AssertFailedException - if mock is not a mock object created using {@link #createMock(Class)}
107     */
108    protected void verify(Object mock) {
109        control(mock).verify();
110    }
111
112    /**
113     * Verify all mocks created with createMock() into replay mode.
114     */
115    protected void verifyAll() {
116        for (Iterator iter = mocks.keySet().iterator(); iter.hasNext();) {
117            Object mock = iter.next();
118            verify(mock);
119        }
120    }
121
122    /**
123     * Return the mock control associated with the mock
124     *
125     * @param mock - the mock
126     * @return the associated MockControl
127     * @throws AssertFailedException - if mock is null
128     * @throws AssertFailedException - if mock is not a mock object created using {@link #createMock(Class)}
129     */
130    protected MockControl control(Object mock) {
131        Assert.notNull(mock, "mock");
132        MockControl control = (MockControl) mocks.get(mock);
133        Assert.notNull(control, "control");
134        return control;
135    }
136
137    //-------------------------------------------------------------------------
138    // Other Helper Methods
139    //-------------------------------------------------------------------------
140
141    /**
142     * Assert that the two objects are not equal
143     *
144     * @param object1 - the first object
145     * @param object2 - the second object
146     */
147    protected void assertNotEquals(String message, Object object1, Object object2) {
148        assertFalse(message, object1.equals(object2));
149    }
150
151    /**
152     * Assert that the two byte arrays have the same length and content
153     *
154     * @param array1 - the first array
155     * @param array2 - the second array
156     */
157    protected void assertEquals(String message, byte[] array1, byte[] array2) {
158        assertTrue("Arrays not equal: " + message, Arrays.equals(array1, array2));
159    }
160
161    /**
162     * Assert that the two Object arrays have the same length and content
163     *
164     * @param array1 - the first array
165     * @param array2 - the second array
166     */
167    protected void assertEquals(String message, Object[] array1, Object[] array2) {
168        assertTrue("Arrays not equal: " + message, Arrays.equals(array1, array2));
169    }
170
171    /**
172     * Create and return a one-element Object[] containing the specified Object
173     *
174     * @param o - the object
175     * @return the Object array, of length 1, containing o
176     */
177    protected static Object[] objArray(Object o) {
178        return new Object[]{o};
179    }
180
181    /**
182     * Create and return a one-element String[] containing the specified String
183     *
184     * @param s - the String
185     * @return the String array, of length 1, containing s
186     */
187    protected static String[] array(String s) {
188        return new String[]{s};
189    }
190
191    /**
192     * Create and return a two-element String[] containing the specified Strings
193     *
194     * @param s1 - the first String
195     * @param s2 - the second String
196     * @return the String array, of length 2, containing s1 and s2
197     */
198    protected static String[] array(String s1, String s2) {
199        return new String[]{s1, s2};
200    }
201
202    /**
203     * Create a new InetAddress from the specified host String, using the
204     * {@link InetAddress#getByName(String)} method, wrapping any checked
205     * exception within a unchecked MockFtpServerException.
206     *
207     * @param host
208     * @return an InetAddress for the specified host
209     * @throws MockFtpServerException - if an UnknownHostException is thrown
210     */
211    protected static InetAddress inetAddress(String host) {
212        try {
213            return InetAddress.getByName(host);
214        }
215        catch (UnknownHostException e) {
216            throw new MockFtpServerException(e);
217        }
218    }
219
220    /**
221     * Create and return a List containing the Objects passed as arguments to this method
222     *
223     * @param e1- the first element to add
224     * @param e2- the second element to add
225     * @return the List containing the specified elements
226     */
227    protected static List list(Object e1, Object e2) {
228        List list = new ArrayList();
229        list.add(e1);
230        list.add(e2);
231        return list;
232    }
233
234    /**
235     * Create and return a List containing the single Object passed as an argument to this method
236     *
237     * @param element- the element to add
238     * @return the List containing the specified element
239     */
240    protected static List list(Object element) {
241        return Collections.singletonList(element);
242    }
243
244    /**
245     * Create and return a Set containing the Objects passed as arguments to this method
246     *
247     * @param e1 - the first element to add
248     * @param e2 - the second element to add
249     * @return the Set containing the specified elements
250     */
251    protected static Set set(Object e1, Object e2) {
252        Set set = new HashSet();
253        set.add(e1);
254        set.add(e2);
255        return set;
256    }
257
258    /**
259     * Create and return a Set containing the Objects passed as arguments to this method
260     *
261     * @param e1 - the first element to add
262     * @param e2 - the second element to add
263     * @param e3 - the third element to add
264     * @return the Set containing the specified elements
265     */
266    protected static Set set(Object e1, Object e2, Object e3) {
267        Set set = set(e1, e2);
268        set.add(e3);
269        return set;
270    }
271
272    /**
273     * Override the default test run behavior to write out the current test name
274     * and handle Errors and Exceptions in a standard way.
275     *
276     * @see junit.framework.TestCase#runBare()
277     */
278    public void runBare() throws Throwable {
279
280        LoggingUtil loggingUtil = null;
281        try {
282            loggingUtil = LoggingUtil.getTestCaseLogger(this);
283            loggingUtil.logStartOfTest();
284            super.runBare();
285        }
286        catch (Exception e) {
287            handleException(e);
288        }
289        catch (Error e) {
290            handleError(e);
291        }
292        finally {
293            if (loggingUtil != null) {
294                loggingUtil.logEndOfTest();
295            }
296        }
297    }
298
299    /**
300     * Setup before each test.
301     */
302    protected void setUp() throws Exception {
303        super.setUp();
304    }
305
306    /**
307     * Cleanup after each test.
308     */
309    protected void tearDown() throws Exception {
310        super.tearDown();
311    }
312
313    //-----------------------------------------------------------
314    // Private Internal Methods
315    //-----------------------------------------------------------
316
317    /**
318     * Handle an exception
319     *
320     * @param e the Exception
321     * @throws Exception
322     */
323    private void handleException(Exception e) throws Exception {
324
325        LOG.error("EXCEPTION: ", e);
326        throw e;
327    }
328
329    /**
330     * Handle an Error
331     *
332     * @param e the Error
333     * @throws Exception
334     */
335    private void handleError(Error e) throws Exception {
336        LOG.error("ERROR: ", e);
337        throw e;
338    }
339
340    //-------------------------------------------------------------------------
341    // Helper methods
342    //-------------------------------------------------------------------------
343
344    /**
345     * Delete the named file if it exists
346     *
347     * @param filename - the full pathname of the file
348     */
349    protected void deleteFile(String filename) {
350        File keyFile = new File(filename);
351        boolean deleted = keyFile.delete();
352        LOG.info("Deleted [" + filename + "]: " + deleted);
353    }
354
355    //-------------------------------------------------------------------------
356    // Common validation helper methods
357    //-------------------------------------------------------------------------
358
359    /**
360     * Verify that the named file exists
361     *
362     * @param filename - the full pathname of the file
363     */
364    protected void verifyFileExists(String filename) {
365        File keyFile = new File(filename);
366        assertTrue("File does not exist [" + filename + "]", keyFile.exists());
367    }
368
369}
370