[Android]CTS Fail项分析方法

[Android]CTS Fail项分析方法

常规步骤为:

  • 通跑某一模块;
  • 查看测试结果;
  • 对Fail项进行单跑;
  • 辅助信息抓取;

通跑某一模块

以网络模块为例,通过如下测试项为例,在cts-tradefed交互界面输入list m可查看与之对应的待测模块(modules):

cts-tf > list m
...
CtsNetTestCases
...

从中可以看到,CtsNetTestCases明显是网络相关的测试模块,因此执行:

cts-tf > run cts -m CtsNetTestCases

可开始该模块的完整测试;

查看测试结果

测试结果存放目录:${cts_root}/results/

文件夹命名格式:yyyy.MM.dd_HH.mm.ss(例如2021.12.28_15.18.09

如果是最近一次测试结果,可直接在这里找到:${cts_root}/results/latest

查看Fail项可直接使用浏览器打开目录下的test_result_failures.html文件即可;

对Fail项进行单跑

还是以CtsNetTestCases的测试结果为例,比如在test_result_failures.html中显示,如下这项测试Fail:

android.net.cts.ConnectivityManagerTest#testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent

则可在cts-tradefed交互界面输入时添加-t参数,接上上面的测试项名称,对单项进行单跑:

cts-tf > run cts -m CtsNetTestCases -t android.net.cts.ConnectivityManagerTest#testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent

如果是网络不稳定导致的Fail,多单跑几次,一般可以PASS;

但如果遇到逻辑上的Fail项,且从日志中也无法确认原因的,则想办法添加辅助信息,并抓取后分析了;

辅助信息抓取

以上面提到的android.net.cts.ConnectivityManagerTest#testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent测试项为例,通过测试项名称,可以快速定位到源码中对应的代码:

类名:  android.net.cts.ConnectivityManagerTest
方法名:testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent

注意:源码中的代码并不一定与当前CTS版本完全一致,只能作为参考,若需要获取完全对应的,可下载AOSP源码,并checkout到对应的分支(tag)后,使用同样方法查看代码;

通过查找,可知ConnectivityManagerTest类在这里:

cts/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java

结合cts-tradefed交互界面的异常栈信息:

12-29 10:03:34 I/ConsoleReporter: [1/1 arm64-v8a CtsNetTestCases 1234567] android.net.cts.ConnectivityManagerTest#testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent fail: junit.framework.AssertionFailedError
    at junit.framework.Assert.fail(Assert.java:48)
    at junit.framework.Assert.assertTrue(Assert.java:20)
    at junit.framework.Assert.assertTrue(Assert.java:27)
    at android.net.cts.ConnectivityManagerTest.testHttpRequest(ConnectivityManagerTest.java:724)
    at android.net.cts.ConnectivityManagerTest.disconnectFromWifi(ConnectivityManagerTest.java:744)
    at android.net.cts.ConnectivityManagerTest.toggleWifi(ConnectivityManagerTest.java:663)
    at android.net.cts.ConnectivityManagerTest.testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent(ConnectivityManagerTest.java:636)
    at java.lang.reflect.Method.invoke(Native Method)
    at junit.framework.TestCase.runTest(TestCase.java:168)
    at junit.framework.TestCase.runBare(TestCase.java:134)
    at junit.framework.TestResult$1.protect(TestResult.java:115)
    at androidx.test.internal.runner.junit3.AndroidTestResult.runProtected(AndroidTestResult.java:73)
    at junit.framework.TestResult.run(TestResult.java:118)
    at androidx.test.internal.runner.junit3.AndroidTestResult.run(AndroidTestResult.java:51)
    at junit.framework.TestCase.run(TestCase.java:124)
    at androidx.test.internal.runner.junit3.NonLeakyTestSuite$NonLeakyTest.run(NonLeakyTestSuite.java:62)
    at androidx.test.internal.runner.junit3.AndroidTestSuite$2.run(AndroidTestSuite.java:101)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:764)

可知问题发生在android.net.cts.ConnectivityManagerTest.testHttpRequest(同理,行数参考意义不大,重点关注方法调用即可)
从而快速定位到Fail的原因:

    private void testHttpRequest(Socket s) throws IOException {
        OutputStream out = s.getOutputStream();
        InputStream in = s.getInputStream();

        final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
        byte[] responseBytes = new byte[4096];
        out.write(requestBytes);
        in.read(responseBytes);
        assertTrue(new String(responseBytes, "UTF-8").startsWith("HTTP/1.0 204 No Content\r\n"));
    }

