cmd_test.TestScanCommand   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 86
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 54
nop 1
dl 0
loc 86
rs 7.5721
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
package cmd_test
2
3
import (
4
	"io/ioutil"
5
	"net"
6
	"net/http"
7
	"net/http/httptest"
8
	"os"
9
	"sync"
10
	"syscall"
11
	"testing"
12
	"time"
13
14
	"github.com/armon/go-socks5"
15
	"github.com/stefanoj3/dirstalk/pkg/common/test"
16
	"github.com/stretchr/testify/assert"
17
)
18
19
const socks5TestServerHost = "127.0.0.1:8899"
20
21
func TestScanCommand(t *testing.T) {
22
	logger, loggerBuffer := test.NewLogger()
23
24
	c := createCommand(logger)
25
	assert.NotNil(t, c)
26
27
	testServer, serverAssertion := test.NewServerWithAssertion(
28
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29
			if r.URL.Path == "/test/" {
30
				w.WriteHeader(http.StatusOK)
31
32
				return
33
			}
34
			if r.URL.Path == "/potato" {
35
				w.WriteHeader(http.StatusOK)
36
37
				return
38
			}
39
40
			if r.URL.Path == "/test/test/" {
41
				http.Redirect(w, r, "/potato", http.StatusMovedPermanently)
42
43
				return
44
			}
45
46
			w.WriteHeader(http.StatusNotFound)
47
		}),
48
	)
49
	defer testServer.Close()
50
51
	err := executeCommand(
52
		c,
53
		"scan",
54
		testServer.URL,
55
		"--dictionary",
56
		"testdata/dict2.txt",
57
		"-v",
58
		"--http-statuses-to-ignore",
59
		"404",
60
		"--http-timeout",
61
		"300",
62
	)
63
	assert.NoError(t, err)
64
65
	assert.Equal(t, 17, serverAssertion.Len())
66
67
	requestsMap := map[string]string{}
68
69
	serverAssertion.Range(func(_ int, r http.Request) {
70
		requestsMap[r.URL.Path] = r.Method
71
	})
72
73
	expectedRequests := map[string]string{
74
		"/test/":               http.MethodGet,
75
		"/test/home":           http.MethodGet,
76
		"/test/blabla":         http.MethodGet,
77
		"/test/home/index.php": http.MethodGet,
78
		"/potato":              http.MethodGet,
79
80
		"/potato/test/":          http.MethodGet,
81
		"/potato/home":           http.MethodGet,
82
		"/potato/home/index.php": http.MethodGet,
83
		"/potato/blabla":         http.MethodGet,
84
85
		"/test/test/test/":          http.MethodGet,
86
		"/test/test/home":           http.MethodGet,
87
		"/test/test/home/index.php": http.MethodGet,
88
		"/test/test/blabla":         http.MethodGet,
89
90
		"/test/test/": http.MethodGet,
91
92
		"/home":           http.MethodGet,
93
		"/blabla":         http.MethodGet,
94
		"/home/index.php": http.MethodGet,
95
	}
96
97
	assert.Equal(t, expectedRequests, requestsMap)
98
99
	expectedResultTree := `/
100
├── potato
101
└── test
102
    └── test
103
104
`
105
106
	assert.Contains(t, loggerBuffer.String(), expectedResultTree)
107
}
108
109
func TestScanShouldWriteOutput(t *testing.T) {
110
	logger, _ := test.NewLogger()
111
112
	c := createCommand(logger)
113
	assert.NotNil(t, c)
114
115
	testServer, _ := test.NewServerWithAssertion(
116
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
117
			if r.URL.Path == "/home" {
118
				w.WriteHeader(http.StatusOK)
119
120
				return
121
			}
122
123
			w.WriteHeader(http.StatusNotFound)
124
		}),
125
	)
126
	defer testServer.Close()
127
128
	outputFilename := test.RandStringRunes(10)
129
	outputFilename = "testdata/out/" + outputFilename + ".txt"
130
131
	defer func() {
132
		err := os.Remove(outputFilename)
133
		if err != nil {
134
			panic("failed to remove file create during test: " + err.Error())
135
		}
136
	}()
137
138
	err := executeCommand(
139
		c,
140
		"scan",
141
		testServer.URL,
142
		"--dictionary",
143
		"testdata/dict2.txt",
144
		"--out",
145
		outputFilename,
146
	)
