github.com/glycerine/xcryptossh@v7.0.4+incompatible/timeout_test.go (about) 1 package ssh 2 3 import ( 4 "fmt" 5 "io" 6 "net" 7 "runtime/debug" 8 "testing" 9 "time" 10 ) 11 12 func init() { 13 // see all goroutines on panic for proper debugging of tests. 14 debug.SetTraceback("all") 15 } 16 17 // Tests of the Timeout factility. 18 // 19 // 1. Given that we want to detect when the remote side 20 // is not responding, when we set a read or 21 // a write timeout, the ssh.Channel should 22 // unblock our read (write) when the timeout 23 // expires. The channel should remain open 24 // (and not be auto closed) so that 25 // subsequent attempts to read (write) 26 // the slow-to-respond remote may actually 27 // succeed if they come back to servicing 28 // the ssh.Channel. In this respect we 29 // allow an ssh.Channel to act like a 30 // net.Conn with its deadline based timeouts. 31 // 32 // 2. When I/O does happen on an ssh.Channel, it 33 // should automatically bump the timeout 34 // into the future, so that the client 35 // reading (writing) doesn't have to keep 36 // re-setting the timeout manually, and 37 // more importantly, so transfers that 38 // take a long time but are actively 39 // moving bytes don't timeout simply 40 // because we didn't magically anticipate 41 // this and know it was going 42 // to be a large and lengthy file transfer. 43 // 44 // We call this facility 45 // SetIdleTimeout(dur time.Duration). 46 // 47 // It is the main API for ssh timeouts, and 48 // avoids requiring that client users need to 49 // manually re-impliment timeout handling logic 50 // after every Read and Write. In contrast, when 51 // using net.Conn deadlines, idle timeouts must 52 // be done very manually. Moreover cannot use 53 // standard appliances like io.Copy() because 54 // the Reads inside each require a prior 55 // deadline setting. 56 // 57 // See cts_test.go in addition to this file. 58 59 /* // write timeouts don't actuall work. 60 func TestSimpleWriteTimeout(t *testing.T) { 61 defer xtestend(xtestbegin(t)) 62 halt := NewHalter() 63 defer halt.RequestStop() 64 65 r, w, mux := channelPair(t, halt) 66 defer w.Close() 67 defer r.Close() 68 defer mux.Close() 69 70 abandon := "should never be written" 71 magic := "expected saluations" 72 go func() { 73 // use a quick timeout so the test runs quickly. 74 _, err := w.SetWriteIdleTimeout(50 * time.Millisecond) 75 if err != nil { 76 t.Fatalf("SetIdleTimeout: %v", err) 77 } 78 wt := w.GetWriteIdleTimer() 79 wt.BeginAttempt() 80 time.Sleep(100 * time.Millisecond) 81 n, err := w.Write([]byte(abandon)) 82 if err == nil || !err.(net.Error).Timeout() { 83 panic(fmt.Sprintf("expected to get a net.Error that had Timeout() true: '%v'. wrote n=%v", err, n)) 84 } 85 86 _, err = w.SetWriteIdleTimeout(0) 87 if err != nil { 88 t.Fatalf("canceling idle timeout: %v", err) 89 } 90 time.Sleep(200 * time.Millisecond) 91 p("SimpleTimeout: about to write which should succeed") 92 _, err = w.Write([]byte(magic)) 93 if err != nil { 94 p("SimpleTimeout: just write failed unexpectedly") 95 panic(fmt.Sprintf("write after cancelling write deadline: %v", err)) // timeout after canceling! 96 } 97 p("SimpleTimeout: just write which did succeed") 98 }() 99 100 var buf [1024]byte 101 n, err := r.Read(buf[:]) 102 if err != nil { 103 panic(fmt.Sprintf("Read: %v", err)) 104 } 105 got := string(buf[:n]) 106 if got != magic { 107 panic(fmt.Sprintf("Read: got %q want %q", got, magic)) 108 } 109 110 err = w.Close() 111 switch { 112 case err == nil: 113 //ok 114 case err == io.EOF: 115 // ok 116 default: 117 panic(fmt.Sprintf("Close: %v", err)) 118 } 119 } 120 */ 121 122 func TestSimpleReadTimeout(t *testing.T) { 123 defer xtestend(xtestbegin(t)) 124 halt := NewHalter() 125 defer halt.RequestStop() 126 127 r, w, mux := channelPair(t, halt) 128 defer w.Close() 129 defer r.Close() 130 defer mux.Close() 131 132 var buf [1024]byte 133 cancel := make(chan bool) 134 135 go func() { 136 select { 137 case <-time.After(100 * time.Second): 138 panic("2 msec Read timeout did not fire after 100 sec") 139 case <-cancel: 140 } 141 }() 142 143 // use a quick timeout so the test runs quickly. 144 err := r.SetReadIdleTimeout(2 * time.Millisecond) 145 if err != nil { 146 panic(fmt.Sprintf("SetIdleTimeout: %v", err)) 147 } 148 149 // no writer, so this should timeout. 150 n, err := r.Read(buf[:]) 151 152 if err == nil || !err.(net.Error).Timeout() || n > 0 { 153 panic(fmt.Sprintf("expected to get a net.Error that had Timeout() true with n = 0")) 154 } 155 cancel <- true 156 157 err = w.Close() 158 switch { 159 case err == nil: 160 //ok 161 case err == io.EOF: 162 // ok 163 default: 164 panic(fmt.Sprintf("Close: %v", err)) 165 } 166 } 167 168 func TestSimpleReadAfterTimeout(t *testing.T) { 169 defer xtestend(xtestbegin(t)) 170 halt := NewHalter() 171 defer halt.RequestStop() 172 173 r, w, mux := channelPair(t, halt) 174 defer w.Close() 175 defer r.Close() 176 defer mux.Close() 177 178 var buf [1024]byte 179 cancel := make(chan bool) 180 181 go func() { 182 select { 183 case <-time.After(100 * time.Second): 184 panic("2 msec Read timeout did not fire after 100 sec") 185 case <-cancel: 186 } 187 }() 188 189 // use a quick timeout so the test runs quickly. 190 err := r.SetReadIdleTimeout(2 * time.Millisecond) 191 if err != nil { 192 panic(fmt.Sprintf("SetIdleTimeout: %v", err)) 193 } 194 195 // no writer, so this should timeout. 196 n, err := r.Read(buf[:]) 197 198 if err == nil || !err.(net.Error).Timeout() || n > 0 { 199 panic(fmt.Sprintf("expected to get a net.Error that had Timeout() true with n = 0")) 200 } 201 cancel <- true 202 203 // And we *must* reset the timeout status before trying to Read again. 204 err = r.SetReadIdleTimeout(0) 205 if err != nil { 206 panic(fmt.Sprintf("reset with SetIdleTimeout: %v", err)) 207 } 208 209 // now start a writer and verify that we can read okay 210 // even after a prior timeout. 211 212 magic := "expected saluations" 213 go func() { 214 _, werr := w.Write([]byte(magic)) 215 if werr != nil { 216 panic(fmt.Sprintf("write after cancelling write deadline: %v", werr)) 217 } 218 }() 219 220 n, err = r.Read(buf[:]) 221 if err != nil { 222 panic(fmt.Sprintf("Read after timed-out Read got err: %v", err)) 223 } 224 if n != len(magic) { 225 panic(fmt.Sprintf("short Read after timed-out Read")) 226 } 227 got := string(buf[:n]) 228 if got != magic { 229 panic(fmt.Sprintf("Read: got %q want %q", got, magic)) 230 } 231 232 err = w.Close() 233 switch { 234 case err == nil: 235 //ok 236 case err == io.EOF: 237 // ok 238 default: 239 panic(fmt.Sprintf("Close: %v", err)) 240 } 241 } 242 243 // deadlines 244 245 func TestSimpleReadDeadline(t *testing.T) { 246 defer xtestend(xtestbegin(t)) 247 248 halt := NewHalter() 249 defer halt.RequestStop() 250 251 r, w, mux := channelPair(t, halt) 252 defer w.Close() 253 defer r.Close() 254 defer mux.Close() 255 256 var buf [1024]byte 257 cancel := make(chan bool) 258 259 go func() { 260 select { 261 case <-time.After(10 * time.Second): 262 panic("20 msec Read timeout did not fire after 10 sec") 263 case <-cancel: 264 } 265 }() 266 267 // use a quick timeout so the test runs quickly. 268 err := r.SetReadDeadline(time.Now().Add(20 * time.Millisecond)) 269 if err != nil { 270 panic(fmt.Sprintf("SetReadDeadline: %v", err)) 271 } 272 273 // no writer, so this should timeout. 274 n, err := r.Read(buf[:]) 275 276 if err == nil || !err.(net.Error).Timeout() || n > 0 { 277 panic(fmt.Sprintf("expected to get a net.Error that had Timeout() true with n = 0")) 278 } 279 cancel <- true 280 281 err = w.Close() 282 switch { 283 case err == nil: 284 //ok 285 case err == io.EOF: 286 // ok 287 default: 288 panic(fmt.Sprintf("Close: %v", err)) 289 } 290 }