001/* Base class for tests that use models in the auto/ directory.
002
003   Copyright (c) 2011-2018 The Regents of the University of California.
004   All rights reserved.
005   Permission is hereby granted, without written agreement and without
006   license or royalty fees, to use, copy, modify, and distribute this
007   software and its documentation for any purpose, provided that the above
008   copyright notice and the following two paragraphs appear in all copies
009   of this software.
010
011   IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012   FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013   ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014   THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015   SUCH DAMAGE.
016
017   THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020   PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021   CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022   ENHANCEMENTS, OR MODIFICATIONS.
023
024   PT_COPYRIGHT_VERSION_2
025   COPYRIGHTENDKEY
026
027 */
028
029package ptolemy.util.test.junit;
030
031import java.io.File;
032import java.io.FilenameFilter;
033import java.io.IOException;
034import java.lang.reflect.Constructor;
035import java.lang.reflect.Method;
036import java.util.Arrays;
037import java.util.Comparator;
038import java.util.Locale;
039
040///////////////////////////////////////////////////////////////////
041//// ModelTests
042/**
043 * Base class for tests that use models in the auto/ directory.
044 *
045 *
046 * @author Christopher Brooks
047 * @version $Id$
048 * @since Ptolemy II 10.0
049 * @Pt.ProposedRating Red (cxh)
050 * @Pt.AcceptedRating Red (cxh)
051 */
052public class ModelTests {
053
054    /**
055     * Return a two dimensional array of arrays of strings that name the model
056     * to be executed. If auto/ does not exist, or does not contain files that
057     * end with .xml or .moml, return a list with one element that contains
058     * the value of the THERE_ARE_NO_AUTO_TESTS variable.
059     *
060     * @return The List of model names in auto/
061     * @exception IOException If there is a problem accessing the auto/ directory.
062     */
063    public Object[] modelValues() throws IOException {
064        return modelValues("auto/", THERE_ARE_NO_AUTO_TESTS);
065    }
066
067    /**
068     * Return a two dimensional array of arrays of strings that name the model
069     * to be executed. If directory does not exist, or does not contain files that
070     * end with .xml or .moml, return a list with the value of the message parameter.
071     *
072     * @param directory The directory, which is usually either "auto/" or
073     * "auto/knownFailedTests/".
074     * @param message The message to use if the directory contains no
075     * *.xml or *.moml files.
076     * @return The List of model names in the directory.
077     * @exception IOException If there is a problem accessing the directory.
078     */
079    public Object[] modelValues(String directory, String message)
080            throws IOException {
081        File auto = new File(directory);
082        if (auto.isDirectory()) {
083            String[] modelFiles = auto.list(new FilenameFilter() {
084                /**
085                 * Return true if the file name ends with .xml or .moml
086                 *
087                 * @param directory
088                 *            Ignored
089                 * @param name
090                 *            The name of the file.
091                 * @return true if the file name ends with .xml or .moml
092                 */
093                @Override
094                public boolean accept(File directory, String name) {
095                    String fileName = name.toLowerCase(Locale.getDefault());
096                    return fileName.endsWith(".xml")
097                            || fileName.endsWith(".moml");
098                }
099            });
100            int i = 0;
101            Object[][] data = new Object[modelFiles.length][1];
102            if (modelFiles.length > 0) {
103                for (String modelFile : modelFiles) {
104                    data[i++][0] = new File(directory + modelFile)
105                            .getCanonicalPath();
106                }
107                // Sort the files so that we execute the tests in
108                // a predictable order.  Tests in ptolemy/actor/lib/test/auto
109                // need this.  File.list() returns files in a different order
110                // on different platforms.  So much for write once, run everywhere.
111                Arrays.sort(data, new Comparator<Object[]>() {
112                    @Override
113                    public int compare(final Object[] entry1,
114                            final Object[] entry2) {
115                        final String file1 = (String) entry1[0];
116                        final String file2 = (String) entry2[0];
117                        return file1.compareTo(file2);
118                    }
119                });
120                return data;
121            } else {
122                return new Object[][] { { message } };
123            }
124        }
125        return new Object[][] { { message } };
126    }
127
128    ///////////////////////////////////////////////////////////////////
129    ////                         protected variables               ////
130
131    /**
132     * The application class. We use reflection here to avoid false dependencies
133     * if auto/ does not exist.
134     * In derived classes, _applicationClass should be initialized in right
135     * before it is to be used.  It should not be initialized in setup()
136     * so that we can avoid dependencies on MoMLSimpleApplication.
137     */
138    protected static Class<?> _applicationClass = null;
139
140    /** The application constructor. */
141    protected static Constructor _applicationConstructor;
142
143    /** The application toplevel method. */
144    protected static Method _applicationToplevelMethod = null;
145
146    /**
147     * A special string that is passed when there are no known failed tests.
148     * This is necessary to avoid an exception in the JUnitParameters.
149     */
150    protected final static String THERE_ARE_NO_AUTO_TESTS = "ThereAreNoAutoTests";
151
152    /**
153     * A special string that is passed when there are no known failed tests.
154     * This is necessary to avoid an exception in the JUnitParameters.
155     */
156    protected final static String THERE_ARE_NO_AUTO_ARCH_TESTS = "ThereAreNoAutoArchTests";
157
158    /**
159     * A special string that is passed when there are no known failed tests.
160     * This is necessary to avoid an exception in the JUnitParameters.
161     */
162    protected final static String THERE_ARE_NO_KNOWN_FAILED_TESTS = "ThereAreNoKnowFailedTests";
163
164    static {
165        // ptolemy.actor.lib.test.NonStrictTest checks isRunningNightlyBuild and
166        // throws an exception if trainingMode is true.
167        System.setProperty("ptolemy.ptII.isRunningNightlyBuild", "true");
168
169        // ptolemy.util.StringUtilities.exit() checks ptolemy.ptII.doNotExit.
170        System.setProperty("ptolemy.ptII.doNotExit", "true");
171    }
172}