@@ -2,6 +2,7 @@ use std::{
2
2
collections:: HashMap ,
3
3
ops:: Deref ,
4
4
option_env,
5
+ path:: { Path , PathBuf } ,
5
6
sync:: { Arc , Mutex as StdMutex } ,
6
7
time:: Duration ,
7
8
} ;
@@ -21,9 +22,14 @@ use tokio::sync::Mutex;
21
22
22
23
static USERS : Lazy < Mutex < HashMap < String , ( Client , TempDir ) > > > = Lazy :: new ( Mutex :: default) ;
23
24
25
+ enum SqlitePath {
26
+ Random ,
27
+ Path ( PathBuf ) ,
28
+ }
29
+
24
30
pub struct TestClientBuilder {
25
31
username : String ,
26
- use_sqlite : bool ,
32
+ use_sqlite_dir : Option < SqlitePath > ,
27
33
encryption_settings : EncryptionSettings ,
28
34
http_proxy : Option < String > ,
29
35
}
@@ -32,7 +38,7 @@ impl TestClientBuilder {
32
38
pub fn new ( username : impl Into < String > ) -> Self {
33
39
Self {
34
40
username : username. into ( ) ,
35
- use_sqlite : false ,
41
+ use_sqlite_dir : None ,
36
42
encryption_settings : Default :: default ( ) ,
37
43
http_proxy : None ,
38
44
}
@@ -45,7 +51,16 @@ impl TestClientBuilder {
45
51
}
46
52
47
53
pub fn use_sqlite ( mut self ) -> Self {
48
- self . use_sqlite = true ;
54
+ self . use_sqlite_dir = Some ( SqlitePath :: Random ) ;
55
+ self
56
+ }
57
+
58
+ /// Create or re-use a Sqlite store (with no passphrase) in the supplied
59
+ /// directory. Note: this path must remain valid throughout the use of
60
+ /// the constructed Client, so if you created a TempDir you must hang on
61
+ /// to a reference to it throughout the test.
62
+ pub fn use_sqlite_dir ( mut self , path : & Path ) -> Self {
63
+ self . use_sqlite_dir = Some ( SqlitePath :: Path ( path. to_owned ( ) ) ) ;
49
64
self
50
65
}
51
66
@@ -59,6 +74,42 @@ impl TestClientBuilder {
59
74
self
60
75
}
61
76
77
+ pub async fn duplicate ( self , other : & Client ) -> Result < Client > {
78
+ let homeserver_url =
79
+ option_env ! ( "HOMESERVER_URL" ) . unwrap_or ( "http://localhost:8228" ) . to_owned ( ) ;
80
+ let sliding_sync_proxy_url =
81
+ option_env ! ( "SLIDING_SYNC_PROXY_URL" ) . unwrap_or ( "http://localhost:8338" ) . to_owned ( ) ;
82
+
83
+ let mut client_builder = Client :: builder ( )
84
+ . user_agent ( "matrix-sdk-integration-tests" )
85
+ . homeserver_url ( homeserver_url)
86
+ . sliding_sync_proxy ( sliding_sync_proxy_url)
87
+ . with_encryption_settings ( self . encryption_settings )
88
+ . request_config ( RequestConfig :: short_retry ( ) ) ;
89
+
90
+ if let Some ( proxy) = self . http_proxy {
91
+ client_builder = client_builder. proxy ( proxy) ;
92
+ }
93
+
94
+ let client = match self . use_sqlite_dir {
95
+ Some ( SqlitePath :: Path ( path_buf) ) => {
96
+ client_builder. sqlite_store ( & path_buf, None ) . build ( ) . await ?
97
+ }
98
+ _ => {
99
+ panic ! ( "You must call use_sqlite_dir for a duplicate client!" ) ;
100
+ }
101
+ } ;
102
+
103
+ client
104
+ . restore_session (
105
+ other. session ( ) . expect ( "Session must be logged in before we can duplicate it" ) ,
106
+ )
107
+ . await
108
+ . expect ( "Failed to restore session" ) ;
109
+
110
+ Ok ( client)
111
+ }
112
+
62
113
pub async fn build ( self ) -> Result < Client > {
63
114
let mut users = USERS . lock ( ) . await ;
64
115
if let Some ( ( client, _) ) = users. get ( & self . username ) {
@@ -83,10 +134,14 @@ impl TestClientBuilder {
83
134
client_builder = client_builder. proxy ( proxy) ;
84
135
}
85
136
86
- let client = if self . use_sqlite {
87
- client_builder. sqlite_store ( tmp_dir. path ( ) , None ) . build ( ) . await ?
88
- } else {
89
- client_builder. build ( ) . await ?
137
+ let client = match self . use_sqlite_dir {
138
+ None => client_builder. build ( ) . await ?,
139
+ Some ( SqlitePath :: Random ) => {
140
+ client_builder. sqlite_store ( tmp_dir. path ( ) , None ) . build ( ) . await ?
141
+ }
142
+ Some ( SqlitePath :: Path ( path_buf) ) => {
143
+ client_builder. sqlite_store ( & path_buf, None ) . build ( ) . await ?
144
+ }
90
145
} ;
91
146
92
147
// safe to assume we have not registered this user yet, but ignore if we did
0 commit comments