1, 概述

CTS(Compatibility Test Suite)全名兼容性测试,主要目的就是让Android设备开发商能够开发出兼容性更好的android设备。

本文的CTS源码基于android 5.1,和其他自动化测试指令一样,CTS测试命令也是通过脚本运行的。

CTS源码中的脚本路径: CTS/tools/tradefed-host/etc/ cts-tradefed

Linux环境中也是运行cts-tradefed脚本进行测试。

cts-tradefed脚本最后一行如下,

java $RDBG_FLAG \  -cp ${JAR_PATH} -DCTS_ROOT=${CTS_ROOT} com.android.cts.tradefed.command.CtsConsole "$@"

由此可见,android系统中测试的入口为CtsConsole.java类的main方法。

2,main方法

main方法的流程图如下,

CtsConsole的main方法如下,

public static void main(String[] args) throws InterruptedException, ConfigurationException {        Console console = new CtsConsole(); // 构造CtsConsole对象        Console.startConsole(console, args); // 调用父类的startConsole方法    }

CtsConsole继承于Console,而Console继承于Thread类。

startConsole方法如下,

public static void startConsole(Console console, String[] args)    throws InterruptedException, ConfigurationException  {    // 将命令参数复制到ArrayList中    List nonGlobalArgs = GlobalConfiguration.createGlobalConfiguration(args);      console.setArgs(nonGlobalArgs); // 将命令参数保存在变量mMainArgs中    console.setCommandScheduler(GlobalConfiguration.getInstance().getCommandScheduler());    console.setDaemon(true);    console.start(); // 启动线程 调用run方法    console.awaitScheduler();  }}

CtsConsole的run方法如下

@Override    public void run() {        printLine(String.format("Android CTS %s", CtsBuildProvider.CTS_BUILD_VERSION));        super.run();    }

首先看看打印信息的printLine方法,在父类Console中实现。

protected void printLine(String output)  {    System.out.print(output);    System.out.println();  }

Console的run方法会做一些检查,最后会调用executeCmdRunnable方法。然后回调内部类ArgRunnable的run方法。

2.1 任务添加

Console的run方法会还会调用CommandScheduler的start方法启动线程。

  this.mScheduler.start();      this.mScheduler.await();

ArgRunnable的run方法会调用CommandScheduler的addCommand方法添加任务。

addCommand调用流程图如下


internalAddCommand方法首先调用ConfigurationFactory的createConfigurationFromArgs方法解析配置文件,

然后根据配置文件的信息调用addExecCommandToQueue将执行计划放入到队列中。

private boolean internalAddCommand(String[] args, long totalExecTime, String cmdFilePath)    throws ConfigurationException  {    assertStarted();    IConfiguration config = getConfigFactory().createConfigurationFromArgs(args);   •••      config.validateOptions();      if (config.getCommandOptions().runOnAllDevices())      {        addCommandForAllDevices(totalExecTime, args, cmdFilePath);      }      else      {        CommandTracker cmdTracker = createCommandTracker(args, cmdFilePath);        cmdTracker.incrementExecTime(totalExecTime);        ExecutableCommand cmdInstance = createExecutableCommand(cmdTracker, config, false);        addExecCommandToQueue(cmdInstance, 0L);      }      return true;    }    return false;  }

addExecCommandToQueue方法如下,

private synchronized boolean addExecCommandToQueue(final ExecutableCommand cmd, long delayTime)  {    if (isShutdown()) {      return false;    }    if (delayTime > 0L)    {      this.mSleepingCommands.add(cmd);            Runnable delayCommand = new Runnable()      {        public void run()        {          synchronized (CommandScheduler.this)          {            if (CommandScheduler.this.mSleepingCommands.remove(cmd))            {              CommandScheduler.this.mReadyCommands.add(cmd);              CommandScheduler.this.mCommandProcessWait.signalEventReceived();            }          }        }      };      this.mCommandTimer.schedule(delayCommand, delayTime, TimeUnit.MILLISECONDS);    }    else    {      this.mReadyCommands.add(cmd);      this.mCommandProcessWait.signalEventReceived();    }    return true;  }

另外开一个线程利用回调添加任务,添加到mReadyCommands中

private List mReadyCommands;

2.2 组件配置

internalCreateConfigurationFromArgs方法如下,

private IConfiguration internalCreateConfigurationFromArgs(String[] arrayArgs, List optionArgsRef)    throws ConfigurationException  {    if (arrayArgs.length == 0) {      throw new ConfigurationException("Configuration to run was not specified");    }    optionArgsRef.addAll(Arrays.asList(arrayArgs));        String configName = (String)optionArgsRef.remove(0);    ConfigurationDef configDef = getConfigurationDef(configName, false);    return configDef.createConfiguration();  }

该方法中取出第一个参数cts然后传入getConfigurationDef方法中,获取ConfigurationDef对象。

ConfigurationDef根据测试指令配置相关属性,然后保存在变量中

private final Map> mObjectClassMap;  private final List mOptionList;  private final Map mClassFrequency;  private final String mName;

属性值的定义在Configuration中。

这样属性也配置好了,如果使用脚本执行CTS测试,每个CTS测试任务都会放入队列中,然后取出依次执行,直到所有执行完为止。

更多相关文章

  1. tcping测试服务器TCP端口
  2. 带你一步一步深入Handler源码,拿下面试官不在话下!
  3. 使用TestProject Python SDK创建移动Appium测试
  4. Android(安卓)Fragment中监听事件
  5. Dagger2使用详解
  6. android基础(1)
  7. Android(安卓)8.0指纹流程
  8. android中开启子线程
  9. Android离线Doc文档访问速度慢的有效解决方法

随机推荐

  1. Android内核源码交叉编译
  2. struts2服务端与android交互
  3. Activity属性设置大全
  4. 高焕堂android中文书全,电子文件for vers
  5. android 透明度
  6. android检测当前网络是否可用
  7. Android预定义样式
  8. 关于Android中xml布局文件
  9. Android全屏显示的两种方式
  10. android 几个常用命令