CTS問(wèn)題指南
1.簡(jiǎn)介
CTS為google為了android手機(jī)可以表現(xiàn)良好而推出的兼容性測(cè)試包沸呐。針對(duì)每個(gè)不同的系統(tǒng)版本胃珍,都有不止一個(gè)的CTS包以供測(cè)試。
具體的CTS代碼可以通過(guò)下載下來(lái)的android代碼目錄里的./cts目錄進(jìn)行查看,必要時(shí)需要切換具體tag進(jìn)行查看不同版本.
本文檔主要會(huì)介紹CTS的幾種fail場(chǎng)景,并且結(jié)合之前問(wèn)題進(jìn)行分析以及提供可用方法刨秆。
2.CTS錯(cuò)誤形式
1. assert fail
這個(gè)問(wèn)題現(xiàn)象就很簡(jiǎn)單了,junit的assert所指示的變量失敗忆畅,從而查看該變量或者方法是如何所得的即可衡未。
有偶現(xiàn)與必現(xiàn)兩種:
1.必現(xiàn)情況:
必現(xiàn)情況比較好解決。由于一直可以復(fù)現(xiàn)家凯,添加log和跟蹤代碼即可缓醋。一般來(lái)說(shuō)必現(xiàn)CTS fail較少,因?yàn)閍ndroid對(duì)應(yīng)相對(duì)版本的CTS都在google內(nèi)部測(cè)試很多次绊诲,所以必現(xiàn)問(wèn)題一般與展訊自身或者android版本之類(lèi)的有關(guān)送粱。
2.偶現(xiàn)情況:
偶現(xiàn)情況就比較復(fù)雜了。由于CTS的每一個(gè)方法都非常獨(dú)立掂之,一般偶現(xiàn)情況會(huì)由網(wǎng)絡(luò)情況抗俄,前一個(gè)case影響,以及本case的代碼執(zhí)行時(shí)序問(wèn)題所導(dǎo)致世舰。
這一系列的問(wèn)題都沒(méi)有什么好的參照动雹,也比較難以分析》氤耍可能是最難的CTS問(wèn)題洽胶。
勉強(qiáng)舉一個(gè)例子:
android.webkit.cts.WebViewSslTest -- testClearSslPreferences -- failed
1224901 01-01 18:47:46.019 5420 6160 I TestRunner: failed: testClearSslPreferences(android.webkit.cts.WebViewSslTest)
1224902 01-01 18:47:46.019 5420 6160 I TestRunner: ----- begin exception -----
1224903 01-01 18:47:46.019 5420 6160 I TestRunner: junit.framework.AssertionFailedError
1224904 01-01 18:47:46.019 5420 6160 I TestRunner: at junit.framework.Assert.fail(Assert.java:48)
1224905 01-01 18:47:46.019 5420 6160 I TestRunner: at junit.framework.Assert.assertTrue(Assert.java:20)
1224906 01-01 18:47:46.019 5420 6160 I TestRunner: at junit.framework.Assert.assertTrue(Assert.java:27)
1224907 01-01 18:47:46.019 5420 6160 I TestRunner: at android.webkit.cts.WebViewSslTest.testClearSslPreferences(WebViewSslTest.java:567 )
1224908 01-01 18:47:46.019 5420 6160 I TestRunner: at java.lang.reflect.Method.invoke(Native Method)
1224909 01-01 18:47:46.019 5420 6160 I TestRunner: at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
1224910 01-01 18:47:46.019 5420 6160 I TestRunner: at android.test.InstrumentationTestCase.-wrap0(InstrumentationTestCase.java)
1224911 01-01 18:47:46.019 5420 6160 I TestRunner: at android.test.InstrumentationTestCase$2.run(InstrumentationTestCase.java:189)
1224912 01-01 18:47:46.019 5420 6160 I TestRunner: at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:1897)
1224913 01-01 18:47:46.019 5420 6160 I TestRunner: at android.os.Handler.handleCallback(Handler.java:739)
1224914 01-01 18:47:46.019 5420 6160 I TestRunner: at android.os.Handler.dispatchMessage(Handler.java:95)
1224915 01-01 18:47:46.019 5420 6160 I TestRunner: at android.os.Looper.loop(Looper.java:148)
1224916 01-01 18:47:46.019 5420 6160 I TestRunner: at android.app.ActivityThread.main(ActivityThread.java:5435)
1224917 01-01 18:47:46.019 5420 6160 I TestRunner: at java.lang.reflect.Method.invoke(Native Method)
1224918 01-01 18:47:46.019 5420 6160 I TestRunner: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:762)
1224919 01-01 18:47:46.019 5420 6160 I TestRunner: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
1224920 01-01 18:47:46.019 5420 6160 I TestRunner: ----- end exception -----
error的result已經(jīng)明確指明錯(cuò)誤點(diǎn)為android.webkit.cts.WebViewSslTest.testClearSslPreferences(WebViewSslTest.java:567)
這行的assert fail
從cts case代碼看到
547 @UiThreadTest
548 public void testClearSslPreferences() throws Throwable {
549 if (!NullWebViewUtils.isWebViewAvailable()) {
550 return;
551 }
552 // Load the first page. We expect a call to
553 // WebViewClient.onReceivedSslError().
554 final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread);
555 startWebServer(true);
556 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
557 mOnUiThread.setWebViewClient(webViewClient);
558 mOnUiThread.clearSslPreferences();
559 mOnUiThread.loadUrlAndWaitForCompletion(url);
560 assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
561
562 // Load the page again. We expect another call to
563 // WebViewClient.onReceivedSslError() since we cleared sslpreferences.
564 mOnUiThread.clearSslPreferences();
565 webViewClient.resetWasOnReceivedSslErrorCalled();
566 mOnUiThread.loadUrlAndWaitForCompletion(url);
567 assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
568 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
569
570 // Load the page once again, without clearing the sslpreferences.
571 // Make sure we do not get the callback.
572 webViewClient.resetWasOnReceivedSslErrorCalled();
573 mOnUiThread.loadUrlAndWaitForCompletion(url);
574 assertFalse(webViewClient.wasOnReceivedSslErrorCalled());
575 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
567行為
567 assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
我們明確兩個(gè)情況,
第一裆馒,該問(wèn)題偶現(xiàn)姊氓,故可以認(rèn)為實(shí)際代碼邏輯其實(shí)并沒(méi)有問(wèn)題,可能有其他因素干擾所致喷好。
第二翔横,查看case發(fā)現(xiàn)Line 556-560與Line 566-568其實(shí)做的是同一件事情,除去中間Line 564-565是在做清理工作外梗搅,其他都沒(méi)有任何區(qū)別禾唁。
結(jié)合第二點(diǎn)和偶現(xiàn)問(wèn)題發(fā)生時(shí),總是在567行出錯(cuò)无切,之前Line 560的assert從未fail過(guò)荡短,所以我們可以懷疑兩點(diǎn)
第一,Line 564-565兩個(gè)清理工作方法存在偶現(xiàn)問(wèn)題哆键,有時(shí)候會(huì)清楚不了ssl相關(guān)信息掘托。
第二,第一次的訪問(wèn)影響到了第二次的訪問(wèn)籍嘹,導(dǎo)致情況不一致闪盔。
這個(gè)問(wèn)題如果可以查看到具體的cap log弯院,可能就不需要自頂向下閱讀代碼,但是由于該服務(wù)器架設(shè)在手機(jī)內(nèi)部泪掀,不知道為何cap log中并沒(méi)有相關(guān)ssl 握手信息听绳。只好從ssl錯(cuò)誤回調(diào)開(kāi)始看,一直閱讀一直復(fù)現(xiàn)异赫。
閱讀代碼沒(méi)什么可說(shuō)的椅挣,可以發(fā)現(xiàn)懷疑點(diǎn)一不是問(wèn)題的根本,清除工作做得很正常祝辣。
最終發(fā)現(xiàn)由于連接訪問(wèn)過(guò)程中l(wèi)oadUrlAndWaitForCompletion只是等待到了主資源加載完畢贴妻,而子資源(favicon.ico)依然還在連接。導(dǎo)致下一個(gè)請(qǐng)求訪問(wèn)開(kāi)始時(shí)蝙斜,sslconfig并沒(méi)有清空。由于ssl證書(shū)與host關(guān)聯(lián)澎胡,故第二次請(qǐng)求主資源的時(shí)候雖然出現(xiàn)了問(wèn)題孕荠,但是認(rèn)為是已知的證書(shū)問(wèn)題,忽略該錯(cuò)誤直接發(fā)送請(qǐng)求攻谁。
目前認(rèn)為該問(wèn)題無(wú)法修改機(jī)制稚伍,只能提交TR。
2. 顯示5min或者10min超時(shí)
一般超時(shí)問(wèn)題都相對(duì)可以追溯戚宦,與assert fail不同个曙,一般超時(shí)是指setup階段,teardown階段受楼,以及測(cè)試方法本身出現(xiàn)deadlock垦搬,從而一直超時(shí)。
其實(shí)考慮到webview本身是一個(gè)獨(dú)立的app組件艳汽,一般情況下死鎖是能夠在瀏覽器使用的時(shí)候就發(fā)現(xiàn)的猴贰,所以setup和teardown階段是最有可能出現(xiàn)死鎖的。
例:
android.webkit.cts.WebViewSslTest –
testSslErrorProceedResponseNotReusedForDifferentHost - failed
android.webkit.cts.WebViewSslTest –
testSslErrorProceedResponseNotReusedForSameHost - failed
Test failed to run to completion. Reason: 'Failed to receive adb shell test output within 600000 ms. Test may have timed out, or adb connection to device became unresponsive'. Check device logcat for details
result輸出可能有多樣河狐,但是基本的情況就是slog所打印出的log從該case start開(kāi)始大約有5-10min沒(méi)有任何CTS測(cè)試相關(guān)的log輸出米绕。包括最后的finish也沒(méi)有。
這種情況可以通過(guò)在CTS的測(cè)試代碼中添加log進(jìn)行檢查到底是哪里出現(xiàn)deadlock馋艺。
比如這個(gè)問(wèn)題栅干,實(shí)際上是出在CTS的teardown方法中:
457 @Override
458 protected void tearDown() throws Exception {
459 if (mOnUiThread != null) {
460 mOnUiThread.cleanUp();
461 }
462 if (mWebServer != null) {
463 stopWebServer();
464 }
465 super.tearDown();
466 }
在每一行都添加log后通過(guò)復(fù)現(xiàn)可以發(fā)現(xiàn)死鎖卡在stopWebServer這行。從而導(dǎo)致test無(wú)法執(zhí)行完畢捐祠。
相類(lèi)似的情況可能在setup函數(shù)或者是case本身
3. 解決思路及方案
目前已知的解決辦法就兩種
1.提交TR說(shuō)明問(wèn)題原因以及現(xiàn)象碱鳞。具體模板可以直接問(wèn)CTS接口人索取。
一般需要確認(rèn)原因并且最好有android或者chromium的官方issue輔證為佳雏赦。
2.直接修改代碼以符合測(cè)試要求劫笙。這一類(lèi)比較大膽芙扎,可以通過(guò)activityManager查詢(xún)當(dāng)前process name來(lái)分別到底是cts測(cè)試還是實(shí)際的app使用了webview組件,再根據(jù)死板的cts測(cè)試流程給予正確的回復(fù)填大。