Package com.asakusafw.testtools.inspect

Source Code of com.asakusafw.testtools.inspect.DefaultInspector

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.asakusafw.testtools.inspect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Calendar;

import org.apache.hadoop.io.Writable;

import com.asakusafw.runtime.value.Date;
import com.asakusafw.runtime.value.DateOption;
import com.asakusafw.runtime.value.DateTime;
import com.asakusafw.runtime.value.DateTimeOption;
import com.asakusafw.runtime.value.StringOption;
import com.asakusafw.runtime.value.ValueOption;
import com.asakusafw.testtools.ColumnInfo;
import com.asakusafw.testtools.inspect.Cause.Type;

/**
* 標準的な{@link Inspector}の実装。
*/
public final class DefaultInspector extends AbstractInspector {

    @Override
    protected void inspect(Writable expectRow, Writable actualRow) {
        for (ColumnInfo columnInfo : getColumnInfos()) {
            Method method;
            try {
                method = expectRow.getClass().getMethod(columnInfo.getGetterName());
                ValueOption<?> expectVal = (ValueOption<?>) method.invoke(expectRow);
                ValueOption<?> actualVal = (ValueOption<?>) method.invoke(actualRow);
                inspect(expectRow, actualRow, expectVal, actualVal, columnInfo);
            } catch (SecurityException e) {
                throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 指定のレコードに対する値を検査する。
     * @param expect 期待値のレコード(エラーメッセージの作成に使用)
     * @param actual 実値のレコード(エラーメッセージの作成に使用)
     * @param expectVal 期待値
     * @param actualVal 実値
     * @param columnInfo カラム情報
     */
    private void inspect(
            Writable expect,
            Writable actual,
            ValueOption<?> expectVal,
            ValueOption<?> actualVal,
            ColumnInfo columnInfo) {
        if (actualVal.isNull()) {
            switch (columnInfo.getNullValueCondition()) {
            case NULL_IS_NG:
                fail(Type.COLUMN_VALUE_MISSMATCH, expect, actual, expectVal, actualVal, columnInfo);
                return;
            case NULL_IS_OK:
                return;
            case NORMAL:
            case NOT_NULL_IS_NG:
            case NOT_NULL_IS_OK:
                break; // 次に進む
            default:
                throw new RuntimeException("Unsupported test condition");
            }
        }
        if (!actualVal.isNull()) {
            switch (columnInfo.getNullValueCondition()) {
            case NOT_NULL_IS_NG:
                fail(Type.COLUMN_VALUE_MISSMATCH, expect, actual, expectVal, actualVal, columnInfo);
                return;
            case NOT_NULL_IS_OK:
                return;
            case NORMAL:
            case NULL_IS_OK:
            case NULL_IS_NG:
                break; // 次に進む
            default:
                throw new RuntimeException("Unsupported test condition");
            }
        }
        switch (columnInfo.getColumnMatchingCondition()) {
        case EXACT: // 完全一致
            inspectExact(expect, actual, expectVal, actualVal, columnInfo);
            break;
        case NONE: // 検査しない場合常に成功
            return;
        case NOW: // 現在時刻
            inspectNow(expect, actual, expectVal, actualVal, columnInfo);
            break;
        case TODAY: // 現在日
            inspectToday(expect, actual, expectVal, actualVal, columnInfo);
            break;
        case PARTIAL: // 部分一致
            inspectPartialt(expect, actual, expectVal, actualVal, columnInfo);
            break;
        default:
            throw new RuntimeException("Unsupported test Condition");
        }
    }

    /**
     * 指定のレコードに対する値を厳密に検査する。
     * @param expect 期待値のレコード(エラーメッセージの作成に使用)
     * @param actual 実値のレコード(エラーメッセージの作成に使用)
     * @param expectVal 期待値
     * @param actualVal 実値
     * @param columnInfo カラム情報
     */
    private void inspectExact(
            Writable expect,
            Writable actual,
            ValueOption<?> expectVal,
            ValueOption<?> actualVal,
            ColumnInfo columnInfo) {
        if (!expectVal.equals(actualVal)) {
            fail(Type.COLUMN_VALUE_MISSMATCH, expect, actual, expectVal, actualVal, columnInfo);
            return;
        } else {
            return;
        }
    }

    /**
     * 指定のレコードに対する値を部分的に検査する。
     * @param expect 期待値のレコード(エラーメッセージの作成に使用)
     * @param actual 実値のレコード(エラーメッセージの作成に使用)
     * @param expectVal 期待値
     * @param actualVal 実値
     * @param columnInfo カラム情報
     */
    private void inspectPartialt(
            Writable expect,
            Writable actual,
            ValueOption<?> expectVal,
            ValueOption<?> actualVal,
            ColumnInfo columnInfo) {
        // StringOptionにキャスト
        StringOption actualStringOption;
        StringOption expectStringOption;
        if (actualVal instanceof StringOption) {
            actualStringOption = (StringOption) actualVal;
            expectStringOption = (StringOption) expectVal;
        } else {
            fail(Type.CONDITION_PARTIAL_ON_INVALID_COLUMN, expect, actual, expectVal, actualVal, columnInfo);
            return;
        }
        // まず完全一致をテストする(期待値と実値が両方ともNULLまたはNULL文字列の場合も
        // 完全一致とみなされるため、以降期待値と実値が両方ともNULLまたはNULL文字列の場合を
        // 考慮しなくてもよい
        if (actualStringOption.equals(expectStringOption)) {
            return;
        }
        // 期待値、実地のどちらかがNULLかNULL文字列の場合、検証を失敗させる
        if (actualStringOption.isNull()
                || expectStringOption.isNull()
                || actualStringOption.getAsString().length() == 0
                || expectStringOption.getAsString().length() == 0) {
            fail(Type.COLUMN_VALUE_MISSMATCH, expect, actual, expectVal, actualVal, columnInfo);
            return;
        }
        String actualString = actualStringOption.getAsString();
        String expectString = expectStringOption.getAsString();
        if (actualString.indexOf(expectString) == -1) {
            fail(Type.COLUMN_VALUE_MISSMATCH, expect, actual, expectVal, actualVal, columnInfo);
            return;
        } else {
            return;
        }
    }

    /**
     * 「現在」に関する項目を検査する。
     * @param expect 期待値のレコード(エラーメッセージの作成に使用)
     * @param actual 実値のレコード(エラーメッセージの作成に使用)
     * @param expectVal 期待値
     * @param actualVal 実値
     * @param columnInfo カラム情報
     */
    private void inspectNow(
            Writable expect,
            Writable actual,
            ValueOption<?> expectVal,
            ValueOption<?> actualVal,
            ColumnInfo columnInfo) {
        Calendar cal = Calendar.getInstance();
        if (actualVal instanceof DateTimeOption) {
            if (actualVal.isNull()) {
                fail(Type.NOT_IN_TESTING_TIME, expect, actual, expectVal, actualVal, columnInfo);
                return;
            }
            DateTimeOption dateTimeOption = (DateTimeOption) actualVal;
            DateTime dateTime = dateTimeOption.get();
            int y = dateTime.getYear();
            int m = dateTime.getMonth();
            int d = dateTime.getDay();
            int h = dateTime.getHour();
            int min = dateTime.getMinute();
            int s = dateTime.getSecond();
            cal.clear();
            cal.set(y, m - 1, d, h, min, s);
        } else {
            fail(Type.CONDITION_NOW_ON_INVALID_COLUMN, expect, actual, expectVal, actualVal, columnInfo);
            return;
        }
        long time = cal.getTimeInMillis();
        // getStartTime()はミリ秒の値を持つのに対し、timeはミリ秒の値を持たない
        // この影響を排除するため、startTime - 1秒の値を使用して比較する
        if (getStartTime() - 1000 <= time && time <= getFinishTime()) {
            return;
        } else {
            fail(Type.NOT_IN_TESTING_TIME, expect, actual, expectVal, actualVal, columnInfo);
            return;
        }
    }

    /**
     * 「本日」に関する項目を検査する。
     * @param expect 期待値のレコード(エラーメッセージの作成に使用)
     * @param actual 実値のレコード(エラーメッセージの作成に使用)
     * @param expectVal 期待値
     * @param actualVal 実値
     * @param columnInfo カラム情報
     */
    private void inspectToday(
            Writable expect,
            Writable actual,
            ValueOption<?> expectVal,
            ValueOption<?> actualVal,
            ColumnInfo columnInfo) {
        Calendar cal = Calendar.getInstance();
        if (actualVal instanceof DateOption) {
            if (actualVal.isNull()) {
                fail(Type.NOT_IN_TEST_DAY, expect, actual, expectVal, actualVal, columnInfo);
                return;
            }
            DateOption dateOption = (DateOption) actualVal;
            Date date = dateOption.get();
            cal.clear();
            cal.set(date.getYear(), date.getMonth() - 1, date.getDay());
        } else if (actualVal instanceof DateTimeOption) {
            if (actualVal.isNull()) {
                fail(Type.NOT_IN_TEST_DAY, expect, actual, expectVal, actualVal, columnInfo);
                return;
            }
            DateTimeOption dateTimeOption = (DateTimeOption) actualVal;
            DateTime dateTime = dateTimeOption.get();
            int y = dateTime.getYear();
            int m = dateTime.getMonth();
            int d = dateTime.getDay();
            int h = dateTime.getHour();
            int min = dateTime.getMinute();
            int s = dateTime.getSecond();
            cal.clear();
            cal.set(y, m - 1, d, h, min, s);
        } else {
            fail(Type.CONDITION_TODAY_ON_INVALID_COLUMN, expect, actual, expectVal, actualVal, columnInfo);
            return;
        }
        Calendar startDay = Calendar.getInstance();
        startDay.setTimeInMillis(getStartTime());
        truncateCalendar(startDay);
        Calendar finishDay = Calendar.getInstance();
        finishDay.setTimeInMillis(getFinishTime());
        truncateCalendar(finishDay);
        finishDay.add(Calendar.DAY_OF_MONTH, 1);
        long time = cal.getTimeInMillis();
        if (startDay.getTimeInMillis() <= time && time < finishDay.getTimeInMillis()) {
            return;
        } else {
            fail(Type.NOT_IN_TEST_DAY, expect, actual, expectVal, actualVal, columnInfo);
            return;
        }
    }

    /**
     * 指定したカレンダーオブジェクトの時分秒を切り捨てる。
     * @param cal 対象のカレンダー
     */
    private void truncateCalendar(Calendar cal) {
        int y = cal.get(Calendar.YEAR);
        int m = cal.get(Calendar.MONTH);
        int d = cal.get(Calendar.DAY_OF_MONTH);
        cal.clear();
        cal.set(y, m, d);
    }
}
TOP

Related Classes of com.asakusafw.testtools.inspect.DefaultInspector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.