PLRepoController.java

1
package edu.ucsb.cs.scaffold.controller;
2
3
import edu.ucsb.cs.scaffold.entity.PlRepo;
4
import edu.ucsb.cs.scaffold.errors.EntityNotFoundException;
5
import edu.ucsb.cs.scaffold.repository.PlAssessmentQuestionRepository;
6
import edu.ucsb.cs.scaffold.repository.PlAssessmentRepository;
7
import edu.ucsb.cs.scaffold.repository.PlInstanceRepository;
8
import edu.ucsb.cs.scaffold.repository.PlQuestionRepository;
9
import edu.ucsb.cs.scaffold.repository.PlRepoRepository;
10
import edu.ucsb.cs.scaffold.repository.PlScaffoldAssessmentRepository;
11
import io.swagger.v3.oas.annotations.Operation;
12
import io.swagger.v3.oas.annotations.Parameter;
13
import io.swagger.v3.oas.annotations.tags.Tag;
14
import java.util.regex.Pattern;
15
import lombok.extern.slf4j.Slf4j;
16
import org.springframework.beans.factory.annotation.Autowired;
17
import org.springframework.security.access.prepost.PreAuthorize;
18
import org.springframework.transaction.annotation.Transactional;
19
import org.springframework.web.bind.annotation.DeleteMapping;
20
import org.springframework.web.bind.annotation.GetMapping;
21
import org.springframework.web.bind.annotation.PostMapping;
22
import org.springframework.web.bind.annotation.RequestMapping;
23
import org.springframework.web.bind.annotation.RequestParam;
24
import org.springframework.web.bind.annotation.RestController;
25
26
@Tag(name = "PlRepo")
27
@RequestMapping("/api/plrepo")
28
@RestController
29
@Slf4j
30
public class PLRepoController extends ApiController {
31
32
  // A GitHub owner/organization name: alphanumeric characters or hyphens, cannot begin or end
33
  // with a hyphen.
34
  private static final String OWNER_PATTERN = "[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?";
35
36
  // A GitHub repository name: alphanumeric characters, hyphens, underscores, or periods.
37
  private static final String REPO_PATTERN = "[A-Za-z0-9._-]{1,100}";
38
39
  private static final Pattern REPO_NAME_PATTERN =
40
      Pattern.compile("^" + OWNER_PATTERN + "/" + REPO_PATTERN + "$");
41
42
  @Autowired private PlRepoRepository plRepoRepository;
43
44
  @Autowired private PlInstanceRepository plInstanceRepository;
45
46
  @Autowired private PlQuestionRepository plQuestionRepository;
47
48
  @Autowired private PlScaffoldAssessmentRepository plScaffoldAssessmentRepository;
49
50
  @Autowired private PlAssessmentRepository plAssessmentRepository;
51
52
  @Autowired private PlAssessmentQuestionRepository plAssessmentQuestionRepository;
53
54
  @Operation(summary = "List all PlRepos")
55
  @PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_INSTRUCTOR')")
56
  @GetMapping("")
57
  public Iterable<PlRepo> allPlRepos() {
58 1 1. allPlRepos : replaced return value with Collections.emptyList for edu/ucsb/cs/scaffold/controller/PLRepoController::allPlRepos → KILLED
    return plRepoRepository.findAll();
59
  }
60
61
  @Operation(summary = "Create a new PlRepo")
62
  @PreAuthorize("hasRole('ROLE_ADMIN')")
63
  @PostMapping("")
64
  public PlRepo postPlRepo(@Parameter(name = "repoName") @RequestParam String repoName) {
65
    String trimmedRepoName = repoName.strip();
66 1 1. postPlRepo : removed call to edu/ucsb/cs/scaffold/controller/PLRepoController::validateRepoName → KILLED
    validateRepoName(trimmedRepoName);
67
68 1 1. postPlRepo : negated conditional → KILLED
    if (plRepoRepository.existsByRepoName(trimmedRepoName)) {
69
      throw new IllegalArgumentException(
70
          "PlRepo with repoName %s already exists".formatted(trimmedRepoName));
71
    }
72
73
    PlRepo plRepo = PlRepo.builder().repoName(trimmedRepoName).build();
74 1 1. postPlRepo : replaced return value with null for edu/ucsb/cs/scaffold/controller/PLRepoController::postPlRepo → KILLED
    return plRepoRepository.save(plRepo);
75
  }
76
77
  @Operation(
78
      summary =
79
          "Delete a PlRepo, cascading the delete to its PlInstances, PlQuestions, "
80
              + "PlScaffoldAssessments, and PlAssessments")
81
  @PreAuthorize("hasRole('ROLE_ADMIN')")
82
  @DeleteMapping("")
83
  @Transactional
84
  public Object deletePlRepo(@Parameter(name = "id") @RequestParam Long id) {
85
    PlRepo plRepo =
86
        plRepoRepository
87
            .findById(id)
88 1 1. lambda$deletePlRepo$0 : replaced return value with null for edu/ucsb/cs/scaffold/controller/PLRepoController::lambda$deletePlRepo$0 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(PlRepo.class, id));
89
90 1 1. deletePlRepo : removed call to edu/ucsb/cs/scaffold/repository/PlAssessmentQuestionRepository::deleteByPlRepoId → KILLED
    plAssessmentQuestionRepository.deleteByPlRepoId(id);
91 1 1. deletePlRepo : removed call to edu/ucsb/cs/scaffold/repository/PlScaffoldAssessmentRepository::deleteByPlRepoId → KILLED
    plScaffoldAssessmentRepository.deleteByPlRepoId(id);
92 1 1. deletePlRepo : removed call to edu/ucsb/cs/scaffold/repository/PlAssessmentRepository::deleteByPlRepoId → KILLED
    plAssessmentRepository.deleteByPlRepoId(id);
93 1 1. deletePlRepo : removed call to edu/ucsb/cs/scaffold/repository/PlInstanceRepository::deleteByPlRepoId → KILLED
    plInstanceRepository.deleteByPlRepoId(id);
94 1 1. deletePlRepo : removed call to edu/ucsb/cs/scaffold/repository/PlQuestionRepository::deleteByPlRepoId → KILLED
    plQuestionRepository.deleteByPlRepoId(id);
95 1 1. deletePlRepo : removed call to edu/ucsb/cs/scaffold/repository/PlRepoRepository::delete → KILLED
    plRepoRepository.delete(plRepo);
96
97 1 1. deletePlRepo : replaced return value with null for edu/ucsb/cs/scaffold/controller/PLRepoController::deletePlRepo → KILLED
    return genericMessage("PlRepo with id %s deleted".formatted(id));
98
  }