可见此处是在打开Socket并尝试进行通信,异常处为方法最后一行,即:判断返回的字符串是否与预期一致。

分析到了这里,我们可以确定与网络环境有较大因素,但是如果要确认assertTrue为何不满足,即返回值到底是什么的话,那么我们就需要添加一些日志了;

由于上面提到的原因,CTS测试跑的时候,这段代码是通过已经打好包的APK形式提供的,我们并没有办法对其进行修改;但是反过来想,我们是不是可以用自己编译好的APK,替换掉CTS中的APK呢?

那么这就是一个方法:

  1. 从AOSP下载对应版本的代码(如果行数与当前基线差异不大,也可以先用当前基线尝试);
  2. 添加必要信息,例如:
    private void testHttpRequest(Socket s) throws IOException {
        OutputStream out = s.getOutputStream();
        InputStream in = s.getInputStream();

        final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
        byte[] responseBytes = new byte[4096];
        //添加日志输出完整请求URL
        Log.i(TAG, "HTTP_REQUEST = " + HTTP_REQUEST);
        out.write(requestBytes);
        in.read(responseBytes);
        //添加日志输出返回结果
        String formattedResponse = new String(responseBytes, "UTF-8");
        Log.i(TAG, "responseBytes = " + formattedResponse);
        assertTrue(formattedResponse.startsWith("HTTP/1.0 204 No Content\r\n"));
    }
  1. 编译模块,模块名查找方式这里不做介绍,此处为make CtsNetTestCases
$ make CtsNetTestCases

编译完成后生成的产物存放在这里:

out/target/product/${project}/testcases/CtsNetTestCases/(arm64|arm)/CtsNetTestCases.apk

备份CTS包中提供的APK:

$ mv ./testcases/CtsNetTestCases.apk ./testcases/CtsNetTestCases_apk

将编译出的APK放入:

$ cp ~/aosp/out/target/product/${project}/testcases/CtsNetTestCases/(arm64|arm)/CtsNetTestCases.apk ./testcases/CtsNetTestCases.apk
  1. 然后再进行一次单跑,同时抓取logcat日志:
12-29 11:13:40.348 I/ConnectivityManagerTest(26037): Network type: 1 state: CONNECTED
12-29 11:13:40.390 I/ConnectivityManagerTest(26037): HTTP_REQUEST = GET /generate_204 HTTP/1.0
12-29 11:13:40.390 I/ConnectivityManagerTest(26037): Host: connectivitycheck.gstatic.com
12-29 11:13:40.390 I/ConnectivityManagerTest(26037): Connection: keep-alive
12-29 11:13:40.390 I/ConnectivityManagerTest(26037): 
12-29 11:13:40.431 I/ConnectivityManagerTest(26037): responseBytes = HTTP/1.0 403 Forbidden
12-29 11:13:40.431 I/ConnectivityManagerTest(26037): Server: bfe
12-29 11:13:40.431 I/ConnectivityManagerTest(26037): Date: Wed, 29 Dec 2021 03:13:40 GMT
12-29 11:13:40.431 I/ConnectivityManagerTest(26037): Content-Length: 0
12-29 11:13:40.431 I/ConnectivityManagerTest(26037): Content-Type: text/plain; charset=utf-8
12-29 11:13:40.431 I/ConnectivityManagerTest(26037): 
12-29 11:13:40.431 I/ConnectivityManagerTest(26037): ...
12-29 11:13:40.433 I/TestRunner(26037): failed: testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent(android.net.cts.ConnectivityManagerTest)
12-29 11:13:40.433 I/TestRunner(26037): 	at android.net.cts.ConnectivityManagerTest.testHttpRequest(ConnectivityManagerTest.java:725)
12-29 11:13:40.433 I/TestRunner(26037): 	at android.net.cts.ConnectivityManagerTest.disconnectFromWifi(ConnectivityManagerTest.java:745)
12-29 11:13:40.433 I/TestRunner(26037): 	at android.net.cts.ConnectivityManagerTest.toggleWifi(ConnectivityManagerTest.java:661)
12-29 11:13:40.433 I/TestRunner(26037): 	at android.net.cts.ConnectivityManagerTest.testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent(ConnectivityManagerTest.java:634)

可见此处请求返回码期望为204,返回头期望为"HTTP/1.0 204 No Content",但实际返回"HTTP/1.0 403 Forbidden"

导致403的原因很多,这个就是接下来具体问题具体分析的地方了,这里只放出针对此题的结论——路由器端DNS配置不合理,具体过程就不再赘述了。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值