384 lines
12 KiB
Java
384 lines
12 KiB
Java
package auctiora;
|
|
|
|
import org.junit.jupiter.api.*;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Paths;
|
|
import java.sql.SQLException;
|
|
import java.time.LocalDateTime;
|
|
import java.util.List;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
/**
|
|
* Test cases for DatabaseService.
|
|
* Tests database operations including schema creation, CRUD operations, and data retrieval.
|
|
*/
|
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
|
class DatabaseServiceTest {
|
|
|
|
private DatabaseService db;
|
|
private String testDbPath;
|
|
|
|
@BeforeAll
|
|
void setUp() throws SQLException {
|
|
testDbPath = "test_database_" + System.currentTimeMillis() + ".db";
|
|
db = new DatabaseService(testDbPath);
|
|
db.ensureSchema();
|
|
}
|
|
|
|
@AfterAll
|
|
void tearDown() throws Exception {
|
|
// Clean up test database
|
|
Files.deleteIfExists(Paths.get(testDbPath));
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should create database schema successfully")
|
|
void testEnsureSchema() {
|
|
assertDoesNotThrow(() -> db.ensureSchema());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should insert and retrieve auction")
|
|
void testUpsertAndGetAuction() throws SQLException {
|
|
var auction = new AuctionInfo(
|
|
12345,
|
|
"Test Auction",
|
|
"Amsterdam, NL",
|
|
"Amsterdam",
|
|
"NL",
|
|
"https://example.com/auction/12345",
|
|
"A7",
|
|
50,
|
|
LocalDateTime.of(2025, 12, 15, 14, 30)
|
|
);
|
|
|
|
db.upsertAuction(auction);
|
|
|
|
var auctions = db.getAllAuctions();
|
|
assertFalse(auctions.isEmpty());
|
|
|
|
var retrieved = auctions.stream()
|
|
.filter(a -> a.auctionId() == 12345)
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
assertNotNull(retrieved);
|
|
assertEquals("Test Auction", retrieved.title());
|
|
assertEquals("Amsterdam", retrieved.city());
|
|
assertEquals("NL", retrieved.country());
|
|
assertEquals(50, retrieved.lotCount());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should update existing auction on conflict")
|
|
void testUpsertAuctionUpdate() throws SQLException {
|
|
var auction1 = new AuctionInfo(
|
|
99999,
|
|
"Original Title",
|
|
"Rotterdam, NL",
|
|
"Rotterdam",
|
|
"NL",
|
|
"https://example.com/auction/99999",
|
|
"A1",
|
|
10,
|
|
null
|
|
);
|
|
|
|
db.upsertAuction(auction1);
|
|
|
|
// Update with same ID
|
|
var auction2 = new AuctionInfo(
|
|
99999,
|
|
"Updated Title",
|
|
"Rotterdam, NL",
|
|
"Rotterdam",
|
|
"NL",
|
|
"https://example.com/auction/99999",
|
|
"A1",
|
|
20,
|
|
null
|
|
);
|
|
|
|
db.upsertAuction(auction2);
|
|
|
|
var auctions = db.getAllAuctions();
|
|
var retrieved = auctions.stream()
|
|
.filter(a -> a.auctionId() == 99999)
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
assertNotNull(retrieved);
|
|
assertEquals("Updated Title", retrieved.title());
|
|
assertEquals(20, retrieved.lotCount());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should retrieve auctions by country code")
|
|
void testGetAuctionsByCountry() throws SQLException {
|
|
// Insert auctions from different countries
|
|
db.upsertAuction(new AuctionInfo(
|
|
10001, "Dutch Auction", "Amsterdam, NL", "Amsterdam", "NL",
|
|
"https://example.com/10001", "A1", 10, null
|
|
));
|
|
|
|
db.upsertAuction(new AuctionInfo(
|
|
10002, "Romanian Auction", "Cluj, RO", "Cluj", "RO",
|
|
"https://example.com/10002", "A2", 15, null
|
|
));
|
|
|
|
db.upsertAuction(new AuctionInfo(
|
|
10003, "Another Dutch", "Utrecht, NL", "Utrecht", "NL",
|
|
"https://example.com/10003", "A3", 20, null
|
|
));
|
|
|
|
var nlAuctions = db.getAuctionsByCountry("NL");
|
|
assertEquals(2, nlAuctions.stream().filter(a -> a.auctionId() >= 10001 && a.auctionId() <= 10003).count());
|
|
|
|
var roAuctions = db.getAuctionsByCountry("RO");
|
|
assertEquals(1, roAuctions.stream().filter(a -> a.auctionId() == 10002).count());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should insert and retrieve lot")
|
|
void testUpsertAndGetLot() throws SQLException {
|
|
var lot = new Lot(
|
|
12345, // saleId
|
|
67890, // lotId
|
|
"Forklift",
|
|
"Electric forklift in good condition",
|
|
"Toyota",
|
|
"Electric",
|
|
2018,
|
|
"Machinery",
|
|
1500.00,
|
|
"EUR",
|
|
"https://example.com/lot/67890",
|
|
LocalDateTime.of(2025, 12, 20, 16, 0),
|
|
false
|
|
);
|
|
|
|
db.upsertLot(lot);
|
|
|
|
var lots = db.getAllLots();
|
|
assertFalse(lots.isEmpty());
|
|
|
|
var retrieved = lots.stream()
|
|
.filter(l -> l.lotId() == 67890)
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
assertNotNull(retrieved);
|
|
assertEquals("Forklift", retrieved.title());
|
|
assertEquals("Toyota", retrieved.manufacturer());
|
|
assertEquals(2018, retrieved.year());
|
|
assertEquals(1500.00, retrieved.currentBid(), 0.01);
|
|
assertFalse(retrieved.closingNotified());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should update lot current bid")
|
|
void testUpdateLotCurrentBid() throws SQLException {
|
|
var lot = new Lot(
|
|
11111, 22222, "Test Item", "Description", "", "", 0, "Category",
|
|
100.00, "EUR", "https://example.com/lot/22222", null, false
|
|
);
|
|
|
|
db.upsertLot(lot);
|
|
|
|
// Update bid
|
|
var updatedLot = new Lot(
|
|
11111, 22222, "Test Item", "Description", "", "", 0, "Category",
|
|
250.00, "EUR", "https://example.com/lot/22222", null, false
|
|
);
|
|
|
|
db.updateLotCurrentBid(updatedLot);
|
|
|
|
var lots = db.getAllLots();
|
|
var retrieved = lots.stream()
|
|
.filter(l -> l.lotId() == 22222)
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
assertNotNull(retrieved);
|
|
assertEquals(250.00, retrieved.currentBid(), 0.01);
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should update lot notification flags")
|
|
void testUpdateLotNotificationFlags() throws SQLException {
|
|
var lot = new Lot(
|
|
33333, 44444, "Test Item", "Description", "", "", 0, "Category",
|
|
100.00, "EUR", "https://example.com/lot/44444", null, false
|
|
);
|
|
|
|
db.upsertLot(lot);
|
|
|
|
// Update notification flag
|
|
var updatedLot = new Lot(
|
|
33333, 44444, "Test Item", "Description", "", "", 0, "Category",
|
|
100.00, "EUR", "https://example.com/lot/44444", null, true
|
|
);
|
|
|
|
db.updateLotNotificationFlags(updatedLot);
|
|
|
|
var lots = db.getAllLots();
|
|
var retrieved = lots.stream()
|
|
.filter(l -> l.lotId() == 44444)
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
assertNotNull(retrieved);
|
|
assertTrue(retrieved.closingNotified());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should insert and retrieve image records")
|
|
void testInsertAndGetImages() throws SQLException {
|
|
// First create a lot
|
|
var lot = new Lot(
|
|
55555, 66666, "Test Lot", "Description", "", "", 0, "Category",
|
|
100.00, "EUR", "https://example.com/lot/66666", null, false
|
|
);
|
|
db.upsertLot(lot);
|
|
|
|
// Insert images
|
|
db.insertImage(66666, "https://example.com/img1.jpg",
|
|
"C:/images/66666/img1.jpg", List.of("car", "vehicle"));
|
|
|
|
db.insertImage(66666, "https://example.com/img2.jpg",
|
|
"C:/images/66666/img2.jpg", List.of("truck"));
|
|
|
|
var images = db.getImagesForLot(66666);
|
|
assertEquals(2, images.size());
|
|
|
|
var img1 = images.stream()
|
|
.filter(i -> i.url().contains("img1.jpg"))
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
assertNotNull(img1);
|
|
assertEquals("car,vehicle", img1.labels());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should count total images")
|
|
void testGetImageCount() throws SQLException {
|
|
int initialCount = db.getImageCount();
|
|
|
|
// Add a lot and image
|
|
var lot = new Lot(
|
|
77777, 88888, "Test Lot", "Description", "", "", 0, "Category",
|
|
100.00, "EUR", "https://example.com/lot/88888", null, false
|
|
);
|
|
db.upsertLot(lot);
|
|
|
|
db.insertImage(88888, "https://example.com/test.jpg",
|
|
"C:/images/88888/test.jpg", List.of("object"));
|
|
|
|
int newCount = db.getImageCount();
|
|
assertTrue(newCount > initialCount);
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should handle empty database gracefully")
|
|
void testEmptyDatabase() throws SQLException, IOException {
|
|
DatabaseService emptyDb = new DatabaseService("empty_test_" + System.currentTimeMillis() + ".db");
|
|
emptyDb.ensureSchema();
|
|
|
|
var auctions = emptyDb.getAllAuctions();
|
|
var lots = emptyDb.getAllLots();
|
|
int imageCount = emptyDb.getImageCount();
|
|
|
|
assertNotNull(auctions);
|
|
assertNotNull(lots);
|
|
assertTrue(auctions.isEmpty());
|
|
assertTrue(lots.isEmpty());
|
|
assertEquals(0, imageCount);
|
|
|
|
// Clean up
|
|
Files.deleteIfExists(Paths.get("empty_test_" + System.currentTimeMillis() + ".db"));
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should handle lots with null closing time")
|
|
void testLotWithNullClosingTime() throws SQLException {
|
|
var lot = new Lot(
|
|
98765, 12340, "Test Item", "Description", "", "", 0, "Category",
|
|
100.00, "EUR", "https://example.com/lot/12340", null, false
|
|
);
|
|
|
|
assertDoesNotThrow(() -> db.upsertLot(lot));
|
|
|
|
var retrieved = db.getAllLots().stream()
|
|
.filter(l -> l.lotId() == 12340)
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
assertNotNull(retrieved);
|
|
assertNull(retrieved.closingTime());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should retrieve active lots only")
|
|
void testGetActiveLots() throws SQLException {
|
|
var activeLot = new Lot(
|
|
11111, 55551, "Active Lot", "Description", "", "", 0, "Category",
|
|
100.00, "EUR", "https://example.com/lot/55551",
|
|
LocalDateTime.now().plusDays(1), false
|
|
);
|
|
|
|
db.upsertLot(activeLot);
|
|
|
|
var activeLots = db.getActiveLots();
|
|
assertFalse(activeLots.isEmpty());
|
|
|
|
var found = activeLots.stream()
|
|
.anyMatch(l -> l.lotId() == 55551);
|
|
assertTrue(found);
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("Should handle concurrent upserts")
|
|
void testConcurrentUpserts() throws InterruptedException, SQLException {
|
|
Thread t1 = new Thread(() -> {
|
|
try {
|
|
for (int i = 0; i < 10; i++) {
|
|
db.upsertLot(new Lot(
|
|
99000 + i, 99100 + i, "Concurrent " + i, "Desc", "", "", 0, "Cat",
|
|
100.0, "EUR", "https://example.com/" + i, null, false
|
|
));
|
|
}
|
|
} catch (SQLException e) {
|
|
fail("Thread 1 failed: " + e.getMessage());
|
|
}
|
|
});
|
|
|
|
Thread t2 = new Thread(() -> {
|
|
try {
|
|
for (int i = 10; i < 20; i++) {
|
|
db.upsertLot(new Lot(
|
|
99000 + i, 99100 + i, "Concurrent " + i, "Desc", "", "", 0, "Cat",
|
|
200.0, "EUR", "https://example.com/" + i, null, false
|
|
));
|
|
}
|
|
} catch (SQLException e) {
|
|
fail("Thread 2 failed: " + e.getMessage());
|
|
}
|
|
});
|
|
|
|
t1.start();
|
|
t2.start();
|
|
t1.join();
|
|
t2.join();
|
|
|
|
var lots = db.getAllLots();
|
|
long concurrentLots = lots.stream()
|
|
.filter(l -> l.lotId() >= 99100 && l.lotId() < 99120)
|
|
.count();
|
|
|
|
assertTrue(concurrentLots >= 20);
|
|
}
|
|
}
|