[BadCase]代码提交
This commit is contained in:
201
app/build.gradle
201
app/build.gradle
@@ -4,75 +4,83 @@ apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'android-aspectjx'
|
||||
apply plugin: 'bugly'
|
||||
apply plugin: 'apm-plugin'
|
||||
|
||||
if (!isAndroidTestBuild()) {
|
||||
apply plugin: 'apm-plugin'
|
||||
}
|
||||
|
||||
//apply ByteX宿主
|
||||
apply plugin: 'bytex'
|
||||
ByteX {
|
||||
enable true
|
||||
enableInDebug true
|
||||
logLevel "DEBUG"
|
||||
|
||||
if (!isAndroidTestBuild()) {
|
||||
apply plugin: 'bytex'
|
||||
ByteX {
|
||||
enable true
|
||||
enableInDebug true
|
||||
logLevel "DEBUG"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'bytex.threadOpt'
|
||||
if (!isAndroidTestBuild()) {
|
||||
apply plugin: 'bytex.threadOpt'
|
||||
thread_opt {
|
||||
enable true
|
||||
enableInDebug true
|
||||
rxJavaIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
rxJavaComputationReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
coroutineIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
coroutineDefaultReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
}
|
||||
|
||||
thread_opt {
|
||||
enable true
|
||||
enableInDebug true
|
||||
rxJavaIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
rxJavaComputationReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
coroutineIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
coroutineDefaultReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
/**
|
||||
* 方便使用systrace工具,在工程侧打点,便于分析工程侧性能问题
|
||||
*/
|
||||
apply plugin: 'bytex.systrace'
|
||||
systrace {
|
||||
/**
|
||||
* 交付时要关闭,会有性能损耗
|
||||
*/
|
||||
enable false
|
||||
enableInDebug false
|
||||
/**
|
||||
* - 是否使用[Trace.beginAsyncSection(String, int)/Trace.endAsyncSection(String, int)]进行打点
|
||||
* - 默认使用[Trace.beginSection(String)/Trace.endSection()]进行打点
|
||||
*/
|
||||
isTraceAsync false
|
||||
/**
|
||||
* - 是否在运行时只针对主线程打点,其它线程不打
|
||||
*/
|
||||
isOnlyMainThread false
|
||||
|
||||
/**
|
||||
* - 是否忽略对类的静态构造方法打点
|
||||
* - 默认不忽略
|
||||
*/
|
||||
isIgnoreClinitMethod false
|
||||
|
||||
/**
|
||||
* - 是否忽略对类中的简单方法打点
|
||||
* 简单方法定义:
|
||||
* - 空方法
|
||||
* - get/set 方法
|
||||
* - 单独的方法,方法体内没有调用其它方法
|
||||
* - 默认不忽略
|
||||
*/
|
||||
isIgnoreSampleMethod false
|
||||
|
||||
/**
|
||||
* - 针对特定类集合,配置打点白名单,在此集合中的类中的所有方法不打点
|
||||
* - 支持正则表达式
|
||||
*/
|
||||
whiteListForClass = []
|
||||
|
||||
/**
|
||||
* - 针对特定包名集合,配置打点白名单,所有类以此包名为前缀的类不打点
|
||||
* - 支持正则表达式
|
||||
*/
|
||||
whiteListForPackage = []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 方便使用systrace工具,在工程侧打点,便于分析工程侧性能问题
|
||||
*/
|
||||
apply plugin: 'bytex.systrace'
|
||||
systrace {
|
||||
/**
|
||||
* 交付时要关闭,会有性能损耗
|
||||
*/
|
||||
enable false
|
||||
enableInDebug false
|
||||
/**
|
||||
* - 是否使用[Trace.beginAsyncSection(String, int)/Trace.endAsyncSection(String, int)]进行打点
|
||||
* - 默认使用[Trace.beginSection(String)/Trace.endSection()]进行打点
|
||||
*/
|
||||
isTraceAsync false
|
||||
/**
|
||||
* - 是否在运行时只针对主线程打点,其它线程不打
|
||||
*/
|
||||
isOnlyMainThread false
|
||||
|
||||
/**
|
||||
* - 是否忽略对类的静态构造方法打点
|
||||
* - 默认不忽略
|
||||
*/
|
||||
isIgnoreClinitMethod false
|
||||
|
||||
/**
|
||||
* - 是否忽略对类中的简单方法打点
|
||||
* 简单方法定义:
|
||||
* - 空方法
|
||||
* - get/set 方法
|
||||
* - 单独的方法,方法体内没有调用其它方法
|
||||
* - 默认不忽略
|
||||
*/
|
||||
isIgnoreSampleMethod false
|
||||
|
||||
/**
|
||||
* - 针对特定类集合,配置打点白名单,在此集合中的类中的所有方法不打点
|
||||
* - 支持正则表达式
|
||||
*/
|
||||
whiteListForClass = []
|
||||
|
||||
/**
|
||||
* - 针对特定包名集合,配置打点白名单,所有类以此包名为前缀的类不打点
|
||||
* - 支持正则表达式
|
||||
*/
|
||||
whiteListForPackage = []
|
||||
}
|
||||
|
||||
/*apply plugin: 'chain.log.hook'
|
||||
hooklog{
|
||||
@@ -146,6 +154,10 @@ android {
|
||||
targetCompatibility 1.8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'src/main/AndroidManifest.xml'
|
||||
@@ -199,6 +211,10 @@ android {
|
||||
packagingOptions {
|
||||
exclude 'META-INF/io.netty.versions.properties'
|
||||
}
|
||||
|
||||
useLibrary 'android.test.runner'
|
||||
useLibrary 'android.test.base'
|
||||
useLibrary 'android.test.mock'
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -236,31 +252,38 @@ dependencies {
|
||||
apply from: "./functions/tts.gradle"
|
||||
apply from: "./functions/och.gradle"
|
||||
|
||||
|
||||
androidTestImplementation rootProject.ext.dependencies.androidx_test_core
|
||||
androidTestImplementation rootProject.ext.dependencies.androidx_test_core_ktx
|
||||
androidTestImplementation rootProject.ext.dependencies.androidx_unit_ext
|
||||
androidTestImplementation rootProject.ext.dependencies.androidx_unit_ext_ktx
|
||||
androidTestImplementation rootProject.ext.dependencies.androidx_runner
|
||||
androidTestImplementation rootProject.ext.dependencies.androidx_espresso_core
|
||||
}
|
||||
|
||||
ApmPlugin {
|
||||
// 是否进行插桩
|
||||
enable true
|
||||
// 是否在Debug包插桩,默认不插桩
|
||||
enableInDebug true
|
||||
// DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR");
|
||||
// INFO 级别Log会汇总所有被插桩处理的类供查看,路径 app/build/ByteX/ApmPlugin
|
||||
logLevel "DEBUG"
|
||||
// 启动分析开关:监控App启动耗时,需要同时开启pageLoadSwitch
|
||||
startSwitch = true
|
||||
// 页面响应开关:监控Activity的生命周期耗时
|
||||
pageLoadSwitch = true
|
||||
// 网络监控开关:监控okhttp3的网络请求
|
||||
okHttp3Switch = true
|
||||
// 白名单下的包进行插桩,需要填写要插装类所在的包名,支持前缀配置
|
||||
whiteList = [
|
||||
"com.mogo"
|
||||
]
|
||||
// 黑名单包下类不进行插桩,可以配置包名和类名,没有可以填空
|
||||
blackList = [
|
||||
if (!isAndroidTestBuild()) {
|
||||
ApmPlugin {
|
||||
// 是否进行插桩
|
||||
enable true
|
||||
// 是否在Debug包插桩,默认不插桩
|
||||
enableInDebug true
|
||||
// DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR");
|
||||
// INFO 级别Log会汇总所有被插桩处理的类供查看,路径 app/build/ByteX/ApmPlugin
|
||||
logLevel "DEBUG"
|
||||
// 启动分析开关:监控App启动耗时,需要同时开启pageLoadSwitch
|
||||
startSwitch = true
|
||||
// 页面响应开关:监控Activity的生命周期耗时
|
||||
pageLoadSwitch = true
|
||||
// 网络监控开关:监控okhttp3的网络请求
|
||||
okHttp3Switch = true
|
||||
// 白名单下的包进行插桩,需要填写要插装类所在的包名,支持前缀配置
|
||||
whiteList = [
|
||||
"com.mogo"
|
||||
]
|
||||
// 黑名单包下类不进行插桩,可以配置包名和类名,没有可以填空
|
||||
blackList = [
|
||||
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
android.applicationVariants.all { variant ->
|
||||
@@ -305,3 +328,13 @@ def getWorkingBranchHash() {
|
||||
println "Working branch hash: " + workingBranchHash
|
||||
return workingBranchHash
|
||||
}
|
||||
|
||||
|
||||
boolean isAndroidTestBuild() {
|
||||
for (String s : gradle.startParameter.taskNames) {
|
||||
if (s.contains("AndroidTest")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.mogo.functions.test
|
||||
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
|
||||
import com.mogo.eagle.core.function.hmi.ui.MoGoHmiFragment
|
||||
import com.mogo.eagle.core.function.main.MainLauncherActivity
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.random.Random
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@LargeTest
|
||||
class AutoPilotBadCaseTest {
|
||||
|
||||
lateinit var launch: ActivityScenario<MainLauncherActivity>
|
||||
|
||||
@Before
|
||||
fun launch() {
|
||||
launch = ActivityScenario.launch(MainLauncherActivity::class.java)
|
||||
}
|
||||
|
||||
@ExperimentalCoroutinesApi @Test
|
||||
fun showBadCaseEntrance1(): Unit = runBlocking(Dispatchers.Main) {
|
||||
val f = ensureMoGoHmiFragmentShow()
|
||||
var index = 0
|
||||
(1 until 50)
|
||||
.map { it }
|
||||
.asFlow()
|
||||
.onEach {
|
||||
delay(TimeUnit.SECONDS.toMillis(5))
|
||||
f.onAutopilotRecordResult(AutoPilotRecordResult().also {
|
||||
it.diskFree = 100 + index
|
||||
it.duration = 60.0
|
||||
it.fileName = "/user/general/record_$index.log"
|
||||
it.id = 10 + index
|
||||
it.key = "yyy_$index"
|
||||
it.stat = 100
|
||||
it.type = 1
|
||||
it.timestamp = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Date())
|
||||
index++
|
||||
})
|
||||
}
|
||||
.flowOn(Dispatchers.Default)
|
||||
.collect()
|
||||
delay(TimeUnit.HOURS.toMillis(2))
|
||||
}
|
||||
|
||||
|
||||
@ExperimentalCoroutinesApi @Test
|
||||
fun showBadCaseEntrance2():Unit = runBlocking(Dispatchers.Main) {
|
||||
val f = ensureMoGoHmiFragmentShow()
|
||||
var index = 0
|
||||
(1 until 50)
|
||||
.map { it }
|
||||
.asFlow()
|
||||
.onEach {
|
||||
if (index in 1..4) {
|
||||
delay(TimeUnit.SECONDS.toMillis(15))
|
||||
} else {
|
||||
delay(Random(20).nextLong())
|
||||
}
|
||||
f.onAutopilotRecordResult(AutoPilotRecordResult().also {
|
||||
it.diskFree = 100 + index
|
||||
it.duration = 60.0
|
||||
it.fileName = "/user/general/record_$index.log"
|
||||
it.id = 10 + index
|
||||
it.key = "yyy_$index"
|
||||
it.stat = 100
|
||||
it.type = 1
|
||||
it.timestamp = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Date())
|
||||
index++
|
||||
})
|
||||
|
||||
if (index == 5) {
|
||||
f.lifecycleScope.cancel()
|
||||
}
|
||||
|
||||
}
|
||||
.flowOn(Dispatchers.Default)
|
||||
.collect()
|
||||
delay(TimeUnit.HOURS.toMillis(2))
|
||||
}
|
||||
|
||||
@ExperimentalCoroutinesApi @Test
|
||||
fun showBadCaseEntrance3(): Unit = runBlocking(Dispatchers.Main) {
|
||||
val f = ensureMoGoHmiFragmentShow()
|
||||
var index = 0
|
||||
(1 until 50)
|
||||
.map { it }
|
||||
.asFlow()
|
||||
.onEach {
|
||||
delay(TimeUnit.SECONDS.toMillis(20))
|
||||
f.onAutopilotRecordResult(AutoPilotRecordResult().also {
|
||||
it.diskFree = 100 + index
|
||||
it.duration = 60.0
|
||||
it.fileName = "/user/general/record_$index.log"
|
||||
it.id = 10 + index
|
||||
it.key = "yyy_$index"
|
||||
it.stat = 100
|
||||
it.type = 1
|
||||
it.timestamp = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Date())
|
||||
index++
|
||||
})
|
||||
}
|
||||
.flowOn(Dispatchers.Default)
|
||||
.collect()
|
||||
delay(TimeUnit.HOURS.toMillis(2))
|
||||
}
|
||||
|
||||
|
||||
private suspend fun ensureMoGoHmiFragmentShow(): MoGoHmiFragment = suspendCancellableCoroutine {
|
||||
launch.onActivity { itx ->
|
||||
val executor = Executors.newSingleThreadScheduledExecutor()
|
||||
executor.scheduleAtFixedRate({
|
||||
var find =
|
||||
itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
|
||||
while (find == null) {
|
||||
find =
|
||||
itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
|
||||
|
||||
}
|
||||
while (!find.isResumed) {
|
||||
Thread.sleep(500)
|
||||
}
|
||||
it.resumeWith(Result.success(find))
|
||||
try {
|
||||
Thread.sleep(500)
|
||||
executor.shutdownNow()
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}, 50, 500, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user