/*
* Copyright (c) 2012 NTT DATA Corporation
*
* 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 jp.terasoluna.fw.beans.jxpath;
import static java.util.Arrays.asList;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static uk.org.lidalia.slf4jtest.LoggingEvent.info;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.jxpath.JXPathIntrospector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import uk.org.lidalia.slf4jtest.TestLogger;
import uk.org.lidalia.slf4jtest.TestLoggerFactory;
/**
* {@link jp.terasoluna.fw.beans.jxpath.JXPATH152PatchActivator} クラスのブラックボックステスト。
* <p>
* <h4>【クラスの概要】</h4> commons-JXPathのバグ(JXPATH-152)用パッチをアクティベートするクラス。<br>
* 前提条件:<br>
* ・このテストを実行する際、JVMのセキュリティマネージャを有効にしないこと<br>
* ・このテストを実行する際、同一JVM内で同時に他のテストを実行しないこと<br>
* (一時的にセキュリティマネージャを有効にするため、有効になっている間に他のテストが動作すると、 そのテストでエラーが発生する可能性がある。 なお、同時に実行さえしなければ、同一JVM内であとから他のテストを実行してもよい。)<br>
* ・このテストを実行する際、JREのセキュリティポリシーファイル<br>
* (デフォルトでは、JREインストールディレクトリ/lib/security/java.policy)にて、<br>
* permission java.lang.reflect.ReflectPermission "suppressAccessChecks";<br>
* の権限を与えないこと。(インストール後の状態のままであれば、この権限はない。)<br>
* ・このテストを実行する際、テスト対象となるclassファイルと、テストケースのclassファイルは、同一のディレクトリに出力しないこと。
* <p>
* @see jp.terasoluna.fw.beans.jxpath.JXPATH152PatchActivator
*/
public class JXPATH152PatchActivatorTest {
private Map<?, ?> byClassBak = null;
private Map<?, ?> byInterfaceBak = null;
private TestLogger logger = TestLoggerFactory.getTestLogger(
JXPATH152PatchActivator.class);
/**
* 初期化処理を行う。
* @throws Exception このメソッドで発生した例外
*/
@Before
public void setUp() throws Exception {
// クラスロードされていなければクラスロード
// (クラスロード時にstaticイニシャライザ実行)
new JXPATH152PatchActivator();
// JXPATH152PatchActivatorのstaticイニシャライザ実行後の状態を保持
// (tearDownでstaticイニシャライザ実行前の状態に戻してしまわないように)
Field field = JXPathIntrospector.class.getDeclaredField("byClass");
field.setAccessible(true);
byClassBak = (Map<?, ?>) field.get(JXPathIntrospector.class);
field = JXPathIntrospector.class.getDeclaredField("byInterface");
field.setAccessible(true);
byInterfaceBak = (Map<?, ?>) field.get(JXPathIntrospector.class);
logger.clear();
}
/**
* 終了処理を行う。
* @throws Exception このメソッドで発生した例外
*/
@After
public void tearDown() throws Exception {
logger.clear();
Field field = JXPathIntrospector.class.getDeclaredField("byClass");
field.setAccessible(true);
field.set(JXPathIntrospector.class, byClassBak);
field = JXPathIntrospector.class.getDeclaredField("byInterface");
field.setAccessible(true);
field.set(JXPathIntrospector.class, byInterfaceBak);
}
/**
* testActivate01() <br>
* <br>
* (正常系) <br>
* 観点:A <br>
* <br>
* 入力値:(引数) -<br>
* (状態) JXPathIntrospector.byClasst:HashMap<br>
* (状態) JXPathIntrospector.byInterface:HashMap<br>
* <br>
* 期待値:(状態変化) JXPathIntrospector.byClassがHashMapForJXPathIntrospectorになっている。<br>
* (状態変化) JXPathIntrospector.byInterfaceがHashMapForJXPathIntrospectorになっている。<br>
* (状態変化) ログ:ログレベル:INFO<br>
* JXPATH-152 Patch activation succeeded.<br>
* <br>
* セキュリティマネージャに阻止されなければ、 JXPathIntrospectorのbyClassとbyInterfaceがHashMapForJXPathIntrospectorインスタンスになっていることのテスト。 <br>
* @throws Exception このメソッドで発生した例外
*/
@Test
public void testActivate01() throws Exception {
// 前処理
Field field = JXPathIntrospector.class.getDeclaredField("byClass");
field.setAccessible(true);
field.set(JXPathIntrospector.class, new HashMap<Object, Object>());
field = JXPathIntrospector.class.getDeclaredField("byInterface");
field.setAccessible(true);
field.set(JXPathIntrospector.class, new HashMap<Object, Object>());
// テスト実施
Method method = JXPATH152PatchActivator.class.getDeclaredMethod(
"activate");
method.setAccessible(true);
method.invoke(JXPATH152PatchActivator.class);
// 判定
assertThat(logger.getLoggingEvents(), is(asList(info(
"JXPATH-152 Patch activation succeeded."))));
field = JXPathIntrospector.class.getDeclaredField("byClass");
field.setAccessible(true);
assertTrue(((Map<?, ?>) field.get(JXPathIntrospector.class))
.getClass() == HashMapForJXPathIntrospector.class);
field = JXPathIntrospector.class.getDeclaredField("byInterface");
field.setAccessible(true);
assertTrue(((Map<?, ?>) field.get(JXPathIntrospector.class))
.getClass() == HashMapForJXPathIntrospector.class);
}
/**
* testActivate01() <br>
* <br>
* (正常系) <br>
* 観点:A <br>
* <br>
* 入力値:(引数) -<br>
* (状態) JXPathIntrospector.byClasst:HashMap<br>
* (状態) JXPathIntrospector.byInterface:HashMap<br>
* <br>
* 期待値:(状態変化) JXPathIntrospector.byClassがHashMapのまま。<br>
* (状態変化) JXPathIntrospector.byInterfaceがHashMapのまま。<br>
* (状態変化) ログ:ログレベル:FATAL<br>
* JXPATH-152 Patch activation failed.<br>
* <br>
* セキュリティマネージャに阻止された場合、 FATALログを出力することのテスト。 <br>
* @throws Exception このメソッドで発生した例外
*/
@Test
public void testActivate02() throws Exception {
// TODO
// Java7環境下ではAccessController.doPrivileged()に渡しているAccessControlContextのDomainCombiner#combine()が呼び出されず、本テストの動作確認が不可能であるため、コメントアウトしている。
// // アクセス権設定
// final ProtectionDomain testTargetProtectionDomain = JXPATH152PatchActivator.class.getProtectionDomain();
// DomainCombiner domainCombiner = new DomainCombiner() {
// public ProtectionDomain[] combine(
// ProtectionDomain[] currentDomains,
// ProtectionDomain[] assignedDomains) {
// ProtectionDomain[] ret = new ProtectionDomain[currentDomains.length];
// for (int i = 0; i < currentDomains.length ;i++) {
// // テストケースクラスやライブラリにあるクラス等、
// // 試験対象クラス(が含まれるクラスパスにあるクラス)以外は、全操作に対する権限を与える
// if (currentDomains[i].getCodeSource() != testTargetProtectionDomain.getCodeSource()) {
// Permissions permissions = new Permissions();
// permissions.add(new AllPermission());
// ProtectionDomain pd = new ProtectionDomain(currentDomains[i].getCodeSource(), permissions);
// ret[i] = pd;
// } else {
// // 試験対象クラス(が含まれるクラスパスにあるクラス)は、デフォルトの権限のまま
// // (Field#setAccessibleが禁止される)
// ret[i] = currentDomains[i];
// }
// }
// return ret;
// }
// };
// AccessControlContext acc = new AccessControlContext(AccessController.getContext(), domainCombiner);
// System.setSecurityManager(new SecurityManager());
//
// // 上記のDomainCombinerで編集したアクセス権設定で、テストを実行
// AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
//
// public Void run() throws Exception {
// try {
// // 前処理
// UTUtil.setPrivateField(JXPathIntrospector.class, "byClass", new HashMap());
// UTUtil.setPrivateField(JXPathIntrospector.class, "byInterface", new HashMap());
//
// // テスト実施
// UTUtil.invokePrivate(JXPATH152PatchActivator.class, "activate");
//
// // 判定
// assertTrue(LogUTUtil.checkFatal("JXPATH-152 Patch activation failed.", new AccessControlException("")));
// assertTrue(UTUtil.getPrivateField(JXPathIntrospector.class, "byClass").getClass() == HashMap.class);
// assertTrue(UTUtil.getPrivateField(JXPathIntrospector.class, "byInterface").getClass() == HashMap.class);
// } finally {
// System.setSecurityManager(null);
// }
//
// return null;
// }
//
// }, acc);
}
}