Skip to content

Commit

Permalink
Merge pull request #470 from KEEPER31337/feature/#469-CTF-문제-삭제시-포인트-…
Browse files Browse the repository at this point in the history
…롤백안되는-버그-해결

Feature/#469 ctf 문제 삭제시 포인트 롤백안되는 버그 해결
  • Loading branch information
gusah009 authored Dec 13, 2022
2 parents e3ba9b9 + b023d1b commit 7b3c65a
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import static keeper.project.homepage.util.service.CtfUtilService.VIRTUAL_TEAM_ID;

import java.nio.file.AccessDeniedException;
import java.time.LocalDateTime;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import keeper.project.homepage.ctf.dto.CtfChallengeAdminDto;
Expand Down Expand Up @@ -304,7 +303,7 @@ private void setFlagAllTeam(String flag, CtfChallengeEntity challenge, long maxS
.ctfChallengeEntity(challenge)
.isCorrect(false)
.remainedSubmitCount(maxSubmitCount)
.lastTryTime(LocalDateTime.now())
.lastTryTime(null)
.build();
ctfFlagRepository.save(flagEntity);
challenge.getCtfFlagEntity().add(flagEntity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ private void createTeamFlag(CtfTeamDetailDto ctfTeamDetailDto, CtfTeamEntity new
.ctfTeamEntity(newTeamEntity)
.ctfChallengeEntity(challenge)
.isCorrect(false)
.remainedSubmitCount(challenge.getMaxSubmitCount())
.build();
flagRepository.save(flagEntity);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
package keeper.project.homepage.ctf.service;

import static keeper.project.homepage.ApiControllerTestHelper.MemberJobName.회원;
import static keeper.project.homepage.ApiControllerTestHelper.MemberJobName.회장;
import static keeper.project.homepage.ApiControllerTestHelper.MemberRankName.일반회원;
import static keeper.project.homepage.ApiControllerTestHelper.MemberTypeName.정회원;
import static keeper.project.homepage.ctf.entity.CtfChallengeCategoryEntity.CtfChallengeCategory.WEB;
import static keeper.project.homepage.ctf.entity.CtfChallengeTypeEntity.CtfChallengeType.DYNAMIC;
import static keeper.project.homepage.ctf.entity.CtfChallengeTypeEntity.CtfChallengeType.STANDARD;
import static org.assertj.core.api.Assertions.assertThat;

import java.nio.file.AccessDeniedException;
import java.util.List;
import java.util.UUID;
import javax.persistence.EntityManager;
import keeper.project.homepage.ctf.controller.CtfSpringTestHelper;
import keeper.project.homepage.ctf.dto.CtfChallengeAdminDto;
import keeper.project.homepage.ctf.dto.CtfChallengeCategoryDto;
import keeper.project.homepage.ctf.dto.CtfChallengeTypeDto;
import keeper.project.homepage.ctf.dto.CtfDynamicChallengeInfoDto;
import keeper.project.homepage.ctf.dto.CtfFlagDto;
import keeper.project.homepage.ctf.dto.CtfTeamDetailDto;
import keeper.project.homepage.ctf.entity.CtfContestEntity;
import keeper.project.homepage.ctf.entity.CtfFlagEntity;
import keeper.project.homepage.member.entity.MemberEntity;
Expand All @@ -31,12 +39,19 @@ class CtfAdminServiceTest extends CtfSpringTestHelper {

@Autowired
private CtfAdminService ctfAdminService;
@Autowired
private CtfChallengeService ctfChallengeService;
@Autowired
private CtfTeamService ctfTeamService;
@Autowired
EntityManager em;

private CtfContestEntity ctfContestEntity;
private MemberEntity contestCreator;

@BeforeEach
void setUp() {
MemberEntity contestCreator = generateMemberEntity(회장, 정회원, 일반회원);
contestCreator = generateMemberEntity(회장, 정회원, 일반회원);
setAuthentication(contestCreator, 회장);
ctfContestEntity = generateCtfContest(contestCreator);
}
Expand All @@ -52,20 +67,7 @@ private static void setAuthentication(MemberEntity contestCreator, MemberJobName
@Test
@DisplayName("문제 생성 테스트")
void createChallenge() {
CtfChallengeAdminDto challengeAdminDto = CtfChallengeAdminDto.builder()
.isSolvable(true)
.flag("flag")
.type(getStandardType())
.dynamicInfo(null)
.content("content")
.title("title")
.score(1234L)
.category(getWebCategory())
.contestId(ctfContestEntity.getId())
.maxSubmitCount(123L)
.build();

CtfChallengeAdminDto result = ctfAdminService.createChallenge(challengeAdminDto);
CtfChallengeAdminDto result = createStandardChallenge(1234L, "flag", "content", "title", 123L);
CtfFlagEntity flag = ctfFlagRepository.findByCtfChallengeEntityIdAndCtfTeamEntityId(
result.getChallengeId(), CtfUtilService.VIRTUAL_TEAM_ID).orElseThrow();

Expand All @@ -81,8 +83,53 @@ void createChallenge() {
assertThat(result.getContestId()).isEqualTo(ctfContestEntity.getId());
assertThat(flag.getRemainedSubmitCount()).isEqualTo(123L);
assertThat(flag.getIsCorrect()).isEqualTo(false);
}

private CtfChallengeAdminDto createStandardChallenge(long score) {
return createStandardChallenge(score, getRandomUUID(), getRandomUUID(), getRandomUUID(), 15L);
}

private CtfChallengeAdminDto createStandardChallenge(long score, String flag, String content,
String title, long maxSubmitCount) {
setAuthentication(contestCreator, 회장);
CtfChallengeAdminDto challengeAdminDto = CtfChallengeAdminDto.builder()
.isSolvable(true)
.flag(flag)
.type(getStandardType())
.dynamicInfo(null)
.content(content)
.title(title)
.score(score)
.category(getWebCategory())
.contestId(ctfContestEntity.getId())
.maxSubmitCount(maxSubmitCount)
.build();

return ctfAdminService.createChallenge(challengeAdminDto);
}

private CtfChallengeAdminDto createDynamicChallenge(CtfDynamicChallengeInfoDto dynamicScore) {
return createDynamicChallenge(dynamicScore, getRandomUUID(), getRandomUUID(), getRandomUUID(),
15L);
}

private CtfChallengeAdminDto createDynamicChallenge(CtfDynamicChallengeInfoDto dynamicScore,
String flag, String content, String title, long maxSubmitCount) {
setAuthentication(contestCreator, 회장);
CtfChallengeAdminDto challengeAdminDto = CtfChallengeAdminDto.builder()
.isSolvable(true)
.flag(flag)
.type(getDynamicType())
.dynamicInfo(dynamicScore)
.content(content)
.title(title)
.score(0L)
.category(getWebCategory())
.contestId(ctfContestEntity.getId())
.maxSubmitCount(maxSubmitCount)
.build();

return ctfAdminService.createChallenge(challengeAdminDto);
}

private static CtfChallengeCategoryDto getWebCategory() {
Expand All @@ -98,4 +145,181 @@ private static CtfChallengeTypeDto getStandardType() {
.name(STANDARD.getName())
.build();
}

private static CtfChallengeTypeDto getDynamicType() {
return CtfChallengeTypeDto.builder()
.id(DYNAMIC.getId())
.name(DYNAMIC.getName())
.build();
}

@Test
@DisplayName("[시나리오1] STANDRAD 문제 삭제 시 점수 반영 제대로 되는지 테스트")
void deleteProblem_scenario1() {
CtfChallengeAdminDto challenge1 = createStandardChallenge(100L);
CtfChallengeAdminDto challenge2 = createStandardChallenge(200L);
CtfChallengeAdminDto challenge3 = createStandardChallenge(400L);

MemberEntity user1 = generateMemberEntity(회원, 정회원, 일반회원);
CtfTeamDetailDto team1 = createCtfTeam(user1); // 1번, 2번 문제 해결
MemberEntity user2 = generateMemberEntity(회원, 정회원, 일반회원);
CtfTeamDetailDto team2 = createCtfTeam(user2); // 2번, 3번 문제 해결
MemberEntity user3 = generateMemberEntity(회원, 정회원, 일반회원);
CtfTeamDetailDto team3 = createCtfTeam(user3); // 1번, 2번, 3번 모두 해결

assertThat(solveChallenge(challenge1, user1)).isTrue();
assertThat(solveChallenge(challenge2, user1)).isTrue();
assertThat(solveChallenge(challenge2, user2)).isTrue();
assertThat(solveChallenge(challenge3, user2)).isTrue();
assertThat(solveChallenge(challenge1, user3)).isTrue();
assertThat(solveChallenge(challenge2, user3)).isTrue();
assertThat(solveChallenge(challenge3, user3)).isTrue();

assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(300L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(600L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(700L);

em.flush();
em.clear();

deleteCtfChallenge(challenge1.getChallengeId());
assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(200L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(600L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(600L);

deleteCtfChallenge(challenge2.getChallengeId());
assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(0L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(400L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(400L);

CtfChallengeAdminDto challenge4 = createStandardChallenge(800L);

assertThat(solveChallenge(challenge4, user1)).isTrue();
assertThat(solveChallenge(challenge4, user2)).isTrue();

assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(800L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(1200L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(400L);

em.flush();
em.clear();

deleteCtfChallenge(challenge3.getChallengeId());
assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(800L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(800L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(0L);

deleteCtfChallenge(challenge4.getChallengeId());
assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(0L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(0L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(0L);
}

@Test
@DisplayName("[시나리오2] DYNAMIC 문제 삭제 시 점수 반영 제대로 되는지 테스트")
void deleteProblem_scenario2() {
CtfChallengeAdminDto challenge1 = createDynamicChallenge(getDynamicScore(0L, 1000L));
CtfChallengeAdminDto challenge2 = createDynamicChallenge(getDynamicScore(0L, 2000L));
CtfChallengeAdminDto challenge3 = createDynamicChallenge(getDynamicScore(0L, 4000L));

MemberEntity user1 = generateMemberEntity(회원, 정회원, 일반회원);
CtfTeamDetailDto team1 = createCtfTeam(user1); // 1번, 2번 문제 해결
MemberEntity user2 = generateMemberEntity(회원, 정회원, 일반회원);
CtfTeamDetailDto team2 = createCtfTeam(user2); // 2번, 3번 문제 해결
MemberEntity user3 = generateMemberEntity(회원, 정회원, 일반회원);
CtfTeamDetailDto team3 = createCtfTeam(user3); // 1번, 2번, 3번 모두 해결
MemberEntity user4 = generateMemberEntity(회원, 정회원, 일반회원);
CtfTeamDetailDto team4 = createCtfTeam(user4); // 문제 해결 안함

assertThat(solveChallenge(challenge1, user1)).isTrue();
assertThat(solveChallenge(challenge2, user1)).isTrue();
assertThat(solveChallenge(challenge2, user2)).isTrue();
assertThat(solveChallenge(challenge3, user2)).isTrue();
assertThat(solveChallenge(challenge1, user3)).isTrue();
assertThat(solveChallenge(challenge2, user3)).isTrue();
assertThat(solveChallenge(challenge3, user3)).isTrue();

assertThat(getChallengeScore(challenge1)).isEqualTo(750L);
assertThat(getChallengeScore(challenge2)).isEqualTo(875L);
assertThat(getChallengeScore(challenge3)).isEqualTo(3000L);
assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(1625L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(3875L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(4625L);
assertThat(ctfTeamRepository.getById(team4.getId()).getScore()).isEqualTo(0L);

em.flush();
em.clear();

System.out.println(team1.getSolvedChallengeList());
System.out.println(team2.getSolvedChallengeList());
System.out.println(team3.getSolvedChallengeList());
System.out.println(team4.getSolvedChallengeList());
System.out.println();

deleteCtfChallenge(challenge1.getChallengeId());
assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(875L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(3875L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(3875L);

System.out.println(team1.getSolvedChallengeList());
System.out.println(team2.getSolvedChallengeList());
System.out.println(team3.getSolvedChallengeList());
System.out.println(team4.getSolvedChallengeList());
System.out.println();

deleteCtfChallenge(challenge2.getChallengeId());
assertThat(ctfTeamRepository.getById(team1.getId()).getScore()).isEqualTo(0L);
assertThat(ctfTeamRepository.getById(team2.getId()).getScore()).isEqualTo(3000L);
assertThat(ctfTeamRepository.getById(team3.getId()).getScore()).isEqualTo(3000L);

System.out.println(team1.getSolvedChallengeList());
System.out.println(team2.getSolvedChallengeList());
System.out.println(team3.getSolvedChallengeList());
System.out.println(team4.getSolvedChallengeList());
System.out.println();
}

private Long getChallengeScore(CtfChallengeAdminDto challenge1) {
return ctfChallengeRepository.getById(challenge1.getChallengeId()).getScore();
}

private static CtfDynamicChallengeInfoDto getDynamicScore(long minScore, long maxScore) {
return CtfDynamicChallengeInfoDto.builder()
.minScore(minScore)
.maxScore(maxScore)
.build();
}

private void deleteCtfChallenge(long challengeId) {
setAuthentication(contestCreator, 회장);
try {
ctfAdminService.deleteProblem(challengeId);
} catch (AccessDeniedException e) {
throw new RuntimeException("내가 왜 검사 예외를 썼을까... ㅠㅠㅠ", e);
}
}

private CtfTeamDetailDto createCtfTeam(MemberEntity teamLeader) {
setAuthentication(teamLeader, 회원);
return ctfTeamService.createTeam(CtfTeamDetailDto.builder()
.contestId(ctfContestEntity.getId())
.name(getRandomUUID())
.description(getRandomUUID())
.build()
);
}

private boolean solveChallenge(CtfChallengeAdminDto challengeInfo, MemberEntity solvedUser) {
setAuthentication(solvedUser, 회원);
CtfFlagDto result = ctfChallengeService.checkFlag(challengeInfo.getChallengeId(),
CtfFlagDto.builder()
.content(challengeInfo.getFlag())
.build()
);
return result.getIsCorrect();
}

private static String getRandomUUID() {
return UUID.randomUUID().toString();
}
}

0 comments on commit 7b3c65a

Please sign in to comment.