/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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.alibaba.citrus.test;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import com.alibaba.citrus.logconfig.LogConfigurator;
/**
* 用来初始化测试环境的辅助类。
* <p>
* 单元测试要尽可能独立于其它项目。该辅助类帮助单元测试从当前项目的相对路径中取得所有资源文件,包括:
* </p>
* <ul>
* <li>测试根目录<code>basedir</code>,默认为项目根目录。</li>
* <li>测试源文件目录<code>srcdir</code>,默认为<code>${basedir}/src/test/config/</code>。</li>
* <li>测试目标目录<code>destdir</code>,默认为<code>${basedir}/target/test/</code>。</li>
* <li>Logback日志文件,默认为<code>${srcdir}/logback.xml</code>,假如找不到,则使用默认的配置:
* <ul>
* <li><code>WARN</code>以下打印到<code>System.out</code>。</li>
* <li><code>WARN</code>以上打印到<code>System.err</code>。</li>
* <li>所有日志同时打印到<code>${destdir}/test.log</code>。</li>
* </ul>
* </li>
* </ul>
*
* @author Michael Zhou
*/
public class TestEnv {
private Params params = createParams();
private File basedir;
private File srcdir;
private File destdir;
public TestEnv setBasedir(String basedir) {
getParams().basedirParam = basedir;
return this;
}
public TestEnv setSrcdir(String srcdir) {
getParams().srcdirParam = srcdir;
return this;
}
public TestEnv setDestdir(String destdir) {
getParams().destdirParam = destdir;
return this;
}
public TestEnv setLogbackConfig(String logbackConfig) {
getParams().logbackConfigParam = logbackConfig;
return this;
}
public TestEnv setInitFailure(Exception initFailure) {
getParams().initFailure = initFailure;
return this;
}
public TestEnv init() {
Params params = getParams();
if (params.inited) {
return this;
}
params.inited = true;
try {
setupDirectories();
URL logConfigFile = null;
if (getParams().logbackConfigParam != null) {
logConfigFile = findLogbackXml();
}
System.out.println("+-----------------------------------------------------------------------------");
setupLogback(logConfigFile);
} catch (Exception e) {
params.initFailure = e;
}
return this;
}
/** 初始化basedir, srcdir和destdir等。 */
private void setupDirectories() throws IOException {
Params params = getParams();
basedir = new File(params.basedirParam).getCanonicalFile();
srcdir = new File(basedir, params.srcdirParam);
destdir = new File(basedir, params.destdirParam);
if (!destdir.exists()) {
destdir.mkdirs();
}
if (!destdir.isDirectory() || !destdir.exists()) {
throw new IllegalArgumentException("Destination directory does not exist: " + destdir);
}
System.out.println("+-----------------------------------------------------------------------------");
System.out.println("| Set base dir to: " + basedir);
System.out.println("| Set source dir to: " + srcdir);
System.out.println("| Set destination dir to: " + destdir);
}
/** 初始化logback.xml,可用${basedir}, ${srcdir}, ${destdir}。 */
private void setupLogback(URL logConfigFile) throws IOException {
if (logConfigFile == null) {
return;
}
LogConfigurator configurator = LogConfigurator.getConfigurator("logback");
Map<String, String> props = configurator.getDefaultProperties(false);
props.put("basedir", basedir.getAbsolutePath());
props.put("srcdir", srcdir.getAbsolutePath());
props.put("destdir", destdir.getAbsolutePath());
props.put("loggingRoot", destdir.getAbsolutePath());
configurator.configure(logConfigFile, props);
}
private URL findLogbackXml() throws IOException {
File test = new File(srcdir, getParams().logbackConfigParam);
URL logbackXml;
if (test.exists()) {
logbackXml = test.toURI().toURL();
} else {
URL testURL = getClass().getResource("logback-test-default.xml");
if (testURL == null) {
throw new IllegalArgumentException("missing logback-test-default.xml");
}
logbackXml = testURL;
}
System.out.println("| Initializing log system: " + logbackXml.toExternalForm());
return logbackXml;
}
public File getBasedir() {
assertInited();
return basedir;
}
public File getSrcdir() {
assertInited();
return srcdir;
}
public File getDestdir() {
assertInited();
return destdir;
}
protected final void assertInited() {
if (params == null) {
return;
}
if (!params.inited) {
throw new IllegalStateException("Not inited yet!");
}
Exception initFailure = params.initFailure;
params = null;
if (initFailure != null) {
if (initFailure instanceof RuntimeException) {
throw (RuntimeException) initFailure;
} else {
throw new RuntimeException(initFailure);
}
}
}
/**
* 取得初始化参数。
* <p>
* 在初始化完成以后,将返回<code>null</code>。
* </p>
*/
protected final Params getParams() {
if (params == null) {
throw new IllegalStateException();
}
return params;
}
/**
* 创建初始化参数。
* <p>
* 子类可扩展该参数。
* </p>
*/
protected Params createParams() {
return new Params();
}
/** 初始化参数。 */
protected class Params {
public String basedirParam = ".";
public String srcdirParam = "src/test/config/";
public String destdirParam = "target/test/";
public String logbackConfigParam = "logback.xml"; // 相对于srcdir
public Exception initFailure = null;
public boolean inited = false;
}
}