TestInvocation

  1. /**
  2. * {@inheritDoc}
  3. */
  4. @Override
  5. public void invoke(ITestDevice device, IConfiguration config, IRescheduler rescheduler) throws DeviceNotAvailableException, Throwable {
  6. try {
  7. mStatus = "fetching build";
  8. config.getLogOutput().init();
  9. getLogRegistry().registerLogger(config.getLogOutput());
  10. IBuildInfo info = null;
  11. if (config.getBuildProvider() instanceof IDeviceBuildProvider) {
  12. info = ((IDeviceBuildProvider) config.getBuildProvider()).getBuild(device);
  13. } else if (config.getBuildProvider() instanceof IDeviceConfigBuildProvider) {
  14. // 调用config获得cts.xml文件里的<build_provider>标签中相应的类,然后通过调用getBuild得到IBuildInfo对象
  15. info = ((IDeviceConfigBuildProvider) config.getBuildProvider()).getBuild(device, config);
  16. } else {
  17. info = config.getBuildProvider().getBuild();
  18. }
  19. if (info != null) {
  20. // System.out.println(String.format("setup: %s tearDown: %s",
  21. // config.getCommandOptions().isNeedPrepare(),
  22. // config.getCommandOptions().isNeedTearDown()));
  23. CLog.logAndDisplay(LogLevel.INFO,
  24. String.format("setup: %s tearDown: %s", config.getCommandOptions().isNeedPrepare(), config.getCommandOptions().isNeedTearDown()));
  25. // 获取<test>配置项里的測试选项,并注入到info中
  26. injectBuild(info, config.getTests());
  27. if (shardConfig(config, info, rescheduler)) {
  28. CLog.i("Invocation for %s has been sharded, rescheduling", device.getSerialNumber());
  29. } else {
  30. device.setRecovery(config.getDeviceRecovery());
  31. // 准备刷机,启动case
  32. performInvocation(config, device, info, rescheduler);
  33. // exit here, depend on performInvocation to deregister
  34. // logger
  35. return;
  36. }
  37. } else {
  38. mStatus = "(no build to test)";
  39. CLog.d("No build to test");
  40. rescheduleTest(config, rescheduler);
  41. }
  42. } catch (BuildRetrievalError e) {
  43. CLog.e(e);
  44. /*
  45. * because this is BuildRetrievalError, so do not generate test
  46. * result // report an empty invocation, so this error is sent to
  47. * listeners startInvocation(config, device, e.getBuildInfo()); //
  48. * don't want to use #reportFailure, since that will call
  49. * buildNotTested for (ITestInvocationListener listener :
  50. * config.getTestInvocationListeners()) {
  51. * listener.invocationFailed(e); } reportLogs(device,
  52. * config.getTestInvocationListeners(), config.getLogOutput());
  53. * InvocationSummaryHelper.reportInvocationEnded(
  54. * config.getTestInvocationListeners(), 0); return;
  55. */
  56. } catch (IOException e) {
  57. CLog.e(e);
  58. }
  59. // save current log contents to global log
  60. getLogRegistry().dumpToGlobalLog(config.getLogOutput());
  61. getLogRegistry().unregisterLogger();
  62. config.getLogOutput().closeLog();
  63. }

之所以称为调度室,由于它就是去一步一步的执行9大组件的剩余组件,组件与组件之间并不知道对方的存在,仅仅有TestInvocation自己知道。它通过反射的机制到的对象,别创建对象,然后调用当中的接口方法得到它想要的,然后再传给下一个组件。以上方法就能够看出,它先得到buildprovider对象。调用getBuild对象得到IBuildInfo对象。咱们这个程序中,事实上就是调用了CtsBuildProvider的getBuild方法。

假设info不为null:然后给測试任务注入IBuildInfo,推断能否够分拆任务,假设不能分拆的话,注冊设备恢复类,然后跳转到performInvocation方法中。

