@@ -3,6 +3,9 @@ package atreugo
3
3
import (
4
4
"bytes"
5
5
"errors"
6
+ "fmt"
7
+ "math/rand"
8
+ "net"
6
9
"reflect"
7
10
"testing"
8
11
"time"
@@ -160,75 +163,174 @@ func Test_New(t *testing.T) { //nolint:funlen,gocognit
160
163
}
161
164
162
165
func Test_newFasthttpServer (t * testing.T ) { //nolint:funlen
163
- type args struct {
164
- compress bool
166
+ cfg := Config {
167
+ Name : "test" ,
168
+ HeaderReceived : func (header * fasthttp.RequestHeader ) fasthttp.RequestConfig {
169
+ return fasthttp.RequestConfig {}
170
+ },
171
+ Concurrency : rand .Int (), // nolint:gosec
172
+ DisableKeepalive : true ,
173
+ ReadBufferSize : rand .Int (), // nolint:gosec
174
+ WriteBufferSize : rand .Int (), // nolint:gosec
175
+ ReadTimeout : time .Duration (rand .Int ()), // nolint:gosec
176
+ WriteTimeout : time .Duration (rand .Int ()), // nolint:gosec
177
+ IdleTimeout : time .Duration (rand .Int ()), // nolint:gosec
178
+ MaxConnsPerIP : rand .Int (), // nolint:gosec
179
+ MaxRequestsPerConn : rand .Int (), // nolint:gosec
180
+ MaxRequestBodySize : rand .Int (), // nolint:gosec
181
+ ReduceMemoryUsage : true ,
182
+ GetOnly : true ,
183
+ DisablePreParseMultipartForm : true ,
184
+ LogAllErrors : true ,
185
+ DisableHeaderNamesNormalizing : true ,
186
+ SleepWhenConcurrencyLimitsExceeded : time .Duration (rand .Int ()), // nolint:gosec
187
+ NoDefaultServerHeader : true ,
188
+ NoDefaultDate : true ,
189
+ NoDefaultContentType : true ,
190
+ ConnState : func (net.Conn , fasthttp.ConnState ) {},
191
+ KeepHijackedConns : true ,
165
192
}
166
193
167
- type want struct {
168
- compress bool
194
+ srv := newFasthttpServer (cfg , testLog )
195
+
196
+ if srv == nil {
197
+ t .Fatal ("newFasthttpServer() == nil" )
198
+ }
199
+
200
+ fasthttpServerType := reflect .TypeOf (fasthttp.Server {})
201
+ configType := reflect .TypeOf (Config {})
202
+
203
+ fasthttpServerValue := reflect .ValueOf (* srv ) // nolint:govet
204
+ configValue := reflect .ValueOf (cfg )
205
+
206
+ for i := 0 ; i < fasthttpServerType .NumField (); i ++ {
207
+ field := fasthttpServerType .Field (i )
208
+
209
+ if ! unicode .IsUpper (rune (field .Name [0 ])) { // Check if the field is public
210
+ continue
211
+ } else if gotils .StringSliceInclude (notConfigFasthttpFields , field .Name ) {
212
+ continue
213
+ }
214
+
215
+ _ , exist := configType .FieldByName (field .Name )
216
+ if ! exist {
217
+ t .Errorf ("The field '%s' does not exist in atreugo.Config" , field .Name )
218
+ }
219
+
220
+ v1 := fmt .Sprint (fasthttpServerValue .FieldByName (field .Name ).Interface ())
221
+ v2 := fmt .Sprint (configValue .FieldByName (field .Name ).Interface ())
222
+
223
+ if v1 != v2 {
224
+ t .Errorf ("fasthttp.Server.%s == %s, want %s" , field .Name , v1 , v2 )
225
+ }
226
+ }
227
+
228
+ if srv .Handler != nil {
229
+ t .Error ("fasthttp.Server.Handler must be nil" )
230
+ }
231
+
232
+ if ! isEqual (srv .Logger , testLog ) {
233
+ t .Errorf ("fasthttp.Server.Logger == %p, want %p" , srv .Logger , testLog )
234
+ }
235
+ }
236
+
237
+ func TestAtreugo_handler (t * testing.T ) { // nolint:funlen,gocognit
238
+ type args struct {
239
+ cfg Config
240
+ hosts []string
169
241
}
170
242
171
243
tests := []struct {
172
244
name string
173
245
args args
174
- want want
175
246
}{
176
247
{
177
- name : "NotCompress " ,
248
+ name : "Default " ,
178
249
args : args {
179
- compress : false ,
180
- },
181
- want : want {
182
- compress : false ,
250
+ cfg : Config {},
183
251
},
184
252
},
185
253
{
186
254
name : "Compress" ,
187
255
args : args {
188
- compress : true ,
256
+ cfg : Config { Compress : true } ,
189
257
},
190
- want : want {
191
- compress : true ,
258
+ },
259
+ {
260
+ name : "MultiHost" ,
261
+ args : args {
262
+ cfg : Config {},
263
+ hosts : []string {"localhost" , "example.com" },
264
+ },
265
+ },
266
+ {
267
+ name : "MultiHostCompress" ,
268
+ args : args {
269
+ cfg : Config {Compress : true },
270
+ hosts : []string {"localhost" , "example.com" },
192
271
},
193
272
},
194
273
}
195
274
196
- handler := func (ctx * fasthttp.RequestCtx ) {}
197
-
198
275
for _ , test := range tests {
199
276
tt := test
200
277
201
278
t .Run (tt .name , func (t * testing.T ) {
202
- cfg := Config {
203
- LogLevel : "fatal" ,
204
- Compress : tt .args .compress ,
279
+ testView := func (ctx * RequestCtx ) error {
280
+ return ctx .JSONResponse (JSON {"data" : gotils .RandBytes (make ([]byte , 300 ))})
205
281
}
206
- srv := newFasthttpServer (cfg , handler , testLog )
282
+ testPath := "/"
283
+
284
+ s := New (tt .args .cfg )
285
+ s .GET (testPath , testView )
207
286
208
- if (reflect .ValueOf (handler ).Pointer () == reflect .ValueOf (srv .Handler ).Pointer ()) == tt .want .compress {
209
- t .Error ("The handler has not been wrapped by compression handler" )
287
+ for _ , hostname := range tt .args .hosts {
288
+ vHost := s .NewVirtualHost (hostname )
289
+ vHost .GET (testPath , testView )
210
290
}
211
- })
212
- }
213
- }
214
291
215
- func TestAtreugo_ConfigFasthttpFields (t * testing.T ) {
216
- fasthttpServerType := reflect .TypeOf (fasthttp.Server {})
217
- configType := reflect .TypeOf (Config {})
292
+ handler := s .handler ()
218
293
219
- for i := 0 ; i < fasthttpServerType .NumField (); i ++ {
220
- field := fasthttpServerType .Field (i )
294
+ if handler == nil {
295
+ t .Errorf ("handler is nil" )
296
+ }
221
297
222
- if ! unicode .IsUpper (rune (field .Name [0 ])) { // Check if the field is public
223
- continue
224
- } else if gotils .StringSliceInclude (notConfigFasthttpFields , field .Name ) {
225
- continue
226
- }
298
+ newHostname := string (gotils .RandBytes (make ([]byte , 10 ))) + ".com"
227
299
228
- _ , exist := configType .FieldByName (field .Name )
229
- if ! exist {
230
- t .Errorf ("The field '%s' does not exist in atreugo.Config" , field .Name )
231
- }
300
+ hosts := tt .args .hosts
301
+ hosts = append (hosts , newHostname )
302
+
303
+ for _ , hostname := range hosts {
304
+ for _ , path := range []string {testPath , "/notfound" } {
305
+ ctx := new (fasthttp.RequestCtx )
306
+ ctx .Request .Header .Set (fasthttp .HeaderAcceptEncoding , "gzip" )
307
+ ctx .Request .Header .Set (fasthttp .HeaderHost , hostname )
308
+ ctx .Request .URI ().SetHost (hostname )
309
+ ctx .Request .SetRequestURI (path )
310
+
311
+ handler (ctx )
312
+
313
+ statusCode := ctx .Response .StatusCode ()
314
+ wantStatusCode := fasthttp .StatusOK
315
+
316
+ if path != testPath {
317
+ wantStatusCode = fasthttp .StatusNotFound
318
+ }
319
+
320
+ if statusCode != wantStatusCode {
321
+ t .Errorf ("Host %s - Path %s, Status code == %d, want %d" , hostname , path , statusCode , wantStatusCode )
322
+ }
323
+
324
+ if wantStatusCode == fasthttp .StatusNotFound {
325
+ continue
326
+ }
327
+
328
+ if tt .args .cfg .Compress && len (ctx .Response .Header .Peek (fasthttp .HeaderContentEncoding )) == 0 {
329
+ t .Errorf ("The header '%s' is not setted" , fasthttp .HeaderContentEncoding )
330
+ }
331
+ }
332
+ }
333
+ })
232
334
}
233
335
}
234
336
@@ -359,6 +461,10 @@ func TestAtreugo_Serve(t *testing.T) {
359
461
if s .cfg .Network != lnNetwork {
360
462
t .Errorf ("Atreugo.Config.Network = %s, want %s" , s .cfg .Network , lnNetwork )
361
463
}
464
+
465
+ if s .server .Handler == nil {
466
+ t .Error ("Atreugo.server.Handler is nil" )
467
+ }
362
468
}
363
469
364
470
func TestAtreugo_SetLogOutput (t * testing.T ) {
@@ -372,3 +478,70 @@ func TestAtreugo_SetLogOutput(t *testing.T) {
372
478
t .Error ("SetLogOutput() log output was not changed" )
373
479
}
374
480
}
481
+
482
+ func TestAtreugo_NewVirtualHost (t * testing.T ) {
483
+ hostname := "localhost"
484
+ s := New (testAtreugoConfig )
485
+
486
+ if s .virtualHosts != nil {
487
+ t .Error ("Atreugo.virtualHosts must be nil before register a new virtual host" )
488
+ }
489
+
490
+ vHost := s .NewVirtualHost (hostname )
491
+ if vHost == nil {
492
+ t .Fatal ("Atreugo.NewVirtualHost() returned a nil router" )
493
+ }
494
+
495
+ if ! isEqual (vHost .router .NotFound , s .router .NotFound ) {
496
+ t .Errorf ("VirtualHost router.NotFound == %p, want %p" , vHost .router .NotFound , s .router .NotFound )
497
+ }
498
+
499
+ if ! isEqual (vHost .router .MethodNotAllowed , s .router .MethodNotAllowed ) {
500
+ t .Errorf (
501
+ "VirtualHost router.MethodNotAllowed == %p, want %p" ,
502
+ vHost .router .MethodNotAllowed ,
503
+ s .router .MethodNotAllowed ,
504
+ )
505
+ }
506
+
507
+ if ! isEqual (vHost .router .PanicHandler , s .router .PanicHandler ) {
508
+ t .Errorf ("VirtualHost router.PanicHandler == %p, want %p" , vHost .router .PanicHandler , s .router .PanicHandler )
509
+ }
510
+
511
+ if h := s .virtualHosts [hostname ]; h == nil {
512
+ t .Error ("The new virtual host is not registeded" )
513
+ }
514
+
515
+ defer func () {
516
+ err := recover ()
517
+ if err == nil {
518
+ t .Error ("Expected panic when a virtual host is duplicated" )
519
+ }
520
+
521
+ wantErrString := fmt .Sprintf ("a router is already registered for virtual host '%s'" , hostname )
522
+ if err != wantErrString {
523
+ t .Errorf ("Error string == %s, want %s" , err , wantErrString )
524
+ }
525
+ }()
526
+
527
+ // panic when a virtual host is duplicated
528
+ s .NewVirtualHost (hostname )
529
+ }
530
+
531
+ // Benchmarks.
532
+ func Benchmark_Handler (b * testing.B ) {
533
+ s := New (testAtreugoConfig )
534
+ s .GET ("/" , func (ctx * RequestCtx ) error { return nil })
535
+
536
+ ctx := new (fasthttp.RequestCtx )
537
+ ctx .Request .Header .SetMethod ("GET" )
538
+ ctx .Request .SetRequestURI ("/" )
539
+
540
+ handler := s .handler ()
541
+
542
+ b .ResetTimer ()
543
+
544
+ for i := 0 ; i <= b .N ; i ++ {
545
+ handler (ctx )
546
+ }
547
+ }
0 commit comments