22
22
*/
23
23
package com .scanoss ;
24
24
25
+ import com .google .gson .Gson ;
26
+ import com .scanoss .dto .ScanFileDetails ;
27
+ import com .scanoss .dto .ScanFileResult ;
28
+ import com .scanoss .dto .ServerDetails ;
29
+ import com .scanoss .dto .enums .MatchType ;
25
30
import com .scanoss .exceptions .ScannerException ;
26
31
import com .scanoss .filters .FilterConfig ;
27
32
import com .scanoss .settings .ScanossSettings ;
28
33
import com .scanoss .utils .JsonUtils ;
34
+ import com .scanoss .utils .WinnowingUtils ;
29
35
import lombok .extern .slf4j .Slf4j ;
36
+ import okhttp3 .mockwebserver .Dispatcher ;
37
+ import okhttp3 .mockwebserver .MockResponse ;
38
+ import okhttp3 .mockwebserver .MockWebServer ;
39
+ import okhttp3 .mockwebserver .RecordedRequest ;
40
+ import org .jetbrains .annotations .NotNull ;
41
+ import org .junit .After ;
30
42
import org .junit .Before ;
31
43
import org .junit .Test ;
32
44
45
+ import java .io .File ;
33
46
import java .io .FileWriter ;
34
47
import java .io .IOException ;
35
- import java .util .ArrayList ;
36
- import java .util .Arrays ;
37
- import java .util .List ;
48
+ import java .nio .file .*;
49
+ import java .nio .file .attribute .BasicFileAttributes ;
50
+ import java .util .*;
51
+ import java .util .concurrent .*;
52
+ import java .util .stream .Collectors ;
38
53
39
54
import static org .junit .Assert .*;
40
55
41
56
@ Slf4j
42
57
public class TestScanner {
58
+ private MockWebServer server ;
59
+
60
+
43
61
@ Before
44
- public void Setup () {
62
+ public void Setup () throws IOException {
45
63
log .info ("Starting Scanner test cases..." );
46
64
log .debug ("Logging debug enabled" );
47
65
log .trace ("Logging trace enabled" );
66
+ log .info ("Starting Mock Server..." );
67
+ server = new MockWebServer ();
68
+ server .start ();
69
+ }
70
+
71
+ @ After
72
+ public void Finish () {
73
+ log .info ("Shutting down mock server." );
74
+ try {
75
+ server .close ();
76
+ server .shutdown ();
77
+ } catch (IOException e ) {
78
+ log .warn ("Some issue shutting down mock server: {}" , e .getLocalizedMessage ());
79
+ }
48
80
}
49
81
50
82
@ Test
@@ -409,4 +441,116 @@ public void TestScannerCustomFilterConfig() {
409
441
410
442
log .info ("Finished {} -->" , methodName );
411
443
}
412
- }
444
+
445
+ /**
446
+ * Test that we can scan a folder with obfuscation enabled using a mock server.
447
+ * This test focuses on the path obfuscation/deobfuscation functionality in a multi-threaded environment.
448
+ * The dispatcher supports handling multiple files in a single request.
449
+ */
450
+ @ Test
451
+ public void testConcurrentScanWithObfuscation () throws IOException {
452
+ final String folderToScan = "src/test" ;
453
+
454
+ // Set to capture all paths received by the server
455
+ final Set <String > receivedPaths = ConcurrentHashMap .newKeySet ();
456
+
457
+ // Collect all files in the src/test folder before scanning
458
+ final Set <String > allSourceFilePaths = Files .walk (Paths .get (folderToScan ))
459
+ .filter (path -> !Files .isDirectory (path ))
460
+ .map (path -> {
461
+ // Convert to relative path with forward slashes
462
+ String relativePath = Paths .get (folderToScan ).relativize (path ).toString ();
463
+ return relativePath .replace (File .separatorChar , '/' );
464
+ })
465
+ .collect (Collectors .toSet ());
466
+
467
+ log .info ("Found {} files in source directory" , allSourceFilePaths .size ());
468
+
469
+
470
+
471
+
472
+
473
+ // Configure the MockWebServer to return a 'no match' response for any request.
474
+ // This is important for testing without depending on actual scan results.
475
+ //TODO: Extend the mock webserver to other tests.
476
+ final Dispatcher dispatcher = new Dispatcher () {
477
+ @ NotNull
478
+ @ Override
479
+ public MockResponse dispatch (RecordedRequest request ) {
480
+ // Extract the WFP from the request and parse all obfuscated paths
481
+ String requestBody = request .getBody ().readUtf8 ();
482
+ Set <String > paths = WinnowingUtils .extractFilePathsFromWFPBlock (requestBody );
483
+
484
+ // Store all received paths for later verification
485
+ receivedPaths .addAll (paths );
486
+
487
+
488
+ for (String path : paths ) {
489
+ log .debug ("Server received obfuscated path: {}" , path );
490
+ }
491
+
492
+ if (paths .isEmpty ()) {
493
+ return new MockResponse ()
494
+ .setResponseCode (400 )
495
+ .setBody ("error: Bad Request - No valid obfuscated paths found" );
496
+ }
497
+
498
+ // Create response objects using the DTO classes
499
+ Map <String , List <ScanFileDetails >> responseMap = new HashMap <>();
500
+
501
+ // Create server details object (same for all responses)
502
+ ServerDetails .KbVersion kbVersion = new ServerDetails .KbVersion ("25.05" , "21.05.21" );
503
+ ServerDetails serverDetails = new ServerDetails ("5.4.10" , kbVersion );
504
+
505
+ // Create a "none" match result for each path
506
+ for (String path : paths ) {
507
+ ScanFileDetails noMatchResult = ScanFileDetails .builder ()
508
+ .matchType (MatchType .none )
509
+ .serverDetails (serverDetails )
510
+ .build ();
511
+
512
+ responseMap .put (path , Collections .singletonList (noMatchResult ));
513
+ }
514
+
515
+ // Convert to JSON
516
+ Gson gson = new Gson ();
517
+ String responseJson = gson .toJson (responseMap );
518
+
519
+ return new MockResponse ()
520
+ .setResponseCode (200 )
521
+ .setBody (responseJson );
522
+ }
523
+ };
524
+ server .setDispatcher (dispatcher );
525
+
526
+ // Create a scanner with obfuscation enabled and multiple threads
527
+ Scanner scanner = Scanner .builder ()
528
+ .obfuscate (true )
529
+ .numThreads (8 ) // Use multiple threads to process files
530
+ .url (server .url ("/api/scan/direct" ).toString ()) // Use our mock server
531
+ .build ();
532
+
533
+ // Scan the files to test the full obfuscation/deobfuscation cycle
534
+ List <String > results = scanner .scanFolder (folderToScan );
535
+
536
+
537
+ // Verify we got scan results
538
+ assertNotNull ("Should have scan results" , results );
539
+ assertFalse ("Should have result non empty" , results .isEmpty ());
540
+ log .info ("Received {} scan results" , results .size ());
541
+
542
+ // Verify paths received by the server are obfuscated (not matching any source file paths)
543
+ for (String receivedPath : receivedPaths ) {
544
+ assertFalse ("Path should be obfuscated and not match any source path: " + receivedPath ,
545
+ allSourceFilePaths .contains (receivedPath ));
546
+ }
547
+
548
+ List <ScanFileResult > resultsDto = JsonUtils .toScanFileResults (results );
549
+ // Verify (deobfuscation) that all results from scanFolder are valid file paths from our source directory
550
+ for (ScanFileResult r : resultsDto ) {
551
+ assertTrue ("Result should be a valid source file path: " + r .getFilePath (),
552
+ allSourceFilePaths .contains (r .getFilePath ()));
553
+ }
554
+
555
+ }
556
+ }
0 commit comments