@@ -4,12 +4,13 @@ use std::collections::HashSet;
4
4
use std:: io:: prelude:: * ;
5
5
use std:: io:: BufReader ;
6
6
use std:: net:: { SocketAddr , TcpListener , TcpStream } ;
7
+ use std:: path:: PathBuf ;
7
8
use std:: sync:: mpsc:: { channel, Receiver , Sender } ;
8
9
use std:: thread;
9
10
10
11
pub struct Server {
11
12
messages : Option < Sender < Message > > ,
12
- addr : SocketAddr ,
13
+ addr : Addr ,
13
14
thread : Option < thread:: JoinHandle < ( ) > > ,
14
15
}
15
16
@@ -18,8 +19,13 @@ enum Message {
18
19
Write ( String ) ,
19
20
}
20
21
21
- fn run ( listener : & TcpListener , rx : & Receiver < Message > ) {
22
- let mut socket = BufReader :: new ( listener. accept ( ) . unwrap ( ) . 0 ) ;
22
+ enum Addr {
23
+ Tcp ( SocketAddr ) ,
24
+ Unix ( PathBuf ) ,
25
+ }
26
+
27
+ fn run ( stream : impl Read + Write , rx : & Receiver < Message > ) {
28
+ let mut socket = BufReader :: new ( stream) ;
23
29
for msg in rx. iter ( ) {
24
30
match msg {
25
31
Message :: Read ( ref expected) => {
@@ -110,7 +116,7 @@ fn run(listener: &TcpListener, rx: &Receiver<Message>) {
110
116
111
117
let mut dst = Vec :: new ( ) ;
112
118
t ! ( socket. read_to_end( & mut dst) ) ;
113
- assert ! ( dst. len( ) == 0 ) ;
119
+ assert_eq ! ( dst. len( ) , 0 ) ;
114
120
}
115
121
116
122
fn lines_match ( expected : & str , mut actual : & str ) -> bool {
@@ -133,40 +139,79 @@ impl Server {
133
139
let listener = t ! ( TcpListener :: bind( "127.0.0.1:0" ) ) ;
134
140
let addr = t ! ( listener. local_addr( ) ) ;
135
141
let ( tx, rx) = channel ( ) ;
136
- let thread = thread:: spawn ( move || run ( & listener, & rx) ) ;
142
+ let thread = thread:: spawn ( move || run ( listener. accept ( ) . unwrap ( ) . 0 , & rx) ) ;
143
+ Server {
144
+ messages : Some ( tx) ,
145
+ addr : Addr :: Tcp ( addr) ,
146
+ thread : Some ( thread) ,
147
+ }
148
+ }
149
+
150
+ #[ cfg( not( windows) ) ]
151
+ pub fn new_unix ( ) -> Server {
152
+ use std:: os:: unix:: net:: UnixListener ;
153
+
154
+ let path = "/tmp/easy_server.sock" ;
155
+ std:: fs:: remove_file ( path) . ok ( ) ;
156
+ let listener = t ! ( UnixListener :: bind( path) ) ;
157
+ let ( tx, rx) = channel ( ) ;
158
+ let thread = thread:: spawn ( move || run ( listener. incoming ( ) . next ( ) . unwrap ( ) . unwrap ( ) , & rx) ) ;
137
159
Server {
138
160
messages : Some ( tx) ,
139
- addr : addr ,
161
+ addr : Addr :: Unix ( path . into ( ) ) ,
140
162
thread : Some ( thread) ,
141
163
}
142
164
}
143
165
144
166
pub fn receive ( & self , msg : & str ) {
145
- let msg = msg. replace ( "$PORT" , & self . addr . port ( ) . to_string ( ) ) ;
146
- self . msg ( Message :: Read ( msg) ) ;
167
+ self . msg ( Message :: Read ( self . replace_port ( msg) ) ) ;
168
+ }
169
+
170
+ fn replace_port ( & self , msg : & str ) -> String {
171
+ match & self . addr {
172
+ Addr :: Tcp ( addr) => msg. replace ( "$PORT" , & addr. port ( ) . to_string ( ) ) ,
173
+ Addr :: Unix ( _) => msg. to_string ( ) ,
174
+ }
147
175
}
148
176
149
177
pub fn send ( & self , msg : & str ) {
150
- let msg = msg. replace ( "$PORT" , & self . addr . port ( ) . to_string ( ) ) ;
151
- self . msg ( Message :: Write ( msg) ) ;
178
+ self . msg ( Message :: Write ( self . replace_port ( msg) ) ) ;
152
179
}
153
180
154
181
fn msg ( & self , msg : Message ) {
155
182
t ! ( self . messages. as_ref( ) . unwrap( ) . send( msg) ) ;
156
183
}
157
184
158
185
pub fn addr ( & self ) -> & SocketAddr {
159
- & self . addr
186
+ match & self . addr {
187
+ Addr :: Tcp ( addr) => addr,
188
+ Addr :: Unix ( _) => panic ! ( "server is a UnixListener" ) ,
189
+ }
190
+ }
191
+
192
+ #[ cfg( not( windows) ) ]
193
+ pub fn path ( & self ) -> & str {
194
+ match & self . addr {
195
+ Addr :: Tcp ( _) => panic ! ( "server is a TcpListener" ) ,
196
+ Addr :: Unix ( p) => p. as_os_str ( ) . to_str ( ) . unwrap ( ) ,
197
+ }
160
198
}
161
199
162
200
pub fn url ( & self , path : & str ) -> String {
163
- format ! ( "http://{}{}" , self . addr, path)
201
+ match & self . addr {
202
+ Addr :: Tcp ( addr) => format ! ( "http://{}{}" , addr, path) ,
203
+ Addr :: Unix ( _) => format ! ( "http://localhost{}" , path) ,
204
+ }
164
205
}
165
206
}
166
207
167
208
impl Drop for Server {
168
209
fn drop ( & mut self ) {
169
- drop ( TcpStream :: connect ( & self . addr ) ) ;
210
+ match & self . addr {
211
+ Addr :: Tcp ( addr) => drop ( TcpStream :: connect ( addr) ) ,
212
+ Addr :: Unix ( p) => t ! ( std:: fs:: remove_file( p) ) ,
213
+ }
214
+
170
215
drop ( self . messages . take ( ) ) ;
171
216
let res = self . thread . take ( ) . unwrap ( ) . join ( ) ;
172
217
if !thread:: panicking ( ) {
0 commit comments