1// Copyright 2016-2019 The NATS Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package bench 15 16import ( 17 "fmt" 18 "strings" 19 "testing" 20 "time" 21 22 "github.com/nats-io/nats.go" 23) 24 25const ( 26 MsgSize = 8 27 Million = 1000 * 1000 28) 29 30var baseTime = time.Now() 31 32func millionMessagesSecondSample(seconds int) *Sample { 33 messages := Million * seconds 34 start := baseTime 35 end := start.Add(time.Second * time.Duration(seconds)) 36 nc := new(nats.Conn) 37 38 s := NewSample(messages, MsgSize, start, end, nc) 39 s.MsgCnt = uint64(messages) 40 s.MsgBytes = uint64(messages * MsgSize) 41 s.IOBytes = s.MsgBytes 42 return s 43} 44 45func TestDuration(t *testing.T) { 46 s := millionMessagesSecondSample(1) 47 duration := s.End.Sub(s.Start) 48 if duration != s.Duration() || duration != time.Second { 49 t.Fatal("Expected sample duration to be 1 second") 50 } 51} 52 53func TestSeconds(t *testing.T) { 54 s := millionMessagesSecondSample(1) 55 seconds := s.End.Sub(s.Start).Seconds() 56 if seconds != s.Seconds() || seconds != 1.0 { 57 t.Fatal("Expected sample seconds to be 1 second") 58 } 59} 60 61func TestRate(t *testing.T) { 62 s := millionMessagesSecondSample(60) 63 if s.Rate() != Million { 64 t.Fatal("Expected rate at 1 million msgs") 65 } 66} 67 68func TestThoughput(t *testing.T) { 69 s := millionMessagesSecondSample(60) 70 if s.Throughput() != Million*MsgSize { 71 t.Fatalf("Expected throughput at %d million bytes/sec", MsgSize) 72 } 73} 74 75func TestStrings(t *testing.T) { 76 s := millionMessagesSecondSample(60) 77 if len(s.String()) == 0 { 78 t.Fatal("Sample didn't provide a String") 79 } 80} 81 82func TestGroupDuration(t *testing.T) { 83 sg := NewSampleGroup() 84 sg.AddSample(millionMessagesSecondSample(1)) 85 sg.AddSample(millionMessagesSecondSample(2)) 86 duration := sg.End.Sub(sg.Start) 87 if duration != sg.Duration() || duration != time.Duration(2)*time.Second { 88 t.Fatal("Expected aggregate duration to be 2.0 seconds") 89 } 90} 91 92func TestGroupSeconds(t *testing.T) { 93 sg := NewSampleGroup() 94 sg.AddSample(millionMessagesSecondSample(1)) 95 sg.AddSample(millionMessagesSecondSample(2)) 96 sg.AddSample(millionMessagesSecondSample(3)) 97 seconds := sg.End.Sub(sg.Start).Seconds() 98 if seconds != sg.Seconds() || seconds != 3.0 { 99 t.Fatal("Expected aggregate seconds to be 3.0 seconds") 100 } 101} 102 103func TestGroupRate(t *testing.T) { 104 sg := NewSampleGroup() 105 sg.AddSample(millionMessagesSecondSample(1)) 106 sg.AddSample(millionMessagesSecondSample(2)) 107 sg.AddSample(millionMessagesSecondSample(3)) 108 if sg.Rate() != Million*2 { 109 t.Fatal("Expected MsgRate at 2 million msg/sec") 110 } 111} 112 113func TestGroupThoughput(t *testing.T) { 114 sg := NewSampleGroup() 115 sg.AddSample(millionMessagesSecondSample(1)) 116 sg.AddSample(millionMessagesSecondSample(2)) 117 sg.AddSample(millionMessagesSecondSample(3)) 118 if sg.Throughput() != 2*Million*MsgSize { 119 t.Fatalf("Expected througput at %d million bytes/sec", 2*MsgSize) 120 } 121} 122 123func TestMinMaxRate(t *testing.T) { 124 sg := NewSampleGroup() 125 sg.AddSample(millionMessagesSecondSample(1)) 126 sg.AddSample(millionMessagesSecondSample(2)) 127 sg.AddSample(millionMessagesSecondSample(3)) 128 if sg.MinRate() != sg.MaxRate() { 129 t.Fatal("Expected MinRate == MaxRate") 130 } 131} 132 133func TestAvgRate(t *testing.T) { 134 sg := NewSampleGroup() 135 sg.AddSample(millionMessagesSecondSample(1)) 136 sg.AddSample(millionMessagesSecondSample(2)) 137 sg.AddSample(millionMessagesSecondSample(3)) 138 if sg.MinRate() != sg.AvgRate() { 139 t.Fatal("Expected MinRate == AvgRate") 140 } 141} 142 143func TestStdDev(t *testing.T) { 144 sg := NewSampleGroup() 145 sg.AddSample(millionMessagesSecondSample(1)) 146 sg.AddSample(millionMessagesSecondSample(2)) 147 sg.AddSample(millionMessagesSecondSample(3)) 148 if sg.StdDev() != 0.0 { 149 t.Fatal("Expected stddev to be zero") 150 } 151} 152 153func TestBenchSetup(t *testing.T) { 154 bench := NewBenchmark("test", 1, 1) 155 bench.AddSubSample(millionMessagesSecondSample(1)) 156 bench.AddPubSample(millionMessagesSecondSample(1)) 157 bench.Close() 158 if len(bench.RunID) == 0 { 159 t.Fatal("Bench doesn't have a RunID") 160 } 161 if len(bench.Pubs.Samples) != 1 { 162 t.Fatal("Expected one publisher") 163 } 164 if len(bench.Subs.Samples) != 1 { 165 t.Fatal("Expected one subscriber") 166 } 167 if bench.MsgCnt != 2*Million { 168 t.Fatal("Expected 2 million msgs") 169 } 170 if bench.IOBytes != 2*Million*MsgSize { 171 t.Fatalf("Expected %d million bytes", 2*MsgSize) 172 } 173 if bench.Duration() != time.Second { 174 t.Fatal("Expected duration to be 1 second") 175 } 176} 177 178func makeBench(subs, pubs int) *Benchmark { 179 bench := NewBenchmark("test", subs, pubs) 180 for i := 0; i < subs; i++ { 181 bench.AddSubSample(millionMessagesSecondSample(1)) 182 } 183 for i := 0; i < pubs; i++ { 184 bench.AddPubSample(millionMessagesSecondSample(1)) 185 } 186 bench.Close() 187 return bench 188} 189 190func TestCsv(t *testing.T) { 191 bench := makeBench(1, 1) 192 csv := bench.CSV() 193 lines := strings.Split(csv, "\n") 194 if len(lines) != 4 { 195 t.Fatal("Expected 4 lines of output from the CSV string") 196 } 197 198 fields := strings.Split(lines[1], ",") 199 if len(fields) != 7 { 200 t.Fatal("Expected 7 fields") 201 } 202} 203 204func TestBenchStrings(t *testing.T) { 205 bench := makeBench(1, 1) 206 s := bench.Report() 207 lines := strings.Split(s, "\n") 208 if len(lines) != 4 { 209 t.Fatal("Expected 3 lines of output: header, pub, sub, empty") 210 } 211 212 bench = makeBench(2, 2) 213 s = bench.Report() 214 lines = strings.Split(s, "\n") 215 if len(lines) != 10 { 216 fmt.Printf("%q\n", s) 217 218 t.Fatal("Expected 11 lines of output: header, pub header, pub x 2, stats, sub headers, sub x 2, stats, empty") 219 } 220} 221 222func TestMsgsPerClient(t *testing.T) { 223 zero := MsgsPerClient(0, 0) 224 if len(zero) != 0 { 225 t.Fatal("Expected 0 length for 0 clients") 226 } 227 onetwo := MsgsPerClient(1, 2) 228 if len(onetwo) != 2 || onetwo[0] != 1 || onetwo[1] != 0 { 229 t.Fatal("Expected uneven distribution") 230 } 231 twotwo := MsgsPerClient(2, 2) 232 if len(twotwo) != 2 || twotwo[0] != 1 || twotwo[1] != 1 { 233 t.Fatal("Expected even distribution") 234 } 235 threetwo := MsgsPerClient(3, 2) 236 if len(threetwo) != 2 || threetwo[0] != 2 || threetwo[1] != 1 { 237 t.Fatal("Expected uneven distribution") 238 } 239} 240