Fix mock tests
This commit is contained in:
9
.mvn/extensions.xml
Normal file
9
.mvn/extensions.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extensions>
|
||||
<!-- Override Maven's internal Guice with a Java 25 compatible version -->
|
||||
<extension>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>7.0.0</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
8
mvnw.cmd
vendored
Normal file
8
mvnw.cmd
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
@echo off
|
||||
@REM Wrapper script to suppress Maven Guice warnings
|
||||
@REM Redirects stderr warnings to nul while keeping actual errors
|
||||
|
||||
set MAVEN_OPTS=%MAVEN_OPTS% --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED
|
||||
|
||||
@REM Run maven and filter out Guice warnings
|
||||
mvn %* 2>&1 | findstr /V /C:"sun.misc.Unsafe" /C:"com.google.inject" /C:"WARNING: package sun.misc"
|
||||
13
pom.xml
13
pom.xml
@@ -223,6 +223,19 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Explicitly add cron-utils with slf4j excluded to avoid path warning -->
|
||||
<dependency>
|
||||
<groupId>com.cronutils</groupId>
|
||||
<artifactId>cron-utils</artifactId>
|
||||
<version>9.2.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Force Netty 4.1.124.Final to avoid sun.misc.Unsafe warnings -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package auctiora;
|
||||
|
||||
import io.quarkus.runtime.Startup;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.inject.Produces;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.opencv.core.Core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
@@ -13,11 +16,23 @@ import java.sql.SQLException;
|
||||
* CDI Producer for auction monitor services.
|
||||
* Creates and configures singleton instances of core services.
|
||||
*/
|
||||
@Startup
|
||||
@ApplicationScoped
|
||||
public class AuctionMonitorProducer {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(AuctionMonitorProducer.class);
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
// Load OpenCV native library at startup
|
||||
try {
|
||||
nu.pattern.OpenCV.loadLocally();
|
||||
LOG.info("✓ OpenCV loaded successfully");
|
||||
} catch (Exception e) {
|
||||
LOG.warn("⚠️ OpenCV not available - image detection will be disabled: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Produces
|
||||
@Singleton
|
||||
public DatabaseService produceDatabaseService(
|
||||
|
||||
@@ -111,6 +111,36 @@ public class DatabaseService {
|
||||
// Table might not exist yet, which is fine
|
||||
log.debug("Could not check auctions table schema: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Check if sale_id column exists in lots table (old schema used auction_id)
|
||||
try (var rs = stmt.executeQuery("PRAGMA table_info(lots)")) {
|
||||
boolean hasSaleId = false;
|
||||
boolean hasAuctionId = false;
|
||||
while (rs.next()) {
|
||||
String colName = rs.getString("name");
|
||||
if ("sale_id".equals(colName)) {
|
||||
hasSaleId = true;
|
||||
}
|
||||
if ("auction_id".equals(colName)) {
|
||||
hasAuctionId = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have auction_id but not sale_id, we need to rename the column
|
||||
// SQLite doesn't support RENAME COLUMN before 3.25.0, so we add sale_id and copy data
|
||||
if (hasAuctionId && !hasSaleId) {
|
||||
log.info("Migrating schema: Adding 'sale_id' column to lots table and copying data from auction_id");
|
||||
stmt.execute("ALTER TABLE lots ADD COLUMN sale_id INTEGER");
|
||||
stmt.execute("UPDATE lots SET sale_id = auction_id");
|
||||
} else if (!hasSaleId && !hasAuctionId) {
|
||||
// New table, add sale_id
|
||||
log.info("Migrating schema: Adding 'sale_id' column to new lots table");
|
||||
stmt.execute("ALTER TABLE lots ADD COLUMN sale_id INTEGER");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// Table might not exist yet, which is fine
|
||||
log.debug("Could not check lots table schema: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,7 +43,7 @@ class ImageProcessingService {
|
||||
try {
|
||||
var response = httpClient.sendGetBytes(imageUrl);
|
||||
|
||||
if (response.statusCode() == 200) {
|
||||
if (response != null && response.statusCode() == 200) {
|
||||
// Use Windows path: C:\mnt\okcomputer\output\images
|
||||
var baseDir = Paths.get("C:", "mnt", "okcomputer", "output", "images");
|
||||
var dir = baseDir.resolve(String.valueOf(saleId)).resolve(String.valueOf(lotId));
|
||||
|
||||
@@ -91,8 +91,8 @@ public class NotificationService {
|
||||
if ("desktop".equalsIgnoreCase(cfg)) {
|
||||
return new Config(true, false, null, null, null);
|
||||
} else if (cfg.startsWith("smtp:")) {
|
||||
var parts = cfg.split(":", 4);
|
||||
if (parts.length != 4)
|
||||
var parts = cfg.split(":", -1); // Use -1 to include trailing empty strings
|
||||
if (parts.length < 4)
|
||||
throw new IllegalArgumentException("Email config must be 'smtp:username:password:toEmail'");
|
||||
return new Config(true, true, parts[1], parts[2], parts[3]);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ public class ObjectDetectionService {
|
||||
this.classNames = Files.readAllLines(classNamesFile);
|
||||
this.enabled = true;
|
||||
log.info("✓ Object detection enabled with YOLO");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("⚠️ Object detection disabled: OpenCV native libraries not loaded");
|
||||
throw new IOException("Failed to initialize object detection: OpenCV native libraries not loaded", e);
|
||||
} catch (Exception e) {
|
||||
System.err.println("⚠️ Object detection disabled: " + e.getMessage());
|
||||
throw new IOException("Failed to initialize object detection", e);
|
||||
|
||||
@@ -73,7 +73,11 @@ public class ScraperDataAdapter {
|
||||
|
||||
public static int extractNumericId(String id) {
|
||||
if (id == null || id.isBlank()) return 0;
|
||||
var digits = id.replaceAll("\\D+", "");
|
||||
// Remove the type prefix (e.g., "A7-") first, then extract all digits
|
||||
// "A7-39813" → "39813" → 39813
|
||||
// "A1-28505-5" → "28505-5" → "285055"
|
||||
var afterPrefix = id.indexOf('-') >= 0 ? id.substring(id.indexOf('-') + 1) : id;
|
||||
var digits = afterPrefix.replaceAll("\\D+", "");
|
||||
return digits.isEmpty() ? 0 : Integer.parseInt(digits);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,14 @@ class NotificationServiceTest {
|
||||
@Test
|
||||
@DisplayName("Should reject invalid SMTP configuration format")
|
||||
void testInvalidSMTPConfiguration() {
|
||||
// Missing parts
|
||||
// Missing parts (only 2 parts total)
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
new NotificationService("smtp:incomplete")
|
||||
);
|
||||
|
||||
// Wrong format
|
||||
// Wrong format (only 3 parts total, needs 4)
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
new NotificationService("smtp:only:two:parts")
|
||||
new NotificationService("smtp:only:two")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class ObjectDetectionServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should initialize successfully with valid model files")
|
||||
@DisplayName("Should throw IOException when model files exist but OpenCV fails to load")
|
||||
void testInitializeWithValidModels() throws IOException {
|
||||
// Create dummy model files for testing initialization
|
||||
var cfgPath = Paths.get(TEST_CFG);
|
||||
@@ -94,15 +94,10 @@ class ObjectDetectionServiceTest {
|
||||
Files.write(weightsPath, new byte[]{0, 1, 2, 3});
|
||||
Files.writeString(classesPath, "person\ncar\ntruck\n");
|
||||
|
||||
// Note: This will still fail to load actual YOLO model without OpenCV
|
||||
// But it tests file existence check
|
||||
assertDoesNotThrow(() -> {
|
||||
try {
|
||||
new ObjectDetectionService(TEST_CFG, TEST_WEIGHTS, TEST_CLASSES);
|
||||
} catch (IOException e) {
|
||||
// Expected if OpenCV not loaded
|
||||
assertTrue(e.getMessage().contains("Failed to initialize"));
|
||||
}
|
||||
// When files exist but OpenCV native library isn't loaded,
|
||||
// constructor should throw IOException wrapping the UnsatisfiedLinkError
|
||||
assertThrows(IOException.class, () -> {
|
||||
new ObjectDetectionService(TEST_CFG, TEST_WEIGHTS, TEST_CLASSES);
|
||||
});
|
||||
} finally {
|
||||
Files.deleteIfExists(cfgPath);
|
||||
@@ -113,10 +108,16 @@ class ObjectDetectionServiceTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should handle missing class names file")
|
||||
void testMissingClassNamesFile() {
|
||||
assertThrows(IOException.class, () -> {
|
||||
new ObjectDetectionService("non_existent.cfg", "non_existent.weights", "non_existent.txt");
|
||||
});
|
||||
void testMissingClassNamesFile() throws IOException {
|
||||
// When model files don't exist, service initializes in disabled mode (no exception)
|
||||
ObjectDetectionService service = new ObjectDetectionService(
|
||||
"non_existent.cfg",
|
||||
"non_existent.weights",
|
||||
"non_existent.txt"
|
||||
);
|
||||
assertNotNull(service);
|
||||
// Verify it returns empty results when disabled
|
||||
assertTrue(service.detectObjects("test.jpg").isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user