/**
* personium.io
* Copyright 2014 FUJITSU LIMITED
*
* 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.fujitsu.dc.unit.engine.test.extension.support;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import com.fujitsu.dc.engine.extension.support.ExtensionJarLoader;
import com.fujitsu.dc.engine.extension.support.JavaClassRevealFilter;
import com.fujitsu.dc.unit.Unit;
/**
* JavaClassRevealFilterのユニットテスト.
*/
@Category({ Unit.class })
public class ExtensionJarLoaderTest {
/**
* 各テストの実効前に実行する処理.
* @throws Exception テスト実行前の前提条件設定に失敗した場合
*/
@Before
public void before() throws Exception {
// クラスローダが singleton化されたことにより、一部のテスト実施でエラーがでるため、
// テスト中は毎回 singletonを消して、新たにクラスローダが作成されるように修正。
Field field = ExtensionJarLoader.class.getDeclaredField("singleton");
field.setAccessible(true);
field.set(null, null);
}
/**
* 各テストの最後に実行する処理.
*/
@After
public void after() {
// Extention用の jarファイルの置場所をデフォルト設定に戻す
System.setProperty(ExtensionJarLoader.ENGINE_EXTENSION_DIR_KEY, ExtensionJarLoader.DEFAULT_EXTENSION_DIR);
}
/**
* デフォルトディレクトリのjarファイルをロードしその中のクラスがロードされていること.
* @throws Exception エラー
*/
@Test
public void 指定ディレクトリのjarファイルをロードしその中のクラスがロードされていること() throws Exception {
String fileName = this.getClass().getClassLoader().getResource("extension").getFile();
System.out.println("#####>>>> " + fileName);
// Extension用の jarファイルの置場所を指定。この下にはテスト用の jarファイルが置かれているものとする。
System.setProperty(ExtensionJarLoader.ENGINE_EXTENSION_DIR_KEY, fileName);
// fileName.substring(0, fileName.lastIndexOf("/")));
// テスト前に本テスト対象のクラスがデフォルトクラスローダにロードされていないことを確認
try {
this.getClass().getClassLoader().loadClass("com.fujitsu.test.dc.extension.NonRevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
try {
this.getClass().getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
ExtensionJarLoader loader = ExtensionJarLoader.getInstance(this.getClass().getClassLoader(),
new JavaClassRevealFilter());
Class<?> clazz1 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.NonRevealingClass");
assertNotNull(clazz1);
assertTrue(clazz1 instanceof Class);
assertFalse(ScriptableObject.class.isAssignableFrom(clazz1));
Class<?> clazz2 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
assertNotNull(clazz2);
assertTrue(clazz2 instanceof Class);
assertTrue(ScriptableObject.class.isAssignableFrom(clazz2));
// ScriptableObjectを継承した Revealingクラスが ExtensionJarLoaderに設定されていること。
Set<Class<? extends Scriptable>> set = loader.getPrototypeClassSet();
assertFalse(set.contains(clazz1));
assertTrue(set.contains(clazz2));
}
/**
* 指定ディレクトリの孫ディレクトリ内のjarファイルをロードしその中のクラスがロードされていること.
* @throws Exception エラー
*/
@Test
@Ignore
// 子・孫ディレクトリの走査は中止したため、本テストは Skip.
// (背景には、extensionクラス用 propertyファイルの配置・優先順位等の仕様が明確化されていないことがあるため。)
public void 指定ディレクトリの孫ディレクトリ内のjarファイルをロードしその中のクラスがロードされていること() throws Exception {
String fileName = this.getClass().getClassLoader().getResource("extension").getPath();
// Extension用の jarファイルの置場所を指定。この下にはテスト用の jarファイルが置かれているものとする。
System.setProperty(ExtensionJarLoader.ENGINE_EXTENSION_DIR_KEY, fileName);
// テスト前に本テスト対象のクラスがデフォルトクラスローダにロードされていないことを確認
try {
this.getClass().getClassLoader().loadClass("com.fujitsu.test.dc.extension.NonRevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
try {
this.getClass().getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
try {
this.getClass().getClassLoader().loadClass("test.subdir.extension.Ext_RevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
try {
this.getClass().getClassLoader().loadClass("test.subdir.dc.extension.Ext_RevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
ExtensionJarLoader loader = ExtensionJarLoader.getInstance(this.getClass().getClassLoader(),
new JavaClassRevealFilter());
// ./testextension直下の jarファイル内クラス
Class<?> clazz1 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.NonRevealingClass");
assertNotNull(clazz1);
assertTrue(clazz1 instanceof Class);
assertFalse(ScriptableObject.class.isAssignableFrom(clazz1));
Class<?> clazz2 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
assertNotNull(clazz2);
assertTrue(clazz2 instanceof Class);
assertTrue(ScriptableObject.class.isAssignableFrom(clazz2));
// ./testextensionの子/孫サブディレクトリの jarファイル内クラス
Class<?> clazz3 = loader.getClassLoader().loadClass("test.subdir.dc.extension.NonRevealingClass");
assertNotNull(clazz3);
assertTrue(clazz3 instanceof Class);
assertFalse(ScriptableObject.class.isAssignableFrom(clazz3));
Class<?> clazz4 = loader.getClassLoader().loadClass("test.subdir.dc.extension.Ext_RevealingClass");
assertNotNull(clazz4);
assertTrue(clazz4 instanceof Class);
assertTrue(ScriptableObject.class.isAssignableFrom(clazz4));
// ScriptableObjectを継承した Revealingクラスが ExtensionJarLoaderに設定されていること。
Set<Class<? extends Scriptable>> set = loader.getPrototypeClassSet();
assertFalse(set.contains(clazz1));
assertTrue(set.contains(clazz2));
assertFalse(set.contains(clazz3));
assertTrue(set.contains(clazz4));
}
/**
* Extension用クラスのプロパティファイルがロードできること.
* @throws Exception エラー
*/
@Test
public void Extension用クラスのプロパティファイルがロードできること() throws Exception {
String fileName = this.getClass().getClassLoader().getResource("extension").getFile();
System.out.println("#####>>>> " + fileName);
// Extension用の jarファイルの置場所を指定。この下にはテスト用の jarファイルが置かれているものとする。
System.setProperty(ExtensionJarLoader.ENGINE_EXTENSION_DIR_KEY, fileName);
// テスト前に本テスト対象のクラスがデフォルトクラスローダにロードされていないことを確認
try {
this.getClass().getClassLoader().loadClass("com.fujitsu.test.dc.extension.NonRevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
try {
this.getClass().getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
fail("Target class is already loaded.");
} catch (ClassNotFoundException e) {
e.getMessage();
}
ExtensionJarLoader loader = ExtensionJarLoader.getInstance(this.getClass().getClassLoader(),
new JavaClassRevealFilter());
Class<?> clazz1 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.NonRevealingClass");
assertNotNull(clazz1);
assertTrue(clazz1 instanceof Class);
assertFalse(ScriptableObject.class.isAssignableFrom(clazz1));
Class<?> clazz2 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
assertNotNull(clazz2);
assertTrue(clazz2 instanceof Class);
assertTrue(ScriptableObject.class.isAssignableFrom(clazz2));
// ScriptableObjectを継承した Revealingクラスが ExtensionJarLoaderに設定されていること。
Set<Class<? extends Scriptable>> set = loader.getPrototypeClassSet();
assertFalse(set.contains(clazz1));
assertTrue(set.contains(clazz2));
// Ext_RevealingClass.properties の内容が読み取れることを確認
Object instance = clazz2.newInstance();
Method getPropMethod = instance.getClass().getMethod("getProperties", new Class[] {});
Object prop = getPropMethod.invoke(instance, new Object[] {});
assertTrue(prop instanceof Properties);
assertEquals(((Properties) prop).get("propKey"), "propValue");
}
/**
* 存在しないディレクトリをextension_jarフォルダとして指定した場合でも例外が発生しないこと.
* @throws Exception エラー
*/
@Test
public void 存在しないディレクトリをextension_jarフォルダとして指定した場合でも例外が発生しないこと() throws Exception {
// 存在しないディレクトリを指定
System.setProperty(ExtensionJarLoader.ENGINE_EXTENSION_DIR_KEY, "nonExistent");
ExtensionJarLoader loader = ExtensionJarLoader.getInstance(this.getClass().getClassLoader(),
new JavaClassRevealFilter());
try {
Class<?> clazz2 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
fail();
} catch (ClassNotFoundException e) {
assertTrue(true);
}
}
/**
* 空のディレクトリをextension_jarフォルダとして指定した場合でも例外が発生しないこと.
* @throws Exception エラー
*/
@Test
@Ignore
// Eclipseが、target/test-classesに空のディレクトリを作ってくれないので skip
public void 空のディレクトリをextension_jarフォルダとして指定した場合でも例外が発生しないこと() throws Exception {
String fileName = this.getClass().getClassLoader().getResource("emptyExtension").getFile();
System.out.println("#####>>>> " + fileName);
// Extension用の jarファイルの置場所を指定。この下にはテスト用の jarファイルが置かれているものとする。
System.setProperty(ExtensionJarLoader.ENGINE_EXTENSION_DIR_KEY, fileName);
ExtensionJarLoader loader = ExtensionJarLoader.getInstance(this.getClass().getClassLoader(),
new JavaClassRevealFilter());
try {
Class<?> clazz2 = loader.getClassLoader().loadClass("com.fujitsu.test.dc.extension.Ext_RevealingClass");
fail();
} catch (ClassNotFoundException e) {
assertTrue(true);
}
}
}