假设info为null:提示没有可运行的build,调用IRescheduler.rescheduleCommand()重试。

  1. /**
  2. * Performs the invocation
  3. *
  4. * @param config
  5. * the {@link IConfiguration}
  6. * @param device
  7. * the {@link ITestDevice} to use. May be <code>null</code>
  8. * @param info
  9. * the {@link IBuildInfo}
  10. */
  11. private void performInvocation(IConfiguration config, ITestDevice device, IBuildInfo info, IRescheduler rescheduler) throws Throwable {
  12.  
  13. boolean resumed = false;
  14. long startTime = System.currentTimeMillis();
  15. long elapsedTime = -1;
  16.  
  17. info.setDeviceSerial(device.getSerialNumber());
  18. startInvocation(config, device, info);
  19. try {
  20. device.setOptions(config.getDeviceOptions());
  21. // 准备build和跑case
  22. prepareAndRun(config, device, info, rescheduler);
  23. } catch (BuildError e) {
  24. CLog.w("Build %s failed on device %s. Reason: %s", info.getBuildId(), device.getSerialNumber(), e.toString());
  25. takeBugreport(device, config.getTestInvocationListeners(), BUILD_ERROR_BUGREPORT_NAME);
  26. reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
  27. } catch (TargetSetupError e) {
  28. CLog.e("Caught exception while running invocation");
  29. CLog.e(e);
  30. reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
  31. // maybe test device if offline, check it
  32. device.waitForDeviceOnline();
  33. } catch (DeviceNotAvailableException e) {
  34. // log a warning here so its captured before reportLogs is called
  35. CLog.w("Invocation did not complete due to device %s becoming not available. " + "Reason: %s", device.getSerialNumber(), e.getMessage());
  36. if ((e instanceof DeviceUnresponsiveException) && TestDeviceState.ONLINE.equals(device.getDeviceState())) {
  37. // under certain cases it might still be possible to grab a
  38. // bugreport
  39. takeBugreport(device, config.getTestInvocationListeners(), DEVICE_UNRESPONSIVE_BUGREPORT_NAME);
  40. }
  41. resumed = resume(config, info, rescheduler, System.currentTimeMillis() - startTime);
  42. if (!resumed) {
  43. reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
  44. } else {
  45. CLog.i("Rescheduled failed invocation for resume");
  46. }
  47. throw e;
  48. } catch (RuntimeException e) {
  49. // log a warning here so its captured before reportLogs is called
  50. CLog.w("Unexpected exception when running invocation: %s", e.toString());
  51. reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
  52. throw e;
  53. } catch (AssertionError e) {
  54. CLog.w("Caught AssertionError while running invocation: ", e.toString());
  55. reportFailure(e, config.getTestInvocationListeners(), config, info, rescheduler);
  56. } finally {
  57. mStatus = "done running tests";
  58. try {
  59. //
  60. reportLogs(device, config.getTestInvocationListeners(), config.getLogOutput());
  61. elapsedTime = System.currentTimeMillis() - startTime;
  62. if (!resumed) {
  63. // 发送报告
  64. InvocationSummaryHelper.reportInvocationEnded(config.getTestInvocationListeners(), elapsedTime);
  65. }
  66.  
  67. } finally {
  68. config.getBuildProvider().cleanUp(info);
  69. }
  70. }
  71. }

首先启动全部监听器的start方法,起一个通知開始的作用。

  1. /**
  2. * Starts the invocation.
  3. * <p/>
  4. * Starts logging, and informs listeners that invocation has been started.
  5. *
  6. * @param config
  7. * @param device
  8. * @param info
  9. */
  10. private void startInvocation(IConfiguration config, ITestDevice device, IBuildInfo info) {
  11. logStartInvocation(info, device);
  12. for (ITestInvocationListener listener : config.getTestInvocationListeners()) {
  13. try {
  14. listener.invocationStarted(info);
  15. } catch (RuntimeException e) {
  16. // don't let one listener leave the invocation in a bad state
  17. CLog.e("Caught runtime exception from ITestInvocationListener");
  18. CLog.e(e);
  19. }
  20. }
  21. }

然后得到device_options对象,设置到ITestDevice中。再调用prepareAndRun(config, device, info, rescheduler);方法。

  1. private void prepareAndRun(IConfiguration config, ITestDevice device, IBuildInfo info, IRescheduler rescheduler) throws Throwable {
  2. // use the JUnit3 logic for handling exceptions when running tests
  3. Throwable exception = null;
  4.  
  5. try {
  6. //
  7. if (config.getCommandOptions().isNeedPrepare()&&!isRepeat) {
  8. doSetup(config, device, info);
  9. //下次启动的时候,不再刷机
  10. isRepeat = true;
  11. }else{
  12. CLog.logAndDisplay(LogLevel.DEBUG, String.format("No need to flash,derect to run case"));
  13. }
  14. // 跑case
  15. runTests(device, info, config, rescheduler);
  16. } catch (Throwable running) {
  17. exception = running;
  18. } finally {
  19. try {
  20. if (config.getCommandOptions().isNeedTearDown()) {
  21. doTeardown(config, device, info, exception);
  22. }
  23. } catch (Throwable tearingDown) {
  24. if (exception == null) {
  25. exception = tearingDown;
  26. }
  27. }
  28. }
  29. if (exception != null) {
  30. throw exception;
  31. }
  32. }