99
100
  private void validateRepoName(String repoName) {
101 1 1. validateRepoName : negated conditional → KILLED
    if (repoName.isBlank()) {
102
      throw new IllegalArgumentException("repoName is required");
103
    }
104 1 1. validateRepoName : negated conditional → KILLED
    if (!REPO_NAME_PATTERN.matcher(repoName).matches()) {
105
      throw new IllegalArgumentException(
106
          "repoName must be in the format owner/repo, e.g. PrairieLearn/pl-ucsb-cmpsc5b");
107
    }
108
  }
109
}

Mutations

58

1.1
Location : allPlRepos
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_get_all_repos()]
replaced return value with Collections.emptyList for edu/ucsb/cs/scaffold/controller/PLRepoController::allPlRepos → KILLED

66

1.1
Location : postPlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_cannot_post_an_invalid_repo_name()]
removed call to edu/ucsb/cs/scaffold/controller/PLRepoController::validateRepoName → KILLED

68

1.1
Location : postPlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_cannot_post_a_duplicate_repo_name()]
negated conditional → KILLED

74

1.1
Location : postPlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_post_a_new_repo()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/PLRepoController::postPlRepo → KILLED

88

1.1
Location : lambda$deletePlRepo$0
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_tries_to_delete_non_existant_repo_and_gets_right_error_message()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/PLRepoController::lambda$deletePlRepo$0 → KILLED

90

1.1
Location : deletePlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_delete_a_repo_and_cascades_to_instances_and_questions()]
removed call to edu/ucsb/cs/scaffold/repository/PlAssessmentQuestionRepository::deleteByPlRepoId → KILLED

91

1.1
Location : deletePlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_delete_a_repo_and_cascades_to_instances_and_questions()]
removed call to edu/ucsb/cs/scaffold/repository/PlScaffoldAssessmentRepository::deleteByPlRepoId → KILLED

92

1.1
Location : deletePlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_delete_a_repo_and_cascades_to_instances_and_questions()]
removed call to edu/ucsb/cs/scaffold/repository/PlAssessmentRepository::deleteByPlRepoId → KILLED

93

1.1
Location : deletePlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_delete_a_repo_and_cascades_to_instances_and_questions()]
removed call to edu/ucsb/cs/scaffold/repository/PlInstanceRepository::deleteByPlRepoId → KILLED

94

1.1
Location : deletePlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_delete_a_repo_and_cascades_to_instances_and_questions()]
removed call to edu/ucsb/cs/scaffold/repository/PlQuestionRepository::deleteByPlRepoId → KILLED

95

1.1
Location : deletePlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_delete_a_repo_and_cascades_to_instances_and_questions()]
removed call to edu/ucsb/cs/scaffold/repository/PlRepoRepository::delete → KILLED

97

1.1
Location : deletePlRepo
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_can_delete_a_repo_and_cascades_to_instances_and_questions()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/PLRepoController::deletePlRepo → KILLED

101

1.1
Location : validateRepoName
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_cannot_post_an_invalid_repo_name()]
negated conditional → KILLED

104

1.1
Location : validateRepoName
Killed by : edu.ucsb.cs.scaffold.controller.PLRepoControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.PLRepoControllerTests]/[method:admin_cannot_post_an_invalid_repo_name()]
negated conditional → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0