github.com/glycerine/xcryptossh@v7.0.4+incompatible/writeto_test.go (about) 1 package ssh 2 3 // Write timeouts don't actually work. 4 // This is because the underlying ssh 5 // returns err==nil when the write has 6 // only been buffered locally. 7 /* 8 import ( 9 "fmt" 10 "io" 11 "net" 12 "testing" 13 "time" 14 ) 15 16 // Given a 1000 msec idle write timeout, when reads stop, the Write() calls 17 // should return Timeout() == true errors. The is the compliment 18 // to the phase_test.go. 19 // 20 func TestTimeout007WriteIdlesOutWhenReadsStop(t *testing.T) { 21 defer xtestend(xtestbegin(t)) 22 halt := NewHalter() 23 defer halt.RequestStop() 24 25 r, w, mux := channelPair(t, halt) 26 27 idleout := 1000 * time.Millisecond 28 overall := 3 * idleout 29 30 t0 := time.Now() 31 tstop := t0.Add(overall) 32 33 // set the read timeout on the writer 34 err := w.SetIdleTimeout(idleout) 35 if err != nil { 36 panic(fmt.Sprintf("w.SetIdleTimeout: %v", err)) 37 } 38 39 readErr := make(chan error) 40 writeErr := make(chan error) 41 var seq *seqWords 42 var ring *infiniteRing 43 var whenLastWriteTimedout time.Time 44 45 go to007ReaderToRing(idleout, r, overall, tstop, readErr, &ring) 46 47 go to007SeqWordsToWriter(w, tstop, writeErr, &seq, &whenLastWriteTimedout) 48 49 // wait for our overall time, and for both to return 50 var rerr, werr error 51 var rok, wok bool 52 complete := func() bool { 53 return rok && wok 54 } 55 collectionLoop: 56 for { 57 select { 58 case <-time.After(2 * overall): 59 panic(fmt.Sprintf("TestTimeout007WriteIdlesOutWhenReadsStop: waited " + 60 "two overall, yet still no idle timeout!")) 61 62 case rerr = <-readErr: 63 pp("got rerr: '%#v'", rerr) 64 now := time.Now() 65 if now.Before(tstop) { 66 panic(fmt.Sprintf("rerr: '%v', stopped too early, before '%v'. now=%v. now-before=%v", rerr, tstop, now, now.Sub(tstop))) // panicing here 67 } 68 rok = true 69 70 if complete() { 71 break collectionLoop 72 } 73 74 case werr = <-writeErr: 75 pp("got werr") 76 now := time.Now() 77 if now.Before(tstop) { 78 panic(fmt.Sprintf("werr: '%v', stopped too early, before '%v'. now=%v. now-before=%v", werr, tstop, now, now.Sub(tstop))) 79 } 80 wok = true 81 82 // verify that write got a timeout: this is the main point of this test. 83 nerr, ok := werr.(net.Error) 84 if !ok || !nerr.Timeout() { 85 panic(fmt.Sprintf("big problem: expected a timeout error back from Write()."+ 86 " instead got '%v'", werr)) 87 } 88 89 if complete() { 90 break collectionLoop 91 } 92 } 93 94 } 95 p("done with collection loop") 96 97 p("whenLastWriteTimedout=%v, tstop=%v, idleout=%v", whenLastWriteTimedout, tstop, idleout) 98 99 // sanity check that whenLastWriteTimedout in when we expect 100 if whenLastWriteTimedout.Before(tstop) { 101 panic("premature timeout, very bad") 102 } 103 if whenLastWriteTimedout.After(tstop.Add(3 * idleout)) { 104 panic("too slow a time out, very bad") 105 } 106 107 w.Close() 108 r.Close() 109 mux.Close() 110 111 } 112 113 // setup reader r -> infiniteRing ring. returns 114 // readOk upon success. 115 func to007ReaderToRing(idleout time.Duration, r Channel, overall time.Duration, tstop time.Time, readErr chan error, pRing **infiniteRing) (err error) { 116 defer func() { 117 p("readerToRing returning on readErr, err = '%v'", err) 118 readErr <- err 119 }() 120 121 ring := newInfiniteRing() 122 *pRing = ring 123 124 src := r 125 dst := ring 126 buf := make([]byte, 32*1024) 127 128 for { 129 nr, er := src.Read(buf) 130 if nr > 0 { 131 nw, ew := dst.Write(buf[0:nr]) 132 if ew != nil { 133 err = ew 134 p("readerToRing sees Write err %v", ew) 135 break 136 } 137 if nr != nw { 138 err = io.ErrShortWrite 139 break 140 } 141 } 142 143 if time.Now().After(tstop) { 144 p("reader: reached tstop, bailing out of copy loop.") 145 return readOk 146 } 147 148 if er != nil { 149 p("readerToRing sees Read err %v", er) 150 if er != io.EOF { 151 err = er 152 } 153 break 154 } 155 } //end for 156 157 return err 158 } 159 160 // read from the integers 0,1,2,... and write to w until tstop. 161 // returns writeOk upon success 162 func to007SeqWordsToWriter(w Channel, tstop time.Time, writeErr chan error, pSeqWords **seqWords, whenerr *time.Time) (err error) { 163 defer func() { 164 p("to007SeqWordsToWriter returning err = '%v'", err) 165 writeErr <- err 166 }() 167 src := newSequentialWords() 168 *pSeqWords = src 169 dst := w 170 buf := make([]byte, 32*1024) 171 for { 172 nr, er := src.Read(buf) 173 if nr > 0 { 174 nw, ew := dst.Write(buf[0:nr]) 175 *whenerr = time.Now() 176 if ew != nil { 177 pp("seqWriter sees Write err %v", ew) 178 err = ew 179 break 180 } 181 if nr != nw { 182 err = io.ErrShortWrite 183 break 184 } 185 } 186 if er != nil { 187 if er != io.EOF { 188 err = er 189 } 190 break 191 } 192 } 193 194 return err 195 } 196 */