147
	assert.NoError(t, err)
148
149
	//nolint:gosec
150
	file, err := os.Open(outputFilename)
151
	assert.NoError(t, err)
152
153
	b, err := ioutil.ReadAll(file)
154
	assert.NoError(t, err, "failed to read file content")
155
156
	assert.Contains(t, string(b), testServer.Listener.Addr().String())
157
158
	assert.NoError(t, file.Close(), "failed to close file")
159
}
160
161
func TestScanInvalidOutputFileShouldErr(t *testing.T) {
162
	logger, _ := test.NewLogger()
163
164
	c := createCommand(logger)
165
	assert.NotNil(t, c)
166
167
	testServer, _ := test.NewServerWithAssertion(
168
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
169
			if r.URL.Path == "/home" {
170
				w.WriteHeader(http.StatusOK)
171
172
				return
173
			}
174
175
			w.WriteHeader(http.StatusNotFound)
176
		}),
177
	)
178
	defer testServer.Close()
179
180
	err := executeCommand(
181
		c,
182
		"scan",
183
		testServer.URL,
184
		"--dictionary",
185
		"testdata/dict2.txt",
186
		"--out",
187
		"/root/blabla/123/gibberish/123",
188
	)
189
	assert.Error(t, err)
190
	assert.Contains(t, err.Error(), "failed to create output saver")
191
}
192
193
func TestScanWithInvalidStatusesToIgnoreShouldErr(t *testing.T) {
194
	logger, _ := test.NewLogger()
195
196
	c := createCommand(logger)
197
	assert.NotNil(t, c)
198
199
	testServer, serverAssertion := test.NewServerWithAssertion(
200
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
201
	)
202
	defer testServer.Close()
203
204
	err := executeCommand(
205
		c,
206
		"scan",
207
		testServer.URL,
208
		"--dictionary",
209
		"testdata/dict2.txt",
210
		"-v",
211
		"--http-statuses-to-ignore",
212
		"300,gibberish,404",
213
		"--http-timeout",
214
		"300",
215
	)
216
	assert.Error(t, err)
217
	assert.Contains(t, err.Error(), "strconv.Atoi: parsing")
218
	assert.Contains(t, err.Error(), "gibberish")
219
220
	assert.Equal(t, 0, serverAssertion.Len())
221
}
222
223
func TestScanWithNoTargetShouldErr(t *testing.T) {
224
	logger, _ := test.NewLogger()
225
226
	c := createCommand(logger)
227
	assert.NotNil(t, c)
228
229
	err := executeCommand(c, "scan", "--dictionary", "testdata/dict2.txt")
230
	assert.Error(t, err)
231
	assert.Contains(t, err.Error(), "no URL provided")
232
}
233
234
func TestScanWithInvalidTargetShouldErr(t *testing.T) {
235
	logger, _ := test.NewLogger()
236
237
	c := createCommand(logger)
238
	assert.NotNil(t, c)
239
240
	err := executeCommand(c, "scan", "--dictionary", "testdata/dict2.txt", "localhost%%2")
241
	assert.Error(t, err)
242
	assert.Contains(t, err.Error(), "invalid URI")
243
}
244
245
func TestScanCommandCanBeInterrupted(t *testing.T) {
246
	logger, loggerBuffer := test.NewLogger()
247
248
	c := createCommand(logger)
249
	assert.NotNil(t, c)
250
251
	testServer, _ := test.NewServerWithAssertion(
252
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
253
			time.Sleep(time.Millisecond * 650)
254
255
			if r.URL.Path == "/test/" {
256
				w.WriteHeader(http.StatusOK)
257
258
				return
259
			}
260
261
			w.WriteHeader(http.StatusNotFound)
262
		}),
263
	)
264
	defer testServer.Close()
265
266
	go func() {
267
		time.Sleep(time.Millisecond * 200)
268
269
		_ = syscall.Kill(syscall.Getpid(), syscall.SIGINT) //nolint:errcheck
270
	}()
271
272
	err := executeCommand(
273
		c,
274
		"scan",
275
		testServer.URL,
276
		"--dictionary",
277
		"testdata/dict2.txt",
278
		"-v",
279
		"--http-timeout",
280
		"900",
281
	)
282
	assert.NoError(t, err)
283
284
	assert.Contains(t, loggerBuffer.String(), "Received sigint")
