summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-07-29 23:44:25 +0200
committerDavid Lönnhager <david.l@mullvad.net>2020-07-29 23:44:25 +0200
commitca590bb989cea195b67208dc49da9419da14e9a1 (patch)
treead8123dfd711b2b0bdf5a64d547d8629cfa60124
parentce0f3d4bd7a1786d00cb6c9ea7b4a771d1c94ab6 (diff)
parentb1b9c2db0e4c56b817eea92e5404a8cf2fd91790 (diff)
downloadmullvadvpn-ca590bb989cea195b67208dc49da9419da14e9a1.tar.xz
mullvadvpn-ca590bb989cea195b67208dc49da9419da14e9a1.zip
Merge branch 'fix-mullvad-tests'
-rw-r--r--Cargo.lock7
-rw-r--r--mullvad-tests/Cargo.toml13
-rw-r--r--mullvad-tests/build.rs5
-rw-r--r--mullvad-tests/src/lib.rs88
-rw-r--r--mullvad-tests/tests/connection.rs74
-rw-r--r--mullvad-tests/tests/startup.rs4
-rw-r--r--mullvad-types/src/location.rs2
-rw-r--r--mullvad-types/src/states.rs2
8 files changed, 141 insertions, 54 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e9415bc4b6..ca7fff3b06 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1563,14 +1563,21 @@ dependencies = [
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"mullvad-ipc-client 0.1.0",
"mullvad-paths 0.1.0",
+ "mullvad-rpc 0.1.0",
"mullvad-types 0.1.0",
"notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
"openvpn-plugin 0.3.0 (git+https://github.com/mullvad/openvpn-plugin-rs?branch=auth-failed-event)",
+ "parity-tokio-ipc 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"talpid-ipc 0.1.0",
"talpid-types 0.1.0",
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tonic 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tonic-build 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tower 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
diff --git a/mullvad-tests/Cargo.toml b/mullvad-tests/Cargo.toml
index 7aa2857c26..152343c1e9 100644
--- a/mullvad-tests/Cargo.toml
+++ b/mullvad-tests/Cargo.toml
@@ -14,6 +14,7 @@ integration-tests = []
duct = "0.13"
mullvad-ipc-client = { path = "../mullvad-ipc-client" }
mullvad-paths = { path = "../mullvad-paths" }
+mullvad-rpc = { path = "../mullvad-rpc" }
mullvad-types = { path = "../mullvad-types" }
notify = "4.0"
openvpn-plugin = { git = "https://github.com/mullvad/openvpn-plugin-rs", branch = "auth-failed-event", features = ["serde"] }
@@ -23,9 +24,17 @@ tempfile = "3.0"
jsonrpc-client-core = { git = "https://github.com/mullvad/jsonrpc-client-rs", rev = "68aac55b" }
jsonrpc-client-ipc = { git = "https://github.com/mullvad/jsonrpc-client-rs", rev = "68aac55b" }
jsonrpc-client-pubsub = { git = "https://github.com/mullvad/jsonrpc-client-rs", rev = "68aac55b" }
-tokio = "0.1"
-tokio-timer = "0.1"
futures = "0.1.23"
+tokio01 = { package = "tokio", version = "0.1" }
+tokio-timer = "0.1"
+tokio = { version = "0.2", features = [ "io-util", "process", "rt-core", "rt-threaded", "stream", "fs"] }
+tonic = "0.2"
+tower = "0.3"
+prost = "0.6"
+parity-tokio-ipc = "0.7"
+
+[build-dependencies]
+tonic-build = { version = "0.2", default-features = false, features = ["transport", "prost"] }
[target.'cfg(unix)'.dependencies]
libc = "0.2"
diff --git a/mullvad-tests/build.rs b/mullvad-tests/build.rs
new file mode 100644
index 0000000000..71c9068925
--- /dev/null
+++ b/mullvad-tests/build.rs
@@ -0,0 +1,5 @@
+fn main() {
+ const OPENVPN_PROTO_FILE: &str = "../talpid-openvpn-plugin/proto/openvpn_plugin.proto";
+ tonic_build::compile_protos(OPENVPN_PROTO_FILE).unwrap();
+ println!("cargo:rerun-if-changed={}", OPENVPN_PROTO_FILE);
+}
diff --git a/mullvad-tests/src/lib.rs b/mullvad-tests/src/lib.rs
index 38266139c1..ad0d85bf89 100644
--- a/mullvad-tests/src/lib.rs
+++ b/mullvad-tests/src/lib.rs
@@ -1,10 +1,9 @@
#![cfg(not(target_os = "android"))]
use self::{mock_openvpn::MOCK_OPENVPN_ARGS_FILE, platform_specific::*};
-use futures::sync::oneshot;
-use jsonrpc_client_core::{Future, Transport};
use jsonrpc_client_ipc::IpcTransport;
use mullvad_ipc_client::DaemonRpcClient;
+use mullvad_rpc::API_IP_CACHE_FILENAME;
use notify::{RawEvent, RecommendedWatcher, RecursiveMode, Watcher};
use std::{
cmp,
@@ -16,10 +15,20 @@ use std::{
time::{Duration, Instant},
};
use tempfile::TempDir;
-use tokio::reactor::Handle;
pub use notify::op::{self as watch_event, Op as WatchEvent};
+use parity_tokio_ipc::Endpoint as IpcEndpoint;
+use tonic::{
+ self,
+ transport::{Endpoint, Uri},
+};
+use tower::service_fn;
+
+mod openvpn_proto {
+ tonic::include_proto!("talpid_openvpn_plugin");
+}
+use openvpn_proto::openvpn_event_proxy_client::OpenvpnEventProxyClient;
pub mod mock_openvpn;
@@ -205,6 +214,7 @@ fn prepare_test_dirs() -> (TempDir, PathBuf, PathBuf, PathBuf) {
fs::create_dir(&settings_dir).expect("Failed to create settings directory");
prepare_resource_dir(&resource_dir);
+ prepare_cache_dir(&cache_dir);
(temp_dir, cache_dir, resource_dir, settings_dir)
}
@@ -216,8 +226,13 @@ fn prepare_resource_dir(resource_dir: &Path) {
fs::copy(MOCK_OPENVPN_EXECUTABLE_PATH, openvpn_binary)
.expect("Failed to copy mock OpenVPN binary");
File::create(talpid_openvpn_plugin).expect("Failed to create mock Talpid OpenVPN plugin");
+}
+
+fn prepare_cache_dir(cache_dir: &Path) {
+ prepare_relay_list(cache_dir.join("relays.json"));
- prepare_relay_list(resource_dir.join("relays.json"));
+ fs::write(cache_dir.join(API_IP_CACHE_FILENAME), "192.168.0.123")
+ .expect("Failed to cache API IP");
}
fn prepare_relay_list<T: AsRef<Path>>(path: T) {
@@ -235,14 +250,25 @@ fn prepare_relay_list<T: AsRef<Path>>(path: T) {
"relays": [{
"hostname": "fakehost",
"ipv4_addr_in": "192.168.0.100",
- "ipv4_addr_exit": "192.168.0.101",
+ "ipv6_addr_in": null,
"include_in_country": true,
+ "active": true,
+ "owned": false,
+ "provider": "M247",
"weight": 100,
"tunnels": {
"openvpn": [ { "port": 1000, "protocol": "udp" } ],
"wireguard": []
}
- }]
+ }],
+ "location": {
+ "country": "Sweden",
+ "country_code": "se",
+ "city": "Gothenburg",
+ "city_code": "got",
+ "latitude": 57.70887,
+ "longitude": 11.97456
+ }
}]
}]
}"#,
@@ -297,7 +323,7 @@ impl DaemonRunner {
wait_for_file(&self.rpc_socket_path);
let socket_path: String = self.rpc_socket_path.to_string_lossy().to_string();
mullvad_ipc_client::new_standalone_transport(socket_path, |path| {
- IpcTransport::new(&path, &Handle::default())
+ IpcTransport::new(&path, &tokio01::reactor::Handle::default())
})
.map_err(|e| e.to_string())
.map_err(|e| format!("Failed to construct an RPC client - {}", e))
@@ -347,35 +373,30 @@ impl Drop for DaemonRunner {
}
pub struct MockOpenVpnPluginRpcClient {
- rpc: jsonrpc_client_core::ClientHandle,
+ runtime: tokio::runtime::Runtime,
+ rpc: OpenvpnEventProxyClient<tonic::transport::Channel>,
}
impl MockOpenVpnPluginRpcClient {
- fn spawn_event_loop(address: String) -> Result<jsonrpc_client_core::ClientHandle> {
- let (tx, rx) = oneshot::channel();
- thread::spawn(move || {
- let result = IpcTransport::new(&address, &Handle::default())
- .map_err(|error| {
- format!("Failed to create Mock OpenVPN plugin RPC client: {}", error)
- })
- .map(Transport::into_client);
- match result {
- Ok((client, client_handle)) => {
- tx.send(Ok(client_handle)).unwrap();
- tokio::run(client.map_err(|e| {
- println!("RPC client failed: {}", e);
- }));
- }
- Err(e) => tx.send(Err(e)).unwrap(),
- }
- });
+ async fn spawn_event_loop(
+ address: String,
+ ) -> Result<OpenvpnEventProxyClient<tonic::transport::Channel>> {
+ // The URI will be ignored
+ let channel = Endpoint::from_static("lttp://[::]:50051")
+ .connect_with_connector(service_fn(move |_: Uri| {
+ IpcEndpoint::connect(address.clone())
+ }))
+ .await
+ .map_err(|e| format!("Failed to construct an RPC client - {}", e.to_string()))?;
- rx.wait().unwrap()
+ Ok(OpenvpnEventProxyClient::new(channel))
}
pub fn new(address: String) -> Result<Self> {
- let rpc = Self::spawn_event_loop(address)?;
- Ok(MockOpenVpnPluginRpcClient { rpc })
+ let mut runtime = tokio::runtime::Runtime::new().unwrap();
+
+ let rpc = runtime.block_on(Self::spawn_event_loop(address))?;
+ Ok(MockOpenVpnPluginRpcClient { runtime, rpc })
}
pub fn up(&mut self) -> Result<()> {
@@ -403,9 +424,12 @@ impl MockOpenVpnPluginRpcClient {
event: openvpn_plugin::EventType,
env: HashMap<String, String>,
) -> Result<()> {
- self.rpc
- .call_method("openvpn_event", &(event, env))
- .wait()
+ self.runtime
+ .block_on(self.rpc.event(openvpn_proto::EventType {
+ event: event as i16 as i32,
+ env,
+ }))
+ .map(|_| ())
.map_err(|error| format!("Failed to send mock OpenVPN event {:?}: {}", event, error))
}
}
diff --git a/mullvad-tests/tests/connection.rs b/mullvad-tests/tests/connection.rs
index 509ffb5bf8..2d294232ef 100644
--- a/mullvad-tests/tests/connection.rs
+++ b/mullvad-tests/tests/connection.rs
@@ -5,11 +5,11 @@ use mullvad_tests::{
mock_openvpn::search_openvpn_args, watch_event, DaemonRunner, MockOpenVpnPluginRpcClient,
PathWatcher,
};
-use mullvad_types::DaemonEvent;
+use mullvad_types::{location::GeoIpLocation, states::TunnelState, DaemonEvent};
use std::{fs, path::Path, time::Duration};
use talpid_types::{
net::{Endpoint, TransportProtocol, TunnelEndpoint, TunnelType},
- tunnel::{ActionAfterDisconnect, TunnelStateTransition},
+ tunnel::ActionAfterDisconnect,
};
#[cfg(target_os = "linux")]
@@ -67,11 +67,17 @@ fn changes_to_connecting_state() {
let _ = assert_state_event(
state_events,
- TunnelStateTransition::Connecting(get_default_endpoint()),
+ TunnelState::Connecting {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
assert_eq!(
rpc_client.get_state().unwrap(),
- TunnelStateTransition::Connecting(get_default_endpoint())
+ TunnelState::Connecting {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
}
@@ -88,7 +94,10 @@ fn changes_to_connected_state() {
let state_events = assert_state_event(
state_events,
- TunnelStateTransition::Connecting(get_default_endpoint()),
+ TunnelState::Connecting {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
openvpn_args_file_events.assert_create_write_close_sequence();
@@ -98,11 +107,17 @@ fn changes_to_connected_state() {
assert_state_event(
state_events,
- TunnelStateTransition::Connected(get_default_endpoint()),
+ TunnelState::Connected {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
assert_eq!(
rpc_client.get_state().unwrap(),
- TunnelStateTransition::Connected(get_default_endpoint())
+ TunnelState::Connected {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ }
);
}
@@ -119,7 +134,10 @@ fn returns_to_connecting_state() {
let state_events = assert_state_event(
state_events,
- TunnelStateTransition::Connecting(get_default_endpoint()),
+ TunnelState::Connecting {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
openvpn_args_file_events.assert_create_write_close_sequence();
@@ -129,7 +147,10 @@ fn returns_to_connecting_state() {
let state_events = assert_state_event(
state_events,
- TunnelStateTransition::Connected(get_default_endpoint()),
+ TunnelState::Connected {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
mock_plugin_client.route_predown().unwrap();
@@ -140,7 +161,7 @@ fn returns_to_connecting_state() {
let _ = assert_state_event(
state_events,
- TunnelStateTransition::Disconnecting(ActionAfterDisconnect::Reconnect),
+ TunnelState::Disconnecting(ActionAfterDisconnect::Reconnect),
);
}
@@ -157,7 +178,10 @@ fn disconnects() {
let state_events = assert_state_event(
state_events,
- TunnelStateTransition::Connecting(get_default_endpoint()),
+ TunnelState::Connecting {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
openvpn_args_file_events.assert_create_write_close_sequence();
@@ -167,16 +191,19 @@ fn disconnects() {
let state_events = assert_state_event(
state_events,
- TunnelStateTransition::Connected(get_default_endpoint()),
+ TunnelState::Connected {
+ endpoint: get_default_endpoint(),
+ location: get_default_location(),
+ },
);
rpc_client.disconnect().unwrap();
let state_events = assert_state_event(
state_events,
- TunnelStateTransition::Disconnecting(ActionAfterDisconnect::Nothing),
+ TunnelState::Disconnecting(ActionAfterDisconnect::Nothing),
);
- let _ = assert_state_event(state_events, TunnelStateTransition::Disconnected);
+ let _ = assert_state_event(state_events, TunnelState::Disconnected);
}
fn get_default_endpoint() -> TunnelEndpoint {
@@ -186,14 +213,29 @@ fn get_default_endpoint() -> TunnelEndpoint {
protocol: TransportProtocol::Udp,
},
tunnel_type: TunnelType::OpenVpn,
+ proxy: None,
}
}
+fn get_default_location() -> Option<GeoIpLocation> {
+ Some(GeoIpLocation {
+ ipv4: None,
+ ipv6: None,
+ country: "Sweden".to_string(),
+ city: Some("Gothenburg".to_string()),
+ latitude: 57.70887,
+ longitude: 11.97456,
+ mullvad_exit_ip: true,
+ hostname: Some("fakehost".to_string()),
+ bridge_hostname: None,
+ })
+}
+
fn assert_state_event<
S: Stream<Item = DaemonEvent, Error = jsonrpc_client_core::Error> + std::fmt::Debug,
>(
mut receiver: S,
- expected_state: TunnelStateTransition,
+ expected_state: TunnelState,
) -> S {
use futures::future::Either;
@@ -206,7 +248,7 @@ fn assert_state_event<
_ => panic!("Timed out waiting for tunnel state transition"),
};
receiver = receiver2;
- if let DaemonEvent::StateTransition(new_state) = event.unwrap() {
+ if let DaemonEvent::TunnelState(new_state) = event.unwrap() {
transition = Some(new_state);
}
}
diff --git a/mullvad-tests/tests/startup.rs b/mullvad-tests/tests/startup.rs
index 3e6ad205ce..812d443f66 100644
--- a/mullvad-tests/tests/startup.rs
+++ b/mullvad-tests/tests/startup.rs
@@ -1,7 +1,7 @@
#![cfg(feature = "integration-tests")]
use mullvad_tests::DaemonRunner;
-use talpid_types::tunnel::TunnelStateTransition;
+use mullvad_types::states::TunnelState;
#[test]
fn starts_in_disconnected_state() {
@@ -10,5 +10,5 @@ fn starts_in_disconnected_state() {
let state = rpc_client.get_state().expect("Failed to read daemon state");
- assert_eq!(state, TunnelStateTransition::Disconnected);
+ assert_eq!(state, TunnelState::Disconnected);
}
diff --git a/mullvad-types/src/location.rs b/mullvad-types/src/location.rs
index 243c0768e8..17cec7c020 100644
--- a/mullvad-types/src/location.rs
+++ b/mullvad-types/src/location.rs
@@ -66,7 +66,7 @@ pub struct AmIMullvad {
}
/// GeoIP information exposed from the daemon to frontends.
-#[derive(Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(target_os = "android", derive(IntoJava))]
#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))]
pub struct GeoIpLocation {
diff --git a/mullvad-types/src/states.rs b/mullvad-types/src/states.rs
index 805210a7aa..e80b795bba 100644
--- a/mullvad-types/src/states.rs
+++ b/mullvad-types/src/states.rs
@@ -18,7 +18,7 @@ pub enum TargetState {
}
/// Represents the state the client tunnel is in.
-#[derive(Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "state", content = "details")]
#[cfg_attr(target_os = "android", derive(IntoJava))]