github.com/supragya/TendermintConnector@v0.0.0-20210619045051-113e32b84fb1/chains/tm34/libs/flowrate/io_test.go (about) 1 // 2 // Written by Maxim Khitrov (November 2012) 3 // 4 5 package flowrate 6 7 import ( 8 "bytes" 9 "testing" 10 "time" 11 ) 12 13 const ( 14 _50ms = 50 * time.Millisecond 15 _100ms = 100 * time.Millisecond 16 _200ms = 200 * time.Millisecond 17 _300ms = 300 * time.Millisecond 18 _400ms = 400 * time.Millisecond 19 _500ms = 500 * time.Millisecond 20 ) 21 22 func nextStatus(m *Monitor) Status { 23 samples := m.samples 24 for i := 0; i < 30; i++ { 25 if s := m.Status(); s.Samples != samples { 26 return s 27 } 28 time.Sleep(5 * time.Millisecond) 29 } 30 return m.Status() 31 } 32 33 func TestReader(t *testing.T) { 34 in := make([]byte, 100) 35 for i := range in { 36 in[i] = byte(i) 37 } 38 b := make([]byte, 100) 39 r := NewReader(bytes.NewReader(in), 100) 40 start := time.Now() 41 42 // Make sure r implements Limiter 43 _ = Limiter(r) 44 45 // 1st read of 10 bytes is performed immediately 46 if n, err := r.Read(b); n != 10 || err != nil { 47 t.Fatalf("r.Read(b) expected 10 (<nil>); got %v (%v)", n, err) 48 } else if rt := time.Since(start); rt > _50ms { 49 t.Fatalf("r.Read(b) took too long (%v)", rt) 50 } 51 52 // No new Reads allowed in the current sample 53 r.SetBlocking(false) 54 if n, err := r.Read(b); n != 0 || err != nil { 55 t.Fatalf("r.Read(b) expected 0 (<nil>); got %v (%v)", n, err) 56 } else if rt := time.Since(start); rt > _50ms { 57 t.Fatalf("r.Read(b) took too long (%v)", rt) 58 } 59 60 status := [6]Status{0: r.Status()} // No samples in the first status 61 62 // 2nd read of 10 bytes blocks until the next sample 63 r.SetBlocking(true) 64 if n, err := r.Read(b[10:]); n != 10 || err != nil { 65 t.Fatalf("r.Read(b[10:]) expected 10 (<nil>); got %v (%v)", n, err) 66 } else if rt := time.Since(start); rt < _100ms { 67 t.Fatalf("r.Read(b[10:]) returned ahead of time (%v)", rt) 68 } 69 70 status[1] = r.Status() // 1st sample 71 status[2] = nextStatus(r.Monitor) // 2nd sample 72 status[3] = nextStatus(r.Monitor) // No activity for the 3rd sample 73 74 if n := r.Done(); n != 20 { 75 t.Fatalf("r.Done() expected 20; got %v", n) 76 } 77 78 status[4] = r.Status() 79 status[5] = nextStatus(r.Monitor) // Timeout 80 start = status[0].Start 81 82 // Active, Bytes, Samples, InstRate, CurRate, AvgRate, PeakRate, BytesRem, Start, Duration, Idle, TimeRem, Progress 83 want := []Status{ 84 {start, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, 85 {start, 10, 1, 100, 100, 100, 100, 0, _100ms, 0, 0, 0, true}, 86 {start, 20, 2, 100, 100, 100, 100, 0, _200ms, _100ms, 0, 0, true}, 87 {start, 20, 3, 0, 90, 67, 100, 0, _300ms, _200ms, 0, 0, true}, 88 {start, 20, 3, 0, 0, 67, 100, 0, _300ms, 0, 0, 0, false}, 89 {start, 20, 3, 0, 0, 67, 100, 0, _300ms, 0, 0, 0, false}, 90 } 91 for i, s := range status { 92 s := s 93 if !statusesAreEqual(&s, &want[i]) { 94 t.Errorf("r.Status(%v)\nexpected: %v\ngot : %v", i, want[i], s) 95 } 96 } 97 if !bytes.Equal(b[:20], in[:20]) { 98 t.Errorf("r.Read() input doesn't match output") 99 } 100 } 101 102 func TestWriter(t *testing.T) { 103 b := make([]byte, 100) 104 for i := range b { 105 b[i] = byte(i) 106 } 107 w := NewWriter(&bytes.Buffer{}, 200) 108 start := time.Now() 109 110 // Make sure w implements Limiter 111 _ = Limiter(w) 112 113 // Non-blocking 20-byte write for the first sample returns ErrLimit 114 w.SetBlocking(false) 115 if n, err := w.Write(b); n != 20 || err != ErrLimit { 116 t.Fatalf("w.Write(b) expected 20 (ErrLimit); got %v (%v)", n, err) 117 } else if rt := time.Since(start); rt > _50ms { 118 t.Fatalf("w.Write(b) took too long (%v)", rt) 119 } 120 121 // Blocking 80-byte write 122 w.SetBlocking(true) 123 if n, err := w.Write(b[20:]); n != 80 || err != nil { 124 t.Fatalf("w.Write(b[20:]) expected 80 (<nil>); got %v (%v)", n, err) 125 } else if rt := time.Since(start); rt < _300ms { 126 // Explanation for `rt < _300ms` (as opposed to `< _400ms`) 127 // 128 // |<-- start | | 129 // epochs: -----0ms|---100ms|---200ms|---300ms|---400ms 130 // sends: 20|20 |20 |20 |20# 131 // 132 // NOTE: The '#' symbol can thus happen before 400ms is up. 133 // Thus, we can only panic if rt < _300ms. 134 t.Fatalf("w.Write(b[20:]) returned ahead of time (%v)", rt) 135 } 136 137 w.SetTransferSize(100) 138 status := []Status{w.Status(), nextStatus(w.Monitor)} 139 start = status[0].Start 140 141 // Active, Bytes, Samples, InstRate, CurRate, AvgRate, PeakRate, BytesRem, Start, Duration, Idle, TimeRem, Progress 142 want := []Status{ 143 {start, 80, 4, 200, 200, 200, 200, 20, _400ms, 0, _100ms, 80000, true}, 144 {start, 100, 5, 200, 200, 200, 200, 0, _500ms, _100ms, 0, 100000, true}, 145 } 146 147 for i, s := range status { 148 s := s 149 if !statusesAreEqual(&s, &want[i]) { 150 t.Errorf("w.Status(%v)\nexpected: %v\ngot : %v\n", i, want[i], s) 151 } 152 } 153 if !bytes.Equal(b, w.Writer.(*bytes.Buffer).Bytes()) { 154 t.Errorf("w.Write() input doesn't match output") 155 } 156 } 157 158 const maxDeviationForDuration = 50 * time.Millisecond 159 const maxDeviationForRate int64 = 50 160 161 // statusesAreEqual returns true if s1 is equal to s2. Equality here means 162 // general equality of fields except for the duration and rates, which can 163 // drift due to unpredictable delays (e.g. thread wakes up 25ms after 164 // `time.Sleep` has ended). 165 func statusesAreEqual(s1 *Status, s2 *Status) bool { 166 if s1.Active == s2.Active && 167 s1.Start == s2.Start && 168 durationsAreEqual(s1.Duration, s2.Duration, maxDeviationForDuration) && 169 s1.Idle == s2.Idle && 170 s1.Bytes == s2.Bytes && 171 s1.Samples == s2.Samples && 172 ratesAreEqual(s1.InstRate, s2.InstRate, maxDeviationForRate) && 173 ratesAreEqual(s1.CurRate, s2.CurRate, maxDeviationForRate) && 174 ratesAreEqual(s1.AvgRate, s2.AvgRate, maxDeviationForRate) && 175 ratesAreEqual(s1.PeakRate, s2.PeakRate, maxDeviationForRate) && 176 s1.BytesRem == s2.BytesRem && 177 durationsAreEqual(s1.TimeRem, s2.TimeRem, maxDeviationForDuration) && 178 s1.Progress == s2.Progress { 179 return true 180 } 181 return false 182 } 183 184 func durationsAreEqual(d1 time.Duration, d2 time.Duration, maxDeviation time.Duration) bool { 185 return d2-d1 <= maxDeviation 186 } 187 188 func ratesAreEqual(r1 int64, r2 int64, maxDeviation int64) bool { 189 sub := r1 - r2 190 if sub < 0 { 191 sub = -sub 192 } 193 if sub <= maxDeviation { 194 return true 195 } 196 return false 197 }