285
}
286
287
func TestScanWithRemoteDictionary(t *testing.T) {
288
	logger, _ := test.NewLogger()
289
290
	c := createCommand(logger)
291
	assert.NotNil(t, c)
292
293
	dictionaryServer := httptest.NewServer(
294
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
295
			dict := `home
296
home/index.php
297
blabla
298
`
299
			w.WriteHeader(http.StatusOK)
300
			_, _ = w.Write([]byte(dict)) //nolint:errcheck
301
		}),
302
	)
303
	defer dictionaryServer.Close()
304
305
	testServer, serverAssertion := test.NewServerWithAssertion(
306
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
307
			w.WriteHeader(http.StatusNotFound)
308
		}),
309
	)
310
	defer testServer.Close()
311
312
	err := executeCommand(
313
		c,
314
		"scan",
315
		testServer.URL,
316
		"--dictionary",
317
		dictionaryServer.URL,
318
		"--http-timeout",
319
		"300",
320
	)
321
	assert.NoError(t, err)
322
323
	assert.Equal(t, 3, serverAssertion.Len())
324
}
325
326
func TestScanWithUserAgentFlag(t *testing.T) {
327
	const testUserAgent = "my_test_user_agent"
328
329
	logger, loggerBuffer := test.NewLogger()
330
331
	c := createCommand(logger)
332
	assert.NotNil(t, c)
333
334
	testServer, serverAssertion := test.NewServerWithAssertion(
335
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
336
			w.WriteHeader(http.StatusNotFound)
337
		}),
338
	)
339
	defer testServer.Close()
340
341
	err := executeCommand(
342
		c,
343
		"scan",
344
		testServer.URL,
345
		"--user-agent",
346
		testUserAgent,
347
		"--dictionary",
348
		"testdata/dict.txt",
349
		"--http-timeout",
350
		"300",
351
	)
352
	assert.NoError(t, err)
353
354
	assert.Equal(t, 3, serverAssertion.Len())
355
	serverAssertion.Range(func(_ int, r http.Request) {
356
		assert.Equal(t, testUserAgent, r.Header.Get("User-Agent"))
357
	})
358
359
	// to ensure we print the user agent to the cli
360
	assert.Contains(t, loggerBuffer.String(), testUserAgent)
361
}
362
363
func TestScanWithCookies(t *testing.T) {
364
	logger, loggerBuffer := test.NewLogger()
365
366
	c := createCommand(logger)
367
	assert.NotNil(t, c)
368
369
	testServer, serverAssertion := test.NewServerWithAssertion(
370
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
371
	)
372
	defer testServer.Close()
373
374
	err := executeCommand(
375
		c,
376
		"scan",
377
		testServer.URL,
378
		"--cookie",
379
		"name1=val1",
380
		"--cookie",
381
		"name2=val2",
382
		"--dictionary",
383
		"testdata/dict.txt",
384
		"--http-timeout",
385
		"300",
386
	)
387
	assert.NoError(t, err)
388
389
	serverAssertion.Range(func(_ int, r http.Request) {
390
		assert.Equal(t, 2, len(r.Cookies()))
391
392
		assert.Equal(t, r.Cookies()[0].Name, "name1")
393
		assert.Equal(t, r.Cookies()[0].Value, "val1")
394
395
		assert.Equal(t, r.Cookies()[1].Name, "name2")
396
		assert.Equal(t, r.Cookies()[1].Value, "val2")
397
	})
398
399
	// to ensure we print the cookies to the cli
400
	assert.Contains(t, loggerBuffer.String(), "name1=val1")
401
	assert.Contains(t, loggerBuffer.String(), "name2=val2")
402
}
403
404
func TestWhenProvidingCookiesInWrongFormatShouldErr(t *testing.T) {
405
	const malformedCookie = "gibberish"
406
407
	logger, _ := test.NewLogger()
408
409
	c := createCommand(logger)
410
	assert.NotNil(t, c)
411
412
	testServer, serverAssertion := test.NewServerWithAssertion(
413
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
414
			w.WriteHeader(http.StatusNotFound)
415
		}),
416
	)
417
	defer testServer.Close()
418
419
	err := executeCommand(
420
		c,
421
		"scan",
422
		testServer.URL,
423
		"--cookie",
424
		malformedCookie,
425
		"--dictionary",
426
		"testdata/dict.txt",
427
	)
