博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cts框架解析(7)-任务运行的调度室
阅读量:6501 次
发布时间:2019-06-24

本文共 8064 字,大约阅读时间需要 26 分钟。

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文件里的
标签中相应的类,然后通过调用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())); // 获取
配置项里的測试选项,并注入到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 null	 * @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.	 * 

* 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
listeners = config.getTestInvocationListeners(); for (IRemoteTest test : config.getTests()) { if (test instanceof IDeviceTest) { ((IDeviceTest) test).setDevice(device); } test.run(new ResultForwarder(listeners)); } }
上面的方法调用tests配置的类来追个调用里面的run方法启动測试。測试完毕后,来做tearDown的工作。

转载地址:http://xyvyo.baihongyu.com/

你可能感兴趣的文章
三层架构
查看>>
Python变量类型(l整型,长整形,浮点型,复数,列表,元组,字典)学习
查看>>
解决方案(.sln)文件
查看>>
理解cookie和session机制
查看>>
【Treap】bzoj1588-HNOI2002营业额统计
查看>>
第六周作业
查看>>
利用ZYNQ SOC快速打开算法验证通路(5)——system generator算法IP导入IP integrator
查看>>
指针和引用的区别
查看>>
转:strcat与strcpy与strcmp与strlen
查看>>
运行PHP出现No input file specified错误解决办法
查看>>
【重建】从FJOI2016一试谈起
查看>>
selenium之frame操作
查看>>
php 引入其他文件中的变量
查看>>
MYSQL体系结构-来自期刊
查看>>
PHP——图片上传
查看>>
mysql的基本知识
查看>>
exchange 2003配置ASSP 反垃圾邮件
查看>>
CQRS学习——最小单元的Cqrs(CommandEvent)[其一]
查看>>
webpack入门(二)what is webpack
查看>>
UnitOfWork以及其在ABP中的应用
查看>>