Cts框架解析(7)-任务运行的调度室
TestInvocation
/**
* {@inheritDoc}
*/
@Override
public void invoke(ITestDevice device, IConfiguration config, IRescheduler rescheduler) throws DeviceNotAvailableException, Throwable {
try {
mStatus = "fetching build";
config.getLogOutput().init();
getLogRegistry().registerLogger(config.getLogOutput());
IBuildInfo info = null;
if (config.getBuildProvider() instanceof IDeviceBuildProvider) {
info = ((IDeviceBuildProvider) config.getBuildProvider()).getBuild(device);
} else if (config.getBuildProvider() instanceof IDeviceConfigBuildProvider) {
// 调用config获得cts.xml文件里的<build_provider>标签中相应的类,然后通过调用getBuild得到IBuildInfo对象
info = ((IDeviceConfigBuildProvider) config.getBuildProvider()).getBuild(device, config);
} else {
info = config.getBuildProvider().getBuild();
}
if (info != null) {
// System.out.println(String.format("setup: %s tearDown: %s",
// config.getCommandOptions().isNeedPrepare(),
// config.getCommandOptions().isNeedTearDown()));
CLog.logAndDisplay(LogLevel.INFO,
String.format("setup: %s tearDown: %s", config.getCommandOptions().isNeedPrepare(), config.getCommandOptions().isNeedTearDown()));
// 获取<test>配置项里的測试选项,并注入到info中
injectBuild(info, config.getTests());
if (shardConfig(config, info, rescheduler)) {
CLog.i("Invocation for %s has been sharded, rescheduling", device.getSerialNumber());
} else {
device.setRecovery(config.getDeviceRecovery());
// 准备刷机,启动case
performInvocation(config, device, info, rescheduler);
// exit here, depend on performInvocation to deregister
// logger
return;
}
} else {
mStatus = "(no build to test)";
CLog.d("No build to test");
rescheduleTest(config, rescheduler);
}
} catch (BuildRetrievalError e) {
CLog.e(e);
/*
* because this is BuildRetrievalError, so do not generate test
* result // report an empty invocation, so this error is sent to
* listeners startInvocation(config, device, e.getBuildInfo()); //
* don't want to use #reportFailure, since that will call
* buildNotTested for (ITestInvocationListener listener :
* config.getTestInvocationListeners()) {
* listener.invocationFailed(e); } reportLogs(device,
* config.getTestInvocationListeners(), config.getLogOutput());
* InvocationSummaryHelper.reportInvocationEnded(
* config.getTestInvocationListeners(), 0); return;
*/
} catch (IOException e) {
CLog.e(e);
}
// save current log contents to global log
getLogRegistry().dumpToGlobalLog(config.getLogOutput());
getLogRegistry().unregisterLogger();
config.getLogOutput().closeLog();
}
之所以称为调度室,由于它就是去一步一步的执行9大组件的剩余组件,组件与组件之间并不知道对方的存在,仅仅有TestInvocation自己知道。它通过反射的机制到的对象,别创建对象,然后调用当中的接口方法得到它想要的,然后再传给下一个组件。以上方法就能够看出,它先得到buildprovider对象。调用getBuild对象得到IBuildInfo对象。咱们这个程序中,事实上就是调用了CtsBuildProvider的getBuild方法。
假设info不为null:然后给測试任务注入IBuildInfo,推断能否够分拆任务,假设不能分拆的话,注冊设备恢复类,然后跳转到performInvocation方法中。
假设info为null:提示没有可运行的build,调用IRescheduler.rescheduleCommand()重试。
/**
* Performs the invocation
*
* @param config
* the {@link IConfiguration}
* @param device
* the {@link ITestDevice} to use. May be <code>null</code>
* @param info
* the {@link IBuildInfo}
*/
private void performInvocation(IConfiguration config, ITestDevice device, IBuildInfo info, IRescheduler rescheduler) throws Throwable { boolean resumed = false;
long startTime = System.currentTimeMillis();
long elapsedTime = -1; info.setDeviceSerial(device.getSerialNumber());
startInvocation(config, device, info);
try {
device.setOptions(config.getDeviceOptions());
// 准备build和跑case
prepareAndRun(config, device, info, rescheduler);
} catch (BuildError e) {
CLog.w("Build %s failed on device %s. Reason: %s", info.getBuildId(), device.getSerialNumber(), e.toString());
takeBugreport(device, config.getTestInvocationListeners(), BUILD_ERROR_BUGREPORT_NAME);
reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
} catch (TargetSetupError e) {
CLog.e("Caught exception while running invocation");
CLog.e(e);
reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
// maybe test device if offline, check it
device.waitForDeviceOnline();
} catch (DeviceNotAvailableException e) {
// log a warning here so its captured before reportLogs is called
CLog.w("Invocation did not complete due to device %s becoming not available. " + "Reason: %s", device.getSerialNumber(), e.getMessage());
if ((e instanceof DeviceUnresponsiveException) && TestDeviceState.ONLINE.equals(device.getDeviceState())) {
// under certain cases it might still be possible to grab a
// bugreport
takeBugreport(device, config.getTestInvocationListeners(), DEVICE_UNRESPONSIVE_BUGREPORT_NAME);
}
resumed = resume(config, info, rescheduler, System.currentTimeMillis() - startTime);
if (!resumed) {
reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
} else {
CLog.i("Rescheduled failed invocation for resume");
}
throw e;
} catch (RuntimeException e) {
// log a warning here so its captured before reportLogs is called
CLog.w("Unexpected exception when running invocation: %s", e.toString());
reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
throw e;
} catch (AssertionError e) {
CLog.w("Caught AssertionError while running invocation: ", e.toString());
reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
} finally {
mStatus = "done running tests";
try {
//
reportLogs(device, config.getTestInvocationListeners(), config.getLogOutput());
elapsedTime = System.currentTimeMillis() - startTime;
if (!resumed) {
// 发送报告
InvocationSummaryHelper.reportInvocationEnded(config.getTestInvocationListeners(), elapsedTime);
} } finally {
config.getBuildProvider().cleanUp(info);
}
}
}
首先启动全部监听器的start方法,起一个通知開始的作用。
/**
* Starts the invocation.
* <p/>
* Starts logging, and informs listeners that invocation has been started.
*
* @param config
* @param device
* @param info
*/
private void startInvocation(IConfiguration config, ITestDevice device, IBuildInfo info) {
logStartInvocation(info, device);
for (ITestInvocationListener listener : config.getTestInvocationListeners()) {
try {
listener.invocationStarted(info);
} catch (RuntimeException e) {
// don't let one listener leave the invocation in a bad state
CLog.e("Caught runtime exception from ITestInvocationListener");
CLog.e(e);
}
}
}
然后得到device_options对象,设置到ITestDevice中。再调用prepareAndRun(config, device, info, rescheduler);方法。
private void prepareAndRun(IConfiguration config, ITestDevice device, IBuildInfo info, IRescheduler rescheduler) throws Throwable {
// use the JUnit3 logic for handling exceptions when running tests
Throwable exception = null; try {
//
if (config.getCommandOptions().isNeedPrepare()&&!isRepeat) {
doSetup(config, device, info);
//下次启动的时候,不再刷机
isRepeat = true;
}else{
CLog.logAndDisplay(LogLevel.DEBUG, String.format("No need to flash,derect to run case"));
}
// 跑case
runTests(device, info, config, rescheduler);
} catch (Throwable running) {
exception = running;
} finally {
try {
if (config.getCommandOptions().isNeedTearDown()) {
doTeardown(config, device, info, exception);
}
} catch (Throwable tearingDown) {
if (exception == null) {
exception = tearingDown;
}
}
}
if (exception != null) {
throw exception;
}
}
在该方法中先得到依据cmd_options得到是否须要prepare,假设须要,就调用target_prepare类来做准备工作,假设不须要,直接调用runTests方法
private void runTests(ITestDevice device, IBuildInfo buildInfo, IConfiguration config, IRescheduler rescheduler) throws DeviceNotAvailableException {
List<ITestInvocationListener> listeners = config.getTestInvocationListeners();
for (IRemoteTest test : config.getTests()) {
if (test instanceof IDeviceTest) {
((IDeviceTest) test).setDevice(device);
}
test.run(new ResultForwarder(listeners));
}
}
上面的方法调用tests配置的类来追个调用里面的run方法启动測试。測试完毕后,来做tearDown的工作。
Cts框架解析(7)-任务运行的调度室的更多相关文章
- Cts框架解析(15)-任务运行完
case运行完成后.会回到CtsTest的run方法中: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRmb290YmFsbA==/font/5a6L ...
- Cts框架解析(2)-cts调试环境的搭建
上一篇文章中说了怎样在windows搭建cts以及执行cts进行測试.这篇文章来讲讲怎样在eclipse中配置源代码,进行debug调试. 下载 cts源代码地址:https://android.go ...
- Cts框架解析(6)-任务的运行
前两篇讲了任务的加入和9大项配置,这篇讲任务的运行. 任务的运行 任务的运行在CommandScheduler的run方法中,所以删除全部的断点,在run方法中打上断点,重新启动启动debug: 先看 ...
- Cts框架解析(1)-windows下cts配置
环境搭建 下载 cts工具的下载地址:http://source.android.com/compatibility/downloads.html windows选择Android4.4 R3 Com ...
- Cts框架解析(8)-IBuildProvider
IBuildProvider接口中定义了三个方法 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under ...
- Cts框架解析(12)-ITargetPreparer
測试开启前的设备系统准备工作. 接口 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Ap ...
- [转载]iOS 10 UserNotifications 框架解析
活久见的重构 - iOS 10 UserNotifications 框架解析 TL;DR iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifica ...
- iOS 10 UserNotifications 框架解析
摘自:https://onevcat.com/2016/08/notification/ iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifica ...
- Poco::TCPServer框架解析
Poco::TCPServer框架解析 POCO C++ Libraries提供一套 C++ 的类库用以开发基于网络的可移植的应用程序,功能涉及线程.文件.流,网络协议包括:HTTP.FTP.SMTP ...
随机推荐
- hadoop学习;自己定义Input/OutputFormat;类引用mapreduce.mapper;三种模式
hadoop切割与读取输入文件的方式被定义在InputFormat接口的一个实现中.TextInputFormat是默认的实现,当你想要一次获取一行内容作为输入数据时又没有确定的键.从TextInpu ...
- Cocos2d-x 3.0 红孩儿私人义务教育 - 第一章 熟人Cocos2d-x 3.0project
Cocos2d-x 3.0 红孩儿私家必修 前言: 时光飞逝,每每看到博客上的回复和微博上的鼓舞,总会认为亏欠大家点什么.停下来太久.总是认为不太对劲,哈哈,时习之吧,望以此勉励大家. 红孩儿C ...
- Visual Studio Tips: How to change project namespace
/* Author: Jiangong SUN */ If you want to modify a project's namespace and its physical container na ...
- An Overview of Complex Event Processing
An Overview of Complex Event Processing 复杂事件处理技术概览(一) 翻译前言:我在理解复杂事件处理(CEP)方面一直有这样的困惑--为什么这种计算模式是有效的, ...
- current online redo logfile 丢失的处理方法
昨天做了rm -rf操作后的恢复演练,并且是在没有不论什么备份的情况下.今天在做破坏性操作前,做了个rman全备,然后在线删除所有数据库文件,包含控制文件,数据文件,在线日志文件,归档文件等.来看看有 ...
- 无法识别的属性“targetFramework”。请注意,属性名是大写和小写。错误的解决方案
"/CRM"应用server错. 配置错误 说明: 在处理向该请求提供服务所需的配置文件时出错.请检查以下的特定错误具体信息并适当地改动配置文件. 分析器错误消息: 无法识别的属性 ...
- checkbox的attr("checked")一直以来,undefined问题解决
最近,屌丝要项目开发的需要,需要一个完整的选checkbox特征. 该死的~~这不是很easy什么东西,共checkbox,N多个子的checkbox,总checkbox一旦选定,儿checkbox所 ...
- Android程序猿学习路径
而一些工作,而不仅仅是通信毕业生,很多学生没有工作或熟练Android工作人员指导的情况下,,如何学习Android而提高Android更多关注的水平. 享: 1.Android知识 1.1.站点资源 ...
- 利用HttpOnly来防御xss攻击
xss的概念就不用多说了,它的危害是极大的,这就意味着一旦你的站点出现xss漏洞,就能够运行随意的js代码,最可怕的是攻击者利用js获取cookie或者session劫持,假设这里面包括了大量敏感信息 ...
- OpenGL之路(八)加入�光照效果和键盘控制
在opengl中加入�光照的效果,可用键盘控制放大缩小 w键放大 s键缩小 d键开关灯 预览效果例如以下: 源代码例如以下: #include <gl/glut.h> #include & ...