Skip to content

Commit

Permalink
fix: server is not started when game is save is locked (#35)
Browse files Browse the repository at this point in the history
fix: server is not started when game is save is locked;
  • Loading branch information
lightTAKE authored Aug 16, 2024
1 parent 27fd123 commit 543e995
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 5 deletions.
79 changes: 79 additions & 0 deletions BuddySave.UnitTests/Core/GamingSessionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,71 @@ public async Task Run_DoesNotStartTheServer_WhenLoadingSaveFails(
processProviderMock.Verify(x => x.Start(It.IsAny<ProcessStartInfo>()), Times.Never());
}

[Theory]
[InlineAutoMoqData(OrchestratorResult.SaveLocked)]
[InlineAutoMoqData(OrchestratorResult.Failed)]
public async Task Run_DoesNotStartTheServer_WhenGameSaveIsNotLoaded(
OrchestratorResult orchestratorResult,
[Frozen] Mock<ISharedSaveOrchestrator> sharedSaveOrchestratorMock,
[Frozen] Mock<IProcessProvider> processProviderMock,
GameSave gameSave,
Session session,
ServerParameters serverParameters,
GamingSession sut)
{
// Arrange
sharedSaveOrchestratorMock.Setup(x => x.Load(It.IsAny<GameSave>(), It.IsAny<Session>())).ReturnsAsync(orchestratorResult);

// Act
await sut.RunServerWithAutoSave(gameSave, session, serverParameters);

// Assert
processProviderMock.Verify(x => x.Start(It.IsAny<ProcessStartInfo>()), Times.Never());
}

[Theory]
[InlineAutoMoqData(OrchestratorResult.SaveLocked)]
[InlineAutoMoqData(OrchestratorResult.Failed)]
public async Task Run_DoesWaitForServerToStop_WhenGameSaveIsNotLoaded(
OrchestratorResult orchestratorResult,
[Frozen] Mock<ISharedSaveOrchestrator> sharedSaveOrchestratorMock,
[Frozen] Mock<IProcessProvider> processProviderMock,
GameSave gameSave,
Session session,
ServerParameters serverParameters,
GamingSession sut)
{
// Arrange
sharedSaveOrchestratorMock.Setup(x => x.Load(It.IsAny<GameSave>(), It.IsAny<Session>())).ReturnsAsync(orchestratorResult);

// Act
await sut.RunServerWithAutoSave(gameSave, session, serverParameters);

// Assert
processProviderMock.Verify(x => x.WaitForExitAsync(It.IsAny<Process>()), Times.Never());
}

[Theory]
[InlineAutoMoqData(OrchestratorResult.SaveLocked)]
[InlineAutoMoqData(OrchestratorResult.Failed)]
public async Task Run_DoesNotCallSave_WhenGameSaveIsNotLoaded(
OrchestratorResult orchestratorResult,
[Frozen] Mock<ISharedSaveOrchestrator> sharedSaveOrchestratorMock,
GameSave gameSave,
Session session,
ServerParameters serverParameters,
GamingSession sut)
{
// Arrange
sharedSaveOrchestratorMock.Setup(x => x.Load(It.IsAny<GameSave>(), It.IsAny<Session>())).ReturnsAsync(orchestratorResult);

// Act
await sut.RunServerWithAutoSave(gameSave, session, serverParameters);

// Assert
sharedSaveOrchestratorMock.Verify(x => x.Save(It.IsAny<GameSave>(), It.IsAny<Session>()), Times.Never());
}

[Theory]
[AutoMoqData]
public async Task Run_DoesNotSave_WhenStartingServerFails(
Expand All @@ -67,6 +132,9 @@ public async Task Run_DoesNotSave_WhenStartingServerFails(
GamingSession sut)
{
// Arrange
sharedSaveOrchestratorMock
.Setup(x => x.Load(It.IsAny<GameSave>(), It.IsAny<Session>()))
.ReturnsAsync(OrchestratorResult.Loaded);
processProviderMock.Setup(x => x.Start(It.IsAny<ProcessStartInfo>())).Throws(exception);

// Act
Expand All @@ -80,12 +148,18 @@ public async Task Run_DoesNotSave_WhenStartingServerFails(
[Theory]
[AutoMoqData]
public async Task Run_WaitsForServerStop_WhenServerStarts(
[Frozen] Mock<ISharedSaveOrchestrator> sharedSaveOrchestratorMock,
[Frozen] Mock<IProcessProvider> processProviderMock,
GameSave gameSave,
Session session,
ServerParameters serverParameters,
GamingSession sut)
{
// Arrange
sharedSaveOrchestratorMock
.Setup(x => x.Load(It.IsAny<GameSave>(), It.IsAny<Session>()))
.ReturnsAsync(OrchestratorResult.Loaded);

// Act
await sut.RunServerWithAutoSave(gameSave, session, serverParameters);

Expand All @@ -102,6 +176,11 @@ public async Task Run_Saves_WhenServerStops(
ServerParameters serverParameters,
GamingSession sut)
{
// Arrange
sharedSaveOrchestratorMock
.Setup(x => x.Load(It.IsAny<GameSave>(), It.IsAny<Session>()))
.ReturnsAsync(OrchestratorResult.Loaded);

// Act
await sut.RunServerWithAutoSave(gameSave, session, serverParameters);

Expand Down
68 changes: 68 additions & 0 deletions BuddySave.UnitTests/Core/SharedSaveOrchestratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ public async Task Load_NotifyClient_When_GameSaveIsLocked(
lockManagerMock.Verify(x => x.CreateLock(It.IsAny<GameSave>(), It.IsAny<Session>()), Times.Never);
gameSaveSyncManagerMock.Verify(x => x.DownloadSave(gameSave), Times.Never);
}

[Theory, AutoMoqData]
public async Task Load_ReturnSaveLockedResult_When_GameSaveIsLocked(
GameSave gameSave,
Session session,
[Frozen] Mock<ILockManager> lockManagerMock,
SharedSaveOrchestrator sut)
{
// Arrange
lockManagerMock.Setup(x => x.LockExists(It.IsAny<GameSave>())).Returns(true);

// Act
var result = await sut.Load(gameSave, session);

// Assert
Assert.Equal(OrchestratorResult.SaveLocked, result);
}

[Theory, AutoMoqData]
public async Task Load_CallDeleteLock_When_CreateLockThrowsException(
Expand All @@ -53,6 +70,23 @@ public async Task Load_CallDeleteLock_When_CreateLockThrowsException(
clientNotifierMock.Verify(x => x.Notify("Failed loading game save. Deleting game save lock..."), Times.Once);
clientNotifierMock.Verify(x => x.Notify("Game save lock released."), Times.Once);
}

[Theory, AutoMoqData]
public async Task Load_ReturnFailedResult_When_CreateLockThrowsException(
GameSave gameSave,
Session session,
[Frozen] Mock<ILockManager> lockManagerMock,
SharedSaveOrchestrator sut)
{
// Arrange
lockManagerMock.Setup(x => x.CreateLock(It.IsAny<GameSave>(), It.IsAny<Session>())).Throws<Exception>();

// Act
var result = await sut.Load(gameSave, session);

// Assert
Assert.Equal(OrchestratorResult.Failed, result);
}

[Theory, AutoMoqData]
public async Task Load_CallDeleteLock_When_DownloadThrowsException(
Expand All @@ -74,6 +108,23 @@ public async Task Load_CallDeleteLock_When_DownloadThrowsException(
clientNotifierMock.Verify(x => x.Notify("Failed loading game save. Deleting game save lock..."), Times.Once);
clientNotifierMock.Verify(x => x.Notify("Game save lock released."), Times.Once);
}

[Theory, AutoMoqData]
public async Task Load_ReturnFailedResult_When_DownloadThrowsException(
GameSave gameSave,
Session session,
[Frozen] Mock<IGameSaveSyncManager> gameSaveSyncManagerMock,
SharedSaveOrchestrator sut)
{
// Arrange
gameSaveSyncManagerMock.Setup(x => x.DownloadSave(It.IsAny<GameSave>())).Throws<Exception>();

// Act
var result = await sut.Load(gameSave, session);

// Assert
Assert.Equal(OrchestratorResult.Failed, result);
}

[Theory, AutoMoqData]
public async Task Load_LogException_When_DownloadThrowsException(
Expand Down Expand Up @@ -137,6 +188,23 @@ public async Task Load_DownloadCloudSave_When_GameIsNotLocked(
gameSaveSyncManagerMock.Verify(x => x.DownloadSave(gameSave), Times.Once);
clientNotifierMock.Verify(x => x.Notify("Game save is prepared! Enjoy Buddy :)"), Times.Once);
}

[Theory, AutoMoqData]
public async Task Load_ReturnLoadedResult_When_LoadIsSuccessful(
GameSave gameSave,
Session session,
[Frozen] Mock<ILockManager> lockManagerMock,
SharedSaveOrchestrator sut)
{
// Arrange
lockManagerMock.Setup(x => x.LockExists(It.IsAny<GameSave>(), It.IsAny<Session>())).ReturnsAsync(false);

// Act
var result = await sut.Load(gameSave, session);

// Assert
Assert.Equal(OrchestratorResult.Loaded, result);
}

[Theory, AutoMoqData]
public async Task Save_NotifyClient_When_LockFileDoesNotExist(
Expand Down
7 changes: 6 additions & 1 deletion BuddySave/Core/GamingSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ public async Task RunServerWithAutoSave(GameSave gameSave, Session session, Serv
throw new ArgumentException("No server path provided. Cannot start a gaming session.");
}

await sharedSaveOrchestrator.Load(gameSave, session);
var loadResult = await sharedSaveOrchestrator.Load(gameSave, session);
if (loadResult is not OrchestratorResult.Loaded)
{
return;
}

var process = StartServer(serverParameters);
await WaitForServerToStop(process);
await sharedSaveOrchestrator.Save(gameSave, session);
Expand Down
2 changes: 1 addition & 1 deletion BuddySave/Core/ISharedSaveOrchestrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace BuddySave.Core;

public interface ISharedSaveOrchestrator
{
Task Load(GameSave gameSave, Session session);
Task<OrchestratorResult> Load(GameSave gameSave, Session session);

Task Save(GameSave gameSave, Session session);
}
8 changes: 8 additions & 0 deletions BuddySave/Core/Models/OrchestratorResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace BuddySave.Core.Models;

public enum OrchestratorResult
{
Failed = 0,
Loaded,
SaveLocked
}
9 changes: 6 additions & 3 deletions BuddySave/Core/SharedSaveOrchestrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,32 @@ public class SharedSaveOrchestrator(
IClientNotifier clientNotifier)
: ISharedSaveOrchestrator
{
public async Task Load(GameSave gameSave, Session session)
public async Task<OrchestratorResult> Load(GameSave gameSave, Session session)
{
OrchestratorResult result;
if (lockManager.LockExists(gameSave))
{
clientNotifier.Notify("Game save is locked, your friends are playing!");
return;
return OrchestratorResult.SaveLocked;
}

try
{
await lockManager.CreateLock(gameSave, session);
gameSaveSyncManager.DownloadSave(gameSave);
result = OrchestratorResult.Loaded;
}
catch (Exception ex)
{
result = OrchestratorResult.Failed;
logger.LogError(ex, "Error while loading.");
clientNotifier.Notify("Failed loading game save. Deleting game save lock...");
await lockManager.DeleteLock(gameSave, session);
clientNotifier.Notify("Game save lock released.");
return;
}

clientNotifier.Notify("Game save is prepared! Enjoy Buddy :)");
return result;
}

public async Task Save(GameSave gameSave, Session session)
Expand Down

0 comments on commit 543e995

Please sign in to comment.