428
	assert.Error(t, err)
429
	assert.Contains(t, err.Error(), "cookie format is invalid")
430
	assert.Contains(t, err.Error(), malformedCookie)
431
432
	assert.Equal(t, 0, serverAssertion.Len())
433
}
434
435
func TestScanWithCookieJar(t *testing.T) {
436
	const (
437
		serverCookieName  = "server_cookie_name"
438
		serverCookieValue = "server_cookie_value"
439
	)
440
441
	logger, _ := test.NewLogger()
442
443
	c := createCommand(logger)
444
	assert.NotNil(t, c)
445
446
	once := sync.Once{}
447
	testServer, serverAssertion := test.NewServerWithAssertion(
448
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
449
			once.Do(func() {
450
				http.SetCookie(
451
					w,
452
					&http.Cookie{
453
						Name:    serverCookieName,
454
						Value:   serverCookieValue,
455
						Expires: time.Now().AddDate(0, 1, 0),
456
					},
457
				)
458
			})
459
		}),
460
	)
461
462
	defer testServer.Close()
463
464
	err := executeCommand(
465
		c,
466
		"scan",
467
		testServer.URL,
468
		"--use-cookie-jar",
469
		"--dictionary",
470
		"testdata/dict.txt",
471
		"--http-timeout",
472
		"300",
473
		"-t",
474
		"1",
475
	)
476
	assert.NoError(t, err)
477
478
	serverAssertion.Range(func(index int, r http.Request) {
479
		if index == 0 { // first request should have no cookies
480
			assert.Equal(t, 0, len(r.Cookies()))
481
482
			return
483
		}
484
485
		assert.Equal(t, 1, len(r.Cookies()))
486
		assert.Equal(t, r.Cookies()[0].Name, serverCookieName)
487
		assert.Equal(t, r.Cookies()[0].Value, serverCookieValue)
488
	})
489
}
490
491
func TestScanWithUnknownFlagShouldErr(t *testing.T) {
492
	logger, _ := test.NewLogger()
493
494
	c := createCommand(logger)
495
	assert.NotNil(t, c)
496
497
	testServer, serverAssertion := test.NewServerWithAssertion(
498
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
499
	)
500
	defer testServer.Close()
501
502
	err := executeCommand(
503
		c,
504
		"scan",
505
		testServer.URL,
506
		"--gibberishflag",
507
		"--dictionary",
508
		"testdata/dict.txt",
509
	)
510
	assert.Error(t, err)
511
	assert.Contains(t, err.Error(), "unknown flag")
512
513
	assert.Equal(t, 0, serverAssertion.Len())
514
}
515
516
func TestScanWithHeaders(t *testing.T) {
517
	logger, loggerBuffer := test.NewLogger()
518
519
	c := createCommand(logger)
520
	assert.NotNil(t, c)
521
522
	testServer, serverAssertion := test.NewServerWithAssertion(
523
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
524
	)
525
	defer testServer.Close()
526
527
	err := executeCommand(
528
		c,
529
		"scan",
530
		testServer.URL,
531
		"--header",
532
		"Accept-Language: en-US,en;q=0.5",
533
		"--header",
534
		`"Authorization: Bearer 123"`,
535
		"--dictionary",
536
		"testdata/dict.txt",
537
		"--http-timeout",
538
		"300",
539
	)
540
	assert.NoError(t, err)
541
542
	serverAssertion.Range(func(_ int, r http.Request) {
543
		assert.Equal(t, 2, len(r.Header))
544
545
		assert.Equal(t, "en-US,en;q=0.5", r.Header.Get("Accept-Language"))
546
		assert.Equal(t, "Bearer 123", r.Header.Get("Authorization"))
547
	})
548
549
	// to ensure we print the headers to the cli
550
	assert.Contains(t, loggerBuffer.String(), "Accept-Language")
551
	assert.Contains(t, loggerBuffer.String(), "Authorization")
552
	assert.Contains(t, loggerBuffer.String(), "Bearer 123")
553
}
554
555
func TestScanWithMalformedHeaderShouldErr(t *testing.T) {
556
	const malformedHeader = "gibberish"
557
558
	logger, _ := test.NewLogger()
559
560
	c := createCommand(logger)
561
	assert.NotNil(t, c)
562
563
	testServer, serverAssertion := test.NewServerWithAssertion(
564
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
565
	)
566
	defer testServer.Close()
567
568
	err := executeCommand(
569
		c,
570
		"scan",
571
		testServer.URL,
572
		"--header",
573
		"Accept-Language: en-US,en;q=0.5",
574
		"--header",
575
		malformedHeader,
576
		"--dictionary",
577
		"testdata/dict.txt",
578
	)
579
	assert.Error(t, err)
580
	assert.Contains(t, err.Error(), malformedHeader)
581
	assert.Contains(t, err.Error(), "header is in invalid format")
582
583
	assert.Equal(t, 0, serverAssertion.Len())
584
}
585
586
func TestStartScanWithSocks5ShouldFindResultsWhenAServerIsAvailable(t *testing.T) {
587
	logger, _ := test.NewLogger()
588
589
	c := createCommand(logger)
590
	assert.NotNil(t, c)
591
592
	testServer, serverAssertion := test.NewServerWithAssertion(
593
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
594
			w.WriteHeader(http.StatusNotFound)
595
		}),
596
	)
597
	defer testServer.Close()
598
599
	socks5Server := startSocks5TestServer(t)
600
	defer socks5Server.Close() //nolint:errcheck
601
602
	err := executeCommand(
603
		c,
604
		"scan",
605
		testServer.URL,
606
		"--dictionary",
607
		"testdata/dict.txt",
608
		"-v",
609
		"--http-timeout",
610
		"300",
611
		"--socks5",
612
		socks5TestServerHost,
613
	)
614
	assert.NoError(t, err)
615
616
	assert.Equal(t, 3, serverAssertion.Len())
617
}
618
619
func TestShouldFailToScanWithAnUnreachableSocks5Server(t *testing.T) {
620
	logger, loggerBuffer := test.NewLogger()
621
622
	c := createCommand(logger)
623
	assert.NotNil(t, c)
624
625
	testServer, serverAssertion := test.NewServerWithAssertion(
626
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
627
			w.WriteHeader(http.StatusNotFound)
628
		}),
629
	)
630
	defer testServer.Close()
631
632
	socks5Server := startSocks5TestServer(t)
633
	defer socks5Server.Close() //nolint:errcheck
634
635
	err := executeCommand(
636
		c,
637
		"scan",
638
		testServer.URL,
639
		"--dictionary",
640
		"testdata/dict.txt",
641
		"-v",
642
		"--http-timeout",
643
		"300",
644
		"--socks5",
645
		"127.0.0.1:9555", // invalid
646
	)
647
	assert.NoError(t, err)
648
649
	assert.Equal(t, 0, serverAssertion.Len())
650
	assert.Contains(t, loggerBuffer.String(), "failed to perform request")
651
	assert.Contains(t, loggerBuffer.String(), "socks connect tcp")
652
	assert.Contains(t, loggerBuffer.String(), "connect: connection refused")
653
}
654
655
func TestShouldFailToStartWithAnInvalidSocks5Address(t *testing.T) {
656
	logger, _ := test.NewLogger()
657
658
	c := createCommand(logger)
659
	assert.NotNil(t, c)
660
661
	testServer, serverAssertion := test.NewServerWithAssertion(
662
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
663
			w.WriteHeader(http.StatusNotFound)
664
		}),
665
	)
666
	defer testServer.Close()
667
668
	err := executeCommand(
669
		c,
670
		"scan",
671
		testServer.URL,
672
		"--dictionary",
673
		"testdata/dict.txt",
674
		"-v",
675
		"--http-timeout",
676
		"300",
677
		"--socks5",
678
		"localhost%%2", // invalid
679
	)
680
	assert.Error(t, err)
681
	assert.Contains(t, err.Error(), "invalid URL escape")
682
683
	assert.Equal(t, 0, serverAssertion.Len())
684
}
685
686
func TestScanShouldFailToCommunicateWithServerHavingInvalidSSLCertificates(t *testing.T) {
687
	logger, loggerBuffer := test.NewLogger()
688
689
	c := createCommand(logger)
690
	assert.NotNil(t, c)
691
692
	testServer, serverAssertion := test.NewTSLServerWithAssertion(
693
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
694
			w.WriteHeader(http.StatusOK)
695
		}),
696
	)
697
	defer testServer.Close()
698
699
	err := executeCommand(
700
		c,
701
		"scan",
702
		testServer.URL,
703
		"--dictionary",
704
		"testdata/dict2.txt",
705
		"--scan-depth",
706
		"1",
707
	)
