diff --git a/pom.xml b/pom.xml
index fc75358..429ce0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -165,6 +165,11 @@
junit-jupiter
test
+
+ org.mockito
+ mockito-core
+ test
+
@@ -412,6 +417,26 @@
org.apache.maven.plugins
maven-pmd-plugin
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.13
+
+
+
+ prepare-agent
+
+
+
+ report
+
+ report
+
+ test
+
+
+
diff --git a/src/test/java/de/rub/nds/crawler/CommonMainTest.java b/src/test/java/de/rub/nds/crawler/CommonMainTest.java
new file mode 100644
index 0000000..4edf937
--- /dev/null
+++ b/src/test/java/de/rub/nds/crawler/CommonMainTest.java
@@ -0,0 +1,131 @@
+/*
+ * TLS-Crawler - A TLS scanning tool to perform large scale scans with the TLS-Scanner
+ *
+ * Copyright 2018-2023 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH
+ *
+ * Licensed under Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ */
+package de.rub.nds.crawler;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import de.rub.nds.crawler.config.ControllerCommandConfig;
+import de.rub.nds.crawler.config.WorkerCommandConfig;
+import de.rub.nds.crawler.core.Controller;
+import de.rub.nds.crawler.core.Worker;
+import de.rub.nds.crawler.dummy.DummyControllerCommandConfig;
+import de.rub.nds.crawler.orchestration.RabbitMqOrchestrationProvider;
+import de.rub.nds.crawler.persistence.MongoPersistenceProvider;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
+import org.mockito.Mockito;
+
+public class CommonMainTest {
+
+ @Test
+ public void testMainWithNoCommand() {
+ ControllerCommandConfig controllerConfig = new DummyControllerCommandConfig();
+ WorkerCommandConfig workerConfig = new WorkerCommandConfig();
+
+ // Test no command given - should return early without starting controller/worker
+ CommonMain.main(new String[] {}, controllerConfig, workerConfig);
+ // The test passes if no exception is thrown
+ }
+
+ @Test
+ public void testMainWithInvalidCommand() {
+ ControllerCommandConfig controllerConfig = new DummyControllerCommandConfig();
+ WorkerCommandConfig workerConfig = new WorkerCommandConfig();
+
+ // Test invalid command - should return early without starting controller/worker
+ CommonMain.main(new String[] {"invalid"}, controllerConfig, workerConfig);
+ // The test passes if no exception is thrown
+ }
+
+ @Test
+ public void testMainWithControllerCommand() {
+ ControllerCommandConfig controllerConfig = new DummyControllerCommandConfig();
+ controllerConfig.setHostFile("src/test/resources/targets.txt");
+
+ WorkerCommandConfig workerConfig = new WorkerCommandConfig();
+
+ try (MockedConstruction controllerMock =
+ Mockito.mockConstruction(
+ Controller.class,
+ (mock, context) -> {
+ Mockito.doNothing().when(mock).start();
+ });
+ MockedConstruction rabbitMock =
+ Mockito.mockConstruction(RabbitMqOrchestrationProvider.class);
+ MockedConstruction mongoMock =
+ Mockito.mockConstruction(MongoPersistenceProvider.class)) {
+
+ CommonMain.main(new String[] {"controller"}, controllerConfig, workerConfig);
+
+ assertEquals(1, controllerMock.constructed().size());
+ Controller controller = controllerMock.constructed().get(0);
+ Mockito.verify(controller).start();
+ }
+ }
+
+ @Test
+ public void testMainWithWorkerCommand() {
+ ControllerCommandConfig controllerConfig = new DummyControllerCommandConfig();
+ WorkerCommandConfig workerConfig = new WorkerCommandConfig();
+
+ try (MockedConstruction workerMock =
+ Mockito.mockConstruction(
+ Worker.class,
+ (mock, context) -> {
+ Mockito.doNothing().when(mock).start();
+ });
+ MockedConstruction rabbitMock =
+ Mockito.mockConstruction(RabbitMqOrchestrationProvider.class);
+ MockedConstruction mongoMock =
+ Mockito.mockConstruction(MongoPersistenceProvider.class)) {
+
+ CommonMain.main(new String[] {"worker"}, controllerConfig, workerConfig);
+
+ assertEquals(1, workerMock.constructed().size());
+ Worker worker = workerMock.constructed().get(0);
+ Mockito.verify(worker).start();
+ }
+ }
+
+ @Test
+ public void testMainWithSingleConfigParam() {
+ ControllerCommandConfig controllerConfig = new DummyControllerCommandConfig();
+
+ // Test the overloaded method
+ CommonMain.main(new String[] {}, controllerConfig);
+ // The test passes if no exception is thrown
+ }
+
+ @Test
+ public void testMainDefaultCase() {
+ ControllerCommandConfig controllerConfig = new DummyControllerCommandConfig();
+ WorkerCommandConfig workerConfig = new WorkerCommandConfig();
+
+ // Test an unrecognized command - should call usage()
+ CommonMain.main(new String[] {"unknown"}, controllerConfig, workerConfig);
+ // The test passes if no exception is thrown
+ }
+
+ @Test
+ public void testConstructor() {
+ // Test that the constructor can be instantiated
+ // This is mainly for coverage purposes
+ CommonMain commonMain = new CommonMain();
+ assertNotNull(commonMain);
+ }
+
+ @Test
+ public void testMainWithUnknownButValidCommand() {
+ // Since we can't easily create a command that JCommander accepts
+ // but isn't handled by the switch statement, we'll have to accept
+ // that the default case is unreachable in normal circumstances.
+ // This is a limitation of the current implementation.
+ assertTrue(true);
+ }
+}
diff --git a/src/test/java/de/rub/nds/crawler/data/ScanResultTest.java b/src/test/java/de/rub/nds/crawler/data/ScanResultTest.java
new file mode 100644
index 0000000..78c4b5f
--- /dev/null
+++ b/src/test/java/de/rub/nds/crawler/data/ScanResultTest.java
@@ -0,0 +1,235 @@
+/*
+ * TLS-Crawler - A TLS scanning tool to perform large scale scans with the TLS-Scanner
+ *
+ * Copyright 2018-2022 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH
+ *
+ * Licensed under Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ */
+package de.rub.nds.crawler.data;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import de.rub.nds.crawler.constant.JobStatus;
+import org.bson.Document;
+import org.junit.jupiter.api.Test;
+
+public class ScanResultTest {
+
+ private BulkScan createTestBulkScan(String id, String name) {
+ BulkScan bulkScan =
+ new BulkScan(
+ getClass(), // scannerClass
+ getClass(), // crawlerClass
+ name,
+ null, // scanConfig
+ System.currentTimeMillis(),
+ false, // monitored
+ null // notifyUrl
+ );
+ bulkScan.set_id(id);
+ return bulkScan;
+ }
+
+ @Test
+ public void testConstructorWithScanJobDescription() {
+ // Prepare test data
+ BulkScan bulkScan = createTestBulkScan("bulk-scan-123", "test-scan");
+
+ ScanTarget scanTarget = new ScanTarget();
+ scanTarget.setHostname("example.com");
+ scanTarget.setIp("192.168.1.1");
+
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.SUCCESS);
+
+ Document resultDocument = new Document();
+ resultDocument.put("test", "value");
+
+ // Create ScanResult
+ ScanResult scanResult = new ScanResult(jobDescription, resultDocument);
+
+ // Verify properties
+ assertNotNull(scanResult.getId());
+ assertEquals("bulk-scan-123", scanResult.getBulkScan());
+ assertEquals(scanTarget, scanResult.getScanTarget());
+ assertEquals(JobStatus.SUCCESS, scanResult.getResultStatus());
+ assertEquals(resultDocument, scanResult.getResult());
+ }
+
+ @Test
+ public void testConstructorWithScanJobDescriptionInvalidStatus() {
+ // Prepare test data with TO_BE_EXECUTED status
+ BulkScan bulkScan = createTestBulkScan("bulk-scan-123", "test-scan");
+
+ ScanTarget scanTarget = new ScanTarget();
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.TO_BE_EXECUTED);
+
+ Document resultDocument = new Document();
+
+ // Should throw exception for TO_BE_EXECUTED status
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> {
+ new ScanResult(jobDescription, resultDocument);
+ },
+ "ScanJobDescription must not be in TO_BE_EXECUTED state");
+ }
+
+ @Test
+ public void testFromExceptionWithErrorStatus() {
+ // Prepare test data
+ BulkScan bulkScan = createTestBulkScan("bulk-scan-456", "error-scan");
+
+ ScanTarget scanTarget = new ScanTarget();
+ scanTarget.setHostname("error.com");
+
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.ERROR);
+
+ Exception testException = new RuntimeException("Test error");
+
+ // Create ScanResult from exception
+ ScanResult scanResult = ScanResult.fromException(jobDescription, testException);
+
+ // Verify properties
+ assertNotNull(scanResult.getId());
+ assertEquals("bulk-scan-456", scanResult.getBulkScan());
+ assertEquals(scanTarget, scanResult.getScanTarget());
+ assertEquals(JobStatus.ERROR, scanResult.getResultStatus());
+ assertNotNull(scanResult.getResult());
+ assertEquals(testException, scanResult.getResult().get("exception"));
+ }
+
+ @Test
+ public void testFromExceptionWithCancelledStatus() {
+ // Prepare test data with CANCELLED status (which is also an error status)
+ BulkScan bulkScan = createTestBulkScan("bulk-scan-789", "cancelled-scan");
+
+ ScanTarget scanTarget = new ScanTarget();
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.CANCELLED);
+
+ Exception timeoutException = new RuntimeException("Timeout occurred");
+
+ // Create ScanResult from exception
+ ScanResult scanResult = ScanResult.fromException(jobDescription, timeoutException);
+
+ // Verify properties
+ assertNotNull(scanResult);
+ assertEquals("bulk-scan-789", scanResult.getBulkScan());
+ assertEquals(JobStatus.CANCELLED, scanResult.getResultStatus());
+ assertEquals(timeoutException, scanResult.getResult().get("exception"));
+ }
+
+ @Test
+ public void testFromExceptionWithNonErrorStatus() {
+ // Prepare test data with non-error status
+ BulkScan bulkScan = createTestBulkScan("bulk-scan-999", "success-scan");
+ ScanTarget scanTarget = new ScanTarget();
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.SUCCESS);
+
+ Exception testException = new RuntimeException("Test");
+
+ // Should throw exception for non-error status
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> {
+ ScanResult.fromException(jobDescription, testException);
+ },
+ "ScanJobDescription must be in an error state");
+ }
+
+ @Test
+ public void testIdGetterAndSetter() {
+ // Create ScanResult
+ BulkScan bulkScan = createTestBulkScan("bulk-scan", "id-test-scan");
+
+ ScanTarget scanTarget = new ScanTarget();
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.SUCCESS);
+
+ ScanResult scanResult = new ScanResult(jobDescription, new Document());
+
+ // Test default ID
+ String originalId = scanResult.getId();
+ assertNotNull(originalId);
+ assertTrue(originalId.length() > 0);
+
+ // Test setter
+ String newId = "custom-id-123";
+ scanResult.setId(newId);
+ assertEquals(newId, scanResult.getId());
+ }
+
+ @Test
+ public void testAllGetters() {
+ // Prepare test data
+ BulkScan bulkScan = createTestBulkScan("test-bulk-scan", "getter-test-scan");
+
+ ScanTarget scanTarget = new ScanTarget();
+ scanTarget.setHostname("test.com");
+ scanTarget.setPort(443);
+
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.SUCCESS);
+
+ Document resultDoc = new Document();
+ resultDoc.put("key", "value");
+
+ ScanResult scanResult = new ScanResult(jobDescription, resultDoc);
+
+ // Test all getters
+ assertNotNull(scanResult.getId());
+ assertEquals("test-bulk-scan", scanResult.getBulkScan());
+ assertEquals(scanTarget, scanResult.getScanTarget());
+ assertEquals("test.com", scanResult.getScanTarget().getHostname());
+ assertEquals(443, scanResult.getScanTarget().getPort());
+ assertEquals(JobStatus.SUCCESS, scanResult.getResultStatus());
+ assertEquals(resultDoc, scanResult.getResult());
+ assertEquals("value", scanResult.getResult().get("key"));
+ }
+
+ @Test
+ public void testWithEmptyStatus() {
+ // Test with EMPTY status which is not an error
+ BulkScan bulkScan = createTestBulkScan("empty-scan", "empty-scan");
+ ScanTarget scanTarget = new ScanTarget();
+ ScanJobDescription jobDescription =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.EMPTY);
+
+ Document emptyResult = new Document();
+ ScanResult scanResult = new ScanResult(jobDescription, emptyResult);
+
+ assertEquals(JobStatus.EMPTY, scanResult.getResultStatus());
+ assertNotNull(scanResult.getId());
+ }
+
+ @Test
+ public void testWithVariousErrorStatuses() {
+ // Test with different error statuses
+ BulkScan bulkScan = createTestBulkScan("error-scan", "error-scan");
+ ScanTarget scanTarget = new ScanTarget();
+ Exception ex = new RuntimeException("Test");
+
+ // Test RESOLUTION_ERROR
+ ScanJobDescription jobDesc1 =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.RESOLUTION_ERROR);
+ ScanResult result1 = ScanResult.fromException(jobDesc1, ex);
+ assertEquals(JobStatus.RESOLUTION_ERROR, result1.getResultStatus());
+
+ // Test CRAWLER_ERROR
+ ScanJobDescription jobDesc2 =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.CRAWLER_ERROR);
+ ScanResult result2 = ScanResult.fromException(jobDesc2, ex);
+ assertEquals(JobStatus.CRAWLER_ERROR, result2.getResultStatus());
+
+ // Test INTERNAL_ERROR
+ ScanJobDescription jobDesc3 =
+ new ScanJobDescription(scanTarget, bulkScan, JobStatus.INTERNAL_ERROR);
+ ScanResult result3 = ScanResult.fromException(jobDesc3, ex);
+ assertEquals(JobStatus.INTERNAL_ERROR, result3.getResultStatus());
+ }
+}
diff --git a/src/test/java/de/rub/nds/crawler/denylist/DenylistFileProviderTest.java b/src/test/java/de/rub/nds/crawler/denylist/DenylistFileProviderTest.java
new file mode 100644
index 0000000..5a31dcf
--- /dev/null
+++ b/src/test/java/de/rub/nds/crawler/denylist/DenylistFileProviderTest.java
@@ -0,0 +1,221 @@
+/*
+ * TLS-Crawler - A TLS scanning tool to perform large scale scans with the TLS-Scanner
+ *
+ * Copyright 2018-2023 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH
+ *
+ * Licensed under Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ */
+package de.rub.nds.crawler.denylist;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import de.rub.nds.crawler.data.ScanTarget;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class DenylistFileProviderTest {
+
+ private Path tempDenylistFile;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ tempDenylistFile = Files.createTempFile("denylist", ".txt");
+ }
+
+ @AfterEach
+ public void tearDown() throws IOException {
+ Files.deleteIfExists(tempDenylistFile);
+ }
+
+ @Test
+ public void testEmptyDenylist() throws IOException {
+ Files.write(tempDenylistFile, Arrays.asList());
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ ScanTarget target = new ScanTarget();
+ target.setHostname("example.com");
+ target.setIp("192.168.1.1");
+
+ assertFalse(provider.isDenylisted(target));
+ }
+
+ @Test
+ public void testDomainDenylist() throws IOException {
+ Files.write(tempDenylistFile, Arrays.asList("badsite.com", "malicious.org"));
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ ScanTarget denylisted = new ScanTarget();
+ denylisted.setHostname("badsite.com");
+ denylisted.setIp("10.0.0.1");
+ assertTrue(provider.isDenylisted(denylisted));
+
+ ScanTarget allowed = new ScanTarget();
+ allowed.setHostname("goodsite.com");
+ allowed.setIp("10.0.0.2");
+ assertFalse(provider.isDenylisted(allowed));
+ }
+
+ @Test
+ public void testIpDenylist() throws IOException {
+ Files.write(tempDenylistFile, Arrays.asList("192.168.1.1", "10.0.0.1"));
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ ScanTarget denylisted = new ScanTarget();
+ denylisted.setHostname("anysite.com");
+ denylisted.setIp("192.168.1.1");
+ assertTrue(provider.isDenylisted(denylisted));
+
+ ScanTarget allowed = new ScanTarget();
+ allowed.setHostname("anothersite.com");
+ allowed.setIp("192.168.1.2");
+ assertFalse(provider.isDenylisted(allowed));
+ }
+
+ @Test
+ public void testSubnetDenylist() throws IOException {
+ Files.write(tempDenylistFile, Arrays.asList("192.168.1.0/24", "10.0.0.0/16"));
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ ScanTarget denylisted1 = new ScanTarget();
+ denylisted1.setHostname("host1.com");
+ denylisted1.setIp("192.168.1.100");
+ assertTrue(provider.isDenylisted(denylisted1));
+
+ ScanTarget denylisted2 = new ScanTarget();
+ denylisted2.setHostname("host2.com");
+ denylisted2.setIp("10.0.50.1");
+ assertTrue(provider.isDenylisted(denylisted2));
+
+ ScanTarget allowed = new ScanTarget();
+ allowed.setHostname("host3.com");
+ allowed.setIp("172.16.0.1");
+ assertFalse(provider.isDenylisted(allowed));
+ }
+
+ @Test
+ public void testMixedDenylist() throws IOException {
+ Files.write(
+ tempDenylistFile,
+ Arrays.asList("badsite.com", "192.168.1.1", "10.0.0.0/8", "evil.org"));
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ // Test domain denylist
+ ScanTarget domainTarget = new ScanTarget();
+ domainTarget.setHostname("badsite.com");
+ domainTarget.setIp("1.2.3.4");
+ assertTrue(provider.isDenylisted(domainTarget));
+
+ // Test IP denylist
+ ScanTarget ipTarget = new ScanTarget();
+ ipTarget.setHostname("somesite.com");
+ ipTarget.setIp("192.168.1.1");
+ assertTrue(provider.isDenylisted(ipTarget));
+
+ // Test subnet denylist
+ ScanTarget subnetTarget = new ScanTarget();
+ subnetTarget.setHostname("anothersite.com");
+ subnetTarget.setIp("10.5.5.5");
+ assertTrue(provider.isDenylisted(subnetTarget));
+ }
+
+ @Test
+ public void testInvalidEntries() throws IOException {
+ Files.write(
+ tempDenylistFile,
+ Arrays.asList(
+ "validsite.com",
+ "invalid-entry-no-validation",
+ "192.168.1.1",
+ "invalid/subnet",
+ "192.168.1.0/24"));
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ // Valid entries should still work
+ ScanTarget validTarget = new ScanTarget();
+ validTarget.setHostname("validsite.com");
+ validTarget.setIp("1.1.1.1");
+ assertTrue(provider.isDenylisted(validTarget));
+
+ // Invalid entries should be ignored
+ ScanTarget testTarget = new ScanTarget();
+ testTarget.setHostname("invalid-entry-no-validation");
+ testTarget.setIp("192.168.2.1");
+ assertFalse(provider.isDenylisted(testTarget));
+ }
+
+ @Test
+ public void testNonExistentFile() {
+ String nonExistentFile = "/tmp/nonexistent_denylist_file_" + System.currentTimeMillis();
+ DenylistFileProvider provider = new DenylistFileProvider(nonExistentFile);
+
+ ScanTarget target = new ScanTarget();
+ target.setHostname("example.com");
+ target.setIp("192.168.1.1");
+
+ // Should not crash and should return false
+ assertFalse(provider.isDenylisted(target));
+ }
+
+ @Test
+ public void testIpv6SubnetHandling() throws IOException {
+ Files.write(tempDenylistFile, Arrays.asList("192.168.1.0/24"));
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ // Test IPv6 address against IPv4 subnet (should not match)
+ ScanTarget ipv6Target = new ScanTarget();
+ ipv6Target.setHostname("ipv6site.com");
+ ipv6Target.setIp("2001:db8::1");
+ assertFalse(provider.isDenylisted(ipv6Target));
+ }
+
+ @Test
+ public void testConcurrentAccess() throws IOException, InterruptedException {
+ Files.write(tempDenylistFile, Arrays.asList("badsite.com", "192.168.1.0/24"));
+
+ DenylistFileProvider provider = new DenylistFileProvider(tempDenylistFile.toString());
+
+ // Test thread safety of isDenylisted
+ Thread t1 =
+ new Thread(
+ () -> {
+ for (int i = 0; i < 100; i++) {
+ ScanTarget target = new ScanTarget();
+ target.setHostname("test" + i + ".com");
+ target.setIp("192.168.1." + i);
+ provider.isDenylisted(target);
+ }
+ });
+
+ Thread t2 =
+ new Thread(
+ () -> {
+ for (int i = 0; i < 100; i++) {
+ ScanTarget target = new ScanTarget();
+ target.setHostname("badsite.com");
+ target.setIp("10.0.0." + i);
+ provider.isDenylisted(target);
+ }
+ });
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ // If we reach here without exceptions, the concurrent access worked fine
+ assertTrue(true);
+ }
+}
diff --git a/src/test/java/de/rub/nds/crawler/targetlist/CruxListProviderTest.java b/src/test/java/de/rub/nds/crawler/targetlist/CruxListProviderTest.java
new file mode 100644
index 0000000..16147db
--- /dev/null
+++ b/src/test/java/de/rub/nds/crawler/targetlist/CruxListProviderTest.java
@@ -0,0 +1,124 @@
+/*
+ * TLS-Crawler - A TLS scanning tool to perform large scale scans with the TLS-Scanner
+ *
+ * Copyright 2018-2023 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH
+ *
+ * Licensed under Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ */
+package de.rub.nds.crawler.targetlist;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import de.rub.nds.crawler.constant.CruxListNumber;
+import java.util.List;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+
+public class CruxListProviderTest {
+
+ @Test
+ public void testConstructor() {
+ CruxListProvider provider = new CruxListProvider(CruxListNumber.TOP_1k);
+ assertNotNull(provider);
+ }
+
+ @Test
+ public void testGetTargetListFromLines() {
+ CruxListProvider provider = new CruxListProvider(CruxListNumber.TOP_1k);
+
+ // Test with valid HTTPS entries
+ Stream lines =
+ Stream.of(
+ "https://example.com,1",
+ "https://test.com,2",
+ "http://insecure.com,3",
+ "https://third.com,3",
+ "https://outofrange.com,1001");
+
+ List result = provider.getTargetListFromLines(lines);
+
+ assertEquals(3, result.size());
+ assertTrue(result.contains("example.com"));
+ assertTrue(result.contains("test.com"));
+ assertTrue(result.contains("third.com"));
+ assertFalse(result.contains("insecure.com")); // HTTP should be filtered out
+ assertFalse(result.contains("outofrange.com")); // Above rank 1000
+ }
+
+ @Test
+ public void testGetTargetListFromLinesWithTop5K() {
+ CruxListProvider provider = new CruxListProvider(CruxListNumber.TOP_5K);
+
+ Stream lines =
+ Stream.of(
+ "https://example.com,1",
+ "https://test.com,4999",
+ "https://borderline.com,5000",
+ "https://outofrange.com,5001");
+
+ List result = provider.getTargetListFromLines(lines);
+
+ assertEquals(3, result.size());
+ assertTrue(result.contains("example.com"));
+ assertTrue(result.contains("test.com"));
+ assertTrue(result.contains("borderline.com"));
+ assertFalse(result.contains("outofrange.com"));
+ }
+
+ @Test
+ public void testGetTargetListFromLinesEmptyStream() {
+ CruxListProvider provider = new CruxListProvider(CruxListNumber.TOP_1k);
+ Stream lines = Stream.empty();
+
+ List result = provider.getTargetListFromLines(lines);
+
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testGetTargetListFromLinesWithInvalidFormat() {
+ CruxListProvider provider = new CruxListProvider(CruxListNumber.TOP_1k);
+
+ Stream lines =
+ Stream.of(
+ "https://example.com,1",
+ "invalid-format",
+ "https://test.com,2",
+ "https://norank.com");
+
+ // This should throw an exception due to invalid format
+ assertThrows(
+ Exception.class,
+ () -> {
+ provider.getTargetListFromLines(lines);
+ });
+ }
+
+ @Test
+ public void testGetTargetListFromLinesWithComplexUrls() {
+ CruxListProvider provider = new CruxListProvider(CruxListNumber.TOP_1k);
+
+ Stream lines =
+ Stream.of(
+ "https://subdomain.example.com,1",
+ "https://example.com:8443,2",
+ "https://test.com/path,3");
+
+ List result = provider.getTargetListFromLines(lines);
+
+ assertEquals(3, result.size());
+ assertTrue(result.contains("subdomain.example.com"));
+ assertTrue(result.contains("example.com:8443"));
+ assertTrue(result.contains("test.com/path"));
+ }
+
+ @Test
+ public void testAllCruxListNumbers() {
+ // Test that provider can be created with all enum values
+ for (CruxListNumber number : CruxListNumber.values()) {
+ CruxListProvider provider = new CruxListProvider(number);
+ assertNotNull(provider);
+ }
+ }
+}
diff --git a/src/test/resources/scanDefinition.json b/src/test/resources/scanDefinition.json
new file mode 100644
index 0000000..948f500
--- /dev/null
+++ b/src/test/resources/scanDefinition.json
@@ -0,0 +1,4 @@
+{
+ "scanTimeMs": 1000,
+ "port": 443
+}
\ No newline at end of file
diff --git a/src/test/resources/targets.txt b/src/test/resources/targets.txt
new file mode 100644
index 0000000..a2621cc
--- /dev/null
+++ b/src/test/resources/targets.txt
@@ -0,0 +1,2 @@
+example.com
+test.com
\ No newline at end of file