github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/burst_test.go (about) 1 /* 2 * Copyright (c) 2020, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package common 21 22 import ( 23 "testing" 24 "time" 25 ) 26 27 func TestBurstMonitoredConn(t *testing.T) { 28 29 upstreamTargetBytes := int64(100000) 30 downstreamTargetBytes := int64(1000000) 31 burstDeadline := 1 * time.Second 32 33 baseTime := time.Now() 34 35 dummy := &dummyConn{} 36 37 conn := NewBurstMonitoredConn( 38 dummy, 39 true, 40 upstreamTargetBytes, 41 burstDeadline, 42 downstreamTargetBytes, 43 burstDeadline) 44 45 // Simulate 128KB/s up, 1MB/s down; transmit >= min bytes in segments; sets "first" and "min" 46 47 dummy.SetRateLimits(131072, 1048576) 48 49 segments := 10 50 51 b := make([]byte, int(upstreamTargetBytes)/segments) 52 firstReadStart := time.Now() 53 for i := 0; i < segments; i++ { 54 conn.Read(b) 55 } 56 firstReadEnd := time.Now() 57 58 b = make([]byte, int(downstreamTargetBytes)/segments) 59 firstWriteStart := time.Now() 60 for i := 0; i < segments; i++ { 61 conn.Write(b) 62 } 63 firstWriteEnd := time.Now() 64 65 time.Sleep(burstDeadline * 2) 66 67 // Simulate 1MB/s up, 10MB/s down; repeatedly transmit < min bytes before deadline; ignored 68 69 dummy.SetRateLimits(1048576, 10485760) 70 71 b = make([]byte, 1) 72 segments = 1000 73 for i := 0; i < segments; i++ { 74 conn.Read(b) 75 } 76 for i := 0; i < segments; i++ { 77 conn.Write(b) 78 } 79 80 time.Sleep(burstDeadline * 2) 81 82 // Simulate 512Kb/s up, 5MB/s down; transmit >= min bytes; sets "max" 83 84 dummy.SetRateLimits(524288, 5242880) 85 86 maxReadStart := time.Now() 87 conn.Read(make([]byte, upstreamTargetBytes)) 88 maxReadEnd := time.Now() 89 90 maxWriteStart := time.Now() 91 conn.Write(make([]byte, downstreamTargetBytes)) 92 maxWriteEnd := time.Now() 93 94 time.Sleep(burstDeadline * 2) 95 96 // Simulate 256Kb/s up, 2MB/s down;, transmit >= min bytes; sets "last" 97 98 dummy.SetRateLimits(262144, 2097152) 99 100 lastReadStart := time.Now() 101 conn.Read(make([]byte, upstreamTargetBytes)) 102 lastReadEnd := time.Now() 103 104 lastWriteStart := time.Now() 105 conn.Write(make([]byte, downstreamTargetBytes)) 106 lastWriteEnd := time.Now() 107 108 time.Sleep(burstDeadline * 2) 109 110 conn.Close() 111 112 t.Logf("upstream first: %d bytes in %s; %d bytes/s", 113 conn.readBursts.first.bytes, conn.readBursts.first.duration(), conn.readBursts.first.rate()) 114 t.Logf("upstream last: %d bytes in %s; %d bytes/s", 115 conn.readBursts.last.bytes, conn.readBursts.last.duration(), conn.readBursts.last.rate()) 116 t.Logf("upstream min: %d bytes in %s; %d bytes/s", 117 conn.readBursts.min.bytes, conn.readBursts.min.duration(), conn.readBursts.min.rate()) 118 t.Logf("upstream max: %d bytes in %s; %d bytes/s", 119 conn.readBursts.max.bytes, conn.readBursts.max.duration(), conn.readBursts.max.rate()) 120 t.Logf("downstream first: %d bytes in %s; %d bytes/s", 121 conn.writeBursts.first.bytes, conn.writeBursts.first.duration(), conn.writeBursts.first.rate()) 122 t.Logf("downstream last: %d bytes in %s; %d bytes/s", 123 conn.writeBursts.last.bytes, conn.writeBursts.last.duration(), conn.writeBursts.last.rate()) 124 t.Logf("downstream min: %d bytes in %s; %d bytes/s", 125 conn.writeBursts.min.bytes, conn.writeBursts.min.duration(), conn.writeBursts.min.rate()) 126 t.Logf("downstream max: %d bytes in %s; %d bytes/s", 127 conn.writeBursts.max.bytes, conn.writeBursts.max.duration(), conn.writeBursts.max.rate()) 128 129 logFields := conn.GetMetrics(baseTime) 130 131 if len(logFields) != 32 { 132 t.Errorf("unexpected metric count: %d", len(logFields)) 133 } 134 135 for name, expectedValue := range map[string]int64{ 136 "burst_upstream_first_offset": int64(firstReadStart.Sub(baseTime) / time.Millisecond), 137 "burst_upstream_first_duration": int64(firstReadEnd.Sub(firstReadStart) / time.Millisecond), 138 "burst_upstream_first_bytes": upstreamTargetBytes, 139 "burst_upstream_first_rate": 131072, 140 "burst_upstream_last_offset": int64(lastReadStart.Sub(baseTime) / time.Millisecond), 141 "burst_upstream_last_duration": int64(lastReadEnd.Sub(lastReadStart) / time.Millisecond), 142 "burst_upstream_last_bytes": upstreamTargetBytes, 143 "burst_upstream_last_rate": 262144, 144 "burst_upstream_min_offset": int64(firstReadStart.Sub(baseTime) / time.Millisecond), 145 "burst_upstream_min_duration": int64(firstReadEnd.Sub(firstReadStart) / time.Millisecond), 146 "burst_upstream_min_bytes": upstreamTargetBytes, 147 "burst_upstream_min_rate": 131072, 148 "burst_upstream_max_offset": int64(maxReadStart.Sub(baseTime) / time.Millisecond), 149 "burst_upstream_max_duration": int64(maxReadEnd.Sub(maxReadStart) / time.Millisecond), 150 "burst_upstream_max_bytes": upstreamTargetBytes, 151 "burst_upstream_max_rate": 524288, 152 "burst_downstream_first_offset": int64(firstWriteStart.Sub(baseTime) / time.Millisecond), 153 "burst_downstream_first_duration": int64(firstWriteEnd.Sub(firstWriteStart) / time.Millisecond), 154 "burst_downstream_first_bytes": downstreamTargetBytes, 155 "burst_downstream_first_rate": 1048576, 156 "burst_downstream_last_offset": int64(lastWriteStart.Sub(baseTime) / time.Millisecond), 157 "burst_downstream_last_duration": int64(lastWriteEnd.Sub(lastWriteStart) / time.Millisecond), 158 "burst_downstream_last_bytes": downstreamTargetBytes, 159 "burst_downstream_last_rate": 2097152, 160 "burst_downstream_min_offset": int64(firstWriteStart.Sub(baseTime) / time.Millisecond), 161 "burst_downstream_min_duration": int64(firstWriteEnd.Sub(firstWriteStart) / time.Millisecond), 162 "burst_downstream_min_bytes": downstreamTargetBytes, 163 "burst_downstream_min_rate": 1048576, 164 "burst_downstream_max_offset": int64(maxWriteStart.Sub(baseTime) / time.Millisecond), 165 "burst_downstream_max_duration": int64(maxWriteEnd.Sub(maxWriteStart) / time.Millisecond), 166 "burst_downstream_max_bytes": downstreamTargetBytes, 167 "burst_downstream_max_rate": 5242880, 168 } { 169 value, ok := logFields[name] 170 if !ok { 171 t.Errorf("missing expected metric: %s", name) 172 continue 173 } 174 valueInt64, ok := value.(int64) 175 if !ok { 176 t.Errorf("missing expected metric type: %s (%T)", name, value) 177 continue 178 } 179 minAcceptable := int64(float64(expectedValue) * 0.90) 180 maxAcceptable := int64(float64(expectedValue) * 1.10) 181 if valueInt64 < minAcceptable || valueInt64 > maxAcceptable { 182 t.Errorf("unexpected metric value: %s (%v <= %v <= %v)", 183 name, minAcceptable, valueInt64, maxAcceptable) 184 continue 185 } 186 } 187 }