Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import com.naminhyeok.fantazzk.room.domain.TeamLeaderId;
import com.naminhyeok.fantazzk.room.repository.Rooms;
import com.naminhyeok.fantazzk.template.support.TemplateFixture;
import com.naminhyeok.fantazzk.template.support.TemplateFixture;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@
import com.naminhyeok.fantazzk.room.repository.Games;
import com.naminhyeok.fantazzk.room.repository.Rooms;
import com.naminhyeok.fantazzk.template.support.TemplateFixture;
import com.naminhyeok.fantazzk.template.support.TemplateFixture;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
Expand Down Expand Up @@ -60,10 +59,12 @@
"sentry.enabled=false"
}
)
@Import(RoomAuctionIntegrationTest.FixedClockConfiguration.class)
@Import(RoomAuctionIntegrationTest.TestConfig.class)
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
@RequiredArgsConstructor
class RoomAuctionIntegrationTest {
private static final Instant STARTED_AT = Instant.parse("2000-01-01T00:00:00Z");

private final TemplateFixture templateFixture;
private final CreateRoom createRoom;
private final JoinRoom joinRoom;
Expand All @@ -75,10 +76,12 @@ class RoomAuctionIntegrationTest {
private final RoomAuctionDeadlineScheduler roomAuctionDeadlineScheduler;
private final RecordingTaskScheduler recordingTaskScheduler;
private final PlatformTransactionManager transactionManager;
private final MutableClock clock;

@BeforeEach
void clearScheduledTasks() {
recordingTaskScheduler.clear();
clock.reset();
}

@Test
Expand All @@ -100,21 +103,16 @@ void clearScheduledTasks() {
RoomTeamLeader guest = joinRoom.join(created.room().getCode(), "게스트").leader();
Game startedGame = startRoom.start(created.room().getCode(), created.leader().getActionToken());

AuctionBid bid = placeBid.place(startedGame.getId().gameId(), guest.getActionToken(), 150);
expireAuctionRound(created.room().getCode(), Instant.parse("1999-12-31T23:59:55Z"));
Room settled = settleAuctionAttempt.settleIfDue(created.room().getCode());
placeBid.place(startedGame.getId().gameId(), guest.getActionToken(), 150);
advancePastCurrentAuctionDeadline();
settleAuctionAttempt.settleIfDue(created.room().getCode());

Room reloaded = rooms.findByCode(created.room().getCode()).orElseThrow();
AuctionGame game = (AuctionGame) games.findById(reloaded.getStartedGameId()).orElseThrow();

assertThat(bid.teamLeaderId()).isEqualTo(guest.getId());
assertThat(bid.amount()).isEqualTo(150);
assertThat(settled.getStatus()).isEqualTo(RoomStatus.STARTED);
assertThat(reloaded.getStatus()).isEqualTo(RoomStatus.STARTED);
assertThat(game.getBids()).singleElement()
.extracting(AuctionBid::teamLeaderId, AuctionBid::amount)
.containsExactly(guest.getId(), 150);
assertThat(reloaded.getPlayers().getFirst().getPosition()).isEqualTo("TOP");
assertThat(game.getMembers()).singleElement()
.extracting(RosterMember::teamLeaderId, RosterMember::playerName)
.containsExactly(guest.getId(), "선수1");
Expand Down Expand Up @@ -173,7 +171,7 @@ void clearScheduledTasks() {
Game startedGame = startRoom.start(created.room().getCode(), created.leader().getActionToken());

placeBid.place(startedGame.getId().gameId(), guest.getActionToken(), 150);
expireAuctionRound(created.room().getCode(), Instant.parse("1999-12-31T23:59:55Z"));
advancePastCurrentAuctionDeadline();
settleAuctionAttempt.settleIfDue(created.room().getCode());

Room reloaded = rooms.findByCode(created.room().getCode()).orElseThrow();
Expand Down Expand Up @@ -201,15 +199,15 @@ void clearScheduledTasks() {
Game startedGame = startRoom.start(created.room().getCode(), created.leader().getActionToken());
placeBid.place(startedGame.getId().gameId(), guest.getActionToken(), 150);

expireAuctionRound(created.room().getCode(), Instant.parse("1999-12-31T23:59:55Z"));
advancePastCurrentAuctionDeadline();
Instant nextDeadline = clock.instant().plusSeconds(45);

roomAuctionDeadlineScheduler.catchUpAndReschedule();

Room reloaded = rooms.findByCode(created.room().getCode()).orElseThrow();
AuctionGame reloadedGame = (AuctionGame) games.findById(reloaded.getStartedGameId()).orElseThrow();
assertThat(reloaded.getStatus()).isEqualTo(RoomStatus.STARTED);
assertThat(reloadedGame.getCurrentRound()).isEqualTo(2);
assertThat(reloadedGame.getCurrentRoundEndsAt()).isEqualTo(Instant.parse("2000-01-01T00:00:45Z"));
assertThat(reloadedGame.getCurrentRoundEndsAt()).isEqualTo(nextDeadline);
}

@Test
Expand Down Expand Up @@ -239,31 +237,16 @@ void clearScheduledTasks() {
assertThat(rooms.findByCode(created.room().getCode()).orElseThrow().getStatus()).isEqualTo(RoomStatus.WAITING);
}

private void expireAuctionRound(String code, Instant deadline) {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.executeWithoutResult(status -> {
Room room = rooms.findByCode(code).orElseThrow();
AuctionGame game = (AuctionGame) games.findById(room.getStartedGameId()).orElseThrow();
setCurrentAuctionRoundEndsAt(game, deadline);
});
}

private static void setCurrentAuctionRoundEndsAt(AuctionGame game, Instant deadline) {
try {
Field field = AuctionGame.class.getDeclaredField("currentRoundEndsAt");
field.setAccessible(true);
field.set(game, deadline);
} catch (ReflectiveOperationException ex) {
throw new AssertionError(ex);
}
private void advancePastCurrentAuctionDeadline() {
clock.advanceTo(clock.instant().plusSeconds(46));
}

@TestConfiguration
static class FixedClockConfiguration {
static class TestConfig {
@Bean
@Primary
Clock roomAuctionTestClock() {
return Clock.fixed(Instant.parse("2000-01-01T00:00:00Z"), ZoneOffset.UTC);
MutableClock roomAuctionTestClock() {
return new MutableClock(STARTED_AT, ZoneOffset.UTC);
}

@Bean
Expand All @@ -273,6 +256,41 @@ RecordingTaskScheduler roomAuctionIntegrationTaskScheduler() {
}
}

static final class MutableClock extends Clock {
private final Instant initialInstant;
private final ZoneId zone;
private Instant instant;

private MutableClock(Instant initialInstant, ZoneId zone) {
this.initialInstant = initialInstant;
this.zone = zone;
this.instant = initialInstant;
}

void reset() {
instant = initialInstant;
}

void advanceTo(Instant instant) {
this.instant = instant;
}

@Override
public ZoneId getZone() {
return zone;
}

@Override
public Clock withZone(ZoneId zone) {
return new MutableClock(instant, zone);
}

@Override
public Instant instant() {
return instant;
}
}

static final class RecordingTaskScheduler implements TaskScheduler {
private final List<ScheduledTask> scheduledTasks = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@
import com.naminhyeok.fantazzk.room.domain.PlayerStatus;
import com.naminhyeok.fantazzk.room.domain.Room;
import com.naminhyeok.fantazzk.room.domain.RoomErrorType;
import com.naminhyeok.fantazzk.room.domain.RoomStatus;
import com.naminhyeok.fantazzk.room.domain.RoomTeamLeader;
import com.naminhyeok.fantazzk.room.domain.RosterMember;
import com.naminhyeok.fantazzk.room.repository.Games;
import com.naminhyeok.fantazzk.room.repository.Rooms;
import com.naminhyeok.fantazzk.template.TemplateCatalog;
import com.naminhyeok.fantazzk.template.TemplateCatalog.DraftOrderStrategy;
import com.naminhyeok.fantazzk.template.support.TemplateFixture;
import com.naminhyeok.fantazzk.template.support.TemplateFixture;
import jakarta.persistence.EntityManager;
import java.util.List;
import java.util.UUID;
Expand Down Expand Up @@ -79,15 +76,13 @@ class RoomDraftIntegrationTest {
selectDraftPosition.select(created.room().getCode(), guest.getActionToken(), 1);
Game startedGame = startRoom.start(created.room().getCode(), created.leader().getActionToken());

RosterMember member = pickDraft.pick(startedGame.getId().gameId(), guest.getActionToken(), "선수1");
pickDraft.pick(startedGame.getId().gameId(), guest.getActionToken(), "선수1");

entityManager.flush();
entityManager.clear();
Room reloaded = rooms.findByCode(created.room().getCode()).orElseThrow();
DraftGame game = (DraftGame) games.findById(reloaded.getStartedGameId()).orElseThrow();

assertThat(member.playerName()).isEqualTo("선수1");
assertThat(reloaded.getStatus()).isEqualTo(RoomStatus.STARTED);
assertThat(reloaded.getPlayers().stream().filter(it -> it.getName().equals("선수1")).findFirst().orElseThrow().getStatus())
.isEqualTo(PlayerStatus.AVAILABLE);
assertThat(game.getMembers()).singleElement()
Expand Down Expand Up @@ -154,7 +149,6 @@ class RoomDraftIntegrationTest {
Room reloadedAfterSecondPick = rooms.findByCode(created.room().getCode()).orElseThrow();
DraftGame gameAfterSecondPick = (DraftGame) games.findById(reloadedAfterSecondPick.getStartedGameId()).orElseThrow();

assertThat(reloadedAfterSecondPick.getStatus()).isEqualTo(RoomStatus.STARTED);
assertThat(gameAfterSecondPick.getCurrentTurnIndex()).isEqualTo(2);

RosterMember thirdPick = pickDraft.pick(reloadedAfterSecondPick.getStartedGameId().gameId(), guest.getActionToken(), "선수3");
Expand All @@ -172,7 +166,6 @@ class RoomDraftIntegrationTest {
tuple(guest.getId(), "선수2"),
tuple(guest.getId(), "선수3")
);
assertThat(reloadedAfterThirdPick.getStatus()).isEqualTo(RoomStatus.STARTED);
assertThat(gameAfterThirdPick.getCurrentTurnIndex()).isEqualTo(3);
}
}
Loading
Loading