Compare commits
2 commits
fae88aa262
...
7d7cf8148a
Author | SHA1 | Date | |
---|---|---|---|
7d7cf8148a | |||
306f3c25bc |
9 changed files with 284 additions and 45 deletions
10
pom.xml
10
pom.xml
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -49,6 +49,12 @@
|
||||||
<version>4.7.0</version>
|
<version>4.7.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-junit-jupiter</artifactId>
|
||||||
|
<version>4.7.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<!-- to test my json implementation -->
|
<!-- to test my json implementation -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public final class FileSystemDB implements PersistPlayer, FindPlayer {
|
public final class FileSystemDB implements PersistPlayer, FindPlayer {
|
||||||
|
|
||||||
private final File saveDirectory;
|
private final File saveDirectory;
|
||||||
private final SerializationFactory serializationFactory;
|
private final SerializationFactory serializationFactory;
|
||||||
|
|
||||||
|
@ -22,29 +23,32 @@ public final class FileSystemDB implements PersistPlayer, FindPlayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush(final Player player) throws PersistException {
|
public void flush(final Player player) throws WritePlayerException {
|
||||||
final var playerFile = new File(saveDirectory, player.uuid().toString());
|
final var playerFile = new File(saveDirectory, player.uuid().toString());
|
||||||
|
final String serializedPlayer = serializationFactory.createSerializer(player).serialize();
|
||||||
try (final var writer = new FileWriter(playerFile)) {
|
try (final var writer = new FileWriter(playerFile)) {
|
||||||
final String jsonPlayer = serializationFactory.createSerializer(player).serialize();
|
writer.write(serializedPlayer);
|
||||||
writer.write(jsonPlayer);
|
// ensure everything is written
|
||||||
writer.flush();
|
writer.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new PersistException("Could not persist player data with id: " + player.uuid(), e);
|
throw new WritePlayerException("Could not persist player data from player: " + player.uuid(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Player> findById(final UUID uuid) throws FindPlayerException {
|
public Optional<Player> findById(final UUID uuid) throws ReadPlayerException {
|
||||||
final File[] files = getFiles();
|
final File[] files = getFiles();
|
||||||
for (final var file : files) {
|
for (final var file : files) {
|
||||||
if (file.getName().equals(uuid.toString())) {
|
if (!file.getName().equals(uuid.toString())) {
|
||||||
try {
|
continue;
|
||||||
final String fileContent = Files.readString(file.toPath());
|
}
|
||||||
final Player player = serializationFactory.createDeserializer(fileContent);
|
|
||||||
return Optional.of(player);
|
try {
|
||||||
} catch (IOException e) {
|
final String fileContent = Files.readString(file.toPath());
|
||||||
throw new FindPlayerException("Player not found with the uuid: " + uuid, e);
|
final Player player = serializationFactory.createDeserializer(fileContent);
|
||||||
}
|
return Optional.of(player);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ReadPlayerException("Player not found with the uuid: " + uuid, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +56,7 @@ public final class FileSystemDB implements PersistPlayer, FindPlayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Player> findByName(final String name) throws FindPlayerException {
|
public Optional<Player> findByName(final String name) throws ReadPlayerException {
|
||||||
final File[] files = getFiles();
|
final File[] files = getFiles();
|
||||||
for (final var file : files) {
|
for (final var file : files) {
|
||||||
try {
|
try {
|
||||||
|
@ -62,7 +66,7 @@ public final class FileSystemDB implements PersistPlayer, FindPlayer {
|
||||||
return Optional.of(player);
|
return Optional.of(player);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new FindPlayerException("Player not found with the name: " + name, e);
|
throw new ReadPlayerException("Player not found with the name: " + name, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +74,7 @@ public final class FileSystemDB implements PersistPlayer, FindPlayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Player> findAll() throws FindPlayerException {
|
public List<Player> findAll() throws ReadPlayerException {
|
||||||
final File[] files = getFiles();
|
final File[] files = getFiles();
|
||||||
final var playerList = new ArrayList<Player>();
|
final var playerList = new ArrayList<Player>();
|
||||||
for (final var file : files) {
|
for (final var file : files) {
|
||||||
|
@ -79,7 +83,7 @@ public final class FileSystemDB implements PersistPlayer, FindPlayer {
|
||||||
final Player player = serializationFactory.createDeserializer(fileContent);
|
final Player player = serializationFactory.createDeserializer(fileContent);
|
||||||
playerList.add(player);
|
playerList.add(player);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new FindPlayerException("Player not found with the path: " + file.getAbsolutePath(), e);
|
throw new ReadPlayerException("Player not found with the path: " + file.getAbsolutePath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface FindPlayer {
|
public interface FindPlayer {
|
||||||
Optional<Player> findById(UUID uuid) throws FindPlayerException;
|
Optional<Player> findById(UUID uuid) throws ReadPlayerException;
|
||||||
|
|
||||||
Optional<Player> findByName(String name) throws FindPlayerException;
|
Optional<Player> findByName(String name) throws ReadPlayerException;
|
||||||
|
|
||||||
List<Player> findAll() throws FindPlayerException;
|
List<Player> findAll() throws ReadPlayerException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
package de.hhhammer.playtime.ng.persistence;
|
|
||||||
|
|
||||||
public final class FindPlayerException extends Exception {
|
|
||||||
public FindPlayerException(String msg) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FindPlayerException(final String message, final Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package de.hhhammer.playtime.ng.persistence;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public final class PersistException extends Exception {
|
|
||||||
|
|
||||||
public PersistException(final String message, final IOException cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,5 +3,5 @@ package de.hhhammer.playtime.ng.persistence;
|
||||||
import de.hhhammer.playtime.ng.player.Player;
|
import de.hhhammer.playtime.ng.player.Player;
|
||||||
|
|
||||||
public interface PersistPlayer {
|
public interface PersistPlayer {
|
||||||
void flush(Player player) throws PersistException;
|
void flush(Player player) throws WritePlayerException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package de.hhhammer.playtime.ng.persistence;
|
||||||
|
|
||||||
|
public final class ReadPlayerException extends Exception {
|
||||||
|
public ReadPlayerException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadPlayerException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package de.hhhammer.playtime.ng.persistence;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public final class WritePlayerException extends Exception {
|
||||||
|
|
||||||
|
public WritePlayerException(final String message, final IOException cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
package de.hhhammer.playtime.ng.persistence;
|
||||||
|
|
||||||
|
import de.hhhammer.playtime.ng.player.Player;
|
||||||
|
import de.hhhammer.playtime.ng.serialization.SerializationFactory;
|
||||||
|
import de.hhhammer.playtime.ng.serialization.serializer.Serializer;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class FileSystemDBTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SerializationFactory mockSerializationFactory;
|
||||||
|
@Mock
|
||||||
|
private Player mockPlayer;
|
||||||
|
@Mock
|
||||||
|
private Serializer mockSerializer;
|
||||||
|
private File testDirectory;
|
||||||
|
private FileSystemDB fileSystemDB;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() throws IOException {
|
||||||
|
final Path path = Files.createTempDirectory("playtime").toAbsolutePath();
|
||||||
|
this.testDirectory = path.toFile();
|
||||||
|
this.fileSystemDB = new FileSystemDB(testDirectory, mockSerializationFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void cleanup() {
|
||||||
|
testDirectory.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class FlushTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldWriteFile() throws WritePlayerException {
|
||||||
|
when(mockSerializationFactory.createSerializer(any())).thenReturn(mockSerializer);
|
||||||
|
when(mockPlayer.uuid()).thenReturn(UUID.randomUUID());
|
||||||
|
when(mockSerializer.serialize()).thenReturn("");
|
||||||
|
|
||||||
|
assertEquals(0, testDirectory.listFiles().length);
|
||||||
|
|
||||||
|
fileSystemDB.flush(mockPlayer);
|
||||||
|
|
||||||
|
assertEquals(1, testDirectory.listFiles().length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNameFileWithPlayerUUID() throws WritePlayerException {
|
||||||
|
final var uuid = UUID.randomUUID();
|
||||||
|
when(mockSerializationFactory.createSerializer(any())).thenReturn(mockSerializer);
|
||||||
|
when(mockPlayer.uuid()).thenReturn(uuid);
|
||||||
|
when(mockSerializer.serialize()).thenReturn("");
|
||||||
|
|
||||||
|
fileSystemDB.flush(mockPlayer);
|
||||||
|
|
||||||
|
final File[] foundFiles = testDirectory.listFiles();
|
||||||
|
assertEquals(1, foundFiles.length);
|
||||||
|
assertEquals(uuid.toString(), foundFiles[0].getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldWriteContentFromSerializer() throws WritePlayerException, IOException {
|
||||||
|
when(mockSerializationFactory.createSerializer(any())).thenReturn(mockSerializer);
|
||||||
|
when(mockPlayer.uuid()).thenReturn(UUID.randomUUID());
|
||||||
|
final String content = "test content from serializer";
|
||||||
|
when(mockSerializer.serialize()).thenReturn(content);
|
||||||
|
|
||||||
|
fileSystemDB.flush(mockPlayer);
|
||||||
|
|
||||||
|
final File[] foundFiles = testDirectory.listFiles();
|
||||||
|
assertEquals(1, foundFiles.length);
|
||||||
|
final String foundContent = Files.readString(foundFiles[0].toPath());
|
||||||
|
assertEquals(content, foundContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class FindById {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldThrowIfDirectoryIsAFile() {
|
||||||
|
final var notADir = new File(testDirectory, "not_a_dir");
|
||||||
|
final var fileSystemDB = new FileSystemDB(notADir, mockSerializationFactory);
|
||||||
|
final Exception exception = assertThrows(RuntimeException.class, () -> fileSystemDB.findById(UUID.randomUUID()));
|
||||||
|
assertEquals("Could not find files in: " + notADir.getAbsolutePath(), exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeEmptyIfNoFileIsPresent() throws IOException, ReadPlayerException {
|
||||||
|
assertEquals(0, testDirectory.listFiles().length);
|
||||||
|
|
||||||
|
final Optional<Player> foundPlayer = fileSystemDB.findById(UUID.randomUUID());
|
||||||
|
|
||||||
|
assertTrue(foundPlayer.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeEmptyIfUuidNotFound() throws IOException, ReadPlayerException {
|
||||||
|
new File(testDirectory, "not_a_uuid").createNewFile();
|
||||||
|
|
||||||
|
final Optional<Player> foundPlayer = fileSystemDB.findById(UUID.randomUUID());
|
||||||
|
|
||||||
|
assertTrue(foundPlayer.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldDeserializeFileContent() throws IOException, ReadPlayerException {
|
||||||
|
final var playerUUID = UUID.randomUUID();
|
||||||
|
final var fakePlayerFile = new File(testDirectory, playerUUID.toString());
|
||||||
|
final String fileContent = "test content";
|
||||||
|
Files.write(fakePlayerFile.toPath(), fileContent.getBytes());
|
||||||
|
|
||||||
|
when(mockSerializationFactory.createDeserializer(any())).thenReturn(mockPlayer);
|
||||||
|
|
||||||
|
fileSystemDB.findById(playerUUID);
|
||||||
|
|
||||||
|
verify(mockSerializationFactory).createDeserializer(fileContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class FindByName {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeEmptyIfNoFilesExist() throws ReadPlayerException {
|
||||||
|
final Optional<Player> result = fileSystemDB.findByName("username");
|
||||||
|
assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldFindThroughDeserializePlayerWithOnlyOneFile() throws IOException, ReadPlayerException {
|
||||||
|
final var username = "username";
|
||||||
|
when(mockPlayer.name()).thenReturn(username);
|
||||||
|
final var fakePlayerFile = new File(testDirectory, "fake_player_file");
|
||||||
|
Files.write(fakePlayerFile.toPath(), "".getBytes());
|
||||||
|
when(mockSerializationFactory.createDeserializer(anyString())).thenReturn(mockPlayer);
|
||||||
|
|
||||||
|
final Optional<Player> result = fileSystemDB.findByName(username);
|
||||||
|
assertTrue(result.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNotFindThroughDeserializePlayerWithOnlyOneFile() throws IOException, ReadPlayerException {
|
||||||
|
final var username = "username";
|
||||||
|
when(mockPlayer.name()).thenReturn(username);
|
||||||
|
final var fakePlayerFile = new File(testDirectory, "fake_player_file");
|
||||||
|
Files.write(fakePlayerFile.toPath(), "".getBytes());
|
||||||
|
when(mockSerializationFactory.createDeserializer(anyString())).thenReturn(mockPlayer);
|
||||||
|
|
||||||
|
final Optional<Player> result = fileSystemDB.findByName("not_a_username");
|
||||||
|
assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldFindThroughDeserializePlayerOnMultipleFiles() throws IOException, ReadPlayerException {
|
||||||
|
final var wantedUsername = "username";
|
||||||
|
final var notWantedUsername = "not_wanted_username";
|
||||||
|
final var rightPlayer = mock(Player.class);
|
||||||
|
final var wrongPlayer = mock(Player.class);
|
||||||
|
when(rightPlayer.name()).thenReturn(wantedUsername);
|
||||||
|
when(wrongPlayer.name()).thenReturn(notWantedUsername);
|
||||||
|
final var rightPlayerFileContent = "right";
|
||||||
|
final var wrongPlayerFileContent = "wrong";
|
||||||
|
final var rightPlayerFile = new File(testDirectory, "right_player_file");
|
||||||
|
final var wrongPlayerFile = new File(testDirectory, "wrong_player_file");
|
||||||
|
Files.write(rightPlayerFile.toPath(), rightPlayerFileContent.getBytes());
|
||||||
|
Files.write(wrongPlayerFile.toPath(), wrongPlayerFileContent.getBytes());
|
||||||
|
when(mockSerializationFactory.createDeserializer(rightPlayerFileContent)).thenReturn(rightPlayer);
|
||||||
|
when(mockSerializationFactory.createDeserializer(wrongPlayerFileContent)).thenReturn(wrongPlayer);
|
||||||
|
|
||||||
|
final Optional<Player> result = fileSystemDB.findByName(wantedUsername);
|
||||||
|
assertTrue(result.isPresent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class FindAllTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeEmptyIfNoFilesExist() throws ReadPlayerException {
|
||||||
|
final List<Player> result = fileSystemDB.findAll();
|
||||||
|
assertEquals(0, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldFindOneFile() throws IOException, ReadPlayerException {
|
||||||
|
final var fakePlayerFile = new File(testDirectory, "fake_player_file");
|
||||||
|
Files.write(fakePlayerFile.toPath(), "test content".getBytes());
|
||||||
|
when(mockSerializationFactory.createDeserializer(anyString())).thenReturn(mockPlayer);
|
||||||
|
|
||||||
|
final List<Player> result = fileSystemDB.findAll();
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldFindTwoFile() throws IOException, ReadPlayerException {
|
||||||
|
final var fakePlayerFile = new File(testDirectory, "fake_player_file");
|
||||||
|
Files.write(fakePlayerFile.toPath(), "test content".getBytes());
|
||||||
|
final var fakePlayerFile2 = new File(testDirectory, "fake_player_file_2");
|
||||||
|
Files.write(fakePlayerFile2.toPath(), "test content".getBytes());
|
||||||
|
|
||||||
|
when(mockSerializationFactory.createDeserializer(anyString())).thenReturn(mockPlayer);
|
||||||
|
|
||||||
|
final List<Player> result = fileSystemDB.findAll();
|
||||||
|
assertEquals(2, result.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue