Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setting for udp2tcp port #6310

Merged
merged 4 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollToNode
import io.mockk.MockKAnnotations
import io.mockk.coVerify
import io.mockk.mockk
import io.mockk.verify
import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
Expand All @@ -17,6 +18,8 @@ import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_LAST_ITEM_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG
Expand All @@ -25,6 +28,7 @@ import net.mullvad.mullvadvpn.lib.model.Mtu
import net.mullvad.mullvadvpn.lib.model.Port
import net.mullvad.mullvadvpn.lib.model.PortRange
import net.mullvad.mullvadvpn.lib.model.QuantumResistantState
import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation
import net.mullvad.mullvadvpn.onNodeWithTagAndText
import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem
import org.junit.jupiter.api.BeforeEach
Expand Down Expand Up @@ -206,6 +210,77 @@ class VpnSettingsScreenTest {
onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertExists()
}

@Test
fun testSelectTcpOverUdpPortOption() =
composeExtension.use {
// Arrange
val onObfuscationPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true)
setContentWithTheme {
VpnSettingsScreen(
state =
VpnSettingsUiState.createDefault(
selectedObfuscation = SelectedObfuscation.Udp2Tcp,
selectedObfuscationPort = Constraint.Only(Port(5001))
),
onObfuscationPortSelected = onObfuscationPortSelected
)
}

// Act
onNodeWithTag(LAZY_LIST_TEST_TAG)
.performScrollToNode(hasTestTag(LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG))
onNodeWithText("UDP-over-TCP port").performClick()
onNodeWithTag(LAZY_LIST_TEST_TAG)
.performScrollToNode(
hasTestTag(String.format(LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG, 5001))
)

// Assert
onNodeWithTagAndText(
testTag = String.format(LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG, 5001),
text = "5001"
)
.assertExists()
.performClick()

coVerify(exactly = 1) { onObfuscationPortSelected.invoke(Constraint.Only(Port(5001))) }
}

@Test
fun testAttemptSelectTcpOverUdpPortOption() =
composeExtension.use {
// Arrange
val onObfuscationPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true)
setContentWithTheme {
VpnSettingsScreen(
state =
VpnSettingsUiState.createDefault(
selectedObfuscation = SelectedObfuscation.Off,
),
onObfuscationPortSelected = onObfuscationPortSelected
)
}

// Act
onNodeWithTag(LAZY_LIST_TEST_TAG)
.performScrollToNode(hasTestTag(LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG))
onNodeWithText("UDP-over-TCP port").performClick()
onNodeWithTag(LAZY_LIST_TEST_TAG)
.performScrollToNode(
hasTestTag(String.format(LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG, 5001))
)

// Assert
onNodeWithTagAndText(
testTag = String.format(LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG, 5001),
text = "5001"
)
.assertExists()
.performClick()

verify(exactly = 0) { onObfuscationPortSelected.invoke(any()) }
}

