package com.nicewuerfel.blockown.database;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.nicewuerfel.blockown.Material;
import com.nicewuerfel.blockown.OwnedBlock;
import com.nicewuerfel.blockown.OwnedEntity;
import com.nicewuerfel.blockown.User;
import com.nicewuerfel.blockown.output.Output;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;
import java.util.UUID;
public abstract class DatabaseTest {
static final int USER_COUNT = 5;
static final int BLOCK_COUNT = USER_COUNT * 2;
static World testWorld;
static Database db;
static Output output;
static User[] testUsers;
static OwnedBlock[] testBlocks;
static OwnedEntity[] testEntities;
@Rule
public Timeout globalTimeout = Timeout.seconds(10);
@BeforeClass
public static void createWorld() {
testWorld = mock(World.class);
when(testWorld.getName()).thenReturn("testWorld");
}
@BeforeClass
public static void createTestUsers() {
testUsers = new User[USER_COUNT];
for (int i = 0; i < USER_COUNT; i++) {
testUsers[i] = User.getInstance(UUID.randomUUID());
}
}
@BeforeClass
public static void createTestBlocks() {
testBlocks = new OwnedBlock[BLOCK_COUNT];
for (int i = 0; i < BLOCK_COUNT; i++) {
OwnedBlock block = OwnedBlock.newInstance(testWorld.getName(), i, i, i, Material.ANY);
testBlocks[i] = block;
}
}
@BeforeClass
public static void createTestEntites() {
testEntities = new OwnedEntity[BLOCK_COUNT];
for (int i = 0; i < BLOCK_COUNT; i++) {
OwnedEntity entity = OwnedEntity.newInstance(UUID.randomUUID(), testWorld.getName(),
new Material(EntityType.BOAT));
testEntities[i] = entity;
}
}
@After
public void dropTestUsers() {
for (User user : testUsers) {
DatabaseAction dbAction = DatabaseAction.newDropInstance(user);
db.enqueue(dbAction);
}
waitForLock();
}
@Test
public void testOwn() {
db.enqueue(DatabaseAction.newOwnInstance(testBlocks[0], testUsers[0]));
db.enqueue(DatabaseAction.newOwnInstance(testEntities[0], testUsers[0]));
db.enqueue(DatabaseAction.newOwnInstance(testBlocks[1], testUsers[1]));
db.enqueue(DatabaseAction.newOwnInstance(testEntities[1], testUsers[1]));
waitForLock();
assertEquals(testUsers[0], db.getOwner(testBlocks[0]).get());
assertEquals(testUsers[0], db.getOwner(testEntities[0]).get());
assertEquals(testUsers[1], db.getOwner(testBlocks[1]).get());
assertEquals(testUsers[1], db.getOwner(testEntities[1]).get());
}
@Test
public void testUnowned() {
assertFalse(db.getOwner(testBlocks[0]).isPresent());
assertFalse(db.getOwner(testEntities[0]).isPresent());
}
@Test
public void testUnown() {
db.enqueue(DatabaseAction.newUnownInstance(testBlocks[0]));
db.enqueue(DatabaseAction.newUnownInstance(testEntities[0]));
db.enqueue(DatabaseAction.newUnownInstance(testBlocks[1]));
db.enqueue(DatabaseAction.newUnownInstance(testEntities[1]));
waitForLock();
assertFalse(db.getOwner(testBlocks[0]).isPresent());
assertFalse(db.getOwner(testEntities[0]).isPresent());
assertFalse(db.getOwner(testBlocks[1]).isPresent());
assertFalse(db.getOwner(testEntities[1]).isPresent());
}
@Test
public void testDatabaseRestart() {
db.enqueue(DatabaseAction.newOwnInstance(testBlocks[0], testUsers[0]));
db.enqueue(DatabaseAction.newOwnInstance(testEntities[0], testUsers[0]));
waitForLock();
disconnect();
connect();
assertEquals(testUsers[0], db.getOwner(testBlocks[0]).get());
assertEquals(testUsers[0], db.getOwner(testEntities[0]).get());
assertFalse(db.getOwner(testBlocks[1]).isPresent());
assertFalse(db.getOwner(testEntities[1]).isPresent());
}
@Test
public void testOwnAlreadyOwned() {
db.enqueue(DatabaseAction.newOwnInstance(testBlocks[0], testUsers[0]));
db.enqueue(DatabaseAction.newOwnInstance(testEntities[0], testUsers[0]));
waitForLock();
assertEquals(testUsers[0], db.getOwner(testBlocks[0]).get());
assertEquals(testUsers[0], db.getOwner(testEntities[0]).get());
db.enqueue(DatabaseAction.newOwnInstance(testBlocks[0], testUsers[0]));
db.enqueue(DatabaseAction.newOwnInstance(testEntities[0], testUsers[0]));
waitForLock();
assertEquals(testUsers[0], db.getOwner(testBlocks[0]).get());
assertEquals(testUsers[0], db.getOwner(testEntities[0]).get());
}
private static void waitForLock() {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
db.resetThreadPool();
}
abstract void connect();
abstract void disconnect();
}