在该方法中先得到依据cmd_options得到是否须要prepare,假设须要,就调用target_prepare类来做准备工作,假设不须要,直接调用runTests方法

  1. private void runTests(ITestDevice device, IBuildInfo buildInfo, IConfiguration config, IRescheduler rescheduler) throws DeviceNotAvailableException {
  2. List<ITestInvocationListener> listeners = config.getTestInvocationListeners();
  3. for (IRemoteTest test : config.getTests()) {
  4. if (test instanceof IDeviceTest) {
  5. ((IDeviceTest) test).setDevice(device);
  6. }
  7. test.run(new ResultForwarder(listeners));
  8. }
  9. }

上面的方法调用tests配置的类来追个调用里面的run方法启动測试。測试完毕后,来做tearDown的工作。

Cts框架解析(7)-任务运行的调度室的更多相关文章

  1. Cts框架解析(15)-任务运行完

    case运行完成后.会回到CtsTest的run方法中: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRmb290YmFsbA==/font/5a6L ...

  2. Cts框架解析(2)-cts调试环境的搭建

    上一篇文章中说了怎样在windows搭建cts以及执行cts进行測试.这篇文章来讲讲怎样在eclipse中配置源代码,进行debug调试. 下载 cts源代码地址:https://android.go ...

  3. Cts框架解析(6)-任务的运行

    前两篇讲了任务的加入和9大项配置,这篇讲任务的运行. 任务的运行 任务的运行在CommandScheduler的run方法中,所以删除全部的断点,在run方法中打上断点,重新启动启动debug: 先看 ...

  4. Cts框架解析(1)-windows下cts配置

    环境搭建 下载 cts工具的下载地址:http://source.android.com/compatibility/downloads.html windows选择Android4.4 R3 Com ...

  5. Cts框架解析(8)-IBuildProvider

    IBuildProvider接口中定义了三个方法 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under ...

  6. Cts框架解析(12)-ITargetPreparer

    測试开启前的设备系统准备工作. 接口 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Ap ...

  7. [转载]iOS 10 UserNotifications 框架解析

    活久见的重构 - iOS 10 UserNotifications 框架解析 TL;DR iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifica ...

  8. iOS 10 UserNotifications 框架解析

    摘自:https://onevcat.com/2016/08/notification/ iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifica ...

  9. Poco::TCPServer框架解析

    Poco::TCPServer框架解析 POCO C++ Libraries提供一套 C++ 的类库用以开发基于网络的可移植的应用程序,功能涉及线程.文件.流,网络协议包括:HTTP.FTP.SMTP ...

随机推荐

  1. poj2752 Seek the Name, Seek the Fame(next数组的运用)

    题目链接:id=2752" style="color:rgb(202,0,0); text-decoration:none; font-family:Arial; font-siz ...

  2. GIT用服务器上的版本强制覆盖掉本地的版本(转)

    以前在机子上使用git下载了linux git版本库上的源代码,由于在阅读源代码的过程中,难免会对本地的文件进行修改,这样就导致本地文件与服务器上的文件版本不一致,我想做的就是用服务器上的版本强制覆盖 ...

  3. ios 仿新浪微博 UINavigationController 向左滑动时显示上一个控制器的View.

    仿新浪微博 UINavigationController 向左滑动时显示上一个控制器的View. 实现原理,UINavigationController 的 self.view显示时把当前显示的vie ...

  4. 取证学习资料DVD

    http://www.infiniteskills.com/training/learning-computer-forensics.html https://www.youtube.com/watc ...

  5. Lucene40SkipListWriter

    多级跳跃表是保存在tim文件里的. tip是term index,tim是term dictionary.记忆方法是,p是pointer因此是term index. 这个类会保存多个level的las ...

  6. 全文检索引擎Solr 指南

    全文检索引擎Solr系列:第一篇:http://t.cn/RP004gl.第二篇:http://t.cn/RPHDjk7 .第三篇:http://t.cn/RPuJt3T

  7. A. Initial Bet(Codeforces Round #273)

    A. Initial Bet time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  8. [Erlang危机](5.1.0)VM检测概述

    原创文章.转载请注明出处:server非业余研究http://blog.csdn.net/erlib 作者Sunface 把执行指标储存在VM的内存中.能够指定是全局的还是app所特有的. • vms ...

  9. leetcode——Evaluate Reverse Polish Notation 求算式值(AC)

    Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...

  10. iOS开发那些事-iOS6苹果地图有用开发

    在iOS 6之后,不再使用谷歌地图了,而是使用苹果自己的地图,可是API编程接口没有太大的变化.开发者不须要再学习非常多新东西就能开发地图应用,这是负责任的做法.因此本节介绍的内容也相同适用于iOS5 ...