@Test
fun testShowSelectedTunnelQuantumOption() =
composeExtension.use {
Expand Down Expand Up @@ -401,6 +476,29 @@ class VpnSettingsScreenTest {
verify { mockedClickHandler.invoke(null, null) }
}

@Test
fun testShowObfuscationInfo() =
composeExtension.use {
val mockedNavigateToObfuscationInfo: () -> Unit = mockk(relaxed = true)

// Arrange
setContentWithTheme {
VpnSettingsScreen(
state = VpnSettingsUiState.createDefault(),
navigateToObfuscationInfo = mockedNavigateToObfuscationInfo
)
}

// Act

onNodeWithTag(LAZY_LIST_TEST_TAG)
.performScrollToNode(hasTestTag(LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG))
onNodeWithText("WireGuard obfuscation").performClick()

// Assert
verify(exactly = 1) { mockedNavigateToObfuscationInfo() }
}

@Test
fun testShowTunnelQuantumInfo() =
composeExtension.use {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
Expand Down Expand Up @@ -46,14 +47,15 @@ fun ExpandableComposeCell(
title: String,
isExpanded: Boolean,
isEnabled: Boolean = true,
testTag: String = "",
onCellClicked: (Boolean) -> Unit = {},
onInfoClicked: (() -> Unit)? = null
) {
val titleModifier = Modifier.alpha(if (isEnabled) AlphaVisible else AlphaInactive)
val bodyViewModifier = Modifier

BaseCell(
modifier = Modifier.focusProperties { canFocus = false },
modifier = Modifier.testTag(testTag).focusProperties { canFocus = false },
headlineContent = {
BaseCellTitle(
title = title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.component.SpacedColumn
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled
import net.mullvad.mullvadvpn.lib.theme.color.AlphaInvisible
import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible
import net.mullvad.mullvadvpn.lib.theme.color.selected
Expand All @@ -36,6 +37,7 @@ private fun PreviewSelectableCell() {
fun SelectableCell(
title: String,
isSelected: Boolean,
isEnabled: Boolean = true,
iconContentDescription: String? = null,
selectedIcon: @Composable RowScope.() -> Unit = {
Icon(
Expand All @@ -44,7 +46,10 @@ fun SelectableCell(
tint = MaterialTheme.colorScheme.onPrimary,
modifier =
Modifier.padding(end = Dimens.selectableCellTextMargin)
.alpha(if (isSelected) AlphaVisible else AlphaInvisible)
.alpha(
if (isSelected && !isEnabled) AlphaDisabled
else if (isSelected) AlphaVisible else AlphaInvisible
)
)
},
titleStyle: TextStyle = MaterialTheme.typography.labelLarge,
Expand All @@ -56,7 +61,16 @@ fun SelectableCell(
) {
BaseCell(
onCellClicked = onCellClicked,
headlineContent = { BaseCellTitle(title = title, style = titleStyle) },
isRowEnabled = isEnabled,
headlineContent = {
BaseCellTitle(
title = title,
style = titleStyle,
color =
if (isEnabled) MaterialTheme.colorScheme.onPrimary
else MaterialTheme.colorScheme.onPrimary.copy(AlphaDisabled)
)
},
background =
if (isSelected) {
selectedColor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import net.mullvad.mullvadvpn.compose.component.textResource
import net.mullvad.mullvadvpn.compose.extensions.toAnnotatedString
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled

@Preview
@Composable
Expand Down Expand Up @@ -67,7 +68,10 @@ fun NormalSwitchComposeCell(
BaseCellTitle(
title = title,
style = MaterialTheme.typography.labelLarge,
modifier = Modifier.weight(1f, true)
modifier = Modifier.weight(1f, true),
color =
if (isEnabled) MaterialTheme.colorScheme.onPrimary
else MaterialTheme.colorScheme.onPrimary.copy(AlphaDisabled)
)
},
isToggled = isToggled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,17 @@ import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_LAST_ITEM_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_AUTOMATIC_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG
import net.mullvad.mullvadvpn.compose.transitions.SlideInFromRightTransition
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
import net.mullvad.mullvadvpn.compose.util.OnNavResultValue
import net.mullvad.mullvadvpn.compose.util.showSnackbarImmediately
import net.mullvad.mullvadvpn.constant.UDP2TCP_PRESET_PORTS
import net.mullvad.mullvadvpn.constant.WIREGUARD_PRESET_PORTS
import net.mullvad.mullvadvpn.lib.model.Constraint
import net.mullvad.mullvadvpn.lib.model.Mtu
Expand Down Expand Up @@ -258,6 +262,7 @@ fun VpnSettings(
onSelectObfuscationSetting = vm::onSelectObfuscationSetting,
onSelectQuantumResistanceSetting = vm::onSelectQuantumResistanceSetting,
onWireguardPortSelected = vm::onWireguardPortSelected,
onObfuscationPortSelected = vm::onObfuscationPortSelected,
)
}

Expand Down Expand Up @@ -293,8 +298,10 @@ fun VpnSettingsScreen(
onSelectObfuscationSetting: (selectedObfuscation: SelectedObfuscation) -> Unit = {},
onSelectQuantumResistanceSetting: (quantumResistant: QuantumResistantState) -> Unit = {},
onWireguardPortSelected: (port: Constraint<Port>) -> Unit = {},
onObfuscationPortSelected: (port: Constraint<Port>) -> Unit = {},
) {
var expandContentBlockersState by rememberSaveable { mutableStateOf(false) }
var expandUdp2TcpPortSettings by rememberSaveable { mutableStateOf(false) }
val biggerPadding = 54.dp
val topPadding = 6.dp

Expand Down Expand Up @@ -527,7 +534,8 @@ fun VpnSettingsScreen(
itemWithDivider {
SelectableCell(
title = port.toString(),
testTag = String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, port),
testTag =
String.format(null, LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, port),
isSelected = state.selectedWireguardPort.hasValue(port),
onCellClicked = { onWireguardPortSelected(Constraint.Only(Port(port))) }
)
Expand Down Expand Up @@ -582,6 +590,48 @@ fun VpnSettingsScreen(
)
}

itemWithDivider {
ExpandableComposeCell(
title = stringResource(R.string.udp_over_tcp_port_title),
isExpanded = expandUdp2TcpPortSettings,
isEnabled = state.selectedObfuscation != SelectedObfuscation.Off,
onInfoClicked = navigateUdp2TcpInfo,
onCellClicked = { expandUdp2TcpPortSettings = !expandUdp2TcpPortSettings },
testTag = LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG
)
}

if (expandUdp2TcpPortSettings) {
itemWithDivider {
SelectableCell(
title = stringResource(id = R.string.automatic),
isSelected = state.selectedObfuscationPort is Constraint.Any,
isEnabled = state.selectObfuscationPortEnabled,
onCellClicked = { onObfuscationPortSelected(Constraint.Any) },
testTag = LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_AUTOMATIC_TEST_TAG,
)
}

UDP2TCP_PRESET_PORTS.forEach { port ->
itemWithDivider {
SelectableCell(
title = port.toString(),
isSelected = state.selectedObfuscationPort.hasValue(port),
isEnabled = state.selectObfuscationPortEnabled,
onCellClicked = {
onObfuscationPortSelected(Constraint.Only(Port(port)))
},
testTag =
String.format(
null,
LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG,
port
)
)
}
}
}

itemWithDivider {
Spacer(modifier = Modifier.height(Dimens.cellLabelVerticalPadding))
InformationComposeCell(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ data class VpnSettingsUiState(
val customDnsItems: List<CustomDnsItem>,
val contentBlockersOptions: DefaultDnsOptions,
val selectedObfuscation: SelectedObfuscation,
val selectedObfuscationPort: Constraint<Port>,
val quantumResistant: QuantumResistantState,
val selectedWireguardPort: Constraint<Port>,
val customWireguardPort: Constraint<Port>?,
val availablePortRanges: List<PortRange>,
val systemVpnSettingsAvailable: Boolean,
) {
val selectObfuscationPortEnabled = selectedObfuscation != SelectedObfuscation.Off

companion object {
fun createDefault(
Expand All @@ -33,6 +35,7 @@ data class VpnSettingsUiState(
customDnsItems: List<CustomDnsItem> = emptyList(),
contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
selectedObfuscationPort: Constraint<Port> = Constraint.Any,
quantumResistant: QuantumResistantState = QuantumResistantState.Off,
selectedWireguardPort: Constraint<Port> = Constraint.Any,
customWireguardPort: Constraint.Only<Port>? = null,
Expand All @@ -47,6 +50,7 @@ data class VpnSettingsUiState(
customDnsItems,
contentBlockersOptions,
selectedObfuscation,
selectedObfuscationPort,
quantumResistant,
selectedWireguardPort,
customWireguardPort,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ const val LAZY_LIST_TEST_TAG = "lazy_list_test_tag"
const val LAZY_LIST_LAST_ITEM_TEST_TAG = "lazy_list_last_item_test_tag"
const val LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG = "lazy_list_quantum_item_off_test_tag"
const val LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG = "lazy_list_quantum_item_on_test_tag"
const val LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG = "lazy_list_quantum_item_%d_test_tag"
const val LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG = "lazy_list_wireguard_item_%d_test_tag"
const val LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG =
"lazy_list_wireguard_custom_port_text_test_tag"
const val LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG =
"lazy_list_wireguard_custom_port_number_test_tag"
const val LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG = "lazy_list_udp_over_tcp_port_test_tag"
const val LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_AUTOMATIC_TEST_TAG =
"lazy_list_udp_over_tcp_item_automatic_test_tag"
const val LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG = "lazy_list_udp_over_tcp_item_%d_test_tag"
const val CUSTOM_PORT_DIALOG_INPUT_TEST_TAG = "custom_port_dialog_input_test_tag"

// SelectLocationScreen, ConnectScreen, CustomListLocationsScreen
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
package net.mullvad.mullvadvpn.constant

val WIREGUARD_PRESET_PORTS = listOf(51820, 53)
val UDP2TCP_PRESET_PORTS = listOf(80, 5001)
Loading
Loading