/* * 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 org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.HashMap; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * {@link jp.terasoluna.fw.beans.jxpath.HashMapForJXPathIntrospector} クラスのブラックボックステスト。 * * <p> * <h4>【クラスの概要】</h4> * commons-JXPathのバグ(JXPATH-152)回避用HashMap。<br> * <p> * * @see jp.terasoluna.fw.beans.jxpath.HashMapForJXPathIntrospector */ public class HashMapForJXPathIntrospectorTest { /** * testHashMapForJXPathIntrospector01() * <br><br> * * (正常系) * <br> * 観点:A * <br><br> * 入力値:(引数) HashMap<br> * { * "aaa"="xxx", * "bbb"="yyy" * }<br> * * <br> * 期待値:(戻り値) HashMapForJXPathIntrospector<br> * { * "aaa"="xxx", * "bbb"="yyy" * }<br> * * <br> * コンストラクタ引数に与えたMapのエントリーをすべて含むインスタンスがつくられることの確認。 * (スーパークラスへの委譲確認。) * <br> * * @throws Exception このメソッドで発生した例外 */ @Test public void testHashMapForJXPathIntrospector01() throws Exception { // 前処理 HashMap<String, String> srcMap = new HashMap<String, String>(); srcMap.put("aaa", "xxx"); srcMap.put("bbb", "yyy"); // テスト実施 HashMapForJXPathIntrospector<String, String> map = new HashMapForJXPathIntrospector<String, String>(srcMap); // 判定 assertEquals(2, map.size()); assertEquals("xxx", map.get("aaa")); assertEquals("yyy", map.get("bbb")); } /** * testGet01() * <br><br> * * (正常系) * <br> * 観点:A * <br><br> * 入力値:(引数) "aaa"<br> * (状態) { * "aaa"="xxx" * }<br> * (状態) putに2秒かかるキーオブジェクトでput中<br> * * <br> * 期待値:(戻り値) "xxx"<br> * (状態変化) getが即座には終了しない<br> * * <br> * put中はgetが待たされることの確認。 * (戻り値は、スーパークラスへの委譲確認。) * <br> * * @throws Exception このメソッドで発生した例外 */ @Test public void testGet01() throws Exception { // 前処理 final HashMapForJXPathIntrospector<Object, String> map = new HashMapForJXPathIntrospector<Object, String>(new HashMap<Object, String>()); map.put("aaa", "xxx"); new Thread() { @Override public void run() { map.put(new WaitHashObject(2000), "wait"); } }.start(); TimeUnit.MILLISECONDS.sleep(500); // テスト実施 long start = System.currentTimeMillis(); String ret = map.get("aaa"); long time = System.currentTimeMillis() - start; // 判定 assertTrue(time > 1000); // 約1500ミリ秒 assertEquals("xxx", ret); } /** * testGet02() * <br><br> * * (正常系) * <br> * 観点:A * <br><br> * 入力値:(引数) "aaa"<br> * (状態) { * "aaa"="xxx" * getに2秒かかるキーオブジェクト="wait" * }<br> * (状態) getに2秒かかるキーオブジェクトでget中<br> * * <br> * 期待値:(戻り値) "xxx"<br> * (状態変化) getは即座に終了する<br> * * <br> * put中でなければgetは同時に複数スレッドで使用可能であることの確認。 * (戻り値は、スーパークラスへの委譲確認。) * <br> * * @throws Exception このメソッドで発生した例外 */ @Test public void testGet02() throws Exception { // 前処理 final HashMapForJXPathIntrospector<Object, String> map = new HashMapForJXPathIntrospector<Object, String>(new HashMap<Object, String>()); map.put("aaa", "xxx"); final WaitHashObject waitKey = new WaitHashObject(2000); map.put(waitKey, "wait"); new Thread() { @Override public void run() { map.get(waitKey); } }.start(); TimeUnit.MILLISECONDS.sleep(500); // テスト実施 long start = System.currentTimeMillis(); String ret = map.get("aaa"); long time = System.currentTimeMillis() - start; // 判定 assertTrue(time < 500); // ほぼ0ミリ秒 assertEquals("xxx", ret); } /** * testPut01() * <br><br> * * (正常系) * <br> * 観点:A * <br><br> * 入力値:(引数) key:"aaa"<br> * (引数) value:"xxx"<br> * (状態) { * (空) * }<br> * (状態) putに2秒かかるキーオブジェクトでput中<br> * * <br> * 期待値:(状態変化) エントリー"aaa"="xxx"が追加される<br> * (状態変化) putが即座には終了しない<br> * * <br> * put中はputが待たされることの確認。 * (エントリー追加は、スーパークラスへの委譲確認。) * <br> * * @throws Exception このメソッドで発生した例外 */ @Test public void testPut01() throws Exception { // 前処理 final HashMapForJXPathIntrospector<Object, String> map = new HashMapForJXPathIntrospector<Object, String>(new HashMap<Object, String>()); new Thread() { @Override public void run() { map.put(new WaitHashObject(2000), "wait"); } }.start(); TimeUnit.MILLISECONDS.sleep(500); // テスト実施 long start = System.currentTimeMillis(); map.put("aaa", "xxx"); long time = System.currentTimeMillis() - start; // 判定 assertTrue(time > 1000); // 約1500ミリ秒 assertEquals("xxx", map.get("aaa")); } /** * testPut01() * <br><br> * * (正常系) * <br> * 観点:A * <br><br> * 入力値:(引数) key:"aaa"<br> * (引数) value:"xxx"<br> * (状態) { * getに2秒かかるキーオブジェクト="wait" * }<br> * (状態) getに2秒かかるキーオブジェクトでget中<br> * * <br> * 期待値:(状態変化) エントリー"aaa"="xxx"が追加される<br> * (状態変化) putが即座には終了しない<br> * * <br> * get中はputが待たされることの確認。 * (エントリー追加は、スーパークラスへの委譲確認。) * <br> * * @throws Exception このメソッドで発生した例外 */ @Test public void testPut02() throws Exception { // 前処理 final HashMapForJXPathIntrospector<Object, String> map = new HashMapForJXPathIntrospector<Object, String>(new HashMap<Object, String>()); final WaitHashObject waitKey = new WaitHashObject(2000); map.put(waitKey, "wait"); new Thread() { @Override public void run() { map.get(waitKey); } }.start(); TimeUnit.MILLISECONDS.sleep(500); // テスト実施 long start = System.currentTimeMillis(); map.put("aaa", "xxx"); long time = System.currentTimeMillis() - start; // 判定 assertTrue(time > 1000); // 約1500ミリ秒 assertEquals("xxx", map.get("aaa")); } /** * HashMapへのputやgetに時間がかかるキーオブジェクト。 * putやgetの際に利用されるhashCodeメソッドに、スリープを入れている。 * スリープ時間はコンストラクタで指定する。 */ private static class WaitHashObject { private long sleepMillis; public WaitHashObject(long sleepMillis) { this.sleepMillis = sleepMillis; } @Override public int hashCode() { try { TimeUnit.MILLISECONDS.sleep(sleepMillis); } catch (InterruptedException e) { } return super.hashCode(); } } }