708
	assert.NoError(t, err)
709
710
	assert.Equal(t, 0, serverAssertion.Len())
711
712
	assert.Contains(t, loggerBuffer.String(), "certificate")
713
}
714
715
func TestScanShouldBeAbleToSkipSSLCertificatesCheck(t *testing.T) {
716
	logger, loggerBuffer := test.NewLogger()
717
718
	c := createCommand(logger)
719
	assert.NotNil(t, c)
720
721
	testServer, serverAssertion := test.NewTSLServerWithAssertion(
722
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
723
			w.WriteHeader(http.StatusOK)
724
		}),
725
	)
726
	defer testServer.Close()
727
728
	err := executeCommand(
729
		c,
730
		"scan",
731
		testServer.URL,
732
		"--dictionary",
733
		"testdata/dict2.txt",
734
		"--scan-depth",
735
		"1",
736
		"--no-check-certificate",
737
	)
738
	assert.NoError(t, err)
739
740
	assert.Equal(t, 16, serverAssertion.Len())
741
742
	assert.NotContains(t, loggerBuffer.String(), "certificate signed by unknown authority")
743
}
744
745
func startSocks5TestServer(t *testing.T) net.Listener {
746
	conf := &socks5.Config{}
747
748
	server, err := socks5.New(conf)
749
	if err != nil {
750
		t.Fatalf("failed to create socks5: %s", err.Error())
751
	}
752
753
	listener, err := net.Listen("tcp", socks5TestServerHost)
754
	if err != nil {
755
		t.Fatalf("failed to create listener: %s", err.Error())
756
	}
757
758
	go func() {
759
		// Create SOCKS5 proxy on localhost port 8000
760
		if err := server.Serve(listener); err != nil {
761
			t.Logf("socks5 stopped serving: %s", err.Error())
762
		}
763
	}()
764
765
	return listener
766
}
767
768
func TestScanShouldFailIfDictionaryFetchExceedTimeout(t *testing.T) {
769
	logger, _ := test.NewLogger()
770
771
	c := createCommand(logger)
772
	assert.NotNil(t, c)
773
774
	testServer, serverAssertion := test.NewServerWithAssertion(
775
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
776
		}),
777
	)
778
	defer testServer.Close()
779
780
	dictionaryTestServer, _ := test.NewServerWithAssertion(
781
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
782
			time.Sleep(time.Second)
783
			w.Write([]byte("/dictionary/entry")) //nolint
784
		}),
785
	)
786
	defer dictionaryTestServer.Close()
787
788
	err := executeCommand(
789
		c,
790
		"scan",
791
		testServer.URL,
792
		"--dictionary",
793
		dictionaryTestServer.URL,
794
		"--dictionary-get-timeout",
795
		"5",
796
	)
797
	assert.Error(t, err)
798
799
	assert.Contains(t, err.Error(), "dictionary: failed to get")
800
801
	assert.Equal(t, 0, serverAssertion.Len())
802
}
803
804
func TestScanShouldBeAbleToFetchRemoteDictionary(t *testing.T) {
805
	logger, _ := test.NewLogger()
806
807
	c := createCommand(logger)
808
	assert.NotNil(t, c)
809
810
	testServer, serverAssertion := test.NewServerWithAssertion(
811
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
812
			w.WriteHeader(http.StatusNotFound)
813
		}),
814
	)
815
	defer testServer.Close()
816
817
	dictionaryTestServer, dictionaryTestServerAssertion := test.NewServerWithAssertion(
818
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
819
			w.Write([]byte("/dictionary/entry")) //nolint
820
		}),
821
	)
822
	defer dictionaryTestServer.Close()
823
824
	err := executeCommand(
825
		c,
826
		"scan",
827
		testServer.URL,
828
		"--dictionary",
829
		dictionaryTestServer.URL,
830
		"--dictionary-get-timeout",
831
		"500",
832
	)
833
	assert.NoError(t, err)
834
835
	assert.Equal(t, 1, dictionaryTestServerAssertion.Len())
836
	assert.Equal(t, 1, serverAssertion.Len())
837
838
	serverAssertion.At(0, func(r http.Request) {
839
		assert.Equal(t, "/dictionary/entry", r.URL.Path)
840
	})
841
}
842