sync15/
client_types.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//! This module has to be here because of some hard-to-avoid hacks done for the
6//! tabs engine... See issue #2590
7
8use crate::DeviceType;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11
12/// Argument to Store::prepare_for_sync. See comment there for more info. Only
13/// really intended to be used by tabs engine.
14#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
15pub struct ClientData {
16    pub local_client_id: String,
17    /// A hashmap of records in the `clients` collection. Key is the id of the record in
18    /// that collection, which may or may not be the device's fxa_device_id.
19    pub recent_clients: HashMap<String, RemoteClient>,
20}
21
22/// Information about a remote client in the clients collection.
23#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
24pub struct RemoteClient {
25    pub fxa_device_id: Option<String>,
26    pub device_name: String,
27    #[serde(default)]
28    pub device_type: DeviceType,
29}
30
31#[cfg(test)]
32mod client_types_tests {
33    use super::*;
34
35    #[test]
36    fn test_remote_client() {
37        // Missing `device_type` gets DeviceType::Unknown.
38        let dt = serde_json::from_str::<RemoteClient>("{\"device_name\": \"foo\"}").unwrap();
39        assert_eq!(dt.device_type, DeviceType::Unknown);
40        // But reserializes as null.
41        assert_eq!(
42            serde_json::to_string(&dt).unwrap(),
43            "{\"fxa_device_id\":null,\"device_name\":\"foo\",\"device_type\":null}"
44        );
45
46        // explicit null is also unknown.
47        assert_eq!(
48            serde_json::from_str::<RemoteClient>(
49                "{\"device_name\": \"foo\", \"device_type\": null}",
50            )
51            .unwrap()
52            .device_type,
53            DeviceType::Unknown
54        );
55
56        // Unknown device_type string deserializes as DeviceType::Unknown.
57        let dt = serde_json::from_str::<RemoteClient>(
58            "{\"device_name\": \"foo\", \"device_type\": \"foo\"}",
59        )
60        .unwrap();
61        assert_eq!(dt.device_type, DeviceType::Unknown);
62        // The None gets re-serialized as null.
63        assert_eq!(
64            serde_json::to_string(&dt).unwrap(),
65            "{\"fxa_device_id\":null,\"device_name\":\"foo\",\"device_type\":null}"
66        );
67
68        // DeviceType::Unknown gets serialized as null.
69        let dt = RemoteClient {
70            device_name: "bar".to_string(),
71            fxa_device_id: None,
72            device_type: DeviceType::Unknown,
73        };
74        assert_eq!(
75            serde_json::to_string(&dt).unwrap(),
76            "{\"fxa_device_id\":null,\"device_name\":\"bar\",\"device_type\":null}"
77        );
78
79        // DeviceType::Desktop gets serialized as "desktop".
80        let dt = RemoteClient {
81            device_name: "bar".to_string(),
82            fxa_device_id: Some("fxa".to_string()),
83            device_type: DeviceType::Desktop,
84        };
85        assert_eq!(
86            serde_json::to_string(&dt).unwrap(),
87            "{\"fxa_device_id\":\"fxa\",\"device_name\":\"bar\",\"device_type\":\"desktop\"}"
88        );
89    }
90
91    #[test]
92    fn test_client_data() {
93        let client_data = ClientData {
94            local_client_id: "my-device".to_string(),
95            recent_clients: HashMap::from([
96                (
97                    "my-device".to_string(),
98                    RemoteClient {
99                        fxa_device_id: None,
100                        device_name: "my device".to_string(),
101                        device_type: DeviceType::Unknown,
102                    },
103                ),
104                (
105                    "device-no-tabs".to_string(),
106                    RemoteClient {
107                        fxa_device_id: None,
108                        device_name: "device with no tabs".to_string(),
109                        device_type: DeviceType::Unknown,
110                    },
111                ),
112                (
113                    "device-with-a-tab".to_string(),
114                    RemoteClient {
115                        fxa_device_id: None,
116                        device_name: "device with a tab".to_string(),
117                        device_type: DeviceType::Desktop,
118                    },
119                ),
120            ]),
121        };
122        //serialize
123        let client_data_ser = serde_json::to_string(&client_data).unwrap();
124        println!("SER: {}", client_data_ser);
125        // deserialize
126        let client_data_des: ClientData = serde_json::from_str(&client_data_ser).unwrap();
127        assert_eq!(client_data_des, client_data);
128    }
129}