Home | History | Annotate | Download | only in dicttool
      1 /**
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.android.inputmethod.latin.dicttool;
     18 
     19 import com.android.inputmethod.latin.common.FileUtils;
     20 import com.android.inputmethod.latin.makedict.BinaryDictDecoderEncoderTests;
     21 import com.android.inputmethod.latin.makedict.BinaryDictEncoderFlattenTreeTests;
     22 import com.android.inputmethod.latin.makedict.FusionDictionaryTest;
     23 
     24 import java.io.File;
     25 import java.io.IOException;
     26 import java.lang.reflect.Constructor;
     27 import java.lang.reflect.InvocationTargetException;
     28 import java.lang.reflect.Method;
     29 import java.nio.file.Files;
     30 import java.util.ArrayList;
     31 
     32 /**
     33  * Dicttool command implementing self-tests.
     34  */
     35 public class Test extends Dicttool.Command {
     36     private static final String getTmpDir() {
     37         try {
     38             return Files.createTempDirectory("dicttool").toString();
     39         } catch (IOException e) {
     40             throw new RuntimeException("Can't get temporary directory", e);
     41         }
     42     }
     43     private static final String TEST_TMP_DIR_BASE = getTmpDir();
     44     public static final File TEST_TMP_DIR = new File(TEST_TMP_DIR_BASE);
     45     public static final String COMMAND = "test";
     46     private static final int DEFAULT_MAX_UNIGRAMS = 1500;
     47     private long mSeed = System.currentTimeMillis();
     48     private int mMaxUnigrams = DEFAULT_MAX_UNIGRAMS;
     49 
     50     private static final Class<?>[] sClassesToTest = {
     51         BinaryDictOffdeviceUtilsTests.class,
     52         FusionDictionaryTest.class,
     53         BinaryDictDecoderEncoderTests.class,
     54         BinaryDictEncoderFlattenTreeTests.class,
     55     };
     56     private ArrayList<Method> mAllTestMethods = new ArrayList<>();
     57     private ArrayList<String> mUsedTestMethods = new ArrayList<>();
     58 
     59     public Test() {
     60         for (final Class<?> c : sClassesToTest) {
     61             for (final Method m : c.getDeclaredMethods()) {
     62                 if (m.getName().startsWith("test") && Void.TYPE == m.getReturnType()
     63                         && 0 == m.getParameterTypes().length) {
     64                     mAllTestMethods.add(m);
     65                 }
     66             }
     67         }
     68     }
     69 
     70     @Override
     71     public String getHelp() {
     72         final StringBuilder s = new StringBuilder(
     73                 "test [-s seed] [-m maxUnigrams] [-n] [testName...]\n"
     74                 + "If seed is not specified, the current time is used.\n"
     75                 + "If -n option is provided, do not delete temporary files in "
     76                 + TEST_TMP_DIR_BASE + "/*.\n"
     77                 + "Test list is:\n");
     78         for (final Method m : mAllTestMethods) {
     79             s.append("  ");
     80             s.append(m.getName());
     81             s.append("\n");
     82         }
     83         return s.toString();
     84     }
     85 
     86     @Override
     87     public void run() throws IllegalAccessException, InstantiationException,
     88             InvocationTargetException {
     89         int i = 0;
     90         boolean deleteTmpDir = true;
     91         while (i < mArgs.length) {
     92             final String arg = mArgs[i++];
     93             if ("-s".equals(arg)) {
     94                 mSeed = Long.parseLong(mArgs[i++]);
     95             } else if ("-m".equals(arg)) {
     96                 mMaxUnigrams = Integer.parseInt(mArgs[i++]);
     97             } else if ("-n".equals(arg)) {
     98                 deleteTmpDir = false;
     99             } else {
    100                 mUsedTestMethods.add(arg);
    101             }
    102         }
    103         try {
    104             runChosenTests();
    105         } finally {
    106             if (deleteTmpDir) {
    107                 FileUtils.deleteRecursively(TEST_TMP_DIR);
    108             }
    109         }
    110     }
    111 
    112     private void runChosenTests() throws IllegalAccessException, InstantiationException,
    113             InvocationTargetException {
    114         for (final Method m : mAllTestMethods) {
    115             final Class<?> declaringClass = m.getDeclaringClass();
    116             if (!mUsedTestMethods.isEmpty() && !mUsedTestMethods.contains(m.getName())) continue;
    117             // Some of the test classes expose a two-argument constructor, taking a long as a
    118             // seed for Random, and an int for a vocabulary size to test the dictionary with. They
    119             // correspond respectively to the -s and -m numerical arguments to this command, which
    120             // are stored in mSeed and mMaxUnigrams. If the two-arguments constructor is present,
    121             // then invoke it; otherwise, invoke the default constructor.
    122             Constructor<?> twoArgsConstructor = null;
    123             try {
    124                 twoArgsConstructor = declaringClass.getDeclaredConstructor(Long.TYPE, Integer.TYPE);
    125             } catch (NoSuchMethodException e) {
    126                 // No constructor with two args
    127             }
    128             final Object instance = null == twoArgsConstructor ? declaringClass.newInstance()
    129                     : twoArgsConstructor.newInstance(mSeed, mMaxUnigrams);
    130             m.invoke(instance);
    131         }
    132     }
    133 }
    134