mirror of
https://github.com/xtclovver/RKNHardering.git
synced 2026-04-29 05:00:03 +00:00
fix: ipv6/ipv4 баги
This commit is contained in:
parent
f1db21809e
commit
b1ddb1183e
8 changed files with 308 additions and 5 deletions
|
|
@ -0,0 +1,136 @@
|
|||
package com.notcvnt.rknhardering
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.notcvnt.rknhardering.model.CategoryResult
|
||||
import com.notcvnt.rknhardering.model.CdnPullingResponse
|
||||
import com.notcvnt.rknhardering.model.Finding
|
||||
import com.notcvnt.rknhardering.model.IpCheckerGroupResult
|
||||
import com.notcvnt.rknhardering.model.IpCheckerResponse
|
||||
import com.notcvnt.rknhardering.model.IpCheckerScope
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.Robolectric
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class MainActivityUiRenderingTest {
|
||||
|
||||
@Test
|
||||
fun `ip comparison response view hides raw error details`() {
|
||||
val activity = Robolectric.buildActivity(MainActivity::class.java).setup().get()
|
||||
val response = IpCheckerResponse(
|
||||
label = "ip.sb IPv6",
|
||||
url = "https://api-ipv6.ip.sb/ip",
|
||||
scope = IpCheckerScope.NON_RU,
|
||||
error = "OkHttp failed after 3 attempts: Could not connect to server",
|
||||
)
|
||||
|
||||
val view = invokePrivate<View>(activity, "createIpCheckerResponseView", response, false)
|
||||
val text = collectText(view)
|
||||
|
||||
assertTrueContains(text, "ip.sb IPv6")
|
||||
assertTrueContains(text, "https://api-ipv6.ip.sb/ip")
|
||||
assertTrueContains(text, activity.getString(R.string.main_card_status_error))
|
||||
assertFalse(text.contains("OkHttp failed after 3 attempts"))
|
||||
assertFalse(text.contains("Could not connect to server"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ip comparison response view hides ignored ipv6 diagnostics`() {
|
||||
val activity = Robolectric.buildActivity(MainActivity::class.java).setup().get()
|
||||
val response = IpCheckerResponse(
|
||||
label = "ip.sb IPv6",
|
||||
url = "https://api-ipv6.ip.sb/ip",
|
||||
scope = IpCheckerScope.NON_RU,
|
||||
error = "native curl failed",
|
||||
ignoredIpv6Error = true,
|
||||
)
|
||||
|
||||
val view = invokePrivate<View>(activity, "createIpCheckerResponseView", response, false)
|
||||
val text = collectText(view)
|
||||
|
||||
assertFalse(text.contains(activity.getString(R.string.main_ipv6_error_ignored).trim()))
|
||||
assertFalse(text.contains("native curl failed"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cdn pulling response view hides raw error details`() {
|
||||
val activity = Robolectric.buildActivity(MainActivity::class.java).setup().get()
|
||||
val response = CdnPullingResponse(
|
||||
targetLabel = "meduza.io",
|
||||
url = "https://meduza.io",
|
||||
error = "SSLHandshakeException: certificate path validation failed",
|
||||
)
|
||||
|
||||
val view = invokePrivate<View>(activity, "createCdnPullingResponseView", response, false)
|
||||
val text = collectText(view)
|
||||
|
||||
assertTrueContains(text, "meduza.io")
|
||||
assertTrueContains(text, "https://meduza.io")
|
||||
assertTrueContains(text, activity.getString(R.string.main_card_status_error))
|
||||
assertFalse(text.contains("SSLHandshakeException"))
|
||||
assertFalse(text.contains("certificate path validation failed"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `display category keeps error status and hides error finding text`() {
|
||||
val activity = Robolectric.buildActivity(MainActivity::class.java).setup().get()
|
||||
val category = CategoryResult(
|
||||
name = "direct",
|
||||
detected = false,
|
||||
findings = listOf(Finding("Socket timeout to 203.0.113.64", isError = true)),
|
||||
)
|
||||
val card = activity.findViewById<MaterialCardView>(R.id.cardIndirect)
|
||||
val icon = activity.findViewById<ImageView>(R.id.iconIndirect)
|
||||
val status = activity.findViewById<TextView>(R.id.statusIndirect)
|
||||
val findings = activity.findViewById<LinearLayout>(R.id.findingsIndirect)
|
||||
|
||||
invokePrivate<Unit>(
|
||||
activity,
|
||||
"displayCategory",
|
||||
category,
|
||||
card,
|
||||
icon,
|
||||
status,
|
||||
findings,
|
||||
false,
|
||||
)
|
||||
|
||||
assertEquals(activity.getString(R.string.main_card_status_error), status.text.toString())
|
||||
assertFalse(collectText(findings).contains("Socket timeout to 203.0.113.64"))
|
||||
}
|
||||
|
||||
private fun collectText(view: View): String {
|
||||
if (view is TextView) return view.text.toString()
|
||||
if (view !is ViewGroup) return ""
|
||||
return buildString {
|
||||
for (index in 0 until view.childCount) {
|
||||
val childText = collectText(view.getChildAt(index))
|
||||
if (childText.isBlank()) continue
|
||||
if (isNotBlank()) append('\n')
|
||||
append(childText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertTrueContains(text: String, expected: String) {
|
||||
assertFalse("Expected text to contain <$expected>, got <$text>", !text.contains(expected))
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <T> invokePrivate(target: Any, name: String, vararg args: Any?): T {
|
||||
val method = target::class.java.declaredMethods.first { candidate ->
|
||||
candidate.name == name && candidate.parameterTypes.size == args.size
|
||||
}
|
||||
method.isAccessible = true
|
||||
return method.invoke(target, *args) as T
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue